Skip to content

Commit 0f601ee

Browse files
committed
ci: auto-close superseded sync PRs after a sync merges
auto-merge-sync merges a passing sync PR but never closed the older sync PRs it superseded. A sync PR that fails CI is never merged by this job, so once a newer sync overtakes it, it lingers as an orphan (this is what left #109/#113/#114 open and failing until they were closed by hand). After the merge, check out the public intelligence-flow repo for history and close every open sync/intelligence-flow-* PR whose source commit is an ancestor of the just-merged source (already included), skipping the merged branch itself and leaving newer, not-yet-merged syncs untouched. Reuses the primitives already in the pipeline: gh pr list --json, git merge-base --is-ancestor, the sync branch prefix, and UPSTREAM.json's source.commit.
1 parent 2c52259 commit 0f601ee

1 file changed

Lines changed: 35 additions & 0 deletions

File tree

.github/workflows/ci.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,3 +204,38 @@ jobs:
204204
GH_TOKEN: ${{ steps.app-token.outputs.token }}
205205
PR_URL: ${{ github.event.pull_request.html_url }}
206206
run: gh pr merge "$PR_URL" --squash
207+
# After a sync lands, close any older sync PR it supersedes. A sync PR that
208+
# failed CI is never merged by this job, so without this it lingers as an
209+
# orphan once a newer sync overtakes it (see the pile-up that motivated this).
210+
# intelligence-flow is public, so the default token can read its history for
211+
# the ancestry check; closing uses the app token (pull-requests: write).
212+
- name: Check out Intelligence Flow for ancestry
213+
uses: actions/checkout@v4
214+
with:
215+
repository: operatorstack/intelligence-flow
216+
fetch-depth: 0
217+
path: intelligence-flow
218+
- name: Close superseded sync PRs
219+
env:
220+
GH_TOKEN: ${{ steps.app-token.outputs.token }}
221+
shell: bash
222+
run: |
223+
merged="$(jq -r '.source.commit' UPSTREAM.json)"
224+
if [[ -z "$merged" || "$merged" == "null" ]]; then
225+
echo "No recorded source commit; skipping supersession cleanup."
226+
exit 0
227+
fi
228+
gh pr list --state open --json number,headRefName \
229+
--jq '.[] | select(.headRefName | startswith("sync/intelligence-flow-")) | [.number, .headRefName] | @tsv' \
230+
| while IFS=$'\t' read -r number branch; do
231+
short="${branch#sync/intelligence-flow-}"
232+
# Skip the sync that just merged (its own branch), not a supersession.
233+
[[ "${merged:0:12}" == "$short" ]] && continue
234+
# Close only PRs whose source is an ancestor of the merged source —
235+
# i.e. already included. A newer, not-yet-merged sync (descendant) is
236+
# left untouched.
237+
if git -C intelligence-flow merge-base --is-ancestor "$short" "$merged" 2>/dev/null; then
238+
echo "Closing superseded sync PR #$number ($short)."
239+
gh pr close "$number" --comment "Superseded by the sync at ${merged:0:12}, which already includes this PR's source ($short). Closing the stale sync PR automatically."
240+
fi
241+
done

0 commit comments

Comments
 (0)