@databricks-solutions/lakebase-scm-utils 0.2.41 → 0.2.43

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 (76) hide show
  1. package/dist/scripts/github/index.cjs +3 -1
  2. package/dist/scripts/github/index.js +3 -1
  3. package/dist/scripts/github/pr.cli.cjs +3 -1
  4. package/dist/scripts/github/pr.cli.js +3 -1
  5. package/dist/scripts/index.cjs +84 -21
  6. package/dist/scripts/index.d.cts +1 -1
  7. package/dist/scripts/index.d.ts +1 -1
  8. package/dist/scripts/index.js +76 -15
  9. package/dist/scripts/lakebase/branch.cli.cjs +3 -1
  10. package/dist/scripts/lakebase/branch.cli.js +3 -1
  11. package/dist/scripts/lakebase/ci-app-endpoint.cli.cjs +3 -1
  12. package/dist/scripts/lakebase/ci-app-endpoint.cli.js +3 -1
  13. package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +5 -3
  14. package/dist/scripts/lakebase/ci-resolve-branch.cli.js +5 -3
  15. package/dist/scripts/lakebase/collapse-heads.cli.cjs +5 -3
  16. package/dist/scripts/lakebase/collapse-heads.cli.js +5 -3
  17. package/dist/scripts/lakebase/cut-backup.cli.cjs +3 -1
  18. package/dist/scripts/lakebase/cut-backup.cli.js +3 -1
  19. package/dist/scripts/lakebase/cut-tier.cli.cjs +3 -1
  20. package/dist/scripts/lakebase/cut-tier.cli.js +3 -1
  21. package/dist/scripts/lakebase/detect-language.cli.cjs +5 -3
  22. package/dist/scripts/lakebase/detect-language.cli.js +5 -3
  23. package/dist/scripts/lakebase/doctor.cli.cjs +5 -3
  24. package/dist/scripts/lakebase/doctor.cli.js +5 -3
  25. package/dist/scripts/lakebase/get-connection.cli.cjs +5 -3
  26. package/dist/scripts/lakebase/get-connection.cli.js +5 -3
  27. package/dist/scripts/lakebase/index.cjs +84 -21
  28. package/dist/scripts/lakebase/index.d.cts +21 -1
  29. package/dist/scripts/lakebase/index.d.ts +21 -1
  30. package/dist/scripts/lakebase/index.js +76 -15
  31. package/dist/scripts/lakebase/infra-runner.cli.cjs +5 -3
  32. package/dist/scripts/lakebase/infra-runner.cli.js +5 -3
  33. package/dist/scripts/lakebase/new-migration.cli.cjs +5 -3
  34. package/dist/scripts/lakebase/new-migration.cli.js +5 -3
  35. package/dist/scripts/lakebase/schema-diff.cli.cjs +5 -3
  36. package/dist/scripts/lakebase/schema-diff.cli.js +5 -3
  37. package/dist/scripts/lakebase/schema-migrate.cli.cjs +5 -3
  38. package/dist/scripts/lakebase/schema-migrate.cli.js +5 -3
  39. package/dist/scripts/lakebase/scm-abandon-feature.cli.cjs +37 -1
  40. package/dist/scripts/lakebase/scm-abandon-feature.cli.js +37 -1
  41. package/dist/scripts/lakebase/scm-adopt-state.cli.cjs +37 -1
  42. package/dist/scripts/lakebase/scm-adopt-state.cli.js +37 -1
  43. package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +45 -9
  44. package/dist/scripts/lakebase/scm-claim-feature.cli.js +39 -3
  45. package/dist/scripts/lakebase/scm-cleanup.cli.cjs +3 -1
  46. package/dist/scripts/lakebase/scm-cleanup.cli.js +3 -1
  47. package/dist/scripts/lakebase/scm-doctor.cli.cjs +56 -29
  48. package/dist/scripts/lakebase/scm-doctor.cli.js +50 -23
  49. package/dist/scripts/lakebase/scm-feature-branch.cli.cjs +1 -0
  50. package/dist/scripts/lakebase/scm-feature-branch.cli.js +1 -0
  51. package/dist/scripts/lakebase/scm-merge.cli.cjs +61 -9
  52. package/dist/scripts/lakebase/scm-merge.cli.js +55 -3
  53. package/dist/scripts/lakebase/scm-prepare-pr.cli.cjs +34 -0
  54. package/dist/scripts/lakebase/scm-prepare-pr.cli.js +34 -0
  55. package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +6 -3
  56. package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +6 -3
  57. package/dist/scripts/lakebase/scm-recover-orphans.cli.cjs +37 -1
  58. package/dist/scripts/lakebase/scm-recover-orphans.cli.js +37 -1
  59. package/dist/scripts/lakebase/scm-state.cli.cjs +5 -4
  60. package/dist/scripts/lakebase/scm-state.cli.js +4 -3
  61. package/dist/scripts/lakebase/scm-wait-ci.cli.cjs +34 -0
  62. package/dist/scripts/lakebase/scm-wait-ci.cli.js +34 -0
  63. package/dist/scripts/util/index.cjs +5 -3
  64. package/dist/scripts/util/index.js +5 -3
  65. package/package.json +1 -1
  66. package/scripts/lakebase/databricks-cli.ts +7 -1
  67. package/scripts/lakebase/enable-e2e.ts +19 -3
  68. package/scripts/lakebase/scm-doctor.ts +1 -12
  69. package/scripts/lakebase/scm-merge.ts +36 -0
  70. package/scripts/lakebase/scm-workflow-state.ts +49 -0
  71. package/templates/project/common/.github/workflows/merge.yml +17 -6
  72. package/templates/project/common/.github/workflows/pr.yml +17 -6
  73. package/templates/project/common/.gitignore.base +8 -0
  74. package/templates/project/common/scripts/run-tests.sh +18 -1
  75. package/templates/project/python/tests/__pycache__/conftest.cpython-314.pyc +0 -0
  76. package/templates/project/python/tests/conftest.py +10 -3
@@ -1485,7 +1485,6 @@ function isCliEntry(importMetaUrl) {
1485
1485
  // scripts/lakebase/scm-doctor.ts
1486
1486
  init_esm_shims();
1487
1487
  import * as fs13 from "fs";
1488
- import { execFileSync as execFileSync5 } from "child_process";
1489
1488
  import * as path14 from "path";
1490
1489
 
1491
1490
  // scripts/lakebase/branch-utils.ts
@@ -1759,7 +1758,9 @@ function resolveProfile(opts) {
1759
1758
  function buildInvocation(args, opts) {
1760
1759
  const base = opts.env ?? process.env;
1761
1760
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
1762
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
1761
+ const env = { ...base };
1762
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
1763
+ delete env.DATABRICKS_WORKSPACE_ID;
1763
1764
  const profile = resolveProfile(opts);
1764
1765
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
1765
1766
  return { argv, env, profile };
@@ -8680,6 +8681,39 @@ init_esm_shims();
8680
8681
  init_esm_shims();
8681
8682
  import * as fs3 from "fs";
8682
8683
  import * as path3 from "path";
8684
+ import { execFileSync as execFileSync4 } from "child_process";
8685
+ function isGitTracked(projectDir, rel) {
8686
+ try {
8687
+ execFileSync4("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8688
+ return true;
8689
+ } catch {
8690
+ return false;
8691
+ }
8692
+ }
8693
+ function ensureWorkflowStateUntracked(projectDir) {
8694
+ const rel = ".lakebase/workflow-state.json";
8695
+ try {
8696
+ if (isGitTracked(projectDir, rel)) {
8697
+ execFileSync4("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8698
+ }
8699
+ } catch {
8700
+ }
8701
+ try {
8702
+ const gitignore = path3.join(projectDir, ".gitignore");
8703
+ const existing = fs3.existsSync(gitignore) ? fs3.readFileSync(gitignore, "utf8") : "";
8704
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
8705
+ const sep3 = existing === "" || existing.endsWith("\n") ? "" : "\n";
8706
+ fs3.appendFileSync(
8707
+ gitignore,
8708
+ `${sep3}# Runtime SCM claim state (per working tree): a branch checkout must never restore
8709
+ # a stale committed claim over the live one (issue #203 / Finding 28).
8710
+ ${rel}
8711
+ `
8712
+ );
8713
+ }
8714
+ } catch {
8715
+ }
8716
+ }
8683
8717
  var SCM_STATES = [
8684
8718
  "scaffold-complete",
8685
8719
  "feature-claimed",
@@ -8726,6 +8760,7 @@ function writeWorkflowState(projectDir, state) {
8726
8760
  throw new Error(`Refusing to write invalid SCM state:
8727
8761
  ${summary}`);
8728
8762
  }
8763
+ ensureWorkflowStateUntracked(projectDir);
8729
8764
  const dir = path3.join(projectDir, ".lakebase");
8730
8765
  fs3.mkdirSync(dir, { recursive: true });
8731
8766
  const target = stateFilePath(projectDir);
@@ -9019,7 +9054,7 @@ init_esm_shims();
9019
9054
  init_esm_shims();
9020
9055
  import * as fs5 from "fs";
9021
9056
  import * as path5 from "path";
9022
- import { execFileSync as execFileSync4 } from "child_process";
9057
+ import { execFileSync as execFileSync5 } from "child_process";
9023
9058
 
9024
9059
  // scripts/lakebase/branch-create.ts
9025
9060
  init_esm_shims();
@@ -9340,8 +9375,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
9340
9375
  var cached;
9341
9376
  function substrateSelfVersion() {
9342
9377
  if (cached !== void 0) return cached;
9343
- if ("0.2.41".length > 0) {
9344
- cached = "0.2.41";
9378
+ if ("0.2.43".length > 0) {
9379
+ cached = "0.2.43";
9345
9380
  return cached;
9346
9381
  }
9347
9382
  cached = "unknown";
@@ -9530,7 +9565,7 @@ async function isDirty(args) {
9530
9565
 
9531
9566
  // scripts/lakebase/paired-branch.ts
9532
9567
  function gitCurrentBranch(cwd) {
9533
- return execFileSync4("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
9568
+ return execFileSync5("git", ["rev-parse", "--abbrev-ref", "HEAD"], {
9534
9569
  cwd,
9535
9570
  encoding: "utf8",
9536
9571
  stdio: ["ignore", "pipe", "pipe"],
@@ -9539,7 +9574,7 @@ function gitCurrentBranch(cwd) {
9539
9574
  }
9540
9575
  function gitHasLocalBranch(cwd, branch) {
9541
9576
  try {
9542
- execFileSync4("git", ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], {
9577
+ execFileSync5("git", ["rev-parse", "--verify", "--quiet", `refs/heads/${branch}`], {
9543
9578
  cwd,
9544
9579
  stdio: "ignore",
9545
9580
  timeout: KIT_TIMEOUTS.gitDefault
@@ -9551,7 +9586,7 @@ function gitHasLocalBranch(cwd, branch) {
9551
9586
  }
9552
9587
  function gitCheckoutNewBranch(cwd, branch, startPoint) {
9553
9588
  const argv = startPoint ? ["checkout", "-b", branch, startPoint] : ["checkout", "-b", branch];
9554
- execFileSync4("git", argv, {
9589
+ execFileSync5("git", argv, {
9555
9590
  cwd,
9556
9591
  stdio: ["ignore", "pipe", "pipe"],
9557
9592
  timeout: KIT_TIMEOUTS.gitCheckout
@@ -9559,7 +9594,7 @@ function gitCheckoutNewBranch(cwd, branch, startPoint) {
9559
9594
  }
9560
9595
  function gitFetchBranch(cwd, remote, branch) {
9561
9596
  try {
9562
- execFileSync4("git", ["fetch", remote, branch], {
9597
+ execFileSync5("git", ["fetch", remote, branch], {
9563
9598
  cwd,
9564
9599
  stdio: ["ignore", "pipe", "pipe"],
9565
9600
  timeout: KIT_TIMEOUTS.gitNetwork
@@ -9569,7 +9604,7 @@ function gitFetchBranch(cwd, remote, branch) {
9569
9604
  }
9570
9605
  function gitRefExists(cwd, ref) {
9571
9606
  try {
9572
- execFileSync4("git", ["rev-parse", "--verify", "--quiet", ref], {
9607
+ execFileSync5("git", ["rev-parse", "--verify", "--quiet", ref], {
9573
9608
  cwd,
9574
9609
  stdio: ["ignore", "pipe", "pipe"],
9575
9610
  timeout: KIT_TIMEOUTS.gitDefault
@@ -9581,7 +9616,7 @@ function gitRefExists(cwd, ref) {
9581
9616
  }
9582
9617
  function gitIsAncestor(cwd, ancestor, descendant) {
9583
9618
  try {
9584
- execFileSync4("git", ["merge-base", "--is-ancestor", ancestor, descendant], {
9619
+ execFileSync5("git", ["merge-base", "--is-ancestor", ancestor, descendant], {
9585
9620
  cwd,
9586
9621
  stdio: ["ignore", "pipe", "pipe"],
9587
9622
  timeout: KIT_TIMEOUTS.gitDefault
@@ -9614,14 +9649,14 @@ async function assertCleanForFork(cwd, startPoint) {
9614
9649
  }
9615
9650
  function gitCheckoutExistingBranch(cwd, branch, force = false) {
9616
9651
  const argv = force ? ["checkout", "-f", branch] : ["checkout", branch];
9617
- execFileSync4("git", argv, {
9652
+ execFileSync5("git", argv, {
9618
9653
  cwd,
9619
9654
  stdio: ["ignore", "pipe", "pipe"],
9620
9655
  timeout: KIT_TIMEOUTS.gitCheckout
9621
9656
  });
9622
9657
  }
9623
9658
  function gitDeleteLocalBranch(cwd, branch, force = true) {
9624
- execFileSync4("git", ["branch", force ? "-D" : "-d", branch], {
9659
+ execFileSync5("git", ["branch", force ? "-D" : "-d", branch], {
9625
9660
  cwd,
9626
9661
  stdio: ["ignore", "pipe", "pipe"],
9627
9662
  timeout: KIT_TIMEOUTS.gitDefault
@@ -9629,7 +9664,7 @@ function gitDeleteLocalBranch(cwd, branch, force = true) {
9629
9664
  }
9630
9665
  function gitHasRemoteBranch(cwd, remote, branch) {
9631
9666
  try {
9632
- const out = execFileSync4(
9667
+ const out = execFileSync5(
9633
9668
  "git",
9634
9669
  ["ls-remote", "--exit-code", "--heads", remote, branch],
9635
9670
  { cwd, encoding: "utf8", stdio: ["ignore", "pipe", "pipe"], timeout: KIT_TIMEOUTS.gitNetwork }
@@ -9640,7 +9675,7 @@ function gitHasRemoteBranch(cwd, remote, branch) {
9640
9675
  }
9641
9676
  }
9642
9677
  function gitDeleteRemoteBranch(cwd, remote, branch) {
9643
- execFileSync4("git", ["push", remote, "--delete", branch], {
9678
+ execFileSync5("git", ["push", remote, "--delete", branch], {
9644
9679
  cwd,
9645
9680
  stdio: ["ignore", "pipe", "pipe"],
9646
9681
  timeout: KIT_TIMEOUTS.gitPush
@@ -11207,14 +11242,6 @@ function readEnv(projectDir) {
11207
11242
  function leafOf2(b) {
11208
11243
  return b.name.split("/").pop() ?? b.name;
11209
11244
  }
11210
- function isGitTracked(projectDir, rel) {
11211
- try {
11212
- execFileSync5("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
11213
- return true;
11214
- } catch {
11215
- return false;
11216
- }
11217
- }
11218
11245
  function worstOf(a, b) {
11219
11246
  const order = ["ok", "warn", "fail"];
11220
11247
  return order[Math.max(order.indexOf(a), order.indexOf(b))];
@@ -77726,6 +77726,7 @@ var CONVENTION_TIER_DEFAULTS = {
77726
77726
  init_cjs_shims();
77727
77727
  var fs6 = __toESM(require("fs"), 1);
77728
77728
  var path4 = __toESM(require("path"), 1);
77729
+ var import_node_child_process4 = require("child_process");
77729
77730
  var SCM_STATES = [
77730
77731
  "scaffold-complete",
77731
77732
  "feature-claimed",
@@ -120,6 +120,7 @@ var CONVENTION_TIER_DEFAULTS = {
120
120
  // scripts/lakebase/scm-workflow-state.ts
121
121
  import * as fs5 from "fs";
122
122
  import * as path4 from "path";
123
+ import { execFileSync as execFileSync4 } from "child_process";
123
124
  var SCM_STATES = [
124
125
  "scaffold-complete",
125
126
  "feature-claimed",
@@ -85758,7 +85758,9 @@ function resolveProfile(opts) {
85758
85758
  function buildInvocation(args, opts) {
85759
85759
  const base = opts.env ?? process.env;
85760
85760
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
85761
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
85761
+ const env = { ...base };
85762
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
85763
+ delete env.DATABRICKS_WORKSPACE_ID;
85762
85764
  const profile = resolveProfile(opts);
85763
85765
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
85764
85766
  return { argv, env, profile };
@@ -86257,6 +86259,39 @@ async function resolveGitBase(parentBranch, cwd) {
86257
86259
  init_cjs_shims();
86258
86260
  var fs3 = __toESM(require("fs"), 1);
86259
86261
  var path2 = __toESM(require("path"), 1);
86262
+ var import_node_child_process4 = require("child_process");
86263
+ function isGitTracked(projectDir, rel) {
86264
+ try {
86265
+ (0, import_node_child_process4.execFileSync)("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
86266
+ return true;
86267
+ } catch {
86268
+ return false;
86269
+ }
86270
+ }
86271
+ function ensureWorkflowStateUntracked(projectDir) {
86272
+ const rel = ".lakebase/workflow-state.json";
86273
+ try {
86274
+ if (isGitTracked(projectDir, rel)) {
86275
+ (0, import_node_child_process4.execFileSync)("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
86276
+ }
86277
+ } catch {
86278
+ }
86279
+ try {
86280
+ const gitignore = path2.join(projectDir, ".gitignore");
86281
+ const existing = fs3.existsSync(gitignore) ? fs3.readFileSync(gitignore, "utf8") : "";
86282
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
86283
+ const sep2 = existing === "" || existing.endsWith("\n") ? "" : "\n";
86284
+ fs3.appendFileSync(
86285
+ gitignore,
86286
+ `${sep2}# Runtime SCM claim state (per working tree): a branch checkout must never restore
86287
+ # a stale committed claim over the live one (issue #203 / Finding 28).
86288
+ ${rel}
86289
+ `
86290
+ );
86291
+ }
86292
+ } catch {
86293
+ }
86294
+ }
86260
86295
  var SCM_STATES = [
86261
86296
  "scaffold-complete",
86262
86297
  "feature-claimed",
@@ -86303,6 +86338,7 @@ function writeWorkflowState(projectDir, state) {
86303
86338
  throw new Error(`Refusing to write invalid SCM state:
86304
86339
  ${summary}`);
86305
86340
  }
86341
+ ensureWorkflowStateUntracked(projectDir);
86306
86342
  const dir = path2.join(projectDir, ".lakebase");
86307
86343
  fs3.mkdirSync(dir, { recursive: true });
86308
86344
  const target = stateFilePath(projectDir);
@@ -86475,6 +86511,20 @@ function orderForOutput(state) {
86475
86511
  }
86476
86512
 
86477
86513
  // scripts/lakebase/scm-merge.ts
86514
+ async function reconcileTierToOrigin(args) {
86515
+ const { cwd, tier } = args;
86516
+ try {
86517
+ const head = await getCurrentBranch({ cwd });
86518
+ if (head === tier) {
86519
+ await exec2(`git pull --ff-only`, { cwd, timeout: 3e4 });
86520
+ } else {
86521
+ await exec2(`git fetch origin ${shellEscape(`${tier}:${tier}`)}`, { cwd, timeout: 3e4 });
86522
+ }
86523
+ return null;
86524
+ } catch (err) {
86525
+ return `local reconcile of ${tier} to origin/${tier} failed: ${err instanceof Error ? err.message : String(err)}. Reconcile it by hand (git checkout ${tier} && git pull --ff-only).`;
86526
+ }
86527
+ }
86478
86528
  var ScmMergeError = class extends Error {
86479
86529
  constructor(message, code) {
86480
86530
  super(message);
@@ -86600,6 +86650,8 @@ async function mergeFeature(args) {
86600
86650
  }
86601
86651
  } else {
86602
86652
  headAfter = head || current.branch;
86653
+ const reconcileWarning = await reconcileTierToOrigin({ cwd: args.projectDir, tier: switchTo });
86654
+ if (reconcileWarning) warnings.push(reconcileWarning);
86603
86655
  }
86604
86656
  if (headAfter !== current.branch) {
86605
86657
  try {
@@ -88153,8 +88205,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
88153
88205
  var cached;
88154
88206
  function substrateSelfVersion() {
88155
88207
  if (cached !== void 0) return cached;
88156
- if ("0.2.41".length > 0) {
88157
- cached = "0.2.41";
88208
+ if ("0.2.43".length > 0) {
88209
+ cached = "0.2.43";
88158
88210
  return cached;
88159
88211
  }
88160
88212
  cached = "unknown";
@@ -88264,7 +88316,7 @@ var path5 = __toESM(require("path"), 1);
88264
88316
 
88265
88317
  // scripts/lakebase/schema-migrate-runners/alembic.ts
88266
88318
  init_cjs_shims();
88267
- var import_node_child_process4 = require("child_process");
88319
+ var import_node_child_process5 = require("child_process");
88268
88320
  var fs6 = __toESM(require("fs"), 1);
88269
88321
  var path4 = __toESM(require("path"), 1);
88270
88322
  function resolveAlembicBin(projectDir) {
@@ -88286,7 +88338,7 @@ function spawnAlembic(projectDir, args, dsn) {
88286
88338
  const env = { ...process.env };
88287
88339
  env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path4.delimiter);
88288
88340
  if (dsn) env.DATABASE_URL = dsn;
88289
- const child = (0, import_node_child_process4.spawn)(bin, args, {
88341
+ const child = (0, import_node_child_process5.spawn)(bin, args, {
88290
88342
  cwd: projectDir,
88291
88343
  env,
88292
88344
  stdio: ["ignore", "pipe", "pipe"]
@@ -88648,7 +88700,7 @@ var path7 = __toESM(require("path"), 1);
88648
88700
 
88649
88701
  // scripts/lakebase/schema-migrate-runners/flyway.ts
88650
88702
  init_cjs_shims();
88651
- var import_node_child_process5 = require("child_process");
88703
+ var import_node_child_process6 = require("child_process");
88652
88704
  var path6 = __toESM(require("path"), 1);
88653
88705
  function dsnToFlywayEnv(dsn) {
88654
88706
  const u = new URL(dsn);
@@ -88664,7 +88716,7 @@ function migrationsLocation(projectDir) {
88664
88716
  function runFlyway(ctx, args) {
88665
88717
  const { url, user, password } = dsnToFlywayEnv(ctx.dsn);
88666
88718
  return new Promise((resolve2, reject) => {
88667
- const child = (0, import_node_child_process5.spawn)(
88719
+ const child = (0, import_node_child_process6.spawn)(
88668
88720
  "flyway",
88669
88721
  ["-outputType=json", `-locations=${migrationsLocation(ctx.projectDir)}`, ...args],
88670
88722
  {
@@ -88901,7 +88953,7 @@ var path9 = __toESM(require("path"), 1);
88901
88953
 
88902
88954
  // scripts/lakebase/schema-migrate-runners/knex.ts
88903
88955
  init_cjs_shims();
88904
- var import_node_child_process6 = require("child_process");
88956
+ var import_node_child_process7 = require("child_process");
88905
88957
  var fs9 = __toESM(require("fs"), 1);
88906
88958
  var path8 = __toESM(require("path"), 1);
88907
88959
  var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
@@ -88923,7 +88975,7 @@ function spawnKnex(projectDir, args, dsn) {
88923
88975
  );
88924
88976
  return;
88925
88977
  }
88926
- const child = (0, import_node_child_process6.spawn)("npx", ["--no-install", "knex", "--knexfile", knexfile, ...args], {
88978
+ const child = (0, import_node_child_process7.spawn)("npx", ["--no-install", "knex", "--knexfile", knexfile, ...args], {
88927
88979
  cwd: projectDir,
88928
88980
  env: dsn ? { ...process.env, DATABASE_URL: dsn } : { ...process.env },
88929
88981
  stdio: ["ignore", "pipe", "pipe"]
@@ -8280,7 +8280,9 @@ function resolveProfile(opts) {
8280
8280
  function buildInvocation(args, opts) {
8281
8281
  const base = opts.env ?? process.env;
8282
8282
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
8283
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
8283
+ const env = { ...base };
8284
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
8285
+ delete env.DATABRICKS_WORKSPACE_ID;
8284
8286
  const profile = resolveProfile(opts);
8285
8287
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
8286
8288
  return { argv, env, profile };
@@ -8779,6 +8781,39 @@ async function resolveGitBase(parentBranch, cwd) {
8779
8781
  init_esm_shims();
8780
8782
  import * as fs3 from "fs";
8781
8783
  import * as path3 from "path";
8784
+ import { execFileSync as execFileSync4 } from "child_process";
8785
+ function isGitTracked(projectDir, rel) {
8786
+ try {
8787
+ execFileSync4("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8788
+ return true;
8789
+ } catch {
8790
+ return false;
8791
+ }
8792
+ }
8793
+ function ensureWorkflowStateUntracked(projectDir) {
8794
+ const rel = ".lakebase/workflow-state.json";
8795
+ try {
8796
+ if (isGitTracked(projectDir, rel)) {
8797
+ execFileSync4("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8798
+ }
8799
+ } catch {
8800
+ }
8801
+ try {
8802
+ const gitignore = path3.join(projectDir, ".gitignore");
8803
+ const existing = fs3.existsSync(gitignore) ? fs3.readFileSync(gitignore, "utf8") : "";
8804
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
8805
+ const sep2 = existing === "" || existing.endsWith("\n") ? "" : "\n";
8806
+ fs3.appendFileSync(
8807
+ gitignore,
8808
+ `${sep2}# Runtime SCM claim state (per working tree): a branch checkout must never restore
8809
+ # a stale committed claim over the live one (issue #203 / Finding 28).
8810
+ ${rel}
8811
+ `
8812
+ );
8813
+ }
8814
+ } catch {
8815
+ }
8816
+ }
8782
8817
  var SCM_STATES = [
8783
8818
  "scaffold-complete",
8784
8819
  "feature-claimed",
@@ -8825,6 +8860,7 @@ function writeWorkflowState(projectDir, state) {
8825
8860
  throw new Error(`Refusing to write invalid SCM state:
8826
8861
  ${summary}`);
8827
8862
  }
8863
+ ensureWorkflowStateUntracked(projectDir);
8828
8864
  const dir = path3.join(projectDir, ".lakebase");
8829
8865
  fs3.mkdirSync(dir, { recursive: true });
8830
8866
  const target = stateFilePath(projectDir);
@@ -8997,6 +9033,20 @@ function orderForOutput(state) {
8997
9033
  }
8998
9034
 
8999
9035
  // scripts/lakebase/scm-merge.ts
9036
+ async function reconcileTierToOrigin(args) {
9037
+ const { cwd, tier } = args;
9038
+ try {
9039
+ const head = await getCurrentBranch({ cwd });
9040
+ if (head === tier) {
9041
+ await exec2(`git pull --ff-only`, { cwd, timeout: 3e4 });
9042
+ } else {
9043
+ await exec2(`git fetch origin ${shellEscape(`${tier}:${tier}`)}`, { cwd, timeout: 3e4 });
9044
+ }
9045
+ return null;
9046
+ } catch (err) {
9047
+ return `local reconcile of ${tier} to origin/${tier} failed: ${err instanceof Error ? err.message : String(err)}. Reconcile it by hand (git checkout ${tier} && git pull --ff-only).`;
9048
+ }
9049
+ }
9000
9050
  var ScmMergeError = class extends Error {
9001
9051
  constructor(message, code) {
9002
9052
  super(message);
@@ -9122,6 +9172,8 @@ async function mergeFeature(args) {
9122
9172
  }
9123
9173
  } else {
9124
9174
  headAfter = head || current.branch;
9175
+ const reconcileWarning = await reconcileTierToOrigin({ cwd: args.projectDir, tier: switchTo });
9176
+ if (reconcileWarning) warnings.push(reconcileWarning);
9125
9177
  }
9126
9178
  if (headAfter !== current.branch) {
9127
9179
  try {
@@ -9306,8 +9358,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
9306
9358
  var cached;
9307
9359
  function substrateSelfVersion() {
9308
9360
  if (cached !== void 0) return cached;
9309
- if ("0.2.41".length > 0) {
9310
- cached = "0.2.41";
9361
+ if ("0.2.43".length > 0) {
9362
+ cached = "0.2.43";
9311
9363
  return cached;
9312
9364
  }
9313
9365
  cached = "unknown";
@@ -8436,6 +8436,39 @@ var RUNTIME_ARTIFACT_IGNORE = [
8436
8436
  init_cjs_shims();
8437
8437
  var fs3 = __toESM(require("fs"), 1);
8438
8438
  var path2 = __toESM(require("path"), 1);
8439
+ var import_node_child_process4 = require("child_process");
8440
+ function isGitTracked(projectDir, rel) {
8441
+ try {
8442
+ (0, import_node_child_process4.execFileSync)("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8443
+ return true;
8444
+ } catch {
8445
+ return false;
8446
+ }
8447
+ }
8448
+ function ensureWorkflowStateUntracked(projectDir) {
8449
+ const rel = ".lakebase/workflow-state.json";
8450
+ try {
8451
+ if (isGitTracked(projectDir, rel)) {
8452
+ (0, import_node_child_process4.execFileSync)("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8453
+ }
8454
+ } catch {
8455
+ }
8456
+ try {
8457
+ const gitignore = path2.join(projectDir, ".gitignore");
8458
+ const existing = fs3.existsSync(gitignore) ? fs3.readFileSync(gitignore, "utf8") : "";
8459
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
8460
+ const sep2 = existing === "" || existing.endsWith("\n") ? "" : "\n";
8461
+ fs3.appendFileSync(
8462
+ gitignore,
8463
+ `${sep2}# Runtime SCM claim state (per working tree): a branch checkout must never restore
8464
+ # a stale committed claim over the live one (issue #203 / Finding 28).
8465
+ ${rel}
8466
+ `
8467
+ );
8468
+ }
8469
+ } catch {
8470
+ }
8471
+ }
8439
8472
  var SCM_STATES = [
8440
8473
  "scaffold-complete",
8441
8474
  "feature-claimed",
@@ -8482,6 +8515,7 @@ function writeWorkflowState(projectDir, state) {
8482
8515
  throw new Error(`Refusing to write invalid SCM state:
8483
8516
  ${summary}`);
8484
8517
  }
8518
+ ensureWorkflowStateUntracked(projectDir);
8485
8519
  const dir = path2.join(projectDir, ".lakebase");
8486
8520
  fs3.mkdirSync(dir, { recursive: true });
8487
8521
  const target = stateFilePath(projectDir);
@@ -8424,6 +8424,39 @@ var RUNTIME_ARTIFACT_IGNORE = [
8424
8424
  init_esm_shims();
8425
8425
  import * as fs3 from "fs";
8426
8426
  import * as path3 from "path";
8427
+ import { execFileSync as execFileSync4 } from "child_process";
8428
+ function isGitTracked(projectDir, rel) {
8429
+ try {
8430
+ execFileSync4("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8431
+ return true;
8432
+ } catch {
8433
+ return false;
8434
+ }
8435
+ }
8436
+ function ensureWorkflowStateUntracked(projectDir) {
8437
+ const rel = ".lakebase/workflow-state.json";
8438
+ try {
8439
+ if (isGitTracked(projectDir, rel)) {
8440
+ execFileSync4("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
8441
+ }
8442
+ } catch {
8443
+ }
8444
+ try {
8445
+ const gitignore = path3.join(projectDir, ".gitignore");
8446
+ const existing = fs3.existsSync(gitignore) ? fs3.readFileSync(gitignore, "utf8") : "";
8447
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
8448
+ const sep2 = existing === "" || existing.endsWith("\n") ? "" : "\n";
8449
+ fs3.appendFileSync(
8450
+ gitignore,
8451
+ `${sep2}# Runtime SCM claim state (per working tree): a branch checkout must never restore
8452
+ # a stale committed claim over the live one (issue #203 / Finding 28).
8453
+ ${rel}
8454
+ `
8455
+ );
8456
+ }
8457
+ } catch {
8458
+ }
8459
+ }
8427
8460
  var SCM_STATES = [
8428
8461
  "scaffold-complete",
8429
8462
  "feature-claimed",
@@ -8470,6 +8503,7 @@ function writeWorkflowState(projectDir, state) {
8470
8503
  throw new Error(`Refusing to write invalid SCM state:
8471
8504
  ${summary}`);
8472
8505
  }
8506
+ ensureWorkflowStateUntracked(projectDir);
8473
8507
  const dir = path3.join(projectDir, ".lakebase");
8474
8508
  fs3.mkdirSync(dir, { recursive: true });
8475
8509
  const target = stateFilePath(projectDir);
@@ -77698,7 +77698,9 @@ function resolveProfile(opts) {
77698
77698
  function buildInvocation(args, opts) {
77699
77699
  const base = opts.env ?? process.env;
77700
77700
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
77701
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
77701
+ const env = { ...base };
77702
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
77703
+ delete env.DATABRICKS_WORKSPACE_ID;
77702
77704
  const profile = resolveProfile(opts);
77703
77705
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
77704
77706
  return { argv, env, profile };
@@ -79268,8 +79270,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
79268
79270
  var cached;
79269
79271
  function substrateSelfVersion() {
79270
79272
  if (cached !== void 0) return cached;
79271
- if ("0.2.41".length > 0) {
79272
- cached = "0.2.41";
79273
+ if ("0.2.43".length > 0) {
79274
+ cached = "0.2.43";
79273
79275
  return cached;
79274
79276
  }
79275
79277
  cached = "unknown";
@@ -80591,6 +80593,7 @@ async function reconcileTierBranch(args, deps = {}) {
80591
80593
  init_cjs_shims();
80592
80594
  var fs12 = __toESM(require("fs"), 1);
80593
80595
  var path11 = __toESM(require("path"), 1);
80596
+ var import_node_child_process6 = require("child_process");
80594
80597
  var SCM_STATES = [
80595
80598
  "scaffold-complete",
80596
80599
  "feature-claimed",
@@ -175,7 +175,9 @@ function resolveProfile(opts) {
175
175
  function buildInvocation(args, opts) {
176
176
  const base = opts.env ?? process.env;
177
177
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
178
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
178
+ const env = { ...base };
179
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
180
+ delete env.DATABRICKS_WORKSPACE_ID;
179
181
  const profile = resolveProfile(opts);
180
182
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
181
183
  return { argv, env, profile };
@@ -369,8 +371,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
369
371
  var cached;
370
372
  function substrateSelfVersion() {
371
373
  if (cached !== void 0) return cached;
372
- if ("0.2.41".length > 0) {
373
- cached = "0.2.41";
374
+ if ("0.2.43".length > 0) {
375
+ cached = "0.2.43";
374
376
  return cached;
375
377
  }
376
378
  cached = "unknown";
@@ -1682,6 +1684,7 @@ async function reconcileTierBranch(args, deps = {}) {
1682
1684
  // scripts/lakebase/scm-workflow-state.ts
1683
1685
  import * as fs11 from "fs";
1684
1686
  import * as path11 from "path";
1687
+ import { execFileSync as execFileSync3 } from "child_process";
1685
1688
  var SCM_STATES = [
1686
1689
  "scaffold-complete",
1687
1690
  "feature-claimed",
@@ -77816,7 +77816,9 @@ function resolveProfile(opts) {
77816
77816
  function buildInvocation(args, opts) {
77817
77817
  const base = opts.env ?? process.env;
77818
77818
  const trimmedHost = effectiveHost(opts)?.replace(/\/+$/, "");
77819
- const env = trimmedHost ? { ...base, DATABRICKS_HOST: trimmedHost } : base;
77819
+ const env = { ...base };
77820
+ if (trimmedHost) env.DATABRICKS_HOST = trimmedHost;
77821
+ delete env.DATABRICKS_WORKSPACE_ID;
77820
77822
  const profile = resolveProfile(opts);
77821
77823
  const argv = profile && !opts.noProfile && !args.includes("--profile") ? [...args, "--profile", profile] : args;
77822
77824
  return { argv, env, profile };
@@ -78759,6 +78761,39 @@ init_cjs_shims();
78759
78761
  init_cjs_shims();
78760
78762
  var fs6 = __toESM(require("fs"), 1);
78761
78763
  var path4 = __toESM(require("path"), 1);
78764
+ var import_node_child_process4 = require("child_process");
78765
+ function isGitTracked(projectDir, rel) {
78766
+ try {
78767
+ (0, import_node_child_process4.execFileSync)("git", ["ls-files", "--error-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
78768
+ return true;
78769
+ } catch {
78770
+ return false;
78771
+ }
78772
+ }
78773
+ function ensureWorkflowStateUntracked(projectDir) {
78774
+ const rel = ".lakebase/workflow-state.json";
78775
+ try {
78776
+ if (isGitTracked(projectDir, rel)) {
78777
+ (0, import_node_child_process4.execFileSync)("git", ["rm", "--cached", "--quiet", "--ignore-unmatch", "--", rel], { cwd: projectDir, stdio: "ignore" });
78778
+ }
78779
+ } catch {
78780
+ }
78781
+ try {
78782
+ const gitignore = path4.join(projectDir, ".gitignore");
78783
+ const existing = fs6.existsSync(gitignore) ? fs6.readFileSync(gitignore, "utf8") : "";
78784
+ if (!existing.split("\n").some((l) => l.trim() === rel)) {
78785
+ const sep = existing === "" || existing.endsWith("\n") ? "" : "\n";
78786
+ fs6.appendFileSync(
78787
+ gitignore,
78788
+ `${sep}# Runtime SCM claim state (per working tree): a branch checkout must never restore
78789
+ # a stale committed claim over the live one (issue #203 / Finding 28).
78790
+ ${rel}
78791
+ `
78792
+ );
78793
+ }
78794
+ } catch {
78795
+ }
78796
+ }
78762
78797
  var SCM_STATES = [
78763
78798
  "scaffold-complete",
78764
78799
  "feature-claimed",
@@ -78805,6 +78840,7 @@ function writeWorkflowState(projectDir, state) {
78805
78840
  throw new Error(`Refusing to write invalid SCM state:
78806
78841
  ${summary}`);
78807
78842
  }
78843
+ ensureWorkflowStateUntracked(projectDir);
78808
78844
  const dir = path4.join(projectDir, ".lakebase");
78809
78845
  fs6.mkdirSync(dir, { recursive: true });
78810
78846
  const target = stateFilePath(projectDir);