Skip to content

Commit f201ba0

Browse files
authored
implement manual approval for Docker CE release workflow (#705)
* fix(release): implement manual approval for Docker CE release workflow and enhance job structure * fix(release): streamline release workflows by removing unnecessary wait steps and enhancing trigger feedback * fix(release): remove unnecessary output redirection in workflow run commands * fix(release): enhance workflow run commands to extract run URLs and IDs more reliably * fix(release): update dependencies for GitHub release job to include verification steps * fix(release): refine manual approval process for Docker CE release workflow and clarify job dependencies * fix(release): remove unused output variables from release workflow * fix(release): simplify deploy workflow trigger by removing unnecessary output handling
1 parent 32a2323 commit f201ba0

1 file changed

Lines changed: 75 additions & 146 deletions

File tree

.github/workflows/release.yml

Lines changed: 75 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -432,76 +432,64 @@ jobs:
432432

433433
# ---------------------------------------------------------------------------
434434
# Release CLI for Docker Desktop — build, sign & push CLI + Desktop module image
435-
# (triggers docker/inference-engine-llama.cpp: signs macOS/Windows binaries,
436-
# pushes docker/docker-model-cli-desktop-module to Docker Hub)
437435
# ---------------------------------------------------------------------------
438436
release-cli-desktop:
439437
needs: [prepare, test]
440438
runs-on: ubuntu-latest
441-
timeout-minutes: 60
442439
permissions:
443440
contents: read
444441
steps:
445-
- name: Trigger release-cli-dd workflow
446-
id: trigger
442+
- name: Trigger Desktop CLI release and wait for completion
447443
env:
448444
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
449445
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
450446
VERSION: ${{ needs.prepare.outputs.version }}
451447
run: |
452-
TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
453-
echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT"
454-
echo "🚀 Triggering release-cli-dd workflow at $TRIGGER_TIME"
455-
echo " model-cli-ref: $RELEASE_TAG"
456-
echo " tag: v$VERSION"
457-
gh workflow run release-cli-dd.yml \
448+
echo "🚀 Triggering Desktop CLI release workflow"
449+
450+
# gh workflow run returns run URL on stdout (gh v2.87.0+)
451+
OUTPUT=$(gh workflow run release-cli-dd.yml \
458452
--repo docker/inference-engine-llama.cpp \
459453
-f model-cli-ref="$RELEASE_TAG" \
460-
-f tag="v$VERSION"
461-
echo "✅ release-cli-dd workflow triggered"
454+
-f tag="v$VERSION")
462455
463-
- name: Wait for release-cli-dd to complete
464-
env:
465-
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
466-
TRIGGER_TIME: ${{ steps.trigger.outputs.trigger_time }}
467-
run: |
468-
echo "⏳ Waiting for release-cli-dd workflow to appear (triggered at $TRIGGER_TIME)..."
469-
sleep 15
456+
RUN_URL=$(echo "$OUTPUT" \
457+
| grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true
470458
471-
# Find the run created after our trigger time to avoid picking up unrelated runs
472-
for i in $(seq 1 30); do
459+
if [ -z "$RUN_URL" ]; then
460+
echo "⚠️ Could not extract run URL from gh output, querying latest run..."
461+
sleep 5
473462
RUN_ID=$(gh run list \
474463
--repo docker/inference-engine-llama.cpp \
475464
--workflow release-cli-dd.yml \
476-
--limit 5 \
477-
--json databaseId,createdAt \
478-
--jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId")
479-
if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
480-
echo "Found release-cli-dd run: $RUN_ID"
481-
break
482-
fi
483-
echo " Retry $i/30..."
484-
sleep 10
485-
done
465+
--limit 1 \
466+
--json databaseId \
467+
--jq '.[0].databaseId')
468+
else
469+
RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$')
470+
fi
486471
487-
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
488-
echo "::error::Could not find release-cli-dd workflow run created after $TRIGGER_TIME"
472+
if [ -z "$RUN_ID" ]; then
473+
echo "::error::Failed to determine workflow run ID"
489474
exit 1
490475
fi
491476
492-
echo "⏳ Waiting for release-cli-dd run $RUN_ID to complete..."
477+
echo "::add-mask::$RUN_ID"
478+
echo "::add-mask::$RUN_URL"
479+
echo "✅ Desktop CLI release workflow triggered"
480+
481+
echo "⏳ Waiting for Desktop CLI release to complete..."
493482
gh run watch "$RUN_ID" \
494483
--repo docker/inference-engine-llama.cpp \
495484
--exit-status
496-
echo "✅ release-cli-dd workflow completed successfully"
485+
echo "✅ Desktop CLI release completed successfully"
497486
498487
# ---------------------------------------------------------------------------
499488
# Bump docker-model version in pinata and open a PR
500489
# ---------------------------------------------------------------------------
501490
bump-pinata:
502491
needs: [prepare, release-cli-desktop]
503492
runs-on: ubuntu-latest
504-
timeout-minutes: 10
505493
permissions:
506494
contents: read
507495
steps:
@@ -544,64 +532,62 @@ jobs:
544532
draft: true
545533

546534
# ---------------------------------------------------------------------------
547-
# Release CLI for Docker CE — build .deb/.rpm packages and deploy to download.docker.com
548-
# (triggers docker/packaging → docker/release-repo)
535+
# Release CLI for Docker CE — build .deb/.rpm packages and deploy
536+
#
537+
# Triggers packaging, waits for it, then triggers the deploy workflow.
538+
# The verify-docker-ce job (which requires manual approval via the
539+
# "release-repo-deploy" environment) runs after this to confirm the
540+
# deploy completed successfully.
549541
# ---------------------------------------------------------------------------
550-
release-cli-docker-ce:
542+
release-cli-docker-ce-trigger:
551543
if: ${{ !inputs.skipPackaging }}
552544
needs: [prepare, release-cli-desktop]
553545
runs-on: ubuntu-latest
554-
timeout-minutes: 360
555546
permissions:
556547
contents: read
548+
outputs:
549+
packaging_image: ${{ steps.packaging.outputs.packaging_image }}
557550
steps:
558-
- name: Trigger release-model workflow in packaging repo
559-
id: trigger
551+
- name: Trigger packaging and wait for completion
552+
id: packaging
560553
env:
561554
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
562555
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
556+
VERSION: ${{ needs.prepare.outputs.version }}
563557
run: |
564-
TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
565-
echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT"
566-
echo "📦 Triggering release-model workflow in docker/packaging at $TRIGGER_TIME"
567-
echo " ref: $RELEASE_TAG"
568-
gh workflow run release-model.yml \
558+
echo "📦 Triggering packaging workflow"
559+
560+
# gh workflow run returns run URL on stdout (gh v2.87.0+)
561+
OUTPUT=$(gh workflow run release-model.yml \
569562
--repo docker/packaging \
570-
-f ref="$RELEASE_TAG"
571-
echo "✅ release-model workflow triggered in docker/packaging"
563+
-f ref="$RELEASE_TAG")
572564
573-
- name: Wait for packaging workflow to complete
574-
id: packaging
575-
env:
576-
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
577-
VERSION: ${{ needs.prepare.outputs.version }}
578-
TRIGGER_TIME: ${{ steps.trigger.outputs.trigger_time }}
579-
run: |
580-
echo "⏳ Waiting for packaging workflow to appear (triggered at $TRIGGER_TIME)..."
581-
sleep 15
565+
RUN_URL=$(echo "$OUTPUT" \
566+
| grep -o 'https://github.com/[^ ]*/actions/runs/[0-9]*') || true
582567
583-
# Find the run created after our trigger time to avoid picking up unrelated runs
584-
for i in $(seq 1 30); do
568+
if [ -z "$RUN_URL" ]; then
569+
echo "⚠️ Could not extract run URL from gh output, querying latest run..."
570+
sleep 5
585571
RUN_ID=$(gh run list \
586572
--repo docker/packaging \
587573
--workflow release-model.yml \
588-
--limit 5 \
589-
--json databaseId,createdAt \
590-
--jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId")
591-
if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
592-
echo "Found packaging run: $RUN_ID"
593-
break
594-
fi
595-
echo " Retry $i/30..."
596-
sleep 10
597-
done
574+
--limit 1 \
575+
--json databaseId \
576+
--jq '.[0].databaseId')
577+
else
578+
RUN_ID=$(echo "$RUN_URL" | grep -o '[0-9]*$')
579+
fi
598580
599-
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
600-
echo "::error::Could not find packaging workflow run created after $TRIGGER_TIME"
581+
if [ -z "$RUN_ID" ]; then
582+
echo "::error::Failed to determine packaging workflow run ID"
601583
exit 1
602584
fi
603585
604-
echo "⏳ Waiting for packaging run $RUN_ID to complete..."
586+
echo "::add-mask::$RUN_ID"
587+
echo "::add-mask::$RUN_URL"
588+
echo "✅ Packaging workflow triggered"
589+
590+
echo "⏳ Waiting for packaging to complete..."
605591
gh run watch "$RUN_ID" \
606592
--repo docker/packaging \
607593
--exit-status
@@ -613,97 +599,39 @@ jobs:
613599
--jq '.number')
614600
615601
PACKAGING_IMAGE="dockereng/packaging:model-v${VERSION}-${RUN_NUMBER}"
616-
echo "📦 Packaging image: $PACKAGING_IMAGE"
602+
echo "::add-mask::$PACKAGING_IMAGE"
617603
echo "packaging_image=$PACKAGING_IMAGE" >> "$GITHUB_OUTPUT"
618604
echo "✅ Packaging workflow completed successfully"
619605
620-
- name: Trigger release-repo plugin workflow
621-
id: trigger_release_repo
606+
- name: Trigger deploy workflow
622607
env:
623608
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
624609
VERSION: ${{ needs.prepare.outputs.version }}
625610
PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }}
626611
run: |
627-
TRIGGER_TIME=$(date -u +%Y-%m-%dT%H:%M:%SZ)
628-
echo "trigger_time=$TRIGGER_TIME" >> "$GITHUB_OUTPUT"
629-
echo "🚀 Triggering plugin release in docker/release-repo at $TRIGGER_TIME"
630-
echo " packaging_image: $PACKAGING_IMAGE"
631-
echo " model_version: $VERSION"
632-
echo " channel: stable"
633-
echo " release_live: true"
612+
echo "🚀 Triggering deploy workflow"
634613
gh workflow run plugin.yml \
635614
--repo docker/release-repo \
636615
--ref production \
637616
-f packaging_image="$PACKAGING_IMAGE" \
638617
-f model_version="$VERSION" \
639618
-f channel=stable \
640619
-f release_live=true
641-
echo "✅ Plugin release workflow triggered in docker/release-repo"
642-
643-
- name: Wait for release-repo plugin workflow to complete
644-
env:
645-
GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }}
646-
TRIGGER_TIME: ${{ steps.trigger_release_repo.outputs.trigger_time }}
647-
run: |
648-
echo "⏳ Waiting for release-repo plugin workflow to appear (triggered at $TRIGGER_TIME)..."
649-
sleep 15
650-
651-
# Find the run created after our trigger time to avoid picking up unrelated runs
652-
for i in $(seq 1 30); do
653-
RUN_ID=$(gh run list \
654-
--repo docker/release-repo \
655-
--workflow plugin.yml \
656-
--limit 5 \
657-
--json databaseId,createdAt \
658-
--jq "[.[] | select(.createdAt >= \"$TRIGGER_TIME\")] | sort_by(.createdAt) | last | .databaseId")
659-
if [ -n "$RUN_ID" ] && [ "$RUN_ID" != "null" ]; then
660-
echo "Found release-repo run: $RUN_ID"
661-
break
662-
fi
663-
echo " Retry $i/30..."
664-
sleep 10
665-
done
666-
667-
if [ -z "$RUN_ID" ] || [ "$RUN_ID" = "null" ]; then
668-
echo "::error::Could not find release-repo plugin workflow run created after $TRIGGER_TIME"
669-
exit 1
670-
fi
671-
672-
echo "⏳ Waiting for release-repo run $RUN_ID to complete (includes manual deploy-to-live approval)..."
673-
gh run watch "$RUN_ID" \
674-
--repo docker/release-repo \
675-
--exit-status
676-
echo "✅ Release-repo plugin workflow completed successfully"
677-
678-
- name: Post summary
679-
env:
680-
VERSION: ${{ needs.prepare.outputs.version }}
681-
RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }}
682-
PACKAGING_IMAGE: ${{ steps.packaging.outputs.packaging_image }}
683-
run: |
684-
cat >> "$GITHUB_STEP_SUMMARY" <<-SUMMARY
685-
## 📦 Docker CE Packaging & Release
686-
687-
| Step | Status |
688-
|------|--------|
689-
| Packaging image | \`${PACKAGING_IMAGE}\` |
690-
| Model version | \`${VERSION}\` |
691-
| Release channel | \`stable\` |
692-
| Deploy to live | ✅ Yes |
693-
| Release tag | \`${RELEASE_TAG}\` |
694-
695-
The plugin release workflow has been triggered in [docker/release-repo](https://github.com/docker/release-repo/actions/workflows/plugin.yml).
696-
SUMMARY
620+
echo "✅ Deploy workflow triggered"
697621
698622
# ---------------------------------------------------------------------------
699-
# Verify Docker CE installation and server version — install Docker CE,
700-
# start the released model-runner image, and use `docker model version`
701-
# to confirm both client and server versions match the release tag.
623+
# Verify Docker CE installation and server version — requires manual
624+
# approval via the "release-repo-deploy" environment. Before approving,
625+
# ensure the deploy workflow in docker/release-repo completed successfully.
626+
#
627+
# Once approved, installs Docker CE, starts the released model-runner
628+
# image, and uses `docker model version` to confirm both client and
629+
# server versions match the release tag.
702630
# ---------------------------------------------------------------------------
703631
verify-docker-ce:
704-
needs: [prepare, release-cli-docker-ce, build]
632+
needs: [prepare, release-cli-docker-ce-trigger, build]
705633
runs-on: ubuntu-latest
706-
timeout-minutes: 15
634+
environment: release-repo-deploy
707635
steps:
708636
- name: Checkout code
709637
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
@@ -717,7 +645,8 @@ jobs:
717645
# Create GitHub Release with AI-generated release notes
718646
# ---------------------------------------------------------------------------
719647
github-release:
720-
needs: [prepare, release-notes, build, release-cli-desktop]
648+
needs: [prepare, release-notes, build, release-cli-desktop, bump-pinata, verify-docker-ce]
649+
if: ${{ !cancelled() && !contains(needs.*.result, 'failure') }}
721650
runs-on: ubuntu-latest
722651
permissions:
723652
contents: write

0 commit comments

Comments
 (0)