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
23 changes: 15 additions & 8 deletions .github/workflows/actions.lock
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# This file is machine-generated by `gh actions-lock`.

Check failure on line 1 in .github/workflows/actions.lock

View workflow job for this annotation

GitHub Actions / Hypatia neurosymbolic scan

[hypatia] actions.lock failed closed: {:line, 253, {:duplicate_dependency, "swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6"}}

Check failure on line 1 in .github/workflows/actions.lock

View workflow job for this annotation

GitHub Actions / Hypatia neurosymbolic scan

[hypatia] Invalid .github/workflows/actions.lock: {:line, 253, {:duplicate_dependency, "swatinem/rust-cache@6323deb102c322ba6fcbdcafc7e3dddab59af2b6"}}. Regenerate and verify it with gh actions-lock.
# Do not edit by hand; run `gh actions-lock` to update.
# Docs: https://gh.io/actions-lockfile
version: 'v0.0.2'
Expand Down Expand Up @@ -40,10 +40,12 @@
- 'actions/checkout@v7.0.1'
- 'editorconfig-checker/action-editorconfig-checker@v3.0.0'
'.github/workflows/release.yml':
- 'actions/attest-build-provenance@v4.2.2'
- 'actions/checkout@v7.0.1'
- 'actions/upload-artifact@v7.0.1'
- 'softprops/action-gh-release@v3.0.3'
- 'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8'
- 'actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1'
- 'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c'
- 'actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a'
- 'dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772'
- 'softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64'
'.github/workflows/rhodibot.yml':
- 'actions/checkout@v7.0.1'
'.github/workflows/runtime-policy.yml':
Expand Down Expand Up @@ -73,8 +75,8 @@
commit: 'sha1-6323deb102c322ba6fcbdcafc7e3dddab59af2b6'
owner_id: 580492
repo_id: 298565987
'actions/attest-build-provenance@v4.2.2':
ref: 'v4.2.2'
'actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8':
ref: '4d101475d8b20a2381f78447822ac1eab6504dd8'
commit: 'sha1-4d101475d8b20a2381f78447822ac1eab6504dd8'
owner_id: 44036562
repo_id: 760702757
Expand Down Expand Up @@ -105,6 +107,11 @@
commit: 'sha1-368f82528645a54fb793d4d04e342629a3f51346'
owner_id: 44036562
repo_id: 438112499
'actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c':
ref: '3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c'
commit: 'sha1-3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c'
owner_id: 44036562
repo_id: 192626254
'actions/download-artifact@v8.0.1':
ref: 'v8.0.1'
commit: 'sha1-3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c'
Expand Down Expand Up @@ -238,8 +245,8 @@
commit: 'sha1-0c5077e51419868618aeaa5fe8019c62421857d6'
owner_id: 108928776
repo_id: 512644635
'softprops/action-gh-release@v3.0.3':
ref: 'v3.0.3'
'softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64':
ref: 'efb35369e0ad2afab669f228072c1b0d510eae64'
commit: 'sha1-efb35369e0ad2afab669f228072c1b0d510eae64'
owner_id: 2242
repo_id: 204253808
Expand Down
196 changes: 70 additions & 126 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,16 @@
# This workflow is managed by gh actions-lock.
# Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
#
# Release workflow — triggered by version tags (v*).
# Builds artifacts, generates changelog via git-cliff, creates a GitHub Release,
# and produces GitHub native build-provenance attestations (OIDC + Sigstore).
# Release workflow, triggered by a version tag (v*).
# Builds a static `squabble` binary for x86_64-unknown-linux-musl with the
# workspace MSRV toolchain, stages it with a SHA256SUMS file, attests build
# provenance for both files (OIDC + Sigstore), and publishes them on the
# GitHub Release for the tag. Every step fails closed: a missing file stops
# the run before anything is attested or published.
#
# Verify a downloaded binary with:
# sha256sum -c SHA256SUMS
# gh attestation verify squabble-x86_64-linux-musl --repo hyperpolymath/cicd-squabbler
name: Release
on:
push:
Expand All @@ -14,147 +21,84 @@ concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: false
permissions:
actions: read
contents: read
jobs:
build:
name: Build Artifacts
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: read
steps:
- uses: actions/checkout@v7.0.1
- name: Detect project type and build
id: build
run: |
# Auto-detect build system from project files.
# Order matters: more specific markers checked first.
if [ -f "mix.exs" ]; then
echo "::notice::Detected Elixir/Gleam project (mix.exs)"
echo "build_type=mix" >> "$GITHUB_OUTPUT"
mix local.hex --force --if-missing
mix local.rebar --force --if-missing
mix deps.get --only prod
MIX_ENV=prod mix release
elif [ -f "Cargo.toml" ]; then
echo "::notice::Detected Rust project (Cargo.toml)"
echo "build_type=cargo" >> "$GITHUB_OUTPUT"
cargo build --release
elif [ -f "build.zig" ]; then
echo "::notice::Detected Zig project (build.zig)"
echo "build_type=zig" >> "$GITHUB_OUTPUT"
zig build -Doptimize=ReleaseSafe
elif [ -f "deno.json" ] || [ -f "deno.jsonc" ]; then
echo "::notice::Detected Deno project (deno.json)"
echo "build_type=deno" >> "$GITHUB_OUTPUT"
deno task build
elif [ -f "gossamer.conf.json" ]; then
echo "::notice::Detected Gossamer project (gossamer.conf.json)"
echo "build_type=gossamer" >> "$GITHUB_OUTPUT"
gossamer build
elif [ -f "gleam.toml" ]; then
echo "::notice::Detected Gleam project (gleam.toml)"
echo "build_type=gleam" >> "$GITHUB_OUTPUT"
gleam build
elif [ -f "rebar.config" ]; then
echo "::notice::Detected Erlang/Rebar project (rebar.config)"
echo "build_type=rebar" >> "$GITHUB_OUTPUT"
rebar3 as prod release
elif [ -f "Justfile" ] || [ -f "justfile" ]; then
echo "::notice::Detected Justfile — running 'just build'"
echo "build_type=just" >> "$GITHUB_OUTPUT"
just build
else
echo "::error::No recognised build system found."
echo "Expected one of: mix.exs, Cargo.toml, build.zig, deno.json, gossamer.conf.json, gleam.toml, rebar.config, Justfile"
exit 1
fi
# TODO: Upload build artifacts if needed (pin actions/upload-artifact
# to a full commit SHA when enabling, per the SHA-pin policy):
# - uses: actions/upload-artifact@<full-commit-sha> # vX.Y.Z
# with:
# name: release-artifacts
# path: target/release/
changelog:
name: Generate Changelog
name: Build squabble (x86_64-linux-musl)
runs-on: ubuntu-latest
timeout-minutes: 15
timeout-minutes: 20
permissions:
contents: read
outputs:
changelog: ${{ steps.cliff.outputs.content }}
version: ${{ steps.version.outputs.version }}
steps:
- uses: actions/checkout@v7.0.1
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
- name: Extract version from tag
id: version
run: echo "version=${GITHUB_REF_NAME#v}" >> "$GITHUB_OUTPUT"
- name: Install git-cliff
persist-credentials: false
# Untagged dtolnay/rust-toolchain master commit (2026-08-04, merge of #182);
# an ancestor of the moving `v1` branch. Pinned by SHA, so no tag applies.
- uses: dtolnay/rust-toolchain@6c977a6ca4077a0ceb28ffbe03f59d46e9ac8772 # master 2026-08-04
with:
toolchain: 1.85.0
targets: x86_64-unknown-linux-musl
- name: Install musl-tools
run: |
curl -sSfL https://github.com/orhun/git-cliff/releases/latest/download/git-cliff-$(uname -m)-unknown-linux-gnu.tar.gz \
| tar -xz --strip-components=1 -C /usr/local/bin/ git-cliff-*/git-cliff
- name: Generate changelog for this release
id: cliff
sudo apt-get update
sudo apt-get install -y musl-tools
- name: Build release binary
run: cargo build --locked --release -p squabble-cli --target x86_64-unknown-linux-musl
- name: Stage dist/
run: |
# Generate changelog for the current tag only
CHANGELOG=$(git cliff --latest --strip header)
# Write to output using delimiter to handle multiline
{
echo "content<<CLIFF_EOF"
echo "$CHANGELOG"
echo "CLIFF_EOF"
} >> "$GITHUB_OUTPUT"
- name: Update full CHANGELOG.md
mkdir -p dist
cp target/x86_64-unknown-linux-musl/release/squabble dist/squabble-x86_64-linux-musl
cd dist
sha256sum squabble-x86_64-linux-musl > SHA256SUMS
- name: Require both release files
run: |
git cliff --output CHANGELOG.md
- name: Upload updated CHANGELOG.md
uses: actions/upload-artifact@v7.0.1
for f in dist/squabble-x86_64-linux-musl dist/SHA256SUMS; do
test -s "$f" || { echo "::error::missing or empty release file: $f"; exit 1; }
done
cd dist
sha256sum -c SHA256SUMS
- uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: changelog
path: CHANGELOG.md
name: release-dist
path: dist/
if-no-files-found: error
retention-days: 5
release:
name: Create GitHub Release
needs: [build, changelog]
name: Publish GitHub Release
needs: build
runs-on: ubuntu-latest
timeout-minutes: 15
permissions:
contents: write
id-token: write # mint the OIDC token attestation provenance is signed with
attestations: write # write the build-provenance attestation (the "claim")
contents: write # create the release and upload its assets
id-token: write # mint the OIDC token the provenance attestation is signed with
attestations: write # store the build-provenance attestation
steps:
- uses: actions/checkout@v7.0.1
# TODO: Download build artifacts if uploading to the release (pin
# actions/download-artifact to a full commit SHA when enabling):
# - uses: actions/download-artifact@<full-commit-sha> # vX.Y.Z
# with:
# name: release-artifacts
# path: artifacts/
- name: Create GitHub Release
uses: softprops/action-gh-release@v3.0.3
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
with:
body: ${{ needs.changelog.outputs.changelog }}
draft: false
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}
generate_release_notes: false
# TODO: Add artifact files to the release
# files: |
# artifacts/*
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
# GitHub native artifact attestation (build provenance). Generates a
# signed, verifiable claim binding each released artifact to this build
# (commit, workflow, runner) via OIDC + Sigstore — verify with
# `gh attest verify <artifact> --repo ${{ github.repository }}`.
# Replaces the older SLSA-generator job; native attestations need no
# separate isolated workflow.
# TODO: point subject-path at the artifacts this release actually ships
# (must match the `files:` uploaded above, e.g. artifacts/*).
name: release-dist
path: dist
- name: Refuse an empty or incomplete dist/
run: |
shopt -s nullglob
files=(dist/*)
if [ "${#files[@]}" -eq 0 ]; then
echo "::error::dist/ is empty; nothing to attest or release"
exit 1
fi
for f in dist/squabble-x86_64-linux-musl dist/SHA256SUMS; do
test -s "$f" || { echo "::error::missing or empty release file: $f"; exit 1; }
done
cd dist
sha256sum -c SHA256SUMS
- name: Attest build provenance
if: ${{ hashFiles('artifacts/*') != '' }} # skip until real artifacts are wired
uses: actions/attest-build-provenance@v4.2.2
uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2
with:
subject-path: 'dist/*'
- name: Create GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
with:
subject-path: 'artifacts/*'
files: dist/*
fail_on_unmatched_files: true
generate_release_notes: true
prerelease: ${{ contains(github.ref_name, '-rc') || contains(github.ref_name, '-beta') || contains(github.ref_name, '-alpha') }}
2 changes: 1 addition & 1 deletion Justfile
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ release-tag version:
just changelog
git add CHANGELOG.md
git commit -m "chore(release): prepare $TAG"
git tag -a "$TAG" -m "Release $TAG"
git tag -s "$TAG" -m "Release $TAG"
echo "Created tag $TAG — push with: git push origin main --tags"

# ═══════════════════════════════════════════════════════════════════════════════
Expand Down
Loading