From edba2959aa778bf6d949a7cc6f36d3567ce09c87 Mon Sep 17 00:00:00 2001 From: aaccensi Date: Thu, 29 Oct 2026 15:52:58 +0100 Subject: [PATCH] Standarize Dependabot and CI workflows Grouped Dependabot updates with the low-risk ones (security, minor/patch) auto-merged on green CI; majors stay manual. Plus standarization of existing github workflows across all repos. --- .github/dependabot.yml | 47 ++++++++++++++ .github/workflows/dependabot-auto-merge.yml | 70 +++++++++++++++++++++ .github/workflows/label-pull-requests.yml | 31 +++++++++ .semaphore/semaphore.yml | 5 +- 4 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 .github/dependabot.yml create mode 100644 .github/workflows/dependabot-auto-merge.yml create mode 100644 .github/workflows/label-pull-requests.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..c5171c0 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,47 @@ +# Dependabot configuration — etplugin +# +# Policy: +# - Security bumps -> grouped into one PR, auto-merged on green CI. +# - Minor / patch -> one grouped weekly PR, also auto-merged on green CI +# (CI is the "nothing breaks" gate for semver-compatible bumps). +# - Majors -> one grouped "major-updates" PR per ecosystem: a standing +# list of what we're behind on. It won't go green (breaking +# changes bundled) and isn't merged as a unit — it's a +# dashboard; tackle a given major on its own when ready. +# +# The security and minor/patch groups auto-merge on green CI; majors wait for a +# human. The auto-merge logic lives in .github/workflows/dependabot-auto-merge.yml. + +version: 2 + +updates: + # ---- Ruby gems ---- + - package-ecosystem: bundler + directory: "/" + schedule: + interval: weekly + groups: + # Security fixes across all gems -> one PR, auto-merged on green. + security: + applies-to: security-updates + patterns: ["*"] + # Minor + patch gem updates -> one grouped PR per week, auto-merged on green CI. + dependencies: + applies-to: version-updates + patterns: ["*"] + update-types: ["minor", "patch"] + # Every major -> one grouped standing PR (a "what we're behind on" list). It + # won't go green and isn't merged as a unit; tackle each major on its own. + major-updates: + applies-to: version-updates + patterns: ["*"] + update-types: ["major"] + + # ---- GitHub Actions ---- + - package-ecosystem: github-actions + directory: "/" + schedule: + interval: monthly + groups: + actions: + patterns: ["*"] diff --git a/.github/workflows/dependabot-auto-merge.yml b/.github/workflows/dependabot-auto-merge.yml new file mode 100644 index 0000000..355da97 --- /dev/null +++ b/.github/workflows/dependabot-auto-merge.yml @@ -0,0 +1,70 @@ +# Auto-merge low-risk Dependabot updates +# +# Two independent jobs, one per auto-mergeable group, so each group's conditions +# can be tuned on its own: +# - security-auto-merge -> the "security" group +# - dependencies-auto-merge -> the minor/patch "dependencies" group +# Both approve with the GitHub Actions bot (repo requires a review) and enable +# auto-merge, so the update lands once the required CI check is green. Majors, +# Rails, and everything else are left as a PR for a human. +# +# The signal is the Dependabot group name from .github/dependabot.yml, surfaced by +# fetch-metadata as the `dependency-group` output. +# +# Note on `update-type`: it is the highest semver change across the *direct* +# dependencies Dependabot reports, so it does NOT see transitive/indirect bumps +# (Dependabot omits those from its metadata). A transitive major can therefore +# ride inside a minor/patch PR; that risk is covered by CI, which tests against +# the fully-resolved tree, not by this guard. + +name: Dependabot auto-merge + +on: pull_request + +permissions: + contents: write # enable auto-merge + pull-requests: write # approve the PR + +jobs: + security-auto-merge: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Fetch Dependabot metadata + id: meta + uses: dependabot/fetch-metadata@v3 + + - name: Approve and auto-merge security updates + # The security group, but never a major bump — a security fix that needs + # a major version jump is rare and risky enough to want a human. + if: > + steps.meta.outputs.dependency-group == 'security' && + steps.meta.outputs.update-type != 'version-update:semver-major' + run: | + gh pr review --approve "$PR_URL" + gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + dependencies-auto-merge: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Fetch Dependabot metadata + id: meta + uses: dependabot/fetch-metadata@v3 + + - name: Approve and auto-merge minor/patch updates + # The minor/patch "dependencies" group. The major guard is extra safety: + # the dependabot.yml group is already minor/patch-only, and the guard only + # catches direct majors (breaking transitive majors are caught by CI). + if: > + steps.meta.outputs.dependency-group == 'dependencies' && + steps.meta.outputs.update-type != 'version-update:semver-major' + run: | + gh pr review --approve "$PR_URL" + gh pr merge --auto --squash "$PR_URL" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/label-pull-requests.yml b/.github/workflows/label-pull-requests.yml new file mode 100644 index 0000000..10e4873 --- /dev/null +++ b/.github/workflows/label-pull-requests.yml @@ -0,0 +1,31 @@ +# Applies labels to pull requests. Add one job per labelling rule. + +name: Label pull requests + +on: pull_request + +permissions: + pull-requests: write # add labels to the PR + +jobs: + # Label the grouped Dependabot "major-updates" dashboard PR with `do-not-merge`. + # That PR is a standing list of the majors we're behind on and not intended to + # be directly merged. Checks with fetch-metadata's `dependency-group`, so only + # majors PRs are labelled. The `do-not-merge` label must be created manually: + # gh label create do-not-merge --repo quintel/ \ + # --color B60205 --description "Informational PR. Do not merge directly" + + dependabot-majors-dashboard: + if: github.actor == 'dependabot[bot]' + runs-on: ubuntu-latest + steps: + - name: Fetch Dependabot metadata + id: meta + uses: dependabot/fetch-metadata@v3 + + - name: Flag the majors dashboard as do-not-merge + if: steps.meta.outputs.dependency-group == 'major-updates' + run: gh pr edit "$PR_URL" --add-label "do-not-merge" + env: + PR_URL: ${{ github.event.pull_request.html_url }} + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index 0701b08..cf7fded 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -6,6 +6,9 @@ agent: os_image: ubuntu2404 blocks: - name: Smoke + # Skip the suite on the major-updates dashboard branches — never merged, so don't waste CI. + run: + when: "branch !~ '^dependabot/.+/major-updates-'" task: jobs: - name: Load & build @@ -20,4 +23,4 @@ blocks: - env_var: RUBY_VERSION values: - '3.3' - - '4.0' + - '4.0.5'