Skip to content

Release

Release #164

Workflow file for this run

name: Release
on:
push:
tags:
- "v*"
workflow_dispatch:
inputs:
draft-release:
default: false
description: "Draft Release"
required: false
type: boolean
build-docker:
default: false
description: "Build Docker"
required: false
type: boolean
build-linux:
default: true
description: "Build Linux"
required: false
type: boolean
build-mac:
default: true
description: "Build Mac"
required: false
type: boolean
features:
default: ''
description: "Binary Compilation Features"
options:
- ''
- 'redact-sensitive'
required: false
type: choice
jobs:
extract-version:
name: Extract version
runs-on: warp-ubuntu-2404-x64-2x
outputs:
VERSION: ${{ steps.extract_version.outputs.VERSION }}
steps:
- name: Extract version
id: extract_version
run: |
if [[ "${GITHUB_REF_TYPE}" == "tag" ]]; then
VERSION="${GITHUB_REF#refs/tags/}"
else
VERSION="$(echo ${GITHUB_SHA} | cut -c1-7)"
fi
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
echo "${VERSION}"
echo "### Version: \`${VERSION}\`" >> $GITHUB_STEP_SUMMARY
echo "| | |" >> $GITHUB_STEP_SUMMARY
echo "| ------------------- | ---------------------- |" >> $GITHUB_STEP_SUMMARY
echo "| \`GITHUB_REF_TYPE\` | \`${GITHUB_REF_TYPE}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`GITHUB_REF_NAME\` | \`${GITHUB_REF_NAME}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`GITHUB_REF\` | \`${GITHUB_REF}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`GITHUB_SHA\` | \`${GITHUB_SHA}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`VERSION\` | \`${VERSION}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`BUILD_LINUX\` | \`${{ github.event.inputs.build-linux || 'true' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`BUILD_MAC\` | \`${{ github.event.inputs.build-mac || 'true' }}\` |" >> $GITHUB_STEP_SUMMARY
echo "| \`FEATURES\` | \`${{ github.event.inputs.features || 'none' }}\` |" >> $GITHUB_STEP_SUMMARY
build-binary:
name: Build binary (${{ matrix.target }})
needs: extract-version
# Always run - build-linux and build-mac control what actually gets built
runs-on: ${{ matrix.runner }}
permissions:
contents: write
packages: write
strategy:
matrix:
include:
- target: x86_64-unknown-linux-gnu
runner: warp-ubuntu-latest-x64-32x
profile: reproducible
platform: linux
features: ${{ github.event.inputs.features || '' }}
- target: aarch64-apple-darwin
runner: warp-macos-14-arm64-6x
profile: release
platform: mac
features: ${{ github.event.inputs.features || '' }}
steps:
- name: Check platform match
id: platform-check
shell: bash
run: |
# For tag pushes, build both platforms
if [[ "${{ github.event_name }}" == "push" ]]; then
echo "skip=false" >> $GITHUB_OUTPUT
echo "Building for platform: ${{ matrix.platform }} (tag push builds both)"
exit 0
fi
# For manual dispatch, check if platform is enabled
if [[ "${{ matrix.platform }}" == "linux" && "${{ github.event.inputs.build-linux }}" != "true" ]]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "Skipping: Linux build not enabled"
exit 0
fi
if [[ "${{ matrix.platform }}" == "mac" && "${{ github.event.inputs.build-mac }}" != "true" ]]; then
echo "skip=true" >> $GITHUB_OUTPUT
echo "Skipping: Mac build not enabled"
exit 0
fi
echo "skip=false" >> $GITHUB_OUTPUT
echo "Building for platform: ${{ matrix.platform }}"
- uses: actions/checkout@v4
if: steps.platform-check.outputs.skip != 'true'
# Linux: Use Docker for reproducible builds
- name: Set up Docker Buildx
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'linux'
uses: docker/setup-buildx-action@v3
- name: Install rust (for Docker build)
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'linux'
run: |
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y
- name: Build reproducible binary with Docker (Linux)
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'linux'
run: |
RUST_TOOLCHAIN=$(rustc --version | cut -d' ' -f2)
docker build \
--build-arg "RUST_TOOLCHAIN=${RUST_TOOLCHAIN}" \
--build-arg "FEATURES=${{ matrix.features }}" \
--build-arg "VERSION=${{ needs.extract-version.outputs.VERSION }}" \
-f docker/Dockerfile.reproducible -t rbuilder:release \
--output type=local,dest=./target .
# Mac: Build natively with cargo
- name: Install dependencies (Mac)
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac'
run: |
brew install protobuf
- name: Install rust toolchain (Mac)
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac'
uses: dtolnay/rust-toolchain@stable
- name: Build binaries (Mac)
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'mac'
env:
# Workaround for runng-sys CMake compatibility issue
CMAKE_POLICY_VERSION_MINIMUM: "3.5"
run: |
FEATURES="${{ matrix.features }}"
FEATURE_FLAG=""
if [[ -n "$FEATURES" ]]; then
FEATURE_FLAG="--features $FEATURES"
fi
cargo build --profile ${{ matrix.profile }} $FEATURE_FLAG \
--bin rbuilder \
--bin rbuilder-operator \
--bin tbv-bidding-service \
--bin reth-rbuilder \
--bin bid-scraper \
--bin rbuilder-rebalancer
- name: Upload rbuilder artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: rbuilder-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/rbuilder
- name: Upload rbuilder-operator artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: rbuilder-operator-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/rbuilder-operator
- name: Upload tbv-bidding-service artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: tbv-bidding-service-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/tbv-bidding-service
- name: Upload reth-rbuilder artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: reth-rbuilder-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/reth-rbuilder
- name: Upload bid-scraper artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: bid-scraper-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/bid-scraper
- name: Upload rbuilder-rebalancer artifact
if: steps.platform-check.outputs.skip != 'true'
uses: actions/upload-artifact@v4
with:
name: rbuilder-rebalancer-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/${{ matrix.profile }}/rbuilder-rebalancer
- name: Upload *.deb packages
if: steps.platform-check.outputs.skip != 'true' && matrix.platform == 'linux'
uses: actions/upload-artifact@v4
with:
name: deb-${{ needs.extract-version.outputs.VERSION }}-${{ matrix.target }}${{ matrix.features && '-' }}${{ matrix.features }}
path: target/debian/*.deb
draft-release:
name: Draft release
if: ${{ github.event.inputs.draft-release == 'true' || github.event_name == 'push'}} # when manually triggered or version tagged
needs: [extract-version, build-binary]
runs-on: warp-ubuntu-2404-x64-16x
env:
VERSION: ${{ needs.extract-version.outputs.VERSION }}
permissions:
contents: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download artifacts
uses: actions/download-artifact@v4
with:
merge-multiple: true
path: artifacts
- name: Record artifacts checksums
working-directory: artifacts
run: |
find ./ || true
for file in *; do sha256sum "$file" >> sha256sums.txt; done;
cat sha256sums.txt
- name: Create release draft
uses: softprops/action-gh-release@v2.0.5
id: create-release-draft
with:
draft: true
files: artifacts/*
generate_release_notes: true
name: ${{ env.VERSION }}
tag_name: ${{ env.VERSION }}
- name: Write Github Step Summary
run: |
echo "---"
echo "### Release Draft: ${{ env.VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "${{ steps.create-release-draft.outputs.url }}" >> $GITHUB_STEP_SUMMARY
build-docker-linux-amd64:
if: ${{ github.event.inputs.build-docker == 'true' }}
name: Build and publish Docker image (linux/amd64)
needs: [extract-version, build-binary]
runs-on: warp-ubuntu-2404-x64-16x
env:
VERSION: ${{ needs.extract-version.outputs.VERSION }}
permissions:
contents: read
packages: write
steps:
- name: checkout sources
uses: actions/checkout@v4
- name: Download linux rbuilder binary
id: download-binary
continue-on-error: true
uses: actions/download-artifact@v4
with:
name: rbuilder-${{ env.VERSION }}-x86_64-unknown-linux-gnu${{ github.event.inputs.features && format('-{0}', github.event.inputs.features) || '' }}
path: .
- name: Check if binary was downloaded
if: steps.download-binary.outcome != 'success'
run: |
echo "⚠️ Binary artifact not found. Will build from source."
echo "Artifact name attempted: rbuilder-${{ env.VERSION }}-x86_64-unknown-linux-gnu${{ github.event.inputs.features && format('-{0}', github.event.inputs.features) || '' }}"
echo "This is expected if build-binary job didn't run or Linux build was skipped."
- name: Verify binary exists
if: steps.download-binary.outcome == 'success'
run: |
if [ -f "./rbuilder" ]; then
echo "✅ Binary downloaded successfully"
ls -lh ./rbuilder
else
echo "❌ Binary file not found after download"
find . -name "rbuilder" -type f || echo "No rbuilder file found"
exit 1
fi
- name: docker buildx
uses: docker/setup-buildx-action@v3
- name: docker metadata
uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
labels: org.opencontainers.image.source=${{ github.repositoryUrl }}
tags: |
type=sha,suffix=-linux-amd64
type=semver,pattern={{version}},value=${{ env.VERSION }},suffix=-linux-amd64,enable=${{ startsWith(env.VERSION, 'v') }}
type=semver,pattern={{major}}.{{minor}},value=${{ env.VERSION }},suffix=-linux-amd64,enable=${{ startsWith(env.VERSION, 'v') }}
type=semver,pattern={{major}},value=${{ env.VERSION }},suffix=-linux-amd64,enable=${{ startsWith(env.VERSION, 'v') }}
type=raw,value=latest,enable=${{ startsWith(env.VERSION, 'v') && !contains(env.VERSION, '-') }},suffix=-linux-amd64
- name: docker login
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: docker build and push (from binary)
if: steps.download-binary.outcome == 'success'
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
file: docker/Dockerfile.rbuilder-from-binary
context: .
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
- name: docker build and push (from source)
if: steps.download-binary.outcome != 'success'
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
file: docker/Dockerfile.rbuilder
context: .
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/amd64
push: true
tags: ${{ steps.meta.outputs.tags }}
build-docker-linux-arm64:
if: ${{ github.event.inputs.build-docker == 'true' }}
name: Build and publish Docker image (linux/arm64)
needs: [extract-version, build-binary]
runs-on: warp-ubuntu-2404-arm64-16x
env:
VERSION: ${{ needs.extract-version.outputs.VERSION }}
permissions:
contents: read
packages: write
steps:
- name: checkout sources
uses: actions/checkout@v4
- name: docker buildx
uses: docker/setup-buildx-action@v3
- name: docker metadata
uses: docker/metadata-action@v5
id: meta
with:
images: ghcr.io/${{ github.repository }}
labels: org.opencontainers.image.source=${{ github.repositoryUrl }}
tags: |
type=sha,suffix=-linux-arm64
type=semver,pattern={{version}},value=${{ env.VERSION }},suffix=-linux-arm64,enable=${{ startsWith(env.VERSION, 'v') }}
type=semver,pattern={{major}}.{{minor}},value=${{ env.VERSION }},suffix=-linux-arm64,enable=${{ startsWith(env.VERSION, 'v') }}
type=semver,pattern={{major}},value=${{ env.VERSION }},suffix=-linux-arm64,enable=${{ startsWith(env.VERSION, 'v') }}
type=raw,value=latest,enable=${{ startsWith(env.VERSION, 'v') && !contains(env.VERSION, '-') }},suffix=-linux-arm64
- name: docker login
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: docker build and push (from source, native arm64)
uses: docker/build-push-action@v5
with:
cache-from: type=gha
cache-to: type=gha,mode=max
file: docker/Dockerfile.rbuilder
context: .
labels: ${{ steps.meta.outputs.labels }}
platforms: linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
build-docker-manifest:
if: ${{ github.event.inputs.build-docker == 'true' }}
name: Create multi-arch Docker manifest
needs: [extract-version, build-docker-linux-amd64, build-docker-linux-arm64]
runs-on: warp-ubuntu-2404-x64-16x
env:
VERSION: ${{ needs.extract-version.outputs.VERSION }}
permissions:
contents: read
packages: write
steps:
- name: docker buildx
uses: docker/setup-buildx-action@v3
- name: docker login
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Create and push multi-arch manifest
run: |
IMAGE="ghcr.io/${{ github.repository }}"
# Build list of tags - only create semver tags if version starts with 'v'
TAGS=(
"sha-${GITHUB_SHA:0:7}"
)
# Only add version tags if it's a proper semver (starts with 'v')
if [[ "${{ env.VERSION }}" =~ ^v ]]; then
TAGS+=("${{ env.VERSION }}")
# Add version tags (major.minor, major) if not a prerelease
if [[ "${{ env.VERSION }}" != *"-"* ]]; then
TAGS+=("latest")
# Extract major.minor if version format is vX.Y.Z
if [[ "${{ env.VERSION }}" =~ ^v([0-9]+)\.([0-9]+)\. ]]; then
MAJOR="${BASH_REMATCH[1]}"
MINOR="${BASH_REMATCH[2]}"
TAGS+=("${MAJOR}.${MINOR}" "${MAJOR}")
fi
fi
fi
# Create multi-arch manifest for each tag combining both architectures
for TAG in "${TAGS[@]}"; do
echo "Creating multi-arch manifest for tag: ${TAG}"
# Verify both platform-specific images exist before creating manifest
if ! docker buildx imagetools inspect "${IMAGE}:${TAG}-linux-amd64" >/dev/null 2>&1; then
echo "⚠️ Warning: ${IMAGE}:${TAG}-linux-amd64 not found, skipping this tag"
continue
fi
if ! docker buildx imagetools inspect "${IMAGE}:${TAG}-linux-arm64" >/dev/null 2>&1; then
echo "⚠️ Warning: ${IMAGE}:${TAG}-linux-arm64 not found, skipping this tag"
continue
fi
# Create the multi-arch manifest
docker buildx imagetools create \
--tag "${IMAGE}:${TAG}" \
"${IMAGE}:${TAG}-linux-amd64" \
"${IMAGE}:${TAG}-linux-arm64" || {
echo "❌ Failed to create manifest for ${TAG}"
exit 1
}
echo "✅ Created manifest for ${TAG}"
done
echo "✅ Multi-arch manifests created for all tags"
- name: Write Docker Summary
run: |
echo "### 🐳 Multi-Arch Docker Images Published" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Package URL:** https://github.com/${{ github.repository }}/pkgs/container/rbuilder" >> $GITHUB_STEP_SUMMARY
echo "" >> $GITHUB_STEP_SUMMARY
echo "**Pull commands:**" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`bash" >> $GITHUB_STEP_SUMMARY
echo "docker pull ghcr.io/${{ github.repository }}:sha-${GITHUB_SHA:0:7}" >> $GITHUB_STEP_SUMMARY
echo "docker pull ghcr.io/${{ github.repository }}:${{ env.VERSION }}" >> $GITHUB_STEP_SUMMARY
echo "\`\`\`" >> $GITHUB_STEP_SUMMARY