Skip to content

feat: add build verification and attestation to releases #7

feat: add build verification and attestation to releases

feat: add build verification and attestation to releases #7

Workflow file for this run

name: Release
on:
push:
tags:
- 'v*'
workflow_dispatch:
inputs:
version:
description: 'Release version (e.g., v1.0.0)'
required: false
type: string
permissions:
contents: write
attestations: write
id-token: write
jobs:
build-release:
runs-on: macos-26
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Swift
uses: maartene/setup-swift@main
with:
swift-version: '6.2'
- name: Build Release
run: swift build -c release
- name: Generate SHA256 Checksum
id: checksum
run: |
shasum -a 256 .build/release/container-compose | awk '{print $1}' > .build/release/container-compose.sha256
echo "sha256=$(cat .build/release/container-compose.sha256)" >> $GITHUB_OUTPUT
echo "Binary SHA256: $(cat .build/release/container-compose.sha256)"
- name: Attest Build Provenance
uses: actions/attest-build-provenance@v1
with:
subject-path: '.build/release/container-compose'
- name: Generate Verification Instructions
run: |
cat > .build/release/VERIFICATION.md << 'EOF'
# Binary Verification
## SHA256 Checksum
```
${{ steps.checksum.outputs.sha256 }} container-compose
```
## Verify Download
```bash
# macOS/Linux
shasum -a 256 ./container-compose | grep ${{ steps.checksum.outputs.sha256 }}
# Should output matching hash
```
## Build Reproducibility
This binary was built with:
- macOS 26.x
- Xcode 26.3
- Swift 6.2
- Apple Silicon (arm64)
## Attestation
This release includes cryptographic attestation via GitHub Actions.
Verify attestation: `gh attestation verify container-compose --owner explicitcontextualunderstanding`
## Source Code
Tagged commit: ${{ github.sha }}
Compare: https://github.com/${{ github.repository }}/compare/${{ github.ref_name }}
EOF
- name: Create Release with Verification
if: github.event_name == 'push'
uses: softprops/action-gh-release@v1
with:
name: ${{ github.ref_name }}
draft: false
prerelease: ${{ contains(github.ref_name, 'alpha') || contains(github.ref_name, 'beta') }}
files: |
.build/release/container-compose
.build/release/container-compose.sha256
.build/release/VERIFICATION.md
body: |
## Verification
**SHA256:** `${{ steps.checksum.outputs.sha256 }}`
Verify your download:
```bash
shasum -a 256 ./container-compose | grep ${{ steps.checksum.outputs.sha256 }}
```
**Build Attestation:** This release includes cryptographic attestation.
```bash
gh attestation verify container-compose --owner explicitcontextualunderstanding
```
See VERIFICATION.md for full details.
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Upload to Release (workflow_dispatch)
if: github.event_name == 'workflow_dispatch'
run: |
# Create release if it doesn't exist
VERSION="${{ github.inputs.version || 'latest' }}"
TAG="v${VERSION#v}"
# Create or get release ID
RELEASE_ID=$(gh api repos/${{ github.repository }}/releases/tags/$TAG --jq '.id' 2>/dev/null || echo "")
if [ -z "$RELEASE_ID" ]; then
RELEASE_ID=$(gh api repos/${{ github.repository }}/releases -X POST \
--field tag_name="$TAG" \
--field name="$TAG" \
--field draft=false \
--field body="## Verification
**SHA256:** \`${{ steps.checksum.outputs.sha256 }}\`
Verify your download:
\`\`\`bash
shasum -a 256 ./container-compose | grep ${{ steps.checksum.outputs.sha256 }}
\`\`\`
See full verification instructions in VERIFICATION.md" \
--jq '.id')
fi
# Upload assets
gh api repos/${{ github.repository }}/releases/$RELEASE_ID/assets \
-F "file=@.build/release/container-compose" \
-F "name=container-compose"
gh api repos/${{ github.repository }}/releases/$RELEASE_ID/assets \
-F "file=@.build/release/container-compose.sha256" \
-F "name=container-compose.sha256"
gh api repos/${{ github.repository }}/releases/$RELEASE_ID/assets \
-F "file=@.build/release/VERIFICATION.md" \
-F "name=VERIFICATION.md"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}