Skip to content

fix(ci): prevent duplicate Update API Client PRs (HYBIM-922) - #139

Merged
etserend merged 3 commits into
mainfrom
feat/HYBIM-922-fix-duplicate-api-client-prs
Jul 24, 2026
Merged

fix(ci): prevent duplicate Update API Client PRs (HYBIM-922)#139
etserend merged 3 commits into
mainfrom
feat/HYBIM-922-fix-duplicate-api-client-prs

Conversation

@etserend

@etserend etserend commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Root cause: branch name included ${{ github.run_id }}, so every workflow run created a new unique branch and PR
  • Fix: use a static branch name chore/splunk-ao-automation/update-api-client and force-push to it
  • PR creation step now checks for an existing open PR; skips gh pr create if one already exists

Test plan

  • Trigger the regenerate-api-client workflow manually from this branch and verify it runs without errors
  • Trigger it a second time and verify no duplicate PR is created — the existing one is updated instead

Jira: https://splunk.atlassian.net/browse/HYBIM-922

🤖 Generated with Claude Code

Use a static branch name instead of one including the run ID, so
force-pushing to it updates an existing open PR rather than spawning
a new one each run. The PR creation step now checks for an existing
open PR and skips creation if one is found.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

@fercor-cisco fercor-cisco left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 This review was generated by the Astra agent (claude-opus-4-8). It may contain mistakes.

Verdict: request_changes — Static branch name breaks the "nothing was committed this run" guard in the PR-creation step, which can resurrect spurious PRs or fail the job; force-push also silently discards manual fixes on the open branch.

Comment on lines +70 to +78
if ! git ls-remote --exit-code origin refs/heads/$BRANCH_NAME > /dev/null 2>&1; then
echo "No branch to create PR from — nothing was committed"
exit 0
fi
gh pr create -B main -H $BRANCH_NAME --label 'dependencies' --title 'Update API Client' --body 'Fix any breaking changes if this pull request fails to deploy'
EXISTING_PR=$(gh pr list --base main --head $BRANCH_NAME --state open --json number --jq '.[0].number')
if [ -n "$EXISTING_PR" ]; then
echo "PR #$EXISTING_PR already open for branch $BRANCH_NAME — updated via force push"
else
gh pr create -B main -H $BRANCH_NAME --label 'dependencies' --title 'Update API Client' --body 'Fix any breaking changes if this pull request fails to deploy'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟠 major (bug): This step's guard no longer means what it used to. Previously the branch name was unique per run (...-{date}-{run_id}), so git ls-remote refs/heads/$BRANCH_NAME succeeding was a reliable proxy for "this run actually committed and pushed". With a static branch name, ls-remote now succeeds whenever the branch exists from ANY prior run, even when the current run made no spec changes (step 1 hit the exit 0 at line 58-60 and never pushed).

Concrete failure: a previous run created the branch + PR, the PR was later closed or merged but the remote branch was not deleted. Today's scheduled run finds no spec changes, so step 1 doesn't push. Step 2 still runs (no if: gate, no dependency on step 1), ls-remote passes because the stale branch exists, EXISTING_PR is empty (old PR is closed), so gh pr create fires — either resurrecting a PR from stale content or failing with "No commits between main and ..." when the branch equals main. Either way this reintroduces the duplicate/spurious-PR behavior the ticket set out to eliminate, or turns the job red.

Fix: have step 1 emit an explicit output (e.g. echo "changed=true" >> "$GITHUB_OUTPUT" after a successful push, via a step id) and gate this step on it (if: steps.<id>.outputs.changed == 'true'), rather than inferring "did we commit" from branch existence.

🤖 Generated by the Astra agent

Comment thread .github/workflows/regenerate-api-client.yaml
@fercor-cisco

Copy link
Copy Markdown
Collaborator

Pushing back on the Claude review:

force-push also silently discards manual fixes on the open branch.

This is fine, these PRs are supposed to be automated, not manually edited.

…-922)

The previous ls-remote guard was unreliable with a static branch name —
it would pass even when the current run made no spec changes, potentially
resurrecting a closed PR or failing with "no commits between main and branch".

Fix: emit `changed=true` output only after a successful push, and gate the
PR creation step on `steps.regenerate.outputs.changed == 'true'`.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@etserend
etserend force-pushed the feat/HYBIM-922-fix-duplicate-api-client-prs branch from 10eddb4 to 950d8d2 Compare July 24, 2026 17:21
@fercor-cisco

Copy link
Copy Markdown
Collaborator

Verdict: approve — the blocker from the earlier review is resolved and the logic is correct.

The core fix is sound:

  • Step 1 has id: regenerate and emits changed=true/false on both paths.
  • Step 2 is gated with if: steps.regenerate.outputs.changed == 'true', and the fragile git ls-remote guard is gone.

A stale branch lingering from a closed/merged prior run can no longer trigger a spurious gh pr create or a red "No commits between main and ..." job, because Step 2 simply doesn't run when nothing was pushed. That closes the exact failure previously flagged.

Remaining branches check out:

  • git checkout -b runs on a fresh runner from main, so --force overwriting the persistent remote branch is intended.
  • When Step 2 runs, the branch is guaranteed freshly pushed, so the EXISTING_PR check is now just update-vs-create routing — correct and worth keeping.

Minor points (non-blocking)

  1. Dead step — "Get current date" (id: date). Its only consumer was the old branch name; steps.date.outputs.date no longer appears anywhere in the file, so the step is now dead. Worth deleting for tidiness.
  2. Daily force-push churn. git diff --cached --quiet compares against main, not the prior run — so while a PR is open, each scheduled run force-pushes a fresh commit and re-notifies even when the spec hasn't moved since yesterday. Noise, not a bug; the "no duplicate PRs" goal still holds.

None of these block merge.

@fercor-cisco

Copy link
Copy Markdown
Collaborator

@etserend this seems to be dead code, do you want to remove this before merging?

Dead step — "Get current date" (id: date, near line 42). Its only consumer was the old branch name (...-${{ steps.date.outputs.date }}-...). steps.date.outputs.date no longer appears anywhere in the file, so that whole step is now dead. Worth deleting for tidiness.

@etserend

Copy link
Copy Markdown
Contributor Author

@etserend this seems to be dead code, do you want to remove this before merging?

Dead step — "Get current date" (id: date, near line 42). Its only consumer was the old branch name (...-${{ steps.date.outputs.date }}-...). steps.date.outputs.date no longer appears anywhere in the file, so that whole step is now dead. Worth deleting for tidiness.

Will clean up in this PR.

The step's only consumer was the old dynamic branch name which included
steps.date.outputs.date. Now that the branch name is static, the step
is unused.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@etserend
etserend merged commit 6ba8937 into main Jul 24, 2026
14 checks passed
@etserend
etserend deleted the feat/HYBIM-922-fix-duplicate-api-client-prs branch July 24, 2026 17:44
@github-actions github-actions Bot locked and limited conversation to collaborators Jul 24, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants