name: "Release probo-agent" on: push: tags: - "probo-agent/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: windows, goarch: amd64 } - { goos: windows, goarch: arm64 } - { goos: freebsd, goarch: amd64 } - { goos: freebsd, 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/probo-agent${EXT}" ./cmd/probo-agent - name: "Create archive" env: GOOS: "${{ matrix.goos }}" GOARCH: "${{ matrix.goarch }}" run: | case "$GOOS" in linux) OS="Linux" ;; windows) OS="Windows" ;; freebsd) OS="Freebsd" ;; esac case "$GOARCH" in amd64) ARCH="x86_64" ;; *) ARCH="$GOARCH" ;; esac EXT="" if [ "$GOOS" = "windows" ]; then EXT=".exe"; fi mkdir -p archives AGENT_DIR="probo-agent_${OS}_${ARCH}" mkdir -p "staging/${AGENT_DIR}" cp "dist/probo-agent${EXT}" README.md LICENSE "staging/${AGENT_DIR}/" if [ -f cmd/probo-agent/CHANGELOG.md ]; then cp cmd/probo-agent/CHANGELOG.md "staging/${AGENT_DIR}/" fi if [ "$GOOS" = "windows" ]; then (cd staging && zip -r "../archives/${AGENT_DIR}.zip" "${AGENT_DIR}") else tar -czf "archives/${AGENT_DIR}.tar.gz" -C staging "${AGENT_DIR}" fi - uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7 with: name: "archive-${{ matrix.goos }}-${{ matrix.goarch }}" path: "archives/" retention-days: 1 build-macos: name: "macos (darwin pkg + darwin archives)" runs-on: "macos-26" permissions: contents: "read" steps: - uses: "actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0" # v6 with: submodules: recursive - uses: "./.github/actions/setup" with: node: "false" - name: "Select Xcode version" run: | sudo xcode-select -s /Applications/Xcode_26.2.app/Contents/Developer xcode-select -p swift --version - name: "Import signing certificate" env: CERTIFICATE_BASE64: "${{ secrets.APPLE_CERTIFICATE }}" CERTIFICATE_PASSWORD: "${{ secrets.APPLE_CERTIFICATE_PASSWORD }}" KEYCHAIN_PASSWORD: "${{ secrets.KEYCHAIN_PASSWORD }}" run: | KEYCHAIN_PATH="$RUNNER_TEMP/app-signing.keychain-db" security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" echo "$CERTIFICATE_BASE64" | base64 --decode > certificate.p12 security import certificate.p12 -P "$CERTIFICATE_PASSWORD" -A -t cert -f pkcs12 -k "$KEYCHAIN_PATH" security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" security list-keychain -d user -s "$KEYCHAIN_PATH" rm certificate.p12 - name: "Build CGO darwin binaries and darwin pkg" env: CGO_ENABLED: "1" CODESIGN_IDENTITY: "${{ secrets.CODESIGN_IDENTITY }}" INSTALLER_IDENTITY: "${{ secrets.INSTALLER_IDENTITY }}" APPLE_ID: "${{ secrets.APPLE_ID }}" APPLE_ID_PASSWORD: "${{ secrets.APPLE_ID_PASSWORD }}" APPLE_TEAM_ID: "${{ secrets.APPLE_TEAM_ID }}" run: | set -euo pipefail VERSION="${GITHUB_REF_NAME##*/v}" LDFLAGS="-s -w -X 'main.version=${VERSION}'" mkdir -p dist archives staging export COPYFILE_DISABLE=1 GOOS=darwin GOARCH=arm64 go build -ldflags "${LDFLAGS}" \ -gcflags="-e" -o dist/probo-agent_arm64 ./cmd/probo-agent GOOS=darwin GOARCH=amd64 go build -ldflags "${LDFLAGS}" \ -gcflags="-e" -o dist/probo-agent_amd64 ./cmd/probo-agent lipo -create \ dist/probo-agent_arm64 \ dist/probo-agent_amd64 \ -output dist/probo-agent_universal for pair in "arm64:arm64" "amd64:x86_64"; do GOARCH="${pair%%:*}" ARCH="${pair##*:}" AGENT_DIR="probo-agent_Darwin_${ARCH}" mkdir -p "staging/${AGENT_DIR}" cp "dist/probo-agent_${GOARCH}" "staging/${AGENT_DIR}/probo-agent" cp README.md LICENSE "staging/${AGENT_DIR}/" if [ -f cmd/probo-agent/CHANGELOG.md ]; then cp cmd/probo-agent/CHANGELOG.md "staging/${AGENT_DIR}/" fi # Match the PKG payload signing identity so auto-update does # not replace a Developer ID binary with an ad-hoc one (which # multiplies macOS Background Activity entries). codesign --force --options runtime --timestamp \ --identifier com.probo.agent \ --sign "${CODESIGN_IDENTITY}" "staging/${AGENT_DIR}/probo-agent" codesign --verify --verbose=2 "staging/${AGENT_DIR}/probo-agent" tar -czf "archives/${AGENT_DIR}.tar.gz" -C staging "${AGENT_DIR}" done chmod +x cmd/probo-agent/installer/macos/build.sh \ cmd/probo-agent/installer/macos/scripts/preinstall \ cmd/probo-agent/installer/macos/scripts/postinstall cmd/probo-agent/installer/macos/build.sh \ --binary dist/probo-agent_universal \ --version "${VERSION}" \ --output "archives/probo-agent_${VERSION}_darwin.pkg" - uses: "actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a" # v7 with: name: "archive-darwin" path: "archives/" retention-days: 1 github-release: name: "github-release" needs: [build-binary, build-macos] 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 *.pkg > checksums.txt cosign sign-blob --bundle="checksums.txt.bundle" checksums.txt --yes - name: "Inject release checksums into install.sh" run: | TAG="${GITHUB_REF_NAME}" cp cmd/probo-agent/installer/install.sh archives/install.sh sed -i "s|^RELEASE_TAG=\"__PROBO_AGENT_RELEASE_TAG__\"|RELEASE_TAG=\"${TAG}\"|" archives/install.sh grep 'probo-agent_.*\.tar\.gz' archives/checksums.txt > archives/probo-agent-checksums.txt awk ' /# __PROBO_AGENT_CHECKSUMS_BEGIN__/ { print while ((getline line < "archives/probo-agent-checksums.txt") > 0) print line skip = 1 next } /# __PROBO_AGENT_CHECKSUMS_END__/ { skip = 0 print next } !skip { print } END { if (skip) { print "install.sh injection failed: missing # __PROBO_AGENT_CHECKSUMS_END__ marker" > "/dev/stderr" exit 1 } } ' archives/install.sh > archives/install.sh.tmp mv archives/install.sh.tmp archives/install.sh - name: "Generate SBOM" uses: "anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610" # v0.24.0 with: path: ./cmd/probo-agent 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, archives/*.pkg" 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, archives/*.pkg" - name: "Extract release notes" run: | VERSION="${GITHUB_REF_NAME##*/v}" if [ -f cmd/probo-agent/CHANGELOG.md ]; then awk -v ver="$VERSION" ' /^## \[/ { if (found) exit; if ($0 ~ "\\[" ver "\\]") found=1 } found ' cmd/probo-agent/CHANGELOG.md > release-notes.md else echo "probo-agent ${VERSION}" > release-notes.md fi - 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