refactor: migrate to Vercel-native deployment for branch status pages

- Remove GitHub Pages workflow (release-pages.yml)
- Add Vercel configuration (vercel.json)
- Create artifact fetcher script (scripts/fetch-branch-artifacts.sh)
  - Fetches Storybook from Cloudflare Pages
  - Downloads E2E/Vitest reports from GitHub Actions
  - Uses gh CLI for API access
- Update build script with graceful fallbacks
  - Creates placeholder pages for pending CI
  - Supports both local and Vercel environments
  - Handles missing artifacts gracefully
- Add pages:build:branch-status npm script
- Update documentation with new deployment approach

Benefits:
- Deploys immediately on every push
- Fetches artifacts on-demand during build
- Shows loading states for pending CI
- Simpler, more reliable architecture
- No complex artifact passing between GitHub Actions and Vercel

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
snomiao
2026-02-12 08:07:33 +00:00
parent 2a466af154
commit 01a2ca3bcf
7 changed files with 466 additions and 339 deletions

View File

@@ -1,75 +1,203 @@
#!/usr/bin/env bash
set -Eeuo pipefail
set -Eeo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"
echo "======================================================================"
echo "Building Branch Status Pages"
echo "======================================================================"
echo ""
# Build or reuse Storybook
# Helper function to create placeholder HTML
create_placeholder() {
local dir="$1"
local title="$2"
local message="$3"
mkdir -p "$dir"
cat > "$dir/index.html" <<EOF
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>$title</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
display: flex;
align-items: center;
justify-content: center;
min-height: 100vh;
margin: 0;
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
color: white;
}
.container {
text-align: center;
padding: 2rem;
background: rgba(255, 255, 255, 0.1);
border-radius: 1rem;
backdrop-filter: blur(10px);
max-width: 600px;
}
h1 { margin-top: 0; }
.spinner {
border: 4px solid rgba(255, 255, 255, 0.3);
border-top: 4px solid white;
border-radius: 50%;
width: 40px;
height: 40px;
animation: spin 1s linear infinite;
margin: 2rem auto;
}
@keyframes spin {
to { transform: rotate(360deg); }
}
</style>
</head>
<body>
<div class="container">
<h1>$title</h1>
<div class="spinner"></div>
<p>$message</p>
</div>
</body>
</html>
EOF
}
# ============================================================================
# Storybook
# ============================================================================
echo "[build-pages] Setting up Storybook"
rm -rf ".pages/storybook"
if [ -d "./storybook-static" ] && [ "$(find ./storybook-static -name '*.html' | wc -l)" -gt 0 ]; then
echo "✅ Reusing downloaded Storybook build"
if [ -f ".page/storybook-url.txt" ]; then
# Fetched Storybook URL available - create redirect
STORYBOOK_URL=$(cat ".page/storybook-url.txt")
echo " ✅ Using Storybook from: $STORYBOOK_URL"
mkdir -p ".pages/storybook"
cat > ".pages/storybook/index.html" <<EOF
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; url=$STORYBOOK_URL">
<title>Redirecting to Storybook...</title>
</head>
<body>
<p>Redirecting to <a href="$STORYBOOK_URL">Storybook</a>...</p>
</body>
</html>
EOF
elif [ -d "./storybook-static" ] && [ "$(find ./storybook-static -name '*.html' 2>/dev/null | wc -l)" -gt 0 ]; then
echo " ✅ Using local Storybook build"
cp -r "./storybook-static" ".pages/storybook"
elif [ -d ".page/storybook-static" ]; then
echo " ✅ Using fetched Storybook build"
cp -r ".page/storybook-static" ".pages/storybook"
else
echo "🔨 Building Storybook from source"
pnpm build-storybook && cp -r "storybook-static" ".pages/storybook"
echo " ⚠️ No Storybook build available, creating placeholder"
create_placeholder ".pages/storybook" "Storybook" \
"Storybook is being built by CI. Please check back in a few minutes."
fi
# ============================================================================
# Nx Dependency Graph
# ============================================================================
echo "[build-pages] Generating Nx dependency graph"
rm -rf ".pages/nx-graph" && mkdir -p ".pages/nx-graph"
pnpm nx graph --file=".pages/nx-graph/index.html"
# Generate or reuse Vitest test reports
if pnpm nx graph --file=".pages/nx-graph/index.html" 2>/dev/null; then
echo " ✅ Nx graph generated"
else
echo " ⚠️ Nx graph generation failed, creating placeholder"
create_placeholder ".pages/nx-graph" "Nx Dependency Graph" \
"Graph generation is not available in this environment."
fi
# ============================================================================
# Playwright E2E Test Reports
# ============================================================================
echo "[build-pages] Setting up Playwright test reports"
rm -rf ".pages/playwright-reports" && mkdir -p ".pages/playwright-reports"
if [ -d ".page/playwright-reports" ] && [ "$(find .page/playwright-reports -name '*.html' 2>/dev/null | wc -l)" -gt 0 ]; then
echo " ✅ Using fetched Playwright reports"
cp -r ".page/playwright-reports/"* ".pages/playwright-reports/" 2>/dev/null || true
elif [ -d "./playwright-report" ] && [ "$(find ./playwright-report -name '*.html' 2>/dev/null | wc -l)" -gt 0 ]; then
echo " ✅ Using local Playwright reports"
cp -r "./playwright-report/"* ".pages/playwright-reports/" 2>/dev/null || true
else
echo " No Playwright reports available, creating placeholder"
create_placeholder ".pages/playwright-reports" "E2E Test Reports" \
"Playwright tests are running in CI. Results will appear here when complete."
fi
# ============================================================================
# Vitest Test Reports
# ============================================================================
echo "[build-pages] Setting up Vitest test reports"
rm -rf ".pages/vitest-reports" && mkdir -p ".pages/vitest-reports"
if [ -d ".page/vitest-reports" ]; then
echo "✅ Reusing downloaded Vitest reports"
cp -r ".page/vitest-reports/"* ".pages/vitest-reports/" 2>/dev/null || echo "⚠️ No vitest reports to copy"
if [ -d ".page/vitest-reports" ] && [ -f ".page/vitest-reports/index.html" ]; then
echo " ✅ Using fetched Vitest reports"
cp -r ".page/vitest-reports/"* ".pages/vitest-reports/" 2>/dev/null || true
else
echo "🔨 Generating Vitest reports from source"
pnpm exec vitest \
--reporter=json --outputFile.json=".pages/vitest-reports/results.json" \
--reporter=html --outputFile.html=".pages/vitest-reports/index.html" \
--run
echo " No Vitest reports available, creating placeholder"
create_placeholder ".pages/vitest-reports" "Vitest Test Reports" \
"Unit tests are running in CI. Results will appear here when complete."
fi
# Set up Playwright test reports if available
echo "[build-pages] Setting up Playwright test reports"
if [ -d ".page/playwright-reports" ]; then
echo "✅ Reusing downloaded Playwright reports"
mkdir -p ".pages/playwright-reports"
cp -r ".page/playwright-reports/"* ".pages/playwright-reports/" 2>/dev/null || echo "⚠️ No playwright reports to copy"
fi
echo "[build-pages] Generating coverage report"
# ============================================================================
# Coverage Report (Optional - slow to generate)
# ============================================================================
echo "[build-pages] Setting up coverage report"
mkdir -p ".pages/coverage"
if pnpm exec vitest --run --coverage --coverage.reporter=html --coverage.reportsDirectory=".pages/coverage"; then
echo "✅ Coverage report completed"
if [ -d ".page/coverage" ] && [ -f ".page/coverage/index.html" ]; then
echo " ✅ Using fetched coverage report"
cp -r ".page/coverage/"* ".pages/coverage/" 2>/dev/null || true
else
echo " Coverage report failed, continuing..."
echo " Coverage report not available (skipping generation in Vercel)"
create_placeholder ".pages/coverage" "Coverage Report" \
"Code coverage is generated in CI. Results will appear here when complete."
fi
# ============================================================================
# Knip Report (Fast - generate fresh)
# ============================================================================
echo "[build-pages] Generating Knip report"
mkdir -p ".pages/knip"
rm -f ".pages/knip/report.md"
if pnpm knip --reporter markdown --no-progress --no-exit-code > ".pages/knip/report.md" 2>/dev/null && [ -s ".pages/knip/report.md" ]; then
echo "✅ Knip report generated at .pages/knip/report.md"
else
echo "⚠️ Knip report failed, creating placeholder..."
cat > ".pages/knip/report.md" <<'EOF'
# Knip report
> ⚠️ Knip report unavailable.
>
> Generation failed during build. See CI logs for details.
if pnpm knip --reporter markdown --no-progress --no-exit-code > ".pages/knip/report.md" 2>/dev/null && [ -s ".pages/knip/report.md" ]; then
echo " ✅ Knip report generated"
else
echo " ⚠️ Knip report failed, creating placeholder"
cat > ".pages/knip/report.md" <<'EOF'
# Knip Report
> ⚠️ Knip report generation failed
Knip analysis could not be completed in this build environment.
Please check the CI logs for details.
EOF
fi
echo "[build-pages] Landing page already exists at .pages/index.html"
echo "[build-pages] Build artifacts ready in ./.pages"
echo "[build-pages] Note: For local dev, you can develop the .pages/index.html using:
pnpm exec vite .pages
"
# ============================================================================
# Summary
# ============================================================================
echo ""
echo "======================================================================"
echo "Build Complete"
echo "======================================================================"
echo ""
echo "Generated artifacts in ./.pages:"
echo ""
ls -lh ".pages" 2>/dev/null | tail -n +2 | awk '{print " " $9}'
echo ""
echo "Note: For local development, run:"
echo " pnpm pages:dev"
echo ""

168
scripts/fetch-branch-artifacts.sh Executable file
View File

@@ -0,0 +1,168 @@
#!/usr/bin/env bash
set -Eeo pipefail
# Fetch test artifacts from deployed sources for branch status page
# This script runs in Vercel's build environment to fetch test results
# without waiting for all CI to complete
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"
BRANCH="${VERCEL_GIT_COMMIT_REF:-$(git branch --show-current)}"
COMMIT_SHA="${VERCEL_GIT_COMMIT_SHA:-$(git rev-parse HEAD)}"
echo "[fetch-artifacts] Fetching artifacts for branch: $BRANCH (commit: ${COMMIT_SHA:0:7})"
# Create artifact staging directory
ARTIFACT_DIR=".page"
mkdir -p "$ARTIFACT_DIR"
# ============================================================================
# Fetch Storybook from Cloudflare Pages
# ============================================================================
fetch_storybook() {
echo "[fetch-artifacts] Fetching Storybook from Cloudflare Pages..."
# Try to get Storybook URL from recent PR comment
if command -v gh &> /dev/null && [ -n "$GITHUB_TOKEN" ]; then
# Get PR number for current branch
PR_NUMBER=$(gh pr list --head "$BRANCH" --json number --jq '.[0].number' 2>/dev/null || echo "")
if [ -n "$PR_NUMBER" ]; then
echo " Found PR #$PR_NUMBER"
# Look for Storybook URL in comments
STORYBOOK_URL=$(gh api "repos/{owner}/{repo}/issues/$PR_NUMBER/comments" \
--jq '.[] | select(.body | contains("Storybook")) | .body' 2>/dev/null \
| grep -oP 'https://[a-z0-9]+-comfyui-frontend\.pages\.dev' \
| head -1 || echo "")
if [ -n "$STORYBOOK_URL" ]; then
echo " Found Storybook URL: $STORYBOOK_URL"
# Download and extract storybook
if curl -sSL "$STORYBOOK_URL" -o /dev/null -w "%{http_code}" | grep -q "200"; then
echo " ✅ Storybook is accessible, will reference URL"
echo "$STORYBOOK_URL" > "$ARTIFACT_DIR/storybook-url.txt"
return 0
fi
fi
fi
fi
echo " ⚠️ Could not fetch Storybook URL (will show placeholder)"
return 1
}
# ============================================================================
# Fetch E2E Test Results from GitHub Actions
# ============================================================================
fetch_e2e_reports() {
echo "[fetch-artifacts] Fetching E2E test results from GitHub Actions..."
if ! command -v gh &> /dev/null; then
echo " ⚠️ GitHub CLI not installed, skipping E2E reports"
return 1
fi
if [ -z "$GITHUB_TOKEN" ]; then
echo " ⚠️ GITHUB_TOKEN not set, skipping E2E reports"
return 1
fi
# Get latest workflow run for this commit or branch
WORKFLOW_RUN=$(gh api \
"repos/{owner}/{repo}/actions/runs?head_sha=$COMMIT_SHA&status=completed" \
--jq '.workflow_runs | map(select(.name == "Tests CI")) | .[0]' 2>/dev/null || echo "{}")
RUN_ID=$(echo "$WORKFLOW_RUN" | jq -r '.id // empty')
if [ -z "$RUN_ID" ]; then
echo " No completed test runs found for commit $COMMIT_SHA"
# Try latest on branch instead
RUN_ID=$(gh api \
"repos/{owner}/{repo}/actions/runs?branch=$BRANCH&status=completed" \
--jq '.workflow_runs | map(select(.name == "Tests CI")) | .[0].id // empty' 2>/dev/null || echo "")
fi
if [ -n "$RUN_ID" ]; then
echo " Found workflow run: $RUN_ID"
# Download playwright-report artifact
if gh run download "$RUN_ID" -n playwright-report -D "$ARTIFACT_DIR/playwright-reports" 2>/dev/null; then
echo " ✅ Downloaded E2E test reports"
return 0
else
echo " playwright-report artifact not yet available"
fi
else
echo " No completed workflow runs found"
fi
return 1
}
# ============================================================================
# Fetch Vitest Results from GitHub Actions
# ============================================================================
fetch_vitest_reports() {
echo "[fetch-artifacts] Fetching Vitest results from GitHub Actions..."
if ! command -v gh &> /dev/null || [ -z "$GITHUB_TOKEN" ]; then
echo " ⚠️ Skipping (GitHub CLI or token not available)"
return 1
fi
# Similar logic to E2E, but for vitest artifacts
RUN_ID=$(gh api \
"repos/{owner}/{repo}/actions/runs?head_sha=$COMMIT_SHA&status=completed" \
--jq '.workflow_runs | map(select(.name == "Vitest Tests")) | .[0].id // empty' 2>/dev/null || echo "")
if [ -z "$RUN_ID" ]; then
RUN_ID=$(gh api \
"repos/{owner}/{repo}/actions/runs?branch=$BRANCH&status=completed" \
--jq '.workflow_runs | map(select(.name == "Vitest Tests")) | .[0].id // empty' 2>/dev/null || echo "")
fi
if [ -n "$RUN_ID" ]; then
echo " Found workflow run: $RUN_ID"
if gh run download "$RUN_ID" -n vitest-report -D "$ARTIFACT_DIR/vitest-reports" 2>/dev/null; then
echo " ✅ Downloaded Vitest reports"
return 0
else
echo " vitest-report artifact not yet available"
fi
else
echo " No completed Vitest runs found"
fi
return 1
}
# ============================================================================
# Main execution
# ============================================================================
echo ""
echo "======================================================================"
echo "Fetching Branch Artifacts"
echo "======================================================================"
echo ""
# Run all fetchers (don't fail if some are unavailable)
fetch_storybook || true
fetch_e2e_reports || true
fetch_vitest_reports || true
echo ""
echo "======================================================================"
echo "Artifact Fetch Complete"
echo "======================================================================"
echo ""
echo "Available artifacts:"
ls -lh "$ARTIFACT_DIR" 2>/dev/null || echo " (none)"
echo ""
echo "Note: Missing artifacts will show placeholder content in the status page"
echo ""