Release #10
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 }} |