karapace/.github/workflows/release.yml
Marco Allegretti 62b9b569be fix supply chain: bump cargo-cyclonedx 0.5.7, fix SBOM generation, fix rmeta test
- Bump cargo-cyclonedx from 0.5.5 to 0.5.7 (supports lockfile v4)
- Generate SBOM for karapace-cli crate only (single predictable file)
- Fix --output-prefix → --override-filename (CLI change in 0.5.x)
- Fix rmeta tampering test: accept build failure as valid defense
  (cargo rejects corrupted .rmeta with compilation errors)
2026-02-22 20:31:08 +01:00

271 lines
10 KiB
YAML

name: Release
on:
push:
tags: ['v*']
env:
CARGO_TERM_COLOR: always
RUSTFLAGS: >-
-D warnings
--remap-path-prefix /home/runner/work=src
--remap-path-prefix /home/runner/.cargo/registry/src=crate
--remap-path-prefix /home/runner/.rustup=rustup
RUST_TOOLCHAIN: "1.93"
SOURCE_DATE_EPOCH: "0"
CARGO_INCREMENTAL: "0"
permissions:
contents: read
jobs:
build:
name: Build Release (${{ matrix.target }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- target: x86_64-unknown-linux-gnu
- target: x86_64-unknown-linux-musl
steps:
- uses: actions/checkout@v4
- uses: dtolnay/rust-toolchain@stable
with:
toolchain: ${{ env.RUST_TOOLCHAIN }}
targets: ${{ matrix.target }}
- uses: Swatinem/rust-cache@v2
with:
key: ${{ matrix.target }}
- name: Install musl-tools
if: contains(matrix.target, 'musl')
run: sudo apt-get update -qq && sudo apt-get install -y -qq musl-tools
- name: Clean before release build
run: cargo clean
- name: Build release binaries
run: cargo build --release --workspace --target ${{ matrix.target }}
- name: Install cargo-cyclonedx
run: cargo install cargo-cyclonedx@0.5.7 --locked
- name: Generate SBOM
run: |
cargo cyclonedx --manifest-path crates/karapace-cli/Cargo.toml --format json --override-filename karapace_bom
mv crates/karapace-cli/karapace_bom.json .
- name: Compute and verify checksums
run: |
cd target/${{ matrix.target }}/release
sha256sum karapace karapace-dbus > SHA256SUMS
sha256sum -c SHA256SUMS
- name: Validate SBOM
run: |
python3 -c "
import json
with open('karapace_bom.json') as f:
bom = json.load(f)
assert 'components' in bom and len(bom['components']) > 0
print(f'SBOM valid: {len(bom["components"])} components')
"
- name: Verify static linking (musl only)
if: contains(matrix.target, 'musl')
run: |
set -euo pipefail
for bin in karapace karapace-dbus; do
if ldd target/${{ matrix.target }}/release/$bin 2>&1 | grep -q 'not a dynamic executable'; then
echo "PASS: $bin is statically linked"
else
echo "FAIL: $bin is NOT statically linked"
ldd target/${{ matrix.target }}/release/$bin
exit 1
fi
done
- uses: actions/upload-artifact@v4
with:
name: release-${{ matrix.target }}
path: |
target/${{ matrix.target }}/release/karapace
target/${{ matrix.target }}/release/karapace-dbus
target/${{ matrix.target }}/release/SHA256SUMS
sign:
name: Sign Release (${{ matrix.target }})
runs-on: ubuntu-latest
needs: [build]
permissions:
id-token: write
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
suffix: gnu
- target: x86_64-unknown-linux-musl
suffix: musl
steps:
- uses: actions/checkout@v4
- uses: actions/download-artifact@v4
with:
name: release-${{ matrix.target }}
path: artifacts
- uses: sigstore/cosign-installer@v3
- name: Sign binaries
run: |
cosign sign-blob --yes \
artifacts/target/${{ matrix.target }}/release/karapace \
--output-signature artifacts/karapace-${{ matrix.suffix }}.sig \
--output-certificate artifacts/karapace-${{ matrix.suffix }}.crt
cosign sign-blob --yes \
artifacts/target/${{ matrix.target }}/release/karapace-dbus \
--output-signature artifacts/karapace-dbus-${{ matrix.suffix }}.sig \
--output-certificate artifacts/karapace-dbus-${{ matrix.suffix }}.crt
- name: Generate and sign provenance attestation
run: |
cat > artifacts/provenance-${{ matrix.suffix }}.json << EOF
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "karapace-${{ matrix.suffix }}",
"digest": {
"sha256": "$(sha256sum artifacts/target/${{ matrix.target }}/release/karapace | awk '{print $1}')"
}
},
{
"name": "karapace-dbus-${{ matrix.suffix }}",
"digest": {
"sha256": "$(sha256sum artifacts/target/${{ matrix.target }}/release/karapace-dbus | awk '{print $1}')"
}
}
],
"predicate": {
"builder": {
"id": "https://github.com/${{ github.repository }}/actions/runs/${{ github.run_id }}"
},
"buildType": "https://github.com/actions/runner",
"invocation": {
"configSource": {
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
"digest": {
"sha1": "${{ github.sha }}"
},
"entryPoint": ".github/workflows/release.yml"
}
},
"metadata": {
"buildInvocationId": "${{ github.run_id }}",
"completeness": {
"parameters": true,
"environment": true,
"materials": true
},
"reproducible": true
},
"materials": [
{
"uri": "git+https://github.com/${{ github.repository }}@${{ github.ref }}",
"digest": {
"sha1": "${{ github.sha }}"
}
}
]
}
}
EOF
cosign sign-blob --yes \
artifacts/provenance-${{ matrix.suffix }}.json \
--output-signature artifacts/provenance-${{ matrix.suffix }}.json.sig \
--output-certificate artifacts/provenance-${{ matrix.suffix }}.json.crt
- uses: actions/upload-artifact@v4
with:
name: signatures-${{ matrix.suffix }}
path: |
artifacts/*.sig
artifacts/*.crt
artifacts/provenance-${{ matrix.suffix }}.json
verify:
name: Verify Release (${{ matrix.target }})
runs-on: ubuntu-latest
needs: [sign]
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
suffix: gnu
- target: x86_64-unknown-linux-musl
suffix: musl
steps:
- uses: actions/download-artifact@v4
with:
name: release-${{ matrix.target }}
path: release
- uses: actions/download-artifact@v4
with:
name: signatures-${{ matrix.suffix }}
path: sigs
- uses: sigstore/cosign-installer@v3
- name: Verify checksums
run: |
cd release/target/${{ matrix.target }}/release
sha256sum -c SHA256SUMS
- name: Verify binary signatures
run: |
cosign verify-blob release/target/${{ matrix.target }}/release/karapace \
--signature sigs/artifacts/karapace-${{ matrix.suffix }}.sig \
--certificate sigs/artifacts/karapace-${{ matrix.suffix }}.crt \
--certificate-identity-regexp 'https://github.com/marcoallegretti/karapace' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
cosign verify-blob release/target/${{ matrix.target }}/release/karapace-dbus \
--signature sigs/artifacts/karapace-dbus-${{ matrix.suffix }}.sig \
--certificate sigs/artifacts/karapace-dbus-${{ matrix.suffix }}.crt \
--certificate-identity-regexp 'https://github.com/marcoallegretti/karapace' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
- name: Verify provenance attestation
run: |
cosign verify-blob sigs/artifacts/provenance-${{ matrix.suffix }}.json \
--signature sigs/artifacts/provenance-${{ matrix.suffix }}.json.sig \
--certificate sigs/artifacts/provenance-${{ matrix.suffix }}.json.crt \
--certificate-identity-regexp 'https://github.com/marcoallegretti/karapace' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
publish:
name: Publish GitHub Release
runs-on: ubuntu-latest
needs: [verify]
permissions:
contents: write
steps:
- uses: actions/download-artifact@v4
with:
name: release-x86_64-unknown-linux-gnu
path: release-gnu
- uses: actions/download-artifact@v4
with:
name: release-x86_64-unknown-linux-musl
path: release-musl
- uses: actions/download-artifact@v4
with:
name: signatures-gnu
path: sigs-gnu
- uses: actions/download-artifact@v4
with:
name: signatures-musl
path: sigs-musl
- name: Stage release files
run: |
mkdir -p dist
# GNU binaries (renamed with -gnu suffix)
cp release-gnu/target/x86_64-unknown-linux-gnu/release/karapace dist/karapace-linux-x86_64-gnu
cp release-gnu/target/x86_64-unknown-linux-gnu/release/karapace-dbus dist/karapace-dbus-linux-x86_64-gnu
cp release-gnu/target/x86_64-unknown-linux-gnu/release/SHA256SUMS dist/SHA256SUMS-gnu
# Musl binaries (renamed with -musl suffix)
cp release-musl/target/x86_64-unknown-linux-musl/release/karapace dist/karapace-linux-x86_64-musl
cp release-musl/target/x86_64-unknown-linux-musl/release/karapace-dbus dist/karapace-dbus-linux-x86_64-musl
cp release-musl/target/x86_64-unknown-linux-musl/release/SHA256SUMS dist/SHA256SUMS-musl
# Signatures
cp sigs-gnu/artifacts/*.sig sigs-gnu/artifacts/*.crt dist/
cp sigs-gnu/artifacts/provenance-gnu.json dist/
cp sigs-musl/artifacts/*.sig sigs-musl/artifacts/*.crt dist/
cp sigs-musl/artifacts/provenance-musl.json dist/
- name: Create release
uses: softprops/action-gh-release@v2
with:
files: dist/*