@databricks-solutions/lakebase-scm-utils 0.2.48 → 0.2.49

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 (51) hide show
  1. package/dist/ci-secrets-CnGrdQV-.d.cts +84 -0
  2. package/dist/ci-secrets-CnGrdQV-.d.ts +84 -0
  3. package/dist/scripts/index.cjs +2177 -2052
  4. package/dist/scripts/index.d.cts +2 -1
  5. package/dist/scripts/index.d.ts +2 -1
  6. package/dist/scripts/index.js +253 -134
  7. package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +2 -2
  8. package/dist/scripts/lakebase/ci-resolve-branch.cli.js +2 -2
  9. package/dist/scripts/lakebase/collapse-heads.cli.cjs +2 -2
  10. package/dist/scripts/lakebase/collapse-heads.cli.js +2 -2
  11. package/dist/scripts/lakebase/detect-language.cli.cjs +2 -2
  12. package/dist/scripts/lakebase/detect-language.cli.js +2 -2
  13. package/dist/scripts/lakebase/doctor.cli.cjs +2 -2
  14. package/dist/scripts/lakebase/doctor.cli.js +2 -2
  15. package/dist/scripts/lakebase/get-connection.cli.cjs +2 -2
  16. package/dist/scripts/lakebase/get-connection.cli.js +2 -2
  17. package/dist/scripts/lakebase/index.cjs +2163 -2050
  18. package/dist/scripts/lakebase/index.d.cts +8 -0
  19. package/dist/scripts/lakebase/index.d.ts +8 -0
  20. package/dist/scripts/lakebase/index.js +243 -130
  21. package/dist/scripts/lakebase/infra-runner.cli.cjs +2 -2
  22. package/dist/scripts/lakebase/infra-runner.cli.js +2 -2
  23. package/dist/scripts/lakebase/new-migration.cli.cjs +2 -2
  24. package/dist/scripts/lakebase/new-migration.cli.js +2 -2
  25. package/dist/scripts/lakebase/schema-diff.cli.cjs +2 -2
  26. package/dist/scripts/lakebase/schema-diff.cli.js +2 -2
  27. package/dist/scripts/lakebase/schema-migrate.cli.cjs +2 -2
  28. package/dist/scripts/lakebase/schema-migrate.cli.js +2 -2
  29. package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +2 -2
  30. package/dist/scripts/lakebase/scm-claim-feature.cli.js +2 -2
  31. package/dist/scripts/lakebase/scm-doctor.cli.cjs +2 -2
  32. package/dist/scripts/lakebase/scm-doctor.cli.js +2 -2
  33. package/dist/scripts/lakebase/scm-merge.cli.cjs +2216 -1994
  34. package/dist/scripts/lakebase/scm-merge.cli.js +296 -74
  35. package/dist/scripts/lakebase/scm-prepare-pr.cli.cjs +479 -86
  36. package/dist/scripts/lakebase/scm-prepare-pr.cli.js +479 -86
  37. package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +2 -2
  38. package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +2 -2
  39. package/dist/scripts/lakebase/sync-ci-secrets.cli.cjs +56 -30
  40. package/dist/scripts/lakebase/sync-ci-secrets.cli.js +56 -30
  41. package/dist/scripts/util/index.cjs +142 -25
  42. package/dist/scripts/util/index.d.cts +2 -27
  43. package/dist/scripts/util/index.d.ts +2 -27
  44. package/dist/scripts/util/index.js +136 -25
  45. package/package.json +1 -1
  46. package/scripts/lakebase/create-project.ts +2 -2
  47. package/scripts/lakebase/scm-merge.ts +21 -0
  48. package/scripts/lakebase/scm-prepare-pr.ts +10 -1
  49. package/scripts/lakebase/sync-ci-secrets.cli.ts +2 -2
  50. package/scripts/util/ci-secrets.ts +212 -26
  51. package/templates/project/common/scripts/create-token-and-sync-secrets.sh +9 -86
@@ -79288,8 +79288,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
79288
79288
  var cached;
79289
79289
  function substrateSelfVersion() {
79290
79290
  if (cached !== void 0) return cached;
79291
- if ("0.2.48".length > 0) {
79292
- cached = "0.2.48";
79291
+ if ("0.2.49".length > 0) {
79292
+ cached = "0.2.49";
79293
79293
  return cached;
79294
79294
  }
79295
79295
  cached = "unknown";
@@ -389,8 +389,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
389
389
  var cached;
390
390
  function substrateSelfVersion() {
391
391
  if (cached !== void 0) return cached;
392
- if ("0.2.48".length > 0) {
393
- cached = "0.2.48";
392
+ if ("0.2.49".length > 0) {
393
+ cached = "0.2.49";
394
394
  return cached;
395
395
  }
396
396
  cached = "unknown";
@@ -1469,7 +1469,7 @@ __export(sync_ci_secrets_cli_exports, {
1469
1469
  });
1470
1470
  module.exports = __toCommonJS(sync_ci_secrets_cli_exports);
1471
1471
  init_cjs_shims();
1472
- var path2 = __toESM(require("path"), 1);
1472
+ var path3 = __toESM(require("path"), 1);
1473
1473
 
1474
1474
  // scripts/util/cli-entry.ts
1475
1475
  init_cjs_shims();
@@ -1595,6 +1595,7 @@ async function getOwnerRepo(cwd) {
1595
1595
 
1596
1596
  // scripts/util/ci-secrets.ts
1597
1597
  init_cjs_shims();
1598
+ var path2 = __toESM(require("path"), 1);
1598
1599
 
1599
1600
  // scripts/lakebase/databricks-cli.ts
1600
1601
  init_cjs_shims();
@@ -2881,7 +2882,7 @@ paginateRest.VERSION = VERSION5;
2881
2882
 
2882
2883
  // node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
2883
2884
  init_cjs_shims();
2884
- var generateMessage = (path3, cursorValue) => `The cursor at "${path3.join(
2885
+ var generateMessage = (path4, cursorValue) => `The cursor at "${path4.join(
2885
2886
  ","
2886
2887
  )}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
2887
2888
  var MissingCursorChange = class extends Error {
@@ -2922,9 +2923,9 @@ function findPaginatedResourcePath(responseData) {
2922
2923
  }
2923
2924
  return paginatedResourcePath;
2924
2925
  }
2925
- var deepFindPathToProperty = (object, searchProp, path3 = []) => {
2926
+ var deepFindPathToProperty = (object, searchProp, path4 = []) => {
2926
2927
  for (const key of Object.keys(object)) {
2927
- const currentPath = [...path3, key];
2928
+ const currentPath = [...path4, key];
2928
2929
  const currentValue = object[key];
2929
2930
  if (isObject(currentValue)) {
2930
2931
  if (currentValue.hasOwnProperty(searchProp)) {
@@ -2942,12 +2943,12 @@ var deepFindPathToProperty = (object, searchProp, path3 = []) => {
2942
2943
  }
2943
2944
  return [];
2944
2945
  };
2945
- var get = (object, path3) => {
2946
- return path3.reduce((current, nextProperty) => current[nextProperty], object);
2946
+ var get = (object, path4) => {
2947
+ return path4.reduce((current, nextProperty) => current[nextProperty], object);
2947
2948
  };
2948
- var set = (object, path3, mutator) => {
2949
- const lastProperty = path3[path3.length - 1];
2950
- const parentPath = [...path3].slice(0, -1);
2949
+ var set = (object, path4, mutator) => {
2950
+ const lastProperty = path4[path4.length - 1];
2951
+ const parentPath = [...path4].slice(0, -1);
2951
2952
  const parent = get(object, parentPath);
2952
2953
  if (typeof mutator === "function") {
2953
2954
  parent[lastProperty] = mutator(parent[lastProperty]);
@@ -2999,22 +3000,22 @@ var mergeResponses = (response1, response2) => {
2999
3000
  if (Object.keys(response1).length === 0) {
3000
3001
  return Object.assign(response1, response2);
3001
3002
  }
3002
- const path3 = findPaginatedResourcePath(response1);
3003
- const nodesPath = [...path3, "nodes"];
3003
+ const path4 = findPaginatedResourcePath(response1);
3004
+ const nodesPath = [...path4, "nodes"];
3004
3005
  const newNodes = get(response2, nodesPath);
3005
3006
  if (newNodes) {
3006
3007
  set(response1, nodesPath, (values) => {
3007
3008
  return [...values, ...newNodes];
3008
3009
  });
3009
3010
  }
3010
- const edgesPath = [...path3, "edges"];
3011
+ const edgesPath = [...path4, "edges"];
3011
3012
  const newEdges = get(response2, edgesPath);
3012
3013
  if (newEdges) {
3013
3014
  set(response1, edgesPath, (values) => {
3014
3015
  return [...values, ...newEdges];
3015
3016
  });
3016
3017
  }
3017
- const pageInfoPath = [...path3, "pageInfo"];
3018
+ const pageInfoPath = [...path4, "pageInfo"];
3018
3019
  set(response1, pageInfoPath, get(response2, pageInfoPath));
3019
3020
  return response1;
3020
3021
  };
@@ -5435,7 +5436,7 @@ var triggers_notification_paths_default = [
5435
5436
  ];
5436
5437
  function routeMatcher(paths) {
5437
5438
  const regexes = paths.map(
5438
- (path3) => path3.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5439
+ (path4) => path4.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5439
5440
  );
5440
5441
  const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
5441
5442
  return new RegExp(regex2, "i");
@@ -8453,13 +8454,39 @@ async function listSecretNames(ownerRepo) {
8453
8454
 
8454
8455
  // scripts/util/ci-secrets.ts
8455
8456
  var REQUIRED_CI_SECRETS = ["DATABRICKS_HOST", "LAKEBASE_PROJECT_ID", "DATABRICKS_TOKEN"];
8457
+ var CI_TOKEN_LIFETIME_SECONDS = 7776e3;
8458
+ function ciTokenComment(ownerRepo) {
8459
+ const repoName = ownerRepo.includes("/") ? ownerRepo.slice(ownerRepo.lastIndexOf("/") + 1) : ownerRepo;
8460
+ return `GitHub Actions (${repoName})`;
8461
+ }
8456
8462
  async function missingCiSecrets(ownerRepo) {
8457
8463
  const present = new Set(await listSecretNames(ownerRepo));
8458
8464
  return REQUIRED_CI_SECRETS.filter((n) => !present.has(n));
8459
8465
  }
8466
+ async function mintCiToken(args) {
8467
+ try {
8468
+ const raw = await runDatabricks(
8469
+ ["tokens", "create", "--comment", args.comment, "--lifetime-seconds", String(args.lifetimeSeconds), "-o", "json"],
8470
+ { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8471
+ );
8472
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8473
+ const token = parsed.token_value || parsed.token || "";
8474
+ if (token) return token;
8475
+ } catch {
8476
+ }
8477
+ try {
8478
+ const raw = await runDatabricks(["auth", "token", "-o", "json"], {
8479
+ host: args.databricksHost,
8480
+ cwd: args.projectDir,
8481
+ timeout: 3e4
8482
+ });
8483
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8484
+ return parsed.access_token || "";
8485
+ } catch {
8486
+ return "";
8487
+ }
8488
+ }
8460
8489
  async function syncCiSecrets(args) {
8461
- const lifetime = args.lifetimeSeconds ?? 86400;
8462
- const comment = args.comment ?? "GitHub Actions CI";
8463
8490
  const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
8464
8491
  if (!ownerRepo) {
8465
8492
  throw new Error("Could not resolve GitHub repository from git remote");
@@ -8470,20 +8497,19 @@ async function syncCiSecrets(args) {
8470
8497
  if (!args.lakebaseProjectId) {
8471
8498
  throw new Error("syncCiSecrets: lakebaseProjectId is required");
8472
8499
  }
8500
+ const lifetime = args.lifetimeSeconds ?? CI_TOKEN_LIFETIME_SECONDS;
8501
+ const comment = args.comment ?? ciTokenComment(ownerRepo);
8473
8502
  const secrets = {
8474
8503
  DATABRICKS_HOST: args.databricksHost,
8475
8504
  LAKEBASE_PROJECT_ID: args.lakebaseProjectId
8476
8505
  };
8477
- try {
8478
- const tokenRaw = await runDatabricks(
8479
- ["tokens", "create", "--comment", comment, "--lifetime-seconds", String(lifetime), "-o", "json"],
8480
- { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8481
- );
8482
- const parsed = JSON.parse(tokenRaw);
8483
- const token = parsed.token_value || parsed.token || "";
8484
- if (token) secrets.DATABRICKS_TOKEN = token;
8485
- } catch {
8486
- }
8506
+ const token = await mintCiToken({
8507
+ databricksHost: args.databricksHost,
8508
+ projectDir: args.projectDir,
8509
+ comment,
8510
+ lifetimeSeconds: lifetime
8511
+ });
8512
+ if (token) secrets.DATABRICKS_TOKEN = token;
8487
8513
  await setRepoSecrets(ownerRepo, secrets);
8488
8514
  }
8489
8515
 
@@ -8535,8 +8561,8 @@ Flags:
8535
8561
  --host <url> DATABRICKS_HOST (default: .env DATABRICKS_HOST)
8536
8562
  --project-id <id> LAKEBASE_PROJECT_ID (default: .env LAKEBASE_PROJECT_ID)
8537
8563
  --repo <owner/name> Target repo (default: origin remote)
8538
- --lifetime-sec <n> CI PAT lifetime (default: 86400 = 24h)
8539
- --comment <text> Token comment (default: "GitHub Actions CI")
8564
+ --lifetime-sec <n> CI PAT lifetime (default: 7776000 = 90d, the canonical durable lifetime)
8565
+ --comment <text> Token comment (default: canonical "GitHub Actions (<repo>)")
8540
8566
  -h, --help Show this help
8541
8567
 
8542
8568
  Exit codes:
@@ -8551,8 +8577,8 @@ async function runSyncCiSecretsCli(argv) {
8551
8577
  `);
8552
8578
  return 0;
8553
8579
  }
8554
- const projectDir = path2.resolve(args.projectDir ?? process.cwd());
8555
- const envPath = path2.join(projectDir, ".env");
8580
+ const projectDir = path3.resolve(args.projectDir ?? process.cwd());
8581
+ const envPath = path3.join(projectDir, ".env");
8556
8582
  const host = args.host ?? readEnvVar(envPath, "DATABRICKS_HOST");
8557
8583
  const projectId = args.projectId ?? readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
8558
8584
  const ownerRepo = args.repo ?? await getOwnerRepo(projectDir);
@@ -1457,7 +1457,7 @@ var require_light = __commonJS({
1457
1457
 
1458
1458
  // scripts/lakebase/sync-ci-secrets.cli.ts
1459
1459
  init_esm_shims();
1460
- import * as path3 from "path";
1460
+ import * as path4 from "path";
1461
1461
 
1462
1462
  // scripts/util/cli-entry.ts
1463
1463
  init_esm_shims();
@@ -1583,6 +1583,7 @@ async function getOwnerRepo(cwd) {
1583
1583
 
1584
1584
  // scripts/util/ci-secrets.ts
1585
1585
  init_esm_shims();
1586
+ import * as path3 from "path";
1586
1587
 
1587
1588
  // scripts/lakebase/databricks-cli.ts
1588
1589
  init_esm_shims();
@@ -2869,7 +2870,7 @@ paginateRest.VERSION = VERSION5;
2869
2870
 
2870
2871
  // node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
2871
2872
  init_esm_shims();
2872
- var generateMessage = (path4, cursorValue) => `The cursor at "${path4.join(
2873
+ var generateMessage = (path5, cursorValue) => `The cursor at "${path5.join(
2873
2874
  ","
2874
2875
  )}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
2875
2876
  var MissingCursorChange = class extends Error {
@@ -2910,9 +2911,9 @@ function findPaginatedResourcePath(responseData) {
2910
2911
  }
2911
2912
  return paginatedResourcePath;
2912
2913
  }
2913
- var deepFindPathToProperty = (object, searchProp, path4 = []) => {
2914
+ var deepFindPathToProperty = (object, searchProp, path5 = []) => {
2914
2915
  for (const key of Object.keys(object)) {
2915
- const currentPath = [...path4, key];
2916
+ const currentPath = [...path5, key];
2916
2917
  const currentValue = object[key];
2917
2918
  if (isObject(currentValue)) {
2918
2919
  if (currentValue.hasOwnProperty(searchProp)) {
@@ -2930,12 +2931,12 @@ var deepFindPathToProperty = (object, searchProp, path4 = []) => {
2930
2931
  }
2931
2932
  return [];
2932
2933
  };
2933
- var get = (object, path4) => {
2934
- return path4.reduce((current, nextProperty) => current[nextProperty], object);
2934
+ var get = (object, path5) => {
2935
+ return path5.reduce((current, nextProperty) => current[nextProperty], object);
2935
2936
  };
2936
- var set = (object, path4, mutator) => {
2937
- const lastProperty = path4[path4.length - 1];
2938
- const parentPath = [...path4].slice(0, -1);
2937
+ var set = (object, path5, mutator) => {
2938
+ const lastProperty = path5[path5.length - 1];
2939
+ const parentPath = [...path5].slice(0, -1);
2939
2940
  const parent = get(object, parentPath);
2940
2941
  if (typeof mutator === "function") {
2941
2942
  parent[lastProperty] = mutator(parent[lastProperty]);
@@ -2987,22 +2988,22 @@ var mergeResponses = (response1, response2) => {
2987
2988
  if (Object.keys(response1).length === 0) {
2988
2989
  return Object.assign(response1, response2);
2989
2990
  }
2990
- const path4 = findPaginatedResourcePath(response1);
2991
- const nodesPath = [...path4, "nodes"];
2991
+ const path5 = findPaginatedResourcePath(response1);
2992
+ const nodesPath = [...path5, "nodes"];
2992
2993
  const newNodes = get(response2, nodesPath);
2993
2994
  if (newNodes) {
2994
2995
  set(response1, nodesPath, (values) => {
2995
2996
  return [...values, ...newNodes];
2996
2997
  });
2997
2998
  }
2998
- const edgesPath = [...path4, "edges"];
2999
+ const edgesPath = [...path5, "edges"];
2999
3000
  const newEdges = get(response2, edgesPath);
3000
3001
  if (newEdges) {
3001
3002
  set(response1, edgesPath, (values) => {
3002
3003
  return [...values, ...newEdges];
3003
3004
  });
3004
3005
  }
3005
- const pageInfoPath = [...path4, "pageInfo"];
3006
+ const pageInfoPath = [...path5, "pageInfo"];
3006
3007
  set(response1, pageInfoPath, get(response2, pageInfoPath));
3007
3008
  return response1;
3008
3009
  };
@@ -5423,7 +5424,7 @@ var triggers_notification_paths_default = [
5423
5424
  ];
5424
5425
  function routeMatcher(paths) {
5425
5426
  const regexes = paths.map(
5426
- (path4) => path4.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5427
+ (path5) => path5.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5427
5428
  );
5428
5429
  const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
5429
5430
  return new RegExp(regex2, "i");
@@ -8441,13 +8442,39 @@ async function listSecretNames(ownerRepo) {
8441
8442
 
8442
8443
  // scripts/util/ci-secrets.ts
8443
8444
  var REQUIRED_CI_SECRETS = ["DATABRICKS_HOST", "LAKEBASE_PROJECT_ID", "DATABRICKS_TOKEN"];
8445
+ var CI_TOKEN_LIFETIME_SECONDS = 7776e3;
8446
+ function ciTokenComment(ownerRepo) {
8447
+ const repoName = ownerRepo.includes("/") ? ownerRepo.slice(ownerRepo.lastIndexOf("/") + 1) : ownerRepo;
8448
+ return `GitHub Actions (${repoName})`;
8449
+ }
8444
8450
  async function missingCiSecrets(ownerRepo) {
8445
8451
  const present = new Set(await listSecretNames(ownerRepo));
8446
8452
  return REQUIRED_CI_SECRETS.filter((n) => !present.has(n));
8447
8453
  }
8454
+ async function mintCiToken(args) {
8455
+ try {
8456
+ const raw = await runDatabricks(
8457
+ ["tokens", "create", "--comment", args.comment, "--lifetime-seconds", String(args.lifetimeSeconds), "-o", "json"],
8458
+ { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8459
+ );
8460
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8461
+ const token = parsed.token_value || parsed.token || "";
8462
+ if (token) return token;
8463
+ } catch {
8464
+ }
8465
+ try {
8466
+ const raw = await runDatabricks(["auth", "token", "-o", "json"], {
8467
+ host: args.databricksHost,
8468
+ cwd: args.projectDir,
8469
+ timeout: 3e4
8470
+ });
8471
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8472
+ return parsed.access_token || "";
8473
+ } catch {
8474
+ return "";
8475
+ }
8476
+ }
8448
8477
  async function syncCiSecrets(args) {
8449
- const lifetime = args.lifetimeSeconds ?? 86400;
8450
- const comment = args.comment ?? "GitHub Actions CI";
8451
8478
  const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
8452
8479
  if (!ownerRepo) {
8453
8480
  throw new Error("Could not resolve GitHub repository from git remote");
@@ -8458,20 +8485,19 @@ async function syncCiSecrets(args) {
8458
8485
  if (!args.lakebaseProjectId) {
8459
8486
  throw new Error("syncCiSecrets: lakebaseProjectId is required");
8460
8487
  }
8488
+ const lifetime = args.lifetimeSeconds ?? CI_TOKEN_LIFETIME_SECONDS;
8489
+ const comment = args.comment ?? ciTokenComment(ownerRepo);
8461
8490
  const secrets = {
8462
8491
  DATABRICKS_HOST: args.databricksHost,
8463
8492
  LAKEBASE_PROJECT_ID: args.lakebaseProjectId
8464
8493
  };
8465
- try {
8466
- const tokenRaw = await runDatabricks(
8467
- ["tokens", "create", "--comment", comment, "--lifetime-seconds", String(lifetime), "-o", "json"],
8468
- { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8469
- );
8470
- const parsed = JSON.parse(tokenRaw);
8471
- const token = parsed.token_value || parsed.token || "";
8472
- if (token) secrets.DATABRICKS_TOKEN = token;
8473
- } catch {
8474
- }
8494
+ const token = await mintCiToken({
8495
+ databricksHost: args.databricksHost,
8496
+ projectDir: args.projectDir,
8497
+ comment,
8498
+ lifetimeSeconds: lifetime
8499
+ });
8500
+ if (token) secrets.DATABRICKS_TOKEN = token;
8475
8501
  await setRepoSecrets(ownerRepo, secrets);
8476
8502
  }
8477
8503
 
@@ -8523,8 +8549,8 @@ Flags:
8523
8549
  --host <url> DATABRICKS_HOST (default: .env DATABRICKS_HOST)
8524
8550
  --project-id <id> LAKEBASE_PROJECT_ID (default: .env LAKEBASE_PROJECT_ID)
8525
8551
  --repo <owner/name> Target repo (default: origin remote)
8526
- --lifetime-sec <n> CI PAT lifetime (default: 86400 = 24h)
8527
- --comment <text> Token comment (default: "GitHub Actions CI")
8552
+ --lifetime-sec <n> CI PAT lifetime (default: 7776000 = 90d, the canonical durable lifetime)
8553
+ --comment <text> Token comment (default: canonical "GitHub Actions (<repo>)")
8528
8554
  -h, --help Show this help
8529
8555
 
8530
8556
  Exit codes:
@@ -8539,8 +8565,8 @@ async function runSyncCiSecretsCli(argv) {
8539
8565
  `);
8540
8566
  return 0;
8541
8567
  }
8542
- const projectDir = path3.resolve(args.projectDir ?? process.cwd());
8543
- const envPath = path3.join(projectDir, ".env");
8568
+ const projectDir = path4.resolve(args.projectDir ?? process.cwd());
8569
+ const envPath = path4.join(projectDir, ".env");
8544
8570
  const host = args.host ?? readEnvVar(envPath, "DATABRICKS_HOST");
8545
8571
  const projectId = args.projectId ?? readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
8546
8572
  const ownerRepo = args.repo ?? await getOwnerRepo(projectDir);
@@ -1464,11 +1464,17 @@ var require_light = __commonJS({
1464
1464
  // scripts/util/index.ts
1465
1465
  var util_exports = {};
1466
1466
  __export(util_exports, {
1467
+ CI_TOKEN_LIFETIME_SECONDS: () => CI_TOKEN_LIFETIME_SECONDS,
1468
+ CI_TOKEN_REMINT_MARGIN_SECONDS: () => CI_TOKEN_REMINT_MARGIN_SECONDS,
1467
1469
  LAKEBASE_BRANCH_NAME_MAX: () => LAKEBASE_BRANCH_NAME_MAX,
1468
1470
  PROXY_ENV_KEYS: () => PROXY_ENV_KEYS,
1469
1471
  REQUIRED_CI_SECRETS: () => REQUIRED_CI_SECRETS,
1472
+ ciTokenComment: () => ciTokenComment,
1473
+ ciTokenExpiry: () => ciTokenExpiry,
1470
1474
  copyDirSubstituted: () => copyDirSubstituted,
1471
1475
  delay: () => delay,
1476
+ ensureCiSecretsFresh: () => ensureCiSecretsFresh,
1477
+ ensureCiSecretsFreshFromEnv: () => ensureCiSecretsFreshFromEnv,
1472
1478
  exec: () => exec2,
1473
1479
  extractZipToDir: () => extractZipToDir,
1474
1480
  formatOwnerRepo: () => formatOwnerRepo,
@@ -1661,8 +1667,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
1661
1667
  var cached;
1662
1668
  function substrateSelfVersion() {
1663
1669
  if (cached !== void 0) return cached;
1664
- if ("0.2.48".length > 0) {
1665
- cached = "0.2.48";
1670
+ if ("0.2.49".length > 0) {
1671
+ cached = "0.2.49";
1666
1672
  return cached;
1667
1673
  }
1668
1674
  cached = "unknown";
@@ -1722,6 +1728,7 @@ function sanitizeBranchName(gitBranch) {
1722
1728
 
1723
1729
  // scripts/util/ci-secrets.ts
1724
1730
  init_cjs_shims();
1731
+ var path5 = __toESM(require("path"), 1);
1725
1732
 
1726
1733
  // scripts/lakebase/databricks-cli.ts
1727
1734
  init_cjs_shims();
@@ -3023,7 +3030,7 @@ paginateRest.VERSION = VERSION5;
3023
3030
 
3024
3031
  // node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
3025
3032
  init_cjs_shims();
3026
- var generateMessage = (path5, cursorValue) => `The cursor at "${path5.join(
3033
+ var generateMessage = (path6, cursorValue) => `The cursor at "${path6.join(
3027
3034
  ","
3028
3035
  )}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
3029
3036
  var MissingCursorChange = class extends Error {
@@ -3064,9 +3071,9 @@ function findPaginatedResourcePath(responseData) {
3064
3071
  }
3065
3072
  return paginatedResourcePath;
3066
3073
  }
3067
- var deepFindPathToProperty = (object, searchProp, path5 = []) => {
3074
+ var deepFindPathToProperty = (object, searchProp, path6 = []) => {
3068
3075
  for (const key of Object.keys(object)) {
3069
- const currentPath = [...path5, key];
3076
+ const currentPath = [...path6, key];
3070
3077
  const currentValue = object[key];
3071
3078
  if (isObject(currentValue)) {
3072
3079
  if (currentValue.hasOwnProperty(searchProp)) {
@@ -3084,12 +3091,12 @@ var deepFindPathToProperty = (object, searchProp, path5 = []) => {
3084
3091
  }
3085
3092
  return [];
3086
3093
  };
3087
- var get = (object, path5) => {
3088
- return path5.reduce((current, nextProperty) => current[nextProperty], object);
3094
+ var get = (object, path6) => {
3095
+ return path6.reduce((current, nextProperty) => current[nextProperty], object);
3089
3096
  };
3090
- var set = (object, path5, mutator) => {
3091
- const lastProperty = path5[path5.length - 1];
3092
- const parentPath = [...path5].slice(0, -1);
3097
+ var set = (object, path6, mutator) => {
3098
+ const lastProperty = path6[path6.length - 1];
3099
+ const parentPath = [...path6].slice(0, -1);
3093
3100
  const parent = get(object, parentPath);
3094
3101
  if (typeof mutator === "function") {
3095
3102
  parent[lastProperty] = mutator(parent[lastProperty]);
@@ -3141,22 +3148,22 @@ var mergeResponses = (response1, response2) => {
3141
3148
  if (Object.keys(response1).length === 0) {
3142
3149
  return Object.assign(response1, response2);
3143
3150
  }
3144
- const path5 = findPaginatedResourcePath(response1);
3145
- const nodesPath = [...path5, "nodes"];
3151
+ const path6 = findPaginatedResourcePath(response1);
3152
+ const nodesPath = [...path6, "nodes"];
3146
3153
  const newNodes = get(response2, nodesPath);
3147
3154
  if (newNodes) {
3148
3155
  set(response1, nodesPath, (values) => {
3149
3156
  return [...values, ...newNodes];
3150
3157
  });
3151
3158
  }
3152
- const edgesPath = [...path5, "edges"];
3159
+ const edgesPath = [...path6, "edges"];
3153
3160
  const newEdges = get(response2, edgesPath);
3154
3161
  if (newEdges) {
3155
3162
  set(response1, edgesPath, (values) => {
3156
3163
  return [...values, ...newEdges];
3157
3164
  });
3158
3165
  }
3159
- const pageInfoPath = [...path5, "pageInfo"];
3166
+ const pageInfoPath = [...path6, "pageInfo"];
3160
3167
  set(response1, pageInfoPath, get(response2, pageInfoPath));
3161
3168
  return response1;
3162
3169
  };
@@ -5577,7 +5584,7 @@ var triggers_notification_paths_default = [
5577
5584
  ];
5578
5585
  function routeMatcher(paths) {
5579
5586
  const regexes = paths.map(
5580
- (path5) => path5.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5587
+ (path6) => path6.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
5581
5588
  );
5582
5589
  const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
5583
5590
  return new RegExp(regex2, "i");
@@ -8632,13 +8639,40 @@ async function getOwnerRepo(cwd) {
8632
8639
 
8633
8640
  // scripts/util/ci-secrets.ts
8634
8641
  var REQUIRED_CI_SECRETS = ["DATABRICKS_HOST", "LAKEBASE_PROJECT_ID", "DATABRICKS_TOKEN"];
8642
+ var CI_TOKEN_LIFETIME_SECONDS = 7776e3;
8643
+ var CI_TOKEN_REMINT_MARGIN_SECONDS = 86400;
8644
+ function ciTokenComment(ownerRepo) {
8645
+ const repoName = ownerRepo.includes("/") ? ownerRepo.slice(ownerRepo.lastIndexOf("/") + 1) : ownerRepo;
8646
+ return `GitHub Actions (${repoName})`;
8647
+ }
8635
8648
  async function missingCiSecrets(ownerRepo) {
8636
8649
  const present = new Set(await listSecretNames(ownerRepo));
8637
8650
  return REQUIRED_CI_SECRETS.filter((n) => !present.has(n));
8638
8651
  }
8652
+ async function mintCiToken(args) {
8653
+ try {
8654
+ const raw = await runDatabricks(
8655
+ ["tokens", "create", "--comment", args.comment, "--lifetime-seconds", String(args.lifetimeSeconds), "-o", "json"],
8656
+ { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8657
+ );
8658
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8659
+ const token = parsed.token_value || parsed.token || "";
8660
+ if (token) return token;
8661
+ } catch {
8662
+ }
8663
+ try {
8664
+ const raw = await runDatabricks(["auth", "token", "-o", "json"], {
8665
+ host: args.databricksHost,
8666
+ cwd: args.projectDir,
8667
+ timeout: 3e4
8668
+ });
8669
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
8670
+ return parsed.access_token || "";
8671
+ } catch {
8672
+ return "";
8673
+ }
8674
+ }
8639
8675
  async function syncCiSecrets(args) {
8640
- const lifetime = args.lifetimeSeconds ?? 86400;
8641
- const comment = args.comment ?? "GitHub Actions CI";
8642
8676
  const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
8643
8677
  if (!ownerRepo) {
8644
8678
  throw new Error("Could not resolve GitHub repository from git remote");
@@ -8649,21 +8683,98 @@ async function syncCiSecrets(args) {
8649
8683
  if (!args.lakebaseProjectId) {
8650
8684
  throw new Error("syncCiSecrets: lakebaseProjectId is required");
8651
8685
  }
8686
+ const lifetime = args.lifetimeSeconds ?? CI_TOKEN_LIFETIME_SECONDS;
8687
+ const comment = args.comment ?? ciTokenComment(ownerRepo);
8652
8688
  const secrets = {
8653
8689
  DATABRICKS_HOST: args.databricksHost,
8654
8690
  LAKEBASE_PROJECT_ID: args.lakebaseProjectId
8655
8691
  };
8692
+ const token = await mintCiToken({
8693
+ databricksHost: args.databricksHost,
8694
+ projectDir: args.projectDir,
8695
+ comment,
8696
+ lifetimeSeconds: lifetime
8697
+ });
8698
+ if (token) secrets.DATABRICKS_TOKEN = token;
8699
+ await setRepoSecrets(ownerRepo, secrets);
8700
+ }
8701
+ async function ciTokenExpiry(args) {
8702
+ const comment = ciTokenComment(args.ownerRepo);
8703
+ let raw;
8656
8704
  try {
8657
- const tokenRaw = await runDatabricks(
8658
- ["tokens", "create", "--comment", comment, "--lifetime-seconds", String(lifetime), "-o", "json"],
8659
- { host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
8660
- );
8661
- const parsed = JSON.parse(tokenRaw);
8662
- const token = parsed.token_value || parsed.token || "";
8663
- if (token) secrets.DATABRICKS_TOKEN = token;
8705
+ raw = await runDatabricks(["tokens", "list", "-o", "json"], {
8706
+ host: args.databricksHost,
8707
+ cwd: args.projectDir,
8708
+ timeout: 3e4
8709
+ });
8664
8710
  } catch {
8711
+ return null;
8712
+ }
8713
+ let infos;
8714
+ try {
8715
+ const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("["))));
8716
+ infos = Array.isArray(parsed) ? parsed : [];
8717
+ } catch {
8718
+ return null;
8719
+ }
8720
+ const expiries = infos.filter((t) => t.comment === comment).map((t) => t.expiry_time === -1 ? Number.POSITIVE_INFINITY : Number(t.expiry_time)).filter((n) => Number.isFinite(n) || n === Number.POSITIVE_INFINITY);
8721
+ if (expiries.length === 0) return null;
8722
+ return Math.max(...expiries);
8723
+ }
8724
+ async function ensureCiSecretsFresh(args) {
8725
+ const now = args.now ?? Date.now;
8726
+ const marginMs = (args.marginSeconds ?? CI_TOKEN_REMINT_MARGIN_SECONDS) * 1e3;
8727
+ const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
8728
+ if (!ownerRepo) {
8729
+ throw new Error("Could not resolve GitHub repository from git remote");
8730
+ }
8731
+ const sync = () => syncCiSecrets({
8732
+ projectDir: args.projectDir,
8733
+ databricksHost: args.databricksHost,
8734
+ lakebaseProjectId: args.lakebaseProjectId,
8735
+ ownerRepo
8736
+ });
8737
+ const missing = await missingCiSecrets(ownerRepo);
8738
+ if (missing.length > 0) {
8739
+ await sync();
8740
+ return { action: "provisioned", reason: `CI secret(s) were missing (${missing.join(", ")}); provisioned.` };
8741
+ }
8742
+ const expiry = await ciTokenExpiry({ projectDir: args.projectDir, databricksHost: args.databricksHost, ownerRepo });
8743
+ if (expiry === null) {
8744
+ await sync();
8745
+ return { action: "reminted", reason: "no live CI token found (expired or minted under a different identity); re-minted." };
8746
+ }
8747
+ if (expiry !== Number.POSITIVE_INFINITY && expiry < now() + marginMs) {
8748
+ await sync();
8749
+ const hrs = Math.max(0, Math.round((expiry - now()) / 36e5));
8750
+ return { action: "reminted", reason: `CI token expires in ~${hrs}h (within the re-mint margin); re-minted.` };
8751
+ }
8752
+ return { action: "ok", reason: "CI token is current." };
8753
+ }
8754
+ async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
8755
+ const envPath = path5.join(projectDir, ".env");
8756
+ const databricksHost = readEnvVar(envPath, "DATABRICKS_HOST");
8757
+ const lakebaseProjectId = readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
8758
+ if (!databricksHost || !lakebaseProjectId) {
8759
+ return {
8760
+ action: "skipped",
8761
+ reason: "CI-auth preflight skipped: .env is missing DATABRICKS_HOST / LAKEBASE_PROJECT_ID."
8762
+ };
8763
+ }
8764
+ try {
8765
+ return await ensureCiSecretsFresh({
8766
+ projectDir,
8767
+ databricksHost,
8768
+ lakebaseProjectId,
8769
+ ownerRepo: opts?.ownerRepo,
8770
+ marginSeconds: opts?.marginSeconds
8771
+ });
8772
+ } catch (err) {
8773
+ return {
8774
+ action: "failed",
8775
+ reason: `CI-auth preflight could not re-mint (${err instanceof Error ? err.message : String(err)}); if CI fails on auth, run lakebase-sync-ci-secrets.`
8776
+ };
8665
8777
  }
8666
- await setRepoSecrets(ownerRepo, secrets);
8667
8778
  }
8668
8779
 
8669
8780
  // scripts/util/cli-entry.ts
@@ -8772,11 +8883,17 @@ async function pollUntilDefined(probe, opts) {
8772
8883
  }
8773
8884
  // Annotate the CommonJS export names for ESM import in node:
8774
8885
  0 && (module.exports = {
8886
+ CI_TOKEN_LIFETIME_SECONDS,
8887
+ CI_TOKEN_REMINT_MARGIN_SECONDS,
8775
8888
  LAKEBASE_BRANCH_NAME_MAX,
8776
8889
  PROXY_ENV_KEYS,
8777
8890
  REQUIRED_CI_SECRETS,
8891
+ ciTokenComment,
8892
+ ciTokenExpiry,
8778
8893
  copyDirSubstituted,
8779
8894
  delay,
8895
+ ensureCiSecretsFresh,
8896
+ ensureCiSecretsFreshFromEnv,
8780
8897
  exec,
8781
8898
  extractZipToDir,
8782
8899
  formatOwnerRepo,