Skip to content

feat: ship Backstage template + @plinth-dev/scaffolder-actions#1

Merged
hushamsaeed merged 2 commits into
mainfrom
scaffolder-initial
May 1, 2026
Merged

feat: ship Backstage template + @plinth-dev/scaffolder-actions#1
hushamsaeed merged 2 commits into
mainfrom
scaffolder-initial

Conversation

@hushamsaeed
Copy link
Copy Markdown
Contributor

Summary

Mirrors plinth-dev/cli's plinth new flow inside a Backstage portal. Same inputs → same output, regardless of which surface the user enters from.

  • packages/scaffolder-actions/@plinth-dev/scaffolder-actions npm package. Pure-function core (scaffold, applyReplacements, fetchAndExtract, forApi, forWeb) is a TS port of the CLI's Go logic. createPlinthScaffoldAction() wraps it as a Backstage `TemplateAction` with JSON-schema input/output (no zod runtime dep).
  • template.yaml — Backstage software template at repo root. Form parameters: name, web/api toggles, Go module path, starter ref. Registered into a Backstage catalog via the standard URL-location pattern.
  • CI — Node 22 + pnpm 10. install/lint/typecheck/test/build green locally.

Implementation notes

  • Order-sensitive replacement: full Go module path `github.com/plinth-dev/starter-api` runs before the bare `starter-api` token, so sdk-go imports never get corrupted.
  • Skip policy mirrors the CLI: `node_modules/`, `.git/`, `.next/`, `dist/`, `vendor/`, lockfiles (`go.sum`, `pnpm-lock.yaml`, `package-lock.json`, `yarn.lock`), and binary files (NUL-byte probe in first 8 KiB).
  • Tarball fetch via GitHub's codeload `tar.gz` endpoint; single-component prefix strip via `tar` package's `strip: 1`.
  • Backstage action types: `ActionInput`/`ActionOutput` index-signed against `@backstage/types`'s `JsonValue` so `createTemplateAction<I, O>`'s `JsonObject` constraint is satisfied without forcing a zod dep.

Tests

14 vitest tests:

  • rewrite (5): api + web fixtures, idempotency (second run = 0 changes), binary skip, empty replacements no-op.
  • fetch (3): downloads + strips prefix, rejects 404, accepts injected fetch impl. Real `node:http` test server + `tar.create` + `zlib.createGzip`.
  • scaffold (6): both tiers, web-only/api-only, name validation, workspace must be absolute, neither-tier rejection, default ref behaviour.

Roadmap deferred

  • Golden-tree CI parity test that diffs the scaffolder's output against `plinth new`'s output (separate cycle — needs the Go binary in the runner).
  • npm publish of `@plinth-dev/scaffolder-actions`.

Test plan

  • CI green on this branch.
  • After merge, manually wire `createPlinthScaffoldAction()` into a Backstage backend and run the template via the portal.

🤖 Generated with Claude Code

hushamsaeed and others added 2 commits May 1, 2026 19:00
Mirrors plinth-dev/cli's `plinth new` flow inside a Backstage portal so
both surfaces produce the same output for the same inputs.

- packages/scaffolder-actions: pnpm workspace, tsup ESM build, vitest.
  Pure functions (scaffold/applyReplacements/fetchAndExtract/forApi/
  forWeb) are TS ports of the CLI's Go logic — order-sensitive
  replacement (full Go module path before bare service-name token);
  skips node_modules, .git, lockfiles, and binary content; tarball
  fetch via GitHub's codeload tar.gz endpoint with single-component
  prefix strip via `tar` package's `strip: 1`.

- createPlinthScaffoldAction wraps scaffold() in a Backstage
  TemplateAction with a JSON-schema input/output contract. No zod
  runtime dep — schema is plain JSON Schema.

- template.yaml at repo root drives the action with form params for
  name/tiers/module path/ref, registered in a Backstage catalog via
  the standard URL-location pattern.

- 14 vitest tests covering rewrite (api + web fixtures, idempotency,
  binary skip, empty replacements), fetch+extract (httptest fixture
  via node:http + tar.create + zlib + 404 + injected fetch), and the
  scaffold orchestrator (both tiers, web-only, name validation,
  workspace-must-be-absolute, must-pick-at-least-one tier, default
  ref behaviour).

- CI: Node 22 + pnpm 10 — install/lint/typecheck/test/build green.

Roadmap deferred: golden-tree CI parity test against the CLI's output
and npm publish of @plinth-dev/scaffolder-actions.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@hushamsaeed hushamsaeed merged commit 131948f into main May 1, 2026
1 check passed
@hushamsaeed hushamsaeed deleted the scaffolder-initial branch May 1, 2026 14:02
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