diff --git a/.github/workflows/validation.yaml b/.github/workflows/validation.yaml index 7bb00098e..05ff72801 100644 --- a/.github/workflows/validation.yaml +++ b/.github/workflows/validation.yaml @@ -48,3 +48,43 @@ jobs: - name: Run documentation build check run: npm run docs:check + + audit-dependencies: + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v6 + + # Advisory only; needs no install (npm audit reads package-lock.json). + # See CONTRIBUTING.md ("Dependency audit"). + # + # `set -o pipefail` is load-bearing: without it `tee` returns 0 and the + # summary below claims a clean tree over a report full of findings. + - name: Audit production dependencies + id: audit + continue-on-error: true + run: | + set -o pipefail + npm audit --omit=dev --audit-level=high | tee "${RUNNER_TEMP}/audit.log" + + # `outcome` is the result before `continue-on-error` absorbs it; + # `conclusion` is always `success` here. + - name: Publish audit report + env: + AUDIT_OUTCOME: ${{ steps.audit.outcome }} + run: | + { + echo '## Production dependency audit' + echo + if [ "${AUDIT_OUTCOME}" = 'success' ]; then + echo 'No high or critical advisories in the production dependency tree.' + else + echo 'npm audit reported high or critical advisories, or could not run.' + echo 'This check is advisory and does not block merging.' + fi + echo + echo '```' + cat "${RUNNER_TEMP}/audit.log" + echo '```' + } >> "${GITHUB_STEP_SUMMARY}" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0a4fc9ece..caa50399d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -53,6 +53,21 @@ To maintain high code quality and consistency: The project uses `husky` and `lint-staged` to automatically lint and format your changes before each commit. +### Dependency audit + +The `validation` workflow runs `npm audit --omit=dev --audit-level=high` in an +`audit-dependencies` job and writes the report to the run summary. `--omit=dev` +restricts it to the dependencies we publish. + +The job is advisory: it reports a finding, and it does not fail the build. +`npm audit` cannot acknowledge a finding, so a blocking gate would fail every +open pull request as soon as a new advisory is published against a dependency +we already ship. Fix a finding in its own pull request with `npm audit fix`, or +open an issue when the only fix is a major version bump. + +Once the tree is clean at `high`, drop `continue-on-error` from the audit step +so the check starts to block. + ### Sign our Contributor License Agreement Contributions to this project must be accompanied by a