Repository navigation
LuCLI: release.yml drops codegen templates — all template-driven generators emit empty output in installed module #1944
Description
Scope change
This issue originally tracked adding three stretch generators (api-resource, helper, snippets). All three are implemented in source (Module.cfc:190-205, CodeGen.cfc, Scaffold.cfc, + 12 snippet templates). However, e2e testing against an installed wheels binary surfaced a broader packaging bug that makes most generators unusable — reframing this issue to track the fix.
Bug
In a freshly installed Wheels project:
$ wheels generate model Post title:string body:text
create app/models/Post.cfc
$ cat app/models/Post.cfc
component extends="Model" {
function config() {
}
}
No validations. No relationships. Empty config(). Same stripped output for controller, view, scaffold, api-resource. helper fails loudly: Template not found: HelperContent.txt.
Only wheels generate snippets works end-to-end because its templates ship under cli/lucli/templates/snippets/.
Root cause
Templates.cfc::resolveTemplateDir() expects code-generation templates at moduleRoot/templates/codegen/ for installed modules. Per PLAN.md, the release workflow is supposed to copy cli/src/templates/ → cli/lucli/templates/codegen/ before tarring the module.
.github/workflows/release.yml:201 has no such copy step:
tar czf ... wheels-module-${{ env.WHEELS_VERSION }}.tar.gz -C cli/lucli .Result: the distributed tar ships only admin/, app/, deploy/, migrations/, snippets/ under templates/ — no codegen/. All generateFromTemplate() calls targeting ModelContent.txt, ControllerContent.txt, ApiControllerContent.txt, ViewContent.txt, HelperContent.txt, CRUDContent.txt, ActionContent.txt, DBMigrate.txt, tests/*.txt, crud/*.txt, admin/*.txt silently fall through to the empty/error paths.
This is invisible in the monorepo because resolveTemplateDir() fallback #2 resolves cli/src/templates/ directly. The CI test suite also runs in monorepo mode — the bug only manifests against installed distributions.
Fix
Add a bundle step to release.yml (and snapshot.yml for pre-release builds) before the tar:
- name: Bundle codegen templates into module
run: |
mkdir -p cli/lucli/templates/codegen
cp -R cli/src/templates/* cli/lucli/templates/codegen/Verification (e2e smoke test)
Must pass on the just-built tar, not the monorepo source:
# Install the built tar
mkdir -p ~/.wheels/modules/wheels
tar xzf wheels-module-*.tar.gz -C ~/.wheels/modules/wheels
# Scaffold + run each generator
cd /tmp && wheels new smoke && cd smoke
wheels generate model User name:string email:string active:boolean
grep -q "validatesPresenceOf" app/models/User.cfc # must pass
wheels generate controller Users index show
grep -q "function index" app/controllers/Users.cfc # must pass
wheels generate api-resource Product name price:decimal sku:string
grep -q "renderWith" app/controllers/Products.cfc # must pass
wheels generate helper formatting truncateText formatCurrency
test -s app/helpers/FormattingHelper.cfc # must pass
wheels generate scaffold Post title:string body:text
test -s app/views/posts/index.cfm # must pass
wheels generate snippets auth
test -f app/controllers/Sessions.cfc # must passConsider wiring this as a post-build GitHub Actions step so future releases cannot regress the packaging.
Out of scope for this issue
- The broader gap that CI never exercises the distributed tar (separate follow-up).
- Parameter-binding correctness of each generator — covered by existing specs once templates are reachable.
Activity
bpamiri commentedon Mar 16, 2026
Analysis
Synopsis
Add three stretch generators to LuCLI beyond the eight already implemented:
generate api-resource(API-only controller + model, no views),generate helper(app helper inapp/global/), andgenerate snippets(copy snippet templates toapp/snippets/).Merit Assessment
Recommendation: Proceed
api-resourceis the highest-value of the three — it's a common pattern for modern Wheels apps and the scaffold service already supportsapi=true(Scaffold.cfcline 30,CodeGen.cfcline 97). This is mostly a wiring exercise.helperandsnippetsare simple file-copy operations. Low effort, good for completeness.Implementation Plan
1.
generate api-resource(medium priority)Module.cfcgenerate()function (around line 44) for"api-resource"or"api"Scaffold.generateScaffold()withapi=true— this already skips view generation and usesApiControllerContent.txttemplatecli/src/templates/ApiControllerContent.txtalready exists2.
generate helper(low priority)generate()for"helper"app/global/{Name}.cfmwith a basic function skeletonHelperContent.txttocli/src/templates/.cfmfiles with plain functions (no component wrapper)3.
generate snippets(low priority)generate()for"snippets"cli/src/templates/toapp/snippets/in the projectTemplates.cfcline 177) already checksapp/snippets/as an override directory, so once copied, users can customize templates--forceflag to overwrite existing snippets4. Update help text in
generate()(line 48) to list the new generator types.Dependencies & Risks
api-resourcegenerator reuses the proven scaffold pipeline.ApiControllerContent.txttemplate should be verified to produce correct output with the LuCLI template processing (pipe-delimited|ObjectName|placeholders vs.{{variable}}style).Templates.cfchandles both styles (lines 62-146).Automated analysis by @claude — review and adjust as needed.
[-]LuCLI: stretch generators (api-resource, helper, snippets)[/-][+]LuCLI: stretch generators (api-resource, helper, snippets) Issue #1944[/+][-]LuCLI: stretch generators (api-resource, helper, snippets) Issue #1944[/-][+]LuCLI: release.yml drops codegen templates — all template-driven generators emit empty output in installed module[/+]fix(cli): bundle codegen templates into wheels-module tar (#1944) (#2209
ci(config): smoke test installed wheels-module against clean filesyst…
docs(docs): correct tutorial 02 + 03 gaps surfaced by fresh-vm onboar…