You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
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_*.json in 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 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 update subcommand.
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 --skip flags 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 status command 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. Should cookieplone update assume 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 update knows the "old" side of the three-way merge without having to guess? This would be a small addition to write_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 (Implement the repository extension mechanism (extends) #175). Once the repository extension mechanism lands, update has 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 update works 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-run shows the planned changes without writing anything.
--tag lets the caller update to a specific template ref.
--skip honours 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 --tag pinning.
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.
Summary
Add a
cookieplone updatecommand 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
cookieploneand 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 updateCookieplone should:
__template__key persisted in.cookieplone.json, see write_answers() does not persist __template__ key in .cookieplone_answers JSON file #168).git merge.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:
__template__(after write_answers() does not persist __template__ key in .cookieplone_answers JSON file #168), so we do not need a separate.cruft.jsonsidecar.Proposed scope
In scope (first cut)
cookieplone updatesubcommand.--tag,--dry-run, and--skipflags described above.Out of scope (track separately)
cookieplone statuscommand that reports how far a project has drifted from its template without applying any changes. (Nice as a follow-up.)Open questions
.cookieplone_answers_<folder_name>.json. Shouldcookieplone updateassume exactly one such file at the project root, or should it accept a path explicitly?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._copy_without_render?extends(Implement the repository extension mechanism (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.--dry-runshows the planned changes without writing anything.--taglets the caller update to a specific template ref.--skiphonours user-provided globs.--tagpinning.docs/src/reference/cli.md.news/(type:feature).Notes