Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions .github/workflows/distro.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,10 @@ env:
jobs:
toolchain:
name: Stages 01-02 (cross toolchain, temporary tools)
# actions: read, for the tag preflight to read CI's verdict on the commit.
permissions:
contents: read
actions: read
runs-on: ubuntu-24.04
timeout-minutes: 360
outputs:
Expand Down Expand Up @@ -89,6 +93,37 @@ jobs:
with:
sources: fetch

# A release takes only sources whose signatures verify against keys a
# publisher states, whose provenance holds, and a commit whose CI
# passed: the gates CI runs on every push, run again here so a tag
# never outruns them.
- name: The release's sources are signed, and their provenance holds
if: github.ref_type == 'tag'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
./tools/verify-signatures.sh --strict
./tools/verify-provenance.sh --strict
- name: CI passed on the tagged commit
if: github.ref_type == 'tag'
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
sha="$(git rev-parse 'HEAD^{commit}')"
status=none; conclusion=-
for try in $(seq 1 40); do
read -r status conclusion < <(gh api "repos/${GITHUB_REPOSITORY}/actions/workflows/ci.yml/runs?head_sha=${sha}&per_page=1" \
--jq '.workflow_runs[0] | "\(.status // "none") \(.conclusion // "-")"')
case "$status" in
completed) break ;;
none) echo "no CI run for ${sha}: a release is cut from a commit CI has tested"; exit 1 ;;
*) echo "CI is ${status} on ${sha}; waiting (${try}/40)"; sleep 60 ;;
esac
done
[ "$status" = completed ] || { echo "CI did not finish on ${sha} in time"; exit 1; }
[ "$conclusion" = success ] || { echo "CI concluded ${conclusion} on ${sha}: a release is cut only from a commit CI passed"; exit 1; }
echo "CI passed on ${sha}"

# The newest tree, whatever built it: its stamps decide what rebuilds,
# and 01-toolchain.sh clears one that another toolchain built. A tag
# restores nothing: a release holds only what a build from nothing
Expand Down
7 changes: 5 additions & 2 deletions docs/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,11 @@ the release key made offline. The dated builds CI makes of every push to main
```

3. The Distro workflow refuses a held pin (`check-pin-reviews.sh
--no-held`), then builds that version from nothing, with no cached tree,
so the release holds only what a clean build makes: about three hours. It
--no-held`), a source whose signature or provenance does not verify
(`verify-signatures.sh --strict`, `verify-provenance.sh --strict`) and a
commit whose CI did not pass, then builds that version from nothing, with
no cached tree, so the release holds only what a clean build makes: about
three hours. It
builds it as the release under test, over a `0.0.0` build the update
suite updates from, and runs every suite on the images. For a development
release (`v0.x`) its last job drafts the release: the export, the
Expand Down
Loading