Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -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: ["*"]
70 changes: 70 additions & 0 deletions .github/workflows/dependabot-auto-merge.yml
Original file line number Diff line number Diff line change
@@ -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 }}
31 changes: 31 additions & 0 deletions .github/workflows/label-pull-requests.yml
Original file line number Diff line number Diff line change
@@ -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/<repo> \
# --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 }}
5 changes: 4 additions & 1 deletion .semaphore/semaphore.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -20,4 +23,4 @@ blocks:
- env_var: RUBY_VERSION
values:
- '3.3'
- '4.0'
- '4.0.5'