chore: merge shadow branch fixes and improvements to main #146
Workflow file for this run
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: Auto Release on Main Branch | |
| on: | |
| pull_request: | |
| types: [ closed ] | |
| branches: [ main ] | |
| env: | |
| REGISTRY: docker.io | |
| IMAGE_NAME: blockblaz/zeam | |
| permissions: | |
| contents: write | |
| jobs: | |
| create-tags: | |
| # Only run if PR was merged to main branch from release branch and has release label | |
| if: | | |
| github.event.pull_request.merged == true && | |
| github.event.pull_request.head.ref == 'release' && | |
| contains(github.event.pull_request.labels.*.name, 'release') | |
| runs-on: ubuntu-latest | |
| outputs: | |
| version: ${{ steps.get_tags_labels.outputs.version }} | |
| devnet_tag: ${{ steps.get_tags_labels.outputs.devnet_tag }} | |
| docker_tag: ${{ steps.get_tags_labels.outputs.docker_tag }} | |
| github_tag: ${{ steps.get_tags_labels.outputs.github_tag }} | |
| has_devnet_tag: ${{ steps.get_tags_labels.outputs.has_devnet_tag }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Extract tags from PR labels | |
| id: get_tags_labels | |
| run: | | |
| # Get PR labels and extract version | |
| LABELS='${{ toJson(github.event.pull_request.labels.*.name) }}' | |
| echo "PR Labels: $LABELS" | |
| # Look for version label (x.y.z format only) - MANDATORY | |
| VERSION=$(echo $LABELS | jq -r '.[] | select(test("^[0-9]+\\.[0-9]+\\.[0-9]+$"))' | head -n 1) | |
| # Look for devnet tags (devnet0, devnet1, devnet2, etc.) | |
| DEVNET_TAG_LOWER=$(echo $LABELS | jq -r '.[] | select(test("^devnet[0-9]+$"))' | head -n 1) | |
| if [ -z "$VERSION" ] || [ "$VERSION" = "null" ]; then | |
| echo "β Version label is mandatory! Please add a version label in x.y.z format (e.g. 1.0.0)" | |
| exit 1 | |
| else | |
| echo "version=$VERSION" >> $GITHUB_OUTPUT | |
| echo "git_tag=v$VERSION" >> $GITHUB_OUTPUT | |
| echo "β Version found: $VERSION" | |
| fi | |
| if [ -n "$DEVNET_TAG_LOWER" ] && [ "$DEVNET_TAG_LOWER" != "null" ]; then | |
| # docker_tag keeps lowercase label (devnet2) | |
| DOCKER_TAG="$DEVNET_TAG_LOWER" | |
| # github_tag is capitalized first letter (Devnet2) | |
| GITHUB_TAG="D${DEVNET_TAG_LOWER:1}" | |
| echo "devnet_tag=$DOCKER_TAG" >> $GITHUB_OUTPUT | |
| echo "docker_tag=$DOCKER_TAG" >> $GITHUB_OUTPUT | |
| echo "github_tag=$GITHUB_TAG" >> $GITHUB_OUTPUT | |
| echo "has_devnet_tag=true" >> $GITHUB_OUTPUT | |
| echo "β Found devnet tag: label=$DEVNET_TAG_LOWER -> docker_tag=$DOCKER_TAG, github_tag=$GITHUB_TAG" | |
| else | |
| echo "has_devnet_tag=false" >> $GITHUB_OUTPUT | |
| echo "βΉοΈ No devnet tag found (optional)" | |
| fi | |
| - name: Create and push git tags | |
| id: create_tags | |
| run: | | |
| git fetch --prune --tags --force | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| CREATE_VERSION_TAG=false | |
| CREATE_DEVNET_TAG=false | |
| # Check if version tag should be created | |
| if [ -n "${{ steps.get_tags_labels.outputs.version }}" ] && [ "${{ steps.get_tags_labels.outputs.version }}" != "null" ]; then | |
| if git rev-parse "${{ steps.get_tags_labels.outputs.git_tag }}" >/dev/null 2>&1; then | |
| echo "β Version tag ${{ steps.get_tags_labels.outputs.git_tag }} already exists. Please use a different version label." | |
| exit 1 | |
| else | |
| CREATE_VERSION_TAG=true | |
| fi | |
| fi | |
| # Devnet git tag uses github_tag (DevnetX) | |
| if [ "${{ steps.get_tags_labels.outputs.has_devnet_tag }}" = "true" ]; then | |
| DEVNET_GIT_TAG="${{ steps.get_tags_labels.outputs.github_tag }}" | |
| # Allow recreation by deleting local and remote | |
| if git rev-parse "$DEVNET_GIT_TAG" >/dev/null 2>&1; then | |
| echo "ποΈ Devnet tag $DEVNET_GIT_TAG already exists, will be recreated" | |
| git tag -d "$DEVNET_GIT_TAG" || echo "β οΈ Local tag deletion failed" | |
| git push --delete origin "$DEVNET_GIT_TAG" || echo "β οΈ Remote tag deletion failed" | |
| fi | |
| CREATE_DEVNET_TAG=true | |
| fi | |
| # Create version tag if needed | |
| if [ "$CREATE_VERSION_TAG" = "true" ]; then | |
| git tag -a "${{ steps.get_tags_labels.outputs.git_tag }}" -m "Release version ${{ steps.get_tags_labels.outputs.version }}" | |
| git push origin "${{ steps.get_tags_labels.outputs.git_tag }}" | |
| echo "β Created version tag ${{ steps.get_tags_labels.outputs.git_tag }}" | |
| fi | |
| # Create devnet git tag (DevnetX) | |
| if [ "$CREATE_DEVNET_TAG" = "true" ]; then | |
| git tag -a "$DEVNET_GIT_TAG" -m "Devnet release for $DEVNET_GIT_TAG" | |
| git push origin "$DEVNET_GIT_TAG" | |
| echo "β Created devnet git tag $DEVNET_GIT_TAG" | |
| fi | |
| echo "create_version_tag=$CREATE_VERSION_TAG" >> $GITHUB_OUTPUT | |
| echo "create_devnet_tag=$CREATE_DEVNET_TAG" >> $GITHUB_OUTPUT | |
| build-and-push: | |
| needs: create-tags | |
| strategy: | |
| matrix: | |
| include: | |
| - runner: ubuntu-latest | |
| arch: amd64 | |
| - runner: ubuntu-22.04-arm | |
| arch: arm64 | |
| runs-on: ${{ matrix.runner }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Extract metadata | |
| id: meta | |
| uses: docker/metadata-action@v5 | |
| with: | |
| images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} | |
| tags: | | |
| type=raw,value=latest-${{ matrix.arch }} | |
| type=raw,value=${{ needs.create-tags.outputs.version }}-${{ matrix.arch }},enable=${{ needs.create-tags.outputs.version != 'null' }} | |
| type=raw,value=${{ needs.create-tags.outputs.docker_tag }}-${{ matrix.arch }},enable=${{ needs.create-tags.outputs.has_devnet_tag == 'true' }} | |
| - name: Set up Zig | |
| uses: mlugg/setup-zig@v2.0.5 | |
| with: | |
| version: 0.15.2 | |
| - name: Set up Rust/Cargo | |
| uses: actions-rust-lang/setup-rust-toolchain@v1 | |
| with: | |
| toolchain: nightly | |
| - name: Cache Zig packages | |
| uses: actions/cache@v4 | |
| with: | |
| path: ~/.cache/zig | |
| key: ${{ runner.os }}-zig-packages-${{ hashFiles('build.zig.zon') }} | |
| restore-keys: | | |
| ${{ runner.os }}-zig-packages- | |
| - name: Cache Rust dependencies | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: "rust -> target" | |
| key: ${{ runner.os }}-cargo-docker-${{ hashFiles('**/Cargo.lock') }} | |
| - name: Build zeam natively | |
| run: | | |
| if [ "${{ matrix.arch }}" = "amd64" ]; then | |
| zig build -Doptimize=ReleaseSafe -Dtarget=x86_64-linux-gnu -Dcpu=baseline -Dgit_version="$(git rev-parse --short HEAD)" | |
| else | |
| zig build -Doptimize=ReleaseSafe -Dtarget=aarch64-linux-gnu -Dcpu=baseline -Dgit_version="$(git rev-parse --short HEAD)" | |
| fi | |
| - name: Build and push Docker image with pre-built binary (${{ matrix.arch }}) | |
| uses: docker/build-push-action@v5 | |
| with: | |
| context: . | |
| file: ./Dockerfile.prebuilt | |
| push: true | |
| tags: ${{ steps.meta.outputs.tags }} | |
| labels: ${{ steps.meta.outputs.labels }} | |
| build-args: | | |
| GIT_COMMIT=${{ github.sha }} | |
| GIT_BRANCH=${{ github.ref_name }} | |
| cache-from: type=gha | |
| cache-to: type=gha,mode=max | |
| provenance: false | |
| create-manifest: | |
| needs: [ create-tags, build-and-push ] | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@v3 | |
| - name: Log in to Docker Hub | |
| uses: docker/login-action@v3 | |
| with: | |
| registry: ${{ env.REGISTRY }} | |
| username: ${{ secrets.DOCKER_USERNAME }} | |
| password: ${{ secrets.DOCKER_PASSWORD }} | |
| - name: Create and push multi-arch manifest for latest | |
| run: | | |
| docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-amd64 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest-arm64 | |
| - name: Create and push multi-arch manifest for version tag | |
| if: ${{ needs.create-tags.outputs.version != 'null' }} | |
| run: | | |
| docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.version }} \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.version }}-amd64 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.version }}-arm64 | |
| - name: Create and push multi-arch manifest for devnet tag | |
| if: ${{ needs.create-tags.outputs.has_devnet_tag == 'true' }} | |
| run: | | |
| docker buildx imagetools create -t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }} \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }}-amd64 \ | |
| ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }}-arm64 | |
| create-github-release: | |
| needs: [ create-tags, build-and-push, create-manifest ] | |
| runs-on: ubuntu-latest | |
| if: ${{ needs.create-tags.outputs.has_devnet_tag == 'true' }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@v4 | |
| with: | |
| fetch-depth: 0 | |
| - name: Delete existing devnet release if exists | |
| run: | | |
| DEVNET_TAG="${{ needs.create-tags.outputs.github_tag }}" | |
| echo "π Checking for existing $DEVNET_TAG release..." | |
| if gh api repos/${{ github.repository }}/releases/tags/$DEVNET_TAG >/dev/null 2>&1; then | |
| RELEASE_ID=$(gh api repos/${{ github.repository }}/releases/tags/$DEVNET_TAG --jq '.id') | |
| echo "ποΈ Found existing GitHub release for $DEVNET_TAG (ID: $RELEASE_ID), deleting..." | |
| gh api --method DELETE repos/${{ github.repository }}/releases/$RELEASE_ID | |
| echo "β Deleted existing GitHub release" | |
| else | |
| echo "βΉοΈ No existing GitHub release found for $DEVNET_TAG" | |
| fi | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Generate changelog from previous release | |
| id: changelog | |
| run: | | |
| DEVNET_TAG="${{ needs.create-tags.outputs.github_tag }}" | |
| VERSION="${{ needs.create-tags.outputs.version }}" | |
| PREVIOUS_TAG=$(git tag -l | grep -iE "^[Dd]evnet[0-9]+" | sort -V -r | grep -v "^$DEVNET_TAG$" | head -1) | |
| if [ -n "$PREVIOUS_TAG" ] && [ "$PREVIOUS_TAG" != "$DEVNET_TAG" ]; then | |
| echo "β Found previous tag: $PREVIOUS_TAG" | |
| echo "π Generating changelog from $PREVIOUS_TAG to current release..." | |
| # Generate commit log | |
| COMMIT_LOG=$(git log --pretty=format:"- %s (%h)" --no-merges "$PREVIOUS_TAG"..HEAD) | |
| # Generate file changes summary | |
| FILES_CHANGED=$(git diff --name-only "$PREVIOUS_TAG"..HEAD | wc -l) | |
| INSERTIONS=$(git diff --shortstat "$PREVIOUS_TAG"..HEAD | grep -o '[0-9]\+ insertion' | grep -o '[0-9]\+' || echo "0") | |
| DELETIONS=$(git diff --shortstat "$PREVIOUS_TAG"..HEAD | grep -o '[0-9]\+ deletion' | grep -o '[0-9]\+' || echo "0") | |
| # Get contributors | |
| CONTRIBUTORS=$(git log --pretty=format:"%an" --no-merges "$PREVIOUS_TAG"..HEAD | sort | uniq | tr '\n' ', ' | sed 's/, $//') | |
| # Create changelog content in GitHub format | |
| CHANGELOG="## π Changes since $PREVIOUS_TAG | |
| ### π Summary | |
| - **Files changed**: $FILES_CHANGED | |
| - **Insertions**: +$INSERTIONS | |
| - **Deletions**: -$DELETIONS | |
| - **Contributors**: $CONTRIBUTORS | |
| ### π Recent commits | |
| $COMMIT_LOG | |
| ### π Compare changes | |
| [View full diff](${{ github.server_url }}/${{ github.repository }}/compare/$PREVIOUS_TAG...HEAD)" | |
| else | |
| echo "βΉοΈ No previous release found or this is the first release" | |
| CHANGELOG="## π Changes | |
| This is the first devnet release." | |
| fi | |
| # Save changelog to output (escape newlines for GitHub Actions) | |
| echo "changelog<<EOF" >> $GITHUB_OUTPUT | |
| echo "$CHANGELOG" >> $GITHUB_OUTPUT | |
| echo "EOF" >> $GITHUB_OUTPUT | |
| echo "previous_tag=$PREVIOUS_TAG" >> $GITHUB_OUTPUT | |
| - name: Create GitHub Release | |
| uses: softprops/action-gh-release@v1 | |
| with: | |
| tag_name: ${{ needs.create-tags.outputs.github_tag }} | |
| name: "Zeam ${{ needs.create-tags.outputs.github_tag }} Release" | |
| body: | | |
| # Zeam ${{ needs.create-tags.outputs.github_tag }} Release | |
| ## Release Information | |
| - **Version**: ${{ needs.create-tags.outputs.version }} | |
| - **Network**: ${{ needs.create-tags.outputs.github_tag }} | |
| - **Docker Images**: `${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }}` | |
| ## π Changes | |
| ${{ steps.changelog.outputs.changelog }} | |
| ## π Docker Images | |
| ```bash | |
| # Multi-architecture (recommended) | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }} | |
| # Architecture-specific | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }}-amd64 | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }}-arm64 | |
| ``` | |
| ## π·οΈ All Available Tags | |
| ```bash | |
| # Latest release | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest | |
| # Version-specific | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.version }} | |
| # Devnet-specific | |
| docker pull ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.create-tags.outputs.docker_tag }} | |
| ``` | |
| draft: false | |
| prerelease: true | |
| - name: Push code to corresponding devnet branch | |
| run: | | |
| git config user.name "github-actions[bot]" | |
| git config user.email "github-actions[bot]@users.noreply.github.com" | |
| GITHUB_TAG="${{ needs.create-tags.outputs.github_tag }}" | |
| DOCKER_TAG="${{ needs.create-tags.outputs.docker_tag }}" | |
| DEVNET_BRANCH="$DOCKER_TAG" # branch = devnetX | |
| echo "β GitHub tag: $GITHUB_TAG, Docker tag/branch: $DOCKER_TAG" | |
| if git ls-remote --heads origin "$DEVNET_BRANCH" | grep -q "$DEVNET_BRANCH"; then | |
| echo "β $DEVNET_BRANCH branch exists, updating it" | |
| git fetch origin "$DEVNET_BRANCH" | |
| git checkout "$DEVNET_BRANCH" | |
| git merge main --no-edit | |
| else | |
| echo "β $DEVNET_BRANCH branch doesn't exist, creating it from main" | |
| git checkout -b "$DEVNET_BRANCH" | |
| fi | |
| git push origin "$DEVNET_BRANCH" | |
| echo "β Successfully pushed code to $DEVNET_BRANCH branch" | |
| - name: Send Telegram success notification | |
| if: ${{ success() }} | |
| run: | | |
| DOCKER_TAG="${{ needs.create-tags.outputs.docker_tag }}" | |
| GITHUB_TAG="${{ needs.create-tags.outputs.github_tag }}" | |
| VERSION="${{ needs.create-tags.outputs.version }}" | |
| REPO_URL="${{ github.server_url }}/${{ github.repository }}" | |
| MESSAGE="π *Zeam $GITHUB_TAG Release SUCCESS* | |
| *Release Details:* | |
| β’ Version: \`$VERSION\` | |
| β’ Network: \`$GITHUB_TAG\` | |
| β’ Repository: [${{ github.repository }}]($REPO_URL) | |
| *π Docker Images Available:* | |
| β’ Multi-arch: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$DOCKER_TAG\` | |
| β’ AMD64: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$DOCKER_TAG-amd64\` | |
| β’ ARM64: \`${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:$DOCKER_TAG-arm64\` | |
| *π Quick Links:* | |
| β’ [GitHub Release]($REPO_URL/releases/tag/$GITHUB_TAG) | |
| *πΏ Deployment:* | |
| β’ Code pushed to \`$(echo "$DOCKER_TAG")\` branch | |
| _π€ Automated release notification_" | |
| # Send to Telegram | |
| curl -s -X POST "https://api.telegram.org/bot${{ secrets.TELEGRAM_BOT_TOKEN }}/sendMessage" \ | |
| -H "Content-Type: application/json" \ | |
| -d "{ | |
| \"chat_id\": \"${{ secrets.TELEGRAM_CHAT_ID }}\", | |
| \"text\": \"$MESSAGE\", | |
| \"parse_mode\": \"Markdown\", | |
| \"disable_web_page_preview\": true | |
| }" && echo "π± Telegram notification sent successfully" || echo "β Failed to send Telegram notification" |