Skip to content

deps: bump tsx from 4.23.1 to 4.23.12 #355

deps: bump tsx from 4.23.1 to 4.23.12

deps: bump tsx from 4.23.1 to 4.23.12 #355

Workflow file for this run

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