Bump immutable from 5.1.5 to 5.1.9 in /frontend #155
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
| # ============================================================================= | |
| # CycloneDX Assessors Studio - CI Pipeline | |
| # ============================================================================= | |
| # Security hardening: | |
| # - All actions pinned to full commit SHAs (not tags) | |
| # - Top-level permissions deny-all; each job grants minimum needed | |
| # - persist-credentials: false on every checkout | |
| # - npm ci with frozen lockfile (no mutation) | |
| # - No use of pull_request_target | |
| # - No secret exposure to PR builds | |
| # ============================================================================= | |
| name: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| branches: [main] | |
| types: [opened, synchronize, reopened] | |
| workflow_dispatch: | |
| # Deny all permissions by default. Each job opts in to exactly what it needs. | |
| permissions: {} | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Backend | |
| # --------------------------------------------------------------------------- | |
| backend-build: | |
| name: "Backend / Build & Typecheck" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read # checkout only | |
| defaults: | |
| run: | |
| working-directory: backend | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| cache-dependency-path: backend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| env: | |
| NODE_ENV: development | |
| # argon2 requires a native build step; run it explicitly after npm ci | |
| - name: Rebuild native modules | |
| run: npm rebuild argon2 | |
| - name: Typecheck | |
| run: npx tsc --noEmit | |
| - name: Lint (if configured) | |
| run: | | |
| if [ -f .eslintrc.js ] || [ -f .eslintrc.json ] || [ -f .eslintrc.yml ] || [ -f eslint.config.js ] || [ -f eslint.config.mjs ]; then | |
| npx eslint . | |
| else | |
| echo "No ESLint config found, skipping" | |
| fi | |
| backend-test: | |
| name: "Backend / Test" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| needs: backend-build | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: backend | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| cache-dependency-path: backend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Rebuild native modules | |
| run: npm rebuild argon2 | |
| - name: Run tests with coverage | |
| run: npx vitest run --reporter=verbose --coverage | |
| env: | |
| DATABASE_PROVIDER: pglite | |
| PGLITE_DATA_DIR: ./data/test-pglite | |
| JWT_SECRET: ci-testing-secret-that-is-at-least-32-characters-long | |
| PORT: "3001" | |
| LOG_LEVEL: error | |
| CORS_ORIGIN: http://localhost:5173 | |
| - name: Upload backend coverage | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: backend-coverage | |
| path: backend/coverage/lcov.info | |
| retention-days: 5 | |
| if-no-files-found: warn | |
| # --------------------------------------------------------------------------- | |
| # Frontend | |
| # --------------------------------------------------------------------------- | |
| frontend-build: | |
| name: "Frontend / Build & Typecheck" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| env: | |
| NODE_ENV: development | |
| - name: Typecheck | |
| run: npx vue-tsc -b | |
| - name: Lint (if configured) | |
| run: | | |
| if [ -f .eslintrc.js ] || [ -f .eslintrc.json ] || [ -f .eslintrc.yml ] || [ -f eslint.config.js ] || [ -f eslint.config.mjs ]; then | |
| npx eslint . | |
| else | |
| echo "No ESLint config found, skipping" | |
| fi | |
| - name: Production build | |
| run: npx vite build | |
| - name: Upload build artifact | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: frontend-dist | |
| path: frontend/dist/ | |
| retention-days: 5 | |
| if-no-files-found: error | |
| frontend-test: | |
| name: "Frontend / Test" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| needs: frontend-build | |
| permissions: | |
| contents: read | |
| defaults: | |
| run: | |
| working-directory: frontend | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| cache-dependency-path: frontend/package-lock.json | |
| - name: Install dependencies | |
| run: npm ci --ignore-scripts | |
| - name: Run tests with coverage | |
| run: npx vitest run --reporter=verbose --coverage.enabled --coverage.reporter=text --coverage.reporter=lcov --coverage.reportsDirectory=./coverage | |
| - name: Upload frontend coverage | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: frontend-coverage | |
| path: frontend/coverage/lcov.info | |
| retention-days: 5 | |
| if-no-files-found: warn | |
| # --------------------------------------------------------------------------- | |
| # E2E (Playwright) — gated behind a green backend AND frontend build+test. | |
| # Boots backend (PGlite) and frontend (vite dev) in-process, walks the | |
| # setup wizard, seeds demo data, captures per-role storage states, and | |
| # runs the Playwright suite on chromium. Smoke-tagged subset also runs | |
| # on firefox/webkit. See tests/e2e/PLAN.md for the multi-phase plan. | |
| # --------------------------------------------------------------------------- | |
| e2e: | |
| name: "E2E / Playwright" | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| needs: [backend-build, backend-test, frontend-build, frontend-test] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Setup Node | |
| uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0 | |
| with: | |
| node-version-file: .node-version | |
| cache: npm | |
| - name: Install backend dependencies | |
| working-directory: backend | |
| run: npm ci --ignore-scripts | |
| env: | |
| NODE_ENV: development | |
| - name: Rebuild backend native modules | |
| working-directory: backend | |
| run: npm rebuild argon2 | |
| - name: Install frontend dependencies | |
| working-directory: frontend | |
| run: npm ci --ignore-scripts | |
| env: | |
| NODE_ENV: development | |
| - name: Install e2e dependencies | |
| working-directory: tests/e2e | |
| run: npm ci --ignore-scripts | |
| # Cache the Playwright browser binaries by Playwright version so | |
| # that recurring CI runs do not re-download ~300 MB of WebKit and | |
| # Firefox bundles on every commit. | |
| - name: Get Playwright version | |
| id: pw-version | |
| working-directory: tests/e2e | |
| run: | | |
| PW_VERSION=$(node -p "require('@playwright/test/package.json').version") | |
| echo "version=$PW_VERSION" >> "$GITHUB_OUTPUT" | |
| - name: Cache Playwright browsers | |
| id: pw-cache | |
| uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 | |
| with: | |
| path: ~/.cache/ms-playwright | |
| key: playwright-${{ runner.os }}-${{ steps.pw-version.outputs.version }} | |
| - name: Install Playwright browsers and OS deps | |
| working-directory: tests/e2e | |
| # `--with-deps` ensures Ubuntu pulls the libs Chromium/WebKit need. | |
| # When the cache hit, only the OS deps step runs (fast). | |
| run: | | |
| if [ "${{ steps.pw-cache.outputs.cache-hit }}" != 'true' ]; then | |
| npx playwright install --with-deps chromium firefox webkit | |
| else | |
| npx playwright install-deps chromium firefox webkit | |
| fi | |
| - name: Typecheck e2e | |
| working-directory: tests/e2e | |
| run: npx tsc --noEmit | |
| - name: Run Playwright suite | |
| working-directory: tests/e2e | |
| env: | |
| CI: 'true' | |
| # PGlite is the embedded provider; tests run against a fresh | |
| # data directory under tests/e2e/data so each CI run starts | |
| # from a known-empty state. | |
| E2E_PGLITE_DIR: ./data/pglite-e2e | |
| run: npx playwright test | |
| - name: Upload Playwright HTML report | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: playwright-report | |
| path: tests/e2e/playwright-report | |
| retention-days: 7 | |
| if-no-files-found: warn | |
| - name: Upload traces and screenshots on failure | |
| if: failure() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 | |
| with: | |
| name: playwright-traces | |
| path: tests/e2e/test-results | |
| retention-days: 7 | |
| if-no-files-found: warn | |
| # --------------------------------------------------------------------------- | |
| # Codacy coverage (main branch only) - upload coverage from test jobs | |
| # --------------------------------------------------------------------------- | |
| codacy-coverage: | |
| name: "Codacy / Upload Coverage" | |
| if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| needs: [backend-test, frontend-test] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Download backend coverage | |
| uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 | |
| with: | |
| name: backend-coverage | |
| path: backend-coverage | |
| - name: Download frontend coverage | |
| uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 | |
| with: | |
| name: frontend-coverage | |
| path: frontend-coverage | |
| continue-on-error: true | |
| - name: Resolve coverage report paths | |
| id: coverage-paths | |
| run: | | |
| REPORTS="" | |
| if [ -f backend-coverage/lcov.info ]; then | |
| REPORTS="backend-coverage/lcov.info" | |
| fi | |
| if [ -f frontend-coverage/lcov.info ]; then | |
| if [ -n "$REPORTS" ]; then | |
| REPORTS="$REPORTS,frontend-coverage/lcov.info" | |
| else | |
| REPORTS="frontend-coverage/lcov.info" | |
| fi | |
| fi | |
| echo "reports=$REPORTS" >> "$GITHUB_OUTPUT" | |
| - name: Upload coverage to Codacy | |
| if: steps.coverage-paths.outputs.reports != '' | |
| uses: codacy/codacy-coverage-reporter-action@89d6c85cfafaec52c72b6c5e8b2878d33104c699 # v1.3.0 | |
| with: | |
| project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} | |
| coverage-reports: ${{ steps.coverage-paths.outputs.reports }} | |
| # --------------------------------------------------------------------------- | |
| # Dependency review (PR only) - block PRs that introduce known vulns | |
| # --------------------------------------------------------------------------- | |
| dependency-review: | |
| name: "Dependency Review" | |
| if: github.event_name == 'pull_request' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 5 | |
| permissions: | |
| contents: read | |
| pull-requests: write # post review comments | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Dependency Review | |
| uses: actions/dependency-review-action@2031cfc080254a8a887f58cffee85186f0e49e48 # v4.9.0 | |
| with: | |
| fail-on-severity: moderate | |
| deny-licenses: AGPL-3.0, GPL-3.0 | |
| comment-summary-in-pr: always | |
| # --------------------------------------------------------------------------- | |
| # Docker snapshot (main branch only) - build and push snapshot image | |
| # | |
| # Publishes a single image that serves both the Vue 3 SPA and the | |
| # JSON API on the same origin: | |
| # cyclonedx/cyclonedx-assessors-studio:snapshot | |
| # --------------------------------------------------------------------------- | |
| docker: | |
| name: "Docker / Snapshot" | |
| if: (github.event_name == 'push' || github.event_name == 'workflow_dispatch') && github.ref == 'refs/heads/main' | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 30 | |
| # Snapshot images may only be pushed once the full pipeline is green, | |
| # including E2E. Add e2e to the gate so a broken UI flow cannot be | |
| # published to Docker Hub. | |
| needs: [backend-test, frontend-test, e2e] | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| persist-credentials: false | |
| - name: Set up QEMU | |
| uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4.1.0 | |
| with: | |
| username: ${{ secrets.DOCKERHUB_USERNAME }} | |
| password: ${{ secrets.DOCKERHUB_TOKEN }} | |
| - name: Build and push snapshot image | |
| uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7.1.0 | |
| with: | |
| context: . | |
| file: deploy/docker/Dockerfile | |
| platforms: linux/amd64,linux/arm64 | |
| push: true | |
| tags: cyclonedx/cyclonedx-assessors-studio:snapshot | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max |