diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 69cda01..09bddff 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -55,12 +55,6 @@ jobs: echo "::error::npm audit signatures failed after 3 attempts" exit 1 - - name: 'Lint' - run: npm run lint:check - - - name: 'Format' - run: npm run format:check - - name: 'Build' run: npm run build @@ -74,6 +68,58 @@ jobs: path: '*.tgz' if-no-files-found: 'error' + sca: + runs-on: 'ubuntu-latest' + timeout-minutes: 10 + permissions: + contents: 'read' # to check out the repository + steps: + - name: 'Checkout' + uses: actions/checkout@v6.0.3 + # Full history so the diff base commit is available locally. + with: { fetch-depth: '0', ref: '${{ github.event.pull_request.head.sha }}' } + + - name: 'Setup Node.js' + uses: actions/setup-node@v6.4.0 + with: { node-version-file: '.nvmrc', cache: 'npm' } + + - name: 'Install' + run: npm ci --no-fund --no-audit + + - name: 'Resolve diff range' + id: 'range' + # Only lint files that changed in this PR (or push), mirroring the local + # pre-commit hook instead of re-checking the whole tree. + run: | + if [ "${{ github.event_name }}" = 'pull_request' ]; then + base='${{ github.event.pull_request.base.ref }}' + git fetch --no-tags origin "+refs/heads/${base}:refs/remotes/origin/${base}" + echo "value=origin/${base}...HEAD" >> "$GITHUB_OUTPUT" + else + before='${{ github.event.before }}' + if [ -z "$before" ] \ + || [ "$before" = '0000000000000000000000000000000000000000' ] \ + || ! git cat-file -e "${before}^{commit}" 2>/dev/null; then + before="$(git rev-parse HEAD^ 2>/dev/null || git rev-parse HEAD)" + fi + echo "value=${before}...HEAD" >> "$GITHUB_OUTPUT" + fi + + - name: 'Run lint-staged on changed files' + # lint-staged applies eslint/prettier fixes and stages them; it exits + # non-zero on unfixable lint errors. + run: npx lint-staged --diff="${{ steps.range.outputs.value }}" + + - name: 'Verify no fixes were required' + # If lint-staged staged any fix, the changed files were not properly + # linted/formatted before being committed. Surface the diff and fail. + run: | + if ! git diff --quiet HEAD; then + echo '::error::lint-staged applied fixes to changed files. Run "npx lint-staged" locally and commit the result.' + git --no-pager diff HEAD + exit 1 + fi + upload-coverage: needs: 'ci' runs-on: 'ubuntu-latest' @@ -194,7 +240,7 @@ jobs: run: docker compose down --volumes release: - needs: ['ci', 'smoke', 'e2e'] + needs: ['ci', 'sca', 'smoke', 'e2e'] runs-on: 'ubuntu-latest' # Only enter the protected release environment for real releases; pull # request dry runs run without it (its branch policy blocks PR refs).