Skip to content

Publish Release

Publish Release #30

name: Publish Release
on:
workflow_dispatch:
inputs:
release_tag:
description: "Release tag to publish (e.g. v29.0.1). Defaults to github.ref_name."
required: false
type: string
release: # triggered by release event
types: [published]
# Notice:
# ref: https://docs.github.com/en/webhooks/webhook-events-and-payloads#release
# - "published" fires for both full releases and pre-releases
concurrency: # With concurrency control: Only the latest workflow run executes, previous runs get cancelled
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: write
jobs:
resolve-tag:
name: Resolve Release Tag
runs-on: ubuntu-latest
outputs:
tag: ${{ steps.tag.outputs.tag }}
is_rc: ${{ steps.tag.outputs.is_rc }}
steps:
- name: Determine release tag
id: tag
run: |
TAG="${RELEASE_TAG_INPUT:-${RELEASE_TAG_EVENT:-${REF_NAME}}}"
echo "tag=${TAG}" >> "$GITHUB_OUTPUT"
if [[ "$TAG" == *-rc* ]]; then
echo "is_rc=true" >> "$GITHUB_OUTPUT"
else
echo "is_rc=false" >> "$GITHUB_OUTPUT"
fi
env:
RELEASE_TAG_INPUT: ${{ inputs.release_tag }}
RELEASE_TAG_EVENT: ${{ github.event.release.tag_name }}
REF_NAME: ${{ github.ref_name }}
publish-fury:
name: Publish to Fury
needs: resolve-tag
runs-on: ubicloud-standard-2
steps:
- name: Checkout
uses: actions/checkout@v5
with:
fetch-depth: 0
- name: Set Go Version
run: sed -En 's/^go (.*)$/GO_VERSION=\1/p' go.mod >> $GITHUB_ENV
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Download release assets
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ needs.resolve-tag.outputs.tag }}
run: |
mkdir -p dist
gh release download "$RELEASE_TAG" \
--repo ${{ github.repository }} \
--dir dist \
--pattern 'xiond*'
- name: Prepare dist layout
run: |
# goreleaser prebuilt expects: dist/xiond_<os>_<arch>_<variant>/bin/xiond-<os>-<arch>
# Release assets are tarballs containing a 'xiond' binary
declare -A VARIANTS=(
["linux_amd64"]="v1"
["linux_arm64"]="v8.0"
["darwin_amd64"]="v1"
["darwin_arm64"]="v8.0"
)
for platform in linux_amd64 linux_arm64 darwin_amd64 darwin_arm64; do
os="${platform%%_*}"
arch="${platform##*_}"
variant="${VARIANTS[$platform]}"
tarball=$(ls dist/xiond_*_${platform}.tar.gz 2>/dev/null | head -1)
if [ -z "$tarball" ]; then
echo "⚠️ No tarball found for $platform, skipping"
continue
fi
target_dir="dist/xiond_${platform}_${variant}/bin"
mkdir -p "$target_dir"
# Extract and rename the binary
tar xzf "$tarball" -C "$target_dir"
if [ -f "$target_dir/xiond" ]; then
mv "$target_dir/xiond" "$target_dir/xiond-${os}-${arch}"
echo "✅ $platform: $target_dir/xiond-${os}-${arch}"
else
echo "❌ $platform: xiond binary not found in tarball"
ls -la "$target_dir"
fi
done
- name: Import package signing GPG key
id: import_pkg_gpg
uses: crazy-max/ghaction-import-gpg@v6
with:
gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }}
passphrase: ${{ secrets.GPG_PASSPHRASE }}
git_user_signingkey: true
git_commit_gpgsign: true
- name: Save GPG and RSA keys
run: |
echo "${{ secrets.GPG_PRIVATE_KEY }}" > /home/runner/.gnupg/sign.asc
echo "${{ secrets.PEM_PRIVATE_KEY }}" > /home/runner/.gnupg/sign.pem
- name: Install syft
uses: anchore/sbom-action/download-syft@v0
- name: Purge existing Fury packages (idempotent re-runs)
env:
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
RELEASE_TAG: ${{ needs.resolve-tag.outputs.tag }}
run: |
VERSION="${RELEASE_TAG#v}"
ACCOUNT="burnt"
for fmt in deb rpm apk; do
echo "Deleting xiond ${VERSION} (${fmt}) from Fury if it exists..."
curl -sf -X DELETE \
-H "Authorization: Bearer ${FURY_TOKEN}" \
"https://push.fury.io/api/v1/repos/${ACCOUNT}/packages/${fmt}/xiond/versions/${VERSION}" \
&& echo " ✅ Deleted ${fmt}" \
|| echo " ⏭️ Not found or already removed (${fmt})"
done
- name: Run GoReleaser (Fury only)
continue-on-error: true
uses: goreleaser/goreleaser-action@v6
env:
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HOMEBREW_TAP_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
RELEASE_OWNER: ${{ github.repository_owner }}
RELEASE_REPO: xion
SKIP_GITHUB_RELEASE: "true"
GPG_KEY_ID: ${{ steps.import_pkg_gpg.outputs.keyid }}
GPG_KEY_PATH: /home/runner/.gnupg/sign.asc
GPG_FINGERPRINT: ${{ steps.import_pkg_gpg.outputs.fingerprint }}
GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
NFPM_PASSPHRASE: ${{ secrets.GPG_PASSPHRASE }}
PEM_KEY_PATH: /home/runner/.gnupg/sign.pem
with:
distribution: goreleaser-pro
version: "~> v2"
args: release --config .goreleaser/release.yaml --skip=announce,validate
verify-installers:
name: Verify Package Installers
needs: publish-fury
uses: ./.github/workflows/verify-installers.yaml
secrets: inherit
# Downstream triggers — dispatch and wait for completion
trigger-types:
name: Trigger Types
needs: resolve-tag
if: github.repository == 'burnt-labs/xion'
runs-on: ubuntu-latest
steps:
- name: Trigger and wait for xion-types release
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
TAG_NAME: ${{ needs.resolve-tag.outputs.tag }}
run: |
REPO=burnt-labs/xion-types
gh workflow run release.yaml --repo "$REPO" -f "release_tag=${TAG_NAME}"
sleep 5
RUN_ID=$(gh run list --repo "$REPO" --workflow release.yaml --limit 1 --json databaseId --jq '.[0].databaseId')
echo "::notice::Downstream run: https://github.com/${REPO}/actions/runs/${RUN_ID}"
if ! gh run watch "$RUN_ID" --repo "$REPO" --exit-status; then
echo "::group::Downstream logs"
gh run view "$RUN_ID" --repo "$REPO" --log-failed 2>/dev/null || gh run view "$RUN_ID" --repo "$REPO" --log
echo "::endgroup::"
exit 1
fi
update-chain-registry:
name: Update Chain Registry
needs: resolve-tag
if: github.repository == 'burnt-labs/xion'
runs-on: ubuntu-latest
steps:
- name: Dispatch and wait for xion-assets update
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
TAG_NAME: ${{ needs.resolve-tag.outputs.tag }}
run: |
REPO=burnt-labs/xion-assets
EVENT_TYPE=$( [[ "$TAG_NAME" == *-rc* ]] && echo "xion-assets-testnet-release-trigger" || echo "xion-assets-mainnet-release-trigger" )
WORKFLOW=$( [[ "$TAG_NAME" == *-rc* ]] && echo "update-testnet-chain-registry.yaml" || echo "update-mainnet-chain-registry.yaml" )
gh api "repos/${REPO}/dispatches" \
-f "event_type=${EVENT_TYPE}" \
-f "client_payload[tag_name]=${TAG_NAME}"
sleep 5
RUN_ID=$(gh run list --repo "$REPO" --workflow "$WORKFLOW" --limit 1 --json databaseId --jq '.[0].databaseId')
echo "::notice::Downstream run: https://github.com/${REPO}/actions/runs/${RUN_ID}"
if ! gh run watch "$RUN_ID" --repo "$REPO" --exit-status; then
echo "::group::Downstream logs"
gh run view "$RUN_ID" --repo "$REPO" --log-failed 2>/dev/null || gh run view "$RUN_ID" --repo "$REPO" --log
echo "::endgroup::"
exit 1
fi
upgrade-network:
name: Network Upgrade PR
needs: resolve-tag
if: github.repository == 'burnt-labs/xion'
runs-on: ubuntu-latest
steps:
- name: Trigger and wait for upgrade workflow
env:
GH_TOKEN: ${{ secrets.HOMEBREW_TAP_TOKEN }}
TAG_NAME: ${{ needs.resolve-tag.outputs.tag }}
IS_RC: ${{ needs.resolve-tag.outputs.is_rc }}
run: |
if [ "$IS_RC" = "true" ]; then
REPO="burnt-labs/xion-testnet-2"
else
REPO="burnt-labs/xion-mainnet-1"
fi
gh workflow run create-release.yml --repo "$REPO" -f "release_tag=${TAG_NAME}"
sleep 5
RUN_ID=$(gh run list --repo "$REPO" --workflow create-release.yml --limit 1 --json databaseId --jq '.[0].databaseId')
echo "::notice::Downstream run: https://github.com/${REPO}/actions/runs/${RUN_ID}"
if ! gh run watch "$RUN_ID" --repo "$REPO" --exit-status; then
echo "::group::Downstream logs"
gh run view "$RUN_ID" --repo "$REPO" --log-failed 2>/dev/null || gh run view "$RUN_ID" --repo "$REPO" --log
echo "::endgroup::"
exit 1
fi