docs(adr): π mark ADR 0007 as accepted (#5348) #7686
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
| # PR Checks Workflow | |
| # | |
| # Runs build, test, lint, and type-check in parallel for faster feedback. | |
| # Build runs first (required by all others), then test/lint/types fan out. | |
| # | |
| # Path filtering: | |
| # - code or tooling config -> full checks (build + test + lint + types) | |
| # - other non-code changes -> build + lint only | |
| # - manual dispatch -> full checks | |
| # | |
| # Addresses: https://github.com/equinor/design-system/issues/4624 | |
| name: Checks | |
| permissions: | |
| contents: read | |
| on: | |
| workflow_dispatch: | |
| pull_request: | |
| branches: | |
| - main | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} | |
| cancel-in-progress: true | |
| env: | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| NODE_VERSION: '24.16.0' | |
| CACHE_KEY: ${{ github.sha }}-checks | |
| jobs: | |
| # βββ Setup: checkout + install + cache βββββββββββββββββββββββββββ | |
| setup: | |
| uses: ./.github/workflows/_setup.yml | |
| secrets: inherit | |
| with: | |
| cacheKey: ${{ github.sha }}-checks | |
| # βββ Detect what changed to skip unnecessary jobs βββββββββββββββ | |
| changes: | |
| runs-on: ubuntu-latest | |
| # dorny/paths-filter fetches the PR's changed-file list via the REST API on | |
| # pull_request events, which needs pull-requests: read on top of the | |
| # workflow's contents: read. | |
| permissions: | |
| contents: read | |
| pull-requests: read | |
| outputs: | |
| # Manual runs are an explicit request for the complete suite. | |
| code: ${{ github.event_name == 'workflow_dispatch' || steps.filter.outputs.code == 'true' }} | |
| steps: | |
| # fetch-depth: 2 so dorny/paths-filter can diff against the previous | |
| # commit on push events (the default depth of 1 omits it). | |
| - uses: actions/checkout@v7 | |
| with: | |
| fetch-depth: 2 | |
| # SHA-pinned (v3.0.2) β third-party action running on every PR; pin to an | |
| # immutable commit so a compromised tag can't inject code into CI. | |
| - uses: dorny/paths-filter@ceb8a2b8f2d89434be7ff52d3de7ec3738c5cc9d # v4.0.3 | |
| if: github.event_name != 'workflow_dispatch' | |
| id: filter | |
| with: | |
| filters: | | |
| code: | |
| - 'packages/**' | |
| - 'apps/**' | |
| - 'scripts/**' | |
| - '.github/actions/**' | |
| # Root dependencies and tooling config warrant full checks. | |
| - '.npmrc' | |
| - '.node-version' | |
| - '.nvmrc' | |
| - '.prettier*' | |
| - '.stylelintrc*' | |
| - 'package.json' | |
| - 'pnpm-lock.yaml' | |
| - 'pnpm-workspace.yaml' | |
| - 'tsconfig*.json' | |
| - 'babel.config.cjs' | |
| - 'eslint.config.mjs' | |
| # βββ Build (required before test/lint/types) βββββββββββββββββββββ | |
| build: | |
| name: Build | |
| runs-on: ubuntu-latest | |
| needs: [setup, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - name: Restore workspace cache | |
| id: cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }} | |
| # Cache misses are rare (setup runs first and saves the workspace) but | |
| # not impossible β a cache-service hiccup, eviction, or size limit | |
| # shouldn't fail the run when a plain checkout + install can proceed. | |
| - name: Fallback checkout (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v7 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Fallback install (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: pnpm install --frozen-lockfile | |
| # Must run BEFORE the build: `prebuild` regenerates the index in the | |
| # workspace, which would mask a stale committed file. | |
| - name: Check AI component index freshness | |
| run: pnpm run generate:component-index --check | |
| - name: Build packages | |
| run: pnpm run build | |
| - name: Cache build output | |
| uses: actions/cache/save@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }}-built | |
| # βββ Test (parallel, depends on build) βββββββββββββββββββββββββββ | |
| test: | |
| name: Test | |
| runs-on: ubuntu-latest | |
| needs: [build, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - name: Restore build cache | |
| id: cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }}-built | |
| # On a build-cache miss, reconstruct from scratch (checkout + install + | |
| # build) rather than failing β the build job's output cache is not | |
| # guaranteed to survive a cache-service hiccup or eviction. | |
| - name: Fallback checkout (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v7 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Fallback build (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm install --frozen-lockfile | |
| pnpm run build | |
| - name: Test packages | |
| run: pnpm run test | |
| # βββ Lint (parallel, depends on build) βββββββββββββββββββββββββββ | |
| lint: | |
| name: Lint | |
| runs-on: ubuntu-latest | |
| needs: [build, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - name: Restore build cache | |
| id: cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }}-built | |
| # On a build-cache miss, reconstruct from scratch (checkout + install + | |
| # build) rather than failing β the build job's output cache is not | |
| # guaranteed to survive a cache-service hiccup or eviction. | |
| - name: Fallback checkout (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v7 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Fallback build (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm install --frozen-lockfile | |
| pnpm run build | |
| - name: Lint packages | |
| run: pnpm run lint:all | |
| # βββ Type check (parallel, depends on build) ββββββββββββββββββββ | |
| types: | |
| name: Type check | |
| runs-on: ubuntu-latest | |
| needs: [build, changes] | |
| if: needs.changes.outputs.code == 'true' | |
| steps: | |
| - name: Restore build cache | |
| id: cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }}-built | |
| # On a build-cache miss, reconstruct from scratch (checkout + install + | |
| # build) rather than failing β the build job's output cache is not | |
| # guaranteed to survive a cache-service hiccup or eviction. | |
| - name: Fallback checkout (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v7 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Fallback build (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: | | |
| pnpm install --frozen-lockfile | |
| pnpm run build | |
| - name: Type check packages | |
| run: pnpm run types | |
| # βββ Lint-only for non-code changes (workflows, docs) βββββββββββ | |
| # | |
| # Trade-off (decided 2026-06): this job runs a full `pnpm run build` | |
| # before linting because `lint:all` is type-aware and needs every | |
| # workspace package's built `.d.ts` to resolve cross-package imports. | |
| # So a docs/workflow-only PR still pays for a full build here. | |
| # | |
| # We deliberately did NOT add granular per-package affected detection | |
| # (e.g. pnpm `--filter "...[origin/main]"` or Turborepo) because CI is | |
| # currently fast enough and the existing binary `changes.code` gate + | |
| # cross-job `-built` cache already cover the common cases. Revisit only | |
| # if build time becomes a real bottleneck β Turborepo (input-hash | |
| # caching + affected filtering) is the preferred next step if so. | |
| lint-only: | |
| name: Lint (non-code changes) | |
| runs-on: ubuntu-latest | |
| needs: [setup, changes] | |
| if: needs.changes.outputs.code != 'true' | |
| steps: | |
| - name: Restore workspace cache | |
| id: cache | |
| uses: actions/cache/restore@v6 | |
| with: | |
| path: | | |
| ./* | |
| ~/.pnpm-store | |
| key: ${{ env.CACHE_KEY }} | |
| # Cache misses are rare (setup runs first and saves the workspace) but | |
| # not impossible β a cache-service hiccup, eviction, or size limit | |
| # shouldn't fail the run when a plain checkout + install can proceed. | |
| - name: Fallback checkout (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| uses: actions/checkout@v7 | |
| - name: Install Node.js | |
| uses: actions/setup-node@v7 | |
| with: | |
| node-version: ${{ env.NODE_VERSION }} | |
| package-manager-cache: false | |
| - name: Setup pnpm | |
| uses: pnpm/action-setup@v6 | |
| - name: Fallback install (cache miss) | |
| if: steps.cache.outputs.cache-hit != 'true' | |
| run: pnpm install --frozen-lockfile | |
| # lint:all runs type-aware ESLint across the whole monorepo, which | |
| # needs each workspace package's built type declarations. Without a | |
| # build, cross-package imports resolve to `any`/error and trip | |
| # no-unsafe-* / no-redundant-type-constituents. Build first. | |
| - name: Build packages | |
| run: pnpm run build | |
| - name: Lint packages | |
| run: pnpm run lint:all | |
| # βββ Status check (single gate for branch protection) βββββββββββ | |
| checks-passed: | |
| name: All checks passed | |
| runs-on: ubuntu-latest | |
| if: always() | |
| needs: [setup, changes, build, test, lint, types, lint-only] | |
| steps: | |
| - name: Evaluate results | |
| run: | | |
| # Each needs.<job>.result must be expanded as a static expression: | |
| # template expressions are evaluated at render time, before bash runs, | |
| # so a bash loop variable cannot index the needs context. | |
| # A "skipped" result is expected (path filtering) and is not a failure. | |
| for result in \ | |
| "setup:${{ needs.setup.result }}" \ | |
| "changes:${{ needs.changes.result }}" \ | |
| "build:${{ needs.build.result }}" \ | |
| "test:${{ needs.test.result }}" \ | |
| "lint:${{ needs.lint.result }}" \ | |
| "types:${{ needs.types.result }}" \ | |
| "lint-only:${{ needs.lint-only.result }}"; do | |
| job="${result%%:*}" | |
| status="${result#*:}" | |
| if [ "$status" = "failure" ] || [ "$status" = "cancelled" ]; then | |
| echo "::error::Job '$job' $status" | |
| exit 1 | |
| fi | |
| done | |
| echo "All checks passed β " | |
| - name: log-errors-to-slack | |
| if: failure() | |
| uses: act10ns/slack@v2 | |
| with: | |
| status: ${{ job.status }} |