From 18d234cde989252b87e172b685e2a27c7a110b2c Mon Sep 17 00:00:00 2001 From: olen Date: Thu, 14 May 2026 10:49:12 +0200 Subject: [PATCH 1/3] ci: opt-in auto-update of PRs labeled 'updateme' Adds a workflow that runs on every push to main. For each open PR labeled 'updateme' it calls `gh pr update-branch` to merge the new tip of main into the PR branch. PRs without the label are left alone. PRs from forks are skipped because GITHUB_TOKEN cannot push to a fork's branch via the update-branch endpoint; conflicting PRs are logged and skipped. The concurrency group serializes runs so two close-together merges don't race the API. Documents the opt-in label in README under a new Contributing section. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/auto-update-prs.yml | 36 +++++++++++++++++++++++++++ README.md | 10 ++++++++ 2 files changed, 46 insertions(+) create mode 100644 .github/workflows/auto-update-prs.yml diff --git a/.github/workflows/auto-update-prs.yml b/.github/workflows/auto-update-prs.yml new file mode 100644 index 0000000..28adae2 --- /dev/null +++ b/.github/workflows/auto-update-prs.yml @@ -0,0 +1,36 @@ +name: Auto-update PRs + +on: + push: + branches: [main] + +# Serialize so two close-together merges don't race the update API. +concurrency: + group: auto-update-prs + cancel-in-progress: false + +permissions: + pull-requests: write + contents: write + +jobs: + update: + runs-on: ubuntu-latest + steps: + - name: Update PRs labeled 'updateme' to latest main + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + set -u + gh pr list --repo "$GITHUB_REPOSITORY" --state open --label updateme \ + --json number,isCrossRepository \ + --jq '.[] | "\(.number) \(.isCrossRepository)"' \ + | while read -r num is_fork; do + if [ "$is_fork" = "true" ]; then + echo "Skip PR #$num (fork — cannot push via GITHUB_TOKEN)" + continue + fi + echo "Updating PR #$num" + gh pr update-branch "$num" --repo "$GITHUB_REPOSITORY" \ + || echo " -> PR #$num could not be updated (likely conflicting)" + done diff --git a/README.md b/README.md index 4e352f4..0f0cefa 100644 --- a/README.md +++ b/README.md @@ -90,3 +90,13 @@ Demonstrates most `get...()` methods. [Asyncio](https://docs.python.org/3/library/asyncio.html) might seem intimidating in the beginning, but for basic stuff, it is quite easy to follow the examples above, and just remeber to prefix functions that use the API with `async def ...` and to `await` all API-calls and all calls to said functions. [This article](https://realpython.com/async-io-python/) will give a nice introduction to both why, when and how to use asyncio in projects. + +## Contributing + +### Keeping a PR up to date with `main` + +Add the `updateme` label to a PR and a GitHub Actions workflow will automatically merge `main` into the PR branch every time `main` advances. This is opt-in: PRs without the label are left alone. + +Limitations: +- Only works for PRs from branches in this repository. PRs from forks cannot be pushed to via the workflow's token and will be skipped (the workflow logs which PRs it skipped). +- If the update would cause a merge conflict, the PR is left as-is. Resolve the conflict by hand and re-apply the label if you want auto-update to resume. From 8e601c49b23e2c95005cf55e61694a3914f27af0 Mon Sep 17 00:00:00 2001 From: olen Date: Thu, 14 May 2026 10:56:18 +0200 Subject: [PATCH 2/3] ci/docs: address review feedback on auto-update workflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Use set -euo pipefail so a failed `gh pr list` (auth/rate limit/API outage) fails the job loudly instead of being masked by the empty while loop exiting 0. - Filter to PRs whose baseRefName == "main" so we only touch PRs that actually target the branch we just pushed to. `gh pr update-branch` merges from the PR's base branch, so this matches the workflow's documented intent. - README: align language with the new base-branch filter; remove the misleading "re-apply the label" line — the workflow never removes the label, so the next push to main retries automatically. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/auto-update-prs.yml | 6 +++--- README.md | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/auto-update-prs.yml b/.github/workflows/auto-update-prs.yml index 28adae2..6781dda 100644 --- a/.github/workflows/auto-update-prs.yml +++ b/.github/workflows/auto-update-prs.yml @@ -21,10 +21,10 @@ jobs: env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | - set -u + set -euo pipefail gh pr list --repo "$GITHUB_REPOSITORY" --state open --label updateme \ - --json number,isCrossRepository \ - --jq '.[] | "\(.number) \(.isCrossRepository)"' \ + --json number,isCrossRepository,baseRefName \ + --jq '.[] | select(.baseRefName == "main") | "\(.number) \(.isCrossRepository)"' \ | while read -r num is_fork; do if [ "$is_fork" = "true" ]; then echo "Skip PR #$num (fork — cannot push via GITHUB_TOKEN)" diff --git a/README.md b/README.md index 0f0cefa..ae9fa4b 100644 --- a/README.md +++ b/README.md @@ -95,8 +95,9 @@ Demonstrates most `get...()` methods. ### Keeping a PR up to date with `main` -Add the `updateme` label to a PR and a GitHub Actions workflow will automatically merge `main` into the PR branch every time `main` advances. This is opt-in: PRs without the label are left alone. +Add the `updateme` label to a PR targeting `main` and a GitHub Actions workflow will automatically merge `main` into the PR branch every time `main` advances. This is opt-in: PRs without the label are left alone. Limitations: +- Only acts on PRs whose base branch is `main`. PRs targeting other branches are ignored even with the label. - Only works for PRs from branches in this repository. PRs from forks cannot be pushed to via the workflow's token and will be skipped (the workflow logs which PRs it skipped). -- If the update would cause a merge conflict, the PR is left as-is. Resolve the conflict by hand and re-apply the label if you want auto-update to resume. +- If the update would cause a merge conflict, that PR is skipped for this run and logged. The label stays on, so the next push to `main` will retry automatically once the conflict is resolved. From a3d86484e2abb8bf4b46b5a48246a457259efad9 Mon Sep 17 00:00:00 2001 From: olen Date: Thu, 14 May 2026 11:04:52 +0200 Subject: [PATCH 3/3] =?UTF-8?q?ci/docs:=20round=202=20of=20review=20fixes?= =?UTF-8?q?=20=E2=80=94=20pagination=20+=20accurate=20failure=20log?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - `gh pr list --limit 200` so we don't silently truncate at the default 30. Realistically this never matters for this repo, but silent truncation is the wrong default. - Generalize the per-PR failure log: `gh pr update-branch` can return non-zero for many reasons (merge conflict, branch protection, transient API error, deleted head ref), not just conflicts. Refer readers to the preceding `gh` output rather than claiming "likely conflicting". - README: same class-fix — the limitations section now lists representative failure causes instead of saying "merge conflict" exclusively. Co-Authored-By: Claude Opus 4.7 (1M context) --- .github/workflows/auto-update-prs.yml | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/auto-update-prs.yml b/.github/workflows/auto-update-prs.yml index 6781dda..61ac774 100644 --- a/.github/workflows/auto-update-prs.yml +++ b/.github/workflows/auto-update-prs.yml @@ -22,7 +22,7 @@ jobs: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} run: | set -euo pipefail - gh pr list --repo "$GITHUB_REPOSITORY" --state open --label updateme \ + gh pr list --repo "$GITHUB_REPOSITORY" --state open --label updateme --limit 200 \ --json number,isCrossRepository,baseRefName \ --jq '.[] | select(.baseRefName == "main") | "\(.number) \(.isCrossRepository)"' \ | while read -r num is_fork; do @@ -32,5 +32,5 @@ jobs: fi echo "Updating PR #$num" gh pr update-branch "$num" --repo "$GITHUB_REPOSITORY" \ - || echo " -> PR #$num could not be updated (likely conflicting)" + || echo " -> PR #$num: update-branch failed (see preceding gh output; possible causes: merge conflict, branch protection, transient API error)" done diff --git a/README.md b/README.md index ae9fa4b..9650b1f 100644 --- a/README.md +++ b/README.md @@ -100,4 +100,4 @@ Add the `updateme` label to a PR targeting `main` and a GitHub Actions workflow Limitations: - Only acts on PRs whose base branch is `main`. PRs targeting other branches are ignored even with the label. - Only works for PRs from branches in this repository. PRs from forks cannot be pushed to via the workflow's token and will be skipped (the workflow logs which PRs it skipped). -- If the update would cause a merge conflict, that PR is skipped for this run and logged. The label stays on, so the next push to `main` will retry automatically once the conflict is resolved. +- If `gh pr update-branch` fails for a given PR (merge conflict, branch protection rule, transient API error, etc.), that PR is skipped for this run and the failure is logged. The label stays on, so the next push to `main` will retry automatically.