Skip to content

Commit e6e098d

Browse files
docs: expand MIGRATION.md to CNA depth
Closes #170 Co-authored-by: Cursor <cursoragent@cursor.com>
1 parent cf0d014 commit e6e098d

1 file changed

Lines changed: 193 additions & 5 deletions

File tree

docs/MIGRATION.md

Lines changed: 193 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,195 @@
1-
# Migration
1+
# Migration Guide
22

3-
From hand-rolled Cookiecutter/Copier flows:
3+
How to keep a scaffolded project aligned with improvements in
4+
`create-awesome-python-app` and
5+
[cpa-templates](https://github.com/Create-Python-App/cpa-templates).
46

5-
1. Map template repo to `templates.json` entry
6-
2. Add `cpa.config.json`
7-
3. Prefer `uv` lockfiles in generated projects
7+
## Why migration is hard
8+
9+
`create-awesome-python-app` generates a **one-time snapshot** of a template plus
10+
extensions. After scaffolding, the CLI does not maintain a live link to your
11+
project. You own every file and dependency choice going forward.
12+
13+
That is by design -- generated projects should be independent -- but it means
14+
updates require deliberate effort.
15+
16+
## Strategy 1: Manual dependency updates
17+
18+
1. Run `uv lock --upgrade` (or `uv lock --upgrade-package <name>`) in your
19+
project to refresh pinned versions in `uv.lock`.
20+
2. Enable Dependabot if you used the `github-setup` extension (see its workflow
21+
in cpa-templates).
22+
3. Compare your `pyproject.toml` scripts, dependency groups, and dev tools
23+
with the current template in
24+
[cpa-templates](https://github.com/Create-Python-App/cpa-templates/tree/main/templates).
25+
26+
Use `uv tree --outdated` when available to spot stale direct dependencies.
27+
28+
## Strategy 2: Diff against a fresh scaffold
29+
30+
Scaffold a new project with the same template and extensions, then diff:
31+
32+
```bash
33+
uvx create-awesome-python-app@latest my-project-new \
34+
-t <template-slug> \
35+
--addons <extension-slugs> \
36+
--no-install \
37+
--no-interactive
38+
39+
diff -r my-project/ my-project-new/ \
40+
--exclude=.venv \
41+
--exclude=__pycache__ \
42+
--exclude=.git \
43+
--exclude=.pytest_cache \
44+
--exclude=.ruff_cache \
45+
--exclude=dist \
46+
--exclude=build
47+
```
48+
49+
Review differences in config files (`pyproject.toml`, `ruff.toml`, CI
50+
workflows, `.python-version`) and port changes selectively.
51+
52+
## Strategy 3: Selective re-scaffolding
53+
54+
For a single extension update:
55+
56+
1. Scaffold a throwaway project with only that extension applied.
57+
2. Copy the extension-specific files into your existing project (e.g. Alembic
58+
migrations, auth middleware, GitHub Actions workflows).
59+
3. Merge `pyproject.toml` dependency changes manually.
60+
61+
## CNA to CPA renames
62+
63+
If you are porting workflows, docs, or CI from
64+
[create-node-app](https://github.com/Create-Node-App/create-node-app), use the
65+
CPA equivalents:
66+
67+
| CNA | CPA |
68+
|-----|-----|
69+
| `cna.config.json` | `cpa.config.json` |
70+
| `package.json` manifest | `pyproject.toml` |
71+
| `CNA_CACHE_DIR` | `CPA_CACHE_DIR` |
72+
| `CNA_REFRESH` | `CPA_REFRESH` |
73+
| `CNA_REFRESH_AFTER_HOURS` | `CPA_REFRESH_AFTER_HOURS` |
74+
| `CNA_NO_CATALOG_CACHE` | `CPA_NO_CATALOG_CACHE` |
75+
| `CNA_CATALOG_URL` | `CPA_CATALOG_URL` |
76+
| `CNA_STRICT_VERSION` | `CPA_STRICT_VERSION` |
77+
| `CNA_STRICT_REPRO` | `CPA_STRICT_REPRO` |
78+
| `CNA_SKIP_GIT` | `CPA_SKIP_GIT` |
79+
| `CNA_USER_AGENT` | `CPA_USER_AGENT` |
80+
| `~/.cache/cna` (default cache) | `~/.cache/cpa` (default cache) |
81+
82+
CLI flags are the same shape (`--template` / `-t`, `--addons`, `--cache-dir`,
83+
`--refresh`, `--pin`, `--offline`, `--no-install`). See
84+
[cpa-vs-cna-config.md](./cpa-vs-cna-config.md) for manifest and tooling
85+
differences (npm vs `uv`, ESLint vs Ruff).
86+
87+
## Template URL format and slug resolution
88+
89+
The catalog lives in
90+
[cpa-templates `templates.json`](https://github.com/Create-Python-App/cpa-templates/blob/main/templates.json).
91+
Each entry has a `slug` and a `url`.
92+
93+
**Slug resolution.** Pass a slug instead of a full URL and the CLI resolves it
94+
from the catalog:
95+
96+
```bash
97+
create-awesome-python-app my-app -t fastapi-starter --addons github-setup
98+
```
99+
100+
Run `--list-templates` or `--list-addons` to see available slugs. Invalid
101+
slugs fail with a hint to pass a full URL.
102+
103+
**GitHub URLs with `?subdir=`.** Remote templates use the monorepo layout:
104+
105+
```text
106+
https://github.com/Create-Python-App/cpa-templates?subdir=templates/fastapi-starter
107+
https://github.com/Create-Python-App/cpa-templates?subdir=extensions/github-setup
108+
```
109+
110+
**Local `file://` URLs.** For forks, air-gapped work, or integration tests:
111+
112+
```bash
113+
create-awesome-python-app my-app \
114+
-t "file:///path/to/cpa-templates?subdir=templates/fastapi-starter" \
115+
--no-install
116+
```
117+
118+
**Pinning a revision.** Append `?ref=<sha-or-tag>` to the URL, or use
119+
`--pin <ref>` (equivalent to adding `ref=` to the template URL). With
120+
`CPA_STRICT_REPRO=1`, `ref` must be a full 40-character commit SHA.
121+
122+
**Catalog override.** Point at a fork or fixture:
123+
124+
```bash
125+
export CPA_CATALOG_URL="file:///path/to/templates.json"
126+
export CPA_NO_CATALOG_CACHE=1 # skip on-disk catalog cache
127+
```
128+
129+
See [templates-json-schema.md](./templates-json-schema.md) for the full catalog
130+
shape.
131+
132+
## CLI version changelog
133+
134+
Track releases for template and extension changes:
135+
136+
- [create-python-app releases](https://github.com/Create-Python-App/create-python-app/releases)
137+
- [cpa-templates releases](https://github.com/Create-Python-App/cpa-templates/releases)
138+
139+
When upgrading the CLI:
140+
141+
```bash
142+
# ephemeral (recommended)
143+
uvx create-awesome-python-app@latest --help
144+
145+
# Homebrew / AUR / pipx installs
146+
brew upgrade create-awesome-python-app
147+
pipx upgrade create-awesome-python-app
148+
```
149+
150+
Use `--strict-version` (or `CPA_STRICT_VERSION=1`) in CI to fail when the
151+
installed CLI is not the latest PyPI release.
152+
153+
Manage the template cache:
154+
155+
```bash
156+
create-awesome-python-app cache dir
157+
create-awesome-python-app cache list
158+
create-awesome-python-app cache update [id]
159+
create-awesome-python-app cache clean
160+
```
161+
162+
## Adding extensions to an existing project
163+
164+
There is no `cpa add-extension` command yet. To add an extension after the fact:
165+
166+
1. Browse the extension in
167+
[cpa-templates/extensions](https://github.com/Create-Python-App/cpa-templates/tree/main/extensions).
168+
2. Read the extension README for required files and dependencies.
169+
3. Scaffold a minimal project with that extension and copy the relevant files.
170+
4. Install matching dependencies from the extension's `pyproject.toml` (or run
171+
`uv sync` in the throwaway project and mirror the dependency blocks).
172+
173+
Use `--list-addons -t <template-slug>` to see extensions compatible with your
174+
base template.
175+
176+
## Migrating from Cookiecutter or Copier
177+
178+
If you are moving a hand-rolled Cookiecutter/Copier flow into the CPA
179+
ecosystem:
180+
181+
1. Map your template repo to a `templates.json` entry (slug, name, category,
182+
`url` with `?subdir=`).
183+
2. Add `cpa.config.json` at the template root (see
184+
[cpa-config-schema.md](./cpa-config-schema.md)).
185+
3. Prefer `uv` lockfiles (`uv.lock`) in generated projects instead of
186+
unpinned `requirements.txt` unless the template explicitly targets pip-only
187+
workflows.
188+
4. Convert Jinja-style prompts to `customOptions` in `cpa.config.json` where
189+
possible; use `--set key=value` for non-interactive runs.
190+
191+
## Getting help
192+
193+
- [Troubleshooting](./TROUBLESHOOTING.md)
194+
- [GitHub Issues](https://github.com/Create-Python-App/create-python-app/issues)
195+
- [Discussions](https://github.com/Create-Python-App/create-python-app/discussions)

0 commit comments

Comments
 (0)