@databricks-solutions/lakebase-scm-utils 0.2.42 → 0.2.44
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/dist/scripts/github/index.cjs +21 -4
- package/dist/scripts/github/index.js +21 -4
- package/dist/scripts/github/pr.cli.cjs +21 -4
- package/dist/scripts/github/pr.cli.js +21 -4
- package/dist/scripts/index.cjs +58 -10
- package/dist/scripts/index.d.cts +1 -1
- package/dist/scripts/index.d.ts +1 -1
- package/dist/scripts/index.js +57 -10
- package/dist/scripts/lakebase/branch.cli.cjs +21 -4
- package/dist/scripts/lakebase/branch.cli.js +21 -4
- package/dist/scripts/lakebase/ci-app-endpoint.cli.cjs +21 -4
- package/dist/scripts/lakebase/ci-app-endpoint.cli.js +21 -4
- package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +23 -6
- package/dist/scripts/lakebase/ci-resolve-branch.cli.js +23 -6
- package/dist/scripts/lakebase/collapse-heads.cli.cjs +23 -6
- package/dist/scripts/lakebase/collapse-heads.cli.js +23 -6
- package/dist/scripts/lakebase/cut-backup.cli.cjs +21 -4
- package/dist/scripts/lakebase/cut-backup.cli.js +21 -4
- package/dist/scripts/lakebase/cut-tier.cli.cjs +21 -4
- package/dist/scripts/lakebase/cut-tier.cli.js +21 -4
- package/dist/scripts/lakebase/detect-language.cli.cjs +23 -6
- package/dist/scripts/lakebase/detect-language.cli.js +23 -6
- package/dist/scripts/lakebase/doctor.cli.cjs +23 -6
- package/dist/scripts/lakebase/doctor.cli.js +23 -6
- package/dist/scripts/lakebase/get-connection.cli.cjs +23 -6
- package/dist/scripts/lakebase/get-connection.cli.js +23 -6
- package/dist/scripts/lakebase/index.cjs +58 -10
- package/dist/scripts/lakebase/index.d.cts +17 -1
- package/dist/scripts/lakebase/index.d.ts +17 -1
- package/dist/scripts/lakebase/index.js +57 -10
- package/dist/scripts/lakebase/infra-runner.cli.cjs +23 -6
- package/dist/scripts/lakebase/infra-runner.cli.js +23 -6
- package/dist/scripts/lakebase/new-migration.cli.cjs +23 -6
- package/dist/scripts/lakebase/new-migration.cli.js +23 -6
- package/dist/scripts/lakebase/schema-diff.cli.cjs +23 -6
- package/dist/scripts/lakebase/schema-diff.cli.js +23 -6
- package/dist/scripts/lakebase/schema-migrate.cli.cjs +23 -6
- package/dist/scripts/lakebase/schema-migrate.cli.js +23 -6
- package/dist/scripts/lakebase/scm-abandon-feature.cli.cjs +21 -4
- package/dist/scripts/lakebase/scm-abandon-feature.cli.js +21 -4
- package/dist/scripts/lakebase/scm-adopt-state.cli.cjs +21 -4
- package/dist/scripts/lakebase/scm-adopt-state.cli.js +21 -4
- package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +23 -6
- package/dist/scripts/lakebase/scm-claim-feature.cli.js +23 -6
- package/dist/scripts/lakebase/scm-cleanup.cli.cjs +21 -4
- package/dist/scripts/lakebase/scm-cleanup.cli.js +21 -4
- package/dist/scripts/lakebase/scm-doctor.cli.cjs +23 -6
- package/dist/scripts/lakebase/scm-doctor.cli.js +23 -6
- package/dist/scripts/lakebase/scm-merge.cli.cjs +39 -6
- package/dist/scripts/lakebase/scm-merge.cli.js +39 -6
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +23 -6
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +23 -6
- package/dist/scripts/lakebase/scm-recover-orphans.cli.cjs +21 -4
- package/dist/scripts/lakebase/scm-recover-orphans.cli.js +21 -4
- package/dist/scripts/util/index.cjs +23 -6
- package/dist/scripts/util/index.js +23 -6
- package/package.json +1 -1
- package/scripts/lakebase/databricks-cli.ts +44 -4
- package/scripts/lakebase/runner-setup.ts +18 -2
- package/scripts/lakebase/scm-merge.ts +36 -0
- package/scripts/lakebase/secret-auth.ts +9 -2
- package/templates/project/common/.github/workflows/merge.yml +17 -6
- package/templates/project/common/.github/workflows/pr.yml +17 -6
- package/templates/project/common/scripts/run-tests.sh +10 -0
- package/templates/project/python/tests/__pycache__/conftest.cpython-314.pyc +0 -0
- package/templates/project/python/tests/conftest.py +10 -3
|
@@ -85791,16 +85791,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
85791
85791
|
}
|
|
85792
85792
|
async function runDatabricks(args, opts = {}) {
|
|
85793
85793
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
85794
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
85794
85795
|
try {
|
|
85795
|
-
|
|
85796
|
-
env,
|
|
85797
|
-
|
|
85798
|
-
});
|
|
85796
|
+
if (opts.input !== void 0) {
|
|
85797
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
85798
|
+
}
|
|
85799
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
85799
85800
|
return stdout.toString();
|
|
85800
85801
|
} catch (err) {
|
|
85801
85802
|
throw classifyDatabricksError(err, argv, profile);
|
|
85802
85803
|
}
|
|
85803
85804
|
}
|
|
85805
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
85806
|
+
return new Promise((resolve2, reject) => {
|
|
85807
|
+
const child = (0, import_node_child_process3.execFile)("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
85808
|
+
if (err) {
|
|
85809
|
+
err.stdout = String(stdout ?? "");
|
|
85810
|
+
err.stderr = String(stderr ?? "");
|
|
85811
|
+
reject(err);
|
|
85812
|
+
return;
|
|
85813
|
+
}
|
|
85814
|
+
resolve2(String(stdout ?? ""));
|
|
85815
|
+
});
|
|
85816
|
+
child.stdin?.on("error", () => {
|
|
85817
|
+
});
|
|
85818
|
+
child.stdin?.end(input);
|
|
85819
|
+
});
|
|
85820
|
+
}
|
|
85804
85821
|
function runDatabricksSync(args, opts = {}) {
|
|
85805
85822
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
85806
85823
|
try {
|
|
@@ -86511,6 +86528,20 @@ function orderForOutput(state) {
|
|
|
86511
86528
|
}
|
|
86512
86529
|
|
|
86513
86530
|
// scripts/lakebase/scm-merge.ts
|
|
86531
|
+
async function reconcileTierToOrigin(args) {
|
|
86532
|
+
const { cwd, tier } = args;
|
|
86533
|
+
try {
|
|
86534
|
+
const head = await getCurrentBranch({ cwd });
|
|
86535
|
+
if (head === tier) {
|
|
86536
|
+
await exec2(`git pull --ff-only`, { cwd, timeout: 3e4 });
|
|
86537
|
+
} else {
|
|
86538
|
+
await exec2(`git fetch origin ${shellEscape(`${tier}:${tier}`)}`, { cwd, timeout: 3e4 });
|
|
86539
|
+
}
|
|
86540
|
+
return null;
|
|
86541
|
+
} catch (err) {
|
|
86542
|
+
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).`;
|
|
86543
|
+
}
|
|
86544
|
+
}
|
|
86514
86545
|
var ScmMergeError = class extends Error {
|
|
86515
86546
|
constructor(message, code) {
|
|
86516
86547
|
super(message);
|
|
@@ -86636,6 +86667,8 @@ async function mergeFeature(args) {
|
|
|
86636
86667
|
}
|
|
86637
86668
|
} else {
|
|
86638
86669
|
headAfter = head || current.branch;
|
|
86670
|
+
const reconcileWarning = await reconcileTierToOrigin({ cwd: args.projectDir, tier: switchTo });
|
|
86671
|
+
if (reconcileWarning) warnings.push(reconcileWarning);
|
|
86639
86672
|
}
|
|
86640
86673
|
if (headAfter !== current.branch) {
|
|
86641
86674
|
try {
|
|
@@ -88189,8 +88222,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
88189
88222
|
var cached;
|
|
88190
88223
|
function substrateSelfVersion() {
|
|
88191
88224
|
if (cached !== void 0) return cached;
|
|
88192
|
-
if ("0.2.
|
|
88193
|
-
cached = "0.2.
|
|
88225
|
+
if ("0.2.44".length > 0) {
|
|
88226
|
+
cached = "0.2.44";
|
|
88194
88227
|
return cached;
|
|
88195
88228
|
}
|
|
88196
88229
|
cached = "unknown";
|
|
@@ -8313,16 +8313,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
8313
8313
|
}
|
|
8314
8314
|
async function runDatabricks(args, opts = {}) {
|
|
8315
8315
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
8316
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
8316
8317
|
try {
|
|
8317
|
-
|
|
8318
|
-
env,
|
|
8319
|
-
|
|
8320
|
-
});
|
|
8318
|
+
if (opts.input !== void 0) {
|
|
8319
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
8320
|
+
}
|
|
8321
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
8321
8322
|
return stdout.toString();
|
|
8322
8323
|
} catch (err) {
|
|
8323
8324
|
throw classifyDatabricksError(err, argv, profile);
|
|
8324
8325
|
}
|
|
8325
8326
|
}
|
|
8327
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
8328
|
+
return new Promise((resolve2, reject) => {
|
|
8329
|
+
const child = execFile("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
8330
|
+
if (err) {
|
|
8331
|
+
err.stdout = String(stdout ?? "");
|
|
8332
|
+
err.stderr = String(stderr ?? "");
|
|
8333
|
+
reject(err);
|
|
8334
|
+
return;
|
|
8335
|
+
}
|
|
8336
|
+
resolve2(String(stdout ?? ""));
|
|
8337
|
+
});
|
|
8338
|
+
child.stdin?.on("error", () => {
|
|
8339
|
+
});
|
|
8340
|
+
child.stdin?.end(input);
|
|
8341
|
+
});
|
|
8342
|
+
}
|
|
8326
8343
|
function runDatabricksSync(args, opts = {}) {
|
|
8327
8344
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
8328
8345
|
try {
|
|
@@ -9033,6 +9050,20 @@ function orderForOutput(state) {
|
|
|
9033
9050
|
}
|
|
9034
9051
|
|
|
9035
9052
|
// scripts/lakebase/scm-merge.ts
|
|
9053
|
+
async function reconcileTierToOrigin(args) {
|
|
9054
|
+
const { cwd, tier } = args;
|
|
9055
|
+
try {
|
|
9056
|
+
const head = await getCurrentBranch({ cwd });
|
|
9057
|
+
if (head === tier) {
|
|
9058
|
+
await exec2(`git pull --ff-only`, { cwd, timeout: 3e4 });
|
|
9059
|
+
} else {
|
|
9060
|
+
await exec2(`git fetch origin ${shellEscape(`${tier}:${tier}`)}`, { cwd, timeout: 3e4 });
|
|
9061
|
+
}
|
|
9062
|
+
return null;
|
|
9063
|
+
} catch (err) {
|
|
9064
|
+
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).`;
|
|
9065
|
+
}
|
|
9066
|
+
}
|
|
9036
9067
|
var ScmMergeError = class extends Error {
|
|
9037
9068
|
constructor(message, code) {
|
|
9038
9069
|
super(message);
|
|
@@ -9158,6 +9189,8 @@ async function mergeFeature(args) {
|
|
|
9158
9189
|
}
|
|
9159
9190
|
} else {
|
|
9160
9191
|
headAfter = head || current.branch;
|
|
9192
|
+
const reconcileWarning = await reconcileTierToOrigin({ cwd: args.projectDir, tier: switchTo });
|
|
9193
|
+
if (reconcileWarning) warnings.push(reconcileWarning);
|
|
9161
9194
|
}
|
|
9162
9195
|
if (headAfter !== current.branch) {
|
|
9163
9196
|
try {
|
|
@@ -9342,8 +9375,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
9342
9375
|
var cached;
|
|
9343
9376
|
function substrateSelfVersion() {
|
|
9344
9377
|
if (cached !== void 0) return cached;
|
|
9345
|
-
if ("0.2.
|
|
9346
|
-
cached = "0.2.
|
|
9378
|
+
if ("0.2.44".length > 0) {
|
|
9379
|
+
cached = "0.2.44";
|
|
9347
9380
|
return cached;
|
|
9348
9381
|
}
|
|
9349
9382
|
cached = "unknown";
|
|
@@ -77731,16 +77731,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
77731
77731
|
}
|
|
77732
77732
|
async function runDatabricks(args, opts = {}) {
|
|
77733
77733
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
77734
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
77734
77735
|
try {
|
|
77735
|
-
|
|
77736
|
-
env,
|
|
77737
|
-
|
|
77738
|
-
});
|
|
77736
|
+
if (opts.input !== void 0) {
|
|
77737
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
77738
|
+
}
|
|
77739
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
77739
77740
|
return stdout.toString();
|
|
77740
77741
|
} catch (err) {
|
|
77741
77742
|
throw classifyDatabricksError(err, argv, profile);
|
|
77742
77743
|
}
|
|
77743
77744
|
}
|
|
77745
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
77746
|
+
return new Promise((resolve2, reject) => {
|
|
77747
|
+
const child = (0, import_node_child_process2.execFile)("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
77748
|
+
if (err) {
|
|
77749
|
+
err.stdout = String(stdout ?? "");
|
|
77750
|
+
err.stderr = String(stderr ?? "");
|
|
77751
|
+
reject(err);
|
|
77752
|
+
return;
|
|
77753
|
+
}
|
|
77754
|
+
resolve2(String(stdout ?? ""));
|
|
77755
|
+
});
|
|
77756
|
+
child.stdin?.on("error", () => {
|
|
77757
|
+
});
|
|
77758
|
+
child.stdin?.end(input);
|
|
77759
|
+
});
|
|
77760
|
+
}
|
|
77744
77761
|
function runDatabricksSync(args, opts = {}) {
|
|
77745
77762
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
77746
77763
|
try {
|
|
@@ -79270,8 +79287,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
79270
79287
|
var cached;
|
|
79271
79288
|
function substrateSelfVersion() {
|
|
79272
79289
|
if (cached !== void 0) return cached;
|
|
79273
|
-
if ("0.2.
|
|
79274
|
-
cached = "0.2.
|
|
79290
|
+
if ("0.2.44".length > 0) {
|
|
79291
|
+
cached = "0.2.44";
|
|
79275
79292
|
return cached;
|
|
79276
79293
|
}
|
|
79277
79294
|
cached = "unknown";
|
|
@@ -208,16 +208,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
208
208
|
}
|
|
209
209
|
async function runDatabricks(args, opts = {}) {
|
|
210
210
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
211
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
211
212
|
try {
|
|
212
|
-
|
|
213
|
-
env,
|
|
214
|
-
|
|
215
|
-
});
|
|
213
|
+
if (opts.input !== void 0) {
|
|
214
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
215
|
+
}
|
|
216
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
216
217
|
return stdout.toString();
|
|
217
218
|
} catch (err) {
|
|
218
219
|
throw classifyDatabricksError(err, argv, profile);
|
|
219
220
|
}
|
|
220
221
|
}
|
|
222
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
223
|
+
return new Promise((resolve2, reject) => {
|
|
224
|
+
const child = execFile("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
225
|
+
if (err) {
|
|
226
|
+
err.stdout = String(stdout ?? "");
|
|
227
|
+
err.stderr = String(stderr ?? "");
|
|
228
|
+
reject(err);
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
resolve2(String(stdout ?? ""));
|
|
232
|
+
});
|
|
233
|
+
child.stdin?.on("error", () => {
|
|
234
|
+
});
|
|
235
|
+
child.stdin?.end(input);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
221
238
|
function runDatabricksSync(args, opts = {}) {
|
|
222
239
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
223
240
|
try {
|
|
@@ -371,8 +388,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
371
388
|
var cached;
|
|
372
389
|
function substrateSelfVersion() {
|
|
373
390
|
if (cached !== void 0) return cached;
|
|
374
|
-
if ("0.2.
|
|
375
|
-
cached = "0.2.
|
|
391
|
+
if ("0.2.44".length > 0) {
|
|
392
|
+
cached = "0.2.44";
|
|
376
393
|
return cached;
|
|
377
394
|
}
|
|
378
395
|
cached = "unknown";
|
|
@@ -77849,16 +77849,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
77849
77849
|
}
|
|
77850
77850
|
async function runDatabricks(args, opts = {}) {
|
|
77851
77851
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
77852
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
77852
77853
|
try {
|
|
77853
|
-
|
|
77854
|
-
env,
|
|
77855
|
-
|
|
77856
|
-
});
|
|
77854
|
+
if (opts.input !== void 0) {
|
|
77855
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
77856
|
+
}
|
|
77857
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
77857
77858
|
return stdout.toString();
|
|
77858
77859
|
} catch (err) {
|
|
77859
77860
|
throw classifyDatabricksError(err, argv, profile);
|
|
77860
77861
|
}
|
|
77861
77862
|
}
|
|
77863
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
77864
|
+
return new Promise((resolve2, reject) => {
|
|
77865
|
+
const child = (0, import_node_child_process2.execFile)("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
77866
|
+
if (err) {
|
|
77867
|
+
err.stdout = String(stdout ?? "");
|
|
77868
|
+
err.stderr = String(stderr ?? "");
|
|
77869
|
+
reject(err);
|
|
77870
|
+
return;
|
|
77871
|
+
}
|
|
77872
|
+
resolve2(String(stdout ?? ""));
|
|
77873
|
+
});
|
|
77874
|
+
child.stdin?.on("error", () => {
|
|
77875
|
+
});
|
|
77876
|
+
child.stdin?.end(input);
|
|
77877
|
+
});
|
|
77878
|
+
}
|
|
77862
77879
|
function runDatabricksSync(args, opts = {}) {
|
|
77863
77880
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
77864
77881
|
try {
|
|
@@ -321,16 +321,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
321
321
|
}
|
|
322
322
|
async function runDatabricks(args, opts = {}) {
|
|
323
323
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
324
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
324
325
|
try {
|
|
325
|
-
|
|
326
|
-
env,
|
|
327
|
-
|
|
328
|
-
});
|
|
326
|
+
if (opts.input !== void 0) {
|
|
327
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
328
|
+
}
|
|
329
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
329
330
|
return stdout.toString();
|
|
330
331
|
} catch (err) {
|
|
331
332
|
throw classifyDatabricksError(err, argv, profile);
|
|
332
333
|
}
|
|
333
334
|
}
|
|
335
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
336
|
+
return new Promise((resolve2, reject) => {
|
|
337
|
+
const child = execFile("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
338
|
+
if (err) {
|
|
339
|
+
err.stdout = String(stdout ?? "");
|
|
340
|
+
err.stderr = String(stderr ?? "");
|
|
341
|
+
reject(err);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
resolve2(String(stdout ?? ""));
|
|
345
|
+
});
|
|
346
|
+
child.stdin?.on("error", () => {
|
|
347
|
+
});
|
|
348
|
+
child.stdin?.end(input);
|
|
349
|
+
});
|
|
350
|
+
}
|
|
334
351
|
function runDatabricksSync(args, opts = {}) {
|
|
335
352
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
336
353
|
try {
|
|
@@ -1659,8 +1659,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
1659
1659
|
var cached;
|
|
1660
1660
|
function substrateSelfVersion() {
|
|
1661
1661
|
if (cached !== void 0) return cached;
|
|
1662
|
-
if ("0.2.
|
|
1663
|
-
cached = "0.2.
|
|
1662
|
+
if ("0.2.44".length > 0) {
|
|
1663
|
+
cached = "0.2.44";
|
|
1664
1664
|
return cached;
|
|
1665
1665
|
}
|
|
1666
1666
|
cached = "unknown";
|
|
@@ -1928,16 +1928,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
1928
1928
|
}
|
|
1929
1929
|
async function runDatabricks(args, opts = {}) {
|
|
1930
1930
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
1931
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
1931
1932
|
try {
|
|
1932
|
-
|
|
1933
|
-
env,
|
|
1934
|
-
|
|
1935
|
-
});
|
|
1933
|
+
if (opts.input !== void 0) {
|
|
1934
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
1935
|
+
}
|
|
1936
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
1936
1937
|
return stdout.toString();
|
|
1937
1938
|
} catch (err) {
|
|
1938
1939
|
throw classifyDatabricksError(err, argv, profile);
|
|
1939
1940
|
}
|
|
1940
1941
|
}
|
|
1942
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
1943
|
+
return new Promise((resolve, reject) => {
|
|
1944
|
+
const child = (0, import_node_child_process2.execFile)("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
1945
|
+
if (err) {
|
|
1946
|
+
err.stdout = String(stdout ?? "");
|
|
1947
|
+
err.stderr = String(stderr ?? "");
|
|
1948
|
+
reject(err);
|
|
1949
|
+
return;
|
|
1950
|
+
}
|
|
1951
|
+
resolve(String(stdout ?? ""));
|
|
1952
|
+
});
|
|
1953
|
+
child.stdin?.on("error", () => {
|
|
1954
|
+
});
|
|
1955
|
+
child.stdin?.end(input);
|
|
1956
|
+
});
|
|
1957
|
+
}
|
|
1941
1958
|
|
|
1942
1959
|
// scripts/github/secrets.ts
|
|
1943
1960
|
init_cjs_shims();
|
|
@@ -1630,8 +1630,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
1630
1630
|
var cached;
|
|
1631
1631
|
function substrateSelfVersion() {
|
|
1632
1632
|
if (cached !== void 0) return cached;
|
|
1633
|
-
if ("0.2.
|
|
1634
|
-
cached = "0.2.
|
|
1633
|
+
if ("0.2.44".length > 0) {
|
|
1634
|
+
cached = "0.2.44";
|
|
1635
1635
|
return cached;
|
|
1636
1636
|
}
|
|
1637
1637
|
cached = "unknown";
|
|
@@ -1899,16 +1899,33 @@ stdout: ${stdout}` : killed || signal ? `
|
|
|
1899
1899
|
}
|
|
1900
1900
|
async function runDatabricks(args, opts = {}) {
|
|
1901
1901
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
1902
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
1902
1903
|
try {
|
|
1903
|
-
|
|
1904
|
-
env,
|
|
1905
|
-
|
|
1906
|
-
});
|
|
1904
|
+
if (opts.input !== void 0) {
|
|
1905
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
1906
|
+
}
|
|
1907
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
1907
1908
|
return stdout.toString();
|
|
1908
1909
|
} catch (err) {
|
|
1909
1910
|
throw classifyDatabricksError(err, argv, profile);
|
|
1910
1911
|
}
|
|
1911
1912
|
}
|
|
1913
|
+
function execDatabricksWithStdin(argv, input, env, timeout) {
|
|
1914
|
+
return new Promise((resolve, reject) => {
|
|
1915
|
+
const child = execFile("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
1916
|
+
if (err) {
|
|
1917
|
+
err.stdout = String(stdout ?? "");
|
|
1918
|
+
err.stderr = String(stderr ?? "");
|
|
1919
|
+
reject(err);
|
|
1920
|
+
return;
|
|
1921
|
+
}
|
|
1922
|
+
resolve(String(stdout ?? ""));
|
|
1923
|
+
});
|
|
1924
|
+
child.stdin?.on("error", () => {
|
|
1925
|
+
});
|
|
1926
|
+
child.stdin?.end(input);
|
|
1927
|
+
});
|
|
1928
|
+
}
|
|
1912
1929
|
|
|
1913
1930
|
// scripts/github/secrets.ts
|
|
1914
1931
|
init_esm_shims();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@databricks-solutions/lakebase-scm-utils",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.44",
|
|
4
4
|
"description": "Lakebase SCM + substrate engine: database branching, paired-branch SCM workflows, connection/credential minting, schema migration, project scaffold + deploy primitives, and the git/github utility layer. Extracted from consort for portable, standalone consumption by lakebase-scm-extension and the SFTDD orchestration.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -36,6 +36,11 @@ export interface DatabricksCliOptions {
|
|
|
36
36
|
* subcommand. Set this for version/help probes so they work regardless of
|
|
37
37
|
* DATABRICKS_CONFIG_PROFILE. */
|
|
38
38
|
noProfile?: boolean;
|
|
39
|
+
/** Data to feed on the child's STDIN (async path only). Used to keep a
|
|
40
|
+
* credential OFF the command line: pass the secret in a `--json @/dev/stdin`
|
|
41
|
+
* body here instead of as a `--string-value <cred>` argv element, so it never
|
|
42
|
+
* appears in the process table / `ps`. */
|
|
43
|
+
input?: string;
|
|
39
44
|
}
|
|
40
45
|
|
|
41
46
|
/** A `databricks` CLI call failed. Message: `databricks <args> failed: <msg>\nstderr: <stderr>`. */
|
|
@@ -203,17 +208,52 @@ export function classifyDatabricksError(err: unknown, argv: string[], profile: s
|
|
|
203
208
|
/** Run the `databricks` CLI (async), returning stdout. */
|
|
204
209
|
export async function runDatabricks(args: string[], opts: DatabricksCliOptions = {}): Promise<string> {
|
|
205
210
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
211
|
+
const timeout = opts.timeout ?? KIT_TIMEOUTS.cliDefault;
|
|
206
212
|
try {
|
|
207
|
-
|
|
208
|
-
env,
|
|
209
|
-
|
|
210
|
-
});
|
|
213
|
+
if (opts.input !== undefined) {
|
|
214
|
+
return await execDatabricksWithStdin(argv, opts.input, env, timeout);
|
|
215
|
+
}
|
|
216
|
+
const { stdout } = await execFileP("databricks", argv, { env, timeout });
|
|
211
217
|
return stdout.toString();
|
|
212
218
|
} catch (err) {
|
|
213
219
|
throw classifyDatabricksError(err, argv, profile);
|
|
214
220
|
}
|
|
215
221
|
}
|
|
216
222
|
|
|
223
|
+
/**
|
|
224
|
+
* Run `databricks` feeding `input` on STDIN, so a credential can travel in a
|
|
225
|
+
* `--json @/dev/stdin` body instead of a `--string-value <cred>` argv element
|
|
226
|
+
* that leaks into the process table. Buffers stdout/stderr and shapes
|
|
227
|
+
* the result like execFileP so classifyDatabricksError reads it uniformly.
|
|
228
|
+
*
|
|
229
|
+
* The stdin write is GUARDED: a child that exits/rejects the body before we finish
|
|
230
|
+
* writing raises EPIPE on the pipe, which is an UNHANDLED 'error' (crash) unless we
|
|
231
|
+
* listen for it. We swallow the pipe error and let the child's own exit code + stderr
|
|
232
|
+
* be the verdict (guard the write against EPIPE).
|
|
233
|
+
*/
|
|
234
|
+
function execDatabricksWithStdin(
|
|
235
|
+
argv: string[],
|
|
236
|
+
input: string,
|
|
237
|
+
env: NodeJS.ProcessEnv,
|
|
238
|
+
timeout: number,
|
|
239
|
+
): Promise<string> {
|
|
240
|
+
return new Promise((resolve, reject) => {
|
|
241
|
+
const child = execFile("databricks", argv, { env, timeout }, (err, stdout, stderr) => {
|
|
242
|
+
if (err) {
|
|
243
|
+
(err as { stdout?: string; stderr?: string }).stdout = String(stdout ?? "");
|
|
244
|
+
(err as { stdout?: string; stderr?: string }).stderr = String(stderr ?? "");
|
|
245
|
+
reject(err);
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
resolve(String(stdout ?? ""));
|
|
249
|
+
});
|
|
250
|
+
// Guard the pipe: without this an EPIPE (child gone before we finish) is an
|
|
251
|
+
// uncaught exception; the child's exit/stderr is the real verdict.
|
|
252
|
+
child.stdin?.on("error", () => {});
|
|
253
|
+
child.stdin?.end(input);
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
|
|
217
257
|
/** Run the `databricks` CLI (sync), returning stdout. */
|
|
218
258
|
export function runDatabricksSync(args: string[], opts: DatabricksCliOptions = {}): string {
|
|
219
259
|
const { argv, env, profile } = buildInvocation(args, opts);
|
|
@@ -271,8 +271,24 @@ export async function setupRunner(args: SetupRunnerArgs): Promise<RunnerInfo> {
|
|
|
271
271
|
if (needsConfig) {
|
|
272
272
|
report("Registering runner with GitHub...");
|
|
273
273
|
const regToken = await createRegistrationToken(args.fullRepoName);
|
|
274
|
-
|
|
275
|
-
|
|
274
|
+
// Invoke config.sh with an argv array (execFileSync), NOT a shell-interpolated
|
|
275
|
+
// string (execSync). config.sh is GitHub's runner binary and only accepts the
|
|
276
|
+
// registration token as `--token <tok>`, so the token is unavoidably on its argv
|
|
277
|
+
// (a full off-`ps` fix would need the JIT-runner API — disproportionate for a
|
|
278
|
+
// SHORT-LIVED (~1h) reg token). But dropping the `/bin/sh -c` wrapper removes the
|
|
279
|
+
// extra shell process that also carried the token, closes the shell-trace /
|
|
280
|
+
// process-accounting exposure, and eliminates any shell-injection surface on the
|
|
281
|
+
// interpolated url/name.
|
|
282
|
+
cp.execFileSync(
|
|
283
|
+
"./config.sh",
|
|
284
|
+
[
|
|
285
|
+
"--url", `https://github.com/${args.fullRepoName}`,
|
|
286
|
+
"--token", regToken,
|
|
287
|
+
"--name", name,
|
|
288
|
+
"--labels", "self-hosted",
|
|
289
|
+
"--unattended",
|
|
290
|
+
"--replace",
|
|
291
|
+
],
|
|
276
292
|
{ cwd: dir, timeout: KIT_TIMEOUTS.cliLong }
|
|
277
293
|
);
|
|
278
294
|
}
|
|
@@ -21,6 +21,35 @@ import { pollUntil } from "../util/poll-until.js";
|
|
|
21
21
|
import { exec } from "../util/exec.js";
|
|
22
22
|
import { getCurrentBranch } from "../git/inspect.js";
|
|
23
23
|
import { resolveGitBase } from "./scm-git-base.js";
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Fast-forward the local tier ref to origin/<tier> after a remote merge, WITHOUT
|
|
27
|
+
* needing a checkout. A promote interrupted after the remote merge (e.g. a
|
|
28
|
+
* downstream migrate failure) otherwise leaves the local tier BEHIND, so the
|
|
29
|
+
* next sprint plans on stale code and the next push rejects non-fast-forward.
|
|
30
|
+
* Mechanism by head position: when HEAD IS the tier, `git pull --ff-only` syncs
|
|
31
|
+
* ref + working tree; otherwise `git fetch origin <tier>:<tier>` fast-forwards
|
|
32
|
+
* the local ref in place (git refuses fetch-into-current-branch, hence the
|
|
33
|
+
* split). Returns null on success; a warning string when the sync fails (e.g.
|
|
34
|
+
* not a fast-forward because the local tier has its own commits), never throws.
|
|
35
|
+
*/
|
|
36
|
+
export async function reconcileTierToOrigin(args: { cwd: string; tier: string }): Promise<string | null> {
|
|
37
|
+
const { cwd, tier } = args;
|
|
38
|
+
try {
|
|
39
|
+
const head = await getCurrentBranch({ cwd });
|
|
40
|
+
if (head === tier) {
|
|
41
|
+
await exec(`git pull --ff-only`, { cwd, timeout: 30_000 });
|
|
42
|
+
} else {
|
|
43
|
+
await exec(`git fetch origin ${shellEscape(`${tier}:${tier}`)}`, { cwd, timeout: 30_000 });
|
|
44
|
+
}
|
|
45
|
+
return null;
|
|
46
|
+
} catch (err) {
|
|
47
|
+
return (
|
|
48
|
+
`local reconcile of ${tier} to origin/${tier} failed: ${err instanceof Error ? err.message : String(err)}. ` +
|
|
49
|
+
`Reconcile it by hand (git checkout ${tier} && git pull --ff-only).`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
24
53
|
import {
|
|
25
54
|
readWorkflowState,
|
|
26
55
|
writeWorkflowState,
|
|
@@ -328,6 +357,13 @@ export async function mergeFeature(args: MergeArgs): Promise<MergeResult> {
|
|
|
328
357
|
}
|
|
329
358
|
} else {
|
|
330
359
|
headAfter = head || current.branch;
|
|
360
|
+
// HEAD isn't the feature branch, so the checkout+ff path above didn't run.
|
|
361
|
+
// Reconcile the local tier ref to origin anyway (no checkout needed): a
|
|
362
|
+
// promote interrupted after the remote merge must not leave the tier behind
|
|
363
|
+
// (the stockflow F1 case: local staging missed the merge, the next push
|
|
364
|
+
// rejected non-fast-forward). Best-effort; a failure is a warning, not a throw.
|
|
365
|
+
const reconcileWarning = await reconcileTierToOrigin({ cwd: args.projectDir, tier: switchTo });
|
|
366
|
+
if (reconcileWarning) warnings.push(reconcileWarning);
|
|
331
367
|
}
|
|
332
368
|
if (headAfter !== current.branch) {
|
|
333
369
|
try {
|
|
@@ -100,10 +100,17 @@ export async function ensureLakebaseSecretAuth(
|
|
|
100
100
|
throw new Error("databricks tokens create returned no token_value");
|
|
101
101
|
}
|
|
102
102
|
|
|
103
|
-
// 3. Store the PAT
|
|
104
|
-
|
|
103
|
+
// 3. Store the PAT. Feed the secret in a `--json @/dev/stdin` body (via opts.input)
|
|
104
|
+
// rather than a `--string-value <pat>` argv element, so the 90-day user PAT never
|
|
105
|
+
// appears in the process table / `ps`. The JSON MUST use `string_value`
|
|
106
|
+
// (not bytes_value): bare stdin would flip the CLI to a base64 `bytes_value` field,
|
|
107
|
+
// which the app then cannot read back as its Lakebase password at runtime. `pat` is
|
|
108
|
+
// already validated non-empty above, so the empty-stdin "silent success on no value"
|
|
109
|
+
// trap cannot occur here.
|
|
110
|
+
await runDatabricks(["secrets", "put-secret", "--json", "@/dev/stdin"], {
|
|
105
111
|
profile,
|
|
106
112
|
timeout: timeoutMs,
|
|
113
|
+
input: JSON.stringify({ scope: scopeName, key: keyName, string_value: pat }),
|
|
107
114
|
});
|
|
108
115
|
|
|
109
116
|
// 4. ACL (best-effort)
|
|
@@ -74,14 +74,25 @@ jobs:
|
|
|
74
74
|
SCM_UTILS_REF="$(tr -d '[:space:]' < .lakebase/scm-utils-ref 2>/dev/null || true)"
|
|
75
75
|
SCM_UTILS_REF="${SCM_UTILS_REF:-v{{LAKEBASE_SCM_UTILS_VERSION}}}"
|
|
76
76
|
echo "SCM_UTILS_REF=${SCM_UTILS_REF}" >> "$GITHUB_ENV"
|
|
77
|
-
# Registry-first
|
|
78
|
-
#
|
|
79
|
-
# (
|
|
77
|
+
# Registry-first for version tags, with a GitHub fallback when the registry
|
|
78
|
+
# cannot serve the tarball yet: a freshly-published version is blocked by
|
|
79
|
+
# the proxy's same-day security screen for ~24h (a staging merge then fails
|
|
80
|
+
# on npx ETARGET), and a branch/SHA ref only ever has GitHub. Probe the
|
|
81
|
+
# tarball URL once and pick the source that actually serves it, so a
|
|
82
|
+
# same-day publish never stalls CI.
|
|
83
|
+
SPEC=""
|
|
80
84
|
case "$SCM_UTILS_REF" in
|
|
81
|
-
v[0-9]*)
|
|
82
|
-
[0-9]*) echo "SCM_UTILS_NPX_PKG=@databricks-solutions/lakebase-scm-utils@${SCM_UTILS_REF}" >> "$GITHUB_ENV" ;;
|
|
83
|
-
*) echo "SCM_UTILS_NPX_PKG=github:databricks-solutions/lakebase-scm-utils#${SCM_UTILS_REF}" >> "$GITHUB_ENV" ;;
|
|
85
|
+
v[0-9]*|[0-9]*) SPEC="@databricks-solutions/lakebase-scm-utils@${SCM_UTILS_REF#v}" ;;
|
|
84
86
|
esac
|
|
87
|
+
if [ -n "$SPEC" ]; then
|
|
88
|
+
TARBALL_URL="$(npm view "${SPEC}" dist.tarball 2>/dev/null || true)"
|
|
89
|
+
if [ -z "$TARBALL_URL" ] || ! curl -fsSI --max-time 15 "$TARBALL_URL" >/dev/null 2>&1; then
|
|
90
|
+
echo "resolve-substrate: registry cannot serve ${SPEC} yet (same-day publish screen); falling back to GitHub."
|
|
91
|
+
SPEC=""
|
|
92
|
+
fi
|
|
93
|
+
fi
|
|
94
|
+
[ -z "$SPEC" ] && SPEC="github:databricks-solutions/lakebase-scm-utils#${SCM_UTILS_REF}"
|
|
95
|
+
echo "SCM_UTILS_NPX_PKG=${SPEC}" >> "$GITHUB_ENV"
|
|
85
96
|
|
|
86
97
|
- name: Detect project language
|
|
87
98
|
id: detect-lang
|