From d928e9b118143741034d3363278d81585735a298 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Fri, 20 Feb 2026 10:07:14 +0100 Subject: [PATCH 1/8] fix(release): implement manual approval for Docker CE release workflow and enhance job structure --- .github/workflows/release.yml | 62 ++++++++++++++++++++++++++++++----- 1 file changed, 54 insertions(+), 8 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 59fd6096b..fd1cca606 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -438,7 +438,6 @@ jobs: release-cli-desktop: needs: [prepare, test] runs-on: ubuntu-latest - timeout-minutes: 60 permissions: contents: read steps: @@ -501,7 +500,6 @@ jobs: bump-pinata: needs: [prepare, release-cli-desktop] runs-on: ubuntu-latest - timeout-minutes: 10 permissions: contents: read steps: @@ -546,14 +544,24 @@ jobs: # --------------------------------------------------------------------------- # Release CLI for Docker CE — build .deb/.rpm packages and deploy to download.docker.com # (triggers docker/packaging → docker/release-repo) + # + # Split into two jobs: + # 1. release-cli-docker-ce-trigger: triggers packaging, waits for it, then + # triggers release-repo plugin workflow. + # 2. release-cli-docker-ce-wait: requires manual approval (via the + # "release-repo-deploy" environment) before waiting for the release-repo + # workflow to finish. This lets you approve the release-repo deploy-to-live + # gate first, then approve this workflow so both proceed together. # --------------------------------------------------------------------------- - release-cli-docker-ce: + release-cli-docker-ce-trigger: if: ${{ !inputs.skipPackaging }} needs: [prepare, release-cli-desktop] runs-on: ubuntu-latest - timeout-minutes: 360 permissions: contents: read + outputs: + packaging_image: ${{ steps.packaging.outputs.packaging_image }} + release_repo_trigger_time: ${{ steps.trigger_release_repo.outputs.trigger_time }} steps: - name: Trigger release-model workflow in packaging repo id: trigger @@ -640,10 +648,49 @@ jobs: -f release_live=true echo "✅ Plugin release workflow triggered in docker/release-repo" + - name: Post trigger summary + env: + VERSION: ${{ needs.prepare.outputs.version }} + RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} + PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }} + run: | + cat >> "$GITHUB_STEP_SUMMARY" <<-SUMMARY + ## 📦 Docker CE Packaging & Release — Triggered + + | Step | Status | + |------|--------| + | Packaging image | \`${PACKAGING_IMAGE}\` | + | Model version | \`${VERSION}\` | + | Release channel | \`stable\` | + | Deploy to live | ✅ Yes | + | Release tag | \`${RELEASE_TAG}\` | + + The plugin release workflow has been triggered in [docker/release-repo](https://github.com/docker/release-repo/actions/workflows/plugin.yml). + + ⏳ **Next step:** approve the \`release-repo-deploy\` environment in this workflow + once the release-repo deploy-to-live gate has been approved. + SUMMARY + + # --------------------------------------------------------------------------- + # Wait for release-repo — requires manual approval via the + # "release-repo-deploy" environment so the workflow does not block for hours. + # + # Before approving this step: + # 1. Go to docker/release-repo → Actions → plugin.yml run + # 2. Approve the deploy-to-live gate there + # 3. Come back here and approve the "release-repo-deploy" environment + # --------------------------------------------------------------------------- + release-cli-docker-ce-wait: + needs: [prepare, release-cli-docker-ce-trigger] + runs-on: ubuntu-latest + environment: release-repo-deploy + permissions: + contents: read + steps: - name: Wait for release-repo plugin workflow to complete env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} - TRIGGER_TIME: ${{ steps.trigger_release_repo.outputs.trigger_time }} + TRIGGER_TIME: ${{ needs.release-cli-docker-ce-trigger.outputs.release_repo_trigger_time }} run: | echo "⏳ Waiting for release-repo plugin workflow to appear (triggered at $TRIGGER_TIME)..." sleep 15 @@ -679,7 +726,7 @@ jobs: env: VERSION: ${{ needs.prepare.outputs.version }} RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} - PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }} + PACKAGING_IMAGE: ${{ needs.release-cli-docker-ce-trigger.outputs.packaging_image }} run: | cat >> "$GITHUB_STEP_SUMMARY" <<-SUMMARY ## 📦 Docker CE Packaging & Release @@ -701,9 +748,8 @@ jobs: # to confirm both client and server versions match the release tag. # --------------------------------------------------------------------------- verify-docker-ce: - needs: [prepare, release-cli-docker-ce, build] + needs: [prepare, release-cli-docker-ce-wait, build] runs-on: ubuntu-latest - timeout-minutes: 15 steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd From 523b4896172112f734f15547101ad5a9f8c0a605 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Fri, 20 Feb 2026 19:27:27 +0100 Subject: [PATCH 2/8] fix(release): streamline release workflows by removing unnecessary wait steps and enhancing trigger feedback --- .github/workflows/release.yml | 230 ++++++++-------------------------- 1 file changed, 54 insertions(+), 176 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index fd1cca606..0ea73bf59 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -432,8 +432,6 @@ jobs: # --------------------------------------------------------------------------- # Release CLI for Docker Desktop — build, sign & push CLI + Desktop module image - # (triggers docker/inference-engine-llama.cpp: signs macOS/Windows binaries, - # pushes docker/docker-model-cli-desktop-module to Docker Hub) # --------------------------------------------------------------------------- release-cli-desktop: needs: [prepare, test] @@ -441,58 +439,31 @@ jobs: permissions: contents: read steps: - - name: Trigger release-cli-dd workflow - id: trigger + - name: Trigger Desktop CLI release and wait for completion env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} VERSION: ${{ needs.prepare.outputs.version }} run: | - TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) - echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT" - echo "🚀 Triggering release-cli-dd workflow at $TRIGGER_TIME" - echo " model-cli-ref: $RELEASE_TAG" - echo " tag: v$VERSION" - gh workflow run release-cli-dd.yml \ + echo "🚀 Triggering Desktop CLI release workflow" + + # gh workflow run now returns run details (gh v2.87.0+) + RUN_URL=$(gh workflow run release-cli-dd.yml \ --repo docker/inference-engine-llama.cpp \ -f model-cli-ref="$RELEASE_TAG" \ - -f tag="v$VERSION" - echo "✅ release-cli-dd workflow triggered" + -f tag="v$VERSION" 2>&1 \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') - - name: Wait for release-cli-dd to complete - env: - GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} - TRIGGER_TIME: ${{ steps.trigger.outputs.trigger_time }} - run: | - echo "⏳ Waiting for release-cli-dd workflow to appear (triggered at $TRIGGER_TIME)..." - sleep 15 - - # Find the run created after our trigger time to avoid picking up unrelated runs - for i in $(seq 1 30); do - RUN_ID=$(gh run list \ - --repo docker/inference-engine-llama.cpp \ - --workflow release-cli-dd.yml \ - --limit 5 \ - --json databaseId,createdAt \ - --jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId") - if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then - echo "Found release-cli-dd run: $RUN_ID" - break - fi - echo " Retry $i/30..." - sleep 10 - done + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + echo "::add-mask::$RUN_ID" + echo "::add-mask::$RUN_URL" + echo "✅ Desktop CLI release workflow triggered" - if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then - echo "::error::Could not find release-cli-dd workflow run created after $TRIGGER_TIME" - exit 1 - fi - - echo "⏳ Waiting for release-cli-dd run $RUN_ID to complete..." + echo "⏳ Waiting for Desktop CLI release to complete..." gh run watch "$RUN_ID" \ --repo docker/inference-engine-llama.cpp \ --exit-status - echo "✅ release-cli-dd workflow completed successfully" + echo "✅ Desktop CLI release completed successfully" # --------------------------------------------------------------------------- # Bump docker-model version in pinata and open a PR @@ -542,16 +513,14 @@ jobs: draft: true # --------------------------------------------------------------------------- - # Release CLI for Docker CE — build .deb/.rpm packages and deploy to download.docker.com - # (triggers docker/packaging → docker/release-repo) + # Release CLI for Docker CE — build .deb/.rpm packages and deploy # # Split into two jobs: # 1. release-cli-docker-ce-trigger: triggers packaging, waits for it, then - # triggers release-repo plugin workflow. + # triggers the deploy workflow. # 2. release-cli-docker-ce-wait: requires manual approval (via the - # "release-repo-deploy" environment) before waiting for the release-repo - # workflow to finish. This lets you approve the release-repo deploy-to-live - # gate first, then approve this workflow so both proceed together. + # "release-repo-deploy" environment) before waiting for the deploy + # workflow to finish. # --------------------------------------------------------------------------- release-cli-docker-ce-trigger: if: ${{ !inputs.skipPackaging }} @@ -561,55 +530,29 @@ jobs: contents: read outputs: packaging_image: ${{ steps.packaging.outputs.packaging_image }} - release_repo_trigger_time: ${{ steps.trigger_release_repo.outputs.trigger_time }} + release_repo_run_id: ${{ steps.trigger_release_repo.outputs.run_id }} steps: - - name: Trigger release-model workflow in packaging repo - id: trigger - env: - GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} - RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} - run: | - TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) - echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT" - echo "📦 Triggering release-model workflow in docker/packaging at $TRIGGER_TIME" - echo " ref: $RELEASE_TAG" - gh workflow run release-model.yml \ - --repo docker/packaging \ - -f ref="$RELEASE_TAG" - echo "✅ release-model workflow triggered in docker/packaging" - - - name: Wait for packaging workflow to complete + - name: Trigger packaging and wait for completion id: packaging env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} + RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} VERSION: ${{ needs.prepare.outputs.version }} - TRIGGER_TIME: ${{ steps.trigger.outputs.trigger_time }} run: | - echo "⏳ Waiting for packaging workflow to appear (triggered at $TRIGGER_TIME)..." - sleep 15 - - # Find the run created after our trigger time to avoid picking up unrelated runs - for i in $(seq 1 30); do - RUN_ID=$(gh run list \ - --repo docker/packaging \ - --workflow release-model.yml \ - --limit 5 \ - --json databaseId,createdAt \ - --jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId") - if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then - echo "Found packaging run: $RUN_ID" - break - fi - echo " Retry $i/30..." - sleep 10 - done + echo "📦 Triggering packaging workflow" - if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then - echo "::error::Could not find packaging workflow run created after $TRIGGER_TIME" - exit 1 - fi + # gh workflow run now returns run details (gh v2.87.0+) + RUN_URL=$(gh workflow run release-model.yml \ + --repo docker/packaging \ + -f ref="$RELEASE_TAG" 2>&1 \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') + + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + echo "::add-mask::$RUN_ID" + echo "::add-mask::$RUN_URL" + echo "✅ Packaging workflow triggered" - echo "⏳ Waiting for packaging run $RUN_ID to complete..." + echo "⏳ Waiting for packaging to complete..." gh run watch "$RUN_ID" \ --repo docker/packaging \ --exit-status @@ -621,64 +564,42 @@ jobs: --jq '.number') PACKAGING_IMAGE="dockereng/packaging:model-v${VERSION}-${RUN_NUMBER}" - echo "📦 Packaging image: $PACKAGING_IMAGE" + echo "::add-mask::$PACKAGING_IMAGE" echo "packaging_image=$PACKAGING_IMAGE" >> "$GITHUB_OUTPUT" echo "✅ Packaging workflow completed successfully" - - name: Trigger release-repo plugin workflow + - name: Trigger deploy workflow id: trigger_release_repo env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} VERSION: ${{ needs.prepare.outputs.version }} PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }} run: | - TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ) - echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT" - echo "🚀 Triggering plugin release in docker/release-repo at $TRIGGER_TIME" - echo " packaging_image: $PACKAGING_IMAGE" - echo " model_version: $VERSION" - echo " channel: stable" - echo " release_live: true" - gh workflow run plugin.yml \ + echo "🚀 Triggering deploy workflow" + + # gh workflow run now returns run details (gh v2.87.0+) + RUN_URL=$(gh workflow run plugin.yml \ --repo docker/release-repo \ --ref production \ -f packaging_image="$PACKAGING_IMAGE" \ -f model_version="$VERSION" \ -f channel=stable \ - -f release_live=true - echo "✅ Plugin release workflow triggered in docker/release-repo" - - - name: Post trigger summary - env: - VERSION: ${{ needs.prepare.outputs.version }} - RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} - PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }} - run: | - cat >> "$GITHUB_STEP_SUMMARY" <<-SUMMARY - ## 📦 Docker CE Packaging & Release — Triggered - - | Step | Status | - |------|--------| - | Packaging image | \`${PACKAGING_IMAGE}\` | - | Model version | \`${VERSION}\` | - | Release channel | \`stable\` | - | Deploy to live | ✅ Yes | - | Release tag | \`${RELEASE_TAG}\` | - - The plugin release workflow has been triggered in [docker/release-repo](https://github.com/docker/release-repo/actions/workflows/plugin.yml). + -f release_live=true 2>&1 \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') - ⏳ **Next step:** approve the \`release-repo-deploy\` environment in this workflow - once the release-repo deploy-to-live gate has been approved. - SUMMARY + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + echo "::add-mask::$RUN_ID" + echo "::add-mask::$RUN_URL" + echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" + echo "✅ Deploy workflow triggered" # --------------------------------------------------------------------------- - # Wait for release-repo — requires manual approval via the - # "release-repo-deploy" environment so the workflow does not block for hours. + # Wait for deploy — requires manual approval via the "release-repo-deploy" + # environment so the workflow does not block for hours. # # Before approving this step: - # 1. Go to docker/release-repo → Actions → plugin.yml run - # 2. Approve the deploy-to-live gate there - # 3. Come back here and approve the "release-repo-deploy" environment + # 1. Approve the deploy-to-live gate in the deploy workflow + # 2. Come back here and approve the "release-repo-deploy" environment # --------------------------------------------------------------------------- release-cli-docker-ce-wait: needs: [prepare, release-cli-docker-ce-trigger] @@ -687,60 +608,17 @@ jobs: permissions: contents: read steps: - - name: Wait for release-repo plugin workflow to complete + - name: Wait for deploy workflow to complete env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} - TRIGGER_TIME: ${{ needs.release-cli-docker-ce-trigger.outputs.release_repo_trigger_time }} + RUN_ID: ${{ needs.release-cli-docker-ce-trigger.outputs.release_repo_run_id }} run: | - echo "⏳ Waiting for release-repo plugin workflow to appear (triggered at $TRIGGER_TIME)..." - sleep 15 - - # Find the run created after our trigger time to avoid picking up unrelated runs - for i in $(seq 1 30); do - RUN_ID=$(gh run list \ - --repo docker/release-repo \ - --workflow plugin.yml \ - --limit 5 \ - --json databaseId,createdAt \ - --jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId") - if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then - echo "Found release-repo run: $RUN_ID" - break - fi - echo " Retry $i/30..." - sleep 10 - done - - if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then - echo "::error::Could not find release-repo plugin workflow run created after $TRIGGER_TIME" - exit 1 - fi - - echo "⏳ Waiting for release-repo run $RUN_ID to complete (includes manual deploy-to-live approval)..." + echo "::add-mask::$RUN_ID" + echo "⏳ Waiting for deploy workflow to complete..." gh run watch "$RUN_ID" \ --repo docker/release-repo \ --exit-status - echo "✅ Release-repo plugin workflow completed successfully" - - - name: Post summary - env: - VERSION: ${{ needs.prepare.outputs.version }} - RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} - PACKAGING_IMAGE: ${{ needs.release-cli-docker-ce-trigger.outputs.packaging_image }} - run: | - cat >> "$GITHUB_STEP_SUMMARY" <<-SUMMARY - ## 📦 Docker CE Packaging & Release - - | Step | Status | - |------|--------| - | Packaging image | \`${PACKAGING_IMAGE}\` | - | Model version | \`${VERSION}\` | - | Release channel | \`stable\` | - | Deploy to live | ✅ Yes | - | Release tag | \`${RELEASE_TAG}\` | - - The plugin release workflow has been triggered in [docker/release-repo](https://github.com/docker/release-repo/actions/workflows/plugin.yml). - SUMMARY + echo "✅ Deploy workflow completed successfully" # --------------------------------------------------------------------------- # Verify Docker CE installation and server version — install Docker CE, From 55189ae62b3c2907ca5158eb2d3dd2d29cd142da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 09:27:41 +0100 Subject: [PATCH 3/8] fix(release): remove unnecessary output redirection in workflow run commands --- .github/workflows/release.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0ea73bf59..f65bcb335 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -451,7 +451,7 @@ jobs: RUN_URL=$(gh workflow run release-cli-dd.yml \ --repo docker/inference-engine-llama.cpp \ -f model-cli-ref="$RELEASE_TAG" \ - -f tag="v$VERSION" 2>&1 \ + -f tag="v$VERSION" \ | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') @@ -544,7 +544,7 @@ jobs: # gh workflow run now returns run details (gh v2.87.0+) RUN_URL=$(gh workflow run release-model.yml \ --repo docker/packaging \ - -f ref="$RELEASE_TAG" 2>&1 \ + -f ref="$RELEASE_TAG" \ | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') @@ -584,7 +584,7 @@ jobs: -f packaging_image="$PACKAGING_IMAGE" \ -f model_version="$VERSION" \ -f channel=stable \ - -f release_live=true 2>&1 \ + -f release_live=true \ | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') From 707eb643f565db95d29785f52854c7187fc3066a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 15:09:09 +0100 Subject: [PATCH 4/8] fix(release): enhance workflow run commands to extract run URLs and IDs more reliably --- .github/workflows/release.yml | 87 +++++++++++++++++++++++++++++------ 1 file changed, 72 insertions(+), 15 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index f65bcb335..afa59467f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -447,14 +447,33 @@ jobs: run: | echo "🚀 Triggering Desktop CLI release workflow" - # gh workflow run now returns run details (gh v2.87.0+) - RUN_URL=$(gh workflow run release-cli-dd.yml \ + # gh workflow run returns run URL on stdout (gh v2.87.0+) + OUTPUT=$(gh workflow run release-cli-dd.yml \ --repo docker/inference-engine-llama.cpp \ -f model-cli-ref="$RELEASE_TAG" \ - -f tag="v$VERSION" \ - | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') + -f tag="v$VERSION") + + RUN_URL=$(echo "$OUTPUT" \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true + + if [ -z "$RUN_URL" ]; then + echo "⚠️ Could not extract run URL from gh output, querying latest run..." + sleep 5 + RUN_ID=$(gh run list \ + --repo docker/inference-engine-llama.cpp \ + --workflow release-cli-dd.yml \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId') + else + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + fi + + if [ -z "$RUN_ID" ]; then + echo "::error::Failed to determine workflow run ID" + exit 1 + fi - RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') echo "::add-mask::$RUN_ID" echo "::add-mask::$RUN_URL" echo "✅ Desktop CLI release workflow triggered" @@ -541,13 +560,32 @@ jobs: run: | echo "📦 Triggering packaging workflow" - # gh workflow run now returns run details (gh v2.87.0+) - RUN_URL=$(gh workflow run release-model.yml \ + # gh workflow run returns run URL on stdout (gh v2.87.0+) + OUTPUT=$(gh workflow run release-model.yml \ --repo docker/packaging \ - -f ref="$RELEASE_TAG" \ - | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') + -f ref="$RELEASE_TAG") + + RUN_URL=$(echo "$OUTPUT" \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true + + if [ -z "$RUN_URL" ]; then + echo "⚠️ Could not extract run URL from gh output, querying latest run..." + sleep 5 + RUN_ID=$(gh run list \ + --repo docker/packaging \ + --workflow release-model.yml \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId') + else + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + fi + + if [ -z "$RUN_ID" ]; then + echo "::error::Failed to determine packaging workflow run ID" + exit 1 + fi - RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') echo "::add-mask::$RUN_ID" echo "::add-mask::$RUN_URL" echo "✅ Packaging workflow triggered" @@ -577,17 +615,36 @@ jobs: run: | echo "🚀 Triggering deploy workflow" - # gh workflow run now returns run details (gh v2.87.0+) - RUN_URL=$(gh workflow run plugin.yml \ + # gh workflow run returns run URL on stdout (gh v2.87.0+) + OUTPUT=$(gh workflow run plugin.yml \ --repo docker/release-repo \ --ref production \ -f packaging_image="$PACKAGING_IMAGE" \ -f model_version="$VERSION" \ -f channel=stable \ - -f release_live=true \ - | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') + -f release_live=true) + + RUN_URL=$(echo "$OUTPUT" \ + | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true + + if [ -z "$RUN_URL" ]; then + echo "⚠️ Could not extract run URL from gh output, querying latest run..." + sleep 5 + RUN_ID=$(gh run list \ + --repo docker/release-repo \ + --workflow plugin.yml \ + --limit 1 \ + --json databaseId \ + --jq '.[0].databaseId') + else + RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') + fi + + if [ -z "$RUN_ID" ]; then + echo "::error::Failed to determine deploy workflow run ID" + exit 1 + fi - RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') echo "::add-mask::$RUN_ID" echo "::add-mask::$RUN_URL" echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" From 6809a56957d15b17735eb34b16cdc8a9591acf58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 15:45:42 +0100 Subject: [PATCH 5/8] fix(release): update dependencies for GitHub release job to include verification steps --- .github/workflows/release.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index afa59467f..526b1c226 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -698,7 +698,8 @@ jobs: # Create GitHub Release with AI-generated release notes # --------------------------------------------------------------------------- github-release: - needs: [prepare, release-notes, build, release-cli-desktop] + needs: [prepare, release-notes, build, release-cli-desktop, bump-pinata, release-cli-docker-ce-wait, verify-docker-ce] + if: ${{ !cancelled() && !contains(needs.*.result, 'failure') }} runs-on: ubuntu-latest permissions: contents: write From 33b6bf0e7f8482070c58b5313cbe4885cce5d2b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 17:10:52 +0100 Subject: [PATCH 6/8] fix(release): refine manual approval process for Docker CE release workflow and clarify job dependencies --- .github/workflows/release.yml | 50 +++++++++-------------------------- 1 file changed, 13 insertions(+), 37 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 526b1c226..d911898f1 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -534,12 +534,10 @@ jobs: # --------------------------------------------------------------------------- # Release CLI for Docker CE — build .deb/.rpm packages and deploy # - # Split into two jobs: - # 1. release-cli-docker-ce-trigger: triggers packaging, waits for it, then - # triggers the deploy workflow. - # 2. release-cli-docker-ce-wait: requires manual approval (via the - # "release-repo-deploy" environment) before waiting for the deploy - # workflow to finish. + # Triggers packaging, waits for it, then triggers the deploy workflow. + # The verify-docker-ce job (which requires manual approval via the + # "release-repo-deploy" environment) runs after this to confirm the + # deploy completed successfully. # --------------------------------------------------------------------------- release-cli-docker-ce-trigger: if: ${{ !inputs.skipPackaging }} @@ -651,40 +649,18 @@ jobs: echo "✅ Deploy workflow triggered" # --------------------------------------------------------------------------- - # Wait for deploy — requires manual approval via the "release-repo-deploy" - # environment so the workflow does not block for hours. + # Verify Docker CE installation and server version — requires manual + # approval via the "release-repo-deploy" environment. Before approving, + # ensure the deploy workflow in docker/release-repo completed successfully. # - # Before approving this step: - # 1. Approve the deploy-to-live gate in the deploy workflow - # 2. Come back here and approve the "release-repo-deploy" environment - # --------------------------------------------------------------------------- - release-cli-docker-ce-wait: - needs: [prepare, release-cli-docker-ce-trigger] - runs-on: ubuntu-latest - environment: release-repo-deploy - permissions: - contents: read - steps: - - name: Wait for deploy workflow to complete - env: - GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} - RUN_ID: ${{ needs.release-cli-docker-ce-trigger.outputs.release_repo_run_id }} - run: | - echo "::add-mask::$RUN_ID" - echo "⏳ Waiting for deploy workflow to complete..." - gh run watch "$RUN_ID" \ - --repo docker/release-repo \ - --exit-status - echo "✅ Deploy workflow completed successfully" - - # --------------------------------------------------------------------------- - # Verify Docker CE installation and server version — install Docker CE, - # start the released model-runner image, and use `docker model version` - # to confirm both client and server versions match the release tag. + # Once approved, installs Docker CE, starts the released model-runner + # image, and uses `docker model version` to confirm both client and + # server versions match the release tag. # --------------------------------------------------------------------------- verify-docker-ce: - needs: [prepare, release-cli-docker-ce-wait, build] + needs: [prepare, release-cli-docker-ce-trigger, build] runs-on: ubuntu-latest + environment: release-repo-deploy steps: - name: Checkout code uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd @@ -698,7 +674,7 @@ jobs: # Create GitHub Release with AI-generated release notes # --------------------------------------------------------------------------- github-release: - needs: [prepare, release-notes, build, release-cli-desktop, bump-pinata, release-cli-docker-ce-wait, verify-docker-ce] + needs: [prepare, release-notes, build, release-cli-desktop, bump-pinata, verify-docker-ce] if: ${{ !cancelled() && !contains(needs.*.result, 'failure') }} runs-on: ubuntu-latest permissions: From 931ae455bc0d3a4123fcc37a7259dbc4e1d1513b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 17:15:05 +0100 Subject: [PATCH 7/8] fix(release): remove unused output variables from release workflow --- .github/workflows/release.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d911898f1..3a4b1d059 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -547,7 +547,6 @@ jobs: contents: read outputs: packaging_image: ${{ steps.packaging.outputs.packaging_image }} - release_repo_run_id: ${{ steps.trigger_release_repo.outputs.run_id }} steps: - name: Trigger packaging and wait for completion id: packaging @@ -645,7 +644,6 @@ jobs: echo "::add-mask::$RUN_ID" echo "::add-mask::$RUN_URL" - echo "run_id=$RUN_ID" >> "$GITHUB_OUTPUT" echo "✅ Deploy workflow triggered" # --------------------------------------------------------------------------- From 55bcea0518a23125cf71fa5e8fe08ebfcd51bfbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ignacio=20L=C3=B3pez=20Luna?= Date: Mon, 23 Feb 2026 17:20:30 +0100 Subject: [PATCH 8/8] fix(release): simplify deploy workflow trigger by removing unnecessary output handling --- .github/workflows/release.yml | 31 ++----------------------------- 1 file changed, 2 insertions(+), 29 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 3a4b1d059..ceb5463ae 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -604,46 +604,19 @@ jobs: echo "✅ Packaging workflow completed successfully" - name: Trigger deploy workflow - id: trigger_release_repo env: GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} VERSION: ${{ needs.prepare.outputs.version }} PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }} run: | echo "🚀 Triggering deploy workflow" - - # gh workflow run returns run URL on stdout (gh v2.87.0+) - OUTPUT=$(gh workflow run plugin.yml \ + gh workflow run plugin.yml \ --repo docker/release-repo \ --ref production \ -f packaging_image="$PACKAGING_IMAGE" \ -f model_version="$VERSION" \ -f channel=stable \ - -f release_live=true) - - RUN_URL=$(echo "$OUTPUT" \ - | grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true - - if [ -z "$RUN_URL" ]; then - echo "⚠️ Could not extract run URL from gh output, querying latest run..." - sleep 5 - RUN_ID=$(gh run list \ - --repo docker/release-repo \ - --workflow plugin.yml \ - --limit 1 \ - --json databaseId \ - --jq '.[0].databaseId') - else - RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$') - fi - - if [ -z "$RUN_ID" ]; then - echo "::error::Failed to determine deploy workflow run ID" - exit 1 - fi - - echo "::add-mask::$RUN_ID" - echo "::add-mask::$RUN_URL" + -f release_live=true echo "✅ Deploy workflow triggered" # ---------------------------------------------------------------------------