diff --git a/.github/workflows/release-universal.yml b/.github/workflows/release-universal.yml new file mode 100644 index 00000000..8652a4a9 --- /dev/null +++ b/.github/workflows/release-universal.yml @@ -0,0 +1,614 @@ +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 }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3178cdec..0b7b55b1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -10,19 +10,6 @@ on: 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 @@ -47,25 +34,9 @@ jobs: 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 @@ -97,13 +68,7 @@ jobs: 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" + echo "Tagging HEAD as $VERSION" if git tag --list | grep -q "^${VERSION}$"; then echo "Tag $VERSION already exists, deleting it first" @@ -111,7 +76,7 @@ jobs: git push --delete origin $VERSION || true fi - git tag -a $VERSION $COMMIT_REF -m "Release $VERSION" + git tag -a $VERSION HEAD -m "Release $VERSION" git push origin $VERSION - name: Set up Go @@ -209,24 +174,9 @@ jobs: 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 @@ -348,24 +298,9 @@ jobs: 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 @@ -565,24 +500,9 @@ jobs: 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 @@ -636,11 +556,7 @@ jobs: 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 + COMPARE_FROM=$(git tag --sort=-version:refname | grep -E '^v[0-9]+\.[0-9]+\.[0-9]+' | grep -v "$VERSION" | head -1) if [ -z "$COMPARE_FROM" ]; then COMPARE_FROM=$(git rev-list --max-parents=0 HEAD) fi @@ -655,6 +571,42 @@ jobs: cat changelog.md + - name: Build Cosmovisor upgrade-info JSON + id: cosmovisor + run: | + VERSION="${{ steps.version.outputs.version }}" + VERSION_NO_V="${VERSION#v}" + REPO="${{ github.repository }}" + BASE_URL="https://github.com/${REPO}/releases/download/${VERSION}" + PROJECT="${PROJECT_NAME}" + + read_hash() { + awk '{print $1}' "release/${PROJECT}_${VERSION_NO_V}_$1.tar.gz.sha256" + } + + DARWIN_ARM64_HASH=$(read_hash darwin_arm64) + LINUX_AMD64_HASH=$(read_hash linux_amd64) + LINUX_ARM64_HASH=$(read_hash linux_arm64) + + JSON=$(cat <> "$GITHUB_OUTPUT" + - name: Create GitHub Release uses: softprops/action-gh-release@v2 with: @@ -669,6 +621,14 @@ jobs: | Linux | ARM64 (aarch64) | `${{ env.PROJECT_NAME }}_*_linux_arm64.tar.gz` | | macOS | Apple Silicon (arm64) | `${{ env.PROJECT_NAME }}_*_darwin_arm64.tar.gz` | + ## 🚀 Cosmovisor upgrade-info + + Use this payload as the `--upgrade-info` argument when submitting a software-upgrade governance proposal. URLs include `?checksum=sha256:…` so cosmovisor can verify auto-downloaded binaries. + + ```json + ${{ steps.cosmovisor.outputs.json }} + ``` + ## ✅ Verification macOS binaries are code-signed and notarized by Apple.