Release Universal Binaries #25
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 Universal Binaries | |
| on: | |
| push: | |
| tags: | |
| - 'puniversald/v*' | |
| workflow_dispatch: | |
| inputs: | |
| version: | |
| description: 'Version tag (e.g., v1.0.0 — will be tagged as puniversald/v1.0.0)' | |
| required: true | |
| type: string | |
| prerelease: | |
| description: 'Mark as pre-release' | |
| required: false | |
| type: boolean | |
| default: false | |
| permissions: | |
| contents: write | |
| packages: write | |
| env: | |
| BINARY_NAME: puniversald | |
| PROJECT_NAME: push-universal | |
| TAG_PREFIX: puniversald/ | |
| jobs: | |
| # =========================================== | |
| # Linux Build (ubuntu) | |
| # =========================================== | |
| build-linux: | |
| runs-on: ubuntu-22.04 | |
| outputs: | |
| version: ${{ steps.version.outputs.version }} | |
| version_no_v: ${{ steps.version.outputs.version_no_v }} | |
| full_tag: ${{ steps.version.outputs.full_tag }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| INPUT_VERSION="${{ github.event.inputs.version }}" | |
| # Strip puniversald/ prefix if user supplied it | |
| INPUT_VERSION="${INPUT_VERSION#${TAG_PREFIX}}" | |
| VERSION="$INPUT_VERSION" | |
| FULL_TAG="${TAG_PREFIX}${INPUT_VERSION}" | |
| else | |
| FULL_TAG="${GITHUB_REF#refs/tags/}" | |
| VERSION="${FULL_TAG#${TAG_PREFIX}}" | |
| fi | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| echo "full_tag=$FULL_TAG" >> $GITHUB_OUTPUT | |
| echo "Building version: $VERSION (full tag: $FULL_TAG)" | |
| - 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" | |
| FULL_TAG="${{ steps.version.outputs.full_tag }}" | |
| echo "Tagging HEAD as $FULL_TAG" | |
| if git tag --list | grep -q "^${FULL_TAG}$"; then | |
| echo "Tag $FULL_TAG already exists, deleting it first" | |
| git tag -d "$FULL_TAG" || true | |
| git push --delete origin "$FULL_TAG" || true | |
| fi | |
| git tag -a "$FULL_TAG" HEAD -m "Release $FULL_TAG" | |
| git push origin "$FULL_TAG" | |
| - 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: | | |
| 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 | |
| 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 puniversald for linux/amd64 (glibc, static)..." | |
| go build \ | |
| -tags "muslc" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=puniversald -X github.com/cosmos/cosmos-sdk/version.AppName=puniversald -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/puniversald \ | |
| ./cmd/puniversald | |
| file dist/puniversald | |
| file dist/puniversald | grep "statically linked" | |
| cd dist | |
| mkdir -p bin | |
| mv puniversald bin/ | |
| tar -czvf push-universal_${VERSION_NO_V}_linux_amd64.tar.gz bin/ | |
| shasum -a 256 push-universal_${VERSION_NO_V}_linux_amd64.tar.gz > push-universal_${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 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| INPUT_VERSION="${{ github.event.inputs.version }}" | |
| INPUT_VERSION="${INPUT_VERSION#${TAG_PREFIX}}" | |
| VERSION="$INPUT_VERSION" | |
| else | |
| FULL_TAG="${GITHUB_REF#refs/tags/}" | |
| VERSION="${FULL_TAG#${TAG_PREFIX}}" | |
| fi | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| - 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: | | |
| 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 | |
| fi | |
| 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 ../../.. | |
| ls -la dkls23-rs/target/release/libgodkls* || \ | |
| (echo "ERROR: libgodkls not found." && 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 puniversald for linux/arm64 (glibc, static)..." | |
| go build \ | |
| -tags "muslc" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=puniversald -X github.com/cosmos/cosmos-sdk/version.AppName=puniversald -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/puniversald \ | |
| ./cmd/puniversald | |
| file dist/puniversald | |
| file dist/puniversald | grep "statically linked" | |
| cd dist | |
| mkdir -p bin | |
| mv puniversald bin/ | |
| tar -czvf push-universal_${VERSION_NO_V}_linux_arm64.tar.gz bin/ | |
| shasum -a 256 push-universal_${VERSION_NO_V}_linux_arm64.tar.gz > push-universal_${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 | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| INPUT_VERSION="${{ github.event.inputs.version }}" | |
| INPUT_VERSION="${INPUT_VERSION#${TAG_PREFIX}}" | |
| VERSION="$INPUT_VERSION" | |
| else | |
| FULL_TAG="${GITHUB_REF#refs/tags/}" | |
| VERSION="${FULL_TAG#${TAG_PREFIX}}" | |
| fi | |
| 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: Patch dkls23-rs hd-migration to local garbling path | |
| run: | | |
| # puniversald pulls in go-dkls (and its hd-migration dep) which is normally fetched from git; | |
| # redirect to the locally copied garbling tree so cargo doesn't need GitHub auth. | |
| 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: | | |
| # Build go-dkls from the workspace root using `-p` so the wrapper's | |
| # .cargo/config.toml (which injects Linux-only `-soname` linker flags) | |
| # stays out of scope on macOS. | |
| cd dkls23-rs | |
| cargo build -p go-dkls --release | |
| cd .. | |
| echo "Verifying libgodkls was built..." | |
| ls -la dkls23-rs/target/release/libgodkls* || \ | |
| (echo "ERROR: libgodkls not found." && find dkls23-rs/target -name "*godkls*" -type f && exit 1) | |
| - 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: | | |
| WASM_VER=$(grep "github.com/CosmWasm/wasmvm/v2" go.mod | head -1 | awk '{print $2}') | |
| echo "Wasmvm version: $WASM_VER" | |
| 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: | | |
| 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 puniversald for Apple Silicon (arm64)..." | |
| GOOS=darwin GOARCH=arm64 go build \ | |
| -tags "netgo,ledger" \ | |
| -ldflags="-s -w -X github.com/cosmos/cosmos-sdk/version.Name=puniversald -X github.com/cosmos/cosmos-sdk/version.AppName=puniversald -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/puniversald | |
| cp libwasmvm.dylib dist/ | |
| install_name_tool -change @rpath/libwasmvm.dylib @loader_path/libwasmvm.dylib dist/${BINARY_NAME}-darwin-arm64 | |
| ls -la dist/ | |
| echo "Checking dependencies..." | |
| otool -L dist/${BINARY_NAME}-darwin-arm64 || true | |
| - name: Sign Binaries | |
| env: | |
| APPLE_IDENTITY: ${{ secrets.APPLE_IDENTITY }} | |
| run: | | |
| 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 | |
| VERSION_NO_V="${VERSION#v}" | |
| 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 | |
| zip -j ${BINARY_NAME}-darwin-arm64-notarize.zip ${BINARY_NAME}-darwin-arm64 libwasmvm.dylib | |
| cd .. | |
| 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: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Get version | |
| id: version | |
| run: | | |
| if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then | |
| INPUT_VERSION="${{ github.event.inputs.version }}" | |
| INPUT_VERSION="${INPUT_VERSION#${TAG_PREFIX}}" | |
| VERSION="$INPUT_VERSION" | |
| FULL_TAG="${TAG_PREFIX}${INPUT_VERSION}" | |
| else | |
| FULL_TAG="${GITHUB_REF#refs/tags/}" | |
| VERSION="${FULL_TAG#${TAG_PREFIX}}" | |
| fi | |
| VERSION_NO_V="${VERSION#v}" | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "version_no_v=$VERSION_NO_V" >> $GITHUB_OUTPUT | |
| echo "full_tag=$FULL_TAG" >> $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 | |
| 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: | | |
| FULL_TAG="${{ steps.version.outputs.full_tag }}" | |
| COMPARE_FROM=$(git tag --sort=-version:refname | grep -E "^${TAG_PREFIX}v[0-9]+\.[0-9]+\.[0-9]+" | grep -v "^${FULL_TAG}$" | head -1) | |
| if [ -z "$COMPARE_FROM" ]; then | |
| COMPARE_FROM=$(git rev-list --max-parents=0 HEAD) | |
| fi | |
| echo "Generating changelog from $COMPARE_FROM to $FULL_TAG" | |
| { | |
| 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.full_tag }} | |
| name: Universal Client ${{ steps.version.outputs.version }} | |
| body: | | |
| ## 📦 puniversald 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: | | |
| FULL_TAG="${{ steps.version.outputs.full_tag }}" | |
| echo "Verifying release assets..." | |
| gh release view "$FULL_TAG" --json assets --jq '.assets[].name' || true | |
| env: | |
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} |