|
1 | | -# Branching & merge policy |
| 1 | +# Branching & Merge Policy |
2 | 2 |
|
3 | | -This repo runs in **two deployment modes** from a single codebase. The provider |
4 | | -abstraction in `backend/llm_provider.py` and `backend/auth_provider.py` lets |
5 | | -the SAME source code switch between modes via env vars only. |
| 3 | +This repo keeps provider logic behind `backend/llm_provider.py` and |
| 4 | +`backend/auth_provider.py` so auth and LLM behavior can be configured without |
| 5 | +rewriting product code. |
6 | 6 |
|
7 | | -| Branch | LLM_PROVIDER | AUTH_PROVIDER | Where it runs | |
8 | | -| ------------- | ------------ | ------------- | ---------------------------- | |
9 | | -| `master` | `emergent` | `emergent` | emergent.sh preview + deploy | |
10 | | -| `local_setup` | `bedrock` | `jwt` | your local / self-hosted | |
| 7 | +| Branch | LLM_PROVIDER | AUTH_PROVIDER | Where it runs | |
| 8 | +| --------- | ------------ | ------------- | -------------------------- | |
| 9 | +| `master` | `bedrock` | `jwt` | primary development branch | |
| 10 | +| `release` | n/a | n/a | PR-only release branch | |
11 | 11 |
|
12 | 12 | > **Source of truth: `master`.** Features land here first. |
| 13 | +> **`release` is PR-only.** Nobody should push directly or force-update it, but |
| 14 | +> release PRs can be reviewed and merged. |
13 | 15 |
|
14 | 16 | --- |
15 | 17 |
|
16 | | -## Day-to-day workflow |
| 18 | +## Day-to-day Workflow |
17 | 19 |
|
18 | | -### 1. New feature on Emergent.sh |
19 | | -``` |
20 | | -work in emergent.sh chat → "Save to GitHub" → master |
21 | | -``` |
22 | | -Emergent pushes to `master`. Done. |
23 | | - |
24 | | -### 2. Sync local with the latest master |
25 | | -``` |
26 | | -git checkout local_setup |
27 | | -git fetch origin |
28 | | -git merge origin/master |
29 | | -# resolve conflicts ONLY in expected files (server.py rare; .env never) |
30 | | -git push |
31 | | -``` |
| 20 | +### 1. New work |
32 | 21 |
|
33 | | -### 3. Local-only changes (deployment configs, infra) |
34 | 22 | ``` |
35 | | -git checkout local_setup |
| 23 | +git checkout master |
| 24 | +git pull |
| 25 | +git checkout -b feat/my-change |
36 | 26 | # make changes |
37 | | -git commit -m "infra: bump fly.toml memory" |
38 | | -git push |
| 27 | +git push -u origin feat/my-change |
| 28 | +# open PR feat/my-change -> master |
39 | 29 | ``` |
40 | | -**Never** PR these back to master. |
41 | 30 |
|
42 | | -### 4. Polish/refactor done locally that SHOULD reach master |
| 31 | +### 2. Release work |
| 32 | + |
43 | 33 | ``` |
44 | | -git checkout master |
45 | | -git pull |
46 | | -git checkout -b feat/my-polish |
47 | | -git cherry-pick <commit-sha-from-local_setup> |
48 | | -# verify nothing provider-specific snuck in (see checklist below) |
49 | | -git push -u origin feat/my-polish |
50 | | -# open PR feat/my-polish → master |
| 34 | +git checkout -b release/v0.1.0 master |
| 35 | +git push -u origin release/v0.1.0 |
| 36 | +# open PR release/v0.1.0 -> release |
51 | 37 | ``` |
52 | | -**Do not** PR `local_setup → master` directly. Always cherry-pick into a |
53 | | -feature branch first. |
54 | 38 |
|
55 | 39 | --- |
56 | 40 |
|
57 | 41 | ## What MUST stay on `master` |
58 | 42 |
|
59 | 43 | These are enforced automatically by `.github/workflows/master-guardrails.yml`: |
60 | 44 |
|
61 | | -1. `backend/.env.example` defaults to `LLM_PROVIDER=emergent` and `AUTH_PROVIDER=emergent` |
62 | | -2. `backend/llm_provider.py` and `backend/auth_provider.py` exist |
63 | | -3. `emergentintegrations` stays in `backend/requirements.txt` |
64 | | -4. No `.env` file is committed |
65 | | -5. No real AWS keys / JWT secrets in the diff |
| 45 | +1. `backend/llm_provider.py` and `backend/auth_provider.py` exist |
| 46 | +2. No `.env` file is committed |
| 47 | +3. No real AWS keys / JWT secrets in the diff |
66 | 48 |
|
67 | 49 | The PR template's checklist asks reviewers to verify the same. |
68 | 50 |
|
69 | 51 | --- |
70 | 52 |
|
71 | | -## What MUST stay on `local_setup` |
| 53 | +## Required GitHub Branch Protection |
72 | 54 |
|
73 | | -(no automation — these are human discipline) |
| 55 | +Go to **Settings -> Branches -> Add branch protection rule**: |
74 | 56 |
|
75 | | -1. `backend/.env`: `LLM_PROVIDER=bedrock`, `AUTH_PROVIDER=jwt`, plus AWS + JWT secrets |
76 | | -2. Any deployment configs your stack needs (Dockerfile tweaks, `fly.toml`, |
77 | | - `nginx.conf`, k8s manifests, etc.) — keep them in a `deploy/` folder so they |
78 | | - are easy to keep separate during cherry-picks |
79 | | -3. Optional `requirements.local.txt` if you ever need self-hosted-only Python |
80 | | - deps that should NOT ship to master |
| 57 | +- **Branch name pattern**: `master` |
| 58 | +- Require a pull request before merging |
| 59 | +- Require approvals if you want review gates |
| 60 | +- Require review from Code Owners if `.github/CODEOWNERS` is configured |
| 61 | +- Require status checks to pass before merging |
| 62 | + - Add: `Scan for forbidden content` |
| 63 | +- Require branches to be up to date before merging |
| 64 | +- Do not allow bypassing the above settings |
| 65 | +- Restrict pushes that create matching branches if you want to block direct pushes |
| 66 | + |
| 67 | +> The workflow must run at least once on a PR before its jobs appear in the |
| 68 | +> "Status checks" picker. Open a small PR to surface them. |
81 | 69 |
|
82 | 70 | --- |
83 | 71 |
|
84 | | -## Required GitHub branch protection (one-time setup in GitHub UI) |
| 72 | +## Required GitHub Release Branch Protection |
85 | 73 |
|
86 | | -Go to **Settings → Branches → Add branch protection rule**: |
| 74 | +To allow PRs into `release` while blocking direct pushes, use a GitHub ruleset |
| 75 | +or branch protection rule that requires pull requests. |
87 | 76 |
|
88 | | -- **Branch name pattern**: `master` |
89 | | -- ✅ Require a pull request before merging |
90 | | - - ✅ Require approvals: at least 1 |
91 | | - - ✅ **Require review from Code Owners** ← enables `.github/CODEOWNERS` |
92 | | -- ✅ Require status checks to pass before merging |
93 | | - - Add: `Scan for forbidden content` |
94 | | - - Add: `Branch-name & PR-title check for local_setup cherry-picks` |
95 | | -- ✅ Require branches to be up to date before merging |
96 | | -- ✅ Do not allow bypassing the above settings |
97 | | -- ✅ Restrict pushes that create matching branches (optional — locks down direct pushes) |
| 77 | +Go to **Settings -> Rules -> Rulesets -> New ruleset -> New branch ruleset**: |
98 | 78 |
|
99 | | -> The `master-guardrails` workflow MUST run at least once on a PR before its |
100 | | -> jobs appear in the "Status checks" picker. Open a no-op PR (e.g., editing |
101 | | -> this file) to surface them. |
| 79 | +- **Ruleset name**: `Protect release branch` |
| 80 | +- **Enforcement status**: `Active` |
| 81 | +- **Target branches**: include by pattern, `release` |
| 82 | +- Enable: |
| 83 | + - **Require a pull request before merging** |
| 84 | + - **Require status checks to pass** |
| 85 | + - **Restrict deletions** |
| 86 | + - **Block force pushes** |
| 87 | + - **Require linear history** if available |
| 88 | +- Do not enable **Restrict updates** if you want normal PR merges to work. |
| 89 | +- If you are solo, keep required approvals at `0` or add yourself as an allowed |
| 90 | + bypass actor only if GitHub requires an escape hatch. |
102 | 91 |
|
103 | | -> **Before any of this kicks in, edit `.github/CODEOWNERS`** and replace |
104 | | -> `@YOUR-GITHUB-USERNAME` with your real GitHub handle (or a team handle like |
105 | | -> `@your-org/maintainers`). Without that, the `Require review from Code Owners` |
106 | | -> rule has no one to assign. |
| 92 | +Also keep `.github/workflows/master-guardrails.yml` required for PRs so release |
| 93 | +PRs get the same secret/provider checks as `master`. |
107 | 94 |
|
108 | 95 | --- |
109 | 96 |
|
110 | 97 | ## Troubleshooting |
111 | 98 |
|
112 | 99 | **Q: `git merge origin/master` produced a conflict in `backend/.env`.** |
113 | | -A: That should never happen — `.env` is gitignored. Double-check your local |
114 | | -checkout doesn't have `backend/.env` tracked (`git rm --cached backend/.env`). |
115 | | - |
116 | | -**Q: I accidentally pushed Bedrock defaults to master.** |
117 | | -A: The `master-guardrails` action will block the PR. If somehow it merged, |
118 | | -revert with `git revert <merge-sha>` and force-restore the `emergent` |
119 | | -defaults in `backend/.env.example`. |
120 | | - |
121 | | -**Q: I want to test JWT mode against the live preview without breaking |
122 | | -master.** |
123 | | -A: Don't. Test it on `local_setup` or in a temporary branch. The Emergent |
124 | | -preview env always boots from master's `.env`, which must stay on emergent |
125 | | -defaults. |
| 100 | +A: That should never happen because `.env` is gitignored. Double-check your local |
| 101 | +checkout does not have `backend/.env` tracked: |
| 102 | + |
| 103 | +``` |
| 104 | +git rm --cached backend/.env |
| 105 | +``` |
| 106 | + |
| 107 | +**Q: The guardrail workflow blocked a PR.** |
| 108 | +A: Fix the flagged file in your feature branch, push again, and let the PR checks |
| 109 | +rerun. |
0 commit comments