@celilo/cli 0.3.30-alpha.0 → 0.4.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/drizzle/0005_module_operations.sql +12 -0
- package/drizzle/0006_base_module_aspects.sql +15 -0
- package/drizzle/0007_module_systems.sql +17 -0
- package/drizzle/meta/_journal.json +21 -0
- package/package.json +3 -3
- package/schemas/system_config.json +14 -28
- package/src/ansible/inventory.test.ts +46 -62
- package/src/ansible/inventory.ts +48 -25
- package/src/capabilities/registration.ts +25 -7
- package/src/capabilities/validation.test.ts +30 -0
- package/src/capabilities/validation.ts +8 -0
- package/src/cli/backup-rename.test.ts +95 -0
- package/src/cli/cli.test.ts +17 -23
- package/src/cli/command-registry.ts +199 -0
- package/src/cli/commands/backup-list.ts +1 -1
- package/src/cli/commands/events.ts +96 -0
- package/src/cli/commands/machine-add.ts +103 -59
- package/src/cli/commands/module-import.ts +153 -4
- package/src/cli/commands/module-remove.ts +86 -17
- package/src/cli/commands/module-status.ts +6 -2
- package/src/cli/commands/publish/alpha.test.ts +185 -0
- package/src/cli/commands/publish/alpha.ts +226 -0
- package/src/cli/commands/publish/changesets.test.ts +89 -0
- package/src/cli/commands/publish/changesets.ts +144 -0
- package/src/cli/commands/publish/consumer-pins.test.ts +155 -0
- package/src/cli/commands/publish/consumer-pins.ts +149 -0
- package/src/cli/commands/publish/execute.ts +131 -0
- package/src/cli/commands/publish/global-install.test.ts +154 -0
- package/src/cli/commands/publish/global-install.ts +171 -0
- package/src/cli/commands/publish/helpers.ts +227 -0
- package/src/cli/commands/publish/index.ts +365 -0
- package/src/cli/commands/publish/module-registry.test.ts +40 -0
- package/src/cli/commands/publish/module-registry.ts +64 -0
- package/src/cli/commands/publish/plan.ts +107 -0
- package/src/cli/commands/publish/preflight.ts +238 -0
- package/src/cli/commands/publish/types.ts +264 -0
- package/src/cli/commands/publish/workspace.test.ts +323 -0
- package/src/cli/commands/publish/workspace.ts +596 -0
- package/src/cli/commands/restore.ts +126 -0
- package/src/cli/commands/storage-add-local.ts +1 -1
- package/src/cli/commands/storage-add-s3.ts +1 -1
- package/src/cli/commands/subscribers-add.ts +68 -0
- package/src/cli/commands/subscribers-list.ts +48 -0
- package/src/cli/commands/subscribers-remove.ts +38 -0
- package/src/cli/commands/subscribers-serve.ts +77 -0
- package/src/cli/commands/subscribers-status.ts +33 -0
- package/src/cli/commands/subscribers-test.ts +71 -0
- package/src/cli/commands/system-apply-config-equivalence.test.ts +108 -0
- package/src/cli/commands/system-apply-config.test.ts +70 -0
- package/src/cli/commands/system-apply-config.ts +130 -0
- package/src/cli/commands/system-audit.ts +2 -1
- package/src/cli/commands/system-init-deprecation.test.ts +90 -0
- package/src/cli/commands/system-init.ts +36 -70
- package/src/cli/commands/system-update.ts +3 -2
- package/src/cli/completion.ts +22 -1
- package/src/cli/index.ts +214 -6
- package/src/cli/interactive-config.test.ts +19 -0
- package/src/cli/restore-command.test.ts +131 -0
- package/src/db/client.ts +42 -0
- package/src/db/schema.test.ts +13 -16
- package/src/db/schema.ts +161 -9
- package/src/hooks/capability-loader-firewall.test.ts +6 -15
- package/src/hooks/capability-loader.test.ts +2 -3
- package/src/hooks/capability-loader.ts +36 -2
- package/src/hooks/define-hook.test.ts +4 -0
- package/src/hooks/executor.test.ts +18 -0
- package/src/hooks/executor.ts +21 -2
- package/src/hooks/load-hook-config.test.ts +26 -24
- package/src/hooks/load-hook-config.ts +11 -2
- package/src/hooks/run-named-hook.ts +16 -0
- package/src/hooks/types.ts +9 -1
- package/src/manifest/contracts/v1.ts +70 -0
- package/src/manifest/schema.ts +262 -16
- package/src/manifest/validate-privileged.test.ts +84 -0
- package/src/manifest/validate.test.ts +156 -0
- package/src/manifest/validate.ts +69 -0
- package/src/module/import.ts +12 -0
- package/src/services/aspect-approvals.test.ts +231 -0
- package/src/services/aspect-approvals.ts +120 -0
- package/src/services/aspect-runner.test.ts +493 -0
- package/src/services/aspect-runner.ts +438 -0
- package/src/services/aspect-template-resolver.test.ts +101 -0
- package/src/services/aspect-template-resolver.ts +122 -0
- package/src/services/backup-create.ts +104 -25
- package/src/services/backup-envelope-roundtrip.test.ts +199 -0
- package/src/services/backup-in-flight-refusal.test.ts +163 -0
- package/src/services/backup-manifest.test.ts +115 -0
- package/src/services/backup-manifest.ts +163 -0
- package/src/services/backup-restore.ts +154 -19
- package/src/services/build-bus/delivery-events.ts +92 -0
- package/src/services/build-bus/event-factory.ts +54 -0
- package/src/services/build-bus/fan-out.test.ts +279 -0
- package/src/services/build-bus/fan-out.ts +161 -0
- package/src/services/build-bus/hook-dispatch-mgmt.test.ts +157 -0
- package/src/services/build-bus/hook-dispatch.test.ts +207 -0
- package/src/services/build-bus/hook-dispatch.ts +198 -0
- package/src/services/build-bus/hook-dispatcher.ts +115 -0
- package/src/services/build-bus/index.ts +41 -0
- package/src/services/build-bus/receiver-server.test.ts +179 -0
- package/src/services/build-bus/receiver-server.ts +159 -0
- package/src/services/build-bus/status.test.ts +212 -0
- package/src/services/build-bus/status.ts +213 -0
- package/src/services/build-bus/subscriber-store.ts +113 -0
- package/src/services/celilo-events.test.ts +70 -0
- package/src/services/celilo-events.ts +92 -0
- package/src/services/celilo-mgmt-hooks.test.ts +296 -0
- package/src/services/config-interview.ts +13 -95
- package/src/services/cross-module-data-manager.ts +2 -31
- package/src/services/cross-module-read.test.ts +250 -0
- package/src/services/cross-module-read.ts +232 -0
- package/src/services/deploy-validation.ts +7 -0
- package/src/services/deployed-systems.test.ts +235 -0
- package/src/services/deployed-systems.ts +308 -0
- package/src/services/dns-provider-backfill.ts +75 -0
- package/src/services/health-runner.ts +19 -3
- package/src/services/infrastructure-variable-resolver.test.ts +6 -32
- package/src/services/infrastructure-variable-resolver.ts +3 -13
- package/src/services/machine-detector.ts +104 -48
- package/src/services/machine-pool.ts +145 -2
- package/src/services/module-config.ts +78 -120
- package/src/services/module-deploy.ts +113 -40
- package/src/services/module-operations.test.ts +154 -0
- package/src/services/module-operations.ts +154 -0
- package/src/services/module-subscriptions.test.ts +58 -0
- package/src/services/module-subscriptions.ts +24 -1
- package/src/services/module-types-generator.test.ts +3 -3
- package/src/services/module-types-generator.ts +7 -2
- package/src/services/proxmox-reconcile.test.ts +333 -0
- package/src/services/proxmox-reconcile.ts +156 -0
- package/src/services/proxmox-state-recovery.ts +3 -24
- package/src/services/restore-from-file.test.ts +177 -0
- package/src/services/restore-from-file.ts +355 -0
- package/src/services/restore-preflight.test.ts +127 -0
- package/src/services/restore-preflight.ts +118 -0
- package/src/services/storage-providers/s3.ts +10 -2
- package/src/services/system-identity.ts +30 -0
- package/src/services/system-init.test.ts +64 -21
- package/src/services/system-init.ts +28 -26
- package/src/templates/generator.test.ts +7 -16
- package/src/templates/generator.ts +28 -115
- package/src/test-utils/integration.ts +5 -2
- package/src/types/infrastructure.ts +8 -0
- package/src/variables/computed/computed-integration.test.ts +191 -0
- package/src/variables/computed/computed.test.ts +177 -0
- package/src/variables/computed/evaluate.ts +271 -0
- package/src/variables/computed/marker.ts +53 -0
- package/src/variables/computed/parse.ts +262 -0
- package/src/variables/computed/provider-lookup.ts +130 -0
- package/src/variables/context.test.ts +89 -28
- package/src/variables/context.ts +196 -191
- package/src/variables/parser.ts +3 -3
- package/src/variables/resolver.test.ts +61 -0
- package/src/variables/resolver.ts +81 -0
- package/src/variables/types.ts +23 -1
- package/src/services/dns-auto-register.ts +0 -211
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Preflight checks for `celilo publish` — dirty-tree, workspace
|
|
3
|
+
* stale-version, module stale-manifest. Builds a single
|
|
4
|
+
* `PreflightReport` so the planner can decide which gates apply for
|
|
5
|
+
* the current mode (alpha skips workspace + module stale; promote
|
|
6
|
+
* skips workspace stale; normal enforces all three).
|
|
7
|
+
*
|
|
8
|
+
* Also owns `--release-touch`: the auto-fix path for the
|
|
9
|
+
* release-only-drift case where source changed but manifest.yml
|
|
10
|
+
* didn't. Touch + commit + continue is automated when the publisher
|
|
11
|
+
* just hits Enter through it; otherwise --release-touch by itself
|
|
12
|
+
* touches and exits.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { execSync, spawnSync } from 'node:child_process';
|
|
16
|
+
import { readFileSync, writeFileSync } from 'node:fs';
|
|
17
|
+
import { join, relative } from 'node:path';
|
|
18
|
+
import { checkModuleStale } from '../../../services/module-validator/git-hygiene';
|
|
19
|
+
import {
|
|
20
|
+
PACKAGES,
|
|
21
|
+
REPO_ROOT,
|
|
22
|
+
isAncestor,
|
|
23
|
+
isPublished,
|
|
24
|
+
lastCommitTouching,
|
|
25
|
+
listModuleDirs,
|
|
26
|
+
readPkg,
|
|
27
|
+
} from './helpers';
|
|
28
|
+
import type { ModuleStaleIssue, PreflightReport, StalenessIssue } from './types';
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Detect "I bumped source but forgot to bump the version." If a package's
|
|
32
|
+
* current version is already on npm AND there are commits touching the
|
|
33
|
+
* package's source after the last commit that touched its package.json,
|
|
34
|
+
* the publish would silently skip — which is exactly how a feature add
|
|
35
|
+
* never makes it to npm.
|
|
36
|
+
*
|
|
37
|
+
* False positives: a commit that bumps a dependency in package.json
|
|
38
|
+
* (without changing the "version" field) resets staleness even though the
|
|
39
|
+
* version is still stale relative to the last bump. Acceptable for v1 —
|
|
40
|
+
* the common case (forget-to-bump after a feature commit) is caught.
|
|
41
|
+
*/
|
|
42
|
+
export function checkStaleVersion(pkg: string): StalenessIssue | null {
|
|
43
|
+
const { name, version } = readPkg(pkg);
|
|
44
|
+
if (!name || !version) return null;
|
|
45
|
+
if (!isPublished(name, version)) return null;
|
|
46
|
+
const lastPkgJson = lastCommitTouching([`${pkg}/package.json`]);
|
|
47
|
+
const lastSrc = lastCommitTouching([
|
|
48
|
+
pkg,
|
|
49
|
+
`:(exclude)${pkg}/package.json`,
|
|
50
|
+
`:(exclude)${pkg}/node_modules`,
|
|
51
|
+
]);
|
|
52
|
+
if (!lastPkgJson || !lastSrc) return null;
|
|
53
|
+
if (lastSrc === lastPkgJson) return null;
|
|
54
|
+
if (!isAncestor(lastPkgJson, lastSrc)) return null;
|
|
55
|
+
return {
|
|
56
|
+
name,
|
|
57
|
+
pkg,
|
|
58
|
+
version,
|
|
59
|
+
lastSrcCommit: lastSrc,
|
|
60
|
+
lastPkgJsonCommit: lastPkgJson,
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Run every precondition that can fail a publish, accumulating all
|
|
66
|
+
* issues into a single report. Used both by --dry-run (report-only) and
|
|
67
|
+
* by the normal publish flow (where it's the gate before any side
|
|
68
|
+
* effects run).
|
|
69
|
+
*
|
|
70
|
+
* Replaces the old "abort-on-first-failure per phase" pattern that made
|
|
71
|
+
* fresh releases require N round-trips when N modules drifted.
|
|
72
|
+
*/
|
|
73
|
+
export function runPreflight(): PreflightReport {
|
|
74
|
+
const dirtyOutput = execSync('git status --porcelain', {
|
|
75
|
+
encoding: 'utf-8',
|
|
76
|
+
cwd: REPO_ROOT,
|
|
77
|
+
}).trim();
|
|
78
|
+
|
|
79
|
+
const workspaceStale: StalenessIssue[] = [];
|
|
80
|
+
for (const pkg of PACKAGES) {
|
|
81
|
+
const issue = checkStaleVersion(pkg);
|
|
82
|
+
if (issue) workspaceStale.push(issue);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const moduleStale: ModuleStaleIssue[] = [];
|
|
86
|
+
for (const dir of listModuleDirs()) {
|
|
87
|
+
const issue = checkModuleStale(dir);
|
|
88
|
+
if (issue) {
|
|
89
|
+
moduleStale.push({
|
|
90
|
+
moduleDir: issue.moduleDir,
|
|
91
|
+
lastSrcCommit: issue.lastSrcCommit,
|
|
92
|
+
lastManifestCommit: issue.lastManifestCommit,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return {
|
|
98
|
+
dirty: dirtyOutput.length > 0,
|
|
99
|
+
dirtyOutput,
|
|
100
|
+
workspaceStale,
|
|
101
|
+
moduleStale,
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Print a human-readable preflight report. Returns true if any issue is
|
|
107
|
+
* blocking (i.e. publish would fail without --allow-stale).
|
|
108
|
+
*/
|
|
109
|
+
export function printPreflightReport(report: PreflightReport): boolean {
|
|
110
|
+
let anyIssue = false;
|
|
111
|
+
|
|
112
|
+
if (report.dirty) {
|
|
113
|
+
anyIssue = true;
|
|
114
|
+
console.error('\n✗ Working tree has uncommitted changes:\n');
|
|
115
|
+
console.error(execSync('git status --short', { encoding: 'utf-8', cwd: REPO_ROOT }));
|
|
116
|
+
console.error(' fix: commit or stash, then re-run.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (report.workspaceStale.length > 0) {
|
|
120
|
+
anyIssue = true;
|
|
121
|
+
console.error('\n✗ Stale-version drift on workspace packages:\n');
|
|
122
|
+
for (const i of report.workspaceStale) {
|
|
123
|
+
console.error(` ${i.name}@${i.version} is on npm, but commits touching ${i.pkg} landed`);
|
|
124
|
+
console.error(` after the last ${i.pkg}/package.json change.`);
|
|
125
|
+
console.error(` src commit: ${i.lastSrcCommit.slice(0, 12)}`);
|
|
126
|
+
console.error(` package.json commit: ${i.lastPkgJsonCommit.slice(0, 12)}`);
|
|
127
|
+
console.error(` fix: bump ${i.pkg}/package.json#version, commit, re-run.`);
|
|
128
|
+
console.error();
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
if (report.moduleStale.length > 0) {
|
|
133
|
+
anyIssue = true;
|
|
134
|
+
console.error('\n✗ Stale-manifest drift on celilo modules:\n');
|
|
135
|
+
for (const i of report.moduleStale) {
|
|
136
|
+
const rel = relative(REPO_ROOT, i.moduleDir);
|
|
137
|
+
console.error(` ${rel}: src committed after manifest.yml`);
|
|
138
|
+
console.error(` src commit: ${i.lastSrcCommit.slice(0, 12)}`);
|
|
139
|
+
console.error(` manifest.yml commit: ${i.lastManifestCommit.slice(0, 12)}`);
|
|
140
|
+
}
|
|
141
|
+
console.error(
|
|
142
|
+
' fix: bump manifest.yml#version (semver change), or run\n' +
|
|
143
|
+
' `bun run publish --release-touch` to auto-touch all drifted\n' +
|
|
144
|
+
" manifests with today's date (release-only — auto-revision\n" +
|
|
145
|
+
' picks the next +N).',
|
|
146
|
+
);
|
|
147
|
+
console.error();
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (!anyIssue) {
|
|
151
|
+
console.log('✓ Preflight clean: no dirty tree, no stale workspace versions, no stale modules.');
|
|
152
|
+
} else {
|
|
153
|
+
console.error('Pass --allow-stale to publish anyway (the prior versions stay on npm).');
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return anyIssue;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Append (or refresh) a `# released: <ISO timestamp>` trailing comment on
|
|
161
|
+
* the given manifest.yml. Always produces a fresh diff (timestamps are
|
|
162
|
+
* unique per second), so the resulting commit always advances past any
|
|
163
|
+
* source commit on the same day.
|
|
164
|
+
*/
|
|
165
|
+
export function touchManifestRelease(manifestPath: string): void {
|
|
166
|
+
const now = new Date().toISOString().replace(/\.\d{3}Z$/, 'Z');
|
|
167
|
+
const original = readFileSync(manifestPath, 'utf-8');
|
|
168
|
+
const lines = original.split('\n');
|
|
169
|
+
const cleaned: string[] = [];
|
|
170
|
+
for (const line of lines) {
|
|
171
|
+
if (line.match(/^#\s*released:/)) continue;
|
|
172
|
+
cleaned.push(line);
|
|
173
|
+
}
|
|
174
|
+
while (cleaned.length > 0 && cleaned[cleaned.length - 1].trim() === '') {
|
|
175
|
+
cleaned.pop();
|
|
176
|
+
}
|
|
177
|
+
cleaned.push(`# released: ${now}`);
|
|
178
|
+
cleaned.push('');
|
|
179
|
+
writeFileSync(manifestPath, cleaned.join('\n'));
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Apply --release-touch: rewrite every drifted manifest.yml with today's
|
|
184
|
+
* release marker. Doesn't commit — operator reviews `git diff` and
|
|
185
|
+
* commits explicitly so the touch lands as a documented release event,
|
|
186
|
+
* not as a silent script side-effect.
|
|
187
|
+
*/
|
|
188
|
+
export function applyReleaseTouch(issues: ModuleStaleIssue[]): void {
|
|
189
|
+
if (issues.length === 0) {
|
|
190
|
+
console.log('No module drift to touch — nothing to do.');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
console.log(`\nTouching ${issues.length} drifted manifest(s):`);
|
|
194
|
+
for (const i of issues) {
|
|
195
|
+
const manifestPath = join(i.moduleDir, 'manifest.yml');
|
|
196
|
+
touchManifestRelease(manifestPath);
|
|
197
|
+
console.log(` ✎ ${relative(REPO_ROOT, manifestPath)}`);
|
|
198
|
+
}
|
|
199
|
+
console.log('\nReview with `git diff modules/`, commit, then re-run `bun run publish`.');
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Auto-cascade for the common case: only modules drifted. Touches +
|
|
204
|
+
* commits + returns true if the operator approved continuing. Returns
|
|
205
|
+
* false if they aborted (caller should exit). Throws on git failure.
|
|
206
|
+
*
|
|
207
|
+
* Confirmation is gated by `autoYes` — when -y is set, the cascade
|
|
208
|
+
* runs without prompting. When false, the caller already prompted.
|
|
209
|
+
*/
|
|
210
|
+
export function autoTouchAndCommit(
|
|
211
|
+
report: PreflightReport,
|
|
212
|
+
spawnSyncFn: typeof spawnSync = spawnSync,
|
|
213
|
+
): { ok: boolean; recheck: PreflightReport | null } {
|
|
214
|
+
applyReleaseTouch(report.moduleStale);
|
|
215
|
+
const manifestPaths = report.moduleStale.map((i) => join(i.moduleDir, 'manifest.yml'));
|
|
216
|
+
const stageResult = spawnSyncFn('git', ['add', '--', ...manifestPaths], {
|
|
217
|
+
cwd: REPO_ROOT,
|
|
218
|
+
stdio: 'inherit',
|
|
219
|
+
});
|
|
220
|
+
if (stageResult.status !== 0) {
|
|
221
|
+
console.error('git add failed; resolve manually and re-run.');
|
|
222
|
+
return { ok: false, recheck: null };
|
|
223
|
+
}
|
|
224
|
+
const commitMessage = `modules: release-touch drifted manifests (${report.moduleStale
|
|
225
|
+
.map((i) => relative(REPO_ROOT, i.moduleDir).replace('modules/', ''))
|
|
226
|
+
.join(', ')})`;
|
|
227
|
+
const commitResult = spawnSyncFn('git', ['commit', '-m', commitMessage], {
|
|
228
|
+
cwd: REPO_ROOT,
|
|
229
|
+
stdio: 'inherit',
|
|
230
|
+
});
|
|
231
|
+
if (commitResult.status !== 0) {
|
|
232
|
+
console.error('git commit failed; resolve manually and re-run.');
|
|
233
|
+
return { ok: false, recheck: null };
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
const recheck = runPreflight();
|
|
237
|
+
return { ok: true, recheck };
|
|
238
|
+
}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for `celilo publish` — the planner/executor split per
|
|
3
|
+
* v2/PUBLILO_CLI.md Phase 2.
|
|
4
|
+
*
|
|
5
|
+
* The umbrella `PublishPlan` enumerates everything a publish run intends
|
|
6
|
+
* to do. It's produced by the pure planner (`plan.ts`) and consumed by
|
|
7
|
+
* the executor (`execute.ts`). The planner takes its inputs from
|
|
8
|
+
* discovery + flag parsing; the executor only mutates state described in
|
|
9
|
+
* the plan. Dry-run is "build plan, print it, exit"; a real publish is
|
|
10
|
+
* "build plan, confirm, execute."
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Subset of the npm package.json shape we touch. Kept narrow so the
|
|
15
|
+
* planner can't accidentally rely on fields not part of the contract.
|
|
16
|
+
*/
|
|
17
|
+
export interface PackageJson {
|
|
18
|
+
name?: string;
|
|
19
|
+
version?: string;
|
|
20
|
+
dependencies?: Record<string, string>;
|
|
21
|
+
devDependencies?: Record<string, string>;
|
|
22
|
+
peerDependencies?: Record<string, string>;
|
|
23
|
+
optionalDependencies?: Record<string, string>;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Single workspace package → npm-version mapping. Built once at the top
|
|
28
|
+
* of a publish run from each package's package.json#version. In alpha
|
|
29
|
+
* mode it gets tightened to the alpha versions before being threaded
|
|
30
|
+
* through to the workspace-dep rewriter, so cross-package alpha pins
|
|
31
|
+
* resolve to the alpha line.
|
|
32
|
+
*/
|
|
33
|
+
export type WorkspaceVersionMap = Map<string, string>;
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* What kind of publish run is this? Most per-package decisions
|
|
37
|
+
* (preflight gating, version rewrite, bun publish flags, post-publish
|
|
38
|
+
* verification expectations) flow from this single discriminator.
|
|
39
|
+
*
|
|
40
|
+
* - `normal`: bump real semver, publish to `@latest`, run Phase 2/3/4.
|
|
41
|
+
* - `alpha`: publish `X.Y.Z-alpha.N` to the `@alpha` dist-tag. Skip
|
|
42
|
+
* Phase 2 (consumer pins opt in via `@alpha` manually).
|
|
43
|
+
* Phase 3 only runs when `trackAlpha`. Phase 4 only when
|
|
44
|
+
* `alphaModules`.
|
|
45
|
+
* - `promote`: graduate a specific alpha to its base real version (e.g.
|
|
46
|
+
* `@celilo/e2e@0.7.14-alpha.3` → `@celilo/e2e@0.7.14`).
|
|
47
|
+
* Single package; Phase 2/3/4 run normally — this IS a
|
|
48
|
+
* real release.
|
|
49
|
+
*/
|
|
50
|
+
export type PublishMode =
|
|
51
|
+
| { kind: 'normal' }
|
|
52
|
+
| { kind: 'alpha'; trackAlpha: boolean; alphaModules: boolean }
|
|
53
|
+
| { kind: 'promote'; target: { name: string; version: string } };
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Parsed top-level flag bundle. Produced by `parseOptions` and threaded
|
|
57
|
+
* into the planner. Doesn't include flag-validation errors — those bail
|
|
58
|
+
* out before reaching here.
|
|
59
|
+
*/
|
|
60
|
+
export interface PublishOptions {
|
|
61
|
+
allowStale: boolean;
|
|
62
|
+
autoYes: boolean;
|
|
63
|
+
mode: PublishMode;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* One workspace package source committing past its package.json version.
|
|
68
|
+
* Surfaced by `checkStaleVersion` during preflight; blocks a normal
|
|
69
|
+
* publish unless --allow-stale.
|
|
70
|
+
*/
|
|
71
|
+
export interface StalenessIssue {
|
|
72
|
+
name: string;
|
|
73
|
+
pkg: string;
|
|
74
|
+
version: string;
|
|
75
|
+
lastSrcCommit: string;
|
|
76
|
+
lastPkgJsonCommit: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Module source committed past its manifest.yml. Surfaced by
|
|
81
|
+
* `checkModuleStale` during preflight; blocks a normal publish unless
|
|
82
|
+
* --allow-stale or `bun run publish --release-touch`.
|
|
83
|
+
*/
|
|
84
|
+
export interface ModuleStaleIssue {
|
|
85
|
+
moduleDir: string;
|
|
86
|
+
lastSrcCommit: string;
|
|
87
|
+
lastManifestCommit: string;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Snapshot of everything preflight learned about the working tree.
|
|
92
|
+
* Built once at the top of the run and threaded into the planner.
|
|
93
|
+
*/
|
|
94
|
+
export interface PreflightReport {
|
|
95
|
+
dirty: boolean;
|
|
96
|
+
dirtyOutput: string;
|
|
97
|
+
workspaceStale: StalenessIssue[];
|
|
98
|
+
moduleStale: ModuleStaleIssue[];
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Single workspace:^ → explicit-pin rewrite recorded by
|
|
103
|
+
* `rewriteWorkspaceDeps`. Used by the executor for both the actual
|
|
104
|
+
* package.json mutation and the post-publish verification step.
|
|
105
|
+
*/
|
|
106
|
+
export interface WorkspaceRewrite {
|
|
107
|
+
depName: string;
|
|
108
|
+
bucket: string;
|
|
109
|
+
oldSpec: string;
|
|
110
|
+
newSpec: string;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Optional knobs for the package.json rewriter. Lifecycle: the planner
|
|
115
|
+
* decides which to set per package (per-mode), the executor applies them
|
|
116
|
+
* to the live file just before `bun publish` and restores from the
|
|
117
|
+
* captured `original` after.
|
|
118
|
+
*/
|
|
119
|
+
export interface RewriteOptions {
|
|
120
|
+
/**
|
|
121
|
+
* Force the package's `version` field to this value before publish.
|
|
122
|
+
* Used by --alpha (sets `X.Y.Z-alpha.N`) and --promote (forces the
|
|
123
|
+
* base `X.Y.Z` even if source disagrees).
|
|
124
|
+
*/
|
|
125
|
+
targetVersion?: string;
|
|
126
|
+
/**
|
|
127
|
+
* Pin workspace deps to exact versions instead of `^`/`~`. Required for
|
|
128
|
+
* --alpha mode: pre-release semver excludes pre-release versions from
|
|
129
|
+
* caret ranges, so the only way to keep alpha consumers resolvable is
|
|
130
|
+
* to pin to the exact alpha that was just published.
|
|
131
|
+
*/
|
|
132
|
+
exactPins?: boolean;
|
|
133
|
+
/**
|
|
134
|
+
* Stamp a `gitHead` field on the published package.json so future
|
|
135
|
+
* `--alpha` runs can detect "no source change since prior alpha" and
|
|
136
|
+
* skip. bun publish doesn't populate gitHead automatically.
|
|
137
|
+
*/
|
|
138
|
+
gitHead?: string;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Per-package pre-publish work. Currently only `@celilo/e2e` triggers
|
|
143
|
+
* any of these (it ships netapps + registry server + caches inside its
|
|
144
|
+
* tarball), but the plan still enumerates them so dry-run can show
|
|
145
|
+
* what extra work the publish entails.
|
|
146
|
+
*/
|
|
147
|
+
export type PrePublishHookKind =
|
|
148
|
+
| 'registryServerBundle'
|
|
149
|
+
| 'rebuildE2eNetapps'
|
|
150
|
+
| 'stageE2ePublishCaches';
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Single workspace package planned to publish (or explicitly skip) in
|
|
154
|
+
* this run. The plan is built before any side effects so the dry-run
|
|
155
|
+
* can faithfully describe what `bun publish` would do.
|
|
156
|
+
*/
|
|
157
|
+
export interface WorkspaceItem {
|
|
158
|
+
/** Workspace path relative to REPO_ROOT (e.g. 'packages/e2e'). */
|
|
159
|
+
pkg: string;
|
|
160
|
+
/** npm package name (e.g. '@celilo/e2e'). */
|
|
161
|
+
name: string;
|
|
162
|
+
/** Version currently in this package's package.json. */
|
|
163
|
+
baseVersion: string;
|
|
164
|
+
/**
|
|
165
|
+
* What this run will publish. Same as `baseVersion` for normal mode,
|
|
166
|
+
* `X.Y.Z-alpha.N` for alpha mode, base-stripped for promote mode.
|
|
167
|
+
*/
|
|
168
|
+
versionToPublish: string;
|
|
169
|
+
/** npm dist-tag override (only `'alpha'` for alpha mode; undefined → `@latest`). */
|
|
170
|
+
tag?: 'alpha';
|
|
171
|
+
/**
|
|
172
|
+
* Rewrite recipe applied to the package's package.json immediately
|
|
173
|
+
* before `bun publish`. Restored from `originalPackageJson` after.
|
|
174
|
+
*/
|
|
175
|
+
rewriteOptions: RewriteOptions;
|
|
176
|
+
/** Pre-publish work to do (netapp rebuild, cache staging, etc.). */
|
|
177
|
+
hooks: PrePublishHookKind[];
|
|
178
|
+
/**
|
|
179
|
+
* If set, this package is explicitly NOT publishing this run (already
|
|
180
|
+
* on npm, source unchanged since prior alpha, etc.). The reason
|
|
181
|
+
* appears in the dry-run plan and the post-run summary.
|
|
182
|
+
*/
|
|
183
|
+
skipReason?: string;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Pin update planned for a single consumer package.json. Generated by
|
|
188
|
+
* walking the in-repo modules/, apps/, packages/, and any
|
|
189
|
+
* EXTERNAL_PROJECT_PATHS, matching `@celilo/*` deps to current npm
|
|
190
|
+
* latests. Produced in `--normal` and `--promote` modes; skipped in
|
|
191
|
+
* `--alpha` (consumers opt into the @alpha tag manually).
|
|
192
|
+
*/
|
|
193
|
+
export interface ConsumerPinItem {
|
|
194
|
+
/** Absolute path to the package.json. */
|
|
195
|
+
filePath: string;
|
|
196
|
+
/** What this run will rewrite in that file. */
|
|
197
|
+
updates: Array<{
|
|
198
|
+
bucket: 'dependencies' | 'devDependencies' | 'peerDependencies' | 'optionalDependencies';
|
|
199
|
+
depName: string;
|
|
200
|
+
oldSpec: string;
|
|
201
|
+
newSpec: string;
|
|
202
|
+
}>;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Single managed package planned to be force-pinned (or update-pulled)
|
|
207
|
+
* in bun's global install. `target` is the version we expect after the
|
|
208
|
+
* operation; `installed` is what's there now.
|
|
209
|
+
*/
|
|
210
|
+
export interface GlobalUpdateItem {
|
|
211
|
+
name: string;
|
|
212
|
+
installed: string | null;
|
|
213
|
+
target: string;
|
|
214
|
+
/**
|
|
215
|
+
* If true, the executor will run `bun add -g <name>@<target>` — force-
|
|
216
|
+
* pin to an exact version. Used for packages we just published this
|
|
217
|
+
* run (so the global ends up on the precise version, not whatever
|
|
218
|
+
* @latest resolves to a moment later).
|
|
219
|
+
*
|
|
220
|
+
* If false, the executor runs `bun update -g <name>` — chase whatever
|
|
221
|
+
* `@latest` is now. Used for managed packages that we didn't publish
|
|
222
|
+
* this run but might still be drifting in the global install.
|
|
223
|
+
*/
|
|
224
|
+
forcePin: boolean;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Single module planned to publish to the celilo registry. Phase 4 is
|
|
229
|
+
* the slimmest phase: revision selection and tarball construction live
|
|
230
|
+
* inside `celilo module publish` itself, so the plan only needs to
|
|
231
|
+
* enumerate the directories.
|
|
232
|
+
*/
|
|
233
|
+
export interface ModuleItem {
|
|
234
|
+
moduleDir: string;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Umbrella plan — the central data structure of Phase 2 of the publish
|
|
239
|
+
* CLI refactor (v2/PUBLILO_CLI.md). One plan covers all four phases of
|
|
240
|
+
* a publish run; the executor consumes it top-to-bottom.
|
|
241
|
+
*/
|
|
242
|
+
export interface PublishPlan {
|
|
243
|
+
mode: PublishMode;
|
|
244
|
+
options: PublishOptions;
|
|
245
|
+
preflight: PreflightReport;
|
|
246
|
+
/** Workspace npm publishes — Phase 1 of the publish flow. */
|
|
247
|
+
workspace: WorkspaceItem[];
|
|
248
|
+
/** Consumer package.json pin bumps — Phase 2. */
|
|
249
|
+
consumerPins: ConsumerPinItem[];
|
|
250
|
+
/** bun global install force-pins / refreshes — Phase 3. */
|
|
251
|
+
globalUpdate: GlobalUpdateItem[];
|
|
252
|
+
/** Modules to publish to the celilo registry — Phase 4. */
|
|
253
|
+
modulePublish: ModuleItem[];
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Aggregated outcome of a publish run. Mirrors the prior
|
|
258
|
+
* `runPublishPhase` return shape so the post-run summary can keep
|
|
259
|
+
* reporting the same way (published list + skipped list).
|
|
260
|
+
*/
|
|
261
|
+
export interface PublishResult {
|
|
262
|
+
published: Array<{ name: string; version: string }>;
|
|
263
|
+
skipped: string[];
|
|
264
|
+
}
|