@@ -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