Problem
Today, every PR — whether Dependabot or a developer contribution — is merged directly onto main. This creates friction:
Every merge triggers a CI run on main, even for WIP or draft contributions
Release cadence is decoupled from development — no consolidated view of what is about to ship
No integration step to catch cross-package conflicts before shipping
Developers must coordinate merges to avoid stepping on each other on main
Solution
Adopt a staging branch model for all contributions (flat):
feat/xyz PR ─┐
fix/abc PR ─┼──► staging ──► main (release)
dep PRs ─┘
All PRs (dev + Dependabot) target staging directly. main is never the target of a PR.
Staging is an accumulation and integration branch — never a working branch
Each dev opens one PR per feature/fix, targeting staging
Staging is merged into main when the team decides the train is ready
Changes required
.github/dependabot.yml :
.github/workflows/release-on-merge.yml — new file:
Trigger: push on main
Steps: checkout (full history), pnpm install, changesets/version + changesets/publish
OIDC/Trusted Publishing: permissions: { id-token: write } + NPM_CONFIG_PROVENANCE: true
Skip the merge commit itself (detect via github.event.head_commit.message)
Branch setup (manual, not in repo) :
Create staging from main
Add branch protection on staging: PRs required, CI required, no force-push
Update branch protection on main: direct pushes disabled, only staging PR can merge
All existing contributors notified: PRs now target staging, not main
What stays the same
Major-version Dependabot PRs still require manual review before merge onto staging
group-by: dependency-name (from ci: deduplicate Dependabot PRs in monorepo via group-by #43 ) still applies
apps/web with private: true is never published
changesets/action v1.9.0 is still the production-safe version
Merge strategy on staging (Decision needed)
Option
Behavior
Squash and merge
One commit per PR lands on staging
Merge commit
Full history preserved on staging
Recommendation : Squash and merge — keeps staging history clean and linear.
Hotfix path
If a hotfix must bypass the staging gate:
Branch from main, fix, open PR to staging with label "hotfix"
Fast-track CODEOWNERS review
Merge staging -> main immediately
Normal features always go through staging.
Acceptance Criteria
Related
Risks
Medium : Process change for all contributors — requires communication and CONTRIBUTING.md update.
Low : Staging can drift from main if left unmerged too long. Mitigate with a scheduled sync or reminder.
Low : CI reliability on staging — if CI is flaky, the train stalls.
Problem
Today, every PR — whether Dependabot or a developer contribution — is merged directly onto main. This creates friction:
Solution
Adopt a staging branch model for all contributions (flat):
All PRs (dev + Dependabot) target staging directly. main is never the target of a PR.
Changes required
.github/dependabot.yml:
.github/workflows/release-on-merge.yml — new file:
Branch setup (manual, not in repo):
What stays the same
Merge strategy on staging (Decision needed)
Recommendation: Squash and merge — keeps staging history clean and linear.
Hotfix path
If a hotfix must bypass the staging gate:
Normal features always go through staging.
Acceptance Criteria
Related
Risks