name: Pub Release on: push: tags: ["v*"] concurrency: group: release cancel-in-progress: false permissions: contents: write id-token: write # Required for cosign keyless signing via OIDC env: CARGO_TERM_COLOR: always jobs: build-release: name: Build ${{ matrix.target }} runs-on: ${{ matrix.os }} timeout-minutes: 40 strategy: fail-fast: false matrix: include: - os: ubuntu-latest target: x86_64-unknown-linux-gnu artifact: zeroclaw archive_ext: tar.gz cross_compiler: "" linker_env: "" linker: "" - os: ubuntu-latest target: aarch64-unknown-linux-gnu artifact: zeroclaw archive_ext: tar.gz cross_compiler: gcc-aarch64-linux-gnu linker_env: CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER linker: aarch64-linux-gnu-gcc - os: ubuntu-latest target: armv7-unknown-linux-gnueabihf artifact: zeroclaw archive_ext: tar.gz cross_compiler: gcc-arm-linux-gnueabihf linker_env: CARGO_TARGET_ARMV7_UNKNOWN_LINUX_GNUEABIHF_LINKER linker: arm-linux-gnueabihf-gcc - os: macos-15-intel target: x86_64-apple-darwin artifact: zeroclaw archive_ext: tar.gz cross_compiler: "" linker_env: "" linker: "" - os: macos-14 target: aarch64-apple-darwin artifact: zeroclaw archive_ext: tar.gz cross_compiler: "" linker_env: "" linker: "" - os: windows-latest target: x86_64-pc-windows-msvc artifact: zeroclaw.exe archive_ext: zip cross_compiler: "" linker_env: "" linker: "" steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - uses: dtolnay/rust-toolchain@631a55b12751854ce901bb631d5902ceb48146f7 # stable with: targets: ${{ matrix.target }} - uses: useblacksmith/rust-cache@f53e7f127245d2a269b3d90879ccf259876842d5 # v3 - name: Install cross-compilation toolchain (Linux) if: runner.os == 'Linux' && matrix.cross_compiler != '' run: | sudo apt-get update -qq sudo apt-get install -y ${{ matrix.cross_compiler }} - name: Build release env: LINKER_ENV: ${{ matrix.linker_env }} LINKER: ${{ matrix.linker }} run: | if [ -n "$LINKER_ENV" ] && [ -n "$LINKER" ]; then echo "Using linker override: $LINKER_ENV=$LINKER" export "$LINKER_ENV=$LINKER" fi cargo build --release --locked --target ${{ matrix.target }} - name: Check binary size (Unix) if: runner.os != 'Windows' run: | BIN="target/${{ matrix.target }}/release/${{ matrix.artifact }}" if [ ! -f "$BIN" ]; then echo "::error::Expected binary not found: $BIN" exit 1 fi SIZE=$(stat -f%z "$BIN" 2>/dev/null || stat -c%s "$BIN") SIZE_MB=$((SIZE / 1024 / 1024)) echo "Binary size: ${SIZE_MB}MB ($SIZE bytes)" echo "### Binary Size: ${{ matrix.target }}" >> "$GITHUB_STEP_SUMMARY" echo "- Size: ${SIZE_MB}MB ($SIZE bytes)" >> "$GITHUB_STEP_SUMMARY" if [ "$SIZE" -gt 41943040 ]; then echo "::error::Binary exceeds 40MB safeguard (${SIZE_MB}MB)" exit 1 elif [ "$SIZE" -gt 15728640 ]; then echo "::warning::Binary exceeds 15MB advisory target (${SIZE_MB}MB)" elif [ "$SIZE" -gt 5242880 ]; then echo "::warning::Binary exceeds 5MB target (${SIZE_MB}MB)" else echo "Binary size within target." fi - name: Package (Unix) if: runner.os != 'Windows' run: | cd target/${{ matrix.target }}/release tar czf ../../../zeroclaw-${{ matrix.target }}.${{ matrix.archive_ext }} ${{ matrix.artifact }} - name: Package (Windows) if: runner.os == 'Windows' run: | cd target/${{ matrix.target }}/release 7z a ../../../zeroclaw-${{ matrix.target }}.${{ matrix.archive_ext }} ${{ matrix.artifact }} - name: Upload artifact uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6 with: name: zeroclaw-${{ matrix.target }} path: zeroclaw-${{ matrix.target }}.${{ matrix.archive_ext }} retention-days: 7 publish: name: Publish Release needs: build-release runs-on: blacksmith-2vcpu-ubuntu-2404 timeout-minutes: 15 steps: - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - name: Download all artifacts uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4 with: path: artifacts - name: Install syft run: | curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sh -s -- -b /usr/local/bin - name: Generate SBOM (CycloneDX) run: | syft dir:. --source-name zeroclaw -o cyclonedx-json=artifacts/zeroclaw.cdx.json -o spdx-json=artifacts/zeroclaw.spdx.json { echo "### SBOM Generated" echo "- CycloneDX: zeroclaw.cdx.json" echo "- SPDX: zeroclaw.spdx.json" } >> "$GITHUB_STEP_SUMMARY" - name: Generate SHA256 checksums run: | cd artifacts find . -type f \( -name '*.tar.gz' -o -name '*.zip' -o -name '*.cdx.json' -o -name '*.spdx.json' \) -exec sha256sum {} + | sed 's| \./[^/]*/| |' > SHA256SUMS echo "Generated checksums:" cat SHA256SUMS - name: Install cosign uses: sigstore/cosign-installer@3454372f43399081ed03b604cb2d021dabca52bb # v3.8.2 - name: Sign artifacts with cosign (keyless) run: | for file in artifacts/**/*; do [ -f "$file" ] || continue cosign sign-blob --yes \ --oidc-issuer=https://token.actions.githubusercontent.com \ --output-signature="${file}.sig" \ --output-certificate="${file}.pem" \ "$file" done - name: Create GitHub Release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 with: generate_release_notes: true files: | artifacts/**/* artifacts/SHA256SUMS env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}