From f7dc42c8496f53bd1d6005c2f0965c4863b232d4 Mon Sep 17 00:00:00 2001 From: Peter Nehrer Date: Mon, 15 Jun 2026 19:47:27 -0600 Subject: [PATCH 1/2] fix(ci): gate Dependabot auto-merge on CI passing --- .github/workflows/dependabot-automerge.yaml | 107 +++++++++++++------- 1 file changed, 73 insertions(+), 34 deletions(-) diff --git a/.github/workflows/dependabot-automerge.yaml b/.github/workflows/dependabot-automerge.yaml index ec07eab..d563dd8 100644 --- a/.github/workflows/dependabot-automerge.yaml +++ b/.github/workflows/dependabot-automerge.yaml @@ -1,8 +1,9 @@ name: Dependabot Auto-Merge on: - pull_request: - types: [opened, synchronize, reopened] + workflow_run: + workflows: [Rust CI] + types: [completed] permissions: contents: write @@ -11,40 +12,78 @@ permissions: jobs: dependabot-auto-merge: runs-on: ubuntu-latest - if: github.actor == 'dependabot[bot]' + if: > + github.event.workflow_run.conclusion == 'success' && + github.event.workflow_run.event == 'pull_request' && + github.event.workflow_run.actor.login == 'dependabot[bot]' steps: - - name: Checkout repository - uses: actions/checkout@v6 - - - name: Get Dependabot metadata - id: metadata - uses: dependabot/fetch-metadata@v3 - with: - github-token: "${{ secrets.GITHUB_TOKEN }}" - - # In Cargo's SemVer interpretation, a 0.x.y → 0.z.y bump is breaking - # (https://doc.rust-lang.org/cargo/reference/semver.html). Dependabot - # classifies it as `version-update:semver-minor` per the strict SemVer - # 2.0.0 spec, so we additionally exclude minor bumps when the current - # major is 0 — those land as deliberate, reviewed PRs instead. - - name: Auto-approve safe Cargo updates - if: | - steps.metadata.outputs.package-ecosystem == 'cargo' && - (steps.metadata.outputs.update-type == 'version-update:semver-patch' || - (steps.metadata.outputs.update-type == 'version-update:semver-minor' && - !startsWith(steps.metadata.outputs.previous-version, '0.'))) - run: gh pr review --approve "$PR_URL" + - name: Find open PR and check update type + id: check + run: | + pr=$(gh api "repos/$REPO/pulls" \ + --jq "[.[] | select(.head.sha == \"$SHA\" and .state == \"open\")] | first") + number=$(echo "$pr" | jq -r '.number // empty') + if [[ -z "$number" ]]; then + echo "No open PR found for SHA $SHA — skipping" + exit 0 + fi + echo "number=$number" >> "$GITHUB_OUTPUT" + echo "url=$(echo "$pr" | jq -r '.html_url')" >> "$GITHUB_OUTPUT" + + # Dependabot embeds a YAML block in the commit message containing + # update-type and previous-version for each dependency. + # Qualify if every dep is patch or minor, with the exception that + # 0.x minor bumps are excluded: in Cargo's convention a 0.x -> 0.y + # bump is considered breaking. + commit_msg=$(gh api "repos/$REPO/git/commits/$SHA" --jq '.message') + + is_eligible=true + + # Reject if any dep is a major bump + if echo "$commit_msg" | grep 'update-type:' | grep -q 'version-update:semver-major'; then + is_eligible=false + fi + + # Reject if any dep is a minor bump whose previous version starts with 0. + # The YAML block lists deps as: + # - dependency-name: foo + # dependency-version: 0.5.0 + # previous-version: 0.4.2 + # update-type: version-update:semver-minor + # We check each minor-bump entry for a preceding previous-version: 0.* + if [[ "$is_eligible" == "true" ]]; then + while IFS= read -r line; do + if echo "$line" | grep -q 'update-type: version-update:semver-minor'; then + # Look back in the block for the previous-version line + prev=$(echo "$commit_msg" \ + | grep -B5 'update-type: version-update:semver-minor' \ + | grep 'previous-version:' \ + | tail -1 \ + | grep -oP '[\d]+\.[\d]+\.[\d]+' \ + | head -1) + if [[ "$prev" == 0.* ]]; then + is_eligible=false + break + fi + fi + done <<< "$commit_msg" + fi + + # Must have at least one update-type line + has_types=$(echo "$commit_msg" | grep -c 'update-type:' || true) + if [[ "$has_types" -eq 0 ]]; then + is_eligible=false + fi + + echo "is_eligible=$is_eligible" >> "$GITHUB_OUTPUT" env: - PR_URL: ${{ github.event.pull_request.html_url }} + REPO: ${{ github.repository }} + SHA: ${{ github.event.workflow_run.head_sha }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - name: Enable auto-merge for safe Cargo updates - if: | - steps.metadata.outputs.package-ecosystem == 'cargo' && - (steps.metadata.outputs.update-type == 'version-update:semver-patch' || - (steps.metadata.outputs.update-type == 'version-update:semver-minor' && - !startsWith(steps.metadata.outputs.previous-version, '0.'))) - run: gh pr merge --auto --squash "$PR_URL" + - name: Merge safe Cargo updates + if: steps.check.outputs.number != '' && steps.check.outputs.is_eligible == 'true' + run: gh pr merge --squash "$PR_URL" env: - PR_URL: ${{ github.event.pull_request.html_url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + PR_URL: ${{ steps.check.outputs.url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file From 5d00295bcc272e508ff910ccbbb45def96f513a3 Mon Sep 17 00:00:00 2001 From: Peter Nehrer Date: Mon, 15 Jun 2026 19:52:23 -0600 Subject: [PATCH 2/2] fix(ci): filter auto-merge to Cargo updates only --- .github/workflows/dependabot-automerge.yaml | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dependabot-automerge.yaml b/.github/workflows/dependabot-automerge.yaml index d563dd8..0f4a2a0 100644 --- a/.github/workflows/dependabot-automerge.yaml +++ b/.github/workflows/dependabot-automerge.yaml @@ -31,12 +31,19 @@ jobs: echo "url=$(echo "$pr" | jq -r '.html_url')" >> "$GITHUB_OUTPUT" # Dependabot embeds a YAML block in the commit message containing - # update-type and previous-version for each dependency. + # update-type and package-ecosystem for each dependency. Only auto-merge + # Cargo updates (GitHub Actions bumps share the same format but are excluded). # Qualify if every dep is patch or minor, with the exception that # 0.x minor bumps are excluded: in Cargo's convention a 0.x -> 0.y # bump is considered breaking. commit_msg=$(gh api "repos/$REPO/git/commits/$SHA" --jq '.message') + if ! echo "$commit_msg" | grep -q 'package-ecosystem: cargo'; then + echo "Not a Cargo update — skipping" + echo "is_eligible=false" >> "$GITHUB_OUTPUT" + exit 0 + fi + is_eligible=true # Reject if any dep is a major bump @@ -86,4 +93,4 @@ jobs: run: gh pr merge --squash "$PR_URL" env: PR_URL: ${{ steps.check.outputs.url }} - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} \ No newline at end of file + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}