@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.
- package/dist/ci-secrets-CnGrdQV-.d.cts +84 -0
- package/dist/ci-secrets-CnGrdQV-.d.ts +84 -0
- package/dist/scripts/index.cjs +2177 -2052
- package/dist/scripts/index.d.cts +2 -1
- package/dist/scripts/index.d.ts +2 -1
- package/dist/scripts/index.js +253 -134
- package/dist/scripts/lakebase/ci-resolve-branch.cli.cjs +2 -2
- package/dist/scripts/lakebase/ci-resolve-branch.cli.js +2 -2
- package/dist/scripts/lakebase/collapse-heads.cli.cjs +2 -2
- package/dist/scripts/lakebase/collapse-heads.cli.js +2 -2
- package/dist/scripts/lakebase/detect-language.cli.cjs +2 -2
- package/dist/scripts/lakebase/detect-language.cli.js +2 -2
- package/dist/scripts/lakebase/doctor.cli.cjs +2 -2
- package/dist/scripts/lakebase/doctor.cli.js +2 -2
- package/dist/scripts/lakebase/get-connection.cli.cjs +2 -2
- package/dist/scripts/lakebase/get-connection.cli.js +2 -2
- package/dist/scripts/lakebase/index.cjs +2163 -2050
- package/dist/scripts/lakebase/index.d.cts +8 -0
- package/dist/scripts/lakebase/index.d.ts +8 -0
- package/dist/scripts/lakebase/index.js +243 -130
- package/dist/scripts/lakebase/infra-runner.cli.cjs +2 -2
- package/dist/scripts/lakebase/infra-runner.cli.js +2 -2
- package/dist/scripts/lakebase/new-migration.cli.cjs +2 -2
- package/dist/scripts/lakebase/new-migration.cli.js +2 -2
- package/dist/scripts/lakebase/schema-diff.cli.cjs +2 -2
- package/dist/scripts/lakebase/schema-diff.cli.js +2 -2
- package/dist/scripts/lakebase/schema-migrate.cli.cjs +2 -2
- package/dist/scripts/lakebase/schema-migrate.cli.js +2 -2
- package/dist/scripts/lakebase/scm-claim-feature.cli.cjs +2 -2
- package/dist/scripts/lakebase/scm-claim-feature.cli.js +2 -2
- package/dist/scripts/lakebase/scm-doctor.cli.cjs +2 -2
- package/dist/scripts/lakebase/scm-doctor.cli.js +2 -2
- package/dist/scripts/lakebase/scm-merge.cli.cjs +2216 -1994
- package/dist/scripts/lakebase/scm-merge.cli.js +296 -74
- package/dist/scripts/lakebase/scm-prepare-pr.cli.cjs +479 -86
- package/dist/scripts/lakebase/scm-prepare-pr.cli.js +479 -86
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.cjs +2 -2
- package/dist/scripts/lakebase/scm-reconcile-tier.cli.js +2 -2
- package/dist/scripts/lakebase/sync-ci-secrets.cli.cjs +56 -30
- package/dist/scripts/lakebase/sync-ci-secrets.cli.js +56 -30
- package/dist/scripts/util/index.cjs +142 -25
- package/dist/scripts/util/index.d.cts +2 -27
- package/dist/scripts/util/index.d.ts +2 -27
- package/dist/scripts/util/index.js +136 -25
- package/package.json +1 -1
- package/scripts/lakebase/create-project.ts +2 -2
- package/scripts/lakebase/scm-merge.ts +21 -0
- package/scripts/lakebase/scm-prepare-pr.ts +10 -1
- package/scripts/lakebase/sync-ci-secrets.cli.ts +2 -2
- package/scripts/util/ci-secrets.ts +212 -26
- package/templates/project/common/scripts/create-token-and-sync-secrets.sh +9 -86
|
@@ -1913,9 +1913,9 @@ function asBranchUid(s) {
|
|
|
1913
1913
|
}
|
|
1914
1914
|
return s;
|
|
1915
1915
|
}
|
|
1916
|
-
function branchNameFromResourcePath(
|
|
1917
|
-
if (!
|
|
1918
|
-
const leaf =
|
|
1916
|
+
function branchNameFromResourcePath(path33) {
|
|
1917
|
+
if (!path33.includes("/branches/")) return null;
|
|
1918
|
+
const leaf = path33.split("/branches/").pop();
|
|
1919
1919
|
if (!leaf) return null;
|
|
1920
1920
|
try {
|
|
1921
1921
|
return asBranchName(leaf);
|
|
@@ -2518,8 +2518,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
2518
2518
|
var cached;
|
|
2519
2519
|
function substrateSelfVersion() {
|
|
2520
2520
|
if (cached !== void 0) return cached;
|
|
2521
|
-
if ("0.2.
|
|
2522
|
-
cached = "0.2.
|
|
2521
|
+
if ("0.2.49".length > 0) {
|
|
2522
|
+
cached = "0.2.49";
|
|
2523
2523
|
return cached;
|
|
2524
2524
|
}
|
|
2525
2525
|
cached = "unknown";
|
|
@@ -5059,7 +5059,7 @@ paginateRest.VERSION = VERSION5;
|
|
|
5059
5059
|
|
|
5060
5060
|
// node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
|
|
5061
5061
|
init_esm_shims();
|
|
5062
|
-
var generateMessage = (
|
|
5062
|
+
var generateMessage = (path33, cursorValue) => `The cursor at "${path33.join(
|
|
5063
5063
|
","
|
|
5064
5064
|
)}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
|
|
5065
5065
|
var MissingCursorChange = class extends Error {
|
|
@@ -5100,9 +5100,9 @@ function findPaginatedResourcePath(responseData) {
|
|
|
5100
5100
|
}
|
|
5101
5101
|
return paginatedResourcePath;
|
|
5102
5102
|
}
|
|
5103
|
-
var deepFindPathToProperty = (object, searchProp,
|
|
5103
|
+
var deepFindPathToProperty = (object, searchProp, path33 = []) => {
|
|
5104
5104
|
for (const key of Object.keys(object)) {
|
|
5105
|
-
const currentPath = [...
|
|
5105
|
+
const currentPath = [...path33, key];
|
|
5106
5106
|
const currentValue = object[key];
|
|
5107
5107
|
if (isObject(currentValue)) {
|
|
5108
5108
|
if (currentValue.hasOwnProperty(searchProp)) {
|
|
@@ -5120,12 +5120,12 @@ var deepFindPathToProperty = (object, searchProp, path32 = []) => {
|
|
|
5120
5120
|
}
|
|
5121
5121
|
return [];
|
|
5122
5122
|
};
|
|
5123
|
-
var get = (object,
|
|
5124
|
-
return
|
|
5123
|
+
var get = (object, path33) => {
|
|
5124
|
+
return path33.reduce((current, nextProperty) => current[nextProperty], object);
|
|
5125
5125
|
};
|
|
5126
|
-
var set = (object,
|
|
5127
|
-
const lastProperty =
|
|
5128
|
-
const parentPath = [...
|
|
5126
|
+
var set = (object, path33, mutator) => {
|
|
5127
|
+
const lastProperty = path33[path33.length - 1];
|
|
5128
|
+
const parentPath = [...path33].slice(0, -1);
|
|
5129
5129
|
const parent = get(object, parentPath);
|
|
5130
5130
|
if (typeof mutator === "function") {
|
|
5131
5131
|
parent[lastProperty] = mutator(parent[lastProperty]);
|
|
@@ -5177,22 +5177,22 @@ var mergeResponses = (response1, response2) => {
|
|
|
5177
5177
|
if (Object.keys(response1).length === 0) {
|
|
5178
5178
|
return Object.assign(response1, response2);
|
|
5179
5179
|
}
|
|
5180
|
-
const
|
|
5181
|
-
const nodesPath = [...
|
|
5180
|
+
const path33 = findPaginatedResourcePath(response1);
|
|
5181
|
+
const nodesPath = [...path33, "nodes"];
|
|
5182
5182
|
const newNodes = get(response2, nodesPath);
|
|
5183
5183
|
if (newNodes) {
|
|
5184
5184
|
set(response1, nodesPath, (values) => {
|
|
5185
5185
|
return [...values, ...newNodes];
|
|
5186
5186
|
});
|
|
5187
5187
|
}
|
|
5188
|
-
const edgesPath = [...
|
|
5188
|
+
const edgesPath = [...path33, "edges"];
|
|
5189
5189
|
const newEdges = get(response2, edgesPath);
|
|
5190
5190
|
if (newEdges) {
|
|
5191
5191
|
set(response1, edgesPath, (values) => {
|
|
5192
5192
|
return [...values, ...newEdges];
|
|
5193
5193
|
});
|
|
5194
5194
|
}
|
|
5195
|
-
const pageInfoPath = [...
|
|
5195
|
+
const pageInfoPath = [...path33, "pageInfo"];
|
|
5196
5196
|
set(response1, pageInfoPath, get(response2, pageInfoPath));
|
|
5197
5197
|
return response1;
|
|
5198
5198
|
};
|
|
@@ -7613,7 +7613,7 @@ var triggers_notification_paths_default = [
|
|
|
7613
7613
|
];
|
|
7614
7614
|
function routeMatcher(paths) {
|
|
7615
7615
|
const regexes = paths.map(
|
|
7616
|
-
(
|
|
7616
|
+
(path33) => path33.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
|
7617
7617
|
);
|
|
7618
7618
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
|
7619
7619
|
return new RegExp(regex2, "i");
|
|
@@ -10941,16 +10941,16 @@ function isAllSchemas(schema) {
|
|
|
10941
10941
|
}
|
|
10942
10942
|
function buildSchemaQuery(schema) {
|
|
10943
10943
|
const cols = "c.table_schema, c.table_name, c.column_name, c.data_type";
|
|
10944
|
-
const
|
|
10944
|
+
const join34 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
|
|
10945
10945
|
if (isAllSchemas(schema)) {
|
|
10946
10946
|
return {
|
|
10947
|
-
text: `SELECT ${cols} ` +
|
|
10947
|
+
text: `SELECT ${cols} ` + join34 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
|
|
10948
10948
|
values: []
|
|
10949
10949
|
};
|
|
10950
10950
|
}
|
|
10951
10951
|
const one = (schema ?? "").trim() || "public";
|
|
10952
10952
|
return {
|
|
10953
|
-
text: `SELECT ${cols} ` +
|
|
10953
|
+
text: `SELECT ${cols} ` + join34 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
|
|
10954
10954
|
values: [one]
|
|
10955
10955
|
};
|
|
10956
10956
|
}
|
|
@@ -11111,7 +11111,7 @@ async function withLakebaseRollback(opts, fn) {
|
|
|
11111
11111
|
// scripts/lakebase/create-project.ts
|
|
11112
11112
|
init_esm_shims();
|
|
11113
11113
|
import * as fs18 from "fs";
|
|
11114
|
-
import * as
|
|
11114
|
+
import * as path18 from "path";
|
|
11115
11115
|
|
|
11116
11116
|
// scripts/lakebase/project-verify.ts
|
|
11117
11117
|
init_esm_shims();
|
|
@@ -12865,6 +12865,7 @@ async function removeRunner(args) {
|
|
|
12865
12865
|
|
|
12866
12866
|
// scripts/util/ci-secrets.ts
|
|
12867
12867
|
init_esm_shims();
|
|
12868
|
+
import * as path16 from "path";
|
|
12868
12869
|
|
|
12869
12870
|
// scripts/github/secrets.ts
|
|
12870
12871
|
init_esm_shims();
|
|
@@ -12974,13 +12975,40 @@ async function getOwnerRepo(cwd) {
|
|
|
12974
12975
|
|
|
12975
12976
|
// scripts/util/ci-secrets.ts
|
|
12976
12977
|
var REQUIRED_CI_SECRETS = ["DATABRICKS_HOST", "LAKEBASE_PROJECT_ID", "DATABRICKS_TOKEN"];
|
|
12978
|
+
var CI_TOKEN_LIFETIME_SECONDS = 7776e3;
|
|
12979
|
+
var CI_TOKEN_REMINT_MARGIN_SECONDS = 86400;
|
|
12980
|
+
function ciTokenComment(ownerRepo) {
|
|
12981
|
+
const repoName = ownerRepo.includes("/") ? ownerRepo.slice(ownerRepo.lastIndexOf("/") + 1) : ownerRepo;
|
|
12982
|
+
return `GitHub Actions (${repoName})`;
|
|
12983
|
+
}
|
|
12977
12984
|
async function missingCiSecrets(ownerRepo) {
|
|
12978
12985
|
const present = new Set(await listSecretNames(ownerRepo));
|
|
12979
12986
|
return REQUIRED_CI_SECRETS.filter((n) => !present.has(n));
|
|
12980
12987
|
}
|
|
12988
|
+
async function mintCiToken(args) {
|
|
12989
|
+
try {
|
|
12990
|
+
const raw = await runDatabricks(
|
|
12991
|
+
["tokens", "create", "--comment", args.comment, "--lifetime-seconds", String(args.lifetimeSeconds), "-o", "json"],
|
|
12992
|
+
{ host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
|
|
12993
|
+
);
|
|
12994
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
|
|
12995
|
+
const token = parsed.token_value || parsed.token || "";
|
|
12996
|
+
if (token) return token;
|
|
12997
|
+
} catch {
|
|
12998
|
+
}
|
|
12999
|
+
try {
|
|
13000
|
+
const raw = await runDatabricks(["auth", "token", "-o", "json"], {
|
|
13001
|
+
host: args.databricksHost,
|
|
13002
|
+
cwd: args.projectDir,
|
|
13003
|
+
timeout: 3e4
|
|
13004
|
+
});
|
|
13005
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
|
|
13006
|
+
return parsed.access_token || "";
|
|
13007
|
+
} catch {
|
|
13008
|
+
return "";
|
|
13009
|
+
}
|
|
13010
|
+
}
|
|
12981
13011
|
async function syncCiSecrets(args) {
|
|
12982
|
-
const lifetime = args.lifetimeSeconds ?? 86400;
|
|
12983
|
-
const comment = args.comment ?? "GitHub Actions CI";
|
|
12984
13012
|
const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
|
|
12985
13013
|
if (!ownerRepo) {
|
|
12986
13014
|
throw new Error("Could not resolve GitHub repository from git remote");
|
|
@@ -12991,27 +13019,104 @@ async function syncCiSecrets(args) {
|
|
|
12991
13019
|
if (!args.lakebaseProjectId) {
|
|
12992
13020
|
throw new Error("syncCiSecrets: lakebaseProjectId is required");
|
|
12993
13021
|
}
|
|
13022
|
+
const lifetime = args.lifetimeSeconds ?? CI_TOKEN_LIFETIME_SECONDS;
|
|
13023
|
+
const comment = args.comment ?? ciTokenComment(ownerRepo);
|
|
12994
13024
|
const secrets = {
|
|
12995
13025
|
DATABRICKS_HOST: args.databricksHost,
|
|
12996
13026
|
LAKEBASE_PROJECT_ID: args.lakebaseProjectId
|
|
12997
13027
|
};
|
|
13028
|
+
const token = await mintCiToken({
|
|
13029
|
+
databricksHost: args.databricksHost,
|
|
13030
|
+
projectDir: args.projectDir,
|
|
13031
|
+
comment,
|
|
13032
|
+
lifetimeSeconds: lifetime
|
|
13033
|
+
});
|
|
13034
|
+
if (token) secrets.DATABRICKS_TOKEN = token;
|
|
13035
|
+
await setRepoSecrets(ownerRepo, secrets);
|
|
13036
|
+
}
|
|
13037
|
+
async function ciTokenExpiry(args) {
|
|
13038
|
+
const comment = ciTokenComment(args.ownerRepo);
|
|
13039
|
+
let raw;
|
|
12998
13040
|
try {
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
const token = parsed.token_value || parsed.token || "";
|
|
13005
|
-
if (token) secrets.DATABRICKS_TOKEN = token;
|
|
13041
|
+
raw = await runDatabricks(["tokens", "list", "-o", "json"], {
|
|
13042
|
+
host: args.databricksHost,
|
|
13043
|
+
cwd: args.projectDir,
|
|
13044
|
+
timeout: 3e4
|
|
13045
|
+
});
|
|
13006
13046
|
} catch {
|
|
13047
|
+
return null;
|
|
13048
|
+
}
|
|
13049
|
+
let infos;
|
|
13050
|
+
try {
|
|
13051
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("["))));
|
|
13052
|
+
infos = Array.isArray(parsed) ? parsed : [];
|
|
13053
|
+
} catch {
|
|
13054
|
+
return null;
|
|
13055
|
+
}
|
|
13056
|
+
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);
|
|
13057
|
+
if (expiries.length === 0) return null;
|
|
13058
|
+
return Math.max(...expiries);
|
|
13059
|
+
}
|
|
13060
|
+
async function ensureCiSecretsFresh(args) {
|
|
13061
|
+
const now = args.now ?? Date.now;
|
|
13062
|
+
const marginMs = (args.marginSeconds ?? CI_TOKEN_REMINT_MARGIN_SECONDS) * 1e3;
|
|
13063
|
+
const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
|
|
13064
|
+
if (!ownerRepo) {
|
|
13065
|
+
throw new Error("Could not resolve GitHub repository from git remote");
|
|
13066
|
+
}
|
|
13067
|
+
const sync = () => syncCiSecrets({
|
|
13068
|
+
projectDir: args.projectDir,
|
|
13069
|
+
databricksHost: args.databricksHost,
|
|
13070
|
+
lakebaseProjectId: args.lakebaseProjectId,
|
|
13071
|
+
ownerRepo
|
|
13072
|
+
});
|
|
13073
|
+
const missing = await missingCiSecrets(ownerRepo);
|
|
13074
|
+
if (missing.length > 0) {
|
|
13075
|
+
await sync();
|
|
13076
|
+
return { action: "provisioned", reason: `CI secret(s) were missing (${missing.join(", ")}); provisioned.` };
|
|
13077
|
+
}
|
|
13078
|
+
const expiry = await ciTokenExpiry({ projectDir: args.projectDir, databricksHost: args.databricksHost, ownerRepo });
|
|
13079
|
+
if (expiry === null) {
|
|
13080
|
+
await sync();
|
|
13081
|
+
return { action: "reminted", reason: "no live CI token found (expired or minted under a different identity); re-minted." };
|
|
13082
|
+
}
|
|
13083
|
+
if (expiry !== Number.POSITIVE_INFINITY && expiry < now() + marginMs) {
|
|
13084
|
+
await sync();
|
|
13085
|
+
const hrs = Math.max(0, Math.round((expiry - now()) / 36e5));
|
|
13086
|
+
return { action: "reminted", reason: `CI token expires in ~${hrs}h (within the re-mint margin); re-minted.` };
|
|
13087
|
+
}
|
|
13088
|
+
return { action: "ok", reason: "CI token is current." };
|
|
13089
|
+
}
|
|
13090
|
+
async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
|
|
13091
|
+
const envPath = path16.join(projectDir, ".env");
|
|
13092
|
+
const databricksHost = readEnvVar(envPath, "DATABRICKS_HOST");
|
|
13093
|
+
const lakebaseProjectId = readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
|
|
13094
|
+
if (!databricksHost || !lakebaseProjectId) {
|
|
13095
|
+
return {
|
|
13096
|
+
action: "skipped",
|
|
13097
|
+
reason: "CI-auth preflight skipped: .env is missing DATABRICKS_HOST / LAKEBASE_PROJECT_ID."
|
|
13098
|
+
};
|
|
13099
|
+
}
|
|
13100
|
+
try {
|
|
13101
|
+
return await ensureCiSecretsFresh({
|
|
13102
|
+
projectDir,
|
|
13103
|
+
databricksHost,
|
|
13104
|
+
lakebaseProjectId,
|
|
13105
|
+
ownerRepo: opts?.ownerRepo,
|
|
13106
|
+
marginSeconds: opts?.marginSeconds
|
|
13107
|
+
});
|
|
13108
|
+
} catch (err) {
|
|
13109
|
+
return {
|
|
13110
|
+
action: "failed",
|
|
13111
|
+
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.`
|
|
13112
|
+
};
|
|
13007
13113
|
}
|
|
13008
|
-
await setRepoSecrets(ownerRepo, secrets);
|
|
13009
13114
|
}
|
|
13010
13115
|
|
|
13011
13116
|
// scripts/lakebase/scm-workflow-state.ts
|
|
13012
13117
|
init_esm_shims();
|
|
13013
13118
|
import * as fs17 from "fs";
|
|
13014
|
-
import * as
|
|
13119
|
+
import * as path17 from "path";
|
|
13015
13120
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
13016
13121
|
function isGitTracked(projectDir, rel) {
|
|
13017
13122
|
try {
|
|
@@ -13030,7 +13135,7 @@ function ensureWorkflowStateUntracked(projectDir) {
|
|
|
13030
13135
|
} catch {
|
|
13031
13136
|
}
|
|
13032
13137
|
try {
|
|
13033
|
-
const gitignore =
|
|
13138
|
+
const gitignore = path17.join(projectDir, ".gitignore");
|
|
13034
13139
|
const existing = fs17.existsSync(gitignore) ? fs17.readFileSync(gitignore, "utf8") : "";
|
|
13035
13140
|
if (!existing.split("\n").some((l) => l.trim() === rel)) {
|
|
13036
13141
|
const sep4 = existing === "" || existing.endsWith("\n") ? "" : "\n";
|
|
@@ -13058,7 +13163,7 @@ var STATE_INDEX = SCM_STATES.reduce(
|
|
|
13058
13163
|
);
|
|
13059
13164
|
var STATE_FILE_REL = ".lakebase/workflow-state.json";
|
|
13060
13165
|
function stateFilePath(projectDir) {
|
|
13061
|
-
return
|
|
13166
|
+
return path17.join(projectDir, STATE_FILE_REL);
|
|
13062
13167
|
}
|
|
13063
13168
|
function readWorkflowState(projectDir) {
|
|
13064
13169
|
const p = stateFilePath(projectDir);
|
|
@@ -13098,7 +13203,7 @@ function writeWorkflowState(projectDir, state) {
|
|
|
13098
13203
|
${summary}`);
|
|
13099
13204
|
}
|
|
13100
13205
|
ensureWorkflowStateUntracked(projectDir);
|
|
13101
|
-
const dir =
|
|
13206
|
+
const dir = path17.join(projectDir, ".lakebase");
|
|
13102
13207
|
fs17.mkdirSync(dir, { recursive: true });
|
|
13103
13208
|
const target = stateFilePath(projectDir);
|
|
13104
13209
|
const tmp = `${target}.tmp`;
|
|
@@ -13329,7 +13434,7 @@ function orderForOutput(state) {
|
|
|
13329
13434
|
async function createProject(input, progress) {
|
|
13330
13435
|
const report = progress ?? (() => {
|
|
13331
13436
|
});
|
|
13332
|
-
const projectDir =
|
|
13437
|
+
const projectDir = path18.join(input.parentDir, input.projectName);
|
|
13333
13438
|
const lakebaseProjectId = input.projectName;
|
|
13334
13439
|
const host = input.databricksHost.replace(/\/+$/, "");
|
|
13335
13440
|
const useGithub = input.createGithubRepo !== false;
|
|
@@ -13490,8 +13595,6 @@ Last probe error:
|
|
|
13490
13595
|
projectDir,
|
|
13491
13596
|
databricksHost: host,
|
|
13492
13597
|
lakebaseProjectId,
|
|
13493
|
-
comment: "GitHub Actions CI",
|
|
13494
|
-
lifetimeSeconds: 86400,
|
|
13495
13598
|
ownerRepo: fullRepoName
|
|
13496
13599
|
});
|
|
13497
13600
|
const missing = await missingCiSecrets(fullRepoName);
|
|
@@ -13558,9 +13661,9 @@ Last probe error:
|
|
|
13558
13661
|
const scmRef = envRef || (ver !== "unknown" ? `v${ver}` : "");
|
|
13559
13662
|
if (scmRef) {
|
|
13560
13663
|
try {
|
|
13561
|
-
const dir =
|
|
13664
|
+
const dir = path18.join(projectDir, ".lakebase");
|
|
13562
13665
|
fs18.mkdirSync(dir, { recursive: true });
|
|
13563
|
-
fs18.writeFileSync(
|
|
13666
|
+
fs18.writeFileSync(path18.join(dir, "scm-utils-ref"), `${scmRef}
|
|
13564
13667
|
`, "utf8");
|
|
13565
13668
|
} catch (err) {
|
|
13566
13669
|
warnings.push(`Substrate ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13571,9 +13674,9 @@ Last probe error:
|
|
|
13571
13674
|
const kitRef = process.env.LAKEBASE_KIT_REF?.trim();
|
|
13572
13675
|
if (kitRef) {
|
|
13573
13676
|
try {
|
|
13574
|
-
const dir =
|
|
13677
|
+
const dir = path18.join(projectDir, ".lakebase");
|
|
13575
13678
|
fs18.mkdirSync(dir, { recursive: true });
|
|
13576
|
-
fs18.writeFileSync(
|
|
13679
|
+
fs18.writeFileSync(path18.join(dir, "kit-ref"), `${kitRef}
|
|
13577
13680
|
`, "utf8");
|
|
13578
13681
|
} catch (err) {
|
|
13579
13682
|
warnings.push(`Kit ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13655,7 +13758,7 @@ Last probe error:
|
|
|
13655
13758
|
init_esm_shims();
|
|
13656
13759
|
import * as cp5 from "child_process";
|
|
13657
13760
|
import * as fs19 from "fs";
|
|
13658
|
-
import * as
|
|
13761
|
+
import * as path19 from "path";
|
|
13659
13762
|
async function adoptLakebaseProject(args) {
|
|
13660
13763
|
const warnings = [];
|
|
13661
13764
|
const filesWritten = [];
|
|
@@ -13664,7 +13767,7 @@ async function adoptLakebaseProject(args) {
|
|
|
13664
13767
|
if (!fs19.existsSync(args.projectDir)) {
|
|
13665
13768
|
throw new Error(`adoptLakebaseProject: project directory does not exist: ${args.projectDir}`);
|
|
13666
13769
|
}
|
|
13667
|
-
if (!fs19.existsSync(
|
|
13770
|
+
if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
|
|
13668
13771
|
throw new Error(
|
|
13669
13772
|
`adoptLakebaseProject: ${args.projectDir} is not a git repo. Run \`git init\` first, or pass an existing repo path.`
|
|
13670
13773
|
);
|
|
@@ -13730,7 +13833,7 @@ async function adoptLakebaseProject(args) {
|
|
|
13730
13833
|
};
|
|
13731
13834
|
}
|
|
13732
13835
|
function assertEnvCompatibility(projectDir, expectedProjectId) {
|
|
13733
|
-
const envPath =
|
|
13836
|
+
const envPath = path19.join(projectDir, ".env");
|
|
13734
13837
|
if (!fs19.existsSync(envPath)) return;
|
|
13735
13838
|
const content = fs19.readFileSync(envPath, "utf8");
|
|
13736
13839
|
const match = content.match(/^LAKEBASE_PROJECT_ID\s*=\s*(.+?)\s*$/m);
|
|
@@ -13746,7 +13849,7 @@ function assertAdoptionPreflight(args) {
|
|
|
13746
13849
|
if (!fs19.existsSync(args.projectDir)) {
|
|
13747
13850
|
throw new Error(`assertAdoptionPreflight: project directory does not exist: ${args.projectDir}`);
|
|
13748
13851
|
}
|
|
13749
|
-
if (!fs19.existsSync(
|
|
13852
|
+
if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
|
|
13750
13853
|
throw new Error(
|
|
13751
13854
|
`assertAdoptionPreflight: ${args.projectDir} is not a git repo.`
|
|
13752
13855
|
);
|
|
@@ -13760,7 +13863,7 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
13760
13863
|
cp5.execSync("git init --quiet", { cwd: opts.dir, stdio: "pipe" });
|
|
13761
13864
|
if (opts.packageJson) {
|
|
13762
13865
|
fs19.writeFileSync(
|
|
13763
|
-
|
|
13866
|
+
path19.join(opts.dir, "package.json"),
|
|
13764
13867
|
JSON.stringify(opts.packageJson, null, 2) + "\n"
|
|
13765
13868
|
);
|
|
13766
13869
|
}
|
|
@@ -13769,7 +13872,7 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
13769
13872
|
// scripts/lakebase/infra-runner.ts
|
|
13770
13873
|
init_esm_shims();
|
|
13771
13874
|
import * as fs27 from "fs";
|
|
13772
|
-
import * as
|
|
13875
|
+
import * as path28 from "path";
|
|
13773
13876
|
|
|
13774
13877
|
// scripts/lakebase/schema-diff.ts
|
|
13775
13878
|
init_esm_shims();
|
|
@@ -13966,12 +14069,12 @@ function dbcli6(args) {
|
|
|
13966
14069
|
// scripts/lakebase/schema-migrate.ts
|
|
13967
14070
|
init_esm_shims();
|
|
13968
14071
|
import * as fs26 from "fs";
|
|
13969
|
-
import * as
|
|
14072
|
+
import * as path27 from "path";
|
|
13970
14073
|
|
|
13971
14074
|
// scripts/lakebase/migration-layout.ts
|
|
13972
14075
|
init_esm_shims();
|
|
13973
14076
|
import * as fs20 from "fs";
|
|
13974
|
-
import * as
|
|
14077
|
+
import * as path20 from "path";
|
|
13975
14078
|
var MIGRATION_LANGUAGES = [
|
|
13976
14079
|
"java",
|
|
13977
14080
|
"kotlin",
|
|
@@ -13987,13 +14090,13 @@ var MIGRATION_DEFAULTS = {
|
|
|
13987
14090
|
unknown: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" }
|
|
13988
14091
|
};
|
|
13989
14092
|
function detectLanguageAt(dir) {
|
|
13990
|
-
if (fs20.existsSync(
|
|
13991
|
-
const kotlinDir =
|
|
14093
|
+
if (fs20.existsSync(path20.join(dir, "pom.xml"))) {
|
|
14094
|
+
const kotlinDir = path20.join(dir, "src", "main", "kotlin");
|
|
13992
14095
|
if (fs20.existsSync(kotlinDir)) {
|
|
13993
14096
|
return "kotlin";
|
|
13994
14097
|
}
|
|
13995
14098
|
try {
|
|
13996
|
-
const pom = fs20.readFileSync(
|
|
14099
|
+
const pom = fs20.readFileSync(path20.join(dir, "pom.xml"), "utf-8");
|
|
13997
14100
|
if (pom.includes("kotlin-maven-plugin")) {
|
|
13998
14101
|
return "kotlin";
|
|
13999
14102
|
}
|
|
@@ -14001,10 +14104,10 @@ function detectLanguageAt(dir) {
|
|
|
14001
14104
|
}
|
|
14002
14105
|
return "java";
|
|
14003
14106
|
}
|
|
14004
|
-
if (fs20.existsSync(
|
|
14107
|
+
if (fs20.existsSync(path20.join(dir, "pyproject.toml")) || fs20.existsSync(path20.join(dir, "requirements.txt")) || fs20.existsSync(path20.join(dir, "alembic.ini"))) {
|
|
14005
14108
|
return "python";
|
|
14006
14109
|
}
|
|
14007
|
-
if (fs20.existsSync(
|
|
14110
|
+
if (fs20.existsSync(path20.join(dir, "package.json"))) {
|
|
14008
14111
|
return "nodejs";
|
|
14009
14112
|
}
|
|
14010
14113
|
return "unknown";
|
|
@@ -14025,14 +14128,14 @@ function resolveMigrationLanguage(projectDir, configuredMigrationPath, override)
|
|
|
14025
14128
|
if (!rel) {
|
|
14026
14129
|
return "unknown";
|
|
14027
14130
|
}
|
|
14028
|
-
const rootResolved =
|
|
14029
|
-
let dir =
|
|
14030
|
-
while (dir === rootResolved || dir.startsWith(rootResolved +
|
|
14131
|
+
const rootResolved = path20.resolve(projectDir);
|
|
14132
|
+
let dir = path20.resolve(projectDir, rel);
|
|
14133
|
+
while (dir === rootResolved || dir.startsWith(rootResolved + path20.sep)) {
|
|
14031
14134
|
const lang = detectLanguageAt(dir);
|
|
14032
14135
|
if (lang !== "unknown") {
|
|
14033
14136
|
return lang;
|
|
14034
14137
|
}
|
|
14035
|
-
const parent =
|
|
14138
|
+
const parent = path20.dirname(dir);
|
|
14036
14139
|
if (parent === dir) {
|
|
14037
14140
|
break;
|
|
14038
14141
|
}
|
|
@@ -14066,17 +14169,17 @@ function resolveMigrationLayout(args) {
|
|
|
14066
14169
|
// scripts/lakebase/adapters/alembic-adapter.ts
|
|
14067
14170
|
init_esm_shims();
|
|
14068
14171
|
import * as fs22 from "fs";
|
|
14069
|
-
import * as
|
|
14172
|
+
import * as path22 from "path";
|
|
14070
14173
|
|
|
14071
14174
|
// scripts/lakebase/schema-migrate-runners/alembic.ts
|
|
14072
14175
|
init_esm_shims();
|
|
14073
14176
|
import { spawn as spawn5 } from "child_process";
|
|
14074
14177
|
import * as fs21 from "fs";
|
|
14075
|
-
import * as
|
|
14178
|
+
import * as path21 from "path";
|
|
14076
14179
|
function resolveAlembicBin(projectDir) {
|
|
14077
14180
|
const candidates = [
|
|
14078
|
-
|
|
14079
|
-
|
|
14181
|
+
path21.join(projectDir, ".venv", "bin", "alembic"),
|
|
14182
|
+
path21.join(projectDir, "venv", "bin", "alembic")
|
|
14080
14183
|
];
|
|
14081
14184
|
for (const candidate of candidates) {
|
|
14082
14185
|
try {
|
|
@@ -14090,7 +14193,7 @@ function spawnAlembic(projectDir, args, dsn) {
|
|
|
14090
14193
|
return new Promise((resolve2, reject) => {
|
|
14091
14194
|
const bin = resolveAlembicBin(projectDir);
|
|
14092
14195
|
const env = { ...process.env };
|
|
14093
|
-
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(
|
|
14196
|
+
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path21.delimiter);
|
|
14094
14197
|
if (dsn) env.DATABASE_URL = dsn;
|
|
14095
14198
|
const child = spawn5(bin, args, {
|
|
14096
14199
|
cwd: projectDir,
|
|
@@ -14138,10 +14241,10 @@ async function createAlembicRevision(opts) {
|
|
|
14138
14241
|
const m = stdout.match(/Generating\s+(\S+\.py)/);
|
|
14139
14242
|
if (m) return m[1].trim();
|
|
14140
14243
|
for (const rel of ["migrations/versions", "alembic/versions"]) {
|
|
14141
|
-
const dir =
|
|
14244
|
+
const dir = path21.join(opts.projectDir, rel);
|
|
14142
14245
|
if (!fs21.existsSync(dir)) continue;
|
|
14143
14246
|
const hit = fs21.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
|
|
14144
|
-
if (hit) return
|
|
14247
|
+
if (hit) return path21.join(dir, hit);
|
|
14145
14248
|
}
|
|
14146
14249
|
throw new SchemaMigrationError(
|
|
14147
14250
|
`alembic revision succeeded but the created file could not be located.
|
|
@@ -14276,8 +14379,8 @@ async function buildDsn2(args) {
|
|
|
14276
14379
|
}
|
|
14277
14380
|
function findVersionsDir(projectDir) {
|
|
14278
14381
|
const candidates = [
|
|
14279
|
-
|
|
14280
|
-
|
|
14382
|
+
path22.join(projectDir, "migrations", "versions"),
|
|
14383
|
+
path22.join(projectDir, "alembic", "versions")
|
|
14281
14384
|
];
|
|
14282
14385
|
return candidates.find((p) => fs22.existsSync(p));
|
|
14283
14386
|
}
|
|
@@ -14309,9 +14412,9 @@ var AlembicAdapter = {
|
|
|
14309
14412
|
* here. Callers can still force-select via project.yaml#migration_tool.
|
|
14310
14413
|
*/
|
|
14311
14414
|
detect(projectDir) {
|
|
14312
|
-
if (fs22.existsSync(
|
|
14313
|
-
if (fs22.existsSync(
|
|
14314
|
-
if (fs22.existsSync(
|
|
14415
|
+
if (fs22.existsSync(path22.join(projectDir, "alembic.ini"))) return true;
|
|
14416
|
+
if (fs22.existsSync(path22.join(projectDir, "migrations", "env.py"))) return true;
|
|
14417
|
+
if (fs22.existsSync(path22.join(projectDir, "alembic", "env.py"))) return true;
|
|
14315
14418
|
return false;
|
|
14316
14419
|
},
|
|
14317
14420
|
async apply(args) {
|
|
@@ -14417,7 +14520,7 @@ var AlembicAdapter = {
|
|
|
14417
14520
|
autogenerate: !!args.autogenerate,
|
|
14418
14521
|
dsn
|
|
14419
14522
|
});
|
|
14420
|
-
return { status: "ok", version: revId, filename:
|
|
14523
|
+
return { status: "ok", version: revId, filename: path22.basename(created), path: created };
|
|
14421
14524
|
} catch (err) {
|
|
14422
14525
|
return {
|
|
14423
14526
|
status: "error",
|
|
@@ -14434,7 +14537,7 @@ var AlembicAdapter = {
|
|
|
14434
14537
|
if (heads.length <= 1) return { status: "noop", headsBefore: heads };
|
|
14435
14538
|
if (args.dryRun) return { status: "ok", headsBefore: heads };
|
|
14436
14539
|
const created = await mergeAlembicHeads(args.projectDir, args.message ?? "merge heads");
|
|
14437
|
-
const mergeRevision =
|
|
14540
|
+
const mergeRevision = path22.basename(created).replace(/\.py$/, "").split("_")[0];
|
|
14438
14541
|
return { status: "ok", headsBefore: heads, mergeRevision, path: created };
|
|
14439
14542
|
} catch (err) {
|
|
14440
14543
|
return {
|
|
@@ -14450,12 +14553,12 @@ registerSchemaMigrationAdapter(AlembicAdapter);
|
|
|
14450
14553
|
// scripts/lakebase/adapters/flyway-adapter.ts
|
|
14451
14554
|
init_esm_shims();
|
|
14452
14555
|
import * as fs23 from "fs";
|
|
14453
|
-
import * as
|
|
14556
|
+
import * as path24 from "path";
|
|
14454
14557
|
|
|
14455
14558
|
// scripts/lakebase/schema-migrate-runners/flyway.ts
|
|
14456
14559
|
init_esm_shims();
|
|
14457
14560
|
import { spawn as spawn6 } from "child_process";
|
|
14458
|
-
import * as
|
|
14561
|
+
import * as path23 from "path";
|
|
14459
14562
|
function dsnToFlywayEnv(dsn) {
|
|
14460
14563
|
const u = new URL(dsn);
|
|
14461
14564
|
const user = decodeURIComponent(u.username);
|
|
@@ -14465,7 +14568,7 @@ function dsnToFlywayEnv(dsn) {
|
|
|
14465
14568
|
return { url, user, password };
|
|
14466
14569
|
}
|
|
14467
14570
|
function migrationsLocation(projectDir) {
|
|
14468
|
-
return `filesystem:${
|
|
14571
|
+
return `filesystem:${path23.join(projectDir, "src", "main", "resources", "db", "migration")}`;
|
|
14469
14572
|
}
|
|
14470
14573
|
function runFlyway(ctx, args) {
|
|
14471
14574
|
const { url, user, password } = dsnToFlywayEnv(ctx.dsn);
|
|
@@ -14566,7 +14669,7 @@ async function statusFlyway(ctx) {
|
|
|
14566
14669
|
if (state === "SUCCESS" || state === "BASELINE") {
|
|
14567
14670
|
current = m.version;
|
|
14568
14671
|
} else if (state === "PENDING") {
|
|
14569
|
-
const filename = m.filepath ?
|
|
14672
|
+
const filename = m.filepath ? path23.basename(m.filepath) : `V${m.version}__migration.sql`;
|
|
14570
14673
|
pending.push({
|
|
14571
14674
|
version: m.version,
|
|
14572
14675
|
filename,
|
|
@@ -14589,7 +14692,7 @@ async function buildDsn3(args) {
|
|
|
14589
14692
|
return result.url;
|
|
14590
14693
|
}
|
|
14591
14694
|
function listFlywayFiles(projectDir) {
|
|
14592
|
-
const dir =
|
|
14695
|
+
const dir = path24.join(projectDir, "src", "main", "resources", "db", "migration");
|
|
14593
14696
|
if (!fs23.existsSync(dir)) return [];
|
|
14594
14697
|
const files = fs23.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
14595
14698
|
return files.map((filename) => {
|
|
@@ -14614,7 +14717,7 @@ var FlywayAdapter = {
|
|
|
14614
14717
|
id: "flyway",
|
|
14615
14718
|
languages: ["java", "kotlin"],
|
|
14616
14719
|
detect(projectDir) {
|
|
14617
|
-
return fs23.existsSync(
|
|
14720
|
+
return fs23.existsSync(path24.join(projectDir, "pom.xml"));
|
|
14618
14721
|
},
|
|
14619
14722
|
async apply(args) {
|
|
14620
14723
|
const dsn = await buildDsn3(args);
|
|
@@ -14672,12 +14775,12 @@ var FlywayAdapter = {
|
|
|
14672
14775
|
// optional-protocol shape makes this additive.
|
|
14673
14776
|
async newMigration(args) {
|
|
14674
14777
|
try {
|
|
14675
|
-
const dir =
|
|
14778
|
+
const dir = path24.join(args.projectDir, "src", "main", "resources", "db", "migration");
|
|
14676
14779
|
fs23.mkdirSync(dir, { recursive: true });
|
|
14677
14780
|
const version = migrationTimestamp();
|
|
14678
14781
|
const slug = migrationSlug2(args.slug);
|
|
14679
14782
|
const filename = `V${version}__${slug}.sql`;
|
|
14680
|
-
const full =
|
|
14783
|
+
const full = path24.join(dir, filename);
|
|
14681
14784
|
if (fs23.existsSync(full)) throw new Error(`${filename} already exists`);
|
|
14682
14785
|
fs23.writeFileSync(
|
|
14683
14786
|
full,
|
|
@@ -14703,17 +14806,17 @@ registerSchemaMigrationAdapter(FlywayAdapter);
|
|
|
14703
14806
|
// scripts/lakebase/adapters/knex-adapter.ts
|
|
14704
14807
|
init_esm_shims();
|
|
14705
14808
|
import * as fs25 from "fs";
|
|
14706
|
-
import * as
|
|
14809
|
+
import * as path26 from "path";
|
|
14707
14810
|
|
|
14708
14811
|
// scripts/lakebase/schema-migrate-runners/knex.ts
|
|
14709
14812
|
init_esm_shims();
|
|
14710
14813
|
import { spawn as spawn7 } from "child_process";
|
|
14711
14814
|
import * as fs24 from "fs";
|
|
14712
|
-
import * as
|
|
14815
|
+
import * as path25 from "path";
|
|
14713
14816
|
var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14714
14817
|
function findKnexfile(projectDir) {
|
|
14715
14818
|
for (const name of KNEXFILE_VARIANTS) {
|
|
14716
|
-
const p =
|
|
14819
|
+
const p = path25.join(projectDir, name);
|
|
14717
14820
|
if (fs24.existsSync(p)) return p;
|
|
14718
14821
|
}
|
|
14719
14822
|
return void 0;
|
|
@@ -14866,7 +14969,7 @@ async function buildDsn4(args) {
|
|
|
14866
14969
|
}
|
|
14867
14970
|
var KNEXFILE_VARIANTS2 = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14868
14971
|
function listKnexFiles(projectDir) {
|
|
14869
|
-
const dir =
|
|
14972
|
+
const dir = path26.join(projectDir, "migrations");
|
|
14870
14973
|
if (!fs25.existsSync(dir)) return [];
|
|
14871
14974
|
const files = fs25.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
14872
14975
|
return files.map((filename) => {
|
|
@@ -14888,7 +14991,7 @@ var KnexAdapter = {
|
|
|
14888
14991
|
* project.yaml#migration_tool.
|
|
14889
14992
|
*/
|
|
14890
14993
|
detect(projectDir) {
|
|
14891
|
-
return KNEXFILE_VARIANTS2.some((name) => fs25.existsSync(
|
|
14994
|
+
return KNEXFILE_VARIANTS2.some((name) => fs25.existsSync(path26.join(projectDir, name)));
|
|
14892
14995
|
},
|
|
14893
14996
|
async apply(args) {
|
|
14894
14997
|
const dsn = await buildDsn4(args);
|
|
@@ -14961,9 +15064,9 @@ var KnexAdapter = {
|
|
|
14961
15064
|
async newMigration(args) {
|
|
14962
15065
|
try {
|
|
14963
15066
|
const created = await createKnexMigration({ projectDir: args.projectDir, slug: migrationSlug2(args.slug) });
|
|
14964
|
-
const stem =
|
|
15067
|
+
const stem = path26.basename(created).replace(/\.(js|ts)$/, "");
|
|
14965
15068
|
const version = stem.match(/^(\d{14})_/)?.[1] ?? stem;
|
|
14966
|
-
return { status: "ok", version, filename:
|
|
15069
|
+
return { status: "ok", version, filename: path26.basename(created), path: created };
|
|
14967
15070
|
} catch (err) {
|
|
14968
15071
|
return {
|
|
14969
15072
|
status: "error",
|
|
@@ -15020,7 +15123,7 @@ function listSchemaMigrations(args = {}) {
|
|
|
15020
15123
|
}
|
|
15021
15124
|
}
|
|
15022
15125
|
function listFlywayMigrations(projectDir) {
|
|
15023
|
-
const dir =
|
|
15126
|
+
const dir = path27.join(projectDir, "src", "main", "resources", "db", "migration");
|
|
15024
15127
|
if (!fs26.existsSync(dir)) return [];
|
|
15025
15128
|
const files = fs26.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
15026
15129
|
return files.map((filename) => {
|
|
@@ -15032,8 +15135,8 @@ function listFlywayMigrations(projectDir) {
|
|
|
15032
15135
|
}
|
|
15033
15136
|
function listAlembicMigrations(projectDir) {
|
|
15034
15137
|
const candidates = [
|
|
15035
|
-
|
|
15036
|
-
|
|
15138
|
+
path27.join(projectDir, "migrations", "versions"),
|
|
15139
|
+
path27.join(projectDir, "alembic", "versions")
|
|
15037
15140
|
];
|
|
15038
15141
|
const dir = candidates.find((p) => fs26.existsSync(p));
|
|
15039
15142
|
if (!dir) return [];
|
|
@@ -15047,7 +15150,7 @@ function listAlembicMigrations(projectDir) {
|
|
|
15047
15150
|
}).sort((a, b) => a.filename.localeCompare(b.filename));
|
|
15048
15151
|
}
|
|
15049
15152
|
function listKnexMigrations(projectDir) {
|
|
15050
|
-
const dir =
|
|
15153
|
+
const dir = path27.join(projectDir, "migrations");
|
|
15051
15154
|
if (!fs26.existsSync(dir)) return [];
|
|
15052
15155
|
const files = fs26.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
15053
15156
|
return files.map((filename) => {
|
|
@@ -15225,7 +15328,7 @@ async function runInfraSuite(args) {
|
|
|
15225
15328
|
duration_ms: Date.now() - start
|
|
15226
15329
|
};
|
|
15227
15330
|
if (args.junitOutput) {
|
|
15228
|
-
fs27.mkdirSync(
|
|
15331
|
+
fs27.mkdirSync(path28.dirname(args.junitOutput), { recursive: true });
|
|
15229
15332
|
fs27.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
|
|
15230
15333
|
}
|
|
15231
15334
|
return result;
|
|
@@ -15273,7 +15376,7 @@ function escapeXml(s) {
|
|
|
15273
15376
|
// scripts/lakebase/scm-claim-feature.ts
|
|
15274
15377
|
init_esm_shims();
|
|
15275
15378
|
import * as fs28 from "fs";
|
|
15276
|
-
import * as
|
|
15379
|
+
import * as path29 from "path";
|
|
15277
15380
|
var ScmClaimError = class extends Error {
|
|
15278
15381
|
constructor(message, code) {
|
|
15279
15382
|
super(message);
|
|
@@ -15330,7 +15433,7 @@ async function claimFeatureBranch(args) {
|
|
|
15330
15433
|
const current = readWorkflowState(args.projectDir);
|
|
15331
15434
|
if (!current) {
|
|
15332
15435
|
throw new ScmClaimError(
|
|
15333
|
-
`No SCM workflow state found at ${
|
|
15436
|
+
`No SCM workflow state found at ${path29.join(args.projectDir, ".lakebase/workflow-state.json")}. Run lakebase-create-project to scaffold, or re-seed via the substrate.`,
|
|
15334
15437
|
"no-state-file"
|
|
15335
15438
|
);
|
|
15336
15439
|
}
|
|
@@ -15435,7 +15538,7 @@ function alreadyClaimedSentinel(state) {
|
|
|
15435
15538
|
}
|
|
15436
15539
|
function workflowStateFileExists(projectDir) {
|
|
15437
15540
|
return fs28.existsSync(
|
|
15438
|
-
|
|
15541
|
+
path29.join(projectDir, ".lakebase/workflow-state.json")
|
|
15439
15542
|
);
|
|
15440
15543
|
}
|
|
15441
15544
|
|
|
@@ -15699,6 +15802,7 @@ async function preparePr(args) {
|
|
|
15699
15802
|
"no-github-remote"
|
|
15700
15803
|
);
|
|
15701
15804
|
}
|
|
15805
|
+
const ciFreshness = await ensureCiSecretsFreshFromEnv(args.projectDir, { ownerRepo });
|
|
15702
15806
|
const now = (args.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
15703
15807
|
let prUrl = args.prUrlOverride ?? "";
|
|
15704
15808
|
let prCreated = false;
|
|
@@ -15743,7 +15847,7 @@ async function preparePr(args) {
|
|
|
15743
15847
|
pushed_at: now.toISOString()
|
|
15744
15848
|
};
|
|
15745
15849
|
writeWorkflowState(args.projectDir, next);
|
|
15746
|
-
return { state: next, prUrl, prCreated };
|
|
15850
|
+
return { state: next, prUrl, prCreated, ciFreshness };
|
|
15747
15851
|
}
|
|
15748
15852
|
async function ensureAheadOfParent(cwd, branch, parent) {
|
|
15749
15853
|
try {
|
|
@@ -15923,11 +16027,11 @@ async function pushCurrentBranchForPr(args) {
|
|
|
15923
16027
|
// scripts/lakebase/workflow-drift.ts
|
|
15924
16028
|
init_esm_shims();
|
|
15925
16029
|
import * as fs29 from "fs";
|
|
15926
|
-
import * as
|
|
16030
|
+
import * as path30 from "path";
|
|
15927
16031
|
function findKitTemplatesDir(start) {
|
|
15928
16032
|
let dir = start;
|
|
15929
16033
|
for (let i = 0; i < 6; i++) {
|
|
15930
|
-
const candidate =
|
|
16034
|
+
const candidate = path30.join(
|
|
15931
16035
|
dir,
|
|
15932
16036
|
"templates",
|
|
15933
16037
|
"project",
|
|
@@ -15936,7 +16040,7 @@ function findKitTemplatesDir(start) {
|
|
|
15936
16040
|
"workflows"
|
|
15937
16041
|
);
|
|
15938
16042
|
if (fs29.existsSync(candidate)) return candidate;
|
|
15939
|
-
const parent =
|
|
16043
|
+
const parent = path30.dirname(dir);
|
|
15940
16044
|
if (parent === dir) break;
|
|
15941
16045
|
dir = parent;
|
|
15942
16046
|
}
|
|
@@ -15960,13 +16064,13 @@ function unifiedDiff(name, projectContent, templateContent) {
|
|
|
15960
16064
|
return out.join("\n");
|
|
15961
16065
|
}
|
|
15962
16066
|
function detectWorkflowDrift(args) {
|
|
15963
|
-
const projectWorkflowsDir =
|
|
16067
|
+
const projectWorkflowsDir = path30.join(
|
|
15964
16068
|
args.projectDir,
|
|
15965
16069
|
".github",
|
|
15966
16070
|
"workflows"
|
|
15967
16071
|
);
|
|
15968
|
-
const here =
|
|
15969
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16072
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16073
|
+
const kitWorkflowsDir = args.kitDir ? path30.join(
|
|
15970
16074
|
args.kitDir,
|
|
15971
16075
|
"templates",
|
|
15972
16076
|
"project",
|
|
@@ -15981,8 +16085,8 @@ function detectWorkflowDrift(args) {
|
|
|
15981
16085
|
const files = [];
|
|
15982
16086
|
for (const name of templateFiles) {
|
|
15983
16087
|
seen.add(name);
|
|
15984
|
-
const projectPath2 =
|
|
15985
|
-
const templatePath =
|
|
16088
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16089
|
+
const templatePath = path30.join(kitWorkflowsDir, name);
|
|
15986
16090
|
if (!fs29.existsSync(projectPath2)) {
|
|
15987
16091
|
files.push({ name, status: "missing" });
|
|
15988
16092
|
continue;
|
|
@@ -16019,10 +16123,10 @@ function detectWorkflowDrift(args) {
|
|
|
16019
16123
|
function readKitVersion(kitWorkflowsDir) {
|
|
16020
16124
|
let dir = kitWorkflowsDir;
|
|
16021
16125
|
for (let i = 0; i < 5; i++) {
|
|
16022
|
-
dir =
|
|
16126
|
+
dir = path30.dirname(dir);
|
|
16023
16127
|
}
|
|
16024
16128
|
try {
|
|
16025
|
-
const raw = fs29.readFileSync(
|
|
16129
|
+
const raw = fs29.readFileSync(path30.join(dir, "package.json"), "utf-8");
|
|
16026
16130
|
const pkg = JSON.parse(raw);
|
|
16027
16131
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16028
16132
|
} catch {
|
|
@@ -16039,7 +16143,7 @@ var COMMAND_HOOK_FILE_PATTERN = /\.(pre|post)-hook\.md$/;
|
|
|
16039
16143
|
function findKitCommandsDir(start) {
|
|
16040
16144
|
let dir = start;
|
|
16041
16145
|
for (let i = 0; i < 6; i++) {
|
|
16042
|
-
const candidate =
|
|
16146
|
+
const candidate = path30.join(
|
|
16043
16147
|
dir,
|
|
16044
16148
|
"templates",
|
|
16045
16149
|
"project",
|
|
@@ -16048,7 +16152,7 @@ function findKitCommandsDir(start) {
|
|
|
16048
16152
|
"commands"
|
|
16049
16153
|
);
|
|
16050
16154
|
if (fs29.existsSync(candidate)) return candidate;
|
|
16051
|
-
const parent =
|
|
16155
|
+
const parent = path30.dirname(dir);
|
|
16052
16156
|
if (parent === dir) break;
|
|
16053
16157
|
dir = parent;
|
|
16054
16158
|
}
|
|
@@ -16061,9 +16165,9 @@ function parsePinnedVersion(content) {
|
|
|
16061
16165
|
return m ? m[1] : void 0;
|
|
16062
16166
|
}
|
|
16063
16167
|
function detectCommandDrift(args) {
|
|
16064
|
-
const projectCommandsDir =
|
|
16065
|
-
const here =
|
|
16066
|
-
const kitCommandsDir = args.kitDir ?
|
|
16168
|
+
const projectCommandsDir = path30.join(args.projectDir, ".claude", "commands");
|
|
16169
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16170
|
+
const kitCommandsDir = args.kitDir ? path30.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
|
|
16067
16171
|
const kitVersion = readKitVersionFromCommandsDir(kitCommandsDir);
|
|
16068
16172
|
const templateFiles = fs29.existsSync(kitCommandsDir) ? fs29.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16069
16173
|
const projectFiles = fs29.existsSync(projectCommandsDir) ? fs29.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
@@ -16071,8 +16175,8 @@ function detectCommandDrift(args) {
|
|
|
16071
16175
|
const files = [];
|
|
16072
16176
|
for (const name of templateFiles) {
|
|
16073
16177
|
seen.add(name);
|
|
16074
|
-
const projectPath2 =
|
|
16075
|
-
const templatePath =
|
|
16178
|
+
const projectPath2 = path30.join(projectCommandsDir, name);
|
|
16179
|
+
const templatePath = path30.join(kitCommandsDir, name);
|
|
16076
16180
|
const templateRaw = fs29.readFileSync(templatePath, "utf8");
|
|
16077
16181
|
if (!fs29.existsSync(projectPath2)) {
|
|
16078
16182
|
files.push({ name, status: "missing", kit_version: kitVersion });
|
|
@@ -16116,10 +16220,10 @@ function detectCommandDrift(args) {
|
|
|
16116
16220
|
function readKitVersionFromCommandsDir(kitCommandsDir) {
|
|
16117
16221
|
let dir = kitCommandsDir;
|
|
16118
16222
|
for (let i = 0; i < 5; i++) {
|
|
16119
|
-
dir =
|
|
16223
|
+
dir = path30.dirname(dir);
|
|
16120
16224
|
}
|
|
16121
16225
|
try {
|
|
16122
|
-
const raw = fs29.readFileSync(
|
|
16226
|
+
const raw = fs29.readFileSync(path30.join(dir, "package.json"), "utf-8");
|
|
16123
16227
|
const pkg = JSON.parse(raw);
|
|
16124
16228
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16125
16229
|
} catch {
|
|
@@ -16136,13 +16240,13 @@ function detectScaffoldedDrift(args) {
|
|
|
16136
16240
|
};
|
|
16137
16241
|
}
|
|
16138
16242
|
function updateWorkflows(args) {
|
|
16139
|
-
const projectWorkflowsDir =
|
|
16243
|
+
const projectWorkflowsDir = path30.join(
|
|
16140
16244
|
args.projectDir,
|
|
16141
16245
|
".github",
|
|
16142
16246
|
"workflows"
|
|
16143
16247
|
);
|
|
16144
|
-
const here =
|
|
16145
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16248
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16249
|
+
const kitWorkflowsDir = args.kitDir ? path30.join(
|
|
16146
16250
|
args.kitDir,
|
|
16147
16251
|
"templates",
|
|
16148
16252
|
"project",
|
|
@@ -16163,8 +16267,8 @@ function updateWorkflows(args) {
|
|
|
16163
16267
|
const files = [];
|
|
16164
16268
|
for (const name of templateFiles) {
|
|
16165
16269
|
seen.add(name);
|
|
16166
|
-
const projectPath2 =
|
|
16167
|
-
const templatePath =
|
|
16270
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16271
|
+
const templatePath = path30.join(kitWorkflowsDir, name);
|
|
16168
16272
|
const templateRaw = fs29.readFileSync(templatePath, "utf-8");
|
|
16169
16273
|
const desired = substitute ? applyPlaceholders(templateRaw, version) : templateRaw;
|
|
16170
16274
|
const existed = fs29.existsSync(projectPath2);
|
|
@@ -16185,7 +16289,7 @@ function updateWorkflows(args) {
|
|
|
16185
16289
|
if (pruneExtras) {
|
|
16186
16290
|
for (const name of projectFiles) {
|
|
16187
16291
|
if (seen.has(name)) continue;
|
|
16188
|
-
const projectPath2 =
|
|
16292
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16189
16293
|
if (!dryRun) {
|
|
16190
16294
|
fs29.unlinkSync(projectPath2);
|
|
16191
16295
|
}
|
|
@@ -16372,6 +16476,15 @@ async function mergeFeature(args) {
|
|
|
16372
16476
|
);
|
|
16373
16477
|
}
|
|
16374
16478
|
}
|
|
16479
|
+
{
|
|
16480
|
+
const ensure = args.ensureCiFresh ?? ((repo) => ensureCiSecretsFreshFromEnv(args.projectDir, { ownerRepo: repo }));
|
|
16481
|
+
try {
|
|
16482
|
+
const r = await ensure(ownerRepo);
|
|
16483
|
+
if (r.action !== "ok" && r.action !== "skipped") preflightNotes.push(`CI-auth preflight: ${r.reason}`);
|
|
16484
|
+
} catch (err) {
|
|
16485
|
+
preflightNotes.push(`CI-auth preflight skipped (${err instanceof Error ? err.message : String(err)}); if the promote CI fails on auth, run lakebase-sync-ci-secrets.`);
|
|
16486
|
+
}
|
|
16487
|
+
}
|
|
16375
16488
|
{
|
|
16376
16489
|
const fetchState = args.fetchPrState ?? ((o, h) => getPullRequest(o, h));
|
|
16377
16490
|
const prState = await fetchState(ownerRepo, current.branch).catch(() => void 0);
|
|
@@ -16777,11 +16890,11 @@ function parentForTopology(t, defaultLeaf) {
|
|
|
16777
16890
|
// scripts/lakebase/scm-doctor.ts
|
|
16778
16891
|
init_esm_shims();
|
|
16779
16892
|
import * as fs30 from "fs";
|
|
16780
|
-
import * as
|
|
16893
|
+
import * as path31 from "path";
|
|
16781
16894
|
var FEATURE_PREFIX = "feature/";
|
|
16782
16895
|
var TIER_LEAFS2 = DEFAULT_PROTECTED_TIER_NAMES;
|
|
16783
16896
|
function readEnv(projectDir) {
|
|
16784
|
-
const envPath =
|
|
16897
|
+
const envPath = path31.join(projectDir, ".env");
|
|
16785
16898
|
const out = /* @__PURE__ */ new Map();
|
|
16786
16899
|
if (!fs30.existsSync(envPath)) return out;
|
|
16787
16900
|
const lines = fs30.readFileSync(envPath, "utf8").split("\n");
|
|
@@ -16839,7 +16952,7 @@ async function runDoctor(args, deps = {}) {
|
|
|
16839
16952
|
}
|
|
16840
16953
|
for (const wf of ["pr.yml", "merge.yml"]) {
|
|
16841
16954
|
try {
|
|
16842
|
-
const p =
|
|
16955
|
+
const p = path31.join(projectDir, ".github", "workflows", wf);
|
|
16843
16956
|
if (!fs30.existsSync(p)) continue;
|
|
16844
16957
|
const body = fs30.readFileSync(p, "utf8");
|
|
16845
16958
|
if (/lakebase-scm-utils#v\d/.test(body)) {
|
|
@@ -17056,7 +17169,7 @@ async function fixFinding(args) {
|
|
|
17056
17169
|
);
|
|
17057
17170
|
}
|
|
17058
17171
|
const sanitized = sanitizeBranchName(branch);
|
|
17059
|
-
const envFile =
|
|
17172
|
+
const envFile = path31.join(args.projectDir, ".env");
|
|
17060
17173
|
updateEnvConnection({
|
|
17061
17174
|
envPath: envFile,
|
|
17062
17175
|
projectId: readEnvVar(envFile, "LAKEBASE_PROJECT_ID") ?? "",
|
|
@@ -17159,10 +17272,10 @@ function shellEscape3(s) {
|
|
|
17159
17272
|
// scripts/lakebase/doctor.ts
|
|
17160
17273
|
init_esm_shims();
|
|
17161
17274
|
import * as fs31 from "fs";
|
|
17162
|
-
import * as
|
|
17275
|
+
import * as path32 from "path";
|
|
17163
17276
|
import * as cp6 from "child_process";
|
|
17164
17277
|
function readEnvFile(projectDir) {
|
|
17165
|
-
const envPath =
|
|
17278
|
+
const envPath = path32.join(projectDir, ".env");
|
|
17166
17279
|
if (!fs31.existsSync(envPath)) return {};
|
|
17167
17280
|
const out = {};
|
|
17168
17281
|
for (const line of fs31.readFileSync(envPath, "utf8").split("\n")) {
|
|
@@ -17420,7 +17533,7 @@ function checkEnv(projectDir) {
|
|
|
17420
17533
|
name: "env-file",
|
|
17421
17534
|
status: "warn",
|
|
17422
17535
|
message: ".env not found",
|
|
17423
|
-
detail: { projectDir, envPath:
|
|
17536
|
+
detail: { projectDir, envPath: path32.join(projectDir, ".env") },
|
|
17424
17537
|
hint: "Run `lakebase-branch sync-env`, or `git checkout <branch>` so the post-checkout hook writes .env (or copy .env.example). The kit stores connection METADATA only , no DB token (the app mints a short-lived credential at runtime)."
|
|
17425
17538
|
};
|
|
17426
17539
|
}
|