From 697cb29015e0d0c300edf99b5945ae32430e1d2d Mon Sep 17 00:00:00 2001 From: maxgfr <25312957+maxgfr@users.noreply.github.com> Date: Mon, 5 Oct 2026 12:06:01 +0200 Subject: [PATCH] ci: publish both images on every push to main codeindex was only published when semantic-release cut a release, and codeindex-embed only when docker/embed/** changed. Now: - main-image.yml chains on the Release workflow (push or dispatch) and, once its gate passes, pushes ghcr.io/maxgfr/codeindex:main and :sha-. latest and version tags stay owned by release.yml. - embed-image.yml drops its path filter, adds :main and :sha-, and also runs after dispatched Release runs so commits merged by grammars-repin (GITHUB_TOKEN, no push event) get an image too. --- .github/workflows/embed-image.yml | 32 ++++++++++------ .github/workflows/main-image.yml | 61 +++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+), 11 deletions(-) create mode 100644 .github/workflows/main-image.yml diff --git a/.github/workflows/embed-image.yml b/.github/workflows/embed-image.yml index f3d8c87..f50ef5c 100644 --- a/.github/workflows/embed-image.yml +++ b/.github/workflows/embed-image.yml @@ -1,19 +1,22 @@ name: Embed image # Publishes the rich-tier embedding server image (Role B): -# ghcr.io/maxgfr/codeindex-embed. Unlike the distribution image (built inside the -# release job because semantic-release's GITHUB_TOKEN pushes don't retrigger -# workflows), this image is driven by ordinary HUMAN pushes that touch -# docker/embed/** — those DO trigger `on: push`, so a plain path-filtered -# workflow is correct here (no anti-recursion gymnastics needed). The version is -# read from the committed docker/embed/VERSION file (starts at 1.0.0); bump it in -# the same commit that changes the server/model. +# ghcr.io/maxgfr/codeindex-embed. Rebuilt on every push to `main` (tagged +# `main` and `sha-`), so the registry always carries an image for the +# current commit. The version tag is read from the committed +# docker/embed/VERSION file (starts at 1.0.0); bump it in the same commit that +# changes the server/model. +# +# Commits merged by grammars-repin with GITHUB_TOKEN never fire `on: push`; that +# job dispatches Release instead, so a dispatched Release run is the trigger for +# those (the `if:` below skips push-started Release runs, already built by push). on: push: branches: [main] - paths: - - "docker/embed/**" - - ".github/workflows/embed-image.yml" + workflow_run: + workflows: [Release] + types: [completed] + branches: [main] workflow_dispatch: permissions: @@ -22,13 +25,18 @@ permissions: jobs: build-and-push: + if: github.event_name != 'workflow_run' || github.event.workflow_run.event == 'workflow_dispatch' runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_sha || github.sha }} - name: Read image version id: meta - run: echo "version=$(cat docker/embed/VERSION)" >> "$GITHUB_OUTPUT" + run: | + echo "version=$(cat docker/embed/VERSION)" >> "$GITHUB_OUTPUT" + echo "short=$(git rev-parse --short=7 HEAD)" >> "$GITHUB_OUTPUT" - name: Set up QEMU uses: docker/setup-qemu-action@v3 @@ -56,3 +64,5 @@ jobs: tags: | ghcr.io/maxgfr/codeindex-embed:${{ steps.meta.outputs.version }} ghcr.io/maxgfr/codeindex-embed:latest + ghcr.io/maxgfr/codeindex-embed:main + ghcr.io/maxgfr/codeindex-embed:sha-${{ steps.meta.outputs.short }} diff --git a/.github/workflows/main-image.yml b/.github/workflows/main-image.yml new file mode 100644 index 0000000..b0d346f --- /dev/null +++ b/.github/workflows/main-image.yml @@ -0,0 +1,61 @@ +name: Main image + +# Publishes ghcr.io/maxgfr/codeindex:main and :sha- for every commit that +# lands on `main`, release or not. `latest` and the version tags stay owned by +# the release job (release.yml), since consumers pin those. +# +# Chained on the Release workflow rather than `on: push`: Release is also +# started by `workflow_dispatch` (grammars-repin self-merges with GITHUB_TOKEN, +# which never fires `on: push`), and waiting for it means the image is only +# published once the typecheck / test / bundle gate has passed. +on: + workflow_run: + workflows: [Release] + types: [completed] + branches: [main] + workflow_dispatch: + +permissions: + contents: read + packages: write + +concurrency: + group: main-image + cancel-in-progress: true + +jobs: + build-and-push: + if: github.event_name == 'workflow_dispatch' || github.event.workflow_run.conclusion == 'success' + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.workflow_run.head_sha || github.sha }} + + - name: Short SHA + id: sha + run: echo "short=$(git rev-parse --short=7 HEAD)" >> "$GITHUB_OUTPUT" + + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to ghcr.io + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + # Same build as the release image (multi-arch, repo-root Dockerfile). + - name: Build and push + run: | + docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --build-arg VERSION="sha-${{ steps.sha.outputs.short }}" \ + --push \ + -t ghcr.io/maxgfr/codeindex:main \ + -t ghcr.io/maxgfr/codeindex:sha-${{ steps.sha.outputs.short }} \ + .