Add cookieplone update command to refresh projects against newer template versions
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 12
- Forks
- 4
- Avg merge
- 4m
- Merged PRs (30d)
- 1
Description
Summary
Add a cookieplone update command that refreshes an already-generated project against the latest version of the template it was created from, preserving the user's local changes and surfacing conflicts for manual review.
Today, once a user runs cookieplone and scaffolds a project, the generated tree is frozen in time. Any improvement that later lands in the upstream template — bugfixes, new CI steps, dependency bumps, new boilerplate files, tightened security defaults — is invisible to existing projects unless the user manually diffs upstream and copies edits over. That is both tedious and error-prone, and in practice means real projects drift further and further away from the templates that spawned them.
A first-class update command would let template authors ship improvements knowing downstream consumers can actually adopt them, and let downstream users benefit from ecosystem-wide fixes with a single command.
User experience
From within a previously generated codebase:
cookieplone update
Cookieplone should:
- Discover which template the project was generated from (via the
__template__key persisted in.cookieplone.json, see #168). - Re-resolve the upstream repository at the current default branch or tag.
- Replay the original answers from the answers file against the latest template.
- Compute a three-way diff between:
- the old rendered template (the snapshot the project was born from),
- the new rendered template (what the current upstream would produce with the same answers),
- the current project on disk (including the user's local edits).
- Apply the new-vs-old diff to the working tree, leaving conflict markers where a hunk overlaps user changes — the same mental model as
git merge. - Report a summary: files added, files removed, files updated cleanly, files with conflicts.
Additional flags to consider:
--answers <path>— override the answers file location (default: the.cookieplone_answers_*.jsonin the project root).--tag <ref>— update against a specific tag/branch/commit of the template repository instead of the default.--dry-run— print the diff without writing anything.--skip <glob>— never touch matching paths (useful for generated lockfiles,.env, etc.).--interactive— prompt per-file before applying changes.
Prior art
This is the same problem that cruft solves on top of plain Cookiecutter. The cruft model (store a reference to the template + the exact commit/version + the answers, and use a three-way merge on update) works well in practice and is worth studying as a reference implementation.
Cookieplone has two advantages over a generic cruft integration:
- It already persists a structured answers file with
__template__(after #168), so we do not need a separate.cruft.jsonsidecar. - It already knows how to resolve Cookieplone repositories, sub-templates, and the v2 schema, so the update command can reuse the same machinery instead of shelling out to cruft.
Proposed scope
In scope (first cut)
- A new
cookieplone updatesubcommand. - Discovery of the source template from the answers file written by the original run.
- Re-rendering with the original answers against the latest template.
- Three-way merge of the old render, the new render, and the working tree.
- Conflict marker output (git-style) for hunks the merge cannot apply cleanly.
- Summary report at the end of the run.
- Support for the
--tag,--dry-run, and--skipflags described above.
Out of scope (track separately)
- Re-prompting the user for new schema fields that did not exist in the original run. (Start by assuming every new field uses the schema's default; add an interactive prompt pass later.)
- Automated answer migration (for example, renaming a question between template versions).
- Updating sub-templates separately from the parent project.
- Cross-template updates (switching from one template to another).
- A
cookieplone statuscommand that reports how far a project has drifted from its template without applying any changes. (Nice as a follow-up.)
Open questions
- Answers file naming. Today the answers file lives as
.cookieplone_answers_<folder_name>.json. Shouldcookieplone updateassume exactly one such file at the project root, or should it accept a path explicitly? - Template pinning. Should the answers file also record the exact template commit/tag at generation time, so
updateknows the "old" side of the three-way merge without having to guess? This would be a small addition towrite_answers()and makes the three-way merge reliable. - Binary and generated files. How should the merge handle binary files, lock files, and files flagged in
_copy_without_render? - Integration with
extends(#175). Once the repository extension mechanism lands,updatehas to handle the case where a project was generated from a downstream repo that inherits from an upstream — updates should walk both layers.
Acceptance criteria
-
cookieplone updateworks end-to-end against a project generated with the current version of Cookieplone. - A three-way merge produces conflict markers for hunks that overlap user edits.
-
--dry-runshows the planned changes without writing anything. -
--taglets the caller update to a specific template ref. -
--skiphonours user-provided globs. - The command reports a structured summary (added / removed / updated / conflicted files).
- Integration tests cover: clean update, update with user edits, update with conflicts, update after a new schema field was added upstream, and update with
--tagpinning. - Documentation:
- New how-to guide: "Update a project against a newer template version".
- Reference entry for the new subcommand in
docs/src/reference/cli.md. - Concept page explaining the three-way merge model and conflict handling.
- News fragment under
news/(type:feature).
Notes
- Milestone: 3.0.0 — this is a substantial feature. File it now so the design conversation can start early and #168 / #175 can inform the final shape.
- Depends on (or interacts with) #175 once the repository extension mechanism lands.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the existing Cookieplone command entry points and write_answers(), along with the design context in #168 and #175. Use the current project-generation flow as the baseline for implementing update, then add integration coverage for clean changes, local edits, conflicts, new schema fields, and --tag pinning. Done means the acceptance criteria pass, including --dry-run, --skip, the structured summary, documentation, and the news fragment.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- cli, tooling
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100