diff --git a/.github/workflows/deploy-gh-pages.yml b/.github/workflows/deploy-gh-pages.yml index 3d8a64936..810a2c747 100644 --- a/.github/workflows/deploy-gh-pages.yml +++ b/.github/workflows/deploy-gh-pages.yml @@ -4,11 +4,15 @@ permissions: contents: read pages: write id-token: write + actions: read on: - push: - branches: - - main + # Trigger after successful CI workflows complete + workflow_run: + workflows: ["Storybook and Chromatic CI", "Vitest Tests", "Tests CI"] + types: [completed] + branches: [main] + # Keep manual trigger for debugging workflow_dispatch: concurrency: @@ -18,9 +22,11 @@ concurrency: jobs: build: runs-on: ubuntu-latest + # Only run if the triggering workflow succeeded (or manual dispatch) + if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 - name: Install pnpm uses: pnpm/action-setup@v4 @@ -28,7 +34,7 @@ jobs: version: 10 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v5 with: node-version: '24' cache: 'pnpm' @@ -36,194 +42,77 @@ jobs: - name: Install dependencies run: pnpm install --frozen-lockfile - - name: Build Storybook - run: pnpm build-storybook --output-dir dist/storybook - - - name: Build Nx Graph - run: | - mkdir -p dist/nx-graph - pnpm nx graph --file=dist/nx-graph/index.html || echo "Nx graph generation skipped" + - name: Download Storybook artifact from latest CI run continue-on-error: true - - - name: Build Vitest UI + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mkdir -p dist/vitest-ui - pnpm test:unit --run --reporter=html --reporter=json --outputFile.html=dist/vitest-ui/index.html --outputFile.json=dist/vitest-ui/results.json || echo "Vitest UI generation skipped" + 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 - - - name: Generate test coverage + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - mkdir -p dist/coverage - pnpm test:unit --run --coverage --coverage.reporter=html --coverage.reportsDirectory=dist/coverage || echo "Coverage generation skipped" - continue-on-error: true + echo "🔍 Downloading latest Vitest reports..." - - name: Generate Knip report - run: | - mkdir -p dist/knip - pnpm knip --reporter json > dist/knip/report.json || echo "{}" > dist/knip/report.json - echo 'Knip Report

Knip Report

' > dist/knip/index.html
-          cat dist/knip/report.json >> dist/knip/index.html
-          echo '
' >> dist/knip/index.html - continue-on-error: true + # Get latest successful Vitest workflow run + LATEST_RUN=$(gh api "repos/${{ github.repository }}/actions/workflows" \ + --jq '.workflows[] | select(.name == "Vitest Tests") | .id' | head -1) - - name: Create index page - run: | - cat > dist/index.html << 'EOF' - - - - - - ComfyUI Frontend - Development Tools - - - -
-
-

🎨 ComfyUI Frontend

-

Development Tools & Documentation

-
+ 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 "") -
- -
📚
-

Storybook

-

Interactive component library and design system documentation

- Available -
+ 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) - -
🔗
-

Nx Dependency Graph

-

Visual representation of project dependencies and build structure

- Available -
+ 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 - -
📊
-

Test Coverage

-

Code coverage reports from Vitest unit tests

- Available -
- - -
🧪
-

Vitest Results

-

Interactive test results and reports

- Available -
- - -
🔍
-

Knip Report

-

Unused code and dependency analysis

- Available -
-
- - -
- - - EOF + - name: Build static assets (with artifact reuse) + run: ./scripts/build-gh-pages.sh - name: Setup Pages uses: actions/configure-pages@v4 @@ -231,8 +120,21 @@ jobs: - name: Upload artifact uses: actions/upload-pages-artifact@v3 with: - path: './dist' + 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: environment: name: github-pages diff --git a/.github/workflows/storybook-and-chromatic-ci.yaml b/.github/workflows/storybook-and-chromatic-ci.yaml index bfac96530..707ac5371 100644 --- a/.github/workflows/storybook-and-chromatic-ci.yaml +++ b/.github/workflows/storybook-and-chromatic-ci.yaml @@ -5,7 +5,7 @@ name: Storybook and Chromatic CI on: workflow_dispatch: # Allow manual triggering pull_request: - branches: [main] + branches: [main, sno-deploy-ghpage] jobs: # Post starting comment for non-forked PRs diff --git a/.github/workflows/vitest-tests.yaml b/.github/workflows/vitest-tests.yaml index 394145188..03a641d53 100644 --- a/.github/workflows/vitest-tests.yaml +++ b/.github/workflows/vitest-tests.yaml @@ -46,3 +46,20 @@ jobs: - name: Run Vitest tests run: pnpm test:unit + + - name: Generate test reports (on main branch) + if: github.ref == 'refs/heads/main' + run: | + mkdir -p ./vitest-reports + pnpm exec vitest \ + --reporter=json --outputFile.json="./vitest-reports/results.json" \ + --reporter=html --outputFile.html="./vitest-reports/index.html" \ + --run + + - name: Upload Vitest reports artifact (on main branch) + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v4 + with: + name: vitest-reports + path: vitest-reports/ + retention-days: 7 diff --git a/.gitignore b/.gitignore index 8f69ce164..d99406b0c 100644 --- a/.gitignore +++ b/.gitignore @@ -92,3 +92,14 @@ storybook-static .github/instructions/nx.instructions.md vite.config.*.timestamp* vitest.config.*.timestamp* + +# Github Pages Build output +/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/ diff --git a/docs/pages/.gitignore b/docs/pages/.gitignore new file mode 100644 index 000000000..d1b99b1d6 --- /dev/null +++ b/docs/pages/.gitignore @@ -0,0 +1,14 @@ +* +!/.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/ diff --git a/docs/GITHUB_PAGES_DEPLOYMENT.md b/docs/pages/README.md similarity index 90% rename from docs/GITHUB_PAGES_DEPLOYMENT.md rename to docs/pages/README.md index aed110f60..940a7c1c2 100644 --- a/docs/GITHUB_PAGES_DEPLOYMENT.md +++ b/docs/pages/README.md @@ -33,11 +33,7 @@ The deployment is managed by the `.github/workflows/deploy-gh-pages.yml` workflo 2. **Build Process**: - Installs dependencies with pnpm - - Builds Storybook static site - - Generates Nx dependency graph - - Creates TypeDoc documentation - - Runs tests and generates coverage reports - - Generates Knip analysis report + - 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 3. **Deployment**: @@ -49,7 +45,7 @@ The deployment is managed by the `.github/workflows/deploy-gh-pages.yml` workflo ### Build Steps -Each tool is built in its own step with `continue-on-error: true`, ensuring that if one tool fails to build, the others will still be deployed. +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. #### Storybook (Required) ```bash @@ -63,12 +59,12 @@ pnpm nx graph --file=dist/nx-graph/index.html #### Test Coverage (Optional) ```bash -pnpm test:unit --run --coverage --coverage.reporter=html +pnpm exec vitest --run --coverage --coverage.reporter=html ``` #### Vitest Results (Optional) ```bash -pnpm test:unit --run --reporter=html +pnpm exec vitest --run --reporter=html --outputFile dist/vitest-ui/index.html ``` #### Knip Report (Optional) diff --git a/docs/pages/index.html b/docs/pages/index.html new file mode 100644 index 000000000..e27c6bcc9 --- /dev/null +++ b/docs/pages/index.html @@ -0,0 +1,215 @@ + + + + + + ComfyUI Frontend - Development Tools + + + +
+
+

🎨 ComfyUI Frontend

+

Development Tools & Documentation

+
+ +
+ +
📚
+

Storybook

+

Interactive component library and design system documentation

+ Checking… +
+ + +
🔗
+

Nx Dependency Graph

+

Visual representation of project dependencies and build structure

+ Checking… +
+ + +
📊
+

Test Coverage

+

Code coverage reports from Vitest unit tests

+ Checking… +
+ + +
🎭
+

Playwright E2E

+

Browser end-to-end test reports generated by Playwright

+ Checking… +
+ + +
🧪
+

Vitest Results

+

Interactive test results and reports

+ Checking… +
+ + +
🔍
+

Knip Report

+

Unused code and dependency analysis

+ Checking… +
+
+ + +
+ + + + diff --git a/docs/pages/tsconfig.json b/docs/pages/tsconfig.json new file mode 100644 index 000000000..077f3c520 --- /dev/null +++ b/docs/pages/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "composite": false + }, + "include": [ + "./vite.config.ts" + ] +} diff --git a/docs/pages/vite.config.ts b/docs/pages/vite.config.ts new file mode 100644 index 000000000..b00b77ce4 --- /dev/null +++ b/docs/pages/vite.config.ts @@ -0,0 +1,46 @@ +import fs from 'node:fs' +import { resolve } from 'node:path' +import { defineConfig } from 'vite' + +const rootDir = __dirname +const outDir = resolve(rootDir, '../pages-dist') + +const discoverHtmlEntries = () => { + const entries = new Map() + const topLevel = resolve(rootDir, 'index.html') + if (fs.existsSync(topLevel)) entries.set('index', topLevel) + + for (const dirent of fs.readdirSync(rootDir, { withFileTypes: true })) { + if (!dirent.isDirectory() || dirent.name.startsWith('.')) continue + const candidate = resolve(rootDir, dirent.name, 'index.html') + if (fs.existsSync(candidate)) entries.set(dirent.name, candidate) + } + + return entries.size > 0 ? Object.fromEntries(entries) : undefined +} + +export default defineConfig({ + root: rootDir, + base: '/ComfyUI_frontend', + appType: 'mpa', + logLevel: 'info', + publicDir: false, + server: { + open: '/index.html', + fs: { + allow: [rootDir], + strict: false + } + }, + preview: { + open: '/index.html' + }, + build: { + emptyOutDir: false, + outDir, + copyPublicDir: false, + rollupOptions: { + input: discoverHtmlEntries() + } + } +}) diff --git a/scripts/build-pages.sh b/scripts/build-pages.sh new file mode 100755 index 000000000..85615ca29 --- /dev/null +++ b/scripts/build-pages.sh @@ -0,0 +1,81 @@ +#!/usr/bin/env bash +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" +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 + echo "🔨 Building Storybook from source" + pnpm build-storybook && cp -r "storybook-static" "$DIST/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" + +# Generate or reuse Vitest test reports +echo "[build-pages] Setting up Vitest test reports" +rm -rf "$DIST/vitest-ui" && mkdir -p "$DIST/vitest-ui" +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" +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" \ + --run +fi + +# Set up Playwright test reports if available +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" +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 + 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" +else + echo "⚠️ Knip report failed, creating placeholder..." + cat > "$DIST/knip/report.md" <<'EOF' +# Knip report + +> ⚠️ Knip report unavailable. +> +> Generation failed during build. See CI logs for details. +EOF +fi + +if cp "${ROOT_DIR}/docs/pages/knip/index.html" "$DIST/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] Build artifacts ready in $DIST" + +echo "[build-pages] Note: For local dev, you can develop the docs/pages/index.html using: + pnpm exec vite ${DIST} +"