Skip to content

Release

Release #10

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: read # Minimum required for security scan
jobs:
# Security gate: must pass zizmor scan before building release
security-scan:
name: Security Scan (zizmor)
runs-on: ubuntu-latest
outputs:
critical_count: ${{ steps.zizmor.outputs.critical_count }}
high_count: ${{ steps.zizmor.outputs.high_count }}
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- name: Install zizmor
run: |
curl -sSfL https://github.com/woodruffw/zizmor/releases/download/v1.23.1/zizmor-v1.23.1-x86_64-unknown-linux-gnu.tar.gz | tar xz
chmod +x zizmor
sudo mv zizmor /usr/local/bin/
- name: Run zizmor scan
id: zizmor
run: |
zizmor --format json .github/workflows/ > zizmor-results.json || true
CRITICAL_COUNT=$(jq '[.[] | select(.severity == "critical")] | length' zizmor-results.json 2>/dev/null || echo "0")
HIGH_COUNT=$(jq '[.[] | select(.severity == "high")] | length' zizmor-results.json 2>/dev/null || echo "0")
echo "critical_count=$CRITICAL_COUNT" >> $GITHUB_OUTPUT
echo "high_count=$HIGH_COUNT" >> $GITHUB_OUTPUT
echo "zizmor findings:"
echo " Critical: $CRITICAL_COUNT"
echo " High: $HIGH_COUNT"
- name: Block release on critical findings
if: steps.zizmor.outputs.critical_count != '0'
run: |
echo "::error::CRITICAL: zizmor found ${{ steps.zizmor.outputs.critical_count }} critical security issues. Release blocked."
echo "::error::Run 'zizmor .github/workflows/' locally to see details."
exit 1
- name: Warn on high findings
if: steps.zizmor.outputs.high_count != '0'
run: |
echo "::warning::zizmor found ${{ steps.zizmor.outputs.high_count }} high severity issues. Review recommended."
build-release:
name: Build and Release
needs: security-scan
if: needs.security-scan.outputs.critical_count == '0'
runs-on: macos-26
permissions:
contents: write
attestations: write
id-token: write
steps:
- name: Checkout code
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false
- 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@f504d1c46aced50f0eb9e7f117c7e8de6b07e2c7 # v1.4.3
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@c1a018d8a49526b35624d8b4709e296ce22f2fd2 # v2.2.0
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: |
VERSION="${{ inputs.version || 'latest' }}"
TAG="v${VERSION#v}"
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\n\n**SHA256:** \`${{ steps.checksum.outputs.sha256 }}\`\n\nVerify your download:\n\`\`\`bash\nshasum -a 256 ./container-compose | grep ${{ steps.checksum.outputs.sha256 }}\n\`\`\`\n\nSee full verification instructions in VERIFICATION.md" \
--jq '.id')
fi
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 }}