From 7236a127aa0757f4bb80b0593e7765749586fa02 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Mon, 2 Feb 2026 21:22:59 +0100 Subject: [PATCH 01/16] Add SBOM --- .github/workflows/release.yml | 52 +++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 50f67f5..ed40483 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -118,6 +118,31 @@ jobs: sudo apt-get update sudo apt-get install -y minisign gnupg + - name: Install SBOM tool (syft) + run: | + set -euo pipefail + syft_version="v1.12.1" + curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin "$syft_version" + syft version + + - name: Generate SBOMs (SPDX + CycloneDX) + run: | + set -euo pipefail + mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) + if [ "${#files[@]}" -eq 0 ]; then + echo "No toolchain tarballs found under dist/." >&2 + exit 1 + fi + + for f in "${files[@]}"; do + base="$(basename "$f" .tar.gz)" + workdir="$(mktemp -d)" + tar -C "$workdir" -xzf "$f" + syft "dir:$workdir" -o spdx-json > "dist/${base}.spdx.json" + syft "dir:$workdir" -o cyclonedx-json > "dist/${base}.cdx.json" + rm -rf "$workdir" + done + - name: Generate SHA256SUMS and signatures env: MINISIGN_KEY: ${{ secrets.MINISIGN_KEY }} @@ -158,7 +183,13 @@ jobs: exit 1 fi - sha256sum "${files[@]}" > dist/SHA256SUMS + mapfile -d '' sboms < <(find dist -maxdepth 1 \( -name 'bugleos-toolchain-*.spdx.json' -o -name 'bugleos-toolchain-*.cdx.json' \) -print0 | sort -z) + if [ "${#sboms[@]}" -eq 0 ]; then + echo "No SBOM files found under dist/." >&2 + exit 1 + fi + + sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS minisign -S -s out/minisign.key -p out/minisign.pub -m dist/SHA256SUMS if [ -n "${GPG_PASSPHRASE:-}" ]; then @@ -186,11 +217,16 @@ jobs: draft: false prerelease: ${{ env.PRERELEASE }} body: | - Supported architectures: - Architecture | Download Link - ------------ | ------------- - x86_64 | [bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz) - aarch64 | [bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz) + # Supported architectures: + + ## 64-bit architecture (x86_64) + [Download bugleos-toolchain-${{ env.VERSION }}-x86_64 toolchain](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz) + [Download bugleos-toolchain-${{ env.VERSION }}-x86_64 minisign](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig) + + ## ARM 64-bit architecture (aarch64) + [Download bugleos-toolchain-${{ env.VERSION }}-aarch64 toolchain](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz) + [Download bugleos-toolchain-${{ env.VERSION }}-aarch64 minisign](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig) + files: | dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz @@ -198,6 +234,10 @@ jobs: dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.asc dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.asc + dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.spdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.spdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.cdx.json + dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.cdx.json dist/SHA256SUMS dist/SHA256SUMS.minisig dist/SHA256SUMS.asc From be85db04e9f0db4e9bc84b11eb554a4030525160 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Mon, 2 Feb 2026 22:29:14 +0100 Subject: [PATCH 02/16] Add SLSA provenance --- .github/workflows/release.yml | 47 +++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index ed40483..d16aea9 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -90,6 +90,39 @@ jobs: path: dist/bugleos-toolchain-${{ env.VERSION }}-${{ matrix.label }}.tar.gz if-no-files-found: error + hash-artifacts: + name: Prepare SLSA subjects + runs-on: ubuntu-latest + needs: build + outputs: + base64_subjects: ${{ steps.hashes.outputs.base64_subjects }} + steps: + - name: Download toolchain tarballs + uses: actions/download-artifact@v4 + with: + path: dist + + - name: Compute base64 subjects + id: hashes + shell: bash + run: | + set -euo pipefail + mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) + if [ "${#files[@]}" -eq 0 ]; then + echo "No toolchain tarballs found under dist/." >&2 + exit 1 + fi + + tmp="$(mktemp)" + for f in "${files[@]}"; do + hash="$(sha256sum "$f" | awk '{print $1}')" + name="$(basename "$f")" + printf '%s %s\n' "$hash" "$name" >> "$tmp" + done + + sort "$tmp" | base64 -w0 > "$tmp.b64" + echo "base64_subjects=$(cat "$tmp.b64")" >> "$GITHUB_OUTPUT" + publish: name: Publish Release runs-on: ubuntu-latest @@ -242,3 +275,17 @@ jobs: dist/SHA256SUMS.minisig dist/SHA256SUMS.asc dist/minisign.pub + + provenance: + name: Generate SLSA provenance + needs: [hash-artifacts, publish] + permissions: + actions: read + id-token: write + contents: write + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 + with: + base64-subjects: "${{ needs.hash-artifacts.outputs.base64_subjects }}" + upload-assets: true + upload-tag-name: ${{ github.ref_name }} + provenance-name: bugleos-toolchain-${{ github.ref_name }}.intoto.jsonl From 8a564bbb27b46f22fb5b3e0324d6a8b427ccdc4f Mon Sep 17 00:00:00 2001 From: Sebastiano Trombetta Date: Tue, 3 Feb 2026 11:21:29 +0100 Subject: [PATCH 03/16] Update syft installation script URL in release.yml --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d16aea9..c0ede1a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -155,7 +155,7 @@ jobs: run: | set -euo pipefail syft_version="v1.12.1" - curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin "$syft_version" + curl -sSfL https://get.anchore.io/syft | sh -s -- -b /usr/local/bin "$syft_version" syft version - name: Generate SBOMs (SPDX + CycloneDX) From 782cf3032898e70787e11e52dc1adc90df165064 Mon Sep 17 00:00:00 2001 From: Sebastiano Trombetta Date: Tue, 3 Feb 2026 12:46:00 +0100 Subject: [PATCH 04/16] Update release.yml --- .github/workflows/release.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c0ede1a..3e4657f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -154,8 +154,7 @@ jobs: - name: Install SBOM tool (syft) run: | set -euo pipefail - syft_version="v1.12.1" - curl -sSfL https://get.anchore.io/syft | sh -s -- -b /usr/local/bin "$syft_version" + curl -sSfL https://get.anchore.io/syft | sh -s -- -b /usr/local/bin syft version - name: Generate SBOMs (SPDX + CycloneDX) From 1358cffd5f71daf7b76cff31c6db15b0aee39f3a Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Tue, 3 Feb 2026 17:10:35 +0100 Subject: [PATCH 05/16] Fix release.yml --- .github/workflows/release.yml | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3e4657f..276ac8a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -179,6 +179,7 @@ jobs: env: MINISIGN_KEY: ${{ secrets.MINISIGN_KEY }} MINISIGN_PUB: ${{ secrets.MINISIGN_PUB }} + MINISIGN_PASSWORD: ${{ secrets.MINISIGN_PASSWORD }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | @@ -223,7 +224,12 @@ jobs: sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS - minisign -S -s out/minisign.key -p out/minisign.pub -m dist/SHA256SUMS + minisign_args=(-S -s out/minisign.key -p out/minisign.pub) + if [ -n "${MINISIGN_PASSWORD:-}" ]; then + minisign_args+=(-P "$MINISIGN_PASSWORD") + fi + + minisign "${minisign_args[@]}" -m dist/SHA256SUMS if [ -n "${GPG_PASSPHRASE:-}" ]; then gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS @@ -232,7 +238,7 @@ jobs: fi for f in "${files[@]}"; do - minisign -S -s out/minisign.key -p out/minisign.pub -m "$f" + minisign "${minisign_args[@]}" -m "$f" if [ -n "${GPG_PASSPHRASE:-}" ]; then gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" From 3a7817de356c82099949a4ff69faf5e63396f2cd Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 07:38:38 +0100 Subject: [PATCH 06/16] Fix minisign and gpg --- .github/workflows/release.yml | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 276ac8a..813f528 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -209,6 +209,13 @@ jobs: echo "No GPG secret key imported." >&2 exit 1 fi + if [ -z "${GPG_PASSPHRASE:-}" ]; then + if ! gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then + echo "GPG_PASSPHRASE is required for the provided GPG key." >&2 + exit 1 + fi + rm -f /tmp/gpg-passcheck.asc + fi mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) if [ "${#files[@]}" -eq 0 ]; then @@ -224,10 +231,19 @@ jobs: sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS - minisign_args=(-S -s out/minisign.key -p out/minisign.pub) + minisign_args=(-S -s out/minisign.key) if [ -n "${MINISIGN_PASSWORD:-}" ]; then minisign_args+=(-P "$MINISIGN_PASSWORD") fi + if [ -z "${MINISIGN_PASSWORD:-}" ]; then + tmp_minisign="$(mktemp)" + printf 'minisign-check' > "$tmp_minisign" + if ! minisign -S -s out/minisign.key -m "$tmp_minisign" >/dev/null 2>&1; then + echo "MINISIGN_PASSWORD is required for the provided minisign key." >&2 + exit 1 + fi + rm -f "$tmp_minisign" "$tmp_minisign.minisig" + fi minisign "${minisign_args[@]}" -m dist/SHA256SUMS if [ -n "${GPG_PASSPHRASE:-}" ]; then From 23f3f91c179b2d9aab1df8bce66975b80a6f584f Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:22:29 +0100 Subject: [PATCH 07/16] Add minisign key check --- .github/workflows/release.yml | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 813f528..1abc89f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -195,11 +195,26 @@ jobs: fi mkdir -p out dist - printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key - printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub + if ! printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key 2>/dev/null; then + echo "MINISIGN_KEY is not valid base64. Re-encode minisign.key and update the secret." >&2 + exit 1 + fi + if ! printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub 2>/dev/null; then + echo "MINISIGN_PUB is not valid base64. Re-encode minisign.pub and update the secret." >&2 + exit 1 + fi chmod 600 out/minisign.key cp out/minisign.pub dist/minisign.pub + if ! grep -qi "minisign secret key" out/minisign.key; then + echo "MINISIGN_KEY does not look like a minisign secret key. Check that secrets are not swapped." >&2 + exit 1 + fi + if ! grep -qi "minisign public key" out/minisign.pub; then + echo "MINISIGN_PUB does not look like a minisign public key. Check that secrets are not swapped." >&2 + exit 1 + fi + export GNUPGHOME GNUPGHOME="$(mktemp -d)" trap 'rm -rf "$GNUPGHOME"' EXIT From 3435b61f66647058abb4fff270af7d9d6c37532c Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 08:50:01 +0100 Subject: [PATCH 08/16] Add build caching --- .github/workflows/release.yml | 67 +++++++++++++++++++++++++++++++++-- 1 file changed, 65 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1abc89f..3323815 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -29,6 +29,26 @@ jobs: with: fetch-depth: 0 + - name: Read package versions + shell: bash + run: | + set -euo pipefail + binutils_version="$(awk -F ' := ' '/^BINUTILS_VERSION/ {print $2; exit}' make/binutils-stage1.mk)" + gcc_version="$(awk -F ' := ' '/^GCC_VERSION/ {print $2; exit}' make/gcc-stage1.mk)" + musl_version="$(awk -F ' := ' '/^MUSL_VERSION/ {print $2; exit}' make/musl.mk)" + linux_version="$(awk -F ' := ' '/^LINUX_VERSION/ {print $2; exit}' make/linux-headers.mk)" + + if [ -z "$binutils_version" ] || [ -z "$gcc_version" ] || [ -z "$musl_version" ] || [ -z "$linux_version" ]; then + echo "Failed to read one or more package versions." >&2 + exit 1 + fi + + echo "BINUTILS_VERSION=${binutils_version}" >> "$GITHUB_ENV" + echo "GCC_VERSION=${gcc_version}" >> "$GITHUB_ENV" + echo "MUSL_VERSION=${musl_version}" >> "$GITHUB_ENV" + echo "LINUX_VERSION=${linux_version}" >> "$GITHUB_ENV" + echo "VERSIONS_KEY=binutils-${binutils_version}-gcc-${gcc_version}-musl-${musl_version}-linux-${linux_version}" >> "$GITHUB_ENV" + - name: Validate tag format run: | set -euo pipefail @@ -47,6 +67,24 @@ jobs: build-essential binutils bash coreutils tar gzip xz-utils bison flex texinfo gawk file curl wget gpg \ libgmp-dev libmpfr-dev libmpc-dev python3 + - name: Restore download cache + uses: actions/cache@v4 + with: + path: | + downloads/ + sources/ + key: downloads-${{ runner.os }}-${{ matrix.arch }}-${{ env.VERSIONS_KEY }} + + - name: Restore build cache + uses: actions/cache@v4 + with: + path: | + builds/ + out/progress/ + out/toolchain/ + out/toolchain-stage1/ + key: build-${{ runner.os }}-${{ matrix.arch }}-${{ env.VERSIONS_KEY }}-${{ hashFiles('Makefile', 'make/*.mk', 'config/*.mk', 'scripts/*.sh') }} + - name: Fetch sources run: | set -euo pipefail @@ -57,10 +95,35 @@ jobs: set -euo pipefail ./scripts/verify-checksums.sh - - name: Build ${{ matrix.arch }} toolchain + - name: Build binutils stage1 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} binutils-stage1 + + - name: Build Linux headers + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} linux-headers + + - name: Build GCC stage1 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} gcc-stage1 + + - name: Build musl + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} musl + + - name: Build binutils stage2 + run: | + set -euo pipefail + make TARGET=${{ matrix.triple }} binutils-stage2 + + - name: Build GCC stage2 run: | set -euo pipefail - make TARGET=${{ matrix.triple }} toolchain + make TARGET=${{ matrix.triple }} gcc-stage2 - name: Upload build logs if: always() From 29de4f3b741a6b8771659fdb5d1900a62dbb601f Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:17:28 +0100 Subject: [PATCH 09/16] Add debugging info --- .github/workflows/release.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3323815..a392afb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -4,6 +4,7 @@ on: push: tags: - "v*" + workflow_dispatch: jobs: build: @@ -269,12 +270,14 @@ jobs: chmod 600 out/minisign.key cp out/minisign.pub dist/minisign.pub - if ! grep -qi "minisign secret key" out/minisign.key; then - echo "MINISIGN_KEY does not look like a minisign secret key. Check that secrets are not swapped." >&2 + key_first_line="$(head -n 1 out/minisign.key | tr -d '\r')" + pub_first_line="$(head -n 1 out/minisign.pub | tr -d '\r')" + if ! printf '%s\n' "$key_first_line" | grep -qi "minisign secret key"; then + echo "MINISIGN_KEY does not look like a minisign secret key. First line: '$key_first_line'." >&2 exit 1 fi - if ! grep -qi "minisign public key" out/minisign.pub; then - echo "MINISIGN_PUB does not look like a minisign public key. Check that secrets are not swapped." >&2 + if ! printf '%s\n' "$pub_first_line" | grep -qi "minisign public key"; then + echo "MINISIGN_PUB does not look like a minisign public key. First line: '$pub_first_line'." >&2 exit 1 fi From 58a99a878d37e71eb6d4a37436cb0f356105fe74 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 10:47:25 +0100 Subject: [PATCH 10/16] Update release.yml --- .github/workflows/release.yml | 46 +++++++++++++++-------------------- 1 file changed, 20 insertions(+), 26 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index a392afb..7f5c46f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -260,27 +260,16 @@ jobs: mkdir -p out dist if ! printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key 2>/dev/null; then - echo "MINISIGN_KEY is not valid base64. Re-encode minisign.key and update the secret." >&2 + echo "Failed to decode MINISIGN_KEY (expected base64). Re-encode minisign.key and update the secret." >&2 exit 1 fi if ! printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub 2>/dev/null; then - echo "MINISIGN_PUB is not valid base64. Re-encode minisign.pub and update the secret." >&2 + echo "Failed to decode MINISIGN_PUB (expected base64). Re-encode minisign.pub and update the secret." >&2 exit 1 fi chmod 600 out/minisign.key cp out/minisign.pub dist/minisign.pub - key_first_line="$(head -n 1 out/minisign.key | tr -d '\r')" - pub_first_line="$(head -n 1 out/minisign.pub | tr -d '\r')" - if ! printf '%s\n' "$key_first_line" | grep -qi "minisign secret key"; then - echo "MINISIGN_KEY does not look like a minisign secret key. First line: '$key_first_line'." >&2 - exit 1 - fi - if ! printf '%s\n' "$pub_first_line" | grep -qi "minisign public key"; then - echo "MINISIGN_PUB does not look like a minisign public key. First line: '$pub_first_line'." >&2 - exit 1 - fi - export GNUPGHOME GNUPGHOME="$(mktemp -d)" trap 'rm -rf "$GNUPGHOME"' EXIT @@ -290,13 +279,6 @@ jobs: echo "No GPG secret key imported." >&2 exit 1 fi - if [ -z "${GPG_PASSPHRASE:-}" ]; then - if ! gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then - echo "GPG_PASSPHRASE is required for the provided GPG key." >&2 - exit 1 - fi - rm -f /tmp/gpg-passcheck.asc - fi mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) if [ "${#files[@]}" -eq 0 ]; then @@ -316,15 +298,27 @@ jobs: if [ -n "${MINISIGN_PASSWORD:-}" ]; then minisign_args+=(-P "$MINISIGN_PASSWORD") fi - if [ -z "${MINISIGN_PASSWORD:-}" ]; then - tmp_minisign="$(mktemp)" - printf 'minisign-check' > "$tmp_minisign" - if ! minisign -S -s out/minisign.key -m "$tmp_minisign" >/dev/null 2>&1; then - echo "MINISIGN_PASSWORD is required for the provided minisign key." >&2 + tmp_minisign="$(mktemp)" + printf 'minisign-check' > "$tmp_minisign" + if ! minisign "${minisign_args[@]}" -m "$tmp_minisign" >/dev/null 2>&1; then + echo "Minisign test signing failed. Check MINISIGN_PASSWORD and key material." >&2 + exit 1 + fi + rm -f "$tmp_minisign" "$tmp_minisign.minisig" + + if [ -n "${GPG_PASSPHRASE:-}" ]; then + if ! gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ + --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then + echo "GPG test signing failed. Check GPG_PASSPHRASE and key material." >&2 + exit 1 + fi + else + if ! gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then + echo "GPG test signing failed. The key may be passphrase-protected; set GPG_PASSPHRASE." >&2 exit 1 fi - rm -f "$tmp_minisign" "$tmp_minisign.minisig" fi + rm -f /tmp/gpg-passcheck.asc minisign "${minisign_args[@]}" -m dist/SHA256SUMS if [ -n "${GPG_PASSPHRASE:-}" ]; then From 3cdea27699614a587c1739810f584c58b9d01dec Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 11:01:02 +0100 Subject: [PATCH 11/16] Add diagnostic information for minisign --- .github/workflows/release.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 7f5c46f..052d80d 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -299,12 +299,22 @@ jobs: minisign_args+=(-P "$MINISIGN_PASSWORD") fi tmp_minisign="$(mktemp)" + tmp_minisign_err="$(mktemp)" printf 'minisign-check' > "$tmp_minisign" - if ! minisign "${minisign_args[@]}" -m "$tmp_minisign" >/dev/null 2>&1; then - echo "Minisign test signing failed. Check MINISIGN_PASSWORD and key material." >&2 + if ! minisign "${minisign_args[@]}" -m "$tmp_minisign" >/dev/null 2>"$tmp_minisign_err"; then + if [ -n "${MINISIGN_PASSWORD:-}" ]; then + if minisign -S -s out/minisign.key -m "$tmp_minisign" >/dev/null 2>&1; then + echo "Minisign test signing succeeded without MINISIGN_PASSWORD. Remove it or update the key/password." >&2 + rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" + exit 1 + fi + fi + echo "Minisign test signing failed. minisign stderr:" >&2 + sed 's/^/ /' "$tmp_minisign_err" >&2 || true + rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" exit 1 fi - rm -f "$tmp_minisign" "$tmp_minisign.minisig" + rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" if [ -n "${GPG_PASSPHRASE:-}" ]; then if ! gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ From f85973c676aafda541fb39d095b7bef8e7040545 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 12:08:20 +0100 Subject: [PATCH 12/16] Update release.yml --- .github/workflows/release.yml | 62 ++++------------------------------- 1 file changed, 7 insertions(+), 55 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 052d80d..d4e014e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -259,14 +259,8 @@ jobs: fi mkdir -p out dist - if ! printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key 2>/dev/null; then - echo "Failed to decode MINISIGN_KEY (expected base64). Re-encode minisign.key and update the secret." >&2 - exit 1 - fi - if ! printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub 2>/dev/null; then - echo "Failed to decode MINISIGN_PUB (expected base64). Re-encode minisign.pub and update the secret." >&2 - exit 1 - fi + printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key + printf '%s' "$MINISIGN_PUB" | base64 -d > out/minisign.pub chmod 600 out/minisign.key cp out/minisign.pub dist/minisign.pub @@ -294,58 +288,16 @@ jobs: sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS - minisign_args=(-S -s out/minisign.key) - if [ -n "${MINISIGN_PASSWORD:-}" ]; then - minisign_args+=(-P "$MINISIGN_PASSWORD") - fi - tmp_minisign="$(mktemp)" - tmp_minisign_err="$(mktemp)" - printf 'minisign-check' > "$tmp_minisign" - if ! minisign "${minisign_args[@]}" -m "$tmp_minisign" >/dev/null 2>"$tmp_minisign_err"; then - if [ -n "${MINISIGN_PASSWORD:-}" ]; then - if minisign -S -s out/minisign.key -m "$tmp_minisign" >/dev/null 2>&1; then - echo "Minisign test signing succeeded without MINISIGN_PASSWORD. Remove it or update the key/password." >&2 - rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" - exit 1 - fi - fi - echo "Minisign test signing failed. minisign stderr:" >&2 - sed 's/^/ /' "$tmp_minisign_err" >&2 || true - rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" - exit 1 - fi - rm -f "$tmp_minisign" "$tmp_minisign.minisig" "$tmp_minisign_err" - - if [ -n "${GPG_PASSPHRASE:-}" ]; then - if ! gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ - --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then - echo "GPG test signing failed. Check GPG_PASSPHRASE and key material." >&2 - exit 1 - fi - else - if ! gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o /tmp/gpg-passcheck.asc /dev/null >/dev/null 2>&1; then - echo "GPG test signing failed. The key may be passphrase-protected; set GPG_PASSPHRASE." >&2 - exit 1 - fi - fi - rm -f /tmp/gpg-passcheck.asc + minisign_args=(-S -s out/minisign.key -P "$MINISIGN_PASSWORD") minisign "${minisign_args[@]}" -m dist/SHA256SUMS - if [ -n "${GPG_PASSPHRASE:-}" ]; then - gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ - --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS - else - gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS - fi + gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ + --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS for f in "${files[@]}"; do minisign "${minisign_args[@]}" -m "$f" - if [ -n "${GPG_PASSPHRASE:-}" ]; then - gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ - --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" - else - gpg --batch --yes --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" - fi + gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ + --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" done - name: Publish GitHub Release From ec07b97f31ad15eda278bac51a4dd11d048737b3 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:59:02 +0100 Subject: [PATCH 13/16] Fix minisign key encoding and decoding --- .github/workflows/release.yml | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d4e014e..fd18717 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -243,7 +243,6 @@ jobs: env: MINISIGN_KEY: ${{ secrets.MINISIGN_KEY }} MINISIGN_PUB: ${{ secrets.MINISIGN_PUB }} - MINISIGN_PASSWORD: ${{ secrets.MINISIGN_PASSWORD }} GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | @@ -288,14 +287,12 @@ jobs: sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS - minisign_args=(-S -s out/minisign.key -P "$MINISIGN_PASSWORD") - - minisign "${minisign_args[@]}" -m dist/SHA256SUMS + minisign -S -s out/minisign.key -m dist/SHA256SUMS gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS for f in "${files[@]}"; do - minisign "${minisign_args[@]}" -m "$f" + minisign -S -s out/minisign.key -m "$f" gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" done From 32a8d2d00255a12ef048bdc2191b3f588ff2118b Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Wed, 4 Feb 2026 17:15:42 +0100 Subject: [PATCH 14/16] Removed GPG signing --- .github/workflows/release.yml | 27 +-------------------------- 1 file changed, 1 insertion(+), 26 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd18717..542a0eb 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -243,8 +243,6 @@ jobs: env: MINISIGN_KEY: ${{ secrets.MINISIGN_KEY }} MINISIGN_PUB: ${{ secrets.MINISIGN_PUB }} - GPG_PRIVATE_KEY: ${{ secrets.GPG_PRIVATE_KEY }} - GPG_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }} run: | set -euo pipefail @@ -252,10 +250,6 @@ jobs: echo "Missing minisign secrets (MINISIGN_KEY / MINISIGN_PUB)." >&2 exit 1 fi - if [ -z "${GPG_PRIVATE_KEY:-}" ]; then - echo "Missing GPG_PRIVATE_KEY secret." >&2 - exit 1 - fi mkdir -p out dist printf '%s' "$MINISIGN_KEY" | base64 -d > out/minisign.key @@ -263,16 +257,6 @@ jobs: chmod 600 out/minisign.key cp out/minisign.pub dist/minisign.pub - export GNUPGHOME - GNUPGHOME="$(mktemp -d)" - trap 'rm -rf "$GNUPGHOME"' EXIT - printf '%s' "$GPG_PRIVATE_KEY" | gpg --batch --import - key_id="$(gpg --list-secret-keys --with-colons | awk -F: '$1=="sec" {print $5; exit}')" - if [ -z "$key_id" ]; then - echo "No GPG secret key imported." >&2 - exit 1 - fi - mapfile -d '' files < <(find dist -name 'bugleos-toolchain-*.tar.gz' -print0 | sort -z) if [ "${#files[@]}" -eq 0 ]; then echo "No toolchain tarballs found under dist/." >&2 @@ -286,16 +270,7 @@ jobs: fi sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS - minisign -S -s out/minisign.key -m dist/SHA256SUMS - gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ - --local-user "$key_id" --armor --detach-sign -o dist/SHA256SUMS.asc dist/SHA256SUMS - - for f in "${files[@]}"; do - minisign -S -s out/minisign.key -m "$f" - gpg --batch --yes --pinentry-mode loopback --passphrase "$GPG_PASSPHRASE" \ - --local-user "$key_id" --armor --detach-sign -o "$f.asc" "$f" - done - name: Publish GitHub Release uses: softprops/action-gh-release@v2 @@ -317,8 +292,8 @@ jobs: files: | dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz - dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig + dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.asc dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.asc From a2b56c57134f1d6d95f8dd5fa4bc1a15cd9df534 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Thu, 5 Feb 2026 08:18:21 +0100 Subject: [PATCH 15/16] Fix SLSA provenance --- .github/workflows/release.yml | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 542a0eb..5a6cf7e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -271,6 +271,9 @@ jobs: sha256sum "${files[@]}" "${sboms[@]}" > dist/SHA256SUMS minisign -S -s out/minisign.key -m dist/SHA256SUMS + for f in "${files[@]}"; do + minisign -S -s out/minisign.key -m "$f" + done - name: Publish GitHub Release uses: softprops/action-gh-release@v2 @@ -280,30 +283,32 @@ jobs: draft: false prerelease: ${{ env.PRERELEASE }} body: | - # Supported architectures: - - ## 64-bit architecture (x86_64) - [Download bugleos-toolchain-${{ env.VERSION }}-x86_64 toolchain](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz) - [Download bugleos-toolchain-${{ env.VERSION }}-x86_64 minisign](dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig) + # Supported architectures + + ## ![64-bit architecture (x86_64)](https://img.shields.io/badge/arch-x86__64-blue) + - Toolchain: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz + - Signature (minisign): https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig + + ## ![ARM64 architecture (aarch64)](https://img.shields.io/badge/arch-aarch64-green) + - Toolchain: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz + - Signature (minisign): https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig - ## ARM 64-bit architecture (aarch64) - [Download bugleos-toolchain-${{ env.VERSION }}-aarch64 toolchain](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz) - [Download bugleos-toolchain-${{ env.VERSION }}-aarch64 minisign](dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig) + ## Verification + - Public key: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/minisign.pub + - Checksums: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/SHA256SUMS + - Checksums signature: https://github.com/${{ github.repository }}/releases/download/${{ github.ref_name }}/SHA256SUMS.minisig files: | dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz - dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig - dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.minisig - dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.asc - dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz.asc + dist/**/bugleos-toolchain-${{ env.VERSION }}-aarch64.tar.gz + dist/**/bugleos-toolchain-${{ env.VERSION }}-x86_64.tar.gz.minisig dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.spdx.json dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.spdx.json dist/bugleos-toolchain-${{ env.VERSION }}-x86_64.cdx.json dist/bugleos-toolchain-${{ env.VERSION }}-aarch64.cdx.json dist/SHA256SUMS dist/SHA256SUMS.minisig - dist/SHA256SUMS.asc dist/minisign.pub provenance: @@ -313,7 +318,7 @@ jobs: actions: read id-token: write contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.10.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 with: base64-subjects: "${{ needs.hash-artifacts.outputs.base64_subjects }}" upload-assets: true From 492b16e62a5fbe527f6e94d6a9b49243a8eccb10 Mon Sep 17 00:00:00 2001 From: strombetta <12155693+strombetta@users.noreply.github.com> Date: Thu, 5 Feb 2026 08:23:48 +0100 Subject: [PATCH 16/16] Fix SLSA provenance version --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5a6cf7e..36a87c3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -318,7 +318,7 @@ jobs: actions: read id-token: write contents: write - uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v1.2.0 + uses: slsa-framework/slsa-github-generator/.github/workflows/generator_generic_slsa3.yml@v2.1.0 with: base64-subjects: "${{ needs.hash-artifacts.outputs.base64_subjects }}" upload-assets: true