deps: bump tsx from 4.23.1 to 4.23.12 #355
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: CI | |
| on: | |
| push: | |
| branches: [main] | |
| pull_request: | |
| permissions: | |
| contents: read | |
| # Cancel superseded runs on the same ref so rapid pushes don't pile up matrices. | |
| concurrency: | |
| group: ci-${{ github.ref }} | |
| cancel-in-progress: true | |
| jobs: | |
| build-test: | |
| name: build + test (node ${{ matrix.node }}) | |
| runs-on: ubuntu-latest | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| # 24 because that is what the Action declares (`using: node24`) and what | |
| # GitHub already runs every action on. 20 stays because every package | |
| # declares `engines: node >=20`; drop it here only when that drops too. | |
| node: ["20", "22", "24"] | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: ${{ matrix.node }} | |
| cache: npm | |
| - run: npm ci | |
| - name: Type-check + build (project references) | |
| run: npm run build | |
| - name: Test (node:test across all packages) | |
| run: npm test | |
| # Advisory: warns (never fails) when the quarterly PQC standards review is | |
| # due. The hard gate is the drift test in `npm test` above. | |
| - name: PQC standards-currency cadence check (advisory) | |
| run: npm run standards:check | |
| lint: | |
| name: lint + format (node 20) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| # ESLint's type-aware rules (no-floating-promises etc.) need the project | |
| # built so the TS program resolves the cross-package references. | |
| - name: Build (for type-aware lint) | |
| run: npm run build | |
| - name: Lint (eslint flat config) | |
| run: npm run lint | |
| - name: Format check (prettier) | |
| run: npm run format:check | |
| - name: Public API surface is frozen (no undocumented drift) | |
| run: npm run api:check | |
| coverage: | |
| name: coverage (node 22, advisory) | |
| runs-on: ubuntu-latest | |
| # Non-gating: Node's --experimental-test-coverage is informational for now. | |
| # Pinned to Node 22 — `npm run test:coverage` needs native root-glob | |
| # expansion (Node 21+) and Node 20's coverage reporter crashes on the | |
| # cross-package dist source maps. See the //test:coverage note in package.json. | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "22" | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run build | |
| - name: Test with coverage (node built-in) | |
| run: npm run test:coverage | |
| dogfood: | |
| name: qScan self-scan (dogfood) | |
| runs-on: ubuntu-latest | |
| needs: build-test | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run build | |
| # Exercise the CLI on our own tree. qScan matches the crypto PATTERNS in | |
| # the detectors' own source, so exit 1 (findings) is expected — but a | |
| # crash (exit > 1) or no output is a real failure we DO want to catch. | |
| - name: Self-scan runs cleanly (findings OK, crash not OK) | |
| run: | | |
| code=0 | |
| node packages/qscan/dist/cli.js packages --format sarif -o /tmp/dogfood.sarif.json || code=$? | |
| if [ "$code" -gt 1 ]; then echo "::error::qScan crashed (exit $code)"; exit 1; fi | |
| test -s /tmp/dogfood.sarif.json || { echo "::error::qScan produced no output"; exit 1; } | |
| node scripts/validate-sarif.mjs /tmp/dogfood.sarif.json | |
| bench: | |
| name: scan benchmark (node 20, advisory) | |
| runs-on: ubuntu-latest | |
| needs: build-test | |
| # Advisory: timings are noisy on shared CI runners, so this never gates. | |
| continue-on-error: true | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run build | |
| - name: Benchmark (serial vs parallel scan) | |
| run: npm run bench | |
| sarif: | |
| name: SARIF structural validation (node 20) | |
| runs-on: ubuntu-latest | |
| needs: build-test | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| - run: npm run build | |
| - name: Produce a SARIF report (self-scan) | |
| # The self-scan finds the crypto patterns in our own detector sources, so | |
| # qScan exits 1 (findings) — that is expected here; we only need the file | |
| # written. `|| true` keeps the step green; validation is the real gate. | |
| run: node packages/qscan/dist/cli.js packages --format sarif -o /tmp/q.sarif.json || true | |
| - name: Validate the SARIF 2.1.0 structure | |
| run: node scripts/validate-sarif.mjs /tmp/q.sarif.json | |
| action-bundle: | |
| name: action dist is fresh | |
| runs-on: ubuntu-latest | |
| # Guards against shipping a stale action: the action runs the committed | |
| # packages/action/dist/index.js, so if someone edits the source | |
| # and forgets to re-bundle, `uses: …@v1` would silently run old code. | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| - name: Build (workspace deps the bundle resolves) | |
| run: npm run build | |
| - name: Re-bundle the action | |
| run: npm run bundle --workspace @quantakrypto/action | |
| - name: Fail if the committed dist/ is out of date | |
| run: | | |
| if ! git diff --exit-code -- packages/action/dist; then | |
| echo "::error::packages/action/dist is stale. Run 'npm run build && npm run bundle -w @quantakrypto/action' and commit the result." | |
| exit 1 | |
| fi | |
| action-smoke: | |
| name: action smoke-test (uses:) | |
| runs-on: ubuntu-latest | |
| needs: build-test | |
| # Runs the bundled action the way a consumer does (uses: a local path | |
| # resolves the same entrypoint as uses: quantakrypto/pqc-tools/...@v1), | |
| # so a runtime break in the action is caught here instead of in the wild. | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - name: Fixture with quantum-vulnerable crypto | |
| run: | | |
| mkdir -p smoke | |
| printf 'const c=require("crypto");\nconst kp=c.generateKeyPairSync("rsa",{modulusLength:2048});\n' > smoke/sample.js | |
| - name: Run the action (report-only) | |
| id: scan | |
| uses: ./packages/action | |
| with: | |
| path: smoke | |
| fail-on-findings: "false" | |
| format: sarif | |
| output: smoke.sarif.json | |
| - name: Assert it scanned, reported, and set outputs | |
| run: | | |
| test -f smoke.sarif.json || { echo "::error::action wrote no SARIF report"; exit 1; } | |
| echo "findings-count=${{ steps.scan.outputs.findings-count }} readiness-score=${{ steps.scan.outputs.readiness-score }}" | |
| test "${{ steps.scan.outputs.findings-count }}" -ge 1 || { echo "::error::expected >=1 finding on the RSA fixture"; exit 1; } | |
| test -n "${{ steps.scan.outputs.readiness-score }}" || { echo "::error::readiness-score output not set"; exit 1; } | |
| reproducible: | |
| name: reproducible build (deterministic pack) | |
| runs-on: ubuntu-latest | |
| needs: build-test | |
| # Supply-chain assurance: the tarball we publish must be re-creatable byte for | |
| # byte from source, so anyone can audit that npm serves exactly what's in git. | |
| # This gate is network-free — it packs each workspace, perturbs the one known | |
| # nondeterminism source (bin file mode), re-normalizes, and asserts the SHA-512 | |
| # integrity is unchanged. Release-time `npm run repro:npm` additionally diffs | |
| # against the registry (needs a published version + network). | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| cache: npm | |
| - run: npm ci | |
| - name: Build (postbuild pins bin modes) | |
| run: npm run build | |
| - name: Verify deterministic pack | |
| run: npm run repro:check | |
| supply-chain: | |
| name: supply-chain invariants (zero-dep + pins + REUSE) | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| - uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0 | |
| with: | |
| node-version: "20" | |
| - name: Enforce zero runtime dependencies (ADR-0001) | |
| run: node scripts/check-zero-deps.mjs | |
| - name: Enforce SHA-pinned GitHub Actions (Scorecard Pinned-Dependencies) | |
| run: node scripts/check-action-pins.mjs | |
| - name: Enforce the offline/agent boundary (ADR-0005) | |
| run: node scripts/check-offline-boundary.mjs | |
| - name: action.yml pair in sync (root Marketplace copy vs packages/action) | |
| run: node scripts/check-action-yml-sync.mjs | |
| # GitHub never parses packages/action/examples, so a broken one ships to | |
| # every reader who copies it. One did. | |
| - name: Example workflows are well-formed and pinned to a moving major | |
| run: node scripts/check-example-workflows.mjs | |
| - name: REUSE lint (SPDX / licensing) — advisory | |
| continue-on-error: true | |
| run: | | |
| pipx install reuse >/dev/null 2>&1 || pip install --user reuse | |
| reuse lint | |
| dependency-review: | |
| name: dependency review (PR gate) | |
| runs-on: ubuntu-latest | |
| # Only meaningful on a PR (it diffs the base..head dependency manifests). | |
| if: github.event_name == 'pull_request' | |
| permissions: | |
| contents: read | |
| steps: | |
| - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 | |
| with: | |
| persist-credentials: false | |
| # Blocks a PR that introduces a known-vulnerable dependency or an | |
| # incompatible license. Zero runtime deps today (ADR-0001), so this guards | |
| # the dev-tool surface and keeps that invariant from eroding via a PR. | |
| - name: Dependency review | |
| uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0 | |
| with: | |
| fail-on-severity: high | |
| # Apache-2.0 project: deny strong-copyleft licenses that would conflict. | |
| deny-licenses: GPL-2.0, GPL-3.0, AGPL-3.0, LGPL-3.0 |