chore(release): deploy version v0.7.119 #9065
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Test and Report | |
| on: | |
| push: | |
| branches: ["main"] | |
| pull_request: | |
| branches: ["main"] | |
| # All jobs declare their required permissions explicitly. | |
| permissions: {} | |
| jobs: | |
| prepare: | |
| runs-on: ubuntu-26.04 | |
| # Only needs read permissions | |
| permissions: | |
| contents: read # Required to check out code | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Run TypeScript check (source) | |
| run: npm run check | |
| - name: Run TypeScript check (tests) | |
| run: npm run check:test | |
| - name: Run ESLint | |
| run: npm run lint | |
| build-validation: | |
| needs: prepare | |
| runs-on: ubuntu-26.04 | |
| # Checkout is the only repository-token operation in this job. | |
| permissions: | |
| contents: read # Required to check out code | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Cache Vite build cache | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: node_modules/.vite | |
| key: v2-${{ runner.os }}-vite-${{ hashFiles('**/package-lock.json') }} | |
| restore-keys: | | |
| v2-${{ runner.os }}-vite- | |
| - name: Build application | |
| run: npm run build | |
| - name: Upload build artifacts | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: build-output | |
| path: dist | |
| if-no-files-found: error | |
| unit-tests: | |
| needs: [prepare, build-validation] | |
| runs-on: ubuntu-26.04 | |
| # Checkout is the only repository-token operation in this job. | |
| permissions: | |
| contents: read # Required to check out code | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: "npm" | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Run unit tests with coverage | |
| run: npm run coverage | |
| env: | |
| JEST_JUNIT_OUTPUT_DIR: "build/coverage" | |
| JEST_JUNIT_OUTPUT_NAME: "junit.xml" | |
| e2e-tests: | |
| needs: [prepare, build-validation] | |
| runs-on: ubuntu-26.04 | |
| # Use Cypress's official browsers image: ships Node + Chrome + Firefox + Edge + Xvfb | |
| # + all GTK/NSS/font system libs preinstalled, removing the need for a custom | |
| # apt-get + Google Chrome bootstrap step. Node is then normalised to the version | |
| # in .nvmrc via actions/setup-node below. | |
| container: | |
| # Use cypress/browsers:latest β this keeps Chrome/Firefox/Edge/Xvfb on a | |
| # rolling release, and `actions/setup-node` below normalises Node to the | |
| # major pinned in .nvmrc (currently 26). We deliberately accept the | |
| # rolling browser version over digest-pinning because .nvmrc is a Node | |
| # major (26), not a patch, so attempting to also pin the container's Node | |
| # patch would just be silently overridden by setup-node and create a | |
| # misleading impression of full reproducibility. | |
| image: cypress/browsers:latest | |
| # Run as root so actions/setup-node cache writes and Cypress binary cache | |
| # writes work without permission issues. The cypress/browsers image's | |
| # default USER is non-root. | |
| options: --user root | |
| # Checkout is the only repository-token operation in this job. | |
| permissions: | |
| contents: read # Required to check out code | |
| env: | |
| CYPRESS_VIDEO: true | |
| # Suppress X11 keyboard configuration warnings | |
| XKB_DEFAULT_RULES: evdev | |
| XKB_DEFAULT_MODEL: pc105 | |
| XKB_DEFAULT_LAYOUT: us | |
| steps: | |
| # NOTE: step-security/harden-runner does not support container jobs, so it | |
| # is intentionally omitted here. Egress hardening for E2E browser traffic | |
| # would block legitimate test traffic anyway. | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: "npm" | |
| - name: Print browser versions | |
| run: | | |
| echo "Node: $(node --version)" | |
| google-chrome --version || true | |
| # cypress/browsers ships Xvfb (used by Cypress's bundled @cypress/xvfb). | |
| command -v Xvfb >/dev/null 2>&1 && echo "Xvfb available" || echo "Xvfb missing" | |
| - name: Cache Cypress binary | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: ~/.cache/Cypress | |
| key: v2-cypress-${{ runner.os }}-${{ hashFiles('package-lock.json') }} | |
| restore-keys: | | |
| v2-cypress-${{ runner.os }}- | |
| - name: Install dependencies | |
| run: npm ci | |
| - name: Verify Cypress | |
| run: npx cypress verify | |
| - name: Start app and run Cypress tests with Three.js optimization | |
| run: | | |
| echo "π Starting Three.js E2E test execution at $(date +%T)" | |
| echo "π Configuration:" | |
| echo " - Chrome: $(google-chrome --version)" | |
| echo " - Node: $(node --version) (memory: 4GB heap)" | |
| echo " - Display: $DISPLAY" | |
| echo " - Target: 10-12 minute execution" | |
| echo "" | |
| START_TIME=$(date +%s) || START_TIME=0 | |
| # cypress/browsers image ships Xvfb but NOT xauth, so the xvfb-run | |
| # wrapper fails with "xauth command not found". Cypress's bundled | |
| # @cypress/xvfb spawns Xvfb directly (no xauth needed) when DISPLAY | |
| # is unset, so we just call npm run test:e2e and let Cypress manage it. | |
| NODE_OPTIONS="--max-old-space-size=4096" npm run test:e2e || TEST_EXIT_CODE=$? | |
| END_TIME=$(date +%s) || END_TIME=$START_TIME | |
| if [ "$START_TIME" -ne 0 ]; then | |
| DURATION=$((END_TIME - START_TIME)) | |
| echo "β E2E tests completed in ${DURATION} seconds" | |
| echo "e2e_duration=${DURATION}" >> $GITHUB_OUTPUT | |
| else | |
| echo "β οΈ Could not measure test duration" | |
| fi | |
| # Exit with test exit code (0 if tests passed) | |
| exit ${TEST_EXIT_CODE:-0} | |
| env: | |
| CYPRESS_VIDEO: true | |
| TERM: dumb | |
| id: e2e_tests | |
| - name: Upload Cypress results | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: cypress-results | |
| path: | | |
| cypress/videos | |
| cypress/screenshots | |
| cypress/results | |
| - name: Report E2E execution time | |
| if: always() | |
| run: | | |
| if [ -n "${{ steps.e2e_tests.outputs.e2e_duration }}" ]; then | |
| echo "π E2E Test Execution Metrics" | |
| echo "================================" | |
| echo "Total Duration: ${{ steps.e2e_tests.outputs.e2e_duration }} seconds" | |
| echo "Previous baseline: 1500-1800 seconds (25-30 minutes)" | |
| echo "Current target: 900-1200 seconds (15-20 minutes)" | |
| echo "Final goal: 600-720 seconds (10-12 minutes)" | |
| DURATION=${{ steps.e2e_tests.outputs.e2e_duration }} | |
| if [ $DURATION -le 720 ]; then | |
| echo "π― EXCELLENT: Test execution at final goal (β€12 minutes)" | |
| elif [ $DURATION -le 1200 ]; then | |
| echo "β GOOD: Test execution within current target (β€20 minutes)" | |
| elif [ $DURATION -le 1800 ]; then | |
| echo "β οΈ NEEDS IMPROVEMENT: Test execution above target but below baseline (20-30 minutes)" | |
| else | |
| echo "β REGRESSION: Test execution above baseline (>30 minutes)" | |
| fi | |
| # Calculate improvement from baseline (assume 27 min = 1620 sec average) | |
| BASELINE=1620 | |
| IMPROVEMENT=$((BASELINE - DURATION)) | |
| PERCENT=$((IMPROVEMENT * 100 / BASELINE)) | |
| if [ $IMPROVEMENT -gt 0 ]; then | |
| echo "π Improvement: ${IMPROVEMENT} seconds (${PERCENT}% faster than baseline)" | |
| else | |
| REGRESSION=$((DURATION - BASELINE)) | |
| PERCENT=$((REGRESSION * 100 / BASELINE)) | |
| echo "π Regression: ${REGRESSION} seconds (${PERCENT}% slower than baseline)" | |
| fi | |
| fi | |
| report: | |
| needs: [unit-tests, e2e-tests] | |
| runs-on: ubuntu-26.04 | |
| if: always() | |
| # Checkout is the only repository-token operation in this job. | |
| permissions: | |
| contents: read # Required to check out code | |
| steps: | |
| - name: Harden the runner (Audit all outbound calls) | |
| uses: step-security/harden-runner@e14015d583714f6e62063499dc959a02595150a1 # v2.21.1 | |
| with: | |
| egress-policy: audit | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version-file: '.nvmrc' | |
| cache: "npm" | |
| - name: Cache APT packages | |
| uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 | |
| with: | |
| path: /var/cache/apt/archives | |
| key: v2-${{ runner.os }}-apt-graphviz-${{ hashFiles('.github/workflows/test-and-report.yml') }} | |
| restore-keys: | | |
| v2-${{ runner.os }}-apt-graphviz- | |
| - name: Install graphviz for reports | |
| timeout-minutes: 5 | |
| run: sudo DEBIAN_FRONTEND=noninteractive apt-get update -qq && sudo DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends graphviz | |
| - name: Install dependencies | |
| run: npm install | |
| - name: Download all artifacts | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 | |
| with: | |
| path: artifacts | |
| - name: Generate test reliability report | |
| continue-on-error: true | |
| run: | | |
| # Copy Cypress results for analysis | |
| if [ -d "artifacts/cypress-results" ]; then | |
| mkdir -p build/cypress/mochawesome | |
| find artifacts/cypress-results -name "*.json" -exec cp {} build/cypress/mochawesome/ \; | |
| fi | |
| # Generate reliability report | |
| npm run test:reliability || echo "No test results to analyze" | |
| - name: Upload combined reports | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: test-reports | |
| path: | | |
| coverage | |
| artifacts/cypress-results | |
| build/reports/test-reliability-report.html |