Skip to content

Commit de2e1b5

Browse files
committed
ci: prevent regenerate-models from opening duplicate empty PRs
Resetting the shared branch to master before committing on top made the open PR's head identical to its base, which GitHub auto-closes, so every docs-PR dispatch spawned a fresh (and mostly empty) PR. The branch now advances to "master + commit" in one atomic force-push, keeping a single PR open and only updated.
1 parent cb6602c commit de2e1b5

1 file changed

Lines changed: 51 additions & 23 deletions

File tree

.github/workflows/manual_regenerate_models.yaml

Lines changed: 51 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -108,31 +108,56 @@ jobs:
108108
echo "has_changes=true" >> "$GITHUB_OUTPUT"
109109
fi
110110
111-
# Point the auto-update branch at the current master so the signed-commit step below records
112-
# the regenerated models as a single commit on top of it. Resetting to master (instead of
113-
# building on a possibly stale existing branch) is what keeps the committed diff relative to
114-
# the current master: an already-merged change can never reappear. Any previous content on the
115-
# branch is intentionally replaced, so the PR always reflects "current master + freshly
116-
# regenerated models" — and it still updates whenever the source docs PR gets new commits.
117-
- name: Point branch at current master
118-
if: steps.changes.outputs.has_changes == 'true'
119-
run: |
120-
git checkout -B "$BRANCH"
121-
git push --force origin "HEAD:refs/heads/$BRANCH"
122-
123-
- name: Commit model changes
111+
# Commit the regenerated models as a single commit on top of the current master and move the
112+
# auto-update branch to it with one atomic force-push. Building on a fresh master checkout (not
113+
# on the possibly stale existing branch) keeps the committed diff relative to the current
114+
# master, so an already-merged change can never reappear as a fresh diff.
115+
#
116+
# The branch goes straight from its previous state to "master + commit" in a single push — it
117+
# is never published as being equal to master. This is the crux of the fix: the previous flow
118+
# force-pushed the branch to master first and committed on top in a second step, and that
119+
# intermediate "branch == master" state made the open PR's head identical to its base, which
120+
# GitHub auto-closes. The next dispatch then opened a brand-new PR (`gh pr list --head` only
121+
# matches open PRs), and the auto-closed one was left looking empty once its commit was orphaned
122+
# by the following reset. Moving the branch forward in one step keeps the single existing PR
123+
# open and simply updates it.
124+
#
125+
# Trade-off vs. apify/actions/signed-commit (used before): the commit is authored with a plain
126+
# `git commit` and is therefore not GPG-"Verified". Signed commits are not required on master
127+
# (branch protection has required_signatures disabled) and this branch is always squash-merged
128+
# through a reviewed PR, so the verified badge carries no weight here.
129+
- name: Update branch with regenerated models
124130
id: commit
125131
if: steps.changes.outputs.has_changes == 'true'
126-
uses: apify/actions/signed-commit@v1.2.0
127-
with:
128-
message: ${{ env.TITLE }}
129-
add: 'src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py'
130-
github-token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
131-
branch: ${{ env.BRANCH }}
132-
create-branch: 'false'
132+
run: |
133+
git config user.name 'Apify Service Account'
134+
git config user.email '64261774+apify-service-account@users.noreply.github.com'
135+
136+
files='src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py'
137+
138+
# If the remote branch already carries exactly these regenerated files, there is nothing to
139+
# do. Skipping the push avoids a redundant commit and the CI re-run it triggers when the
140+
# same docs PR dispatches this workflow repeatedly without actually changing the spec.
141+
if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then
142+
git fetch --depth=1 origin "$BRANCH"
143+
if git diff --quiet FETCH_HEAD -- $files; then
144+
echo "Remote branch '$BRANCH' already has the current regenerated models — skipping push."
145+
echo "pushed=false" >> "$GITHUB_OUTPUT"
146+
exit 0
147+
fi
148+
fi
133149
150+
git checkout -B "$BRANCH"
151+
git add $files
152+
git commit -m "$TITLE"
153+
git push --force origin "$BRANCH"
154+
echo "pushed=true" >> "$GITHUB_OUTPUT"
155+
156+
# Ensure exactly one PR exists for this branch. The branch is never auto-closed now, so an
157+
# existing open PR is found and reused; only the first run (or one whose PR step was cancelled
158+
# by a concurrent dispatch before it could open the PR) actually creates it.
134159
- name: Create or update PR
135-
if: steps.commit.outputs.committed == 'true'
160+
if: steps.changes.outputs.has_changes == 'true'
136161
id: pr
137162
env:
138163
GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
@@ -164,9 +189,12 @@ jobs:
164189
echo "created=true" >> "$GITHUB_OUTPUT"
165190
fi
166191
167-
# Post a cross-repo comment on the original docs PR so reviewers know about the corresponding client-python PR.
192+
# Post a cross-repo comment on the original docs PR so reviewers know about the corresponding
193+
# client-python PR. Comment only when something actually happened — the companion PR was just
194+
# created, or a real spec change was pushed to it. Repeated dispatches that change nothing
195+
# (pushed=false) post no comment, avoiding noise on the docs PR.
168196
- name: Comment on apify-docs PR
169-
if: steps.commit.outputs.committed == 'true' && inputs.docs_pr_number
197+
if: inputs.docs_pr_number && (steps.pr.outputs.created == 'true' || steps.commit.outputs.pushed == 'true')
170198
env:
171199
GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }}
172200
PR_CREATED: ${{ steps.pr.outputs.created }}

0 commit comments

Comments
 (0)