ci: auto-merge clean Dependabot PRs on plugin repos in update-plugins cron#7493
Conversation
… cron The daily update-plugins workflow already syncs boilerplate (workflows, dependabot.yml, etc.) into every ether/ep_* repo via checkPlugin, but it never closes the loop on the Dependabot PRs that config produces. With plugin repos having no per-repo auto-merge wiring, those PRs sit green indefinitely (e.g. ether/ep_loading_message#77). Add a final step that, after the per-plugin updates run, walks every ep_* repo and squash-merges any open Dependabot PR whose mergeStateStatus is CLEAN — i.e. no conflicts, branch up to date, all required checks green. Anything else (DIRTY, BLOCKED, BEHIND, UNSTABLE, …) is left alone for a human. No semver gating: trust each plugin's own CI to fail on a breaking major bump rather than pre-filtering by version delta. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Review Summary by QodoAuto-merge clean Dependabot PRs in plugin repos workflow
WalkthroughsDescription• Adds auto-merge step for clean Dependabot PRs in plugin repos • Walks all ether/ep_* repos and squash-merges PRs with CLEAN mergeStateStatus • Closes loop on boilerplate updates without per-repo auto-merge configuration • Leaves non-clean PRs (conflicts, failing checks) for manual review Diagramflowchart LR
A["update-plugins cron"] --> B["Sync boilerplate to ep_* repos"]
B --> C["List all ether/ep_* repos"]
C --> D["Find open Dependabot PRs"]
D --> E{mergeStateStatus<br/>CLEAN?}
E -->|Yes| F["Squash-merge PR"]
E -->|No| G["Skip for manual review"]
F --> H["Report merged PRs"]
G --> H
File Changes1. .github/workflows/update-plugins.yml
|
Code Review by Qodo
|
Review Summary by QodoAuto-merge clean Dependabot PRs in update-plugins workflow
WalkthroughsDescription• Adds auto-merge step for clean Dependabot PRs in plugin repos • Walks all ether/ep_* repos and squash-merges PRs with CLEAN merge status • Skips PRs with conflicts, failing checks, or other blocking conditions • Closes loop on Dependabot PRs that sit green indefinitely without per-repo auto-merge Diagramflowchart LR
A["update-plugins cron"] --> B["Sync boilerplate to ep_* repos"]
B --> C["Dependabot opens PRs"]
C --> D["New merge step"]
D --> E["Query CLEAN PRs"]
E --> F["Squash-merge PRs"]
F --> G["Delete branches"]
File Changes1. .github/workflows/update-plugins.yml
|
Code Review by Qodo
|
| prs=$(gh pr list --repo "$repo" \ | ||
| --author "app/dependabot" \ | ||
| --state open \ | ||
| --json number,mergeStateStatus,title \ | ||
| --jq '.[] | select(.mergeStateStatus=="CLEAN") | .number') || continue | ||
|
|
There was a problem hiding this comment.
1. Repo pr list errors hidden 🐞 Bug ◔ Observability
If gh pr list fails for a repo, the script uses || continue and emits no warning, so auth/rate-limit/API failures silently skip repos and leave merges unattempted without any visibility in the final summary.
Agent Prompt
### Issue description
Failures from `gh pr list` are swallowed (`|| continue`) with no warning, so the workflow can succeed while skipping many/all repos.
### Issue Context
This step is meant to provide centralized auto-merging; silent skips will look like "nothing to merge" rather than "could not check".
### Fix Focus Areas
- .github/workflows/update-plugins.yml[93-110]
### Suggested change
Replace `|| continue` with explicit error handling that logs a warning including the repo name and tracks failures in a `failed_repos` list (printed in the final summary). Optionally, fail the step if listing fails for an unexpectedly large number of repos.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| - name: Merge clean Dependabot PRs on plugin repos | ||
| env: | ||
| GH_TOKEN: ${{ secrets.PLUGINS_PAT }} | ||
| run: | | ||
| # For every ep_* repo under ether, merge any Dependabot PR whose | ||
| # mergeStateStatus is CLEAN (no conflicts, branch up to date, all | ||
| # required checks green). Anything else is left alone for a human. | ||
| plugins=$(gh repo list ether --limit 200 --json name --jq '.[] | select(.name | startswith("ep_")) | .name') | ||
|
|
||
| merged="" | ||
| for plugin in $plugins; do | ||
| repo="ether/${plugin}" | ||
| prs=$(gh pr list --repo "$repo" \ | ||
| --author "app/dependabot" \ | ||
| --state open \ | ||
| --json number,mergeStateStatus,title \ | ||
| --jq '.[] | select(.mergeStateStatus=="CLEAN") | .number') || continue | ||
|
|
||
| for pr in $prs; do | ||
| echo "Merging ${repo}#${pr}" | ||
| if gh pr merge --repo "$repo" --squash --delete-branch "$pr"; then | ||
| merged="$merged ${repo}#${pr}" | ||
| else | ||
| echo "WARN: failed to merge ${repo}#${pr}" | ||
| fi | ||
| done | ||
| done |
There was a problem hiding this comment.
1. Auto-merge step lacks flag 📘 Rule violation ☼ Reliability
The new step will automatically squash-merge Dependabot PRs on every scheduled run with no feature flag or default-off gating. This violates the requirement that new features be behind a disabled-by-default feature flag to preserve prior behavior unless explicitly enabled.
Agent Prompt
## Issue description
The workflow introduces automatic merging of Dependabot PRs but does not provide a feature flag/explicit enablement mechanism that defaults to off.
## Issue Context
The step `Merge clean Dependabot PRs on plugin repos` runs on the scheduled cron and will merge PRs whenever `mergeStateStatus` is `CLEAN`, changing default behavior for the workflow.
## Fix Focus Areas
- .github/workflows/update-plugins.yml[81-107]
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
| # For every ep_* repo under ether, merge any Dependabot PR whose | ||
| # mergeStateStatus is CLEAN (no conflicts, branch up to date, all | ||
| # required checks green). Anything else is left alone for a human. | ||
| plugins=$(gh repo list ether --limit 200 --json name --jq '.[] | select(.name | startswith("ep_")) | .name') |
There was a problem hiding this comment.
2. Repo list truncates plugins 🐞 Bug ≡ Correctness
The step enumerates plugin repos via gh repo list ether --limit 200, so any ep_* repos beyond the first 200 results are silently skipped and their CLEAN Dependabot PRs will never be considered for merge.
Agent Prompt
## Issue description
The workflow uses `gh repo list ether --limit 200` to discover `ep_*` repos, which can silently omit repos if the org has more than 200 repos (or if `ep_*` repos fall outside the first 200 results). This prevents merging eligible Dependabot PRs for skipped repos.
## Issue Context
There are two occurrences of this pattern in the workflow (one for cloning/updating, one for merging Dependabot PRs). The repo also includes a script that pages through multiple GitHub API pages when listing ether repos, indicating pagination/high limits are expected.
## Fix Focus Areas
- .github/workflows/update-plugins.yml[44-45]
- .github/workflows/update-plugins.yml[85-89]
## Suggested fix
- Increase the limit to something safely above the expected repo count (e.g., `--limit 1000`), **in both places**.
- (Optional) Consider filtering out archived repos by requesting `isArchived` and excluding them in `jq` to avoid wasted API calls.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
Summary
.github/workflows/update-plugins.ymlthat walks everyether/ep_*repo and squash-merges any open Dependabot PR whosemergeStateStatusisCLEAN(no conflicts, branch up to date, all required checks green).DIRTY,BLOCKED,BEHIND,UNSTABLE, …) is left alone for a human to look at.mergeStateStatuswon't beCLEAN— that's the gate.Why
The daily
update-pluginscron already pushes boilerplate updates (workflows,dependabot.yml, etc.) into every plugin repo viacheckPlugin, which causes Dependabot to open PRs against each plugin. But none of the plugin repos have auto-merge configured at the repo level, so those PRs sit green forever — see e.g. ether/ep_loading_message#77, which has beenMERGEABLE+CLEANsince it was opened.This step closes the loop centrally from etherpad-lite, instead of needing to enable auto-merge + add per-repo workflows in 100+ plugin repos.
Test plan
workflow_dispatchonce merged and verify the new step runs without error against the live plugin set.Notes
PLUGINS_PATsecret. The PAT already hascontents: write(the cron pushes commits to plugin repos), and needspull_requests: writeforgh pr mergeto succeed. If the first run showsWARN: failed to merge ...lines, that's the scope to check.🤖 Generated with Claude Code