docs(README): visual refresh + supply-chain badges (#171) #5
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-darwin | |
| # darwin/arm64 release on a macos-14 runner. Attaches binaries to the | |
| # existing GitHub Release created by release-go.yml (which only builds | |
| # linux). Runs after the linux release lands so the target Release | |
| # already exists. | |
| # | |
| # Why a separate workflow: | |
| # - release-go.yml runs on ubuntu-latest. CGO + kuzudb won't | |
| # cross-compile cleanly to darwin from linux. | |
| # - macos-14 runners are arm64 (M1+); cross-compile to darwin/arm64 | |
| # happens via native CC = clang. | |
| # - The two workflows publish to the same tag → same Release. | |
| on: | |
| push: | |
| tags: | |
| - 'v*.*.*' | |
| workflow_dispatch: | |
| inputs: | |
| tag: | |
| description: 'Tag to release (e.g. v0.3.0). Release must already exist.' | |
| required: true | |
| permissions: | |
| contents: write | |
| id-token: write # Sigstore keyless via GitHub OIDC | |
| attestations: write | |
| # Pass the input/ref to the shell via env vars (not inline `${{ }}` | |
| # interpolation) — Semgrep `yaml.github-actions.security.run-shell-injection` | |
| # rule. inputs.tag for workflow_dispatch; GITHUB_REF_NAME for tag pushes. | |
| env: | |
| TAG: ${{ github.event.inputs.tag || github.ref_name }} | |
| jobs: | |
| release-darwin: | |
| name: release (darwin / arm64) | |
| runs-on: macos-14 | |
| steps: | |
| - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6.4.0 | |
| with: | |
| go-version: '1.25.10' | |
| cache: true | |
| cache-dependency-path: go.sum | |
| - name: Build darwin/arm64 binary | |
| env: | |
| CGO_ENABLED: '1' | |
| GOOS: darwin | |
| GOARCH: arm64 | |
| run: | | |
| VERSION="${TAG#v}" | |
| go build \ | |
| -trimpath \ | |
| -ldflags "-s -w \ | |
| -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Version=${VERSION}' \ | |
| -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Commit=$(git rev-parse --short HEAD)' \ | |
| -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Date=$(date -u +%Y-%m-%dT%H:%M:%SZ)' \ | |
| -X 'github.com/randomcodespace/codeiq/internal/buildinfo.Dirty=false'" \ | |
| -o codeiq ./cmd/codeiq | |
| - name: Package archive | |
| run: | | |
| VERSION="${TAG#v}" | |
| ARCHIVE_DIR="codeiq_${VERSION}_darwin_arm64" | |
| mkdir -p "${ARCHIVE_DIR}" | |
| cp codeiq "${ARCHIVE_DIR}/" | |
| cp LICENSE "${ARCHIVE_DIR}/" 2>/dev/null || true | |
| cp README.md "${ARCHIVE_DIR}/" 2>/dev/null || true | |
| cp CHANGELOG.md "${ARCHIVE_DIR}/" 2>/dev/null || true | |
| tar czf "${ARCHIVE_DIR}.tar.gz" "${ARCHIVE_DIR}" | |
| - name: Install Syft (SBOM) | |
| uses: anchore/sbom-action/download-syft@e22c389904149dbc22b58101806040fa8d37a610 # v0.24.0 | |
| - name: Generate SBOM | |
| run: | | |
| VERSION="${TAG#v}" | |
| ARCHIVE="codeiq_${VERSION}_darwin_arm64.tar.gz" | |
| syft "$ARCHIVE" --output spdx-json="${ARCHIVE}.sbom.spdx.json" | |
| - name: Install Cosign (signing) | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| - name: Sign archive (Sigstore keyless, bundle format) | |
| run: | | |
| VERSION="${TAG#v}" | |
| ARCHIVE="codeiq_${VERSION}_darwin_arm64.tar.gz" | |
| cosign sign-blob \ | |
| --yes \ | |
| --bundle "${ARCHIVE}.cosign.bundle" \ | |
| "$ARCHIVE" | |
| - name: Upload to GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| REPO: ${{ github.repository }} | |
| run: | | |
| VERSION="${TAG#v}" | |
| # release-go.yml fires on the same tag push and creates the | |
| # Release via goreleaser. With CGO + Kuzu + cosign + SBOM the | |
| # full pipeline typically lands a Release in 4–8 minutes. We | |
| # poll for up to 15 minutes (30 × 30s) and early-bail if the | |
| # upstream release-go run for this tag already concluded as | |
| # failed / cancelled / timed_out so this job's failure message | |
| # is actionable rather than "timeout after 15m". | |
| MAX_RETRIES=30 | |
| SLEEP_SECS=30 | |
| go_run_failed=0 | |
| for i in $(seq 1 "$MAX_RETRIES"); do | |
| if gh release view "$TAG" --repo "$REPO" >/dev/null 2>&1; then | |
| echo "Release $TAG visible after $((i-1)) wait cycles." | |
| gh release upload "$TAG" --repo "$REPO" \ | |
| "codeiq_${VERSION}_darwin_arm64.tar.gz" \ | |
| "codeiq_${VERSION}_darwin_arm64.tar.gz.sbom.spdx.json" \ | |
| "codeiq_${VERSION}_darwin_arm64.tar.gz.cosign.bundle" \ | |
| --clobber | |
| exit 0 | |
| fi | |
| go_status=$(gh run list --repo "$REPO" \ | |
| --workflow release-go.yml \ | |
| --event push \ | |
| --branch "$TAG" \ | |
| --limit 1 \ | |
| --json conclusion,status 2>/dev/null || echo '[]') | |
| conclusion=$(printf '%s' "$go_status" | jq -r '.[0].conclusion // ""') | |
| status=$(printf '%s' "$go_status" | jq -r '.[0].status // ""') | |
| case "$conclusion" in | |
| failure|cancelled|timed_out) | |
| go_run_failed=1 | |
| echo "::error::release-go.yml for $TAG ended with conclusion=$conclusion — bailing" | |
| break | |
| ;; | |
| esac | |
| echo "Release $TAG not yet visible (release-go status=${status:-unknown} conclusion=${conclusion:-pending}); waiting ${SLEEP_SECS}s ($i/$MAX_RETRIES)..." | |
| sleep "$SLEEP_SECS" | |
| done | |
| if [ "$go_run_failed" = "1" ]; then | |
| echo "::error::release-go.yml failed for $TAG; this darwin job cannot proceed" | |
| else | |
| echo "::error::Release $TAG never appeared after $((MAX_RETRIES * SLEEP_SECS))s" | |
| fi | |
| exit 1 | |
| - name: Attest darwin archive (build provenance) | |
| uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 | |
| with: | |
| subject-path: 'codeiq_*_darwin_arm64.tar.gz' |