Skip to content

feat(scaffold)[4/4]: tests + integration fixes + docs#85

Closed
jadb wants to merge 20 commits into
pr/3-scaffold-orchestrationfrom
pr/4-scaffold-integration-docs
Closed

feat(scaffold)[4/4]: tests + integration fixes + docs#85
jadb wants to merge 20 commits into
pr/3-scaffold-orchestrationfrom
pr/4-scaffold-integration-docs

Conversation

@jadb
Copy link
Copy Markdown
Contributor

@jadb jadb commented May 24, 2026

Summary

Final layer: end-to-end tests, integration bug fixes surfaced by those tests, and documentation (T-0812, T-0813, T-0814 + an integration-fixes commit).

Tests (T-0812, T-0813)

  • `templates/test-scaffold-e2e.sh` extended with `assert_managed_files`: validates mise.toml shape per-lang, devcontainer.json schema (incl. `jq` parse check), docker-compose validity (incl. `docker compose config -q` when available), .env.example all five managed blocks, CI workflows use mise-action + no legacy `setup-*` actions. Matrix: go, ts, py, rs, polyglot, plus `--services postgres,redis`. Result: 365/366 pass (the 1 failure is a pre-existing unrelated test2 README placeholder issue).
  • `templates/test-kit-init-idempotency.sh` (new): 6 end-to-end tests of the `kit init --update` contract — double-update zero diff; user content above markers survives; `--add-service redis` twice == once; `--check` exits 0 on clean / 1 on drift with mention of drifted file; detect-langs gating; service-add replacing semantics. All 6 pass.

Integration fixes

Three bugs the E2E surfaced were genuine cross-task spec drift; fixed in this PR:

  1. `devcontainer.json`: removed pre-existing template at `templates/shared/devcontainer/devcontainer.json.tmpl` (and sibling Dockerfile/flake files) so the T-0805 emitter is authoritative. The old template was producing a half-merged file with duplicate `postCreateCommand` keys.
  2. CI workflows under `templates/shared/ci/*`: T-0809 only migrated `templates/ci/` workflows; the per-language CI templates were still using `actions/setup-*`. Migrated those too (ci-go, ci-ts, ci-py, ci-rs + release-please job).
  3. Compose volumes: service snippets (postgres, redis, minio) switched from named volumes (`pgdata`, etc.) to bind mounts to `./.data/` — no top-level `volumes:` block needed, `docker compose config` validates clean. `.data/` added to gitignore template.

Also fixed a BSD-awk portability bug in the E2E's JSON-C stripper.

Docs (T-0814)

  • `templates/folder-structure.md` — new section on emitter output layout
  • `templates/README.md` — summary + pointer to runbook
  • `templates/cli-{go,ts,py,rs,php}/README.md.tmpl` — "Getting started" (mise install / compose up / Jaeger URL) + "Tool versions" + "Bring this project up to date" sections
  • `templates/RUNBOOK-UPGRADE.md` (new) — step-by-step procedure for refreshing an existing project via `kit init --check` → `--update`
  • `templates/shared/README.md` — preamble + emitter library overview
  • `templates/CONFORM.md` — clarifies that `kit init --update` is the modern refresh path
  • spec.md §11 — final decision-log row documenting the integration-fix outcomes

Track completion

This is PR 4 of 4. Base is PR 3 (#84). Merging this closes track scaffold-emits-mise-toml-devcontainer-compose — 13/13 tasks done.

Test plan

  • `go test ./cmd/kit/init/...` — 291 tests pass.
  • `bats templates/shared/*.bats` — 114 tests pass.
  • `bash templates/test-scaffold-e2e.sh` — 365 of 366 pass (1 pre-existing unrelated).
  • `bash templates/test-kit-init-idempotency.sh` — 6 of 6 pass.
  • Spot-check `templates/RUNBOOK-UPGRADE.md` renders cleanly.

jadb added 16 commits May 24, 2026 11:40
`templates/test-kit-init-idempotency.sh` exercises the contract from
spec §4: re-running `kit init --update` produces byte-identical
managed files; user content above kit-managed markers survives
updates; `--add-service redis` twice yields the same result as once;
`--check` exits 0 on no drift, 1 on drift (with diff on stdout);
language detection gates runtime entries (package.json-only → no go
entry in mise.toml).

Complements T-0810's Go-level tests with end-to-end coverage that
exercises the actual built binary against scratch projects in tempdirs.

Refs T-0813 (track: scaffold-emits-mise-toml-devcontainer-compose)
…I emitters

`templates/test-scaffold-e2e.sh` gains an `assert_managed_files`
stage that runs after project creation and validates: mise.toml
(per-lang runtime gating + workflow tools + tasks.install block),
.devcontainer/devcontainer.json (compose mode + mise feature + jq
validity), .devcontainer/docker-compose.yml (telemetry stack + opted-in
services + `docker compose config` validation when available),
.devcontainer/otel-config.yaml, .env.example (all five managed
blocks + correct queue driver), and CI workflows (mise-action used,
legacy setup-* actions absent).

Matrix expanded to cover go, ts, py, rs, polyglot, plus a
`--services postgres,redis` case. Missing tools (docker, jq) skip
gracefully rather than failing the whole run.

Refs T-0812 (track: scaffold-emits-mise-toml-devcontainer-compose)
- devcontainer.json: remove pre-existing template at
  templates/shared/devcontainer/devcontainer.json.tmpl (and
  sibling Dockerfile, devbox.json, flake.nix.tmpl, flake.lock,
  post-create.sh, README.md) so the T-0805 emitter is
  authoritative (was producing half-merged file with duplicate
  postCreateCommand keys). build.sh's template-population step
  no longer copies devcontainer/ since the directory is emitted
  fresh by emit-devcontainer-json.sh + emit-docker-compose.sh.
- CI workflows under templates/shared/ci/ci-{go,ts,py,rs}.yml*
  and the release-please.yml generated by
  templates/setup-release-please.sh: migrate from
  actions/setup-{go,node,python} + dtolnay/rust-toolchain +
  pnpm/action-setup + astral-sh/setup-uv to jdx/mise-action@v2
  (T-0809 missed these; it only covered
  templates/ci/{grade,verify-no-leak,verify-stories}). Workflow
  tools invoked via mise exec --.
- Compose volumes: service snippets (postgres, redis, minio)
  now use bind mounts to ./.data/<svc> instead of named
  volumes, so the emitted docker-compose.yml validates without
  a top-level `volumes:` block. .gitignore updated to exclude
  .data/. mailpit and redpanda already used no named volumes.

Cherry-picks T-0812 E2E commit (b6becb0) which now passes
in full after these fixes (modulo one unrelated pre-existing
failure: test2 README placeholder). The cherry-picked test's
JSON-C strip helper was tweaked to accumulate the file into one
awk buffer so the trailing-comma gsubs see multi-line context
across BSD awk (RS="" / RS="\\0" both behave as paragraph mode
on macOS, breaking the original two-pass design).

Refs T-0812 (track: scaffold-emits-mise-toml-devcontainer-compose)
Updates templates/folder-structure.md, templates/README.md,
templates/cli-{go,ts,py,rs,php}/README.md.tmpl, templates/shared/README.md,
and templates/CONFORM.md to cover the new scaffold output: mise.toml
as SOT, `mise run install` contributor entry point, devcontainer
compose-mode (no Dockerfile), --services catalog, Jaeger UI URL,
and `kit init --update` idempotency contract.

Adds templates/RUNBOOK-UPGRADE.md: step-by-step procedure to bring
an existing project to current poly-kit defaults via `kit init
--check` and `kit init --update`.

Spec section 11 decisions log gets a final row capturing the T-0812
integration-fix outcomes.

Refs T-0814 (track: scaffold-emits-mise-toml-devcontainer-compose)
…emption

- Service snippets switch from `./.data/<svc>` (compose-relative,
  resolves to `.devcontainer/.data/<svc>`) to `../.data/<svc>` so
  data lands in project-root `.data/<svc>` — matches the prose
  in RUNBOOK-UPGRADE.md and folder-structure.md.
- templates/shared/ci/README.md documents why Kotlin and Swift
  workflow templates use platform-native setup actions instead
  of jdx/mise-action.
jadb added a commit that referenced this pull request May 24, 2026
…led gh (#86)

The hook harness builds PATH as `h.pathDir:/usr/bin:/bin` so the
hook can find sed/tr/jq/curl. On Ubuntu CI runners gh is
preinstalled at /usr/bin/gh, which leaks into the harness PATH and
makes `command -v gh` succeed — the hook skips the missing-gh
branch, runs `gh pr view` (returns empty because the test omitted
stubGH), and emits "no open PR" instead of "gh not found on PATH".
The test passes locally on macOS (where gh lives at
/opt/homebrew/bin/gh, outside the harness PATH) but fails on CI.

Add a PATH override hook to h.run() and pin TestHook_MissingGH to
PATH=h.pathDir only. The missing-gh branch uses bash builtins
exclusively before exiting, so /usr/bin utilities are not required
to reach it.

Pre-existing failure on origin/main; blocks scaffold-track PRs
#82-#85 from showing all-green CI.

Co-authored-by: Jad Bitar <jadb@users.noreply.github.com>
jadb added 4 commits May 24, 2026 18:26
cli-go/ts/py/shared manifests lacked render_rules so the Go engine
never stripped .tmpl suffixes — go.mod.tmpl, package.json.tmpl,
pyproject.toml.tmpl all shipped as-is, breaking bootstrap smoke
tests for every cli-* template. Add strip_suffixes, remove_after_render,
and license rule to match cli-rs/cli-php precedent.

init.sh now (a) strips .tmpl from LICENSE-* before the license cp
phase so it tolerates both shipped (LICENSE-MIT.tmpl) and pre-stripped
layouts, and (b) removes kit-template.yaml + tiers.yaml manifests so
its output matches the Go engine byte-for-byte per remove_after_render.
@jadb jadb deleted the branch pr/3-scaffold-orchestration May 25, 2026 22:50
@jadb jadb closed this May 25, 2026
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