Skip to content

Commit e9b23c4

Browse files
docs: expand TROUBLESHOOTING.md to CNA depth
Closes #169.
1 parent c71f260 commit e9b23c4

1 file changed

Lines changed: 365 additions & 3 deletions

File tree

docs/TROUBLESHOOTING.md

Lines changed: 365 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,367 @@
11
# Troubleshooting
22

3-
- `uv sync` fails: check `.python-version` and network
4-
- Non-empty target dir: pass `--force`
5-
- Offline scaffold: ensure cache warmed or use `file://` fixtures
3+
Common issues when scaffolding projects with `create-awesome-python-app`.
4+
5+
## Python version mismatch
6+
7+
**Symptoms:** The CLI exits immediately with a Python version error.
8+
9+
**Requirement:** Python **>= 3.12**
10+
11+
```bash
12+
python --version
13+
```
14+
15+
**Switch versions:**
16+
17+
- [uv](https://docs.astral.sh/uv/): `uv python install 3.12 && uv python pin 3.12`
18+
- [pyenv](https://github.com/pyenv/pyenv): `pyenv install 3.12 && pyenv local 3.12`
19+
- [mise](https://mise.jdx.dev/): `mise use python@3.12`
20+
21+
The workspace pin file is `.python-version` (currently `3.12`). Generated projects
22+
inherit `requires-python` from their template.
23+
24+
## Non-empty target directory
25+
26+
**Symptoms:** Scaffolding aborts with `CPA_NON_EMPTY_TARGET_DIR` or
27+
`Target directory is not empty: <path>`.
28+
29+
**Cause:** CPA refuses to scaffold into a directory that already contains files,
30+
to avoid overwriting user data.
31+
32+
**Fix:**
33+
34+
```bash
35+
# Scaffold into a new directory (default: my-project)
36+
uvx create-awesome-python-app my-new-app -t fastapi-starter --no-interactive
37+
38+
# Or allow scaffolding into a non-empty directory
39+
uvx create-awesome-python-app existing-dir -t fastapi-starter --force --no-interactive
40+
```
41+
42+
Use `--force` / `-f` only when you intend to merge into an existing tree.
43+
44+
## Catalog and slug errors
45+
46+
**Symptoms:** `Invalid catalog slug: '<slug>'. Run --list-templates / --list-addons or pass a full URL.`
47+
48+
**Cause:** The `-t`, `--addons`, or `--extend` value does not match any entry in
49+
`templates.json` from [cpa-templates](https://github.com/Create-Python-App/cpa-templates).
50+
51+
**Fix:**
52+
53+
```bash
54+
# List official templates
55+
uvx create-awesome-python-app --list-templates
56+
57+
# List extensions (optionally filtered by template)
58+
uvx create-awesome-python-app --list-addons -t fastapi-starter
59+
60+
# Use the exact slug from the catalog
61+
uvx create-awesome-python-app my-app -t fastapi-starter --no-interactive
62+
```
63+
64+
**Tips:**
65+
66+
- Slugs are case-sensitive (`fastapi-starter`, not `FastAPI-Starter`).
67+
- Pass a full URL when using a fork or local template instead of a catalog slug.
68+
- Override the catalog source for forks or offline testing:
69+
70+
```bash
71+
CPA_CATALOG_URL="file:///path/to/cpa-templates/templates.json" \
72+
uvx create-awesome-python-app my-app -t fastapi-starter --no-interactive
73+
```
74+
75+
If the catalog fetch fails but a disk cache exists, CPA falls back to the cached
76+
copy and prints a yellow warning. With no cache and no fixture, scaffolding fails
77+
with `Failed to load template catalog`.
78+
79+
## Template URL not found
80+
81+
**Symptoms:** Scaffolding fails with HTTP 404, `repository not found`, or
82+
`file source not found` (`CPA_FILE`).
83+
84+
**Tips:**
85+
86+
- Registry templates use slugs: `uvx create-awesome-python-app my-app -t fastapi-starter`
87+
- Custom URLs must be valid GitHub HTTPS URLs, `git@` SSH targets, or `file://` paths
88+
- Pin a branch, tag, or commit with `?ref=`:
89+
90+
```bash
91+
uvx create-awesome-python-app my-app \
92+
-t "https://github.com/Create-Python-App/cpa-templates?subdir=templates/fastapi-starter&ref=main"
93+
```
94+
95+
- Test a local template checkout:
96+
97+
```bash
98+
uvx create-awesome-python-app my-app \
99+
-t "file:///path/to/cpa-templates?subdir=templates/fastapi-starter"
100+
```
101+
102+
- List official templates: `uvx create-awesome-python-app --list-templates`
103+
104+
For reproducible CI builds, pin a full 40-character commit SHA and set
105+
`CPA_STRICT_REPRO=1` so non-SHA `ref` values are rejected.
106+
107+
## Cache location and inspection
108+
109+
By default, CPA caches the template catalog and git repos under `~/.cache/cpa`.
110+
The CLI exposes this via:
111+
112+
```bash
113+
uvx create-awesome-python-app cache dir # print the cache root
114+
uvx create-awesome-python-app cache list # entries: id, url, ref, last fetched, sha, size
115+
uvx create-awesome-python-app cache verify # run git fsck on every entry
116+
uvx create-awesome-python-app cache verify <id> # verify one entry
117+
uvx create-awesome-python-app cache clean # remove all repo entries
118+
uvx create-awesome-python-app cache clean <id> # remove one entry by id
119+
uvx create-awesome-python-app cache clean --catalog # also clear catalog/templates.json cache
120+
uvx create-awesome-python-app cache outdated # compare local SHAs to remote tips
121+
uvx create-awesome-python-app cache update # refresh all cached repos
122+
uvx create-awesome-python-app cache update <id> # refresh one entry
123+
uvx create-awesome-python-app cache doctor # check git, network, cache dir, integrity
124+
```
125+
126+
Layout:
127+
128+
```text
129+
~/.cache/cpa/
130+
catalog/
131+
templates.json
132+
repos/
133+
<cache-key>/
134+
.cpa-cache.json
135+
...
136+
```
137+
138+
If a scaffold "looks weird" and you suspect a stale cache, the first diagnostic
139+
step is `cache verify`. If any entry fails, `cache clean` and re-run. Use
140+
`cache outdated` + `cache update` when you need newer template content without
141+
a full re-download.
142+
143+
## Forcing a fresh fetch
144+
145+
```bash
146+
# Force a re-fetch of templates.json and template repos on every run.
147+
uvx create-awesome-python-app my-app -t fastapi-starter --no-cache --no-interactive
148+
149+
# Disable git pull on cache hit (use the local copy as-is).
150+
uvx create-awesome-python-app my-app -t fastapi-starter --offline --no-interactive
151+
152+
# Control refresh policy explicitly (default: stale).
153+
uvx create-awesome-python-app my-app -t fastapi-starter --refresh always --no-interactive
154+
uvx create-awesome-python-app my-app -t fastapi-starter --refresh manual --no-interactive
155+
156+
# Pin the cache to a project-local directory (useful in CI).
157+
CPA_CACHE_DIR="$PWD/.cpa-cache" uvx create-awesome-python-app my-app -t fastapi-starter --no-interactive
158+
159+
# Or use the CLI flag (sets CPA_CACHE_DIR internally)
160+
uvx create-awesome-python-app my-app -t fastapi-starter --cache-dir "$PWD/.cpa-cache" --no-interactive
161+
```
162+
163+
### CPA_* environment variables
164+
165+
| Variable | Purpose |
166+
|----------|---------|
167+
| `CPA_CACHE_DIR` | Override cache root (default `~/.cache/cpa`) |
168+
| `CPA_CATALOG_URL` | Override catalog URL (default raw GitHub `templates.json`) |
169+
| `CPA_NO_CATALOG_CACHE` | Set by `--no-cache`; skip in-memory/disk catalog cache |
170+
| `CPA_REFRESH` | Refresh mode: `always`, `stale` (default), or `manual` |
171+
| `CPA_REFRESH_AFTER_HOURS` | Hours before a stale entry is refreshed (default `24`) |
172+
| `CPA_STRICT_REPRO` | Require full 40-char SHA in `?ref=` for reproducibility |
173+
| `CPA_STRICT_VERSION` | Fail when CLI is older than latest PyPI release |
174+
| `CPA_SKIP_GIT` | Skip `git init` in generated project (testing) |
175+
| `CPA_CATALOG_FIXTURE` | Load bundled catalog fixture (testing) |
176+
| `CPA_TEMPLATES_ROOT` | Local `cpa-templates` checkout for integration tests |
177+
178+
`--no-cache` sets `CPA_NO_CATALOG_CACHE=1` and forces `--refresh always` for
179+
template repos. `--offline` uses cached repos only; a cache miss raises
180+
`CPA_OFFLINE`.
181+
182+
See also: [MIGRATION.md](./MIGRATION.md) for keeping scaffolded projects up to date.
183+
184+
## uv sync failures
185+
186+
**Symptoms:** Scaffolding copies files but fails during `uv sync` in the generated
187+
project, or exits with `CPA_ABORTED`.
188+
189+
**Cause:** The template includes a `pyproject.toml` and CPA runs `uv sync` by
190+
default to install dependencies.
191+
192+
**Fix:**
193+
194+
1. Confirm `uv` is installed and on `PATH`:
195+
196+
```bash
197+
uv --version
198+
create-awesome-python-app --info
199+
```
200+
201+
1. Check the generated project's `.python-version` and `requires-python` in
202+
`pyproject.toml` match your interpreter.
203+
204+
1. Retry manually inside the project:
205+
206+
```bash
207+
cd my-app
208+
uv sync
209+
```
210+
211+
1. If you only need the file tree (no install), skip sync during scaffold:
212+
213+
```bash
214+
uvx create-awesome-python-app my-app -t fastapi-starter --no-install --no-interactive
215+
```
216+
217+
1. For network or index issues, retry with verbose logging or behind a proxy;
218+
CPA does not wrap `uv` output -- read the `uv sync` error directly.
219+
220+
## Git clone failures
221+
222+
**Symptoms:** `git clone failed` (`CPA_GIT`), `git executable not found`, or
223+
`offline mode: cache miss` (`CPA_OFFLINE`).
224+
225+
**Cause:** CPA clones template and extension repos from GitHub (or custom URLs)
226+
into the local cache before copying layers.
227+
228+
**Fix:**
229+
230+
1. Confirm git is available:
231+
232+
```bash
233+
git --version
234+
create-awesome-python-app --info
235+
```
236+
237+
1. Warm the cache while online, then scaffold offline:
238+
239+
```bash
240+
uvx create-awesome-python-app my-app -t fastapi-starter --no-interactive
241+
uvx create-awesome-python-app my-app2 -t fastapi-starter --offline --no-interactive
242+
```
243+
244+
1. For private repos, ensure SSH keys or credentials work outside CPA:
245+
246+
```bash
247+
git ls-remote git@github.com:your-org/your-template.git
248+
```
249+
250+
1. Clear a corrupted cache entry and retry:
251+
252+
```bash
253+
uvx create-awesome-python-app cache verify
254+
uvx create-awesome-python-app cache clean
255+
uvx create-awesome-python-app my-app -t fastapi-starter --no-interactive
256+
```
257+
258+
1. Use `file://` URLs to scaffold from a local checkout without network access.
259+
260+
## incompatibleWith errors
261+
262+
**Symptoms:** `Incompatible extension combination from cpa.config.json: 'foo' <-> 'bar'. Remove one of each conflicting pair and retry.`
263+
264+
**Cause:** Two or more selected extensions declare each other in `incompatibleWith`
265+
(either in `cpa.config.json` or in catalog metadata). CPA validates addon/extend
266+
layers before merging.
267+
268+
**Fix:**
269+
270+
1. List extensions and read their descriptions:
271+
272+
```bash
273+
uvx create-awesome-python-app --list-addons -t fastapi-starter
274+
```
275+
276+
1. Remove one extension from each conflicting pair in `--addons` / `--extend`.
277+
278+
1. When authoring extensions, set `incompatibleWith` in `cpa.config.json`:
279+
280+
```json
281+
{
282+
"name": "postgres",
283+
"incompatibleWith": ["sqlite"]
284+
}
285+
```
286+
287+
Matches use each layer's `name` field (slug-like id), not the catalog display name.
288+
289+
## `--set` values with spaces
290+
291+
When passing custom options that contain spaces, quote the entire `key=value` pair:
292+
293+
```bash
294+
uvx create-awesome-python-app my-app -t fastapi-starter \
295+
--set 'projectName=My Awesome Project' \
296+
--no-interactive
297+
```
298+
299+
Multiple `--set` flags merge into the Jinja context alongside `cpa.config.json`
300+
defaults.
301+
302+
## CI reproduction tips
303+
304+
Reproduce scaffold failures locally the way CI does:
305+
306+
```bash
307+
# Match the test workflow environment
308+
git clone https://github.com/Create-Python-App/create-python-app.git
309+
cd create-python-app
310+
git clone https://github.com/Create-Python-App/cpa-templates.git ../cpa-templates
311+
312+
uv sync --group dev
313+
export CPA_TEMPLATES_ROOT="$(cd ../cpa-templates && pwd)"
314+
export CPA_SKIP_GIT=1
315+
export CPA_CACHE_DIR="$PWD/.cpa-cache-ci"
316+
export CPA_NO_CATALOG_CACHE=1
317+
318+
uv run create-awesome-python-app test-app \
319+
-t fastapi-starter \
320+
--no-interactive \
321+
--cache-dir "$CPA_CACHE_DIR"
322+
```
323+
324+
**Checklist:**
325+
326+
- Use `--no-interactive` in CI (interactive prompts are skipped when `CI=true`).
327+
- Pin `CPA_CACHE_DIR` to a workspace path for cache reuse across steps.
328+
- Set `CPA_CATALOG_URL` to a `file://` catalog when testing forks offline.
329+
- Run `create-awesome-python-app --info` in bug reports (Python, uv, git versions).
330+
- Run `create-awesome-python-app cache doctor` before blaming template content.
331+
- Use `CPA_STRICT_REPRO=1` and a full commit SHA in `?ref=` for deterministic builds.
332+
333+
## Distribution channels
334+
335+
Install the CLI from PyPI or run it ephemerally with uv:
336+
337+
```bash
338+
# Ephemeral (recommended for end users)
339+
uvx create-awesome-python-app@latest my-app
340+
341+
# Pin a release
342+
uvx create-awesome-python-app@0.1.0 my-app --template fastapi-starter --no-interactive
343+
344+
# Install into the active environment
345+
uv tool install create-awesome-python-app
346+
create-awesome-python-app my-app -t fastapi-starter --no-interactive
347+
```
348+
349+
Other channels (same package, different installers):
350+
351+
| Channel | Install |
352+
|---------|---------|
353+
| **PyPI** | `uv tool install create-awesome-python-app` or `uvx create-awesome-python-app` |
354+
| **Homebrew** | `brew tap Create-Python-App/tap && brew install create-awesome-python-app` |
355+
| **AUR** | `yay -S create-awesome-python-app` |
356+
| **Docker** | `docker run --rm -v "${PWD}:/app" -w /app ulisesjeremias/create-awesome-python-app my-app` |
357+
358+
Verify the installed version:
359+
360+
```bash
361+
create-awesome-python-app --version
362+
uvx create-awesome-python-app@latest --version
363+
```
364+
365+
If behavior differs between `uvx` and a global install, compare versions and
366+
clear the uv tool cache. See [DISTRIBUTION_SETUP.md](./DISTRIBUTION_SETUP.md) for
367+
maintainer release workflow.

0 commit comments

Comments
 (0)