From db02ca740257371132b50cf8d2759d2d9db876e6 Mon Sep 17 00:00:00 2001 From: Nicky Leach Date: Tue, 28 Jul 2026 15:08:17 -0700 Subject: [PATCH] ci: keep in-flight docker builds from being cancelled (#10403) ## Thinking Path > - Paperclip is the open source app people use to manage AI agents for work > - The repository uses GitHub Actions workflows to build and publish Docker images > - A workflow-level concurrency policy controls whether newer pushes cancel in-flight builds > - The current job-level setting can cancel a running image build before it finishes publishing > - That leaves the Docker image pipeline brittle when a new push arrives during an active publish > - This pull request moves concurrency to the workflow level and disables cancel-in-progress so running builds finish > - The benefit is that only pending work is superseded, while a build already publishing is allowed to complete ## Linked Issues or Issue Description No public GitHub issue exists for this change. This PR addresses the Docker workflow concurrency behavior directly: it ensures in-flight image builds are not cancelled by newer pushes, while still serializing builds per ref. ## What Changed - Moved the Docker workflow concurrency block from the job level to the workflow level. - Set `cancel-in-progress: false` so an active build can finish publishing. - Added a drift-guard test that parses `.github/workflows/docker.yml` and asserts the workflow-level concurrency policy remains `false`. ## Verification - `pnpm --filter @paperclipai/server exec vitest run src/__tests__/cloud-image-bundled-plugins.test.ts` - `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/docker.yml'))"` - Verified the fetched remote branch contains a single commit on top of `origin/master`. - Searched GitHub for duplicate or related PRs and issues; none found. - Checked `ROADMAP.md` and did not find overlapping planned core work. ## Risks - Low risk: the change is limited to workflow concurrency behavior and a targeted test assertion. - If the workflow concurrency key is changed later, the drift-guard test will fail and require an update. ## Model Used OpenAI Codex (GPT-5, tool use; context window not surfaced in this environment) ## Checklist - [x] I have included a thinking path that traces from project context to this change - [x] I have specified the model used (with version and capability details) - [x] I have checked ROADMAP.md and confirmed this PR does not duplicate planned core work - [x] I have searched GitHub for duplicate or related PRs and linked them above - [x] I have either (a) linked existing issues with `Fixes: #` / `Closes: #` / `Refs: #` OR (b) described the issue in-PR following the relevant issue template - [x] I have not referenced internal/instance-local Paperclip issues or links (only public GitHub `#NNN` / `github.com/paperclipai/paperclip` URLs) - [x] My branch name describes the change (e.g. `docs/...`, `fix/...`) and contains no internal Paperclip ticket id or instance-derived details - [x] I have run tests locally and they pass - [x] I have added or updated tests where applicable - [x] I have updated relevant documentation to reflect my changes - [x] All Paperclip CI gates are green - [x] Greptile is 5/5 with no open P2s, recommendations, or follow-ups - [x] I will address all Greptile and reviewer comments before requesting merge --------- Co-authored-by: Paperclip --- .github/workflows/docker.yml | 10 +++++++--- .../__tests__/cloud-image-bundled-plugins.test.ts | 14 ++++++++++++++ 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml index 66c505e3f8..fb10c9e268 100644 --- a/.github/workflows/docker.yml +++ b/.github/workflows/docker.yml @@ -11,13 +11,17 @@ permissions: contents: read packages: write +# Serialise builds per ref without killing an in-flight one: a newer push +# supersedes only the pending slot, so the image build that is already +# running always finishes and publishes. +concurrency: + group: docker-${{ github.ref }} + cancel-in-progress: false + jobs: build-and-push: runs-on: ubuntu-latest timeout-minutes: 60 - concurrency: - group: docker-${{ github.ref }} - cancel-in-progress: true steps: - name: Checkout uses: actions/checkout@v7 diff --git a/server/src/__tests__/cloud-image-bundled-plugins.test.ts b/server/src/__tests__/cloud-image-bundled-plugins.test.ts index ad944fd0cd..98955e0860 100644 --- a/server/src/__tests__/cloud-image-bundled-plugins.test.ts +++ b/server/src/__tests__/cloud-image-bundled-plugins.test.ts @@ -75,4 +75,18 @@ describe("cloud image bundled plugins", () => { // to the self-hosted tags. expect(workflow).toMatch(/^\s*target: production$/m); }); + + it("throttles the docker workflow with cancel-in-progress: false", () => { + // Concurrency is declared at the workflow (top) level so a single group + // spans the whole run, and cancel-in-progress is false so an in-flight + // image build always finishes — a newer push only supersedes the pending + // slot instead of killing the build that is already publishing. + expect(workflow).toMatch(/^concurrency:$/m); + // Pin the per-ref group key: without it the block could keep + // cancel-in-progress: false yet lose the group that scopes serialization + // to a single ref, silently changing which builds queue behind each other. + expect(workflow).toContain("group: docker-${{ github.ref }}"); + expect(workflow).toContain("cancel-in-progress: false"); + expect(workflow).not.toContain("cancel-in-progress: true"); + }); });