name: release-verify
on:
workflow_call:
inputs:
ref:
description: The commit to verify.
required: true
type: string
full:
description: Run the expensive closure verification.
required: false
default: false
type: boolean
permissions:
contents: read
jobs:
lint:
name: release lint
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- &install-release-tool
name: Build release-tool
run: cargo install --locked --force miden-release-tool
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with:
ref: ${{ inputs.ref }}
fetch-depth: 0
persist-credentials: false
- &install-rust
name: Install Rust
run: |
rustup update --no-self-update
rustc --version
- name: Lint release configuration
run: release-tool lint
- name: Check publication order is derivable
run: release-tool package-order
closure:
name: package closure
if: ${{ inputs.full }}
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- *install-release-tool
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with:
ref: ${{ inputs.ref }}
persist-credentials: false
- *install-rust
- name: Verify the package closure
run: release-tool verify-closure --cache-dir "${RUNNER_TEMP}/index-cache"
workflow-policy:
name: workflow policy
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 with:
ref: ${{ inputs.ref }}
persist-credentials: false
- name: Assert release workflow invariants
run: |
set -euo pipefail
fail() { echo "workflow-policy: $1" >&2; exit 1; }
# Only the production workflow may enter the production environment.
# Match the `environment:` key rather than any mention of the name, so
# that this check does not trip over its own search pattern.
# Written as `if grep` rather than `grep && fail`: in an `A && B` list
# the failure of A is invisible to `set -e`, so a broken pattern would
# read as a passing check rather than as an error.
for wf in .github/workflows/*.yml; do
case "$(basename "$wf")" in
release.yml) ;;
*)
if grep -Eq '^[[:space:]]+environment:[[:space:]]*release' "$wf"; then
fail "$wf enters the production environment"
fi ;;
esac
done
# Production must not accept scope or versions as inputs; the scope
# comes from the reviewed .release/release.toml and nothing else.
if [ -f .github/workflows/release.yml ]; then
if grep -Eq '^\s+(version|unit|units|scope):' .github/workflows/release.yml; then
fail "release.yml accepts scope or version inputs"
fi
fi
# The token must never appear on a command line.
if grep -rn -- '--token' .github/workflows/ | grep -v 'rehearsal'; then
fail "a token is passed as a command-line argument"
fi
# No long-lived registry secret anywhere. Publication authenticates
# through Trusted Publishing, which issues a short-lived token; a
# stored one would be a second, weaker way in.
if grep -rn 'secrets\.CARGO_REGISTRY_TOKEN' .github/workflows/; then
fail "a long-lived crates.io secret is referenced"
fi
echo "workflow-policy: ok"
- name: actionlint
uses: docker://rhysd/actionlint@sha256:9d36088643581e728c969f35141f88139fec77280b2be23c1f66f8e40e1025e7
with:
args: -color