Skip to content

Forward-only develop with dual-target Dependabot + codegen; push-vs-pull docs - #78

Merged
ptr727 merged 3 commits into
developfrom
forward-only-and-codegen-to-develop
May 11, 2026
Merged

Forward-only develop with dual-target Dependabot + codegen; push-vs-pull docs#78
ptr727 merged 3 commits into
developfrom
forward-only-and-codegen-to-develop

Conversation

@ptr727

@ptr727 ptr727 commented May 11, 2026

Copy link
Copy Markdown
Owner

Codifies the branching model AGENTS.md actually implies and aligns the bots/docs to match. Closes the gap that made me push two unnecessary admin-bypass back-merges (ffb9e64 and 5ce95cf) — those violated the develop squash-only ruleset and shouldn't have happened.

What changes

Workflow + config

File Change
.github/dependabot.yml Every ecosystem (nuget, github-actions, uv) now has two entries — one with target-branch: "main", one with target-branch: "develop". Dependabot opens parallel PRs against each branch independently.
.github/workflows/run-codegen-pull-request-task.yml Codegen runs as a matrix over main and develop. Branches codegen-main and codegen-develop; each opens a PR against its own base. fail-fast: false so a per-branch failure doesn't block the other.
.github/workflows/merge-bot-pull-request.yml merge-codegen Accepts both head/base pairings (codegen-main → main, codegen-develop → develop) with strict pairing to prevent cross-targeting. Merge step uses the same case statement as merge-dependabot to dispatch --squash (develop) vs --merge (main) per base.

Documentation

  • AGENTS.md "Branching Model" — new bullets codifying forward-only develop (no main → develop back-merges; develop squash-only ruleset blocks them) and the dual-target bot pattern with rationale.
  • README.md "Template - Branching Workflow" — rewritten to mirror AGENTS.md. Drops the stale "Squash and merge from develop to main" and "bots merge into main directly" lines.
  • README.md "Template - Release Distribution Model: Push vs. Pull" (new section) — documents the default push-on-merge release model (every commit on main → release) and walks through the manual-release alternative for HACS / distro-vendored projects, referencing homeassistant-purpleair as the working example.
  • README.md "Template - GitHub Setup" — codegen auto-merge condition updated for the new head/base pairing + actor check + dual-target pointer. Rulesets section split into Develop (squash-only) and Main (merge-only) with shared settings called out.

Why dual-target, not develop-only

Considered develop-only-with-flow-through (codegen and Dependabot target develop only; main picks up changes through develop → main releases). Two problems with that model:

  1. Push-distribution channels consume main directly — HACS, distros that vendor from main, Linux package managers. If main only got dep bumps via the next develop → main release and the release cadence is tied to feature completion, main runs stale code for weeks.
  2. Codegen content can be production-critical. This template's codegen is trivial demo content (quote-of-the-day, date stamps), but derived projects can use codegen for live API-derived data (language lists, build catalogs, license databases). Stale codegen on main isn't merely cosmetic.

Dual-target keeps both branches current on their own cadence, no back-merges, forward-only invariant preserved.

Test plan

  • CI passes on this PR.
  • After merge to develop, the next Dependabot scheduled run opens two PRs per ecosystem (one against main, one against develop).
  • Next codegen run opens two PRs (one against main, one against develop).
  • Each PR auto-merges via the merge-bot using the correct method (--squash for develop, --merge for main).
  • No more back-merges land on develop.

…ull docs

Codifies the branching model AGENTS.md actually implies: develop is
forward-only (no main -> develop back-merges, develop ruleset squash-
only blocks them anyway), and every automated content path (Dependabot
scheduled updates, codegen) opens *parallel* PRs against main and
develop so both branches stay current independently without any
back-merging.

Reasoning the historical back-merges suggested otherwise: when only
develop received bot PRs, main fell out of date on dep versions and
generated content until the next develop -> main release. For projects
on pull-distribution channels (Docker, NuGet, PyPI) where every push
to main triggers a release, that worked fine because the next release
was usually imminent. For projects on push-distribution channels (HACS,
distros that vendor from main directly) or with long-running develop
features, main could go stale for weeks. The previous "back-merge
main into develop occasionally" workaround violates the develop ruleset
(merge commits forbidden on develop). The dual-target bot model is the
clean fix.

Workflow + config changes
- .github/dependabot.yml: every ecosystem now has two entries, one
  with `target-branch: "main"` and one with `target-branch: "develop"`.
  Dependabot opens parallel PRs to each branch independently. Header
  comment rewritten to explain the dual-target rationale.
- .github/workflows/run-codegen-pull-request-task.yml: codegen now runs
  as a matrix over `main` and `develop`. Branch names are codegen-main
  and codegen-develop; each opens its own PR against its base. `fail-
  fast: false` so a failure on one branch doesn't block the other.
- .github/workflows/merge-bot-pull-request.yml `merge-codegen` job:
  accepts either head/base pair (codegen-main -> main or
  codegen-develop -> develop) with strict pairing so a misconfigured
  branch can't cross targets. Merge step now uses the same `case`
  statement as merge-dependabot to dispatch --squash vs --merge by
  base ref. Header comment block updated to reflect the dual-target
  model.

Documentation
- AGENTS.md "Branching Model": new bullet codifying forward-only
  develop (with explicit callout that historical back-merge commits
  predate the rule). New bullet describing the dual-target bot model
  with rationale. Existing Dependabot-targets-develop bullet rolled
  into the dual-target one.
- README.md "Template - Branching Workflow": rewritten to match
  AGENTS.md exactly (squash to develop, merge-commit to main, forward-
  only, dual-target bots). Drops the stale "Squash and merge from
  develop to main" and "bots merge into main directly" lines.
- README.md "Template - Release Distribution Model: Push vs. Pull"
  (new section): documents the push-on-merge default this template
  ships with and the manual-release alternative for HACS / distro-
  vendored projects. Walks through the exact `publish-release.yml`
  trigger change and the trade-offs of keeping or dropping the
  main-target Dependabot entries in that mode. References
  homeassistant-purpleair as the working example.
- README.md "Template - GitHub Setup" codegen auto-merge condition:
  updated to show the new head/base pairing, the github.actor check,
  and a pointer to AGENTS.md "Branching Model" for the dual-target
  rationale. Rulesets section split into Develop (squash-only) and
  Main (merge-only) with shared settings called out separately.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 11, 2026 23:22

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR aligns repository automation and documentation with a forward-only develop branching model by having bots (Dependabot + codegen) open parallel PRs to both main and develop, and by updating merge automation and docs to prevent main → develop back-merges.

Changes:

  • Duplicate each Dependabot ecosystem entry so scheduled updates open PRs against both main and develop.
  • Run codegen as a matrix over main and develop, producing branch-paired PRs (codegen-main → main, codegen-develop → develop) and update merge-bot logic to enforce strict pairing + base-driven merge method.
  • Update AGENTS.md and README.md to document the forward-only develop model, dual-target bot rationale, and push-vs-pull release guidance.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
README.md Updates GitHub setup + branching workflow docs; adds push-vs-pull release model section and reflects dual-target bots.
AGENTS.md Codifies forward-only develop and dual-target bot strategy as the authoritative branching model.
.github/workflows/run-codegen-pull-request-task.yml Converts codegen into a main/develop matrix that opens one PR per base branch.
.github/workflows/merge-bot-pull-request.yml Enforces strict codegen head/base pairing and selects merge method via case on base ref.
.github/dependabot.yml Duplicates update configs so Dependabot targets both main and develop for each ecosystem.

Comment thread .github/workflows/run-codegen-pull-request-task.yml
Comment thread README.md
Comment thread README.md Outdated
…nable

Three fair findings from Copilot:

1. The matrix-job `name:` ended in the matrix ref (`(main)` /
   `(develop)`) instead of the required "job" suffix from AGENTS.md.
   Reorder to put the matrix ref before "job":
   `Run ${{ matrix.target.ref }} codegen and pull request job`.

2. README rulesets section had `Require linear history` in the
   "Shared settings" block while also noting it only applies to
   develop. That's contradictory and could mislead adopters into
   enabling it on main (where it would block merge commits). Move
   the setting into the Develop-only ruleset entry.

3. README repo-level Pull Requests settings listed only `Allow
   squash merging`, but the main ruleset is merge-commit-only — so
   "Allow merge commits" must also be enabled at the repo level
   (rulesets pick from what the repo permits). Rewrote that block
   to enable both squash and merge, dropped the stale TODO about
   disabling merge/rebase (which contradicts the actual config).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Comment thread .github/workflows/merge-bot-pull-request.yml Outdated
Comment thread README.md Outdated
@ptr727
ptr727 enabled auto-merge (squash) May 11, 2026 23:33
Copilot review on 6458380 caught that the prior wording claimed the
github.actor check stops maintainer-pushed commits from auto-merging.
That's only half right: it stops the *job* from re-enabling
auto-merge, but it doesn't disable auto-merge that's already active
from the initial bot-driven `opened` event. So once auto-merge is on,
any commit that passes CI will land — including a maintainer's.

Rewrite both the workflow comment and the README auto-merge condition
to spell this out accurately, with the maintainer-edit workaround
(`gh pr merge --disable-auto <PR>` before pushing).

A real safeguard job (a `synchronize`-triggered `disable-auto` for
non-bot actors) is a worthwhile follow-up but is out of scope for
this PR.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated no new comments.

@ptr727
ptr727 merged commit 1b1df86 into develop May 11, 2026
25 checks passed
ptr727 added a commit that referenced this pull request May 12, 2026
…nups (#77)

Release merge: brings two squashed PRs and one unnecessary back-merge
commit from `develop` into `main`.

## Squashed PRs included

- **#76 — Document `dotnet/nbgv@master` exception and drop redundant
`secrets: inherit`.**
- `.github/workflows/get-version-task.yml`: inline comment carves out
`dotnet/nbgv@master` as the deliberate deviation from the AGENTS.md
SHA-pinning rule (upstream tag stream is dormant, Dependabot would stall
or attempt a downgrade if we pinned, upstream owner is Microsoft so
retargeting risk is low).
- `.github/workflows/build-nugetlibrary-task.yml`: dropped `secrets:
inherit` from the `get-version` job call (same fix PR #74 applied to
`build-pypilibrary-task.yml`).

- **#78 — Forward-only develop with dual-target Dependabot + codegen.**
The substantive change in this release:
- **AGENTS.md "Branching Model"** explicitly codifies forward-only
develop (no `main → develop` back-merges; develop squash-only ruleset
blocks them) and the dual-target bot model with rationale.
- **`.github/dependabot.yml`** duplicates every ecosystem entry per
branch (six entries total) so Dependabot opens parallel PRs against both
`main` and `develop` independently. Both branches stay current on dep
versions without back-merges.
- **`.github/workflows/run-codegen-pull-request-task.yml`** runs as a
matrix over `main` and `develop`. Branch names `codegen-main` and
`codegen-develop`; each opens a PR against its own base.
- **`.github/workflows/merge-bot-pull-request.yml`** `merge-codegen` job
uses strict head/base pairing and dispatches `--squash` (develop) vs
`--merge` (main) per base, same `case` statement pattern as
`merge-dependabot`.
- **README.md "Template - Release Distribution Model: Push vs. Pull"**
(new section) — documents the default push-on-merge model and the
manual-release alternative for HACS / distro-vendored projects,
referencing
[homeassistant-purpleair](https://github.com/ptr727/homeassistant-purpleair)
as the working example.
- **README.md "Template - GitHub Setup"** rulesets section split into
separate Develop (squash-only + `Require linear history`) and Main
(merge-commit-only) rulesets with shared settings extracted. Repo-level
Pull Requests block now correctly shows **both** `Allow merge commits`
and `Allow squash merging` enabled (the prior wording suggested merge
would be disabled, which contradicted the actual main ruleset).

## Unnecessary back-merge `5ce95cf` (acknowledged misstep)

I opened this release with a `Merge remote-tracking branch 'origin/main'
into develop` commit assuming the back-merge pattern was the standard
cycle close. **It wasn't.** That model conflicts with AGENTS.md's
squash-only develop rule (the push only succeeded via admin bypass). PR
#78's AGENTS.md update now explicitly forbids future back-merges and
routes both bots to update both branches independently — closing the gap
that made this pattern feel necessary.

The back-merge commit is left in place: reverting requires a destructive
force-push to develop. Behavioral effect is a one-time gitHeight bump,
which fixes the `--pre` channel ordering (develop's next dev publish is
now unambiguously higher than main's last release).

## Operator action items (already completed)

- `CODEGEN_APP_ID` / `CODEGEN_APP_PRIVATE_KEY` in both Actions and
Dependabot secret stores. ✓
- `WORKFLOW_PAT` secret + PAT revoked. ✓
- `pypi` GitHub environment Deployment branch rule allows `main` and
`develop`. ✓

## Open follow-up (tracked separately, not in this release)

PR #78 documented a limitation in the actor-check guardrail on
`merge-codegen` / `merge-dependabot`: it stops the merge-bot from
re-invoking `gh pr merge --auto` on a maintainer-triggered
`synchronize`, but **does not** disable auto-merge that's already
enabled. Once auto-merge is on a bot PR, maintainer commits will land.
The honest workaround is documented (`gh pr merge --disable-auto <PR>`
before pushing). The real safeguard — a `synchronize`-triggered job that
disables auto-merge automatically when the actor isn't the bot — is a
follow-up PR I'll open after this release lands.

## Notes

- Merge method: **merge-commit** (per [AGENTS.md branching
model](https://github.com/ptr727/ProjectTemplate/blob/develop/AGENTS.md#branching-model)).

## Test plan

- [ ] CI passes on the merge commit.
- [ ] `publish-release.yml` on main publishes `1.0.<N>.<B>` as the next
stable release.
- [ ] After release, `pip install ptr727-projecttemplate-library`
resolves to the new stable; `pip install --pre
ptr727-projecttemplate-library` resolves to the latest develop dev
(assuming develop's gitHeight exceeds main's, which the back-merge
ensures).
- [ ] Next Dependabot scheduled run opens **two** PRs per ecosystem (one
against main, one against develop).
- [ ] Next codegen weekly run opens **two** PRs (`codegen-main` against
main, `codegen-develop` against develop).
- [ ] Each bot PR auto-merges via the merge-bot with the correct method
(`--squash` for develop, `--merge` for main).
@ptr727
ptr727 deleted the forward-only-and-codegen-to-develop branch May 12, 2026 01:14
ptr727 added a commit that referenced this pull request May 12, 2026
Copilot review on PR #79 flagged the unpinned `actions/create-github-
app-token@v1` and I initially declined, citing AGENTS.md's clause
that "first-party `actions/*` are encouraged but not required" to be
SHA-pinned. The maintainer corrected: that softening was meant
narrowly for `dotnet/nbgv@master` (where tag-tracking would propose
a downgrade), not as a blanket first-party exemption. Every other
action must be SHA-pinned.

Rule change in AGENTS.md "Workflow YAML Conventions":

- Old: third-party actions must be SHA-pinned; first-party `actions/*`
  are encouraged but not required.
- New: every action (first- or third-party) must be SHA-pinned. The
  only documented exception is `dotnet/nbgv@master`, whose rationale
  is recorded inline in get-version-task.yml.
- Also updated the meta-note from "Don't open a PR purely to apply
  these rules across the repo" to "Sweep PRs that apply a rule
  everywhere are welcome when a rule changes" — which is exactly
  what this commit does.

Sweep applied to every workflow file:

- `actions/checkout@v6` → `de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2`
- `actions/setup-dotnet@v5` → `c2fa09f4bde5ebb9d1777cf28262a3eb3db3ced7 # v5.2.0`
- `actions/create-github-app-token@v1` → `d72941d797fd3113feb6b93fd0dec494b13a2547 # v1.12.0` (4 occurrences across merge-bot + run-codegen)
- `actions/upload-artifact@v6` → `b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0`
- `actions/download-artifact@v7` → `37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0`

Every SHA is the current target of the floating tag it replaces, so
behaviour is unchanged at the moment of the pin; only the
defence-in-depth against tag retargeting is added. Future bumps come
through Dependabot's GitHub Actions ecosystem (already configured for
both `main` and `develop` per PR #78).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request May 12, 2026
… tag matches

Two follow-on Copilot findings on PR #79:

1. run-periodic-codegen-pull-request.yml header comment claimed the
   workflow "checks out and targets main/codegen" — stale since PR #78
   converted the reusable workflow to a matrix over both `main` and
   `develop` (branch names codegen-main / codegen-develop). Rewrote the
   concurrency comment and renamed the group from `codegen-main` to
   plain `codegen` to match the actual behavior (one group for the whole
   workflow; a new scheduled or manual run supersedes the matrix-legs
   of an in-flight one).

2. The `RubbaBoy/BYOB@a491910... # v1` pin uses a major-only version
   comment, but the AGENTS.md action-pinning rule prescribes
   `# vX.Y.Z`. The reason for the major-only comment: the upstream's
   `@v1` floating tag at RubbaBoy/BYOB points at a SHA that doesn't
   correspond to any specific v1.x tag (v1.3.0 is the latest specific
   release and has a different SHA). Pinning to v1.3.0 would be a
   behavior change away from what the floating tag currently delivers.
   Updating AGENTS.md to allow `# vX` (major-only) in this narrow case
   — the SHA pin still gives full protection, only the version comment
   loses specificity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request May 12, 2026
Implements the follow-up that PR #78 deferred: a workflow job that
automatically disables auto-merge on a bot PR when a maintainer pushes
commits to the bot's branch.

## Problem

PR #78 acknowledged that the `github.actor` check on `merge-codegen` /
`merge-dependabot` only stops those jobs from re-invoking `gh pr merge
--auto` on a maintainer-triggered `synchronize`. It does not disable
auto-merge that's already enabled from the initial bot-driven `opened`
event. So once auto-merge is on a bot PR, any maintainer commit pushed
to the bot's branch would be auto-merged when CI passed. The documented
workaround ("`gh pr merge --disable-auto <PR>` before pushing") is
fragile.

## Solution

Three-job model in
[`.github/workflows/merge-bot-pull-request.yml`](.github/workflows/merge-bot-pull-request.yml):

1. **`merge-dependabot` / `merge-codegen`** — now restricted to `opened`
and `reopened` events only. Each enables auto-merge exactly once per PR.
Skipping `synchronize` is what keeps step 3's disable sticky (otherwise
a bot-triggered rebase synchronize would re-enable auto-merge and undo
the safeguard).
2. **Method dispatch unchanged** — same `case` statement on
`pull_request.base.ref` (develop → `--squash`, main → `--merge`).
3. **NEW: `disable-auto-merge-on-maintainer-push`** — fires on
`synchronize` events against bot-authored PRs when the event actor is
NOT the same bot. Calls `gh pr merge --disable-auto`. The command is
idempotent.

### Token strategy

The new job uses an App token (same pattern as the other jobs) because
Dependabot PRs run the workflow with restricted secrets regardless of
event actor — `GITHUB_TOKEN` would be read-only.

### Side change

Dropped `github.actor == 'ptr727-codegen[bot]'` from `merge-codegen`'s
`if:`. It was a partial safeguard against the same case that the new
disable job now handles properly. The remaining checks (PR author,
strict head/base pairing, opened/reopened filter) are sufficient.

## Documentation

- [`AGENTS.md`](AGENTS.md) Branching Model — new bullet documenting the
maintainer-push-disables-auto-merge invariant.
- [`README.md`](README.md) Template - GitHub Setup — codegen auto-merge
condition list now leads with the `opened`/`reopened` filter, drops the
obsolete `github.actor` warning that PR #78 had to soften, and adds a
dedicated bullet for the new disable job.

## Test plan

CI on this PR can only verify YAML/workflow syntax. The real test is
post-merge, manual:

- [ ] CI passes on this PR.
- [ ] After merge, wait for the next Dependabot scheduled bump on either
branch.
- [ ] Verify `merge-dependabot` enables auto-merge (visible as the
"Auto-merge enabled" banner on the PR).
- [ ] As a maintainer, push a trivial commit to the Dependabot branch.
- [ ] Verify `disable-auto-merge-on-maintainer-push` runs (visible in
Actions log) and the "Auto-merge enabled" banner disappears.
- [ ] Verify the PR does NOT auto-merge when its CI passes.
- [ ] Manually re-enable auto-merge (`gh pr merge --auto <PR>` or UI)
and confirm it merges normally.

Same test applies to codegen PRs (next Monday's run, or
`workflow_dispatch` on `run-periodic-codegen-pull-request.yml`).

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request May 12, 2026
…forward-only) (#81)

Resolves the root cause behind why [PR
#80](#80) (the develop →
main release) is blocked by "the head branch is not up to date with the
base branch". The forward-only develop model PR #78 codified is
fundamentally incompatible with the ruleset's `Require branches to be up
to date before merging` rule, and the README's documented "shared
settings" block hid the contradiction.

## What's actually happening

The "up to date" check is **graph-based**: it asks "is main's tip commit
reachable from develop?", not "does develop have main's content?". After
any develop → main release, main has a new merge commit (e.g. `fb10a16`
from PR #77) whose first-parent walk isn't in develop's history. Develop
is strictly *ahead* in content but "behind" in graph terms.

Historical back-merge commits (`ffb9e64`, `5ce95cf`) had been **quietly
compensating** for this — each one created a develop commit whose second
parent was main's release-merge commit, making main's tip reachable from
develop. PR #78 codified forward-only and forbade back-merges, but the
README rulesets section still listed `Require branches to be up to date`
as a shared setting. The contradiction was invisible until the first
release without a preceding back-merge tried to land — which is PR #80.

## What this PR changes

- **`README.md`** "Rules / Rulesets": move `Require branches to be up to
date before merging` out of "Shared settings" and into the Develop-only
ruleset entry (where it's standard hygiene for feature → develop
merges). Add explicit "intentionally OFF" callout in the Main ruleset
entry with the full rationale.
- **`AGENTS.md`** "Branching Model": new bullet codifying *why* the main
ruleset omits this rule, with a pointer to README for the configured
state.

## What you'll need to do in the GitHub UI

Untick `Require branches to be up to date before merging` in **Settings
→ Rulesets → Main**. That's a config change, not a code change, and
rulesets are security-sensitive so it stays your direct action. After:

- PR #80 will merge cleanly via `gh pr merge --merge` (no admin bypass
needed).
- Future develop → main releases land without admin bypass.

## Test plan

- [ ] CI passes on this PR.
- [ ] After merge to develop, PR #80's head auto-advances to include
this docs update.
- [ ] After you untick the rule on Settings → Rulesets → Main, PR #80
merges cleanly without `--admin`.
- [ ] Future develop → main releases also land without admin bypass (the
safeguard PR #79's content joins this release on main once PR #80
lands).

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ptr727 added a commit that referenced this pull request May 12, 2026
…rules-docs alignment (#80)

Release merge: brings two squashed PRs from `develop` into `main`.

## Squashed PRs included

- **#79 — Disable auto-merge on maintainer push to bot PR.** Started
narrow (a `synchronize`-triggered job that calls `gh pr merge
--disable-auto` when a maintainer pushes to a bot PR, closing the gap PR
#78 documented but didn't fix) and grew to cover repo-wide SHA pinning
of every action after the maintainer corrected my reading of AGENTS.md's
first-party-actions clause.

  ### What landed
- **New `disable-auto-merge-on-maintainer-push` job** in
`.github/workflows/merge-bot-pull-request.yml`. Fires on
`pull_request.synchronize` events against bot-authored PRs (Dependabot
or codegen) when the event actor isn't the same bot — calls `gh pr merge
--disable-auto`. App-token-driven (Dependabot PRs run with restricted
secrets regardless of event actor).
- **`merge-dependabot` and `merge-codegen` restricted to
`opened`/`reopened`** so auto-merge is enabled exactly once per PR;
skipping `synchronize` is what keeps the disable safeguard sticky
against bot rebases.
- **`concurrency.cancel-in-progress: false`** in
`merge-bot-pull-request.yml` so the three-job model runs events to
completion in arrival order.
- **Every action SHA-pinned** across all workflows: `actions/*`
(checkout, setup-dotnet, create-github-app-token, upload-artifact,
download-artifact), `docker/*` (setup-qemu-action, setup-buildx-action,
login-action, build-push-action), and `RubbaBoy/BYOB`.
`dotnet/nbgv@master` is the only documented exception.
- **AGENTS.md "Workflow YAML Conventions"** tightened: every action must
be SHA-pinned (the prior "first-party `actions/*` encouraged but not
required" softening is gone). `# vX` major-only comment allowed when
upstream's floating major tag doesn't correspond to a specific
patch/minor release SHA. Concurrency convention gains a documented
exception for `merge-bot-pull-request.yml`.
- **AGENTS.md "Branching Model"** + **README "Template - GitHub Setup"**
updated for the new disable job and the auto-merge condition list.

- **#81 — Drop "branches up to date" rule from main ruleset
(incompatible with forward-only).** Resolved the root cause behind PR
#80 being initially blocked. GitHub's "Require branches to be up to date
before merging" is a graph-based check (it asks whether main's tip merge
commit is reachable from develop) that's fundamentally incompatible with
the forward-only develop model PR #78 codified. Historical back-merges
had been quietly compensating for this; PR #78 forbade them but left the
README's documented "shared settings" ruleset block contradictorily
listing the rule.
- **README "Rules / Rulesets"**: moved `Require branches to be up to
date before merging` out of "Shared settings" into the Develop-only
ruleset entry (where it's standard hygiene). Added explicit
"intentionally OFF" callout in the Main ruleset entry with the full
rationale.
- **AGENTS.md "Branching Model"**: new bullet codifying *why* the main
ruleset omits this rule, framed purely in graph-reachability terms.

## Operator action already completed

- `Require branches to be up to date before merging` unticked on
Settings → Rulesets → Main. ✓ Verified via API.

## Notes

- Merge method: **merge-commit** (per [AGENTS.md branching
model](https://github.com/ptr727/ProjectTemplate/blob/develop/AGENTS.md#branching-model)).
- **No rebase required.** With the ruleset rule now disabled, GitHub no
longer enforces graph-reachability of main's tip from develop, so the
merge proceeds cleanly without admin bypass or back-merge.

## Test plan

- [ ] CI passes on the merge commit.
- [ ] `publish-release.yml` on main produces the next stable release.
- [ ] Next bot PR (Dependabot or codegen) opens with auto-merge enabled
exactly once. A maintainer push to the bot's branch disables auto-merge;
re-enable manually to land the maintainer's edits.
- [ ] No floating-tag actions remain anywhere in `.github/workflows/`
except `dotnet/nbgv@master`.
- [ ] Future develop → main releases land without admin bypass.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants