name: "Release prb" on: push: tags: - "prb/v*" permissions: contents: "read" jobs: build-binary: name: "binary (${{ matrix.goos }}/${{ matrix.goarch }})" runs-on: "runs-on=${{ github.run_id }}/runner=4cpu-linux-x64/extras=s3-cache" permissions: contents: "read" strategy: fail-fast: false matrix: include: - { goos: linux, goarch: amd64 } - { goos: linux, goarch: arm64 } - { goos: darwin, goarch: amd64 } - { goos: darwin, goarch: arm64 } - { goos: windows, goarch: amd64 } - { goos: freebsd, goarch: amd64 } - { goos: freebsd, goarch: arm64 } - { goos: openbsd, goarch: amd64 } - { goos: openbsd, goarch: arm64 } steps: - uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v6 with: submodules: recursive - uses: "runs-on/action@d141ef83eb66d096ce8afc767e09115a65c63b60" # v2 - uses: "./.github/actions/setup" with: node: "false" - name: "Build binary" env: CGO_ENABLED: "0" GOOS: "${{ matrix.goos }}" GOARCH: "${{ matrix.goarch }}" run: | VERSION="${GITHUB_REF_NAME##*/v}" EXT="" if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi go build -ldflags "-s -w -X 'main.version=${VERSION}'" \ -gcflags="-e" -o "dist/prb${EXT}" ./cmd/prb/main.go - name: "Create archive" env: GOOS: "${{ matrix.goos }}" GOARCH: "${{ matrix.goarch }}" run: | case "$GOOS" in linux) OS="Linux" ;; darwin) OS="Darwin" ;; windows) OS="Windows" ;; freebsd) OS="Freebsd" ;; openbsd) OS="Openbsd" ;; esac case "$GOARCH" in amd64) ARCH="x86_64" ;; *) ARCH="$GOARCH" ;; esac EXT="" if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi mkdir -p archives PRB_DIR="prb_${OS}_${ARCH}" mkdir -p "staging/${PRB_DIR}" cp "dist/prb${EXT}" README.md LICENSE cmd/prb/CHANGELOG.md "staging/${PRB_DIR}/" if [ "$GOOS" = "windows" ]; then (cd staging && zip -r "../archives/${PRB_DIR}.zip" "${PRB_DIR}") else tar -czf "archives/${PRB_DIR}.tar.gz" -C staging "${PRB_DIR}" fi - uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7 with: name: "archive-${{ matrix.goos }}-${{ matrix.goarch }}" path: "archives/" retention-days: 1 github-release: name: "github-release" needs: [build-binary] runs-on: "runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/extras=s3-cache" permissions: contents: "write" id-token: "write" attestations: "write" steps: - uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v6 with: fetch-depth: 0 - uses: "runs-on/action@d141ef83eb66d096ce8afc767e09115a65c63b60" # v2 - uses: "sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6" # v4.1.2 - uses: "actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c" # v8 with: pattern: "archive-*" path: "archives" merge-multiple: true - name: "Generate checksums and sign" run: | cd archives sha256sum *.tar.gz *.zip > checksums.txt cosign sign-blob --bundle="checksums.txt.bundle" checksums.txt --yes - name: "Generate SBOM" uses: "anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610" # v0.24.0 with: path: ./cmd/prb format: cyclonedx-json output-file: sbom.json - name: "Run vulnerability scan" uses: "anchore/scan-action@e1165082ffb1fe366ebaf02d8526e7c4989ea9d2" # v7.4.0 with: sbom: "sbom.json" fail-build: true severity-cutoff: critical - name: "Attest SBOM for archives" uses: "actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e" # v4 with: subject-path: "archives/*.tar.gz, archives/*.zip" sbom-path: "sbom.json" - name: "Attest build provenance for archives" uses: "actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373" # v4 with: subject-path: "archives/*.tar.gz, archives/*.zip" - name: "Extract release notes" run: | VERSION="${GITHUB_REF_NAME##*/v}" awk -v ver="$VERSION" ' /^## \[/ { if (found) exit; if ($0 ~ "\\[" ver "\\]") found=1 } found ' cmd/prb/CHANGELOG.md > release-notes.md - name: "Create GitHub release" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | PRERELEASE_FLAG="" if echo "${GITHUB_REF_NAME}" | grep -qE '(alpha|beta|rc)'; then PRERELEASE_FLAG="--prerelease" fi gh release delete "${GITHUB_REF_NAME}" --yes 2>/dev/null || true gh release create "${GITHUB_REF_NAME}" \ --title "${GITHUB_REF_NAME}" \ --notes-file release-notes.md \ $PRERELEASE_FLAG \ archives/* sbom.json - uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7 with: name: "sbom" path: "sbom.json" retention-days: 30 homebrew: name: "homebrew" needs: [github-release] runs-on: "runs-on=${{ github.run_id }}/runner=2cpu-linux-x64/extras=s3-cache" permissions: contents: "read" steps: - uses: "runs-on/action@d141ef83eb66d096ce8afc767e09115a65c63b60" # v2 - name: "Download checksums from release" env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | gh release download "${GITHUB_REF_NAME}" \ --repo "${GITHUB_REPOSITORY}" \ --pattern "checksums.txt" - name: "Generate and publish Homebrew formula" env: GH_TOKEN: ${{ secrets.HOMEBREW_TAP_GITHUB_TOKEN }} run: | VERSION="${GITHUB_REF_NAME##*/v}" TAG="${GITHUB_REF_NAME}" BASE_URL="https://github.com/${GITHUB_REPOSITORY}/releases/download/${TAG}" DARWIN_ARM64_SHA=$(grep "prb_Darwin_arm64.tar.gz" checksums.txt | awk '{print $1}') DARWIN_X86_64_SHA=$(grep "prb_Darwin_x86_64.tar.gz" checksums.txt | awk '{print $1}') LINUX_ARM64_SHA=$(grep "prb_Linux_arm64.tar.gz" checksums.txt | awk '{print $1}') LINUX_X86_64_SHA=$(grep "prb_Linux_x86_64.tar.gz" checksums.txt | awk '{print $1}') cat > prb.rb << RUBY # typed: false # frozen_string_literal: true class Prb < Formula desc "Probo CLI" homepage "https://github.com/getprobo/probo" version "${VERSION}" license "MIT" on_macos do on_arm do url "${BASE_URL}/prb_Darwin_arm64.tar.gz" sha256 "${DARWIN_ARM64_SHA}" end on_intel do url "${BASE_URL}/prb_Darwin_x86_64.tar.gz" sha256 "${DARWIN_X86_64_SHA}" end end on_linux do on_arm do url "${BASE_URL}/prb_Linux_arm64.tar.gz" sha256 "${LINUX_ARM64_SHA}" end on_intel do url "${BASE_URL}/prb_Linux_x86_64.tar.gz" sha256 "${LINUX_X86_64_SHA}" end end def install bin.install "prb" end test do assert_match version.to_s, shell_output("#{bin}/prb --version") end end RUBY CONTENT=$(base64 -w0 prb.rb) HEAD_OID=$(gh api "repos/getprobo/homebrew-tap/git/ref/heads/main" --jq '.object.sha') gh api graphql -f query=' mutation($headline: String!, $oid: GitObjectID!, $contents: Base64String!) { createCommitOnBranch(input: { branch: { repositoryNameWithOwner: "getprobo/homebrew-tap" branchName: "main" } message: { headline: $headline } expectedHeadOid: $oid fileChanges: { additions: [{ path: "Formula/prb.rb" contents: $contents }] } }) { commit { url } } }' \ -f headline="prb ${VERSION}" \ -f oid="${HEAD_OID}" \ -f contents="${CONTENT}"