feat(branch-reports)!: feat(branch-reports): migrate docs/pages to .pages and update CI for Git\n\n- Remove and replace CI workflow for deploying GitHub Pages: deleted .github/workflows/deploy-gh-pages.yml; added .github/workflows/release-pages.yml to deploy to GitHub Pages and Vercel.\n- Reorganize docs assets: move docs/pages to .pages, renaming index.html, knip.html, and Vite config to .pages, and updating README accordingly.\n- Update Knip configuration to include new .pages path and adjust excludes.\n- Update build tooling and scripts to target the new .pages folder: add pages:dev and pages:build scripts, and adjust scripts/build-pages.sh to output to .pages.\n- Update package.json and TS/Vitest configs: include .pages in tsconfig; adjust vitest coverage settings to output under .vitest; add required reporters.\n- Remove legacy docs/pages ignores and tsconfig pointing at docs/pages; replace with .pages equivalents.\n- Note breaking changes: All generated docs/pages outputs are now under .pages. Existing paths, and GitHub Actions workflows expecting docs/pages are replaced by new .pages structure and the release-pages workflow.\n- New Knip HTML wrapper is now placed at .pages/knip.html.

This commit is contained in:
snomiao
2025-10-14 10:31:38 +00:00
parent e4de597460
commit 46d2fd594e
14 changed files with 270 additions and 241 deletions

View File

@@ -1,174 +0,0 @@
name: Deploy to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
actions: read
on:
# Trigger after successful CI workflows complete
workflow_run:
workflows: ["Storybook and Chromatic CI", "Vitest Tests", "Tests CI"]
types: [completed]
branches: [main]
# 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:
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
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: Download Storybook artifact from latest CI run
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🔍 Downloading latest Storybook artifact..."
# Get latest successful Storybook workflow run
LATEST_RUN=$(gh api "repos/${{ github.repository }}/actions/workflows" \
--jq '.workflows[] | select(.name == "Storybook and Chromatic CI") | .id' | head -1)
if [ -n "$LATEST_RUN" ]; then
RUN_ID=$(gh api "repos/${{ github.repository }}/actions/workflows/$LATEST_RUN/runs?status=success&branch=main" \
--jq '.workflow_runs[0].id' 2>/dev/null || echo "")
if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
# Download storybook-static artifact
ARTIFACT_ID=$(gh api "repos/${{ github.repository }}/actions/runs/$RUN_ID/artifacts" \
--jq '.artifacts[] | select(.name == "storybook-static") | .id' | head -1)
if [ -n "$ARTIFACT_ID" ]; then
gh api "repos/${{ github.repository }}/actions/artifacts/$ARTIFACT_ID/zip" > storybook-static.zip
unzip -q storybook-static.zip -d ./storybook-static
echo "✅ Downloaded and extracted Storybook artifact"
else
echo "⚠️ Storybook artifact not found, will build from source"
fi
else
echo "⚠️ No successful Storybook runs found, will build from source"
fi
else
echo "⚠️ Storybook workflow not found, will build from source"
fi
- name: Download Vitest reports from latest CI run
continue-on-error: true
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
echo "🔍 Downloading latest Vitest reports..."
# Get latest successful Vitest workflow run
LATEST_RUN=$(gh api "repos/${{ github.repository }}/actions/workflows" \
--jq '.workflows[] | select(.name == "Vitest Tests") | .id' | head -1)
if [ -n "$LATEST_RUN" ]; then
RUN_ID=$(gh api "repos/${{ github.repository }}/actions/workflows/$LATEST_RUN/runs?status=success&branch=main" \
--jq '.workflow_runs[0].id' 2>/dev/null || echo "")
if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
# Download vitest-reports artifact
ARTIFACT_ID=$(gh api "repos/${{ github.repository }}/actions/runs/$RUN_ID/artifacts" \
--jq '.artifacts[] | select(.name == "vitest-reports") | .id' | head -1)
if [ -n "$ARTIFACT_ID" ]; then
mkdir -p ./.gh-pages-cache
gh api "repos/${{ github.repository }}/actions/artifacts/$ARTIFACT_ID/zip" > vitest-reports.zip
unzip -q vitest-reports.zip -d ./.gh-pages-cache/vitest-reports
echo "✅ Downloaded and extracted Vitest reports"
else
echo "⚠️ Vitest reports not found, will generate from source"
fi
else
echo "⚠️ No successful Vitest runs found, will generate from source"
fi
else
echo "⚠️ Vitest workflow not found, will generate from source"
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@v3
with:
name: built-pages
path: './docs/pages'
# deploy-for-sno-deploy-ghpage-branch:
# runs-on: ubuntu-latest
# needs: build
# if: github.ref == 'refs/heads/sno-deploy-ghpage'
# steps:
# - name: Debug deployment
# run: |
# echo "Contents of ./docs/pages:"
# ls -la ./docs/pages
# echo "Contents of ./docs/pages/vitest-reports (if exists):"
# ls -la ./docs/pages/vitest-reports || echo "No vitest-reports directory"
# echo "Preview URL: https://comfyorg-comfyui-frontend.vercel.app"
deploy-github-pages:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
deploy-vercel-app:
runs-on: ubuntu-latest
needs: build
steps:
- name: Checkout code
uses: actions/checkout@v5
- name: download built pages
uses: actions/download-artifact@v3
with:
name: built-pages
path: ./docs/pages
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} # Required
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} # Required
working-directory: ./docs/pages
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} # Required for Vercel Action

152
.github/workflows/release-pages.yml vendored Normal file
View File

@@ -0,0 +1,152 @@
name: Deploy to GitHub Pages
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: 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: actions/download-artifact@v4
with:
name: storybook-static
path: storybook-static
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- 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@v3
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: actions/download-artifact@v4
with:
name: vitest-reports
path: ./.pages
run-id: ${{ github.event.workflow_run.id }}
github-token: ${{ secrets.GITHUB_TOKEN }}
- 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@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
workflow: vitest-tests.yaml
name: vitest-reports
branch: main
workflow_conclusion: success
path: ./.pages
- 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@v3
with:
name: built-pages
path: './docs/pages'
# deploy-for-sno-deploy-ghpage-branch:
# runs-on: ubuntu-latest
# needs: build
# if: github.ref == 'refs/heads/sno-deploy-ghpage'
# steps:
# - name: Debug deployment
# run: |
# echo "Contents of ./docs/pages:"
# ls -la ./docs/pages
# echo "Contents of ./docs/pages/vitest-reports (if exists):"
# ls -la ./docs/pages/vitest-reports || echo "No vitest-reports directory"
# echo "Preview URL: https://comfyorg-comfyui-frontend.vercel.app"
incremental-deploy-github-pages:
permissions:
contents: read
pages: write
id-token: write
actions: read
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: incremental-build
steps:
# - [Feature request: Partial upload/deploy · Issue #349 · actions/deploy-pages]( https://github.com/actions/deploy-pages/issues/349 )
- name: Checkout code
uses: actions/checkout@v5
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
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@v3
with:
name: built-pages
path: ./docs/pages
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }} # Required
vercel-org-id: ${{ secrets.VERCEL_ORG_ID }} # Required
vercel-project-id: ${{ secrets.VERCEL_PROJECT_ID }} # Required
working-directory: ./docs/pages
env:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }} # Required for Vercel Action

14
.gitignore vendored
View File

@@ -78,7 +78,7 @@ templates_repo/
vite.config.mts.timestamp-*.mjs
# Linux core dumps
./core
/core
*storybook.log
storybook-static
@@ -93,14 +93,8 @@ storybook-static
vite.config.*.timestamp*
vitest.config.*.timestamp*
# Github Pages Build output
/pages-dist
# Generated reports in docs/pages (exclude generated, keep HTML templates)
/.pages/*/**/*
/.pages-dist/
# Generated reports in docs/pages (exclude JSON data, keep HTML templates)
docs/pages/knip/report.json
docs/pages/vitest-ui/results.json
docs/pages/coverage/
docs/pages/nx-graph/
docs/pages/storybook/
docs/pages/playwright-reports/
.vercel

View File

@@ -17,11 +17,7 @@
align-items: center;
justify-content: center;
padding: 2rem;
/* bg: gray + white lines net */
background: #909090;
background-image: radial-gradient(circle, rgba(255, 255, 255, 0.05) 2px, transparent 2px), radial-gradient(circle, rgba(255, 255, 255, 0.05) 2px, transparent 2px);
background-position: 0 0, 25px 25px;
background-size: 50px 50px;
background: linear-gradient(135deg, #667eea 0%, #52b2bb 100%);
}
.container {
max-width: 1200px;

80
.pages/knip.html Normal file
View File

@@ -0,0 +1,80 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Knip Report</title>
<style>
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', sans-serif;
padding: 2rem;
background: #1a1a1a;
color: #f0f0f0;
line-height: 1.6;
}
h1 {
color: #4a9eff;
border-bottom: 3px solid #4a9eff;
padding-bottom: 1rem;
}
.status {
display: inline-block;
padding: 0.5rem 1rem;
margin: 1rem 0;
border-radius: 6px;
font-weight: 500;
}
.error {
background: #d32f2f;
color: #ffebee;
}
.loading {
background: #f57c00;
color: #fff3e0;
}
#content {
background: #2a2a2a;
padding: 1rem;
border-radius: 8px;
border: 1px solid #404040;
}
</style>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js" defer></script>
</head>
<body>
<h1>🧹 Knip Code Quality Report</h1>
<div id="status" class="status loading">Loading report...</div>
<div id="content"></div>
<script>
async function loadReport() {
const statusEl = document.getElementById('status')
const contentEl = document.getElementById('content')
try {
const response = await fetch('./knip/report.md')
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const reportText = await response.text()
statusEl.style.display = 'none'
if (window.marked) {
contentEl.innerHTML = window.marked.parse(reportText)
} else {
contentEl.innerHTML = `<pre>${reportText}</pre>`
}
} catch (error) {
statusEl.className = 'status error'
statusEl.textContent = `Failed to load report: ${error.message}`
contentEl.innerHTML = '<p>The Knip report could not be loaded. This might happen if:</p><ul><li>The report generation failed during build</li><li>No unused code was detected</li><li>Network connectivity issues</li></ul>'
}
}
loadReport()
</script>
</body>
</html>

View File

@@ -3,7 +3,7 @@ import { resolve } from 'node:path'
import { defineConfig } from 'vite'
const rootDir = __dirname
const outDir = resolve(rootDir, '../pages-dist')
const outDir = resolve(rootDir, '../.pages-dist')
const discoverHtmlEntries = () => {
const entries = new Map<string, string>()

14
docs/pages/.gitignore vendored
View File

@@ -1,14 +0,0 @@
*
!/.gitignore
!/README.md
!/index.html
!/knip/
!/knip/index.html
knip/report.md
!/vite.config.ts
!/tsconfig.json
/storybook/
/nx-graph/
/coverage/
/vitest-ui/
/playwright-reports/

View File

@@ -1,9 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"composite": false
},
"include": [
"./vite.config.ts"
]
}

View File

@@ -40,8 +40,8 @@ const config: KnipConfig = {
'packages/registry-types/src/comfyRegistryTypes.ts',
// Used by a custom node (that should move off of this)
'src/scripts/ui/components/splitButton.ts',
'docs/pages/public/**/*',
'docs/pages/public/vite.config.ts'
'.pages/**/*',
'.pages/vite.config.ts'
],
compilers: {
// https://github.com/webpro-nl/knip/issues/1008#issuecomment-3207756199

View File

@@ -10,7 +10,6 @@
"scripts": {
"build:desktop": "nx build @comfyorg/desktop-ui",
"build-storybook": "storybook build",
"build:pages": "bash scripts/build-pages.sh",
"build:types": "nx build --config vite.types.config.mts && node scripts/prepare-types.js",
"build": "cross-env NODE_OPTIONS='--max-old-space-size=8192' pnpm typecheck && nx build",
"collect-i18n": "pnpm exec playwright test --config=playwright.i18n.config.ts",
@@ -32,6 +31,8 @@
"lint:unstaged": "git diff --name-only HEAD | grep -E '\\.(js|ts|vue|mts)$' | xargs -r eslint --cache",
"lint": "eslint src --cache",
"locale": "lobe-i18n locale",
"pages:dev": "vite --config ./.pages/vite.config.ts",
"pages:build": "bash scripts/build-pages.sh && vite build --config ./.pages/vite.config.ts",
"preinstall": "pnpm dlx only-allow pnpm",
"prepare": "husky || true && git config blame.ignoreRevsFile .git-blame-ignore-revs || true",
"preview": "nx preview",

View File

@@ -3,34 +3,34 @@ set -Eeuo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
cd "$ROOT_DIR"
DIST="./docs/pages"
# Build or reuse Storybook
echo "[build-pages] Setting up Storybook"
rm -rf "$DIST/storybook"
rm -rf "./.pages/storybook"
if [ -d "./storybook-static" ] && [ "$(find ./storybook-static -name '*.html' | wc -l)" -gt 0 ]; then
echo "✅ Reusing downloaded Storybook build"
cp -r "./storybook-static" "$DIST/storybook"
elsew
cp -r "./storybook-static" "./.pages/storybook"
else
echo "🔨 Building Storybook from source"
pnpm build-storybook && cp -r "storybook-static" "$DIST/storybook"
pnpm build-storybook && cp -r "storybook-static" "./.pages/storybook"
fi
echo "[build-pages] Generating Nx dependency graph"
rm -rf "$DIST/nx-graph" && mkdir -p "$DIST/nx-graph"
pnpm nx graph --file="$DIST/nx-graph/index.html"
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
echo "[build-pages] Setting up Vitest test reports"
rm -rf "$DIST/vitest-ui" && mkdir -p "$DIST/vitest-ui"
rm -rf "./.pages/vitest-reports" && mkdir -p "./.pages/vitest-reports"
if [ -d "./.gh-pages-cache/vitest-reports" ]; then
echo "✅ Reusing downloaded Vitest reports"
cp -r "./.gh-pages-cache/vitest-reports/"* "$DIST/vitest-ui/" 2>/dev/null || echo "⚠️ No vitest reports to copy"
cp -r "./.gh-pages-cache/vitest-reports/"* "./.pages/vitest-reports/" 2>/dev/null || echo "⚠️ No vitest reports to copy"
else
echo "🔨 Generating Vitest reports from source"
pnpm exec vitest \
--reporter=json --outputFile.json="$DIST/vitest-ui/results.json" \
--reporter=html --outputFile.html="$DIST/vitest-ui/index.html" \
--reporter=json --outputFile.json="./.pages/vitest-reports/results.json" \
--reporter=html --outputFile.html="./.pages/vitest-reports/index.html" \
--run
fi
@@ -38,26 +38,26 @@ fi
echo "[build-pages] Setting up Playwright test reports"
if [ -d "./.gh-pages-cache/playwright-reports" ]; then
echo "✅ Reusing downloaded Playwright reports"
mkdir -p "$DIST/playwright-reports"
cp -r "./.gh-pages-cache/playwright-reports/"* "$DIST/playwright-reports/" 2>/dev/null || echo "⚠️ No playwright reports to copy"
mkdir -p "./.pages/playwright-reports"
cp -r "./.gh-pages-cache/playwright-reports/"* "./.pages/playwright-reports/" 2>/dev/null || echo "⚠️ No playwright reports to copy"
fi
echo "[build-pages] Generating coverage report"
mkdir -p "$DIST/coverage"
if pnpm exec vitest --run --coverage --coverage.reporter=html --coverage.reportsDirectory="$DIST/coverage"; then
mkdir -p "./.pages/coverage"
if pnpm exec vitest --run --coverage --coverage.reporter=html --coverage.reportsDirectory="./.pages/coverage"; then
echo "✅ Coverage report completed"
else
echo "⚠️ Coverage report failed, continuing..."
fi
echo "[build-pages] Generating Knip report"
mkdir -p "$DIST/knip"
rm -f "$DIST/knip/report.md"
if pnpm knip --reporter markdown --no-progress --no-exit-code > "$DIST/knip/report.md" 2>/dev/null && [ -s "$DIST/knip/report.md" ]; then
echo "✅ Knip report generated at $DIST/knip/report.md"
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 > "$DIST/knip/report.md" <<'EOF'
cat > "./.pages/knip/report.md" <<'EOF'
# Knip report
> ⚠️ Knip report unavailable.
@@ -66,16 +66,16 @@ else
EOF
fi
if cp "${ROOT_DIR}/docs/pages/knip/index.html" "$DIST/knip/index.html" 2>/dev/null; then
if cp "${ROOT_DIR}/docs/pages/knip/index.html" "./.pages/knip/index.html" 2>/dev/null; then
echo "✅ Knip HTML wrapper completed"
else
echo "⚠️ Knip HTML wrapper missing, continuing..."
fi
echo "[build-pages] Landing page already exists at $DIST/index.html"
echo "[build-pages] Landing page already exists at ./.pages/index.html"
echo "[build-pages] Build artifacts ready in $DIST"
echo "[build-pages] Build artifacts ready in ./.pages"
echo "[build-pages] Note: For local dev, you can develop the docs/pages/index.html using:
pnpm exec vite ${DIST}
pnpm exec vite ./.pages
"

View File

@@ -49,6 +49,7 @@
"rootDir": "./"
},
"include": [
".pages/*.ts",
".storybook/**/*",
"eslint.config.ts",
"global.d.ts",

View File

@@ -23,8 +23,10 @@ export default defineConfig({
'src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}'
],
coverage: {
reporter: ['text', 'json', 'html']
reporter: ['text', 'json', 'html'],
reportsDirectory: './.vitest/coverage'
},
reporters: ['html', 'json'],
exclude: [
'**/node_modules/**',
'**/dist/**',