Release (auto patch bump) + latest #98
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: Release | |
| run-name: >- | |
| Release | |
| ${{ inputs.releaseTag != '' && inputs.releaseTag || format('(auto {0} bump)', inputs.bumpType || 'patch') }} | |
| ${{ inputs.pushLatest && ' + latest' || '' }} | |
| on: | |
| workflow_dispatch: | |
| inputs: | |
| bumpType: | |
| description: "Version bump type (ignored when releaseTag is provided)" | |
| required: false | |
| type: choice | |
| options: | |
| - patch | |
| - minor | |
| - major | |
| default: "patch" | |
| releaseTag: | |
| description: "Explicit release tag — overrides auto-bump (e.g., v1.2.3)" | |
| required: false | |
| type: string | |
| pushLatest: | |
| description: "Tag images produced by this job as latest" | |
| required: false | |
| type: boolean | |
| default: false | |
| llamaServerVersion: | |
| description: "llama-server version" | |
| required: false | |
| type: string | |
| default: "latest" | |
| vllmVersion: | |
| description: "vLLM version" | |
| required: false | |
| type: string | |
| default: "0.17.0" | |
| sglangVersion: | |
| description: "SGLang version" | |
| required: false | |
| type: string | |
| default: "0.4.0" | |
| # This can be removed once we have llama.cpp built for MUSA and CANN. | |
| buildMusaCann: | |
| description: "Build MUSA and CANN images" | |
| required: false | |
| type: boolean | |
| default: false | |
| imagesOnly: | |
| description: "Only build and push Docker images (skip CLI releases, pinata bump, docs update, and CE packaging)" | |
| required: false | |
| type: boolean | |
| default: false | |
| jobs: | |
| # --------------------------------------------------------------------------- | |
| # Determine or create the release tag. | |
| # Auto-bumps the latest tag (or uses explicit releaseTag if provided). | |
| # --------------------------------------------------------------------------- | |
| prepare: | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| outputs: | |
| release_tag: ${{ steps.resolve.outputs.release_tag }} | |
| version: ${{ steps.resolve.outputs.version }} | |
| previous_tag: ${{ steps.resolve.outputs.previous_tag }} | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| with: | |
| fetch-depth: 0 | |
| - name: Resolve release tag | |
| id: resolve | |
| env: | |
| EXPLICIT_TAG: ${{ inputs.releaseTag }} | |
| BUMP_TYPE: ${{ inputs.bumpType || 'patch' }} | |
| run: | | |
| # --- Find the latest existing v* tag --- | |
| LATEST_TAG=$(git tag --list 'v*' --sort=-v:refname | head -1) | |
| echo "Latest existing tag: ${LATEST_TAG:-<none>}" | |
| if [ -n "$EXPLICIT_TAG" ]; then | |
| # Validate explicit tag format | |
| if ! echo "$EXPLICIT_TAG" | grep -qE '^v[0-9]+\.[0-9]+\.[0-9]+$'; then | |
| echo "::error::Invalid release tag format: '$EXPLICIT_TAG'. Expected format: v<MAJOR>.<MINOR>.<PATCH> (e.g., v1.2.3)" | |
| exit 1 | |
| fi | |
| # Explicit tag provided — use it directly | |
| RELEASE_TAG="$EXPLICIT_TAG" | |
| VERSION="${EXPLICIT_TAG#v}" | |
| PREVIOUS_TAG="$LATEST_TAG" | |
| echo "Explicit tag provided: $RELEASE_TAG" | |
| else | |
| # Auto-bump from latest tag | |
| if [ -z "$LATEST_TAG" ]; then | |
| echo "No existing tags found — starting at v0.1.0" | |
| RELEASE_TAG="v0.1.0" | |
| VERSION="0.1.0" | |
| PREVIOUS_TAG="" | |
| else | |
| PREVIOUS_TAG="$LATEST_TAG" | |
| # Strip leading 'v' for parsing | |
| VERSION="${LATEST_TAG#v}" | |
| MAJOR=$(echo "$VERSION" | cut -d. -f1) | |
| MINOR=$(echo "$VERSION" | cut -d. -f2) | |
| PATCH=$(echo "$VERSION" | cut -d. -f3) | |
| case "$BUMP_TYPE" in | |
| major) | |
| MAJOR=$((MAJOR + 1)) | |
| MINOR=0 | |
| PATCH=0 | |
| ;; | |
| minor) | |
| MINOR=$((MINOR + 1)) | |
| PATCH=0 | |
| ;; | |
| patch) | |
| PATCH=$((PATCH + 1)) | |
| ;; | |
| esac | |
| VERSION="${MAJOR}.${MINOR}.${PATCH}" | |
| RELEASE_TAG="v${VERSION}" | |
| echo "Auto-bumped $BUMP_TYPE: $LATEST_TAG → $RELEASE_TAG" | |
| fi | |
| fi | |
| echo "release_tag=$RELEASE_TAG" >> "$GITHUB_OUTPUT" | |
| echo "version=$VERSION" >> "$GITHUB_OUTPUT" | |
| echo "previous_tag=${PREVIOUS_TAG:-}" >> "$GITHUB_OUTPUT" | |
| echo "🏷️ Release tag: $RELEASE_TAG" | |
| echo "🏷️ Version: $VERSION" | |
| echo "🏷️ Previous tag: ${PREVIOUS_TAG:-<none>}" | |
| - name: Create and push tag | |
| env: | |
| RELEASE_TAG: ${{ steps.resolve.outputs.release_tag }} | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| run: | | |
| # Check if the tag already exists | |
| if git rev-parse "$RELEASE_TAG" >/dev/null 2>&1; then | |
| echo "⚠️ Tag $RELEASE_TAG already exists — skipping creation" | |
| exit 0 | |
| fi | |
| echo "Creating tag $RELEASE_TAG on $(git rev-parse --short HEAD)" | |
| git tag "$RELEASE_TAG" | |
| git push origin "$RELEASE_TAG" | |
| echo "✅ Tag $RELEASE_TAG created and pushed" | |
| # --------------------------------------------------------------------------- | |
| # Generate release notes using cagent AI agent (runs in parallel with test) | |
| # --------------------------------------------------------------------------- | |
| release-notes: | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| with: | |
| fetch-depth: 0 | |
| - name: Generate release notes | |
| uses: docker/cagent-action@3a12dbd0c6cd7dda3d4e05f24f0143c9701456de | |
| with: | |
| agent: .github/agents/release-notes-generator.yaml | |
| anthropic-api-key: ${{ secrets.ANTHROPIC_API_KEY }} | |
| prompt: | | |
| **Release Tag:** ${{ needs.prepare.outputs.release_tag }} | |
| **Previous Tag:** ${{ needs.prepare.outputs.previous_tag }} | |
| **Repository:** docker/model-runner | |
| - name: Verify release notes | |
| env: | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| PREVIOUS_TAG: ${{ needs.prepare.outputs.previous_tag }} | |
| run: | | |
| if [ ! -f "release-notes.md" ]; then | |
| echo "::warning::Release notes were not generated. Using fallback." | |
| echo "## What's Changed" > release-notes.md | |
| echo "" >> release-notes.md | |
| if [ -n "$PREVIOUS_TAG" ]; then | |
| echo "**Full Changelog**: https://github.com/docker/model-runner/compare/${PREVIOUS_TAG}...${RELEASE_TAG}" >> release-notes.md | |
| else | |
| echo "**Full Changelog**: https://github.com/docker/model-runner/tree/${RELEASE_TAG}" >> release-notes.md | |
| fi | |
| fi | |
| echo "✅ Release notes:" | |
| cat release-notes.md | |
| - name: Upload release notes | |
| uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f | |
| with: | |
| name: release-notes | |
| path: release-notes.md | |
| # --------------------------------------------------------------------------- | |
| # Run tests | |
| # --------------------------------------------------------------------------- | |
| test: | |
| needs: prepare | |
| runs-on: ubuntu-latest | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Set up Go | |
| uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 | |
| with: | |
| go-version: 1.25.8 | |
| cache: true | |
| - name: Run tests | |
| run: go test -race ./... | |
| # --------------------------------------------------------------------------- | |
| # Build and push Docker images | |
| # --------------------------------------------------------------------------- | |
| build: | |
| needs: [prepare, test] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| env: | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| LLAMA_SERVER_VERSION: ${{ inputs.llamaServerVersion || 'latest' }} | |
| VLLM_VERSION: ${{ inputs.vllmVersion }} | |
| SGLANG_VERSION: ${{ inputs.sglangVersion || '0.4.0' }} | |
| PUSH_LATEST: ${{ inputs.pushLatest || 'false' }} | |
| BUILD_MUSA_CANN: ${{ inputs.buildMusaCann || 'false' }} | |
| steps: | |
| - name: Checkout repo | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Format tags | |
| id: tags | |
| shell: bash | |
| run: | | |
| echo "cpu<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "cuda<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-cuda" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-cuda" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "vllm-cuda<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-vllm-cuda" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-vllm-cuda" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "sglang-cuda<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-sglang-cuda" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-sglang-cuda" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "rocm<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-rocm" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-rocm" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "musa<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-musa" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-musa" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| echo "cann<<EOF" >> "$GITHUB_OUTPUT" | |
| echo "docker/model-runner:$RELEASE_TAG-cann" >> "$GITHUB_OUTPUT" | |
| if [ "$PUSH_LATEST" == "true" ]; then | |
| echo "docker/model-runner:latest-cann" >> "$GITHUB_OUTPUT" | |
| fi | |
| echo 'EOF' >> "$GITHUB_OUTPUT" | |
| - name: Log in to DockerHub | |
| uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 | |
| with: | |
| username: "docker" | |
| password: ${{ secrets.ORG_ACCESS_TOKEN }} | |
| - name: Set up Buildx | |
| uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0 | |
| with: | |
| version: "lab:latest" | |
| driver: cloud | |
| endpoint: "docker/make-product-smarter" | |
| install: true | |
| - name: Build CPU image | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-llamacpp | |
| platforms: linux/amd64, linux/arm64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.cpu }} | |
| - name: Build CUDA image | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-llamacpp | |
| platforms: linux/amd64, linux/arm64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=cuda" | |
| "BASE_IMAGE=nvidia/cuda:12.9.0-runtime-ubuntu24.04" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.cuda }} | |
| - name: Build vLLM CUDA image | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-vllm | |
| platforms: linux/amd64, linux/arm64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=cuda" | |
| "BASE_IMAGE=nvidia/cuda:13.0.2-runtime-ubuntu24.04" | |
| "VLLM_VERSION=${{ env.VLLM_VERSION }}" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.vllm-cuda }} | |
| - name: Build SGLang CUDA image | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-sglang | |
| platforms: linux/amd64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=cuda" | |
| "BASE_IMAGE=nvidia/cuda:12.9.0-runtime-ubuntu24.04" | |
| "SGLANG_VERSION=${{ env.SGLANG_VERSION }}" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.sglang-cuda }} | |
| - name: Build ROCm image | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-llamacpp | |
| platforms: linux/amd64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=rocm" | |
| "BASE_IMAGE=rocm/dev-ubuntu-22.04" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.rocm }} | |
| - name: Build MUSA image | |
| if: ${{ env.BUILD_MUSA_CANN == 'true' }} | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-llamacpp | |
| platforms: linux/amd64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=musa" | |
| "BASE_IMAGE=mthreads/musa:rc4.3.0-runtime-ubuntu22.04-amd64" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.musa }} | |
| - name: Build CANN image | |
| if: ${{ env.BUILD_MUSA_CANN == 'true' }} | |
| uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 | |
| with: | |
| file: Dockerfile | |
| target: final-llamacpp | |
| platforms: linux/arm64, linux/amd64 | |
| build-args: | | |
| "LLAMA_SERVER_VERSION=${{ env.LLAMA_SERVER_VERSION }}" | |
| "LLAMA_SERVER_VARIANT=cann" | |
| "BASE_IMAGE=ascendai/cann:8.2.rc2-910b-ubuntu22.04-py3.11" | |
| "VERSION=${{ env.RELEASE_TAG }}" | |
| push: true | |
| sbom: true | |
| provenance: mode=max | |
| tags: ${{ steps.tags.outputs.cann }} | |
| # --------------------------------------------------------------------------- | |
| # Release CLI for Docker Desktop — build, sign & push CLI + Desktop module image | |
| # --------------------------------------------------------------------------- | |
| release-cli-desktop: | |
| if: ${{ !inputs.imagesOnly }} | |
| needs: [prepare, test] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - 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: | | |
| echo "🚀 Triggering Desktop CLI release workflow" | |
| # 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") | |
| 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 | |
| echo "::add-mask::$RUN_ID" | |
| echo "::add-mask::$RUN_URL" | |
| echo "✅ Desktop CLI release workflow triggered" | |
| echo "⏳ Waiting for Desktop CLI release to complete..." | |
| gh run watch "$RUN_ID" \ | |
| --repo docker/inference-engine-llama.cpp \ | |
| --exit-status | |
| echo "✅ Desktop CLI release completed successfully" | |
| # --------------------------------------------------------------------------- | |
| # Bump docker-model version in pinata and open a PR | |
| # --------------------------------------------------------------------------- | |
| bump-pinata: | |
| if: ${{ !inputs.imagesOnly }} | |
| needs: [prepare, release-cli-desktop] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Checkout pinata | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| with: | |
| repository: docker/pinata | |
| token: ${{ secrets.CLI_RELEASE_PAT }} | |
| fetch-depth: 0 | |
| - name: Bump docker-model version in build.json | |
| env: | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| NEW_VERSION="v${VERSION}" | |
| jq --arg v "$NEW_VERSION" '.["docker-model"].version = $v' build.json > build.json.tmp | |
| mv build.json.tmp build.json | |
| - name: Create pull request | |
| uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 | |
| with: | |
| token: ${{ secrets.CLI_RELEASE_PAT }} | |
| base: main | |
| commit-message: "chore: bump docker-model to v${{ needs.prepare.outputs.version }}" | |
| branch: bump-docker-model-v${{ needs.prepare.outputs.version }} | |
| title: "Bump docker-model to v${{ needs.prepare.outputs.version }}" | |
| body: | | |
| ### Ticket(s) | |
| N/A — automated version bump | |
| ### What this PR does | |
| Bumps docker-model version to v${{ needs.prepare.outputs.version }} in build.json. | |
| ### Notes for the reviewer | |
| Automated PR created by the model-runner release workflow. | |
| draft: true | |
| # --------------------------------------------------------------------------- | |
| # Update CLI reference docs in docker/docs | |
| # --------------------------------------------------------------------------- | |
| update-docs: | |
| if: ${{ !inputs.imagesOnly }} | |
| needs: [prepare] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| steps: | |
| - name: Check if CLI docs changed | |
| id: check-docs | |
| env: | |
| GH_TOKEN: ${{ secrets.CLI_RELEASE_PAT }} | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| PREVIOUS_TAG: ${{ needs.prepare.outputs.previous_tag }} | |
| run: | | |
| if [ -z "$PREVIOUS_TAG" ]; then | |
| echo "No previous tag — assuming docs changed" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| exit 0 | |
| fi | |
| CHANGED=$(gh api repos/docker/model-runner/compare/${PREVIOUS_TAG}...${RELEASE_TAG} \ | |
| --jq '[.files[].filename | select(startswith("cmd/cli/docs/reference/"))] | length') | |
| if [ "$CHANGED" -gt 0 ]; then | |
| echo "CLI docs changed ($CHANGED files)" | |
| echo "changed=true" >> "$GITHUB_OUTPUT" | |
| else | |
| echo "No CLI docs changes between $PREVIOUS_TAG and $RELEASE_TAG — skipping" | |
| echo "changed=false" >> "$GITHUB_OUTPUT" | |
| fi | |
| - name: Checkout docs | |
| if: steps.check-docs.outputs.changed == 'true' | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| with: | |
| repository: docker/docs | |
| token: ${{ secrets.CLI_RELEASE_PAT }} | |
| fetch-depth: 0 | |
| - name: Set up Go | |
| if: steps.check-docs.outputs.changed == 'true' | |
| uses: actions/setup-go@4b73464bb391d4059bd26b0524d20df3927bd417 | |
| with: | |
| go-version: 1.25.8 | |
| cache: true | |
| - name: Vendor model-runner CLI docs | |
| if: steps.check-docs.outputs.changed == 'true' | |
| env: | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| run: | | |
| VENDOR_MODULE=github.com/docker/model-runner@${RELEASE_TAG} make vendor | |
| # Remove the second require block added by `go get` — the docs repo | |
| # only needs the direct dependency in the first require block. | |
| awk '/^require \(/{n++} n==2{if(/^\)/) n=3; next} n!=2' go.mod > go.mod.tmp && mv go.mod.tmp go.mod | |
| - name: Create pull request | |
| if: steps.check-docs.outputs.changed == 'true' | |
| uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 | |
| with: | |
| token: ${{ secrets.DOCKER_DOCS }} | |
| base: main | |
| push-to-fork: ilopezluna/docs | |
| commit-message: | | |
| vendor: github.com/docker/model-runner ${{ needs.prepare.outputs.release_tag }} | |
| See changes in https://github.com/docker/model-runner/compare/${{ needs.prepare.outputs.previous_tag }}...${{ needs.prepare.outputs.release_tag }}. | |
| branch: update-model-runner-${{ needs.prepare.outputs.release_tag }} | |
| title: "vendor: github.com/docker/model-runner ${{ needs.prepare.outputs.release_tag }}" | |
| body: | | |
| ## Description | |
| Update Model Runner CLI docs. | |
| See changes in https://github.com/docker/model-runner/compare/${{ needs.prepare.outputs.previous_tag }}...${{ needs.prepare.outputs.release_tag }}. | |
| ``` | |
| VENDOR_MODULE=github.com/docker/model-runner@${{ needs.prepare.outputs.release_tag }} make vendor | |
| ``` | |
| ## Reviews | |
| <!-- Notes for reviewers here --> | |
| <!-- List applicable reviews (optionally @tag reviewers) --> | |
| - [ ] Technical review | |
| - [ ] Editorial review | |
| - [ ] Product review | |
| draft: true | |
| # --------------------------------------------------------------------------- | |
| # Release CLI for Docker CE — build .deb/.rpm packages and deploy | |
| # | |
| # 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.imagesOnly }} | |
| needs: [prepare, release-cli-desktop] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: read | |
| outputs: | |
| packaging_image: ${{ steps.packaging.outputs.packaging_image }} | |
| steps: | |
| - 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 }} | |
| run: | | |
| echo "📦 Triggering packaging workflow" | |
| # 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") | |
| 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 | |
| echo "::add-mask::$RUN_ID" | |
| echo "::add-mask::$RUN_URL" | |
| echo "✅ Packaging workflow triggered" | |
| echo "⏳ Waiting for packaging to complete..." | |
| gh run watch "$RUN_ID" \ | |
| --repo docker/packaging \ | |
| --exit-status | |
| # Get the run number to construct the image tag | |
| RUN_NUMBER=$(gh run view "$RUN_ID" \ | |
| --repo docker/packaging \ | |
| --json number \ | |
| --jq '.number') | |
| PACKAGING_IMAGE="dockereng/packaging:model-v${VERSION}-${RUN_NUMBER}" | |
| echo "::add-mask::$PACKAGING_IMAGE" | |
| echo "packaging_image=$PACKAGING_IMAGE" >> "$GITHUB_OUTPUT" | |
| echo "✅ Packaging workflow completed successfully" | |
| - name: Trigger deploy workflow | |
| 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 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 "✅ Deploy workflow triggered" | |
| # --------------------------------------------------------------------------- | |
| # 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. | |
| # | |
| # 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: | |
| if: ${{ !inputs.imagesOnly }} | |
| needs: [prepare, release-cli-docker-ce-trigger, build] | |
| runs-on: ubuntu-latest | |
| environment: release-repo-deploy | |
| steps: | |
| - name: Checkout code | |
| uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd | |
| - name: Verify client and server versions | |
| run: | | |
| chmod +x scripts/test-docker-ce-installation.sh | |
| ./scripts/test-docker-ce-installation.sh "${{ needs.prepare.outputs.release_tag }}" | |
| # --------------------------------------------------------------------------- | |
| # Create GitHub Release with AI-generated release notes | |
| # --------------------------------------------------------------------------- | |
| github-release: | |
| needs: [prepare, release-notes, build, release-cli-desktop, bump-pinata, update-docs, verify-docker-ce] | |
| if: ${{ !cancelled() && !contains(needs.*.result, 'failure') }} | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - name: Download release notes | |
| uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c | |
| with: | |
| name: release-notes | |
| - name: Create GitHub Release | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| VERSION: ${{ needs.prepare.outputs.version }} | |
| run: | | |
| echo "Creating GitHub Release for $RELEASE_TAG" | |
| gh release create "$RELEASE_TAG" \ | |
| --repo docker/model-runner \ | |
| --title "Docker Model Runner $RELEASE_TAG" \ | |
| --notes-file release-notes.md | |
| - name: Send Slack notification | |
| if: success() | |
| env: | |
| RELEASE_TAG: ${{ needs.prepare.outputs.release_tag }} | |
| SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }} | |
| run: | | |
| BUILD_URL="${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}" | |
| RELEASE_URL="https://github.com/docker/model-runner/releases/tag/${RELEASE_TAG}" | |
| SLACK_MESSAGE=$(cat <<EOF | |
| { | |
| "text": "🚀 Docker Model Runner ${RELEASE_TAG} has been released!", | |
| "blocks": [ | |
| { | |
| "type": "header", | |
| "text": { | |
| "type": "plain_text", | |
| "text": "🚀 Docker Model Runner Released" | |
| } | |
| }, | |
| { | |
| "type": "section", | |
| "fields": [ | |
| { | |
| "type": "mrkdwn", | |
| "text": "*Version:*\n${RELEASE_TAG}" | |
| }, | |
| { | |
| "type": "mrkdwn", | |
| "text": "*Repository:*\ndocker/model-runner" | |
| } | |
| ] | |
| }, | |
| { | |
| "type": "actions", | |
| "elements": [ | |
| { | |
| "type": "button", | |
| "text": { | |
| "type": "plain_text", | |
| "text": "View Release" | |
| }, | |
| "url": "${RELEASE_URL}", | |
| "style": "primary" | |
| }, | |
| { | |
| "type": "button", | |
| "text": { | |
| "type": "plain_text", | |
| "text": "View Build" | |
| }, | |
| "url": "${BUILD_URL}" | |
| } | |
| ] | |
| } | |
| ] | |
| } | |
| EOF | |
| ) | |
| curl -X POST -H 'Content-type: application/json' \ | |
| --data "${SLACK_MESSAGE}" \ | |
| "${SLACK_WEBHOOK_URL}" |