From 55e619b81218868e258d7698c5c42dafce077aea Mon Sep 17 00:00:00 2001 From: Alex Date: Sat, 12 Sep 2026 23:29:33 +0100 Subject: [PATCH] ci: let the image workflows be run by hand None of the three image workflows could be started manually, so when 0.20.0 tagged before the release chain knew about the frontend and sandbox images, there was no way to build those images for the tag short of recreating the release. Add a workflow_dispatch trigger taking the version to build. A manual run also gets a `move_latest` switch, so rebuilding an older tag does not drag `latest` backwards. The rule for the moving tag now lives in the manifest step's shell rather than in a nested expression: `latest` follows the build unless the release is a prerelease, the run asked it not to, or it is the rolling `develop` build. --- .github/workflows/ci.yml | 35 +++++++++++++++++++++++----- .github/workflows/cife.yml | 36 ++++++++++++++++++++++------- .github/workflows/sandbox-image.yml | 36 ++++++++++++++++++++++------- 3 files changed, 85 insertions(+), 22 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b2985af5..af3d1137 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -14,11 +14,25 @@ on: description: Release tag to build and push (the images are tagged with it) type: string required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true secrets: DOCKER_USERNAME: required: true DOCKER_PASSWORD: required: true + workflow_dispatch: + inputs: + version: + description: Release tag to build and push (the images are tagged with it) + type: string + required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true permissions: contents: read @@ -142,15 +156,24 @@ jobs: - name: Create and push multi-arch manifests env: TAG: ${{ env.RELEASE_TAG }}${{ matrix.variant }} - # A stable release moves `latest`; a prerelease published by hand - # moves only its own tag (the release trigger fires for those too). - LATEST: ${{ (inputs.version || !github.event.release.prerelease) && format('latest{0}', matrix.variant) || '' }} + VARIANT: ${{ matrix.variant }} + # Raw facts; the shell below decides from them what `latest` does. + IS_PRERELEASE: ${{ github.event.release.prerelease || false }} + MOVE_LATEST: ${{ inputs.move_latest }} run: | set -e - # $LATEST is deliberately unquoted: it is empty for a prerelease, and - # an empty word would create a manifest named "$repo:". + # `latest` follows this build, except for a release marked prerelease + # (the release trigger fires for those too) or a manual run that asked + # it not to. MOVE_LATEST is empty for a release event, where only the + # prerelease flag decides. + moving="latest${VARIANT}" + if [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then + moving="" + fi + # $moving is deliberately unquoted: an empty word would create a + # manifest named "$repo:". for repo in "$DOCKERHUB_NAMESPACE/docsgpt" "ghcr.io/${{ github.repository_owner }}/docsgpt"; do - for name in "$TAG" $LATEST; do + for name in "$TAG" $moving; do docker manifest create "$repo:$name" \ --amend "$repo:$TAG-amd64" \ --amend "$repo:$TAG-arm64" diff --git a/.github/workflows/cife.yml b/.github/workflows/cife.yml index 6c8c301f..11ddaa9f 100644 --- a/.github/workflows/cife.yml +++ b/.github/workflows/cife.yml @@ -14,11 +14,25 @@ on: description: Release tag to build and push (the images are tagged with it) type: string required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true secrets: DOCKER_USERNAME: required: true DOCKER_PASSWORD: required: true + workflow_dispatch: + inputs: + version: + description: Release tag to build and push (the images are tagged with it) + type: string + required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true permissions: contents: read @@ -26,10 +40,6 @@ permissions: env: # The tag being published: passed in by the caller, or the release's own. RELEASE_TAG: ${{ inputs.version || github.event.release.tag_name }} - # A stable release also moves `latest`. A prerelease published by hand moves - # only its own tag: the release trigger fires for those too, and they must not - # become `latest`. - MOVING_TAG: ${{ (inputs.version || !github.event.release.prerelease) && 'latest' || '' }} jobs: build: @@ -143,13 +153,23 @@ jobs: - name: Create and push multi-arch manifests env: TAG: ${{ env.RELEASE_TAG }} - MOVING: ${{ env.MOVING_TAG }} + # Raw facts; the shell below decides from them what `latest` does. + IS_PRERELEASE: ${{ github.event.release.prerelease || false }} + MOVE_LATEST: ${{ inputs.move_latest }} run: | set -e - # $MOVING is deliberately unquoted: it is empty for a prerelease, and - # an empty word would create a manifest named "$repo:". + # `latest` follows this build, except for a release marked prerelease + # (the release trigger fires for those too) or a manual run that asked + # it not to. MOVE_LATEST is empty for a release event, where only the + # prerelease flag decides. + moving=latest + if [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then + moving="" + fi + # $moving is deliberately unquoted: an empty word would create a + # manifest named "$repo:". for repo in "$DOCKERHUB_NAMESPACE/docsgpt-fe" "ghcr.io/${{ github.repository_owner }}/docsgpt-fe"; do - for name in "$TAG" $MOVING; do + for name in "$TAG" $moving; do docker manifest create "$repo:$name" \ --amend "$repo:$TAG-amd64" \ --amend "$repo:$TAG-arm64" diff --git a/.github/workflows/sandbox-image.yml b/.github/workflows/sandbox-image.yml index c26e5b8d..96303100 100644 --- a/.github/workflows/sandbox-image.yml +++ b/.github/workflows/sandbox-image.yml @@ -21,11 +21,25 @@ on: description: Release tag to build and push (the images are tagged with it) type: string required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true secrets: DOCKER_USERNAME: required: true DOCKER_PASSWORD: required: true + workflow_dispatch: + inputs: + version: + description: Release tag to build and push (the images are tagged with it) + type: string + required: true + move_latest: + description: Also move the `latest` tag onto this build + type: boolean + default: true push: branches: [main] paths: @@ -38,10 +52,6 @@ permissions: env: # The version being published, or `develop` for a push to main. RELEASE_TAG: ${{ inputs.version || github.event.release.tag_name || 'develop' }} - # A stable release also moves `latest`. A push to main moves nothing but - # `develop`, and a prerelease published by hand moves only its own tag: the - # release trigger fires for those too, and they must not become `latest`. - MOVING_TAG: ${{ (inputs.version || (github.event.release.tag_name && !github.event.release.prerelease)) && 'latest' || '' }} jobs: build: @@ -155,13 +165,23 @@ jobs: - name: Create and push multi-arch manifests env: TAG: ${{ env.RELEASE_TAG }} - MOVING: ${{ env.MOVING_TAG }} + # Raw facts; the shell below decides from them what `latest` does. + IS_PRERELEASE: ${{ github.event.release.prerelease || false }} + MOVE_LATEST: ${{ inputs.move_latest }} run: | set -e - # $MOVING is deliberately unquoted: it is empty for a push to main, - # and an empty word would create a manifest named "$repo:". + # `latest` follows this build, except for the rolling `develop` build, + # a release marked prerelease (the release trigger fires for those + # too), or a manual run that asked it not to. MOVE_LATEST is empty for + # a release event and for a push, where the other two rules decide. + moving=latest + if [ "$TAG" = develop ] || [ "$IS_PRERELEASE" = true ] || [ "$MOVE_LATEST" = false ]; then + moving="" + fi + # $moving is deliberately unquoted: an empty word would create a + # manifest named "$repo:". for repo in "$DOCKERHUB_NAMESPACE/docsgpt-sandbox" "ghcr.io/${{ github.repository_owner }}/docsgpt-sandbox"; do - for name in "$TAG" $MOVING; do + for name in "$TAG" $moving; do docker manifest create "$repo:$name" \ --amend "$repo:$TAG-amd64" \ --amend "$repo:$TAG-arm64"