Repository navigation
ci: prevent regenerate-models from opening duplicate empty PRs #895
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
de2e1b5
ci: prevent regenerate-models from opening duplicate empty PRs
vdusek bdf729b
ci: append signed commits in regenerate-models instead of force-pushing
vdusek 8e22335
ci: tighten comments in regenerate-models workflow
vdusek a2d2349
ci: use double quotes for YAML scalars in regenerate-models workflow
vdusek cc4171f
ci: fix regenerate-models signed-commit retries and master baseline
vdusek d0ecfed
ci: shallow-fetch update branch and quote create-branch input
vdusek aff6e22
ci: start the auto-update branch from master, not the dispatched ref
vdusek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -63,6 +63,45 @@ jobs: | |
| with: | ||
| token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} | ||
|
|
||
| # Record master's SHA up front: a later step checks out the auto-update branch, so the change check below | ||
| # can't compare against HEAD. Resolve master from the remote rather than the checked-out ref: the run may be | ||
| # dispatched from a non-master ref, but that check and the PR both target master, so master is the baseline. | ||
| - name: Record master ref | ||
| id: base | ||
| run: | | ||
| git fetch --depth=1 origin master | ||
| echo "sha=$(git rev-parse FETCH_HEAD)" >> "$GITHUB_OUTPUT" | ||
|
|
||
| # Does the auto-update branch already exist on the remote? If so, a previous dispatch opened the PR | ||
| # and we append to it. If not, we start it from master (below) so signed-commit creates it there. | ||
| - name: Determine auto-update branch state | ||
| id: branch | ||
| run: | | ||
| if git ls-remote --exit-code --heads origin "$BRANCH" >/dev/null 2>&1; then | ||
| echo "exists=true" >> "$GITHUB_OUTPUT" | ||
| echo "create=false" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "exists=false" >> "$GITHUB_OUTPUT" | ||
| echo "create=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # Check out the existing branch before regenerating so the new models land as a NEW commit on top, | ||
| # mirroring the commit just pushed to the docs PR. We must switch now, while the tree is clean: | ||
| # signed-commit's own checkout is a plain `git checkout` that would refuse to overwrite the | ||
| # regenerated files (which differ between master and the branch) once they're in the working tree. | ||
| - name: Check out existing auto-update branch | ||
|
vdusek marked this conversation as resolved.
Resolved
|
||
| if: steps.branch.outputs.exists == 'true' | ||
| run: | | ||
| git fetch --depth=1 origin "$BRANCH" | ||
| git checkout -B "$BRANCH" FETCH_HEAD | ||
|
|
||
| # The branch doesn't exist yet, so regenerate from the recorded master SHA rather than the dispatched | ||
| # ref (a manual run may be dispatched from a non-master ref). Regenerating on master keeps the codegen | ||
| # tooling current, and signed-commit then creates the branch (the PR head) on top of master, the PR base. | ||
| - name: Start the auto-update branch from master | ||
| if: steps.branch.outputs.exists == 'false' | ||
| run: git checkout "${{ steps.base.outputs.sha }}" | ||
|
|
||
| # Download the pre-built OpenAPI spec artifact from the apify-docs workflow run. | ||
| # Skipped for manual runs — datamodel-codegen will fetch from the published spec URL instead. | ||
| - name: Download OpenAPI spec artifact | ||
|
|
@@ -93,46 +132,44 @@ jobs: | |
| uv run poe generate-models | ||
| fi | ||
|
|
||
| # Proceed only when regeneration actually changes the models relative to the current master. | ||
| # The job runs on a fresh master checkout, so anything already merged into master (e.g. a | ||
| # manually merged client PR carrying the same spec change, or a docs PR that merged master in | ||
| # and re-emits an already-applied change) produces no diff here and we skip — instead of | ||
| # opening a PR that just duplicates what master already has. | ||
| # Proceed only when the regenerated models differ from master (compared against the recorded SHA, | ||
| # since the tree may now sit on the branch), which skips empty-PR runs: a spec change that doesn't | ||
| # affect the client models, or one already merged into master. Also avoids creating an empty branch. | ||
| - name: Check for model changes | ||
| id: changes | ||
| run: | | ||
| if git diff --quiet -- src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py; then | ||
| if git diff --quiet "${{ steps.base.outputs.sha }}" -- src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py; then | ||
| echo "No model changes relative to master — nothing to regenerate." | ||
| echo "has_changes=false" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "has_changes=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # Point the auto-update branch at the current master so the signed-commit step below records | ||
| # the regenerated models as a single commit on top of it. Resetting to master (instead of | ||
| # building on a possibly stale existing branch) is what keeps the committed diff relative to | ||
| # the current master: an already-merged change can never reappear. Any previous content on the | ||
| # branch is intentionally replaced, so the PR always reflects "current master + freshly | ||
| # regenerated models" — and it still updates whenever the source docs PR gets new commits. | ||
| - name: Point branch at current master | ||
| if: steps.changes.outputs.has_changes == 'true' | ||
| run: | | ||
| git checkout -B "$BRANCH" | ||
| git push --force origin "HEAD:refs/heads/$BRANCH" | ||
|
|
||
| - name: Commit model changes | ||
| # Append the regenerated models to the auto-update branch as a single signed ("Verified") commit | ||
| # via apify/actions/signed-commit (GitHub's createCommitOnBranch GraphQL mutation). It's added on | ||
| # top of the branch tip, never resetting to master: a fresh docs PR creates the branch | ||
| # (create-branch) and its first commit, and each later docs-PR commit triggers a dispatch that | ||
| # appends another, so the client PR mirrors the docs PR and stays open. | ||
| # | ||
| # Appending (rather than force-pushing the branch to master, as before) is what keeps the PR open: | ||
| # a "branch == master" tip makes the PR head equal its base, which GitHub auto-closes, and each | ||
| # dispatch then opens a duplicate PR. signed-commit also sets committed=false when the staged | ||
| # files match the tip, so a repeated dispatch regenerating identical models adds no commit. | ||
| - name: Commit regenerated models | ||
| id: commit | ||
| if: steps.changes.outputs.has_changes == 'true' | ||
| uses: apify/actions/[email protected] | ||
| with: | ||
| message: ${{ env.TITLE }} | ||
| add: 'src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py' | ||
| add: "src/apify_client/_models.py src/apify_client/_typeddicts.py src/apify_client/_literals.py" | ||
| github-token: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} | ||
| branch: ${{ env.BRANCH }} | ||
| create-branch: 'false' | ||
| create-branch: "${{ steps.branch.outputs.create }}" | ||
|
|
||
| # Ensure exactly one PR exists for this branch. It's no longer auto-closed, so an existing PR is | ||
| # reused. Only the first run (or one whose PR step a concurrent dispatch cancelled) creates it. | ||
| - name: Create or update PR | ||
| if: steps.commit.outputs.committed == 'true' | ||
| if: steps.changes.outputs.has_changes == 'true' | ||
| id: pr | ||
| env: | ||
| GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} | ||
|
|
@@ -164,9 +201,11 @@ jobs: | |
| echo "created=true" >> "$GITHUB_OUTPUT" | ||
| fi | ||
|
|
||
| # Post a cross-repo comment on the original docs PR so reviewers know about the corresponding client-python PR. | ||
| # Post a cross-repo comment on the docs PR pointing reviewers to the companion client-python PR. | ||
| # Only when something happened: the PR was just created, or a commit was appended. A repeated | ||
| # dispatch that changes nothing (committed=false) posts no comment, avoiding noise on the docs PR. | ||
| - name: Comment on apify-docs PR | ||
| if: steps.commit.outputs.committed == 'true' && inputs.docs_pr_number | ||
| if: inputs.docs_pr_number && (steps.pr.outputs.created == 'true' || steps.commit.outputs.committed == 'true') | ||
| env: | ||
| GH_TOKEN: ${{ secrets.APIFY_SERVICE_ACCOUNT_GITHUB_TOKEN }} | ||
| PR_CREATED: ${{ steps.pr.outputs.created }} | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.