Skip to content

fix(security): make review-dependencies advisory (#33) #23

fix(security): make review-dependencies advisory (#33)

fix(security): make review-dependencies advisory (#33) #23

Workflow file for this run

# Self-CI Test
name: Self-CI Test
# A PR self-tests its composites via local `./` refs against the real checkout
# (GITHUB_SHA == HEAD); `commit-artifacts` pushes to a local bare remote, with
# `contents: read` as the backstop, so no real branch is touched. No secrets.
# Tag-driven paths can't be faked here — the runner re-injects GITHUB_REF_NAME /
# GITHUB_SHA inside a composite — so generate-changelog and pin-version stay
# validated at real release time.
on:
push:
branches: [main]
pull_request:
permissions:
contents: read
jobs:
test-verify-tag:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Pass — HEAD matches the run SHA
uses: ./.github/actions/release/verify-tag
- name: Move HEAD so it diverges from the run SHA
shell: bash
run: |
set -euo pipefail
git config user.email "ci@ci"; git config user.name "ci"; git config commit.gpgsign false
git commit -q --allow-empty -m "smoke: move HEAD"
- name: Fail — HEAD no longer matches
id: moved
continue-on-error: true
uses: ./.github/actions/release/verify-tag
- name: Assert the moved branch failed
shell: bash
run: |
set -euo pipefail
[ "${{ steps.moved.outcome }}" = "failure" ] || { echo "::error::verify-tag must fail when HEAD != GITHUB_SHA"; exit 1; }
echo "::notice::verify-tag passes on match, fails on divergence"
test-generate-changelog:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: SemVer gate rejects a non-tag ref
id: gate
continue-on-error: true
uses: ./.github/actions/release/generate-changelog
- name: Assert the gate rejected it
shell: bash
run: |
set -euo pipefail
[ "${{ steps.gate.outcome }}" = "failure" ] || { echo "::error::SemVer gate must reject the non-SemVer ref '${GITHUB_REF_NAME}'"; exit 1; }
echo "::notice::generate-changelog SemVer gate rejects non-tag refs"
test-commit-artifacts:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
path: _src
- name: Build a fixture repo + local bare remote
shell: bash
run: |
set -euo pipefail
# Throwaway non-shallow repo at the workspace root, where the composite's run executes.
# The PR's own checkout is shallow (push rejected) and lives under _src. GITHUB_REF_NAME
# is the real ref here — it only lands in the commit subject, asserted loosely below.
remote="${RUNNER_TEMP}/origin.git"; git init -q --bare "${remote}"
git init -q -b main
git config user.email "ci@ci"; git config user.name "ci"; git config commit.gpgsign false
git remote add origin "${remote}"
git commit -q --allow-empty -m base
git push -q origin HEAD:refs/heads/main
printf 'a\n' > art1.txt; printf 'b\n' > art2.txt
echo "REMOTE=${remote}" >> "${GITHUB_ENV}"
- name: Changed → commit + push (FILES word-split)
uses: ./_src/.github/actions/release/commit-artifacts
with:
files: art1.txt art2.txt
- name: Assert the remote advanced with both files
shell: bash
run: |
set -euo pipefail
git --git-dir="${REMOTE}" log -1 --pretty=%s main | grep -qE '^chore: release .+ \[skip ci\]$' \
|| { echo "::error::commit-artifacts subject malformed"; exit 1; }
tree="$(git --git-dir="${REMOTE}" ls-tree --name-only main)"
grep -qx 'art1.txt' <<<"${tree}" || { echo "::error::art1.txt missing from pushed tree"; exit 1; }
grep -qx 'art2.txt' <<<"${tree}" || { echo "::error::art2.txt missing from pushed tree (FILES word-split)"; exit 1; }
echo "BEFORE=$(git --git-dir="${REMOTE}" rev-parse main)" >> "${GITHUB_ENV}"
echo "::notice::commit-artifacts pushed both artifacts"
- name: Nothing changed → no-op
uses: ./_src/.github/actions/release/commit-artifacts
with:
files: art1.txt
- name: Assert the no-op left the remote untouched
shell: bash
run: |
set -euo pipefail
[ "${BEFORE}" = "$(git --git-dir="${REMOTE}" rev-parse main)" ] \
|| { echo "::error::no-op branch pushed unexpectedly"; exit 1; }
echo "::notice::commit-artifacts no-op left main untouched"
test-cargo-deny:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Plant a forbidden consumer override
shell: bash
run: |
set -euo pipefail
: > deny.exceptions.toml
- name: Composite must reject deny.exceptions.toml
id: reject
continue-on-error: true
uses: ./.github/actions/security/rust/cargo-deny
- name: Assert the reject guard fired
shell: bash
run: |
set -euo pipefail
[ "${{ steps.reject.outcome }}" = "failure" ] || { echo "::error::cargo-deny must reject a consumer deny.exceptions.toml"; exit 1; }
echo "::notice::cargo-deny rejects consumer deny.exceptions.toml"
test-install-dist:
# cargo-dist packages the Windows zip flat (dist.exe at root) but the Linux/macOS
# tarballs nested — extraction differs per OS, so the smoke covers all three.
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: ./.github/actions/rust/install-dist
- name: Assert dist is installed and runnable
shell: bash
run: |
set -euo pipefail
dist --version || { echo "::error::dist not on PATH after install-dist"; exit 1; }
echo "::notice::install-dist OK — $(dist --version)"
test-native-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Plant a fixture ci/setup.sh that records CARGO_DIST_TARGET
shell: bash
run: |
set -euo pipefail
mkdir -p ci
cat > ci/setup.sh <<'SH'
#!/usr/bin/env bash
echo "${CARGO_DIST_TARGET-}" > seen-target.txt
SH
- name: Host preflight — CARGO_DIST_TARGET unset
uses: ./.github/actions/rust/native-deps
- name: Assert the host hook ran and saw an empty target
shell: bash
run: |
set -euo pipefail
[ -f seen-target.txt ] || { echo "::error::ci/setup.sh did not run on host preflight"; exit 1; }
[ -z "$(cat seen-target.txt)" ] || { echo "::error::CARGO_DIST_TARGET must be empty on host preflight"; exit 1; }
- name: Export the target the way dist-build does
shell: bash
run: echo "CARGO_DIST_TARGET=aarch64-unknown-linux-gnu" >> "${GITHUB_ENV}"
- name: Cross leg — CARGO_DIST_TARGET exported
uses: ./.github/actions/rust/native-deps
- name: Assert the hook saw the exported target
shell: bash
run: |
set -euo pipefail
got="$(cat seen-target.txt)"
[ "${got}" = "aarch64-unknown-linux-gnu" ] || { echo "::error::ci/setup.sh saw '${got}', expected the exported target"; exit 1; }
echo "::notice::native-deps passes CARGO_DIST_TARGET through to ci/setup.sh"
test-test-deps:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- name: Absent hooks → no-op
uses: ./.github/actions/rust/test-deps
- name: Plant ci/test.env and ci/test-setup.sh
shell: bash
run: |
set -euo pipefail
mkdir -p ci
printf 'FOO=1\n' > ci/test.env
cat > ci/test-setup.sh <<'SH'
#!/usr/bin/env bash
touch test-setup-ran
SH
- name: Run the test hooks
uses: ./.github/actions/rust/test-deps
- name: Assert fixtures ran and test.env propagated
shell: bash
run: |
set -euo pipefail
[ -f test-setup-ran ] || { echo "::error::ci/test-setup.sh did not run"; exit 1; }
[ "${FOO:-}" = "1" ] || { echo "::error::ci/test.env did not propagate FOO to the job env"; exit 1; }
echo "::notice::test-deps runs test-setup.sh and propagates test.env"
test-javascript-base:
runs-on: ubuntu-latest
env:
NPM_CONFIG_FILE: "registry=https://registry.npmjs.org/"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
path: _src
- name: Stage the npm fixture at the workspace root
shell: bash
run: cp -a _src/test/fixtures/npm-package/. .
- uses: ./_src/.github/actions/javascript/base
- name: Assert install, lint, build, and test ran
shell: bash
run: |
set -euo pipefail
for m in lint-ran build-ran test-ran; do
[ -f "${m}" ] || { echo "::error::javascript/base did not run ${m%-ran}"; exit 1; }
done
echo "::notice::javascript/base ran install (sfw + frozen lockfile), lint, build, test on the fixture"
test-rust-base:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
path: _src
- name: Stage the rust fixture at the workspace root
shell: bash
run: cp -a _src/test/fixtures/rust-crate/. .
- uses: ./_src/.github/actions/rust/base
- name: Confirm rust/base completed the gates
shell: bash
run: echo "::notice::rust/base ran fmt --check, clippy -D warnings, and test on the fixture"