Skip to content

Commit 2a88198

Browse files
rafizamankhancursoragentchriscarrollsmith
authored
docs: document stripe branch and add propagate/CI support (#229)
* docs: document stripe branch and add propagate/CI support (#228) Point main docs and README at the optional stripe branch, document the merge recipe and conflict-prone files, and extend propagate.yml and test.yml so stripe receives main updates and runs CI with dummy Stripe env. Co-authored-by: Cursor <cursoragent@cursor.com> * fix(ci): keep Test workflow push triggers unfiltered Narrowing push to main/stripe would drop CI on feature branches and modal/hetzner; only extend pull_request targets for stripe. --------- Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: chriscarrollsmith <chriscarrollsmith@gmail.com>
1 parent 85b5fe9 commit 2a88198

7 files changed

Lines changed: 147 additions & 2 deletions

File tree

.github/workflows/propagate.yml

Lines changed: 99 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ jobs:
1313
strategy:
1414
fail-fast: false
1515
matrix:
16-
branch: [modal, hetzner]
16+
branch: [modal, hetzner, stripe]
1717
runs-on: ubuntu-latest
1818
steps:
1919
- name: Generate token
@@ -162,6 +162,101 @@ jobs:
162162
git push origin "$BRANCH"
163163
}
164164
165+
conflicts_are_stripe_overlay() {
166+
[ "$BRANCH" = "stripe" ] || return 1
167+
168+
conflicts="$(unresolved_conflicts)"
169+
[ -n "$conflicts" ] || return 1
170+
171+
while IFS= read -r file; do
172+
case "$file" in
173+
pyproject.toml|uv.lock) ;;
174+
*) return 1 ;;
175+
esac
176+
done <<< "$conflicts"
177+
}
178+
179+
add_stripe_dependency() {
180+
python3 <<'PY'
181+
from pathlib import Path
182+
import subprocess
183+
import tomllib
184+
185+
def is_stripe_dependency(dependency: str) -> bool:
186+
return dependency.split(";", 1)[0].strip().lower().startswith("stripe")
187+
188+
189+
def stripe_dependency_from_branch() -> str:
190+
try:
191+
result = subprocess.run(
192+
["git", "show", ":2:pyproject.toml"],
193+
check=True,
194+
capture_output=True,
195+
text=True,
196+
)
197+
except subprocess.CalledProcessError:
198+
return "stripe>=15.3.0"
199+
200+
dependencies = tomllib.loads(result.stdout).get("project", {}).get("dependencies", [])
201+
return next(
202+
(dependency for dependency in dependencies if is_stripe_dependency(dependency)),
203+
"stripe>=15.3.0",
204+
)
205+
206+
207+
path = Path("pyproject.toml")
208+
text = path.read_text()
209+
data = tomllib.loads(text)
210+
211+
dependencies = data.get("project", {}).get("dependencies", [])
212+
if any(is_stripe_dependency(dependency) for dependency in dependencies):
213+
raise SystemExit(0)
214+
215+
lines = text.splitlines()
216+
start = next(
217+
(index for index, line in enumerate(lines) if line.strip() == "dependencies = ["),
218+
None,
219+
)
220+
if start is None:
221+
raise SystemExit("Could not find project dependencies in pyproject.toml")
222+
223+
end = next(
224+
(index for index in range(start + 1, len(lines)) if lines[index].strip() == "]"),
225+
None,
226+
)
227+
if end is None:
228+
raise SystemExit("Could not find end of project dependencies in pyproject.toml")
229+
230+
lines.insert(end, f' "{stripe_dependency_from_branch()}",')
231+
path.write_text("\n".join(lines) + "\n")
232+
PY
233+
}
234+
235+
resolve_stripe_overlay() {
236+
if unresolved_conflicts | grep -qx "pyproject.toml"; then
237+
git checkout --theirs pyproject.toml
238+
fi
239+
240+
add_stripe_dependency
241+
242+
if unresolved_conflicts | grep -qx "uv.lock"; then
243+
git checkout --ours uv.lock
244+
fi
245+
246+
uv lock
247+
git add pyproject.toml uv.lock
248+
249+
remaining_conflicts="$(unresolved_conflicts)"
250+
if [ -n "$remaining_conflicts" ]; then
251+
echo "Conflicts remain after stripe overlay resolution:"
252+
echo "$remaining_conflicts"
253+
return 1
254+
fi
255+
256+
git commit --no-edit
257+
git push origin "$BRANCH"
258+
}
259+
165260
git checkout "$BRANCH"
166261
167262
if git merge origin/main --no-edit; then
@@ -170,6 +265,9 @@ jobs:
170265
elif conflicts_are_modal_overlay; then
171266
echo "Merge conflict only affects the modal dependency overlay; resolving automatically"
172267
resolve_modal_overlay
268+
elif conflicts_are_stripe_overlay; then
269+
echo "Merge conflict only affects the stripe dependency overlay; resolving automatically"
270+
resolve_stripe_overlay
173271
else
174272
echo "Merge conflict detected, opening PR"
175273
git merge --abort

.github/workflows/test.yml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: Test
33
on:
44
push:
55
pull_request:
6-
branches: [main]
6+
branches: [main, stripe]
77
workflow_dispatch:
88
workflow_call:
99

@@ -62,4 +62,10 @@ jobs:
6262
DB_NAME: db
6363
DB_USER: postgres
6464
DB_PASSWORD: postgres
65+
SECRET_KEY: test-secret-key-that-is-at-least-32-bytes-long
66+
BASE_URL: http://localhost:8000
67+
# Required on the stripe branch (billing always on); harmless on main.
68+
STRIPE_SECRET_KEY: sk_test_dummy
69+
STRIPE_WEBHOOK_SECRET: whsec_test_dummy
70+
STRIPE_PRICE_ID: price_test_dummy
6571
run: uv run pytest tests/

README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@ The template also includes full-featured secure auth with:
3434
- Password recovery flow
3535
- Role-based access control system
3636

37+
## Optional branches
38+
39+
Some capabilities are maintained on dedicated branches so `main` stays lean:
40+
41+
| Branch | Purpose |
42+
|--------|---------|
43+
| `main` | Core template (auth, orgs, RBAC) |
44+
| [`stripe`](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/stripe) | Organization-scoped Stripe billing |
45+
| [`modal`](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/modal) | Modal.com deployment artifacts |
46+
| [`hetzner`](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/hetzner) | Hetzner Cloud deployment artifacts |
47+
48+
New SaaS forks can start from `stripe`, or merge it later:
49+
50+
```bash
51+
git remote add upstream https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp.git
52+
git fetch upstream stripe
53+
git merge upstream/stripe
54+
```
55+
3756
## Design Philosophy
3857

3958
The design philosophy of the template is to prefer low-level,

user_guide/00-overview.qmd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ The template also includes full-featured secure auth with:
2424
- Password recovery flow
2525
- Role-based access control system
2626

27+
Optional [organization-scoped Stripe billing](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/stripe) (Checkout, Customer Portal, webhooks) lives on the **`stripe`** branch.
28+
2729
## Design Philosophy
2830

2931
The design philosophy of the template is to prefer low-level, best-in-class open-source frameworks that offer flexibility, scalability, and performance without vendor-lock-in. You'll find the template amazingly easy not only to understand and customize, but also to deploy to any major cloud hosting platform.

user_guide/04-customization.qmd

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,20 @@ Your custom Python backend code should go primarily in the `routers/app/` and `u
3232

3333
For the frontend, you will also need to develop custom Jinja2 templates in the `templates/` folder and add custom static assets in `static/`.
3434

35+
### Billing (optional)
36+
37+
Organization-scoped Stripe billing is maintained on the [`stripe`](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/stripe) branch. See `user_guide/07-billing.qmd` on that branch for Dashboard setup, webhooks, fork helpers (`org_has_active_subscription`), and a manual end-to-end checklist.
38+
39+
To add billing to an existing fork:
40+
41+
```bash
42+
git remote add upstream https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp.git
43+
git fetch upstream stripe
44+
git merge upstream/stripe
45+
```
46+
47+
When merging, expect conflicts in shared core files such as `main.py`, `pyproject.toml`, `utils/core/db.py`, `routers/core/organization.py`, header/organization templates, `tests/conftest.py`, and `.env.example`. Resolve by keeping billing additions from `stripe` while preserving your fork-specific changes.
48+
3549
### Testing
3650

3751
The project uses Pytest for unit testing. It's highly recommended to write and run tests before committing code to ensure nothing is broken!

user_guide/05-deployment.qmd

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ There are *many* hosting options available for each of these services; this guid
1313

1414
::: {.callout-note}
1515
Deployment artifacts (Dockerfiles, deploy scripts, compose files, etc.) are kept on separate git branches — one per deployment target — to avoid cluttering the main branch. See the `modal` branch for Modal deployment files and the `hetzner` branch for Hetzner Cloud deployment files. The documentation below describes how to use them.
16+
17+
Optional organization-scoped Stripe billing (Checkout, Customer Portal, webhooks) lives on the [`stripe`](https://github.com/Promptly-Technologies-LLC/fastapi-jinja2-postgres-webapp/tree/stripe) branch — not on `main`. Deploy billing-enabled apps from `stripe` (or after merging it into your fork); see `user_guide/07-billing.qmd` on that branch for setup.
1618
:::
1719

1820
## Deploying and Configuring the FastAPI App

user_guide/06-contributing.qmd

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,10 @@ To contribute code to the project:
4343
- Provide a clear description of the changes
4444
- Link to any related issues
4545

46+
### Optional branches
47+
48+
Core template changes on `main` propagate automatically to `modal`, `hetzner`, and `stripe` via CI. Pull requests to `main` that touch shared files (`main.py`, `pyproject.toml`, `utils/core/db.py`, `routers/core/organization.py`, templates, `tests/conftest.py`, `.env.example`) may need manual conflict resolution when those changes are merged into `stripe`. See the [customization guide](https://promptlytechnologies.com/fastapi-jinja2-postgres-webapp/user-guide/customization.html) for the `git merge upstream/stripe` recipe.
49+
4650
### Rendering the documentation
4751

4852
The documentation website is built with [Great Docs](https://posit-dev.github.io/great-docs/). If you make changes to the `.qmd` files in the `user_guide/` folder, you will need to rebuild the docs with Great Docs.

0 commit comments

Comments
 (0)