Skip to content

Auto-merge safe Dependabot updates and declare workflow permissions - #110

Open
allamiro wants to merge 2 commits into
mainfrom
ci/dependabot-auto-merge
Open

allamiro wants to merge 2 commits into
mainfrom
ci/dependabot-auto-merge

Conversation

@allamiro

@allamiro allamiro commented Sep 8, 2026 •

Copy link
Copy Markdown
Owner

Security updates were already enabled at the repository level, but every Dependabot pull request waited for a human, and there was no dependabot.yml — so ordinary version updates were never raised and a security fix tended to arrive as a large jump from a long-stale version.

What now merges without a human

Update Behaviour
Security fix, patch or minor Approved, auto-merge enabled, lands when CI passes
Ordinary patch or minor Same
Any major, including a security advisory Never auto-merged. Labelled needs-triage, commented, left open

A major is where a fix is most likely to change behaviour, so it gets a human even when it carries a CVE.

Why branch protection is part of this

GitHub's auto-merge lands a pull request as soon as it is mergeable. With no required status checks, "auto-merge" means "merge immediately, without waiting for CI" — the opposite of what is wanted. main is therefore now protected with the deterministic CI contexts as required checks:

test (3.9) … test (3.14), lint, docker

Deliberately not required: fuzz-pr, triage, and the third-party AI reviewers. Those are either event-specific or outside our control, and a flaky external service should not be able to wedge the merge queue.

Also deliberate:

  • Administrators are not included (enforce_admins: false), so you can still push directly to main and merge by hand. This adds a gate for the bot, not for you.
  • No required human review, which would otherwise block every auto-merge.
  • Force pushes and branch deletion on main are disabled.

Repository settings changed alongside this: allow_auto_merge enabled (it was off, so the workflow could not have worked), and delete_branch_on_merge enabled so merged Dependabot branches clean themselves up.

Dependabot scope

github-actions and pip, weekly, grouped so routine bumps arrive as one pull request instead of one per dependency. Worth being explicit: the project declares no runtime dependencies, so these updates touch CI and the optional kafka/fuzz extras only — they never change the shipped package.

CodeQL

ci.yml and fuzz.yml now declare least-privilege permissions: contents: read, clearing alerts #1–#4 ("workflow does not contain permissions"). Every workflow in the repository now states its permissions explicitly.

Alerts #5 and #6 (binding a socket to all interfaces, net.py:76 and :97) are not addressed here — see the PR discussion; I believe those are correct behaviour for a syslog receiver rather than defects, and that is a call worth making deliberately rather than in passing.


Summary by cubic

Adds automatic merging for safe Dependabot updates and declares least-privilege workflow permissions. Previously every Dependabot PR waited for a human; now security fixes and patch/minor updates merge after CI passes, while major versions and the runtime-shipped kafka-python are left for review.

Dependabot auto-merge

  • Adds dependabot.yml for weekly grouped updates to GitHub Actions and pip; kafka-python is excluded from the group because it ships to users through the kafka extra.
  • New workflow approves and auto-merges security fixes and patch/minor updates; major versions and any PR touching kafka-python get needs-triage label and a comment, never auto-merged.
  • Protects main with required CI checks so auto-merge waits for CI; admins are excluded.
  • Requires repo settings allow_auto_merge and delete_branch_on_merge enabled.

Workflow permissions

  • Declares permissions: contents: read in ci.yml and fuzz.yml, clearing CodeQL "workflow does not contain permissions" alerts.

Written for commit ab1948b. Summary will update on new commits.

Review in cubic

Security updates were already enabled at the repository level but every
pull request waited for a human, and there was no dependabot.yml, so
ordinary version updates were never raised and a security fix tended to
arrive as a large jump.

Add dependabot.yml for the workflow actions and the optional Python extras,
grouped so routine bumps arrive as one pull request rather than one per
dependency. The project declares no runtime dependencies, so these updates
change CI and the kafka/fuzz extras only, never the shipped package.

Add a workflow that approves a Dependabot pull request and turns on
auto-merge for a security fix or an ordinary patch/minor bump. A major
version is never merged unattended, including for a security advisory,
because a major is where a fix is most likely to change behaviour; those are
labelled needs-triage and left open with a comment saying why.

Merging uses GitHub's auto-merge, which lands the pull request only after
the required checks pass. Auto-merge without required checks merges
immediately, so main is now protected with the deterministic CI contexts
(the six test matrix jobs, lint, docker) as required checks. Administrators
are deliberately not included, so direct pushes still work.

Also declare explicit least-privilege permissions in ci.yml and fuzz.yml,
which clears the four CodeQL "workflow does not contain permissions" alerts.
Every workflow in the repository now states its permissions.
@github-actions github-actions Bot added the ci CI and release workflows label Sep 8, 2026
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 8, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-09-08T09:21:17.973292Z ab1948b New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9e2eda4c4e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

# part of this mechanism, not an optional extra.
name: Dependabot auto-merge

on: pull_request

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Use a trusted event for Dependabot writes

For Dependabot-authored PRs, GitHub treats workflows triggered by pull_request as fork-originated and restricts GITHUB_TOKEN to read-only, even though this job requests write permissions. Consequently, the gh pr edit, gh pr review, and gh pr merge commands fail under the default security model, so routine updates are never auto-merged and major updates are not labeled; use a suitably actor-guarded pull_request_target workflow that does not execute PR code.

Useful? React with 👍 / 👎.

@cubic-dev-ai cubic-dev-ai Bot left a comment •

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All reported issues were addressed across 4 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread .github/dependabot.yml
kafka-python backs the kafka extra and is imported at runtime in net.py,
so a bump does reach users -- the claim in dependabot.yml that a dependency
update never changes the shipped package was wrong. CI has no live broker,
so a green matrix is not evidence the extra still works, which is exactly
the evidence auto-merge relies on.

Excluding it from the grouped pull request is not enough on its own: the
group only controls how updates are batched, not whether they merge, so a
separate kafka-python pull request would still have merged unattended. The
auto-merge workflow now gates on the dependency name as well as the semver
level, and holds the pull request whenever a shipped runtime dependency
appears -- including when it arrives inside a group.

The gate is exact-name matched, so a different package with a similar name
is not caught by accident. Verified against the whole matrix: CI-only
patch and minor merge; kafka-python holds at patch, minor and major, alone
or grouped; any major holds; kafka-python-ng is not mistaken for it.

The comment in dependabot.yml now says which updates reach users instead
of claiming none of them do.
@allamiro

allamiro commented Sep 8, 2026

Copy link
Copy Markdown
Owner Author

Thanks both. One finding was right and is fixed; the other I checked against GitHub's documentation and am not taking, with reasoning below.

cubic — kafka-python is a shipped runtime dependency (fixed in ab1948b)

Correct, and the premise in my own comment was wrong. kafka-python>=2.0 backs the kafka extra and is imported at runtime in syslogcef/net.py:304, so a bump does reach users. CI has no live broker, which means a green matrix is not evidence the extra still works — and that evidence is precisely what auto-merge leans on.

The suggested exclude-patterns alone would not have fixed it, though, so I went further. A Dependabot group controls how updates are batched, not whether they merge — a standalone kafka-python pull request would still have been auto-merged as a patch or minor. The fix is in both places:

  • dependabot.yml excludes it from the grouped pull request, so it is reviewed on its own rather than riding along with CI tooling.
  • The workflow now gates on the dependency name as well as the semver level, and holds whenever a shipped runtime dependency appears — including when it arrives inside a group.

Verified against the full matrix:

Update Result
patch/minor, actions or pytest only merge
patch kafka-python hold
minor, kafka-python inside a group hold
any major hold
patch kafka-python-ng merge (exact-name match, not a substring, so no false positive)

The misleading comment claiming a dependency update never changes the shipped package is gone; it now names the one that does.

Codex — pull_request vs pull_request_target (not taking this)

The claim is that a Dependabot-triggered pull_request run gets a read-only GITHUB_TOKEN "even though this job requests write permissions", so the gh calls fail. The first half is true, the conclusion is not. GitHub's own documentation states:

"By default, GitHub Actions workflows triggered by Dependabot get a GITHUB_TOKEN with read-only permissions. You can use the permissions key in your workflow to increase the access for the token."

The permissions key is the documented mechanism for lifting that default, and this job already declares contents: write / pull-requests: write. GitHub's canonical auto-merge example in "Automating Dependabot with GitHub Actions" is on: pull_request with exactly that block and the same gh pr merge --auto call.

I would also rather not adopt the suggested alternative on its own merits. pull_request_target runs in the context of the base repository with a writable token — the pattern to avoid unless fork-authored code genuinely has to be handled. Dependabot branches live in this repository, not a fork, so it would take on that risk for no gain. I have recorded the reasoning in a comment at the top of the workflow so the trigger choice is not "corrected" later.

If it turns out the token really is read-only in practice, the failure will be loud and contained — the first Dependabot pull request will fail at gh pr review and simply sit there awaiting a human, which is the current behaviour anyway. I would rather find that out than pre-emptively adopt a riskier trigger.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 issue found across 2 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name=".github/workflows/dependabot-auto-merge.yml">

<violation number="1" location=".github/workflows/dependabot-auto-merge.yml:64">
P1: When Dependabot reports a security major update, `UPDATE_TYPE` is `security-update:semver-major`, so this condition falls through and auto-merges a non-runtime dependency. Match both update-type prefixes, because the policy explicitly excludes all majors, including security advisories.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

names=",$(printf '%s' "$DEPENDENCY_NAMES" | tr -d '[:space:]'),"
reason=""

if [ "$UPDATE_TYPE" = "version-update:semver-major" ]; then

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1: When Dependabot reports a security major update, UPDATE_TYPE is security-update:semver-major, so this condition falls through and auto-merges a non-runtime dependency. Match both update-type prefixes, because the policy explicitly excludes all majors, including security advisories.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At .github/workflows/dependabot-auto-merge.yml, line 64:

<comment>When Dependabot reports a security major update, `UPDATE_TYPE` is `security-update:semver-major`, so this condition falls through and auto-merges a non-runtime dependency. Match both update-type prefixes, because the policy explicitly excludes all majors, including security advisories.</comment>

<file context>
@@ -31,24 +46,60 @@ jobs:
+          names=",$(printf '%s' "$DEPENDENCY_NAMES" | tr -d '[:space:]'),"
+          reason=""
+
+          if [ "$UPDATE_TYPE" = "version-update:semver-major" ]; then
+            reason="this is a major version update, where a fix is most likely to change behaviour"
+          else
</file context>
Suggested change
if [ "$UPDATE_TYPE" = "version-update:semver-major" ]; then
if [ "$UPDATE_TYPE" = "version-update:semver-major" ] ||
[ "$UPDATE_TYPE" = "security-update:semver-major" ]; then

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ab1948bf20

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +103 to +104
gh pr review "$PR" --approve \
--body "Automatically approved: ${UPDATE_TYPE} for ${DEPENDENCY_NAMES}. These affect CI only; the shipped package is unchanged."

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Remove the approval that prevents enabling auto-merge

When the repository's Allow GitHub Actions to create and approve pull requests setting is disabled, gh pr review --approve is rejected even when the job grants pull-requests: write; because this script uses set -e, it exits before gh pr merge --auto runs. The change describes enabling auto-merge but not this separate Actions setting, and branch protection deliberately requires no approval, so remove this unnecessary command or explicitly enable the repository setting documented under default GITHUB_TOKEN permissions.

Useful? React with 👍 / 👎.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci CI and release workflows

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant