From c003f611767c4c9d0671dce871e0d55565dac1d6 Mon Sep 17 00:00:00 2001 From: MrTango Date: Fri, 22 May 2026 01:36:51 +0300 Subject: [PATCH 1/2] Add legacy-package migration guidance to plonecli skill Document how to adapt old mr.bob/buildout/setup.py packages so plonecli subtemplates wire in correctly: make minimal structural edits (add the [tool.plone.backend_addon.settings] block, stub configure.zcml) instead of hand-writing subtemplate output or re-running the backend_addon template. --- plonecli/skills/plonecli/SKILL.md | 5 +- plonecli/skills/plonecli/reference/add.md | 2 + plonecli/skills/plonecli/reference/migrate.md | 122 ++++++++++++++++++ 3 files changed, 127 insertions(+), 2 deletions(-) create mode 100644 plonecli/skills/plonecli/reference/migrate.md diff --git a/plonecli/skills/plonecli/SKILL.md b/plonecli/skills/plonecli/SKILL.md index ecbc187..d188473 100644 --- a/plonecli/skills/plonecli/SKILL.md +++ b/plonecli/skills/plonecli/SKILL.md @@ -1,6 +1,6 @@ --- name: plonecli -description: Scaffold and develop Plone packages with plonecli (copier-template based). Use for any plonecli command (create, add, setup, serve, test, debug, update, config) and whenever working on Plone add-on features: creating a backend add-on or Zope project; adding or creating a content type, behavior, view, viewlet, portlet, vocabulary, indexer, subscriber, control panel, form, theme, REST API service, or any other subtemplate; scaffolding an upgrade step / GenericSetup migration after changing profile XML (catalog.xml, types, workflows, registry, rolemap) so it reaches already-installed sites; running/testing/reconfiguring a generated project. Triggers on "plonecli ...", "create a Plone addon", "add/create a content type / behavior / view / viewlet / portlet / vocabulary / indexer / subscriber / control panel / REST API service", "add upgrade_step / upgrade step for the last change", "bump profile version / metadata.xml", "migrate already-installed Plone sites", "plone scaffold", "zope-setup". +description: Scaffold and develop Plone packages with plonecli (copier-template based). Use for any plonecli command (create, add, setup, serve, test, debug, update, config) and whenever working on Plone add-on features: creating a backend add-on or Zope project; adding a content type, behavior, view, viewlet, portlet, vocabulary, indexer, subscriber, control panel, form, theme, or any other subtemplate; scaffolding an upgrade step / GenericSetup migration after changing profile XML (catalog, types, workflows, registry, rolemap) so it reaches already-installed sites; adapting an old/legacy package (mr.bob/bobtemplates, buildout, setup.py) to the structure plonecli's templates need; running/testing/reconfiguring a generated project. Triggers on "plonecli ...", "create a Plone addon", "add a content type / behavior / restapi service", "add upgrade_step", "migrate already-installed Plone sites", "use plonecli on an old/legacy package", "convert setup.py / buildout addon to plonecli", "zope-setup". --- # plonecli @@ -34,7 +34,7 @@ On first run, plonecli clones the copier-templates to `~/.copier-templates/plone ## Decision flow 1. **New project?** → `create`. Pure backend add-on: `plonecli create backend_addon my.addon`. Add-on **with** a runnable instance in one step: `plonecli create addon my.addon` (composite = `backend_addon` + `zope-setup`). Zope project: `plonecli create zope-setup my-project`. `addon` is **not** an alias of `backend_addon` — they are different templates. Details and template list: [reference/create.md](reference/create.md). -2. **Add a feature to an existing addon?** → `cd` into the project, then `plonecli add content_type` / `behavior` / `restapi_service`. Field/wiring specifics: [reference/add.md](reference/add.md). +2. **Add a feature to an existing addon?** → `cd` into the project, then `plonecli add content_type` / `behavior` / `restapi_service`. Field/wiring specifics: [reference/add.md](reference/add.md). **Old/legacy package that doesn't fit the templates?** (no `[tool.plone.backend_addon.settings]`, `setup.py`/`bobtemplate.cfg`/buildout layout, `plonecli -l` lists nothing, or `add` lands files/registrations wrong) → don't hand-write subtemplate files, and don't re-run the `backend_addon` template (it overwrites `__init__.py` and real code). Inspect the structure and make the minimal edits the subtemplate hooks need. See the legacy rule below and [reference/migrate.md](reference/migrate.md). 3. **Changed GenericSetup profile XML (`profiles/default/*`) that must reach already-installed sites?** → `plonecli add upgrade_step` to scaffold the migration. See the upgrade-step rule below and [reference/add.md](reference/add.md). 4. **Need a runnable Plone instance around an addon?** → `plonecli setup` (inside the addon). 5. **Run / test it?** → `plonecli test` to test. For serving, follow the server rule below. @@ -49,6 +49,7 @@ On first run, plonecli clones the copier-templates to `~/.copier-templates/plone - **Tests must pass — never skip them.** After scaffolding or adding a feature, run `plonecli test` and report real results. - **Profile XML changes need an upgrade step — scaffold it automatically.** Whenever you edit GenericSetup profile XML under `profiles/default/` (e.g. `catalog.xml`, `types/*.xml`, `types.xml`, `workflows.xml`, `registry.xml`, `rolemap.xml`) in a way that must propagate to already-installed sites, run `plonecli add upgrade_step --defaults -d upgrade_step_title=""` as part of the same change — don't leave it to the user to remember. It bumps `profiles/default/metadata.xml` and registers a GS upgrade handler; then fill that handler so existing sites actually get the change (reapply the relevant import step or migrate data). Never hand-edit `metadata.xml`'s version to "do an upgrade" — that bumps the number without a registered step. Details and what does/doesn't need a step: [reference/add.md](reference/add.md). - **Don't recreate to change settings.** Re-running `create` over an existing project is wrong; use the reconfigure flow ([reference/maintain.md](reference/maintain.md)). +- **Old/legacy package: adapt the structure minimally, never hand-roll old-style files.** If `plonecli add` won't wire features into an old package (mr.bob/`bobtemplates.plone`, buildout, `setup.py` — typically missing `[tool.plone.backend_addon.settings]` or a `src//configure.zcml`), don't fall back to writing the subtemplate's files by hand, and don't re-run the `backend_addon` template over it (it overwrites `__init__.py` and other real code). Inspect what's there, then make only the minimal edits the subtemplate hooks need to function — chiefly the `[tool.plone.backend_addon.settings]` block (so plonecli detects the addon and can register subtemplates) and a stub `src//configure.zcml` if absent (hooks append ``s before `` and silently skip it when the file is missing). Preserve existing code; recommend but don't force broader modernization. Then run `plonecli add` normally. Details: [reference/migrate.md](reference/migrate.md). - After `create`/`add`/reconfigure, generated files change — review `git status`/diff and preserve intentional local edits. ## Quick start diff --git a/plonecli/skills/plonecli/reference/add.md b/plonecli/skills/plonecli/reference/add.md index 8e8097a..c25c6f7 100644 --- a/plonecli/skills/plonecli/reference/add.md +++ b/plonecli/skills/plonecli/reference/add.md @@ -2,6 +2,8 @@ Run from **inside** a plonecli-generated project. If you are not in one, the command fails with `NotInPackageError` — `cd` into the project root first. +If you *are* inside an addon but it's an **old/legacy package** (mr.bob/`bobtemplates.plone`, buildout, `setup.py`) where `add` lands files in the wrong place or doesn't register them, the structure doesn't yet fit the templates. Don't hand-write the files and don't re-run the `backend_addon` template — make the minimal structural edits first. See [migrate.md](migrate.md). + ```shell cd collective.todo plonecli add content_type diff --git a/plonecli/skills/plonecli/reference/migrate.md b/plonecli/skills/plonecli/reference/migrate.md new file mode 100644 index 0000000..7bfef02 --- /dev/null +++ b/plonecli/skills/plonecli/reference/migrate.md @@ -0,0 +1,122 @@ +# Adapting an old/legacy package to fit plonecli + +Older Plone packages (mr.bob / `bobtemplates.plone`, buildout, `setup.py`) often +have a structure that plonecli's copier subtemplates can't fully wire into. When +`plonecli add ...` would land files in the wrong place or fail to register them, +**do not hand-write the subtemplate output in the old style, and do not re-run +the `backend_addon` template over the package** — that template overwrites files +like `src//__init__.py` (it is *not* in `_skip_if_exists`) and would +destroy real code there. + +Instead: **inspect the existing structure, compare it against what recent +plonecli + copier-templates actually need to function, and make only the minimal, +needed changes by hand** — preserving all existing code. Real package layouts +vary too much for a one-shot re-scaffold; a targeted edit is safer and an agent +can do it better. + +## How the subtemplates wire in (so you know what to provide) + +`plonecli add ` runs `copier copy` into the project root, then a +post-copy hook edits a few existing files. Those hooks (in +`shared/hooks/addon_context.py`, `shared/utils/xml_updater.py`, +`shared/utils/pyproject_updater.py`): + +- **Detect the parent addon** from `pyproject.toml`'s + `[tool.plone.backend_addon.settings]` (preferred) or fall back to + `bobtemplate.cfg` / `setup.py` (package name inferred). On the legacy fallback + they still run but print "Consider running the backend_addon template to + modernize" and registration is less reliable. +- **Register the new feature** into + `[tool.plone.backend_addon.settings.subtemplates]` (`content_types`, + `behaviors`, `services`, …) — this needs a `pyproject.toml` to write to. +- **Extend ZCML by appending before the closing `` tag**, and add + ``-style lines to the package's + `configure.zcml` — **but only if that file already exists** (`if + parent_zcml.exists()`); otherwise the include is *silently skipped* and the + feature never loads. There are **no special comment markers** — the anchor is + the `` / `` closing tag, and missing leaf files + (`behaviors/configure.zcml`, `types.xml`) are auto-created. xmlns prefixes are + auto-added as needed; edits are idempotent. + +## What recent plonecli/copier-templates need to function + +Check the package against this list and fix only what's missing: + +1. **`pyproject.toml` with `[tool.plone.backend_addon.settings]`** — at minimum + `package_name` and `package_folder` (folder = package name with `.`→`/`, e.g. + `collective.todo` → `collective/todo`). Also add the empty subtemplates table + so registration has somewhere to write: + + ```toml + [tool.plone.backend_addon.settings] + package_name = "collective.todo" + package_folder = "collective/todo" + + [tool.plone.backend_addon.settings.subtemplates] + content_types = [] + behaviors = [] + services = [] + ``` + + This single block is what makes `plonecli` detect the project as a + `backend_addon` (see `project.py`) and what subtemplate hooks read/write. If + the package has only `setup.py`/`bobtemplate.cfg` and no `pyproject.toml`, + adding this block is usually the highest-value minimal change. Leave the rest + of an existing working `pyproject.toml` (deps, build-system) alone unless it's + actually broken. + +2. **`src//` source layout.** If the package uses a flat or + different layout, the subtemplates still target `src//…`. + Confirm this path exists and matches `package_folder`. + +3. **`src//configure.zcml` must exist** and contain a + `` block. Without it, every `` + the hooks try to add is dropped silently. If it's missing, create a minimal + one (don't overwrite an existing one): + + ```xml + + + + ``` + + The hooks add missing xmlns prefixes themselves, so a basic root is enough. + +4. **`profiles/default/metadata.xml` with a ``** — required for + `plonecli add upgrade_step` (the hook reads and bumps ``). `types.xml` + is auto-created for content types if absent. + +5. **Preserve real code.** If `src//__init__.py` contains a message + factory, namespace declaration, or imports, keep them. If `configure.zcml` / + `setuphandlers.py` already exist, keep them — only extend. This is exactly why + we migrate by hand rather than re-running the template. + +## Workflow + +1. **Start from a clean git state** so every change is a reviewable diff. +2. **Inspect:** list `src/`, read `pyproject.toml` (or `setup.py`/`setup.cfg`/ + `bobtemplate.cfg`), and check for the four items above. Identify the gap. +3. **Apply the minimal fix(es)** by hand — typically just the + `[tool.plone.backend_addon.settings]` block, and a stub `configure.zcml` only + if absent. Do not touch working config you don't need to. +4. **Verify detection:** `plonecli -l` inside the package should now list the + `backend_addon` subtemplates. +5. **Add the feature the normal way** ([add.md](add.md)), e.g. + `plonecli add behavior --defaults -d behavior_name="IFeatured"`, then review + the diff to confirm files landed under `src//…` and the + include/registration were added. +6. **Run `plonecli test`** and report real results (add the zope-setup layer via + `plonecli setup` first if there's no `tasks.py`; see [maintain.md](maintain.md)). + Never skip tests. + +## What to recommend but not force + +You may *recommend* modernizing outdated config (buildout/tox → uv, `setup.py` → +hatchling `pyproject.toml`, `*.rst` → `*.md`) and explain the benefit, but if it +still works with current plonecli, **don't change it on your own** — leave it and +let the user decide. The migration's goal is to make `plonecli add` work with the +least disruption, not to rewrite the package. From bb5c002cedf7b198765737098473b80cf8c166e7 Mon Sep 17 00:00:00 2001 From: MrTango Date: Thu, 21 May 2026 15:44:19 -0700 Subject: [PATCH 2/2] Update changelog for legacy-package migration guidance --- CHANGES.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index cf57d07..9f5f175 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -3,7 +3,10 @@ ## 7.0.0b7 (unreleased) -- Nothing changed yet. +- Add legacy-package migration guidance to the bundled plonecli skill, + documenting how to adapt old mr.bob/buildout/setup.py packages so plonecli + subtemplates wire in correctly. + [MrTango] ## 7.0.0b6 (2026-05-22)