From 2816c4abc826cdd098abe9841784db807921a13e Mon Sep 17 00:00:00 2001 From: Amit Kumar Date: Thu, 23 Apr 2026 05:11:48 +0000 Subject: [PATCH] =?UTF-8?q?ci(release):=20switch=20to=20goreleaser=20(scor?= =?UTF-8?q?ecard=20Packaging=20=E2=86=92=20detected)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Swaps softprops/action-gh-release for goreleaser/goreleaser-action, which is what scorecard's Packaging check recognises. Keeps the matrix build (CGO + sqlite-vec needs native hosts for darwin-arm64) by feeding binaries into goreleaser's prebuilt builder. goreleaser handles: - archives (binary, no wrapper) - checksums (SHA256SUMS) - cosign signing (same keyless Sigstore as before) - GitHub release + auto-generated changelog Workflow still: - computes bump (workflow_dispatch input) - builds UI once, binaries in matrix - emits SLSA build provenance (attest-build-provenance v4.1.0) - uploads provenance bundle to the release Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/release.yml | 115 +++++++++++++++------------------- .goreleaser.yaml | 69 ++++++++++++++++++++ 2 files changed, 121 insertions(+), 63 deletions(-) create mode 100644 .goreleaser.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 68a642f..cb3f503 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,12 +1,8 @@ name: release -# Manually-triggered stable release. Pick bump (patch/minor/major); -# the next vX.Y.Z tag is computed from the latest stable tag. -# -# Beta auto-tagging was removed: the scorecard Signed-Releases check -# ignores prereleases, and most users download the latest stable tag. -# Tag pushes are not a trigger so the workflow cannot recurse on its -# own tag. +# Manually-triggered stable release via goreleaser. Pick bump +# (patch/minor/major); the next vX.Y.Z tag is computed from the +# latest stable tag. on: workflow_dispatch: inputs: @@ -92,7 +88,7 @@ jobs: if-no-files-found: error build: - name: build ${{ matrix.suffix }} + name: build ${{ matrix.goos }}-${{ matrix.goarch }} needs: [tag, ui] strategy: fail-fast: false @@ -101,11 +97,9 @@ jobs: - runner: ubuntu-latest goos: linux goarch: amd64 - suffix: linux-amd64 - runner: macos-latest goos: darwin goarch: arm64 - suffix: darwin-arm64 runs-on: ${{ matrix.runner }} permissions: contents: read @@ -126,7 +120,6 @@ jobs: path: ui/dist - name: Build binary - id: build run: | set -eu tag="${{ needs.tag.outputs.tag }}" @@ -134,69 +127,76 @@ jobs: date="$(date -u +%Y-%m-%dT%H:%M:%SZ)" pkg="github.com/RandomCodeSpace/docsiq/cmd" ldflags="-s -w -X ${pkg}.Version=${tag} -X ${pkg}.Commit=${sha} -X ${pkg}.Date=${date}" - out="docsiq-${tag}-${{ matrix.suffix }}" - go build -tags sqlite_fts5 -trimpath -ldflags="${ldflags}" -o "${out}" ./ - echo "binary=${out}" >> "$GITHUB_OUTPUT" + go build -tags sqlite_fts5 -trimpath -ldflags="${ldflags}" -o docsiq ./ - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 with: - name: binary-${{ matrix.suffix }} - path: ${{ steps.build.outputs.binary }} + name: binary-${{ matrix.goos }}-${{ matrix.goarch }} + path: docsiq retention-days: 1 if-no-files-found: error release: - name: sign + publish + name: goreleaser needs: [tag, build] runs-on: ubuntu-latest permissions: contents: write - id-token: write # required for cosign keyless signing - attestations: write # required for actions/attest-build-provenance + id-token: write # cosign keyless + attestations: write # SLSA provenance steps: - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 with: fetch-depth: 0 - - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + - uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 with: - pattern: binary-* - merge-multiple: true - path: dist/ + go-version-file: go.mod - uses: sigstore/cosign-installer@cad07c2e89fa2edd6e2d7bab4c1aa38e53f76003 # v4.1.1 with: - # Pin v2.x — v3 changed sign-blob defaults to emit a Sigstore - # bundle alongside, and our --output-signature/--output-certificate - # flags aren't compatible with that new behaviour. Revisit v3 once - # we're ready to switch to bundle-based attestations. + # v2.x — v3 broke our sign-blob flag compatibility. cosign-release: 'v2.6.3' - - name: Sign binaries + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8 + with: + pattern: binary-* + path: downloaded/ + + - name: Lay out prebuilt/ for goreleaser run: | set -eu - cd dist - for f in docsiq-*; do - case "$f" in *.sig|*.pem|SHA256SUMS*) continue ;; esac - cosign sign-blob --yes \ - --output-signature "${f}.sig" \ - --output-certificate "${f}.pem" \ - "$f" + mkdir -p prebuilt + for dir in downloaded/binary-*; do + rest=$(basename "$dir" | sed 's/^binary-//') + goos="${rest%-*}" + goarch="${rest##*-}" + target_dir="prebuilt/docsiq_${goos}_${goarch}" + mkdir -p "$target_dir" + cp "$dir/docsiq" "$target_dir/docsiq" + chmod +x "$target_dir/docsiq" done + ls -R prebuilt/ - - name: Generate SHA256SUMS (+ signature) + - name: Create + push tag + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eu - cd dist - sha256sum docsiq-* > SHA256SUMS - cosign sign-blob --yes \ - --output-signature SHA256SUMS.sig \ - --output-certificate SHA256SUMS.pem \ - SHA256SUMS - - # SLSA build provenance — scorecard's Signed-Releases check asks - # for in-toto attestations alongside the cosign sigs. The bundle - # covers both binaries and SHA256SUMS. + tag="${{ needs.tag.outputs.tag }}" + git tag "$tag" + git push origin "$tag" + + - name: Run goreleaser + uses: goreleaser/goreleaser-action@e24998b8b67b290c2fa8b7c14fcfa7de2c5c9b8c # v7.1.0 + with: + distribution: goreleaser + version: 'v2.15.4' + args: release --clean + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + GORELEASER_CURRENT_TAG: ${{ needs.tag.outputs.tag }} + - name: Generate SLSA build provenance id: attest uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0 @@ -206,22 +206,11 @@ jobs: dist/docsiq-*-darwin-arm64 dist/SHA256SUMS - - name: Copy attestation into dist + - name: Upload provenance to release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -eu - cp "${{ steps.attest.outputs.bundle-path }}" \ - dist/docsiq-${{ needs.tag.outputs.tag }}.intoto.jsonl - - # softprops/action-gh-release is the pattern scorecard's Packaging - # check recognises, replacing our ad-hoc `gh release create`. - # Creates the tag on the triggering SHA when it doesn't yet exist. - - name: Create GitHub release - uses: softprops/action-gh-release@b4309332981a82ec1c5618f44dd2e27cc8bfbfda # v3.0.0 - with: - tag_name: ${{ needs.tag.outputs.tag }} - name: ${{ needs.tag.outputs.tag }} - target_commitish: ${{ github.sha }} - generate_release_notes: true - make_latest: 'true' - files: | - dist/* + tag="${{ needs.tag.outputs.tag }}" + cp "${{ steps.attest.outputs.bundle-path }}" "docsiq-${tag}.intoto.jsonl" + gh release upload "$tag" "docsiq-${tag}.intoto.jsonl" diff --git a/.goreleaser.yaml b/.goreleaser.yaml new file mode 100644 index 0000000..8938b23 --- /dev/null +++ b/.goreleaser.yaml @@ -0,0 +1,69 @@ +# goreleaser config — https://goreleaser.com +# +# We build docsiq natively on each target OS matrix job (linux-amd64 +# on ubuntu-latest, darwin-arm64 on macos-latest) because CGO + +# sqlite-vec doesn't cross-compile cleanly. The matrix jobs upload +# each binary, and this config picks them up via `builder: prebuilt`. +version: 2 + +project_name: docsiq + +builds: + - id: docsiq + builder: prebuilt + goos: [linux, darwin] + goarch: [amd64, arm64] + targets: + - linux_amd64 + - darwin_arm64 + prebuilt: + path: 'prebuilt/docsiq_{{ .Os }}_{{ .Arch }}/docsiq' + +archives: + - formats: + - binary + name_template: 'docsiq-{{ .Tag }}-{{ .Os }}-{{ .Arch }}' + +checksum: + name_template: SHA256SUMS + algorithm: sha256 + +signs: + - cmd: cosign + stdin: 'y' + artifacts: all + signature: '${artifact}.sig' + certificate: '${artifact}.pem' + args: + - sign-blob + - --yes + - --output-signature=${signature} + - --output-certificate=${certificate} + - ${artifact} + +release: + name_template: '{{ .Tag }}' + make_latest: 'true' + footer: | + ### Verify + + All artifacts are signed with [cosign](https://github.com/sigstore/cosign) keyless via Sigstore. + + ```sh + cosign verify-blob \ + --certificate-identity-regexp 'https://github.com/RandomCodeSpace/docsiq/\.github/workflows/release\.yml.*' \ + --certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \ + --certificate docsiq-{{ .Tag }}-linux-amd64.pem \ + --signature docsiq-{{ .Tag }}-linux-amd64.sig \ + docsiq-{{ .Tag }}-linux-amd64 + ``` + +changelog: + use: github + sort: asc + filters: + exclude: + - '^ci:' + - '^docs:' + - '^test:' + - '^chore:'