From 1a5b34449e1d03d63f4bbddf485cffe42e0651be Mon Sep 17 00:00:00 2001 From: Beast Date: Fri, 23 Jan 2026 13:59:18 +0800 Subject: [PATCH 1/2] feat: add code quality CI --- .github/workflows/code-quality.yml | 41 ++++++++++++++++++++++++++++++ .github/workflows/seo.yml | 12 ++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/code-quality.yml diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 0000000..b431b35 --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,41 @@ +name: Code Quality + +on: + push: + branches: ["main"] + pull_request: + branches: ["main"] + +jobs: + code-quality: + name: Code Quality + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + # Cache dependencies for faster builds + - uses: actions/cache@v4 + id: bun-cache + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('website/bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun- + + - uses: actions/cache@v4 + id: node-modules-cache + with: + path: website/node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('website/package.json') }} + restore-keys: | + ${{ runner.os }}-node-modules- + + - name: Install Dependencies & Run Code Quality + working-directory: website + run: | + bun install --frozen-lockfile + bun run format:check \ No newline at end of file diff --git a/.github/workflows/seo.yml b/.github/workflows/seo.yml index e9f7227..4f3ef68 100644 --- a/.github/workflows/seo.yml +++ b/.github/workflows/seo.yml @@ -1,11 +1,21 @@ name: Quality & SEO Audit -on: [pull_request] +on: + workflow_run: + workflows: ["Code Quality"] + types: + - completed jobs: audit: runs-on: ubuntu-latest + # Only run if the code-quality workflow succeeded + if: ${{ github.event.workflow_run.conclusion == 'success' }} steps: - uses: actions/checkout@v4 + with: + # Checkout the same commit that triggered the code-quality workflow + ref: ${{ github.event.workflow_run.head_branch }} + sha: ${{ github.event.workflow_run.head_sha }} - uses: oven-sh/setup-bun@v2 with: From 9c8ecab2c8d9db399f999b17b964aaf9b87adf2c Mon Sep 17 00:00:00 2001 From: Beast Date: Fri, 23 Jan 2026 14:04:09 +0800 Subject: [PATCH 2/2] feat: merge workflow --- .github/workflows/code-quality.yml | 108 ++++++++++++++++++++++++++- .github/workflows/seo.yml | 114 ----------------------------- 2 files changed, 106 insertions(+), 116 deletions(-) delete mode 100644 .github/workflows/seo.yml diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml index b431b35..daccca1 100644 --- a/.github/workflows/code-quality.yml +++ b/.github/workflows/code-quality.yml @@ -1,4 +1,4 @@ -name: Code Quality +name: Code Quality & SEO Audit on: push: @@ -38,4 +38,108 @@ jobs: working-directory: website run: | bun install --frozen-lockfile - bun run format:check \ No newline at end of file + bun run format:check + + seo-audit: + name: SEO Audit + runs-on: ubuntu-latest + # Only run if code-quality job succeeds + needs: code-quality + steps: + - uses: actions/checkout@v4 + + - uses: oven-sh/setup-bun@v2 + with: + bun-version: latest + + # Cache dependencies for faster builds + - uses: actions/cache@v4 + id: bun-cache + with: + path: ~/.bun/install/cache + key: ${{ runner.os }}-bun-${{ hashFiles('website/bun.lock') }} + restore-keys: | + ${{ runner.os }}-bun- + + - uses: actions/cache@v4 + id: node-modules-cache + with: + path: website/node_modules + key: ${{ runner.os }}-node-modules-${{ hashFiles('website/package.json') }} + restore-keys: | + ${{ runner.os }}-node-modules- + + # Install Chromium for Puppeteer (required by Unlighthouse) + # This action sets CHROMIUM_PATH environment variable automatically + - name: Setup Chromium + uses: browser-actions/setup-chromium@v1 + with: + chromium-version: latest + + # 1. Build and Start Server + # NOTE: Astro outputs to 'dist' directory by default + # Set SITE_BASE_URL to localhost for CI so all links point to localhost instead of production + - name: Install Dependencies & Build + working-directory: website + env: + SITE_BASE_URL: "http://localhost:3000" + run: | + bun install --frozen-lockfile + bun run build + + # 2. Start Static Server (Astro outputs to 'dist' directory) + - name: Start Static Server + working-directory: website + run: | + npx --yes serve@latest dist -p 3000 & + npx wait-on http://localhost:3000 --timeout 60000 || (echo "Server failed to start" && exit 1) + + # 3. FAIL FAST: Broken Link Checker + # Only check links on localhost:3000, skip external links (e.g., https://www.quantus.com) + - name: Check for Broken Links + run: | + npx --yes linkinator http://localhost:3000 --recurse --skip "^(?!http://localhost:3000)" + + # 4. DEEP AUDIT: Unlighthouse + # Scans all pages for both desktop and mobile devices + # Fails if SEO score is below 100 (configured in unlighthouse.config.ts) + # The '--build-static' flag generates the HTML report files. + # PUPPETEER_SKIP_CHROMIUM_DOWNLOAD tells Puppeteer to use the system Chromium from setup-chromium + # CHROMIUM_PATH is automatically set by the setup-chromium action + - name: Run Unlighthouse Mobile Audit + working-directory: website + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" + PUPPETEER_EXECUTABLE_PATH: ${{ env.CHROMIUM_PATH }} + run: | + npx --yes @unlighthouse/cli@latest --build-static --mobile --output-path ./.unlighthouse/mobile + + - name: Run Unlighthouse Desktop Audit + working-directory: website + env: + PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" + PUPPETEER_EXECUTABLE_PATH: ${{ env.CHROMIUM_PATH }} + run: | + npx --yes @unlighthouse/cli@latest --build-static --desktop --output-path ./.unlighthouse/desktop + + # 5. UPLOAD ARTIFACT + # This takes the generated report and saves it as a zip file. + # Note: Unlighthouse runs in website/ directory, so output is at website/.unlighthouse + # Includes both mobile and desktop reports + - name: Create SEO Report Zip + if: always() + run: | + cd website + zip -r seo-report.zip .unlighthouse/ || echo "Failed to create zip, but continuing..." + ls -lh seo-report.zip || echo "Zip file not created" + echo "Report includes:" + ls -la .unlighthouse/ 2>/dev/null || echo "No .unlighthouse directory" + + - name: Upload SEO Report + uses: actions/upload-artifact@v4 + if: always() # Upload even if previous step failed + with: + name: seo-report + path: website/seo-report.zip + if-no-files-found: warn # Warn instead of error if no files found + retention-days: 7 # Auto-delete after 7 days to save space \ No newline at end of file diff --git a/.github/workflows/seo.yml b/.github/workflows/seo.yml deleted file mode 100644 index 4f3ef68..0000000 --- a/.github/workflows/seo.yml +++ /dev/null @@ -1,114 +0,0 @@ -name: Quality & SEO Audit -on: - workflow_run: - workflows: ["Code Quality"] - types: - - completed - -jobs: - audit: - runs-on: ubuntu-latest - # Only run if the code-quality workflow succeeded - if: ${{ github.event.workflow_run.conclusion == 'success' }} - steps: - - uses: actions/checkout@v4 - with: - # Checkout the same commit that triggered the code-quality workflow - ref: ${{ github.event.workflow_run.head_branch }} - sha: ${{ github.event.workflow_run.head_sha }} - - - uses: oven-sh/setup-bun@v2 - with: - bun-version: latest - - # Cache dependencies for faster builds - - uses: actions/cache@v4 - id: bun-cache - with: - path: ~/.bun/install/cache - key: ${{ runner.os }}-bun-${{ hashFiles('website/bun.lock') }} - restore-keys: | - ${{ runner.os }}-bun- - - - uses: actions/cache@v4 - id: node-modules-cache - with: - path: website/node_modules - key: ${{ runner.os }}-node-modules-${{ hashFiles('website/package.json') }} - restore-keys: | - ${{ runner.os }}-node-modules- - - # Install Chromium for Puppeteer (required by Unlighthouse) - # This action sets CHROMIUM_PATH environment variable automatically - - name: Setup Chromium - uses: browser-actions/setup-chromium@v1 - with: - chromium-version: latest - - # 1. Build and Start Server - # NOTE: Astro outputs to 'dist' directory by default - # Set SITE_BASE_URL to localhost for CI so all links point to localhost instead of production - - name: Install Dependencies & Build - working-directory: website - env: - SITE_BASE_URL: "http://localhost:3000" - run: | - bun install --frozen-lockfile - bun run build - - # 2. Start Static Server (Astro outputs to 'dist' directory) - - name: Start Static Server - working-directory: website - run: | - npx --yes serve@latest dist -p 3000 & - npx wait-on http://localhost:3000 --timeout 60000 || (echo "Server failed to start" && exit 1) - - # 3. FAIL FAST: Broken Link Checker - # Only check links on localhost:3000, skip external links (e.g., https://www.quantus.com) - - name: Check for Broken Links - run: | - npx --yes linkinator http://localhost:3000 --recurse --skip "^(?!http://localhost:3000)" - - # 4. DEEP AUDIT: Unlighthouse - # Scans all pages for both desktop and mobile devices - # Fails if SEO score is below 100 (configured in unlighthouse.config.ts) - # The '--build-static' flag generates the HTML report files. - # PUPPETEER_SKIP_CHROMIUM_DOWNLOAD tells Puppeteer to use the system Chromium from setup-chromium - # CHROMIUM_PATH is automatically set by the setup-chromium action - - name: Run Unlighthouse Mobile Audit - working-directory: website - env: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" - PUPPETEER_EXECUTABLE_PATH: ${{ env.CHROMIUM_PATH }} - run: | - npx --yes @unlighthouse/cli@latest --build-static --mobile --output-path ./.unlighthouse/mobile - - - name: Run Unlighthouse Desktop Audit - working-directory: website - env: - PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: "true" - PUPPETEER_EXECUTABLE_PATH: ${{ env.CHROMIUM_PATH }} - run: | - npx --yes @unlighthouse/cli@latest --build-static --desktop --output-path ./.unlighthouse/desktop - - # 5. UPLOAD ARTIFACT - # This takes the generated report and saves it as a zip file. - # Note: Unlighthouse runs in website/ directory, so output is at website/.unlighthouse - # Includes both mobile and desktop reports - - name: Create SEO Report Zip - if: always() - run: | - cd website - zip -r seo-report.zip .unlighthouse/ || echo "Failed to create zip, but continuing..." - ls -lh seo-report.zip || echo "Zip file not created" - echo "Report includes:" - ls -la .unlighthouse/ 2>/dev/null || echo "No .unlighthouse directory" - - - name: Upload SEO Report - uses: actions/upload-artifact@v4 - if: always() # Upload even if previous step failed - with: - name: seo-report - path: website/seo-report.zip - if-no-files-found: warn # Warn instead of error if no files found - retention-days: 7 # Auto-delete after 7 days to save space