Release Binaries #105
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Release Binaries | |
| on: | |
| push: | |
| tags: | |
| - 'v*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version tag (e.g., v1.0.0)' | |
| required: true | |
| type: string | |
| branch: | |
| description: 'Branch to build from (default: main)' | |
| required: false | |
| type: string | |
| default: 'main' | |
| commit_id: | |
| description: 'Specific commit SHA to build (overrides branch if set)' | |
| required: false | |
| type: string | |
| compare_from: | |
| description: 'Compare from tag (optional, auto-detects if empty)' | |
| required: false | |
| type: string | |
| prerelease: | |
| description: 'Mark as pre-release' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| BINARY_NAME: pchaind | |
| PROJECT_NAME: push-chain | |
| jobs: | |
| # =========================================== | |
| # Linux Build (ubuntu) | |
| # =========================================== | |
| build-linux: | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| steps: | |
| - name: Resolve checkout ref | |
| id: resolve-ref | |
| run: | | |
| COMMIT_ID="${{ github.event.inputs.commit_id }}" | |
| BRANCH="${{ github.event.inputs.branch }}" | |
| # Strip vcs.revision= prefix if accidentally included | |
| COMMIT_ID="${COMMIT_ID#vcs.revision=}" | |
| if [ -n "$COMMIT_ID" ]; then | |
| echo "ref=$COMMIT_ID" >> $GITHUB_OUTPUT | |
| elif [ -n "$BRANCH" ]; then | |
| echo "ref=$BRANCH" >> $GITHUB_OUTPUT | |
| else | |
| echo "ref=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.resolve-ref.outputs.ref || '' }} | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| fi | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Setup dkls23-rs | |
| uses: ./.github/actions/setup-dkls23 | |
| with: | |
| ci_token: ${{ secrets.CI_DKLS_GARBLING }} | |
| - name: Copy dkls23-rs and garbling into build context | |
| run: | | |
| cp -r ../dkls23-rs ./dkls23-rs | |
| cp -r ../garbling ./garbling | |
| sed -i 's|go-wrapper => ../dkls23-rs/wrapper/go-wrappers|go-wrapper => ./dkls23-rs/wrapper/go-wrappers|' go.mod | |
| - name: Create and push version tag | |
| if: github.event_name == 'workflow_dispatch' | |
| run: | | |
| git config --local user.email "action@github.com" | |
| git config --local user.name "GitHub Action" | |
| VERSION=${{ steps.version.outputs.version }} | |
| COMMIT_REF="${{ github.event.inputs.commit_id }}" | |
| # Strip vcs.revision= prefix if accidentally included | |
| COMMIT_REF="${COMMIT_REF#vcs.revision=}" | |
| if [ -z "$COMMIT_REF" ]; then | |
| COMMIT_REF="HEAD" | |
| fi | |
| echo "Tagging commit: $COMMIT_REF" | |
| if git tag --list | grep -q "^${VERSION}$"; then | |
| echo "Tag $VERSION already exists, deleting it first" | |
| git tag -d $VERSION || true | |
| git push --delete origin $VERSION || true | |
| fi | |
| git tag -a $VERSION $COMMIT_REF -m "Release $VERSION" | |
| git push origin $VERSION | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.23.8' | |
| cache: true | |
| - name: Set up Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Patch dkls23-rs for static linking | |
| run: | | |
| # Add staticlib to crate-type for go-dkls crate (produces .a file for static linking) | |
| if grep -q 'crate-type = \["cdylib", "rlib"\]' dkls23-rs/wrapper/go-dkls/Cargo.toml; then | |
| sed -i 's/crate-type = \["cdylib", "rlib"\]/crate-type = ["staticlib", "cdylib", "rlib"]/' dkls23-rs/wrapper/go-dkls/Cargo.toml | |
| echo "Added staticlib to crate-type" | |
| fi | |
| # Fix hd-migration to use local garbling path instead of git | |
| find dkls23-rs -name "Cargo.toml" -type f -exec grep -l "hd-migration" {} \; | while read -r file; do | |
| sed -i 's|hd-migration = { git = "https://github.com/pushchain/garbling.git", branch = "main" }|hd-migration = { path = "../garbling/crates/hd-migration" }|g' "$file" | |
| sed -i 's|hd-migration = { git = "https://github.com/pushchain/garbling.git", branch = "main"}|hd-migration = { path = "../garbling/crates/hd-migration" }|g' "$file" | |
| done | |
| - name: Build dkls23-rs dependency | |
| run: | | |
| cd dkls23-rs/wrapper/go-dkls | |
| cargo build --release | |
| cd ../../.. | |
| echo "Verifying libgodkls was built..." | |
| ls -la dkls23-rs/target/release/libgodkls* || \ | |
| (echo "ERROR: libgodkls not found. Searching..." && find dkls23-rs/target -name "*godkls*" -type f && exit 1) | |
| - name: Download libwasmvm_muslc | |
| run: | | |
| WASM_VER=$(grep "github.com/CosmWasm/wasmvm/v2" go.mod | head -1 | awk '{print $2}') | |
| echo "Downloading wasmvm static library version: $WASM_VER" | |
| sudo wget -O /usr/lib/libwasmvm_muslc.x86_64.a \ | |
| "https://github.com/CosmWasm/wasmvm/releases/download/${WASM_VER}/libwasmvm_muslc.x86_64.a" | |
| sudo ln -sf /usr/lib/libwasmvm_muslc.x86_64.a /usr/lib/libwasmvm_muslc.a | |
| ls -la /usr/lib/libwasmvm_muslc* | |
| - name: Patch chain ID for production | |
| run: | | |
| sed -i 's/"localchain_9000-1"/"push_42101-1"/' app/app.go | |
| grep -n "ChainID" app/app.go | |
| - name: Build Linux binary | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| VERSION_NO_V="${VERSION#v}" | |
| COMMIT=$(git rev-parse HEAD) | |
| mkdir -p dist | |
| export GOTOOLCHAIN=local | |
| export CGO_ENABLED=1 | |
| export CGO_LDFLAGS="-L$(pwd)/dkls23-rs/target/release -lm" | |
| echo "Building pchaind for linux/amd64 (glibc, static)..." | |
| go build \ | |
| -tags "muslc" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=pchain -X github.com/cosmos/cosmos-sdk/version.AppName=pchaind -X github.com/cosmos/cosmos-sdk/version.Version=${VERSION} -X github.com/cosmos/cosmos-sdk/version.Commit=${COMMIT} -X github.com/cosmos/cosmos-sdk/version.BuildTags=muslc -linkmode=external -extldflags '-Wl,-z,muldefs -static'" \ | |
| -trimpath \ | |
| -o dist/pchaind \ | |
| ./cmd/pchaind | |
| # Verify static linking | |
| file dist/pchaind | |
| file dist/pchaind | grep "statically linked" | |
| # Package with bin/ structure for Cosmovisor compatibility | |
| cd dist | |
| mkdir -p bin | |
| mv pchaind bin/ | |
| tar -czvf push-chain_${VERSION_NO_V}_linux_amd64.tar.gz bin/ | |
| shasum -a 256 push-chain_${VERSION_NO_V}_linux_amd64.tar.gz > push-chain_${VERSION_NO_V}_linux_amd64.tar.gz.sha256 | |
| rm -rf bin | |
| - name: Upload Linux artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-binaries | |
| path: | | |
| dist/*.tar.gz | |
| dist/*.sha256 | |
| retention-days: 1 | |
| # =========================================== | |
| # Linux ARM64 Build | |
| # =========================================== | |
| build-linux-arm64: | |
| runs-on: ubuntu-22.04-arm | |
| needs: build-linux # Wait for version tag to be created | |
| steps: | |
| - name: Resolve checkout ref | |
| id: resolve-ref | |
| run: | | |
| COMMIT_ID="${{ github.event.inputs.commit_id }}" | |
| BRANCH="${{ github.event.inputs.branch }}" | |
| COMMIT_ID="${COMMIT_ID#vcs.revision=}" | |
| if [ -n "$COMMIT_ID" ]; then | |
| echo "ref=$COMMIT_ID" >> $GITHUB_OUTPUT | |
| elif [ -n "$BRANCH" ]; then | |
| echo "ref=$BRANCH" >> $GITHUB_OUTPUT | |
| else | |
| echo "ref=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.resolve-ref.outputs.ref || '' }} | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| fi | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION" | |
| - name: Setup dkls23-rs | |
| uses: ./.github/actions/setup-dkls23 | |
| with: | |
| ci_token: ${{ secrets.CI_DKLS_GARBLING }} | |
| - name: Copy dkls23-rs and garbling into build context | |
| run: | | |
| cp -r ../dkls23-rs ./dkls23-rs | |
| cp -r ../garbling ./garbling | |
| sed -i 's|go-wrapper => ../dkls23-rs/wrapper/go-wrappers|go-wrapper => ./dkls23-rs/wrapper/go-wrappers|' go.mod | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.23.8' | |
| cache: true | |
| - name: Set up Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Patch dkls23-rs for static linking | |
| run: | | |
| # Add staticlib to crate-type for go-dkls crate (produces .a file for static linking) | |
| if grep -q 'crate-type = \["cdylib", "rlib"\]' dkls23-rs/wrapper/go-dkls/Cargo.toml; then | |
| sed -i 's/crate-type = \["cdylib", "rlib"\]/crate-type = ["staticlib", "cdylib", "rlib"]/' dkls23-rs/wrapper/go-dkls/Cargo.toml | |
| echo "Added staticlib to crate-type" | |
| fi | |
| # Fix hd-migration to use local garbling path instead of git | |
| find dkls23-rs -name "Cargo.toml" -type f -exec grep -l "hd-migration" {} \; | while read -r file; do | |
| sed -i 's|hd-migration = { git = "https://github.com/pushchain/garbling.git", branch = "main" }|hd-migration = { path = "../garbling/crates/hd-migration" }|g' "$file" | |
| sed -i 's|hd-migration = { git = "https://github.com/pushchain/garbling.git", branch = "main"}|hd-migration = { path = "../garbling/crates/hd-migration" }|g' "$file" | |
| done | |
| - name: Build dkls23-rs dependency | |
| run: | | |
| cd dkls23-rs/wrapper/go-dkls | |
| cargo build --release | |
| cd ../../.. | |
| echo "Verifying libgodkls was built..." | |
| ls -la dkls23-rs/target/release/libgodkls* || \ | |
| (echo "ERROR: libgodkls not found. Searching..." && find dkls23-rs/target -name "*godkls*" -type f && exit 1) | |
| - name: Download libwasmvm_muslc | |
| run: | | |
| WASM_VER=$(grep "github.com/CosmWasm/wasmvm/v2" go.mod | head -1 | awk '{print $2}') | |
| echo "Downloading wasmvm static library version: $WASM_VER" | |
| sudo wget -O /usr/lib/libwasmvm_muslc.aarch64.a \ | |
| "https://github.com/CosmWasm/wasmvm/releases/download/${WASM_VER}/libwasmvm_muslc.aarch64.a" | |
| sudo ln -sf /usr/lib/libwasmvm_muslc.aarch64.a /usr/lib/libwasmvm_muslc.a | |
| ls -la /usr/lib/libwasmvm_muslc* | |
| - name: Patch chain ID for production | |
| run: | | |
| sed -i 's/"localchain_9000-1"/"push_42101-1"/' app/app.go | |
| grep -n "ChainID" app/app.go | |
| - name: Build Linux ARM64 binary | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| VERSION_NO_V="${VERSION#v}" | |
| COMMIT=$(git rev-parse HEAD) | |
| mkdir -p dist | |
| export GOTOOLCHAIN=local | |
| export CGO_ENABLED=1 | |
| export CGO_LDFLAGS="-L$(pwd)/dkls23-rs/target/release -lm" | |
| echo "Building pchaind for linux/arm64 (glibc, static)..." | |
| go build \ | |
| -tags "muslc" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=pchain -X github.com/cosmos/cosmos-sdk/version.AppName=pchaind -X github.com/cosmos/cosmos-sdk/version.Version=${VERSION} -X github.com/cosmos/cosmos-sdk/version.Commit=${COMMIT} -X github.com/cosmos/cosmos-sdk/version.BuildTags=muslc -linkmode=external -extldflags '-Wl,-z,muldefs -static'" \ | |
| -trimpath \ | |
| -o dist/pchaind \ | |
| ./cmd/pchaind | |
| # Verify static linking | |
| file dist/pchaind | |
| file dist/pchaind | grep "statically linked" | |
| # Package with bin/ structure for Cosmovisor compatibility | |
| cd dist | |
| mkdir -p bin | |
| mv pchaind bin/ | |
| tar -czvf push-chain_${VERSION_NO_V}_linux_arm64.tar.gz bin/ | |
| shasum -a 256 push-chain_${VERSION_NO_V}_linux_arm64.tar.gz > push-chain_${VERSION_NO_V}_linux_arm64.tar.gz.sha256 | |
| rm -rf bin | |
| - name: Upload Linux ARM64 artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: linux-arm64-binaries | |
| path: | | |
| dist/*.tar.gz | |
| dist/*.sha256 | |
| retention-days: 1 | |
| # =========================================== | |
| # macOS Build (Apple Silicon) | |
| # =========================================== | |
| build-macos: | |
| runs-on: macos-latest | |
| needs: build-linux # Wait for version tag to be created | |
| steps: | |
| - name: Resolve checkout ref | |
| id: resolve-ref | |
| run: | | |
| COMMIT_ID="${{ github.event.inputs.commit_id }}" | |
| BRANCH="${{ github.event.inputs.branch }}" | |
| COMMIT_ID="${COMMIT_ID#vcs.revision=}" | |
| if [ -n "$COMMIT_ID" ]; then | |
| echo "ref=$COMMIT_ID" >> $GITHUB_OUTPUT | |
| elif [ -n "$BRANCH" ]; then | |
| echo "ref=$BRANCH" >> $GITHUB_OUTPUT | |
| else | |
| echo "ref=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.resolve-ref.outputs.ref || '' }} | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| fi | |
| # Strip 'v' prefix for file naming | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION (stripped: $VERSION_NO_V)" | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: '1.23.8' | |
| cache: true | |
| - name: Set up Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Setup dkls23-rs | |
| uses: ./.github/actions/setup-dkls23 | |
| with: | |
| ci_token: ${{ secrets.CI_DKLS_GARBLING }} | |
| - name: Copy dkls23-rs and garbling into build context | |
| run: | | |
| rsync -a --exclude='ci/template' ../dkls23-rs/ ./dkls23-rs/ | |
| rsync -a ../garbling/ ./garbling/ | |
| sed -i '' 's|go-wrapper => ../dkls23-rs/wrapper/go-wrappers|go-wrapper => ./dkls23-rs/wrapper/go-wrappers|' go.mod | |
| - name: Build dkls23-rs dependency | |
| run: | | |
| cd dkls23-rs | |
| cargo build --release | |
| - name: Import Code Signing Certificate | |
| env: | |
| APPLE_CERTIFICATE_BASE64: ${{ secrets.APPLE_CERTIFICATE_BASE64 }} | |
| APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} | |
| run: | | |
| CERTIFICATE_PATH=$RUNNER_TEMP/certificate.p12 | |
| KEYCHAIN_PATH=$RUNNER_TEMP/app-signing.keychain-db | |
| KEYCHAIN_PASSWORD=$(openssl rand -base64 32) | |
| echo "$APPLE_CERTIFICATE_BASE64" | base64 --decode > "$CERTIFICATE_PATH" | |
| security create-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| security set-keychain-settings -lut 21600 "$KEYCHAIN_PATH" | |
| security unlock-keychain -p "$KEYCHAIN_PASSWORD" "$KEYCHAIN_PATH" | |
| security import "$CERTIFICATE_PATH" \ | |
| -P "$APPLE_CERTIFICATE_PASSWORD" \ | |
| -A \ | |
| -t cert \ | |
| -f pkcs12 \ | |
| -k "$KEYCHAIN_PATH" | |
| security list-keychain -d user -s "$KEYCHAIN_PATH" | |
| security set-key-partition-list \ | |
| -S apple-tool:,apple:,codesign: \ | |
| -s \ | |
| -k "$KEYCHAIN_PASSWORD" \ | |
| "$KEYCHAIN_PATH" | |
| echo "Available signing identities:" | |
| security find-identity -v -p codesigning "$KEYCHAIN_PATH" | |
| - name: Download libwasmvm | |
| run: | | |
| # Get wasmvm version from go.mod | |
| WASM_VER=$(grep "github.com/CosmWasm/wasmvm/v2" go.mod | head -1 | awk '{print $2}') | |
| echo "Wasmvm version: $WASM_VER" | |
| # Download dylib for bundling with release | |
| curl -L -o libwasmvm.dylib \ | |
| "https://github.com/CosmWasm/wasmvm/releases/download/${WASM_VER}/libwasmvm.dylib" | |
| ls -la libwasmvm.dylib | |
| - name: Patch chain ID for production | |
| run: | | |
| sed -i '' 's/"localchain_9000-1"/"push_42101-1"/' app/app.go | |
| grep -n "ChainID" app/app.go | |
| - name: Build Mac Binary (ARM64 only - native build) | |
| run: | | |
| # Note: GitHub macos-latest is ARM64, can't cross-compile for AMD64 with CGO | |
| # We only build ARM64 (Apple Silicon) which covers most modern Macs | |
| mkdir -p dist | |
| VERSION=${{ steps.version.outputs.version }} | |
| export CGO_ENABLED=1 | |
| export CGO_LDFLAGS="-L$(pwd)/dkls23-rs/target/release" | |
| COMMIT=$(git rev-parse HEAD) | |
| echo "Building for Apple Silicon (arm64)..." | |
| GOOS=darwin GOARCH=arm64 go build \ | |
| -tags "netgo,ledger" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=pchain -X github.com/cosmos/cosmos-sdk/version.AppName=pchaind -X github.com/cosmos/cosmos-sdk/version.Version=${VERSION} -X github.com/cosmos/cosmos-sdk/version.Commit=${COMMIT} -X github.com/cosmos/cosmos-sdk/version.BuildTags=netgo,ledger" \ | |
| -o dist/${BINARY_NAME}-darwin-arm64 \ | |
| ./cmd/pchaind | |
| # Copy libwasmvm.dylib to dist for bundling | |
| cp libwasmvm.dylib dist/ | |
| # Fix rpath to look in same directory as binary (before signing!) | |
| install_name_tool -change @rpath/libwasmvm.dylib @loader_path/libwasmvm.dylib dist/${BINARY_NAME}-darwin-arm64 | |
| ls -la dist/ | |
| # Verify dependencies | |
| echo "Checking dependencies..." | |
| otool -L dist/${BINARY_NAME}-darwin-arm64 || true | |
| - name: Sign Binaries | |
| env: | |
| APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} | |
| run: | | |
| # Sign both the binary and the dylib | |
| codesign --force --options runtime --timestamp --sign "$APPLE_IDENTITY" dist/${BINARY_NAME}-darwin-arm64 | |
| codesign --force --options runtime --timestamp --sign "$APPLE_IDENTITY" dist/libwasmvm.dylib | |
| echo "Verifying signatures..." | |
| codesign -dv --verbose=2 dist/${BINARY_NAME}-darwin-arm64 | |
| codesign -dv --verbose=2 dist/libwasmvm.dylib | |
| - name: Notarize Binary | |
| timeout-minutes: 15 | |
| continue-on-error: true | |
| env: | |
| APPLE_ID: ${{ secrets.APPLE_ID }} | |
| APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} | |
| APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| xcrun notarytool store-credentials "notary-profile" \ | |
| --apple-id "$APPLE_ID" \ | |
| --team-id "$APPLE_TEAM_ID" \ | |
| --password "$APPLE_APP_PASSWORD" | |
| cd dist | |
| # Use version without 'v' prefix for file naming | |
| VERSION_NO_V="${VERSION#v}" | |
| # Create archive with bin/ directory structure for Cosmovisor compatibility | |
| # Cosmovisor extracts binary to upgrades/<name>/bin/ but leaves other files in parent | |
| # By including both in bin/, they'll end up in the same directory | |
| mkdir -p bin | |
| cp ${BINARY_NAME}-darwin-arm64 bin/${BINARY_NAME} | |
| cp libwasmvm.dylib bin/ | |
| tar -czvf ${PROJECT_NAME}_${VERSION_NO_V}_darwin_arm64.tar.gz bin/ | |
| rm -rf bin | |
| # For notarization, use flat structure (zip handles differently) | |
| zip -j ${BINARY_NAME}-darwin-arm64-notarize.zip ${BINARY_NAME}-darwin-arm64 libwasmvm.dylib | |
| cd .. | |
| # Notarize | |
| xcrun notarytool submit dist/${BINARY_NAME}-darwin-arm64-notarize.zip \ | |
| --keychain-profile "notary-profile" --wait | |
| rm -f dist/*-notarize.zip | |
| - name: Create Checksums | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| VERSION_NO_V="${VERSION#v}" | |
| cd dist | |
| shasum -a 256 ${PROJECT_NAME}_${VERSION_NO_V}_darwin_arm64.tar.gz > ${PROJECT_NAME}_${VERSION_NO_V}_darwin_arm64.tar.gz.sha256 | |
| ls -la | |
| - name: Upload macOS artifacts | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: macos-binaries | |
| path: | | |
| dist/*.tar.gz | |
| dist/*.sha256 | |
| retention-days: 1 | |
| # =========================================== | |
| # Create Unified Release | |
| # =========================================== | |
| create-release: | |
| runs-on: ubuntu-latest | |
| needs: [build-linux, build-linux-arm64, build-macos] | |
| steps: | |
| - name: Resolve checkout ref | |
| id: resolve-ref | |
| run: | | |
| COMMIT_ID="${{ github.event.inputs.commit_id }}" | |
| BRANCH="${{ github.event.inputs.branch }}" | |
| COMMIT_ID="${COMMIT_ID#vcs.revision=}" | |
| if [ -n "$COMMIT_ID" ]; then | |
| echo "ref=$COMMIT_ID" >> $GITHUB_OUTPUT | |
| elif [ -n "$BRANCH" ]; then | |
| echo "ref=$BRANCH" >> $GITHUB_OUTPUT | |
| else | |
| echo "ref=" >> $GITHUB_OUTPUT | |
| fi | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| ref: ${{ steps.resolve-ref.outputs.ref || '' }} | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| VERSION="${{ github.event.inputs.version }}" | |
| else | |
| VERSION="${GITHUB_REF#refs/tags/}" | |
| fi | |
| # Strip 'v' prefix for file naming | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| - name: Download Linux artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: linux-binaries | |
| path: dist/linux | |
| - name: Download Linux ARM64 artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: linux-arm64-binaries | |
| path: dist/linux-arm64 | |
| - name: Download macOS artifacts | |
| uses: actions/download-artifact@v4 | |
| with: | |
| name: macos-binaries | |
| path: dist/macos | |
| - name: Prepare release assets | |
| run: | | |
| mkdir -p release | |
| # Copy all artifacts to release folder | |
| cp dist/linux/*.tar.gz release/ 2>/dev/null || true | |
| cp dist/linux/*.sha256 release/ 2>/dev/null || true | |
| cp dist/linux-arm64/*.tar.gz release/ 2>/dev/null || true | |
| cp dist/linux-arm64/*.sha256 release/ 2>/dev/null || true | |
| cp dist/macos/*.tar.gz release/ 2>/dev/null || true | |
| cp dist/macos/*.sha256 release/ 2>/dev/null || true | |
| echo "Release assets:" | |
| ls -la release/ | |
| - name: Generate changelog | |
| id: changelog | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| # Use provided compare_from or auto-detect previous tag | |
| COMPARE_FROM="${{ github.event.inputs.compare_from }}" | |
| if [ -z "$COMPARE_FROM" ]; then | |
| COMPARE_FROM=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | grep -v "$VERSION" | head -1) | |
| fi | |
| if [ -z "$COMPARE_FROM" ]; then | |
| COMPARE_FROM=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| echo "Generating changelog from $COMPARE_FROM to $VERSION" | |
| { | |
| echo "## What's Changed" | |
| echo "" | |
| git log ${COMPARE_FROM}..HEAD --pretty=format:"- %s" | head -30 | |
| } > changelog.md | |
| cat changelog.md | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| tag_name: ${{ steps.version.outputs.version }} | |
| name: Release ${{ steps.version.outputs.version }} | |
| body: | | |
| ## 📦 Binaries | |
| | Platform | Architecture | File | | |
| |----------|--------------|------| | |
| | Linux | AMD64 (x86_64) | `${{ env.PROJECT_NAME }}_*_linux_amd64.tar.gz` | | |
| | Linux | ARM64 (aarch64) | `${{ env.PROJECT_NAME }}_*_linux_arm64.tar.gz` | | |
| | macOS | Apple Silicon (arm64) | `${{ env.PROJECT_NAME }}_*_darwin_arm64.tar.gz` | | |
| ## ✅ Verification | |
| macOS binaries are code-signed and notarized by Apple. | |
| Verify checksums using the `.sha256` files. | |
| draft: false | |
| prerelease: ${{ github.event.inputs.prerelease || false }} | |
| files: release/* | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| continue-on-error: true | |
| - name: Verify Release | |
| run: | | |
| VERSION=${{ steps.version.outputs.version }} | |
| echo "Verifying release assets..." | |
| gh release view $VERSION --json assets --jq '.assets[].name' || true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |