Skip to content
Merged
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
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Treat this file as authoritative for everything else; don't restate its rules el
- `develop` → `main` is **merge-commit only** (no squash, no rebase). Merge commits preserve develop's commit list as a real second-parent reference on main, which is what makes the "release on every push" model attribute releases to the develop commits that produced them. Branch protection enforces this: the develop ruleset allows only `squash`, the main ruleset allows only `merge`.
- All commits on both branches must be cryptographically signed (SSH or GPG). Squash and merge commits created via the GitHub UI are signed by GitHub's web-flow key.
- **`develop` is forward-only — no `main → develop` back-merges.** The develop ruleset's squash-only setting physically blocks merge commits on develop. Historical back-merge commits visible in `git log` (`b9b0447`, `410ba56`, `ffb9e64`, `5ce95cf`, etc.) predate this rule and must not be repeated.
- **Main ruleset intentionally omits "Require branches to be up to date before merging".** This GitHub branch-protection check is graph-based — it asks whether main's tip commit is reachable from develop, not whether the two branches have the same content. After any develop → main release, main's tip is a brand-new merge commit that develop's history doesn't contain. Forward-only develop never adds it (no back-merge of main into develop), so the check would fail on every subsequent release. Other technical workarounds — rebasing develop onto main, or rewriting develop's history — exist but contradict the squash-only develop ruleset and the linearity invariant. The develop ruleset keeps the "up to date" check on (it's normal hygiene for feature → develop merges); only the main ruleset omits it. See [`README.md`](./README.md#template---github-setup) "Rules / Rulesets" for the configured state.
- **Bots (Dependabot and codegen) target both `main` and `develop` in parallel.** [`.github/dependabot.yml`](./.github/dependabot.yml) duplicates every ecosystem entry (one per branch) and [`.github/workflows/run-codegen-pull-request-task.yml`](./.github/workflows/run-codegen-pull-request-task.yml) runs as a matrix over both branches with branch names `codegen-main` and `codegen-develop`. Each branch absorbs its own bot PRs independently, so neither falls behind, and the forward-only rule still holds (nothing is back-merged from main to develop — both branches receive their updates directly). The merge-bot ([`.github/workflows/merge-bot-pull-request.yml`](./.github/workflows/merge-bot-pull-request.yml)) dispatches `--squash` or `--merge` from each PR's base ref via a `case` statement so the form matches the ruleset on either base. Dependabot **security** PRs (CVE-driven) always open against the repo default branch (`main`) regardless of `target-branch` — the same `case` statement covers them.
- **Maintainer-pushed commits on a bot PR auto-disable auto-merge.** The merge-bot's `merge-dependabot` and `merge-codegen` jobs only fire on `opened` / `reopened` events (auto-merge is enabled exactly once per PR). When a maintainer pushes commits to a bot's branch (a `synchronize` event with an actor that isn't the same bot), the merge-bot's `disable-auto-merge-on-maintainer-push` job fires and calls `gh pr merge --disable-auto`. The maintainer's commits stay in the PR but won't auto-merge with the bot's content; re-enable auto-merge manually (`gh pr merge --auto <PR>` or the GitHub UI) when ready.
- **Why parallel dual-target rather than develop-only with eventual flow-through:** push-distribution channels (HACS for Home Assistant integrations, Linux distros that vendor from `main`, etc.) consume `main` directly. A develop-only model would leave `main` running stale code during long-running develop features. Codegen content can also be production-critical (live API-derived data, language lists, build catalogs) rather than just sample/demo content, so both branches need fresh codegen on their own cadence.
Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -478,15 +478,17 @@ Licensed under the [MIT License][license-link]\
- `Allow rebase merging` — disabled (no flow uses it; the develop ruleset forbids it anyway)
- `Always suggest updating pull request branches`
- `Allow auto-merge`
- Rules / Rulesets — **separate rulesets per branch** so allowed merge methods differ (develop = squash-only; main = merge-commit-only, per AGENTS.md). Everything else is shared.
- Rules / Rulesets — **separate rulesets per branch**. Develop and main intentionally diverge on three rules — allowed merge methods, `Require linear history`, and `Require branches to be up to date before merging`; everything else is shared.
- "Develop":
- Target branches: `develop`.
- Allowed merge methods: `Squash`
- `Require linear history` (develop is kept linear; main carries merge commits by design, so this setting belongs to develop only)
- `Require status checks to pass` → `Require branches to be up to date before merging` ✓ (feature branches must rebase or merge develop before merging back — standard hygiene)
- Plus shared settings (below).
- "Main":
- Target branches: `main`.
- Allowed merge methods: `Merge`
- `Require status checks to pass` → `Require branches to be up to date before merging` **intentionally OFF**. This rule is incompatible with the forward-only develop model. GitHub's "up to date" check is graph-based: it asks whether main's tip commit is reachable from develop. After any develop → main release, main's new tip is a brand-new merge commit that develop's history doesn't contain. Forward-only develop never adds it (no back-merge of main into develop, no rebase of develop onto main), so the check fails permanently on every subsequent release. Leaving the rule on would force every release through an admin bypass. See [AGENTS.md "Branching Model"](./AGENTS.md#branching-model) for the full reasoning.
- Plus shared settings (below).
- Shared settings (apply to both rulesets):
- `Restrict deletions`
Expand All @@ -495,7 +497,6 @@ Licensed under the [MIT License][license-link]\
- `Dismiss stale pull request approvals when new commits are pushed`
- `Require conversation resolution before merging`
- `Require status checks to pass`
- `Require branches to be up to date before merging`
- Status checks that are required: `Check pull request workflow status`
- `Block force pushes`
- `Automatically request Copilot code review`
Expand Down
Loading