/** * GitHub Actions workflow scaffolder for `cleo init --workflows`. * * Renders the `*.yml.tmpl` templates shipped with `@cleocode/core` into a * consuming project's `.github/workflows/` directory. Placeholder * substitution draws from three sources, in precedence order: * * 1. `.cleo/release-config.json` — project-supplied overrides * (`nodeVersion`, `releaseBranchPrefix`, `prLabel`, fanout/rollback * knobs, etc.). * 2. ADR-061 tool resolver — `tool:install|lint|typecheck|test|build` * resolution via `resolveToolCommand`, honouring * `.cleo/project-context.json` plus per-`primaryType` defaults. * 3. Hard-coded fallbacks — `22.x` for Node, `release` for branch/label * prefixes, the conventional pnpm-flavoured commands. * * T9531 (Phase 3 of T9494) shipped the prepare-only scaffold — * `release-prepare.yml.tmpl` → `.github/workflows/release-prepare.yml`. * T9536 (Phase 4 of T9497) extended the default to walk the full * four-template set: `release-prepare`, `release-publish`, * `release-fanout`, `release-rollback`. Callers MAY still pass an * explicit single-template `templates` array to scaffold a subset. * * Implementation notes: * * - Substitution is deterministic regex `s/{{NAME}}/value/g` per * `packages/core/templates/workflows/README.md` — no Mustache / * Handlebars / nested templating. A re-render against the same * inputs MUST produce a byte-identical output (idempotence). * - Writes are atomic via tmp-then-rename so partial files cannot leak * onto disk if the process crashes mid-write. * - `force=true` audit-logs the overwrite event to * `.cleo/audit/init-workflows.jsonl` so reviewers can prove a CI * deviation was operator-initiated. Same convention as * `force-bypass.jsonl` (ADR-039). * - The scaffolder returns the rendered YAML in the result envelope * even on `dryRun=true` — the CLI uses this for stdout preview. * * @module init/scaffold-workflows * @task T9531 * @epic T9494 * @adr ADR-061 * @adr ADR-065 */ /** * Logical name of a renderable workflow template. The scaffolder reads * `/.yml.tmpl` and writes * `/.github/workflows/.yml`. * * All four canonical templates are now wired by default (T9536). Callers * that need a single-template subset (legacy T9531 behaviour) MUST pass * an explicit `templates` array — the default is the full four-template * set so a fresh `cleo init --workflows` produces the complete pipeline. */ export type WorkflowName = 'release-prepare' | 'release-publish' | 'release-fanout' | 'release-rollback'; /** * The four canonical placeholder values resolved from * `.cleo/project-context.json` via ADR-061. Exposed for testability — the * unit test asserts against the resolved shape instead of recomputing it. */ export interface ResolvedToolPlaceholders { install: string; lint: string; typecheck: string; test: string; build: string; } /** * Inputs read from `.cleo/release-config.json` that influence * substitution. All fields are optional — missing fields fall back to * hard-coded defaults documented in * `packages/core/templates/workflows/README.md`. */ export interface ScaffoldReleaseConfig { /** * Override the package-install command. NOT part of the ADR-061 canonical * tool list (those are test/build/lint/typecheck/audit/security-scan), so * it falls through `.cleo/release-config.json` instead of the resolver. * Defaults to {@link DEFAULT_INSTALL_CMD}. */ installCmd?: string; nodeVersion?: string; releaseBranchPrefix?: string; prLabel?: string; npmPublishCmd?: string; publishers?: string; fanout?: { docsBuildCmd?: string; docsDeploy?: boolean; dockerRetag?: boolean; sentinelNotify?: boolean; studioDeploy?: boolean; nightlyTrigger?: boolean; dockerImage?: string; dockerHubUser?: string; sentinelWebhookUrl?: string; studioDeployHook?: string; }; rollback?: { npmPackages?: string; cargoCrates?: string; }; } /** * Options for {@link scaffoldWorkflows}. */ export interface ScaffoldWorkflowsOptions { /** * Absolute path to the consuming project's root (NOT the cleocode * monorepo). Required — the scaffolder writes * `/.github/workflows/*.yml`. */ projectRoot: string; /** * Absolute path to the directory containing `*.yml.tmpl` files. In * normal usage the CLI resolves this against the `@cleocode/core` * package root. Exposed as an input so the unit test can point at a * fixture tree without depending on package layout. */ templatesDir: string; /** * Which templates to render. T9531 shipped a prepare-only default; * T9536 flipped the default to ALL four canonical templates — * `release-prepare`, `release-publish`, `release-fanout`, * `release-rollback`. Callers MAY still pass a subset (e.g. * `['release-prepare']`) to scaffold one template at a time. * * See {@link DEFAULT_WORKFLOW_TEMPLATES} for the default ordering. */ templates?: ReadonlyArray; /** * `true` ⇒ skip the actual write. The rendered YAML is still returned * in the result envelope so the caller can pipe it to stdout. Idempotent * with `force=true`. */ dryRun?: boolean; /** * `true` ⇒ overwrite an existing `/.github/workflows/*.yml` * even when its content already differs from the rendered output. * Appends an audit-log row to `.cleo/audit/init-workflows.jsonl`. */ force?: boolean; /** * Override the loaded release config — primarily for unit tests. When * omitted the scaffolder reads `/.cleo/release-config.json`. */ releaseConfigOverride?: ScaffoldReleaseConfig; } /** * Per-template scaffold outcome. */ export interface ScaffoldWorkflowOutcome { /** Which template was rendered. */ template: WorkflowName; /** Absolute path to the destination workflow file. */ targetPath: string; /** Rendered YAML contents (returned regardless of `dryRun`). */ rendered: string; /** * Disposition of the write step: * - `'created'` — the destination did not exist; new file written. * - `'updated'` — destination existed with different content; rewritten * (requires `force=true`). * - `'unchanged'` — destination existed with identical content; no-op. * - `'skipped'` — destination existed with different content but * `force=false`. No write occurred. * - `'dry-run'` — `dryRun=true`; no write attempted. */ status: 'created' | 'updated' | 'unchanged' | 'skipped' | 'dry-run'; } /** * Result envelope returned by {@link scaffoldWorkflows}. */ export interface ScaffoldWorkflowsResult { /** Per-template outcomes in the order they were rendered. */ outcomes: ScaffoldWorkflowOutcome[]; /** The resolved placeholder set (useful for surfacing in CLI output). */ resolvedTools: ResolvedToolPlaceholders; } /** * Canonical full set of release-pipeline workflow templates rendered by * `cleo init --workflows` when no explicit `templates` array is provided. * * Ordering matters for the audit log + CLI stdout summary: prepare lands * first (the entrypoint), publish second (tag-on-merge), fanout third * (best-effort downstream), rollback last (workflow_dispatch only). * * @task T9536 */ export declare const DEFAULT_WORKFLOW_TEMPLATES: ReadonlyArray; /** * Render and write the requested workflow templates. * * T9536 default behaviour: renders ALL four canonical templates * (`release-prepare`, `release-publish`, `release-fanout`, * `release-rollback`). Pass an explicit `templates` array to scaffold a * subset (legacy T9531 prepare-only behaviour is recovered by passing * `templates: ['release-prepare']`). * * @example * ```ts * const result = await scaffoldWorkflows({ * projectRoot: '/path/to/my-project', * templatesDir: '/path/to/@cleocode/core/templates/workflows', * }); * for (const o of result.outcomes) { * console.log(`${o.status}: ${o.targetPath}`); * } * ``` * * @task T9531 * @task T9536 — full four-template default */ export declare function scaffoldWorkflows(opts: ScaffoldWorkflowsOptions): Promise; /** * Enumerate the template files actually present in `templatesDir`. Used * by diagnostics surfaces (e.g. `cleo doctor`) — NOT used by the * scaffolder itself, which prefers the explicit * {@link ScaffoldWorkflowsOptions.templates} list so a bad input fails * deterministically. * * @task T9531 */ /** * Resolve the absolute path to `@cleocode/core`'s shipped * `templates/workflows/` directory. Works both in the monorepo source * layout (`packages/core/templates/workflows/`) and in the installed * npm package layout (`node_modules/@cleocode/core/templates/workflows/`). * * Replaces the per-CLI `getWorkflowTemplatesDir()` helpers introduced in * T9531/T9536 — those resolved against `packages/cleo/templates/`, which * violated the Package-Boundary Check now that templates live in core * (T9858). * * @returns Absolute path to the workflows template directory. * * @deprecated Use * {@link import('../templates/registry.js').getTemplatesByKind | getTemplatesByKind('workflow')} * from the SSoT template registry. The directory-resolver pattern loses the * per-template substitution + update policy the registry exposes. Rewire * planned in T9879 (Saga T9855). * * @task T9858 */ export declare function getWorkflowTemplatesDir(): string; /** * Resolve the absolute path to `@cleocode/core`'s shipped * `templates/git-hooks/` directory. Mirrors {@link getWorkflowTemplatesDir} * for the git-hook installer surface (T1588 / T1608). * * @returns Absolute path to the git-hooks template directory. * * @deprecated Use * {@link import('../templates/registry.js').getTemplatesByKind | getTemplatesByKind('config')} * filtered by `installPath.startsWith('.git/hooks/')`. Rewire planned in * T9879 (Saga T9855). * * @task T9858 */ export declare function getGitHookTemplatesDir(): string; export declare function listAvailableWorkflowTemplates(templatesDir: string): Promise; //# sourceMappingURL=scaffold-workflows.d.ts.map