mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-19 22:34:15 +00:00
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:
186
.github/workflows/release-pages.yml
vendored
186
.github/workflows/release-pages.yml
vendored
@@ -1,186 +0,0 @@
|
||||
name: Deploy to GitHub Pages
|
||||
description: Build and deploy to GitHub Pages and Vercel on successful completion of tests and builds
|
||||
|
||||
on:
|
||||
# Triggers when any of these workflows complete on main branch
|
||||
# Runs ONCE per workflow completion (e.g., if "Vitest Tests" completes, this workflow runs once)
|
||||
workflow_run:
|
||||
workflows: ['Storybook and Chromatic CI', 'Vitest Tests', 'Tests CI']
|
||||
types: [completed]
|
||||
# Allow direct pushes to the debug branch to kick off the full pipeline
|
||||
push:
|
||||
branches: [sno-deploy-ghpage]
|
||||
# Keep manual trigger for debugging
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
incremental-build:
|
||||
runs-on: ubuntu-latest
|
||||
# Only run if the triggering workflow succeeded (or manual dispatch/push)
|
||||
if: github.event_name == 'workflow_dispatch' || github.event_name == 'push' || github.event.workflow_run.conclusion == 'success'
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: Install pnpm
|
||||
uses: pnpm/action-setup@v4
|
||||
with:
|
||||
version: 10
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v5
|
||||
with:
|
||||
node-version: '24'
|
||||
cache: 'pnpm'
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Cache build artifacts
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
.pages
|
||||
storybook-static
|
||||
coverage
|
||||
key: build-cache-${{ github.ref_name }}-${{ github.run_id }}-${{ hashFiles('pnpm-lock.yaml', 'package.json') }}
|
||||
restore-keys: |
|
||||
build-cache-${{ github.ref_name }}-
|
||||
build-cache-main-
|
||||
|
||||
- name: Download Storybook artifact (source run)
|
||||
id: fetch_storybook_trigger
|
||||
continue-on-error: true
|
||||
if: github.event_name == 'workflow_run' && github.event.workflow_run.name == 'Storybook and Chromatic CI'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: storybook-and-chromatic-ci.yaml
|
||||
name: storybook-static
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: storybook-static
|
||||
|
||||
- name: Download Storybook artifact (latest successful run on main)
|
||||
continue-on-error: true
|
||||
if: steps.fetch_storybook_trigger.outcome != 'success'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: storybook-and-chromatic-ci.yaml
|
||||
name: storybook-static
|
||||
branch: main
|
||||
workflow_conclusion: success
|
||||
path: storybook-static
|
||||
|
||||
- name: Download Vitest reports (source run)
|
||||
id: fetch_vitest_trigger
|
||||
continue-on-error: true
|
||||
if: github.event_name == 'workflow_run' && github.event.workflow_run.name == 'Vitest Tests'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: vitest-tests.yaml
|
||||
name: vitest-reports
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: ./.pages/vitest-reports
|
||||
|
||||
- name: Download Vitest reports (latest successful run on main)
|
||||
continue-on-error: true
|
||||
if: steps.fetch_vitest_trigger.outcome != 'success'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: vitest-tests.yaml
|
||||
name: vitest-reports
|
||||
branch: main
|
||||
workflow_conclusion: success
|
||||
path: ./.pages/vitest-reports
|
||||
|
||||
- name: Download Playwright E2E reports (source run)
|
||||
id: fetch_playwright_trigger
|
||||
continue-on-error: true
|
||||
if: github.event_name == 'workflow_run' && github.event.workflow_run.name == 'Tests CI'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: ci-tests-e2e.yaml
|
||||
name_is_regexp: true
|
||||
name: playwright-report-.*
|
||||
run_id: ${{ github.event.workflow_run.id }}
|
||||
path: ./playwright-reports-temp
|
||||
|
||||
- name: Download Playwright E2E reports (latest successful run on main)
|
||||
continue-on-error: true
|
||||
if: steps.fetch_playwright_trigger.outcome != 'success'
|
||||
uses: dawidd6/action-download-artifact@v6
|
||||
with:
|
||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||
workflow: ci-tests-e2e.yaml
|
||||
name_is_regexp: true
|
||||
name: playwright-report-.*
|
||||
branch: main
|
||||
workflow_conclusion: success
|
||||
path: ./playwright-reports-temp
|
||||
|
||||
- name: Organize Playwright reports by browser
|
||||
if: always()
|
||||
run: |
|
||||
mkdir -p ./.pages/playwright-reports
|
||||
|
||||
# Move each browser report to its own directory
|
||||
if [ -d "./playwright-reports-temp" ]; then
|
||||
for dir in ./playwright-reports-temp/playwright-report-*; do
|
||||
if [ -d "$dir" ]; then
|
||||
browser_name=$(basename "$dir" | sed 's/playwright-report-//')
|
||||
mkdir -p "./.pages/playwright-reports/${browser_name}"
|
||||
cp -r "$dir"/* "./.pages/playwright-reports/${browser_name}/"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
- name: Build static assets (with artifact reuse)
|
||||
run: ./scripts/build-pages.sh
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Upload built pages as cache
|
||||
uses: actions/upload-pages-artifact@v4
|
||||
with:
|
||||
name: built-pages
|
||||
path: '.pages'
|
||||
|
||||
deploy-vercel-app:
|
||||
runs-on: ubuntu-latest
|
||||
needs: incremental-build
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- name: download built pages
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: built-pages
|
||||
path: ./artifact
|
||||
|
||||
- name: Extract artifact
|
||||
run: |
|
||||
mkdir -p ./.pages
|
||||
cd ./artifact
|
||||
tar -xf artifact.tar -C ../.pages
|
||||
|
||||
# debug ls of ./.pages
|
||||
- name: List ./.pages contents
|
||||
run: ls -la ./.pages
|
||||
|
||||
- name: Deploy to Vercel
|
||||
uses: amondnet/vercel-action@v20
|
||||
with:
|
||||
vercel-token: ${{ secrets.VERCEL_TOKEN }}
|
||||
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }}
|
||||
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }}
|
||||
working-directory: .pages
|
||||
vercel-args: ${{ github.ref_name == 'main' && '--prod' || '' }}
|
||||
github-comment: true
|
||||
alias-domains: |
|
||||
${{ github.ref_name }}-comfyui-frontend-reports.vercel.app
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -97,4 +97,7 @@ vitest.config.*.timestamp*
|
||||
/.pages/*/**/*
|
||||
/.pages-dist/
|
||||
|
||||
# Fetched artifacts for Vercel builds
|
||||
/.page/
|
||||
|
||||
.vercel
|
||||
|
||||
211
.pages/README.md
211
.pages/README.md
@@ -1,160 +1,153 @@
|
||||
# GitHub Pages Deployment
|
||||
# Branch Status Pages
|
||||
|
||||
This document describes the GitHub Pages deployment setup for ComfyUI Frontend development tools.
|
||||
This directory contains the source for the branch status pages that aggregate development tools and test reports.
|
||||
|
||||
## Overview
|
||||
## Deployment
|
||||
|
||||
The project automatically deploys the following development tools to GitHub Pages on every merge to the `main` branch:
|
||||
The branch status pages are automatically deployed to **Vercel** on every push to any branch.
|
||||
|
||||
- **Storybook** - Interactive component library and design system documentation
|
||||
- **Nx Dependency Graph** - Visual representation of project dependencies
|
||||
- **Test Coverage Reports** - Code coverage from Vitest unit tests
|
||||
- **Vitest Results** - Interactive test results and reports
|
||||
- **Knip Report** - Unused code and dependency analysis
|
||||
### Architecture
|
||||
|
||||
## Accessing the Tools
|
||||
|
||||
Once deployed, all tools are accessible from a single landing page at:
|
||||
```
|
||||
https://comfy-org.github.io/ComfyUI_frontend/
|
||||
Push to Branch
|
||||
↓
|
||||
├─→ GitHub Actions (runs tests, deploys artifacts)
|
||||
│ ├─→ Storybook → Cloudflare Pages
|
||||
│ ├─→ E2E Tests → GitHub Actions Artifacts
|
||||
│ └─→ Vitest → GitHub Actions Artifacts
|
||||
│
|
||||
└─→ Vercel (auto-triggered)
|
||||
↓
|
||||
Runs: pnpm pages:build:branch-status
|
||||
↓
|
||||
1. Fetches test results from deployed sources
|
||||
2. Builds status pages
|
||||
3. Deploys automatically
|
||||
```
|
||||
|
||||
## Primary Use Case: Storybook for Design Team
|
||||
### URLs
|
||||
|
||||
The primary motivation for this deployment is to provide the design team with a consistent, bookmarkable URL to reference the latest component system state. Instead of sharing PR-specific Storybook builds, the design team can always access the latest approved components from the main branch.
|
||||
- **Production** (main branch): `https://comfyui-frontend-reports.vercel.app`
|
||||
- **Preview** (PR branches): `https://<branch>-comfyui-frontend-reports.vercel.app`
|
||||
|
||||
## Deployment Workflow
|
||||
## What's Included
|
||||
|
||||
The deployment is managed by the `.github/workflows/release-pages.yml` workflow, which:
|
||||
The branch status page aggregates:
|
||||
|
||||
1. **Triggers on**:
|
||||
- Push to `main` branch
|
||||
- Manual workflow dispatch
|
||||
1. **Storybook** - Component library documentation
|
||||
2. **Nx Dependency Graph** - Project structure visualization
|
||||
3. **Playwright Reports** - E2E test results
|
||||
4. **Vitest Reports** - Unit test results
|
||||
5. **Coverage Report** - Code coverage metrics
|
||||
6. **Knip Report** - Unused code and dependency analysis
|
||||
|
||||
2. **Build Process**:
|
||||
- Installs dependencies with pnpm
|
||||
- Runs `scripts/build-pages.sh` to generate Storybook, Nx dependency graph, Vitest reports, coverage, and Knip analysis
|
||||
- Creates a landing page with links to all tools
|
||||
## How It Works
|
||||
|
||||
3. **Deployment**:
|
||||
- Uses GitHub Pages deploy action
|
||||
- Deploys to `gh-pages` branch
|
||||
- Available at the GitHub Pages URL
|
||||
### Artifact Fetching
|
||||
|
||||
## Workflow Details
|
||||
The `scripts/fetch-branch-artifacts.sh` script fetches test results from:
|
||||
|
||||
### Build Steps
|
||||
- **Storybook**: Deployed to Cloudflare Pages (fetches URL from PR comments)
|
||||
- **E2E/Vitest**: Downloaded from GitHub Actions artifacts using `gh` CLI
|
||||
- **Knip**: Generated fresh during build (fast)
|
||||
|
||||
The build script handles optional tooling gracefully—if an individual tool fails to build, the remainder of the deployment still proceeds and the failure is logged as a warning.
|
||||
### Graceful Fallbacks
|
||||
|
||||
If artifacts aren't available yet (CI still running), the build script creates placeholder pages with loading indicators. This allows Vercel to deploy immediately without waiting for all CI to complete.
|
||||
|
||||
## Local Development
|
||||
|
||||
#### Storybook (Required)
|
||||
```bash
|
||||
pnpm build-storybook --output-dir dist/storybook
|
||||
# Develop the index page
|
||||
pnpm pages:dev
|
||||
|
||||
# Build without fetching artifacts (uses local builds)
|
||||
pnpm pages:build
|
||||
|
||||
# Build with artifact fetching (simulates Vercel)
|
||||
pnpm pages:build:branch-status
|
||||
```
|
||||
|
||||
#### Nx Graph (Optional)
|
||||
```bash
|
||||
pnpm nx graph --file=dist/nx-graph/index.html
|
||||
```
|
||||
## Environment Variables (Vercel)
|
||||
|
||||
#### Test Coverage (Optional)
|
||||
```bash
|
||||
pnpm exec vitest --run --coverage --coverage.reporter=html
|
||||
```
|
||||
Configure these in Vercel project settings:
|
||||
|
||||
#### Vitest Results (Optional)
|
||||
```bash
|
||||
pnpm exec vitest --run --reporter=html --outputFile dist/vitest-ui/index.html
|
||||
```
|
||||
- `GITHUB_TOKEN` - For fetching artifacts via GitHub API (required)
|
||||
- `CLOUDFLARE_ACCOUNT_ID` - For Cloudflare API (optional)
|
||||
- `CLOUDFLARE_API_TOKEN` - For Cloudflare API (optional)
|
||||
|
||||
#### Knip Report (Optional)
|
||||
```bash
|
||||
pnpm knip --reporter json
|
||||
```
|
||||
## Files
|
||||
|
||||
### Permissions
|
||||
- **index.html** - Main landing page with links to all reports
|
||||
- **vite.config.ts** - Vite configuration for building the static site
|
||||
- **knip.html** - Wrapper for displaying Knip markdown report
|
||||
- **playwright-reports.html** - Wrapper for E2E test reports
|
||||
|
||||
The workflow requires the following permissions:
|
||||
```yaml
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
```
|
||||
## Adding New Reports
|
||||
|
||||
## Manual Deployment
|
||||
To add a new report to the status page:
|
||||
|
||||
You can manually trigger a deployment from the GitHub Actions tab:
|
||||
|
||||
1. Go to Actions → Deploy to GitHub Pages
|
||||
2. Click "Run workflow"
|
||||
3. Select the `main` branch
|
||||
4. Click "Run workflow"
|
||||
1. Update `scripts/fetch-branch-artifacts.sh` to fetch the new artifact
|
||||
2. Update `scripts/build-pages.sh` to process and copy it
|
||||
3. Add a link in `index.html`
|
||||
4. Optionally create a wrapper HTML file for custom styling
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Storybook Build Fails
|
||||
### Artifacts not appearing
|
||||
|
||||
If the Storybook build fails:
|
||||
1. Check that all Storybook stories are syntactically correct
|
||||
2. Verify that all components can be imported
|
||||
3. Run `pnpm build-storybook` locally to reproduce the issue
|
||||
- Check Vercel build logs for fetch errors
|
||||
- Verify `GITHUB_TOKEN` is set in Vercel environment
|
||||
- Ensure GitHub Actions workflows completed successfully
|
||||
- Artifacts may not be available for old commits (7-day retention)
|
||||
|
||||
### Other Tools Fail
|
||||
### Slow builds
|
||||
|
||||
Since all tools except Storybook are marked with `continue-on-error: true`, they will not prevent deployment. If a tool consistently fails:
|
||||
- Artifact fetching is designed to be fast (<30s)
|
||||
- If builds are slow, check network connectivity to GitHub/Cloudflare
|
||||
- Consider skipping slow-to-generate reports (like coverage)
|
||||
|
||||
1. Check the GitHub Actions logs for the specific error
|
||||
2. Test the build command locally
|
||||
3. Consider adjusting the build command in the workflow
|
||||
### Storybook redirect not working
|
||||
|
||||
### GitHub Pages Not Updating
|
||||
- Verify Cloudflare Pages deployment succeeded
|
||||
- Check PR comments for correct Storybook URL
|
||||
- Fallback: Storybook will show placeholder page
|
||||
|
||||
If changes aren't reflected on the live site:
|
||||
## CI Integration
|
||||
|
||||
1. Check the workflow run in the Actions tab
|
||||
2. Verify that the deployment step succeeded
|
||||
3. GitHub Pages can take a few minutes to update
|
||||
4. Clear your browser cache or try an incognito window
|
||||
No GitHub Actions workflow is needed for Vercel deployments. Vercel automatically:
|
||||
|
||||
## Maintenance
|
||||
1. Detects new commits via GitHub webhook
|
||||
2. Triggers build with `pnpm pages:build:branch-status`
|
||||
3. Deploys to branch-specific URL
|
||||
4. Comments on PR with deployment URL
|
||||
|
||||
### Adding New Tools
|
||||
## Migration Notes
|
||||
|
||||
To add a new development tool to the deployment:
|
||||
This replaces the previous GitHub Pages deployment approach which:
|
||||
- ❌ Required complex artifact passing between GitHub Actions and Vercel
|
||||
- ❌ Had to wait for all CI to complete before deploying
|
||||
- ❌ Was prone to failure due to artifact extraction issues
|
||||
|
||||
1. Add a new build step in `.github/workflows/release-pages.yml`
|
||||
2. Ensure the output goes to a subdirectory of `dist/`
|
||||
3. Add `continue-on-error: true` if the tool is optional
|
||||
4. Update the landing page `dist/index.html` with a link to the new tool
|
||||
The new Vercel-native approach:
|
||||
- ✅ Deploys immediately on every push
|
||||
- ✅ Fetches artifacts on-demand during build
|
||||
- ✅ Shows placeholders for pending CI
|
||||
- ✅ Simpler, more reliable architecture
|
||||
|
||||
### Removing Tools
|
||||
## Primary Use Case: Development Team
|
||||
|
||||
To remove a tool from deployment:
|
||||
This deployment provides:
|
||||
|
||||
1. Remove the build step from the workflow
|
||||
2. Remove the corresponding link from the landing page
|
||||
|
||||
## Cost Considerations
|
||||
|
||||
GitHub Pages is free for public repositories and includes:
|
||||
- 1 GB storage
|
||||
- 100 GB bandwidth per month
|
||||
- 10 builds per hour
|
||||
|
||||
This should be more than sufficient for the development tools deployment.
|
||||
|
||||
## Security
|
||||
|
||||
The deployment only includes static, built artifacts:
|
||||
- No source code is directly exposed
|
||||
- No secrets or credentials are included
|
||||
- All content is publicly accessible (appropriate for public repo)
|
||||
1. **For Design Team**: Consistent, bookmarkable URL to reference the latest component system state
|
||||
2. **For Developers**: Quick access to test results and coverage for any branch
|
||||
3. **For PR Reviews**: Easy verification of Storybook changes and test results
|
||||
|
||||
## Related Documentation
|
||||
|
||||
- [GitHub Pages Documentation](https://docs.github.com/en/pages)
|
||||
- [Vercel Documentation](https://vercel.com/docs)
|
||||
- [Storybook Documentation](https://storybook.js.org/docs)
|
||||
- [Nx Documentation](https://nx.dev)
|
||||
- [Vitest Documentation](https://vitest.dev)
|
||||
- [Knip Documentation](https://knip.dev)
|
||||
- [Knip Documentation](https://knip.dev)
|
||||
- [Playwright Documentation](https://playwright.dev)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
"build-storybook": "storybook build",
|
||||
"build:types": "nx build --config vite.types.config.mts && node scripts/prepare-types.js",
|
||||
"build:analyze": "cross-env ANALYZE_BUNDLE=true pnpm build",
|
||||
"build:branch-status": "...",
|
||||
"build": "cross-env NODE_OPTIONS='--max-old-space-size=8192' pnpm typecheck && nx build",
|
||||
"size:collect": "node scripts/size-collect.js",
|
||||
"size:report": "node scripts/size-report.js",
|
||||
@@ -37,6 +38,7 @@
|
||||
"locale": "lobe-i18n locale",
|
||||
"oxlint": "oxlint src --type-aware",
|
||||
"pages:build": "bash scripts/build-pages.sh && vite build --config ./.pages/vite.config.ts",
|
||||
"pages:build:branch-status": "bash scripts/fetch-branch-artifacts.sh && bash scripts/build-pages.sh && vite build --config ./.pages/vite.config.ts",
|
||||
"pages:dev": "vite --config ./.pages/vite.config.ts",
|
||||
"preinstall": "pnpm dlx only-allow pnpm",
|
||||
"prepare": "husky || true && git config blame.ignoreRevsFile .git-blame-ignore-revs || true",
|
||||
|
||||
@@ -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
168
scripts/fetch-branch-artifacts.sh
Executable 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 ""
|
||||
19
vercel.json
Normal file
19
vercel.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"$schema": "https://openapi.vercel.sh/vercel.json",
|
||||
"buildCommand": "pnpm pages:build:branch-status",
|
||||
"outputDirectory": ".pages/dist",
|
||||
"installCommand": "pnpm install --frozen-lockfile",
|
||||
"framework": null,
|
||||
"devCommand": "pnpm pages:dev",
|
||||
"git": {
|
||||
"deploymentEnabled": {
|
||||
"main": true,
|
||||
"*": true
|
||||
}
|
||||
},
|
||||
"github": {
|
||||
"enabled": true,
|
||||
"autoAlias": true,
|
||||
"silent": false
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user