Skip to content

fix: unbreak scaffold-smoke — resolve generate language headlessly, add per-language legs - #128

Merged
cultron merged 1 commit into
mainfrom
fix/go-scaffold-smoke-headless
Aug 19, 2026
Merged

fix: unbreak scaffold-smoke — resolve generate language headlessly, add per-language legs#128
cultron merged 1 commit into
mainfrom
fix/go-scaffold-smoke-headless

Conversation

@cultron

@cultron cultron commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Problem

The weekly scaffold smoke test workflow has been red on every run since 2026-08-03 (runs 30802602127, 31366760662, 32003487994).

Root cause

The run scaffolds a TypeScript project, then calls a bare apso generate. Because the v2.0.0 TypeScript template ships an .apsorc without a language field and apso init never records the language it was given, generate fell through its flag > .apsorc > prompt resolution to the interactive inquirer prompt — which dies in the non-TTY CI runner. From the failed run log (job 95308243016):

==> Generating code from .apsorc
? Select target language for code generation: (Use arrow keys)
❯ TypeScript (NestJS + TypeORM)
  Python (FastAPI + SQLAlchemy)
  Go (Gin + GORM) FAIL: apso generate errored on a fresh scaffold
##[error]Process completed with exit code 1.

(The Go/Python templates already carry "language" in their .apsorc; only the pinned TS template lacks it.)

Two latent issues sat behind that one: every generator hard-errors on "entities": [], so even past the prompt the old script would have failed while exercising zero codegen; and the workflow had no Go or Python leg at all despite being the only regression net for the generators shipped in 0.36/0.37.

Changes

  • init: stamp the chosen language into the scaffolded .apsorc (stampApsorcLanguage, called from cloneTemplate). Fresh scaffolds are self-describing, so a bare apso generate — what the docs tell a new user to run — works. Best-effort: existing values and unparseable files are left alone. New unit test suite (5 tests).
  • generate: if the language can't be resolved from the flag or .apsorc and the session is headless, fail fast naming the flag instead of prompting (isInteractive()/missingFlag(), the same pattern init already uses):
    Error: Running non-interactively (no TTY / CI / APSO_NONINTERACTIVE). Pass
    --language <typescript|python|go> or set "language" in .apsorc.
    
  • scripts/scaffold-smoke.sh: seed one entity before generating so the run tests real codegen, then install/compile per language — tsc --noEmit --rootDir . (TS; the v2.0.0 template tsconfig includes test/** with rootDir: src, tripping TS6059 under bare tsc), go mod tidy + swag init + go build ./... (Go; the template imports the swag-generated app/docs package, per its README setup), venv + pip install -e . + compileall (Python).
  • workflow: matrix over [typescript, python, go] with fail-fast: false, plus setup-go/setup-python steps. Refreshed the stale header comment (the "unpublished @apso/crud" blocker it described is resolved; v2.0.0 installs from npm).

Verification

  • Reproduced the failure headlessly on unfixed main: CI=true bin/run generate on a scaffold without .apsorc language renders the prompt and exits 130. After the fix: language-less config fails fast with the error above; a fresh scaffold generates without prompting ([apso] Using language from .apsorc: ...).
  • All three legs green locally: bash scripts/scaffold-smoke.sh typescript|python|go each end in PASS: scaffolded <language> project installs and compiles.
  • npm test: 26 suites, 351 tests passing. npm run lint: 0 errors.
  • Will trigger the workflow on this branch via workflow_dispatch to prove it in CI.

🤖 Generated with Claude Code

…dd per-language legs

The weekly scaffold-smoke workflow has been red since 2026-08-03. The run
scaffolds a TypeScript project and then calls a bare `apso generate`, which
fell through to the interactive inquirer language prompt ("Select target
language for code generation:") because the v2.0.0 TypeScript template ships
an .apsorc without a `language` field and init never recorded the one it was
given. In the non-TTY CI runner the prompt dies immediately (exit 130).

Fixes, smallest first:

- init: stamp the chosen language into the scaffolded .apsorc
  (stampApsorcLanguage in template.ts, called from cloneTemplate). A fresh
  scaffold is now self-describing, so a bare `apso generate` resolves the
  language from config. Best-effort: existing values and unparseable files
  are left alone. Covered by a new unit test suite.
- generate: when the language cannot be resolved from the flag or .apsorc
  and the session is headless (CI / no TTY / APSO_NONINTERACTIVE), fail fast
  with the flag named instead of prompting, using the existing
  isInteractive()/missingFlag() pattern from init.
- scaffold-smoke.sh: seed one entity before generating (every generator
  errors on "entities": [], so the old script both failed and tested no
  codegen), then install/compile per language: tsc --noEmit --rootDir . for
  TypeScript (the v2.0.0 template tsconfig includes test/** with rootDir
  src, tripping TS6059), go mod tidy + swag init + go build for Go (the
  template imports the swag-generated app/docs package), venv + pip install
  + compileall for Python.
- workflow: matrix over typescript/python/go with fail-fast off, so the
  weekly run is a real regression net for the Go and Python generators that
  shipped in 0.36/0.37.

All three legs verified green locally via bash scripts/scaffold-smoke.sh
<language>.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cultron
cultron merged commit 2ea1e17 into main Aug 19, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant