@biffo/cli 0.69.1 → 0.69.3

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.
Files changed (2) hide show
  1. package/dist/index.js +90 -17
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -125,6 +125,31 @@ function readInstanceCoreVersion(cwd) {
125
125
  }
126
126
  return result.data.version;
127
127
  }
128
+ function planCoreVersionCleanup(cwd) {
129
+ const path = join(cwd, CORE_VERSION_FILE);
130
+ if (!existsSync(path)) return null;
131
+ const found = readFileSync(path, "utf8").trim();
132
+ if (!existsSync(join(cwd, INSTANCE_CORE_FILE))) {
133
+ return { path, action: "keep", found, reason: "no-authority" };
134
+ }
135
+ let authority;
136
+ try {
137
+ authority = readInstanceCoreVersion(cwd);
138
+ } catch {
139
+ return { path, action: "keep", found, reason: "no-authority" };
140
+ }
141
+ if (authority !== null && coreVersionsEqual(found, authority)) {
142
+ return { path, action: "delete", found };
143
+ }
144
+ return { path, action: "keep", found, reason: "repurposed" };
145
+ }
146
+ function coreVersionsEqual(a, b) {
147
+ try {
148
+ return compareCoreVersions(a, b) === 0;
149
+ } catch {
150
+ return false;
151
+ }
152
+ }
128
153
  function serializeInstanceCoreVersion(version) {
129
154
  parseCoreVersion(version);
130
155
  return `${JSON.stringify({ version }, null, 2)}
@@ -407,7 +432,7 @@ async function runCoreStatus(options) {
407
432
 
408
433
  // src/commands/core-upgrade.ts
409
434
  import { execSync as execSync2 } from "child_process";
410
- import { existsSync as existsSync10 } from "fs";
435
+ import { existsSync as existsSync10, rmSync as rmSync5 } from "fs";
411
436
  import { join as join11, resolve as resolve3 } from "path";
412
437
  import chalk4 from "chalk";
413
438
  import { execa as execa3 } from "execa";
@@ -2182,6 +2207,7 @@ async function runCoreUpgradeResolved(options, deps, cleanups) {
2182
2207
  console.log(` target: ${toVersion}
2183
2208
  `);
2184
2209
  const migrations = planMigrationCarry({ templateDir: theirsDir, instanceDir: options.cwd });
2210
+ const coreVersionCleanup = planCoreVersionCleanup(options.cwd);
2185
2211
  if (plan.changes.length === 0 && migrations.entries.length === 0) {
2186
2212
  log.success("Nothing to upgrade \u2014 the instance already matches the target for all core files.");
2187
2213
  return;
@@ -2196,6 +2222,7 @@ async function runCoreUpgradeResolved(options, deps, cleanups) {
2196
2222
  printBreakingChanges(breaking, options.apply === true);
2197
2223
  printPlan(plan);
2198
2224
  printMigrationCarry(migrations);
2225
+ printCoreVersionCleanup(coreVersionCleanup, options.apply === true);
2199
2226
  warnStaleFirstPartyCopies(options.cwd);
2200
2227
  console.log(
2201
2228
  `
@@ -2210,9 +2237,19 @@ async function runCoreUpgradeResolved(options, deps, cleanups) {
2210
2237
  );
2211
2238
  return;
2212
2239
  }
2213
- await applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVersion, breaking, theirsDir);
2240
+ await applyAndOpenPr(
2241
+ options,
2242
+ deps,
2243
+ plan,
2244
+ migrations,
2245
+ fromVersion,
2246
+ toVersion,
2247
+ breaking,
2248
+ theirsDir,
2249
+ coreVersionCleanup
2250
+ );
2214
2251
  }
2215
- async function applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVersion, breaking, theirsDir) {
2252
+ async function applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVersion, breaking, theirsDir, coreVersionCleanup) {
2216
2253
  if (breaking.length > 0 && !options.acknowledgeBreaking) {
2217
2254
  throw new Error(
2218
2255
  `This upgrade crosses ${breaking.length} documented breaking change(s): ${breaking.map((b) => b.version).join(", ")}. They are printed above and in ${UPGRADE_GUIDE_PATH}. Read what each one requires \u2014 some destroy data or need manual work after the deploy \u2014 then re-run with --acknowledge-breaking.`
@@ -2234,10 +2271,17 @@ async function applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVe
2234
2271
  const applied = applyUpgradePlan(options.cwd, plan, theirsDir);
2235
2272
  const carried = applyMigrationCarry(options.cwd, migrations);
2236
2273
  writeInstanceCoreVersion(options.cwd, toVersion);
2274
+ const cleanedCoreVersion = coreVersionCleanup?.action === "delete";
2275
+ if (cleanedCoreVersion && existsSync10(coreVersionCleanup.path)) {
2276
+ rmSync5(coreVersionCleanup.path);
2277
+ log.info(
2278
+ `Deleted orphaned ${CORE_VERSION_FILE} (inherited copy recording ${coreVersionCleanup.found}, superseded by biffo.core.json) \u2014 nothing reads it as an authority (#434).`
2279
+ );
2280
+ }
2237
2281
  log.step(
2238
2282
  2,
2239
2283
  4,
2240
- `Applied ${applied.written.length} change(s), ${applied.deleted.length} deletion(s), ${carried.length} new migration(s)`
2284
+ `Applied ${applied.written.length} change(s), ${applied.deleted.length + (cleanedCoreVersion ? 1 : 0)} deletion(s), ${carried.length} new migration(s)`
2241
2285
  );
2242
2286
  const lockfiles = await refreshInstanceLockfiles(options.cwd, applied, deps);
2243
2287
  await git.add(options.cwd, ["-A"]);
@@ -2257,7 +2301,16 @@ async function applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVe
2257
2301
  head: branch,
2258
2302
  base,
2259
2303
  title: `Upgrade Biffo core ${fromVersion} \u2192 ${toVersion}`,
2260
- body: buildPrBody(fromVersion, toVersion, plan, migrations, base, lockfiles, breaking)
2304
+ body: buildPrBody(
2305
+ fromVersion,
2306
+ toVersion,
2307
+ plan,
2308
+ migrations,
2309
+ base,
2310
+ lockfiles,
2311
+ breaking,
2312
+ cleanedCoreVersion ? coreVersionCleanup : null
2313
+ )
2261
2314
  });
2262
2315
  if (plan.conflicts.length > 0) {
2263
2316
  log.warn(`PR opened with ${plan.conflicts.length} conflict(s) to resolve: ${pr.url}`);
@@ -2265,7 +2318,7 @@ async function applyAndOpenPr(options, deps, plan, migrations, fromVersion, toVe
2265
2318
  log.success(`Opened PR #${pr.number}: ${pr.url}`);
2266
2319
  }
2267
2320
  }
2268
- function buildPrBody(from, to, plan, migrations, base = GLOBAL_DISPATCH_REF, lockfiles = [], breaking = []) {
2321
+ function buildPrBody(from, to, plan, migrations, base = GLOBAL_DISPATCH_REF, lockfiles = [], breaking = [], coreVersionCleanup = null) {
2269
2322
  const lines = [];
2270
2323
  if (breaking.length > 0) {
2271
2324
  lines.push(
@@ -2304,6 +2357,14 @@ function buildPrBody(from, to, plan, migrations, base = GLOBAL_DISPATCH_REF, loc
2304
2357
  "Review the DDL before merging: merging this PR runs these migrations against the database on the next deploy."
2305
2358
  );
2306
2359
  }
2360
+ if (coreVersionCleanup && coreVersionCleanup.action === "delete") {
2361
+ lines.push(
2362
+ "",
2363
+ "## Cleanup \u2014 removed orphaned `core.version`",
2364
+ "",
2365
+ `This instance still carried a \`${CORE_VERSION_FILE}\` file (recording \`${coreVersionCleanup.found}\`), inherited through GitHub template generation before the template retired it (#423). It matched the version \`biffo.core.json\` records, so it was the un-repurposed inherited copy, and nothing reads it as an authority \u2014 \`biffo.core.json\` wins every lookup. This upgrade **deleted it** (#434). The fallback readers in \`deploy.ts\` and \`core-upgrade.ts\` still read \`${CORE_VERSION_FILE}\` when it is present elsewhere; only this orphaned instance copy was removed.`
2366
+ );
2367
+ }
2307
2368
  const globalWorkflowChanges = plan.changes.filter(
2308
2369
  (c) => GLOBAL_DISPATCH_WORKFLOW_PATHS.includes(c.path)
2309
2370
  );
@@ -2374,6 +2435,18 @@ function printMigrationCarry(migrations) {
2374
2435
  console.log(` ${chalk4.green("migration".padEnd(15))} ${e.path}${suffix}`);
2375
2436
  }
2376
2437
  }
2438
+ function printCoreVersionCleanup(cleanup, applying) {
2439
+ if (cleanup === null) return;
2440
+ if (cleanup.action === "delete") {
2441
+ const verb = applying ? "delete" : "will delete";
2442
+ console.log(
2443
+ ` ${chalk4.red("cleanup".padEnd(15))} ${CORE_VERSION_FILE} ` + chalk4.dim(`(orphaned inherited copy recording ${cleanup.found}) \u2014 ${verb}`)
2444
+ );
2445
+ return;
2446
+ }
2447
+ const why = cleanup.reason === "repurposed" ? `does not match biffo.core.json \u2014 looks repurposed, keeping ${CORE_VERSION_FILE}` : `biffo.core.json absent or unparseable \u2014 no authority to check, keeping ${CORE_VERSION_FILE}`;
2448
+ console.log(` ${chalk4.dim("cleanup".padEnd(15))} ${chalk4.dim(`${cleanup.found}: ${why}`)}`);
2449
+ }
2377
2450
  function printPlan(plan) {
2378
2451
  const ordered = [...plan.conflicts, ...plan.changes.filter((c) => !c.conflicted)];
2379
2452
  for (const e of ordered) {
@@ -2921,7 +2994,7 @@ import {
2921
2994
  mkdirSync as mkdirSync4,
2922
2995
  readdirSync as readdirSync4,
2923
2996
  readFileSync as readFileSync7,
2924
- rmSync as rmSync5,
2997
+ rmSync as rmSync6,
2925
2998
  statSync as statSync2,
2926
2999
  writeFileSync as writeFileSync5
2927
3000
  } from "fs";
@@ -2989,7 +3062,7 @@ function markStepComplete(session, step) {
2989
3062
  }
2990
3063
  function deleteSession(projectName) {
2991
3064
  const path = sessionPath(projectName);
2992
- if (existsSync11(path)) rmSync5(path);
3065
+ if (existsSync11(path)) rmSync6(path);
2993
3066
  }
2994
3067
  function projectsDir() {
2995
3068
  return process.env["BIFFO_PROJECTS_DIR"] ?? join12(homedir(), ".biffo", "projects");
@@ -3011,7 +3084,7 @@ function loadProjectConfig(name) {
3011
3084
  }
3012
3085
  function deleteProjectConfig(name) {
3013
3086
  const path = join12(projectsDir(), `${name}.json`);
3014
- if (existsSync11(path)) rmSync5(path);
3087
+ if (existsSync11(path)) rmSync6(path);
3015
3088
  }
3016
3089
  function listProjectConfigs() {
3017
3090
  const dir = projectsDir();
@@ -4665,7 +4738,7 @@ import {
4665
4738
  mkdirSync as mkdirSync6,
4666
4739
  readdirSync as readdirSync8,
4667
4740
  readFileSync as readFileSync12,
4668
- rmSync as rmSync6,
4741
+ rmSync as rmSync7,
4669
4742
  statSync as statSync5,
4670
4743
  writeFileSync as writeFileSync6
4671
4744
  } from "fs";
@@ -4710,7 +4783,7 @@ function markSiblingStepComplete(session, step) {
4710
4783
  }
4711
4784
  function deleteSiblingSession(projectName) {
4712
4785
  const path = sessionPath2(projectName);
4713
- if (existsSync18(path)) rmSync6(path);
4786
+ if (existsSync18(path)) rmSync7(path);
4714
4787
  }
4715
4788
 
4716
4789
  // src/commands/sibling-create.ts
@@ -6717,7 +6790,7 @@ async function runPluginSyncMigrations(name, options, deps) {
6717
6790
  }
6718
6791
 
6719
6792
  // src/commands/plugin-uninstall.ts
6720
- import { existsSync as existsSync26, readFileSync as readFileSync19, rmSync as rmSync7 } from "fs";
6793
+ import { existsSync as existsSync26, readFileSync as readFileSync19, rmSync as rmSync8 } from "fs";
6721
6794
  import { join as join27, resolve as resolve15 } from "path";
6722
6795
  import chalk18 from "chalk";
6723
6796
  import { Command as Command18 } from "commander";
@@ -6789,10 +6862,10 @@ async function runPluginUninstall(name, options, deps) {
6789
6862
  `${options.cwd} is not a git repository \u2014 biffo plugin uninstall must be run from a Biffo project checkout.`
6790
6863
  );
6791
6864
  }
6792
- rmSync7(targetDir, { recursive: true, force: true });
6865
+ rmSync8(targetDir, { recursive: true, force: true });
6793
6866
  log.success(`Removed services/${name}/`);
6794
6867
  if (existsSync26(modulesDir)) {
6795
- rmSync7(modulesDir, { recursive: true, force: true });
6868
+ rmSync8(modulesDir, { recursive: true, force: true });
6796
6869
  log.success(`Removed modules/plugins/${name}/`);
6797
6870
  const wiring = syncPluginTerraform(options.cwd);
6798
6871
  stagePaths.push(...wiring.changedPaths);
@@ -6864,7 +6937,7 @@ function printDryRun5(name, version, stagePaths, keepData) {
6864
6937
  }
6865
6938
 
6866
6939
  // src/commands/plugin-upgrade.ts
6867
- import { cpSync as cpSync4, existsSync as existsSync27, mkdirSync as mkdirSync10, readFileSync as readFileSync20, rmSync as rmSync8 } from "fs";
6940
+ import { cpSync as cpSync4, existsSync as existsSync27, mkdirSync as mkdirSync10, readFileSync as readFileSync20, rmSync as rmSync9 } from "fs";
6868
6941
  import { join as join28, relative as relative5, resolve as resolve16 } from "path";
6869
6942
  import chalk19 from "chalk";
6870
6943
  import { Command as Command19 } from "commander";
@@ -6939,13 +7012,13 @@ async function runPluginUpgrade(target, options, deps) {
6939
7012
  log.success(
6940
7013
  `Manifest valid \u2014 ${manifest.tables.length} table(s), ${manifest.api_routes.length} route(s)`
6941
7014
  );
6942
- rmSync8(targetDir, { recursive: true, force: true });
7015
+ rmSync9(targetDir, { recursive: true, force: true });
6943
7016
  mkdirSync10(targetDir, { recursive: true });
6944
7017
  cpSync4(tmpDir, targetDir, { recursive: true });
6945
7018
  log.success(`Upgraded plugin source at services/${entry.name}/`);
6946
7019
  const stagePaths = [`services/${entry.name}`];
6947
7020
  if (existsSync27(modulesDir)) {
6948
- rmSync8(modulesDir, { recursive: true, force: true });
7021
+ rmSync9(modulesDir, { recursive: true, force: true });
6949
7022
  }
6950
7023
  const tfSourceDir = join28(targetDir, "terraform");
6951
7024
  if (existsSync27(tfSourceDir)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@biffo/cli",
3
- "version": "0.69.1",
3
+ "version": "0.69.3",
4
4
  "description": "Biffo project scaffolding CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",