Repository navigation
ci: use the shared Dependabot auto-merge gate - #15061
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Review complete. 🟡 1 medium 💬 Inline comments (1)
The change rewrites
The previous local Reviewed commit: 21c3c44 |
🟢 Tier S · Ready to merge
Replaces the repository-local Dependabot auto-merge logic with a call to a pinned shared workflow. The gate runs after the configured workflows complete and approves and merges eligible patch or minor updates only after checks pass on the exact PR head SHA. Latest changes: The newest commit adds a zizmor suppression to the workflow_run trigger, documenting that the pinned shared workflow does not execute pull request code.
📂 Walkthrough · 1
Reviewed the commits since |
There was a problem hiding this comment.
🟡 Tier B · 1 blocking finding to address. Summary
There was a problem hiding this comment.
This PR replaces the local Dependabot auto-merge gating with a delegated reusable workflow, but grants write permissions to every matching workflow_run with no local safety check.
Key findings
- 🟡 Grant
contents: writeonworkflow_runwith no local gate — dependabot-auto-merge.yml:15
| permissions: | ||
| checks: read | ||
| contents: write | ||
| pull-requests: write | ||
| statuses: read | ||
|
|
||
| jobs: | ||
| auto-merge: | ||
| if: github.event.pull_request.user.login == 'dependabot[bot]' | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| pull-requests: write | ||
| steps: | ||
| - name: Fetch Dependabot metadata | ||
| id: metadata | ||
| uses: dependabot/fetch-metadata@25dd0e34f4fe68f24cc83900b1fe3fe149efef98 # v3.1.0 | ||
| with: | ||
| github-token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| # Auto-merge only waits for checks the base branch requires, so skip it until every gate below is required. | ||
| - name: Check required status checks on the base branch | ||
| id: protection | ||
| run: | | ||
| required=$( { | ||
| gh api "repos/$REPOSITORY/branches/$BASE" --jq '.protection.required_status_checks.contexts // [] | .[]' | ||
| gh api "repos/$REPOSITORY/rules/branches/$BASE" --jq '.[] | select(.type == "required_status_checks") | .parameters.required_status_checks[].context' | ||
| } ) | ||
| missing="" | ||
| for check in CI Console CodeQL Hansi; do | ||
| grep -qxF "$check" <<< "$required" || missing="$missing $check" | ||
| done | ||
| if [ -z "$missing" ]; then | ||
| echo "required=true" >> "$GITHUB_OUTPUT" | ||
| else | ||
| echo "::warning::$BASE does not require:$missing. Auto-merge is not enabled." | ||
| fi | ||
| env: | ||
| REPOSITORY: ${{ github.repository }} | ||
| BASE: ${{ github.event.pull_request.base.ref }} | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: Enable auto-merge for patch and minor updates | ||
| if: steps.protection.outputs.required == 'true' && (steps.metadata.outputs.update-type == 'version-update:semver-patch' || steps.metadata.outputs.update-type == 'version-update:semver-minor') | ||
| run: gh pr merge --auto --merge "$PR_URL" | ||
| env: | ||
| PR_URL: ${{ github.event.pull_request.html_url }} | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| dependabot: | ||
| uses: appwrite/.github/.github/workflows/dependabot-auto-merge.yml@d559a62c510dc7eccf274dda83b0a42f89b0bc06 # main |
There was a problem hiding this comment.
🟡 security · medium
Grant contents: write on workflow_run with no local gate
The workflow now grants contents: write and pull-requests: write at the top level while the trigger changed from pull_request to workflow_run, which fires for any PR that runs the listed workflows — including untrusted fork PRs — and also for non-PR runs (.github/workflows/dependabot-auto-merge.yml:15-23). The previous version checked github.event.pull_request.user.login == 'dependabot[bot]' and verified Dependabot metadata with dependabot/fetch-metadata locally before acting; all of that gating now lives in a remote reusable workflow that this repository cannot review. If that external gate ever resolves the wrong PR, accepts a non-Dependabot actor, or acts on a failed/cancelled run, the error executes with write access to this repo's contents and pull requests. Impact: code/merge manipulation of protected branches becomes one external-workflow regression away.
📋 Prompt for AI Agents
In .github/workflows/dependabot-auto-merge.yml, the dependabot job (lines 22-23) runs for every completed workflow_run of CI/CodeQL/Console/SDK Preview and holds contents: write + pull-requests: write (lines 15-19), with all safety checks delegated to appwrite/.github@d559a62. Add defense-in-depth in this repo: a job-level if (or a guard job before the uses: call) that verifies the triggering PR is authored by dependabot[bot] — e.g. resolve github.event.workflow_run.pull_requests[0].number via the API and check the author — and only then call the reusable workflow. Also verify the pinned reusable workflow (1) maps workflow_run.head_sha to the associated PR via the API (the event carries no pull_request object), (2) rejects non-Dependabot actors and non-success conclusions, (3) merges with gh pr merge --auto rather than a direct merge, and (4) is idempotent under concurrent invocations (multiple listed workflows completing near-simultaneously each fire this trigger; add a concurrency group keyed on the head SHA if not).
Security rulesNo new WARNING or ERROR findings from security rules. 6 existing findings tracked in
|
The shared gate lists the commit's workflow runs, which needs it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
✨ Benchmark resultsComparing
Per-scenario breakdown & investigation detailsMetrics below reflect the current branch (after). Δ P95 compares against the base.
Top API waits (after)
|
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Replaces this repo's
dependabot-auto-merge.ymlwith a call to the shared workflow from appwrite/.github#132, pinned to its merge commit.The shared gate runs after each workflow a PR triggers, from the default branch, so a PR can't change it. For a Dependabot patch or minor update it waits for every workflow run, check run and commit status on the exact head SHA, approves when all of them pass, and merges with
--match-head-commit. Majors and failures stay for a human. Because it merges directly, the repo doesn't need Allow auto-merge or required status checks.Part of fixing Dependabot auto-merge across both orgs: 0 bot merges in 30 days, 266 open PRs.
🤖 Generated with Claude Code