name: Release on: push: tags: - 'V*' permissions: contents: read jobs: build: name: Build runs-on: ${{ matrix.os }} strategy: matrix: include: - os: macos-latest target: release-amd64 artifact_name: binaries-amd64 - os: macos-latest target: release-arm64 artifact_name: binaries-arm64 steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4 - name: Set up Go uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 # v5 with: go-version-file: go.mod - name: Build Binaries run: | make ${{ matrix.target }} ls -l bin/ - name: Package binaries for Homebrew run: | cd bin # Package binaries into tar.gz for Homebrew resource if [[ "${{ matrix.target }}" == "release-arm64" ]]; then tar -czf binaries-darwin-arm64.tar.gz analyze-darwin-arm64 status-darwin-arm64 ls -lh binaries-darwin-arm64.tar.gz else tar -czf binaries-darwin-amd64.tar.gz analyze-darwin-amd64 status-darwin-amd64 ls -lh binaries-darwin-amd64.tar.gz fi - name: Upload artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: ${{ matrix.artifact_name }} path: bin/*-darwin-* retention-days: 1 native: name: Build Native Release runs-on: macos-latest outputs: packaging_mode: ${{ steps.mode.outputs.packaging_mode }} prerelease: ${{ steps.mode.outputs.prerelease }} steps: - name: Checkout code uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v4 - name: Derive native release version run: | echo "ATLAS_VERSION=${GITHUB_REF_NAME#V}" >> "$GITHUB_ENV" echo "ATLAS_BUILD_NUMBER=${GITHUB_RUN_NUMBER}" >> "$GITHUB_ENV" - name: Select native packaging mode id: mode env: ATLAS_RELEASE_APP_CERT_P12_BASE64: ${{ secrets.ATLAS_RELEASE_APP_CERT_P12_BASE64 }} ATLAS_RELEASE_APP_CERT_P12_PASSWORD: ${{ secrets.ATLAS_RELEASE_APP_CERT_P12_PASSWORD }} ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64: ${{ secrets.ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64 }} ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD: ${{ secrets.ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD }} ATLAS_NOTARY_KEY_ID: ${{ secrets.ATLAS_NOTARY_KEY_ID }} ATLAS_NOTARY_ISSUER_ID: ${{ secrets.ATLAS_NOTARY_ISSUER_ID }} ATLAS_NOTARY_API_KEY_BASE64: ${{ secrets.ATLAS_NOTARY_API_KEY_BASE64 }} run: | required_vars=( ATLAS_RELEASE_APP_CERT_P12_BASE64 ATLAS_RELEASE_APP_CERT_P12_PASSWORD ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64 ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD ATLAS_NOTARY_KEY_ID ATLAS_NOTARY_API_KEY_BASE64 ) missing_vars=() for name in "${required_vars[@]}"; do if [[ -z "${!name:-}" ]]; then missing_vars+=("$name") fi done if [[ ${#missing_vars[@]} -eq 0 ]]; then echo "packaging_mode=developer-id" >> "$GITHUB_OUTPUT" echo "prerelease=false" >> "$GITHUB_OUTPUT" echo "ATLAS_RELEASE_SIGNING_MODE=developer-id" >> "$GITHUB_ENV" echo "Using Developer ID release packaging" else echo "packaging_mode=development" >> "$GITHUB_OUTPUT" echo "prerelease=true" >> "$GITHUB_OUTPUT" echo "ATLAS_RELEASE_SIGNING_MODE=development" >> "$GITHUB_ENV" printf 'Falling back to development packaging; missing secrets: %s\n' "${missing_vars[*]}" fi - name: Configure release signing if: steps.mode.outputs.packaging_mode == 'developer-id' env: ATLAS_RELEASE_APP_CERT_P12_BASE64: ${{ secrets.ATLAS_RELEASE_APP_CERT_P12_BASE64 }} ATLAS_RELEASE_APP_CERT_P12_PASSWORD: ${{ secrets.ATLAS_RELEASE_APP_CERT_P12_PASSWORD }} ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64: ${{ secrets.ATLAS_RELEASE_INSTALLER_CERT_P12_BASE64 }} ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD: ${{ secrets.ATLAS_RELEASE_INSTALLER_CERT_P12_PASSWORD }} ATLAS_NOTARY_KEY_ID: ${{ secrets.ATLAS_NOTARY_KEY_ID }} ATLAS_NOTARY_ISSUER_ID: ${{ secrets.ATLAS_NOTARY_ISSUER_ID }} ATLAS_NOTARY_API_KEY_BASE64: ${{ secrets.ATLAS_NOTARY_API_KEY_BASE64 }} run: ./scripts/atlas/setup-release-signing-ci.sh - name: Provision local development signing identity if: steps.mode.outputs.packaging_mode == 'development' run: ./scripts/atlas/ensure-local-signing-identity.sh - name: Validate signing prerequisites if: steps.mode.outputs.packaging_mode == 'developer-id' run: ./scripts/atlas/signing-preflight.sh - name: Build and package Atlas native app run: ./scripts/atlas/package-native.sh - name: Verify DMG can install to the user Applications folder run: KEEP_INSTALLED_APP=1 ./scripts/atlas/verify-dmg-install.sh - name: Upload native release artifacts uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0 with: name: atlas-native-release path: | dist/native/Atlas-for-Mac.zip dist/native/Atlas-for-Mac.dmg dist/native/Atlas-for-Mac.pkg dist/native/Atlas-for-Mac.sha256 retention-days: 1 release: name: Publish Release needs: - build - native runs-on: ubuntu-latest permissions: contents: write attestations: write id-token: write steps: - name: Download all artifacts uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: path: bin pattern: binaries-* merge-multiple: true - name: Download native release artifacts uses: actions/download-artifact@70fc10c6e5e1ce46ad2ea6f2b72d43f7d47b13c3 # v8.0.0 with: name: atlas-native-release path: bin - name: Generate release body run: | if [[ "${{ needs.native.outputs.packaging_mode }}" == "development" ]]; then { echo "Native macOS assets in this tag were packaged in development mode because Developer ID release-signing credentials were not configured for this run." echo echo "These \`.zip\`, \`.dmg\`, and \`.pkg\` files are intended for internal testing or developer use. macOS Gatekeeper may require \`Open Anyway\` or a right-click \`Open\` flow before launch." } > RELEASE_BODY.md else echo "Native macOS assets in this tag were packaged in CI using Developer ID signing and notarization, then uploaded alongside the existing command-line release artifacts." > RELEASE_BODY.md fi - name: Display structure of downloaded files run: ls -R bin/ - name: Generate release checksums run: | cd bin mapfile -t release_files < <(find . -maxdepth 1 -type f -printf '%P\n' | sort) if [[ ${#release_files[@]} -eq 0 ]]; then echo "No release assets found" exit 1 fi sha256sum "${release_files[@]}" > SHA256SUMS cat SHA256SUMS - name: Generate artifact attestation uses: actions/attest-build-provenance@v4 with: subject-path: | bin/analyze-darwin-* bin/status-darwin-* bin/binaries-darwin-*.tar.gz bin/Atlas-for-Mac.zip bin/Atlas-for-Mac.dmg bin/Atlas-for-Mac.pkg bin/Atlas-for-Mac.sha256 bin/SHA256SUMS - name: Create Release uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2 if: startsWith(github.ref, 'refs/tags/') with: name: ${{ github.ref_name }} files: bin/* body_path: RELEASE_BODY.md generate_release_notes: false draft: false prerelease: ${{ needs.native.outputs.prerelease == 'true' }}