Skip to content

Release Binaries

Release Binaries #105

Workflow file for this run

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 }}