From 7822986eac3b614f9f6bfc25c9cf22606dc18ac0 Mon Sep 17 00:00:00 2001 From: Fatih Acet Date: Tue, 8 Sep 2026 11:35:45 +0200 Subject: [PATCH] ci(kai-ci): make the pin job re-runnable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The branch name is derived from the digest, so a re-run of the same build computes the same name. Attempt 1 pushed the branch and then died opening the PR (the App had no pull_requests permission yet); attempt 2 rebuilt an identical commit on a fresh checkout and was rejected non-fast-forward. The job was only ever correct on a clean first run. Same digest means the same edit, so a branch that already exists is already the right branch: reuse it and go on to the PR. Not a force-push — overwriting a branch someone may be reviewing, to replace it with identical content, is all cost and no benefit. The PR step had the mirror of the problem: a re-run whose branch already carries an open PR would fail trying to open a second one. It checks first. This is the same class of bug as the double-charge fixed in kai-server#184: an operation that is not idempotent, re-run after a partial success. Worth naming, because "it worked when nothing went wrong" is how both of them passed review. Both paths verified against the real remote before committing — the existing branch takes the reuse path, an unseen digest takes the push path. --- .github/workflows/build-kai-ci.yml | 31 +++++++++++++++++++++++++++++- 1 file changed, 30 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build-kai-ci.yml b/.github/workflows/build-kai-ci.yml index ef44fb0..f1cf664 100644 --- a/.github/workflows/build-kai-ci.yml +++ b/.github/workflows/build-kai-ci.yml @@ -271,6 +271,7 @@ jobs: token: ${{ steps.token.outputs.token }} - name: Bump the pinned digest + id: bump env: DIGEST: ${{ needs.build.outputs.digest }} PROVENANCE: ${{ needs.build.outputs.provenance }} @@ -280,6 +281,23 @@ jobs: set -euo pipefail NEW="${IMAGE}@${DIGEST}" BR="kai-ci/pin-${DIGEST:7:12}" + echo "branch=$BR" >> "$GITHUB_OUTPUT" + + # RE-RUNNABLE. The branch name is derived from the digest, so a re-run + # of the same build computes the same name — and the first attempt may + # already have pushed it and then failed later (which is exactly how + # this was found: attempt 1 pushed the branch and died opening the PR, + # attempt 2 rebuilt an identical commit and was rejected non-fast- + # forward). Same digest means the same edit, so an existing branch is + # already the right branch: reuse it and move on to the PR. + # + # Not a force-push. Overwriting a branch someone may have reviewed, to + # replace it with identical content, is all cost and no benefit. + if git ls-remote --exit-code --heads origin "$BR" >/dev/null 2>&1; then + echo "$BR already exists — an earlier attempt pushed it; reusing" + exit 0 + fi + git config user.name "kai-ci" git config user.email "noreply@kaicontext.com" git checkout -b "$BR" @@ -322,8 +340,19 @@ jobs: PIN: ${{ inputs.pin }} run: | set -euo pipefail + BR="kai-ci/pin-${DIGEST:7:12}" + + # Same idempotency question, other end: a re-run whose branch already + # carries a PR must not fail trying to open a second one. + EXISTING="$(gh pr list --repo kaicontext/kai-server --head "$BR" \ + --state open --json number --jq '.[0].number // empty')" + if [ -n "$EXISTING" ]; then + echo "PR #$EXISTING already open for $BR — nothing to do" + exit 0 + fi + gh pr create --repo kaicontext/kai-server \ - --head "kai-ci/pin-${DIGEST:7:12}" --base main \ + --head "$BR" --base main \ --title "build(kai-ci): pin the $PIN image to ${DIGEST:7:12}" \ --body "$(cat <