From 50e6b4f03aab516950f9cac59ebbee9e2bb4cdeb Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 21 Apr 2026 14:58:56 -0600 Subject: [PATCH 1/4] Claude init --- CLAUDE.md | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..62416da --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,63 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Commands + +```sh +make deps # Install dev dependencies (uv sync --dev --frozen) +make check # Full check: fmt + lint + test + test-e2e +make check-static # fmt + lint only +make fmt # Run ruff formatter +make lint # Run mypy + ruff + uv lock check +make lint-mypy # Type check only (args= supported) +make test # Run unit tests (args= supported) +make test-e2e # Run e2e tests (requires tool installed) +make docs-watch # Local docs server +``` + +Run a single test: +```sh +uv run --frozen pytest tests/path/to/test_file.py::test_name +``` + +Run CLI during development: +```sh +uv run nava-platform +``` + +## Architecture + +Entry point: `nava/platform/cli/__main__.py` → `cli/main.py` builds a `typer.Typer` with two sub-apps: `infra` and `app`. + +**Layer structure:** + +- `nava/platform/cli/` — CLI layer (typer commands, context, console, logging, config) + - `commands/infra/` — `install`, `update`, `add-app`, `info`, `migrate-from-legacy` subcommands + - `commands/app.py` — app-level subcommands +- `nava/platform/templates/` — core template logic + - `template.py` — `Template` class wraps copier; handles copy/update against a project + - `infra_template.py` — infra-specific template operations + - `state.py` — reads/writes `.nava` answer files that track installed template versions + - `template_name.py` — parses template name from URI +- `nava/platform/projects/` — project/app abstractions (`Project`, `InfraProject`) +- `nava/platform/copier_worker.py` — `NavaWorker` extends copier's `Worker` to support `src_exclude` filtering _before_ template rendering (upstream only filters after) +- `nava/platform/util/` — git helpers, wrappers, collections + +**Key data flow:** CLI command → `CliContext` (log, console, output level) → `Template`/`InfraTemplate` → `NavaWorker` (wraps copier) → writes files to project dir + updates `.nava` state files. + +**State tracking:** Installed template versions are stored in `.nava/` answer files within target projects, not in this repo. + +**Copier pin:** `copier` is pinned to a specific git commit in `pyproject.toml` because a later commit breaks `NavaWorker`'s `src_exclude` setup. + +## Testing + +- Unit tests: `tests/` — mirrors `nava/` package structure +- E2e tests: `tests-e2e/` — shell scripts requiring the tool to be installed; `bin/test-e2e` orchestrates them +- `conftest.py` at `tests/` root contains shared fixtures + +## Linting + +- `ruff` for formatting and linting (line length 100, Google docstring convention) +- `mypy` in strict mode with `local_partial_types = true`; tests exempt from typed def requirements +- In CI, `make fmt` runs with `--check` and `make lint` runs without `--fix` From 1bdbfa91b18d5b1231949ae8150f9bd8c7285a01 Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 21 Apr 2026 14:59:20 -0600 Subject: [PATCH 2/4] Use claude to self update docs --- docs/avoiding-conflicts-on-update.md | 29 +++++++++++++++++-- .../migrating-from-legacy-template.md | 28 ++++++++++++++++++ docs/getting-started/new-project.md | 17 +++++++++++ 3 files changed, 72 insertions(+), 2 deletions(-) diff --git a/docs/avoiding-conflicts-on-update.md b/docs/avoiding-conflicts-on-update.md index c90db4e..ae13fd9 100644 --- a/docs/avoiding-conflicts-on-update.md +++ b/docs/avoiding-conflicts-on-update.md @@ -39,5 +39,30 @@ version of "notifications" for ``, consider calling the module ### Application templates -No good advice at the moment. It can be hard to avoid conflicts given the nature -of applications. But at least keep in mind which files are tracked upstream. +Application templates tend to touch files that projects also customize heavily +(e.g. `README.md`, CI workflow files, root-level config files), so conflicts are +more likely here than in infra templates. A few practical strategies: + +**Know which files are template-owned.** Run `git log --follow ` on files +you intend to customize to see whether they were originally written by the +template. If so, expect that upstream may update them and plan accordingly. + +**Use thin wrapper files where possible.** If an application template ships a +CI workflow you need to tweak, prefer adding a separate workflow file that +extends or supplements it rather than editing the template-owned file directly. +The same applies to configuration files that support an "include" or "extend" +mechanism (e.g. ESLint, TypeScript, Prettier configs). + +**Isolate project-specific content.** Files like `README.md` and +`.github/pull_request_template.md` are natural conflict points. Consider keeping +project-specific content in a separate included file (e.g. +`docs/project-overview.md`) and keeping the template-owned file minimal. + +**Commit project customizations separately from template updates.** When you +first apply a template, make one commit for the raw template output and a +follow-up commit for your project-specific edits. This makes future 3-way merges +cleaner because the "yours" side is clearly separated. + +**Update frequently.** Smaller, more frequent updates mean each merge has less +divergence to reconcile. Letting many template versions accumulate makes +conflicts significantly harder to untangle. diff --git a/docs/getting-started/migrating-from-legacy-template.md b/docs/getting-started/migrating-from-legacy-template.md index 5e37498..2f4f31d 100644 --- a/docs/getting-started/migrating-from-legacy-template.md +++ b/docs/getting-started/migrating-from-legacy-template.md @@ -128,6 +128,34 @@ to `app` - [v0.6.0](https://github.com/navapbc/template-infra/releases/tag/v0.6.0) - Networking changes likely requiring hours of downtime to apply +### Validating the migration + +Before moving on, confirm that the migration landed cleanly: + +1. **Check the `.template-infra/` directory.** It should contain a `base.yml` + and one `app-.yml` per application. Open each file and verify the + `_commit` value matches the version you intended to migrate to and that the + answer variables look correct for your project. + +2. **Run `infra info` to confirm the CLI can read the state:** + ```sh + nava-platform infra info . + ``` + This should print the current version and any available upgrades without + errors. An error here usually means a YAML file in `.template-infra/` is + malformed or missing. + +3. **Check the git log.** The migration and update commits should be present and + the working tree should be clean (`git status` shows nothing uncommitted). + +4. **Review the diff of the update commit.** Run `git show HEAD` (or the + relevant commit hash) and skim the changed files. Pay particular attention to + Terraform state-affecting resources — changes there may require a `terraform + plan` to validate before applying. + +If anything looks wrong, you can re-run the migration command or reach out to +the Platform team before proceeding. + ### Post-migration After completing the migration, you may want to see what results from diff --git a/docs/getting-started/new-project.md b/docs/getting-started/new-project.md index d48ac20..54d6bb0 100644 --- a/docs/getting-started/new-project.md +++ b/docs/getting-started/new-project.md @@ -8,10 +8,27 @@ ```sh nava-platform infra install --commit . ``` + This installs the base infrastructure template and an app-specific infra + layer for ``. Copier will prompt you for project configuration + values (project name, AWS region, etc.). When it finishes, you will have a + populated `infra/` directory and a `.template-infra/` directory tracking + the installed version. The `--commit` flag automatically creates a git + commit with the generated files. 1. Then utilize one of the application templates for `` with: ```sh nava-platform app install --commit --template-uri . ``` + Available application template URIs: + - Flask API: `https://github.com/navapbc/template-application-flask` + - Next.js: `https://github.com/navapbc/template-application-nextjs` + - Rails: `https://github.com/navapbc/template-application-rails` + + For example, to install the Flask template: + ```sh + nava-platform app install --commit \ + --template-uri https://github.com/navapbc/template-application-flask \ + . myapp + ``` 1. Follow the steps in the `First time initialization` section of the generated `/infra/README.md` file for creating the initial resources/dev environment. 1. Once you have a dev environment created, enable a host of other features by running: From 48f92db296eee23cd80cf4b91a17742a3a112045 Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 21 Apr 2026 15:09:53 -0600 Subject: [PATCH 3/4] Add new document on working with existing template --- README.md | 1 + docs/getting-started/.pages | 1 + docs/getting-started/index.md | 4 +- .../working-with-existing-template.md | 131 ++++++++++++++++++ 4 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 docs/getting-started/working-with-existing-template.md diff --git a/README.md b/README.md index ce4d7cd..2faf531 100644 --- a/README.md +++ b/README.md @@ -218,6 +218,7 @@ nava-platform infra install ./just-a-test For comprehensive guides on using the platform CLI with existing projects: - [Getting Started Guide](./docs/getting-started/index.md) - [New Project Setup](./docs/getting-started/new-project.md) +- [Working with an Existing Template](./docs/getting-started/working-with-existing-template.md) - [Migrating from Legacy Template](./docs/getting-started/migrating-from-legacy-template.md) ### Shell Completion diff --git a/docs/getting-started/.pages b/docs/getting-started/.pages index 2fbd1b6..0e1eeab 100644 --- a/docs/getting-started/.pages +++ b/docs/getting-started/.pages @@ -2,3 +2,4 @@ nav: - index.md - migrating-from-legacy-template.md - new-project.md + - working-with-existing-template.md diff --git a/docs/getting-started/index.md b/docs/getting-started/index.md index 7056e8f..3c9ec75 100644 --- a/docs/getting-started/index.md +++ b/docs/getting-started/index.md @@ -3,4 +3,6 @@ For projects using the legacy install/update scripts, see [Migrating old templates to Nava Platform CLI](./migrating-from-legacy-template.md). -For starting a new project, see [Starting a new project](./new-project.md) +For starting a new project, see [Starting a new project](./new-project.md). + +For developing or testing changes to an app template locally, see [Working with an existing template](./working-with-existing-template.md). diff --git a/docs/getting-started/working-with-existing-template.md b/docs/getting-started/working-with-existing-template.md new file mode 100644 index 0000000..f7ebec1 --- /dev/null +++ b/docs/getting-started/working-with-existing-template.md @@ -0,0 +1,131 @@ +# Working with an existing app template + +This guide covers how to develop and test changes to an app template (e.g., `template-application-rails`, `template-application-flask`) and apply those changes to a project using the Platform CLI. + +## How template versioning works + +The Platform CLI uses [Copier](https://copier.readthedocs.io/en/stable/) under the hood, which relies on **Git tags** for version resolution. When you run an `install` or `update` command, the CLI clones the template repository and **checks out the latest tagged version** by default — not `main` or any other branch. + +This means: + +- **Tags are the source of truth.** The CLI will not pick up commits on `main` unless those commits are included in a tagged release. +- **A new tag must be created** in the template repository for the CLI to recognize and install new changes. +- Tags should follow [PEP 440](https://peps.python.org/pep-0440/) versioning (e.g., `v0.1.0`, `v0.2.0`). Non-compliant tags are ignored during version resolution. + +> [!IMPORTANT] +> Simply merging changes to `main` in a template repository is **not sufficient** for those changes to be picked up by the CLI. A new version tag must be pushed to the repository. + +### Example: releasing a new template version + +After merging your changes to the template's `main` branch: + +```sh +# In the template repository +git tag v0.3.0 +git push origin v0.3.0 +``` + +Projects can then pick up this version: + +```sh +nava-platform app update . myapp +``` + +## Developing with a local template + +When working on template changes, you don't need to push to a remote or create tags. The CLI supports pointing directly at a **local directory** and a specific **branch or ref**, which is ideal for development and testing. + +### Setting up a local checkout + +Clone the app template repository (or use an existing clone): + +```sh +git clone https://github.com/navapbc/template-application-rails ~/templates/template-application-rails +``` + +Create a branch for your changes: + +```sh +cd ~/templates/template-application-rails +git checkout -b my-feature-branch +``` + +Make your template changes and commit them. + +> [!NOTE] +> Template changes must be committed to your local branch. Copier works from Git history, so uncommitted changes will not be applied. + +### Using a Git worktree (alternative) + +If you'd rather keep your default branch intact, you can use a [Git worktree](https://git-scm.com/docs/git-worktree) instead of a new clone: + +```sh +cd ~/templates/template-application-rails +git worktree add ../template-application-rails-feature my-feature-branch +``` + +This creates a separate working directory at `../template-application-rails-feature` checked out to `my-feature-branch`, while leaving your original clone on its current branch. + +### Installing from a local template + +Use `--template-uri` to point to your local checkout, and `--version` to specify the branch: + +```sh +nava-platform app install \ + --template-uri ~/templates/template-application-rails \ + --version my-feature-branch \ + --commit \ + . myapp +``` + +### Updating from a local template + +Similarly, to update an existing project using your local template changes: + +```sh +nava-platform app update \ + --template-uri ~/templates/template-application-rails \ + --version my-feature-branch \ + --commit \ + . myapp +``` + +> [!TIP] +> Use `--version HEAD` to always apply the latest commit on the default branch of your local checkout, regardless of tags. + +### Key CLI options for local development + +| Option | Description | +|---|---| +| `--template-uri` | Path or URL to the template source. Can be a local path (e.g., `~/templates/template-application-rails`) or a remote URL. | +| `--version` | Template version to use. Accepts a branch name, tag, commit hash, or `HEAD`. Defaults to the latest tag. | +| `--template-name` | Override the template name if your local directory has a different name than the upstream repository (e.g., if your worktree folder is named differently). | +| `--commit` | Automatically commit the generated changes with a standard message. | + +## Infra template local development + +The infra template works the same way. The default `--template-uri` for `infra` commands is `https://github.com/navapbc/template-infra`, but you can override it: + +```sh +nava-platform infra install \ + --template-uri ~/templates/template-infra \ + --version my-feature-branch \ + --commit \ + . myapp +``` + +```sh +nava-platform infra update \ + --template-uri ~/templates/template-infra \ + --version my-feature-branch \ + . +``` + +## Summary + +| Scenario | What to do | +|---|---| +| Use the latest released template version | Just run `install` or `update` — the CLI defaults to the latest tag. | +| Release a new template version for all projects | Tag a new version in the template repo and push it. | +| Test local template changes during development | Use `--template-uri` pointed at your local clone and `--version` set to your branch. | +| Always use the latest commit (skip tag resolution) | Pass `--version HEAD`. | From eb3b9e4460c2a09bf18719580a6e7448fe169efe Mon Sep 17 00:00:00 2001 From: Bao Nguyen Date: Tue, 21 Apr 2026 20:57:13 -0600 Subject: [PATCH 4/4] Revert "Use claude to self update docs" This reverts commit 1bdbfa91b18d5b1231949ae8150f9bd8c7285a01. --- docs/avoiding-conflicts-on-update.md | 29 ++----------------- .../migrating-from-legacy-template.md | 28 ------------------ docs/getting-started/new-project.md | 17 ----------- 3 files changed, 2 insertions(+), 72 deletions(-) diff --git a/docs/avoiding-conflicts-on-update.md b/docs/avoiding-conflicts-on-update.md index ae13fd9..c90db4e 100644 --- a/docs/avoiding-conflicts-on-update.md +++ b/docs/avoiding-conflicts-on-update.md @@ -39,30 +39,5 @@ version of "notifications" for ``, consider calling the module ### Application templates -Application templates tend to touch files that projects also customize heavily -(e.g. `README.md`, CI workflow files, root-level config files), so conflicts are -more likely here than in infra templates. A few practical strategies: - -**Know which files are template-owned.** Run `git log --follow ` on files -you intend to customize to see whether they were originally written by the -template. If so, expect that upstream may update them and plan accordingly. - -**Use thin wrapper files where possible.** If an application template ships a -CI workflow you need to tweak, prefer adding a separate workflow file that -extends or supplements it rather than editing the template-owned file directly. -The same applies to configuration files that support an "include" or "extend" -mechanism (e.g. ESLint, TypeScript, Prettier configs). - -**Isolate project-specific content.** Files like `README.md` and -`.github/pull_request_template.md` are natural conflict points. Consider keeping -project-specific content in a separate included file (e.g. -`docs/project-overview.md`) and keeping the template-owned file minimal. - -**Commit project customizations separately from template updates.** When you -first apply a template, make one commit for the raw template output and a -follow-up commit for your project-specific edits. This makes future 3-way merges -cleaner because the "yours" side is clearly separated. - -**Update frequently.** Smaller, more frequent updates mean each merge has less -divergence to reconcile. Letting many template versions accumulate makes -conflicts significantly harder to untangle. +No good advice at the moment. It can be hard to avoid conflicts given the nature +of applications. But at least keep in mind which files are tracked upstream. diff --git a/docs/getting-started/migrating-from-legacy-template.md b/docs/getting-started/migrating-from-legacy-template.md index 2f4f31d..5e37498 100644 --- a/docs/getting-started/migrating-from-legacy-template.md +++ b/docs/getting-started/migrating-from-legacy-template.md @@ -128,34 +128,6 @@ to `app` - [v0.6.0](https://github.com/navapbc/template-infra/releases/tag/v0.6.0) - Networking changes likely requiring hours of downtime to apply -### Validating the migration - -Before moving on, confirm that the migration landed cleanly: - -1. **Check the `.template-infra/` directory.** It should contain a `base.yml` - and one `app-.yml` per application. Open each file and verify the - `_commit` value matches the version you intended to migrate to and that the - answer variables look correct for your project. - -2. **Run `infra info` to confirm the CLI can read the state:** - ```sh - nava-platform infra info . - ``` - This should print the current version and any available upgrades without - errors. An error here usually means a YAML file in `.template-infra/` is - malformed or missing. - -3. **Check the git log.** The migration and update commits should be present and - the working tree should be clean (`git status` shows nothing uncommitted). - -4. **Review the diff of the update commit.** Run `git show HEAD` (or the - relevant commit hash) and skim the changed files. Pay particular attention to - Terraform state-affecting resources — changes there may require a `terraform - plan` to validate before applying. - -If anything looks wrong, you can re-run the migration command or reach out to -the Platform team before proceeding. - ### Post-migration After completing the migration, you may want to see what results from diff --git a/docs/getting-started/new-project.md b/docs/getting-started/new-project.md index 54d6bb0..d48ac20 100644 --- a/docs/getting-started/new-project.md +++ b/docs/getting-started/new-project.md @@ -8,27 +8,10 @@ ```sh nava-platform infra install --commit . ``` - This installs the base infrastructure template and an app-specific infra - layer for ``. Copier will prompt you for project configuration - values (project name, AWS region, etc.). When it finishes, you will have a - populated `infra/` directory and a `.template-infra/` directory tracking - the installed version. The `--commit` flag automatically creates a git - commit with the generated files. 1. Then utilize one of the application templates for `` with: ```sh nava-platform app install --commit --template-uri . ``` - Available application template URIs: - - Flask API: `https://github.com/navapbc/template-application-flask` - - Next.js: `https://github.com/navapbc/template-application-nextjs` - - Rails: `https://github.com/navapbc/template-application-rails` - - For example, to install the Flask template: - ```sh - nava-platform app install --commit \ - --template-uri https://github.com/navapbc/template-application-flask \ - . myapp - ``` 1. Follow the steps in the `First time initialization` section of the generated `/infra/README.md` file for creating the initial resources/dev environment. 1. Once you have a dev environment created, enable a host of other features by running: