From cb66c22974e1b297e319d4d9ed3b8a935d40b01b Mon Sep 17 00:00:00 2001 From: Dan Ditomaso Date: Sat, 13 Sep 2025 16:07:13 -0400 Subject: [PATCH] Fixes to github actions for `latest` tag (#848) * fix: ensure latest tag works * update release workflow as well * Update .github/workflows/nightly.yml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/nightly.yml | 35 ++++++++++------ .github/workflows/release-web.yml | 69 +++++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 25 deletions(-) diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index 683888ff..99ad7402 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -53,7 +53,7 @@ jobs: path: packages/web/dist/build.tar if-no-files-found: error - - name: Determine nightly tag + - name: Compute tags and labels id: meta shell: bash env: @@ -61,20 +61,27 @@ jobs: run: | set -euo pipefail DATE="$(date -u +%Y%m%d)" + ISO_CREATED="$(date -u +%Y-%m-%dT%H:%M:%SZ)" SHORTSHA="$(git rev-parse --short=12 HEAD)" + # Try to use latest release tag if it exists; fallback to package version; else date LATEST_TAG="$(gh release view --json tagName --jq .tagName 2>/dev/null || true)" if [ -z "$LATEST_TAG" ] && [ -f packages/web/package.json ]; then LATEST_TAG="v$(jq -r .version packages/web/package.json)" fi - if [ -n "$LATEST_TAG" ] && [ "$LATEST_TAG" != "vnull" ]; then - TAG="nightly-${LATEST_TAG}-${SHORTSHA}" + + if [ -n "${LATEST_TAG:-}" ] && [ "$LATEST_TAG" != "vnull" ]; then + IMMUTABLE="nightly-${LATEST_TAG}-${SHORTSHA}" else - TAG="nightly-${DATE}-${SHORTSHA}" + IMMUTABLE="nightly-${DATE}-${SHORTSHA}" fi - echo "tag=$TAG" >> "$GITHUB_OUTPUT" - echo "tags=nightly-$TAG" >> "$GITHUB_OUTPUT" - echo "Resolved nightly tags: nightly-$TAG" + + # Outputs + echo "immutable_tag=${IMMUTABLE}" >> "$GITHUB_OUTPUT" + echo "moving_tag=nightly" >> "$GITHUB_OUTPUT" + echo "all_tags=nightly,${IMMUTABLE}" >> "$GITHUB_OUTPUT" + echo "created=${ISO_CREATED}" >> "$GITHUB_OUTPUT" + echo "Resolved tags: nightly and ${IMMUTABLE}" - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -86,24 +93,26 @@ jobs: containerfiles: | ./packages/web/infra/Containerfile image: ${{ env.REGISTRY_IMAGE }} - tags: ${{ steps.meta.outputs.tag }} + tags: ${{ steps.meta.outputs.all_tags }} oci: true platforms: linux/amd64,linux/arm64 labels: | org.opencontainers.image.source=${{ github.repository }} org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.created=${{ github.event.head_commit.timestamp }} + org.opencontainers.image.created=${{ steps.meta.outputs.created }} - name: Push To GHCR id: push-to-registry uses: redhat-actions/push-to-registry@v2 with: image: ${{ steps.build-container.outputs.image }} - tags: ${{ steps.build-container.outputs.tags || steps.meta.outputs.tag }} + # Push the same tags used at build time: + tags: ${{ steps.meta.outputs.all_tags }} registry: ghcr.io username: ${{ github.actor }} password: ${{ secrets.GITHUB_TOKEN }} - - - name: Print image URL - run: echo "Image pushed to ${{ steps.push-to-registry.outputs.registry-paths }}" + - name: Print image URLs + run: | + echo "Moving tag: ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.moving_tag }}" + echo "Immutable tag: ${{ env.REGISTRY_IMAGE }}:${{ steps.meta.outputs.immutable_tag }}" diff --git a/.github/workflows/release-web.yml b/.github/workflows/release-web.yml index 2d301caf..f8dbb863 100644 --- a/.github/workflows/release-web.yml +++ b/.github/workflows/release-web.yml @@ -75,20 +75,44 @@ jobs: env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # Compute created timestamp & short SHA for labels/tags + - name: Compute meta + id: gen + shell: bash + run: | + echo "created=$(date -u +%Y-%m-%dT%H:%M:%SZ)" >> "$GITHUB_OUTPUT" + echo "shortsha=$(git rev-parse --short=12 HEAD)" >> "$GITHUB_OUTPUT" + + # Build/tag matrix: + # - For release events: vX.Y.Z, semver helpers, and latest (only if NOT prerelease) + # - For prerelease events: vX.Y.Z and semver helpers (NO latest) + # - For manual runs: + # * if tag_name set: that raw tag + # * else: adhoc- - name: Docker metadata (tags & labels) id: meta uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY_IMAGE }} + labels: | + org.opencontainers.image.source=${{ github.repository }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.created=${{ steps.gen.outputs.created }} tags: | - # For release events, use the release tag (e.g. v1.2.3) + # Full release (semantic tag) type=raw,value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }} - # For manual runs with a provided tag_name - type=raw,value=${{ inputs.tag_name }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name != '' }} - # For manual runs without tag_name, fall back to adhoc- - type=sha,format=short,prefix=adhoc-,enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name == '' }} - # Add "latest" only for full releases (not prereleases) + # Semver helpers (major, major.minor) for releases/prereleases + type=semver,pattern={{version}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' }} + type=semver,pattern={{major}}.{{minor}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }} + type=semver,pattern={{major}},value=${{ github.event.release.tag_name }},enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }} + # Latest only for full releases (not prereleases) type=raw,value=latest,enable=${{ github.event_name == 'release' && github.event.release.prerelease == false }} + # Manual: provided tag_name + type=raw,value=${{ inputs.tag_name }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name != '' }} + # Manual: fallback to adhoc- + type=raw,value=adhoc-${{ steps.gen.outputs.shortsha }},enable=${{ github.event_name == 'workflow_dispatch' && inputs.tag_name == '' }} + # Always add immutable sha tag for traceability + type=raw,value=sha-${{ steps.gen.outputs.shortsha }} - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -96,20 +120,41 @@ jobs: - name: Set up Buildx uses: docker/setup-buildx-action@v3 - - name: Build and (maybe) push image + - name: Login to GHCR + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Push images for: + # - release (released or prereleased) + # - manual with a tag_name (adhoc builds can still be pushed by name) + - name: Build and push image uses: docker/build-push-action@v6 with: context: . file: ./packages/web/infra/Containerfile platforms: linux/amd64,linux/arm64 - push: ${{ github.event_name == 'release' && github.event.release.prerelease == false }} + push: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '') }} tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} + provenance: false - name: Output image refs - if: ${{ github.event_name == 'release' && github.event.release.prerelease == false }} - run: "echo \"🖼️ Pushed: ${{ steps.meta.outputs.tags }}\"" + if: ${{ github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '') }} + run: | + echo "🖼️ Pushed tags:" + echo "${{ steps.meta.outputs.tags }}" + echo + echo "Pull examples:" + if [[ "${{ github.event_name }}" == "release" && "${{ github.event.release.prerelease }}" == "false" ]]; then + echo " docker pull ${{ env.REGISTRY_IMAGE }}:latest" + fi + # Always available: + echo " docker pull ${{ env.REGISTRY_IMAGE }}:${{ github.event.release.tag_name || inputs.tag_name || format('adhoc-{0}', steps.gen.outputs.shortsha) }}" + echo " docker pull ${{ env.REGISTRY_IMAGE }}:sha-${{ steps.gen.outputs.shortsha }}" - name: Explain no image push - if: ${{ !(github.event_name == 'release' && github.event.release.prerelease == false) }} - run: echo "ℹ️ No image pushed (prerelease or manual run)." + if: ${{ !(github.event_name == 'release' || (github.event_name == 'workflow_dispatch' && inputs.tag_name != '')) }} + run: echo "ℹ️ No image pushed (manual run without tag_name)."