@databricks-solutions/lakebase-scm-utils 0.2.48 → 0.2.50
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 +2184 -2054
- package/dist/scripts/index.d.cts +3 -2
- package/dist/scripts/index.d.ts +3 -2
- package/dist/scripts/index.js +259 -136
- 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 +2170 -2052
- package/dist/scripts/lakebase/index.d.cts +21 -2
- package/dist/scripts/lakebase/index.d.ts +21 -2
- package/dist/scripts/lakebase/index.js +249 -132
- 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-cleanup.cli.cjs +5 -2
- package/dist/scripts/lakebase/scm-cleanup.cli.js +5 -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/lakebase-project.ts +17 -3
- 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);
|
|
@@ -2210,9 +2210,12 @@ function assertCreatedProjectReady(projectId, verified, reportedState) {
|
|
|
2210
2210
|
}
|
|
2211
2211
|
return { uid: verified.uid, name: verified.name, state: verified.state ?? "READY" };
|
|
2212
2212
|
}
|
|
2213
|
+
function deleteProjectArgs(projectId) {
|
|
2214
|
+
const name = projectId.startsWith("projects/") ? projectId : `projects/${projectId}`;
|
|
2215
|
+
return ["postgres", "delete-project", name, "--purge", "-o", "json"];
|
|
2216
|
+
}
|
|
2213
2217
|
async function deleteLakebaseProject(args) {
|
|
2214
|
-
|
|
2215
|
-
await dbcli2(["postgres", "delete-project", name, "-o", "json"], args.host);
|
|
2218
|
+
await dbcli2(deleteProjectArgs(args.projectId), args.host);
|
|
2216
2219
|
}
|
|
2217
2220
|
function findDefaultBranchName(items) {
|
|
2218
2221
|
const def = items.find((b) => b.status?.default === true || b.is_default === true);
|
|
@@ -2518,8 +2521,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
2518
2521
|
var cached;
|
|
2519
2522
|
function substrateSelfVersion() {
|
|
2520
2523
|
if (cached !== void 0) return cached;
|
|
2521
|
-
if ("0.2.
|
|
2522
|
-
cached = "0.2.
|
|
2524
|
+
if ("0.2.50".length > 0) {
|
|
2525
|
+
cached = "0.2.50";
|
|
2523
2526
|
return cached;
|
|
2524
2527
|
}
|
|
2525
2528
|
cached = "unknown";
|
|
@@ -5059,7 +5062,7 @@ paginateRest.VERSION = VERSION5;
|
|
|
5059
5062
|
|
|
5060
5063
|
// node_modules/@octokit/plugin-paginate-graphql/dist-bundle/index.js
|
|
5061
5064
|
init_esm_shims();
|
|
5062
|
-
var generateMessage = (
|
|
5065
|
+
var generateMessage = (path33, cursorValue) => `The cursor at "${path33.join(
|
|
5063
5066
|
","
|
|
5064
5067
|
)}" did not change its value "${cursorValue}" after a page transition. Please make sure your that your query is set up correctly.`;
|
|
5065
5068
|
var MissingCursorChange = class extends Error {
|
|
@@ -5100,9 +5103,9 @@ function findPaginatedResourcePath(responseData) {
|
|
|
5100
5103
|
}
|
|
5101
5104
|
return paginatedResourcePath;
|
|
5102
5105
|
}
|
|
5103
|
-
var deepFindPathToProperty = (object, searchProp,
|
|
5106
|
+
var deepFindPathToProperty = (object, searchProp, path33 = []) => {
|
|
5104
5107
|
for (const key of Object.keys(object)) {
|
|
5105
|
-
const currentPath = [...
|
|
5108
|
+
const currentPath = [...path33, key];
|
|
5106
5109
|
const currentValue = object[key];
|
|
5107
5110
|
if (isObject(currentValue)) {
|
|
5108
5111
|
if (currentValue.hasOwnProperty(searchProp)) {
|
|
@@ -5120,12 +5123,12 @@ var deepFindPathToProperty = (object, searchProp, path32 = []) => {
|
|
|
5120
5123
|
}
|
|
5121
5124
|
return [];
|
|
5122
5125
|
};
|
|
5123
|
-
var get = (object,
|
|
5124
|
-
return
|
|
5126
|
+
var get = (object, path33) => {
|
|
5127
|
+
return path33.reduce((current, nextProperty) => current[nextProperty], object);
|
|
5125
5128
|
};
|
|
5126
|
-
var set = (object,
|
|
5127
|
-
const lastProperty =
|
|
5128
|
-
const parentPath = [...
|
|
5129
|
+
var set = (object, path33, mutator) => {
|
|
5130
|
+
const lastProperty = path33[path33.length - 1];
|
|
5131
|
+
const parentPath = [...path33].slice(0, -1);
|
|
5129
5132
|
const parent = get(object, parentPath);
|
|
5130
5133
|
if (typeof mutator === "function") {
|
|
5131
5134
|
parent[lastProperty] = mutator(parent[lastProperty]);
|
|
@@ -5177,22 +5180,22 @@ var mergeResponses = (response1, response2) => {
|
|
|
5177
5180
|
if (Object.keys(response1).length === 0) {
|
|
5178
5181
|
return Object.assign(response1, response2);
|
|
5179
5182
|
}
|
|
5180
|
-
const
|
|
5181
|
-
const nodesPath = [...
|
|
5183
|
+
const path33 = findPaginatedResourcePath(response1);
|
|
5184
|
+
const nodesPath = [...path33, "nodes"];
|
|
5182
5185
|
const newNodes = get(response2, nodesPath);
|
|
5183
5186
|
if (newNodes) {
|
|
5184
5187
|
set(response1, nodesPath, (values) => {
|
|
5185
5188
|
return [...values, ...newNodes];
|
|
5186
5189
|
});
|
|
5187
5190
|
}
|
|
5188
|
-
const edgesPath = [...
|
|
5191
|
+
const edgesPath = [...path33, "edges"];
|
|
5189
5192
|
const newEdges = get(response2, edgesPath);
|
|
5190
5193
|
if (newEdges) {
|
|
5191
5194
|
set(response1, edgesPath, (values) => {
|
|
5192
5195
|
return [...values, ...newEdges];
|
|
5193
5196
|
});
|
|
5194
5197
|
}
|
|
5195
|
-
const pageInfoPath = [...
|
|
5198
|
+
const pageInfoPath = [...path33, "pageInfo"];
|
|
5196
5199
|
set(response1, pageInfoPath, get(response2, pageInfoPath));
|
|
5197
5200
|
return response1;
|
|
5198
5201
|
};
|
|
@@ -7613,7 +7616,7 @@ var triggers_notification_paths_default = [
|
|
|
7613
7616
|
];
|
|
7614
7617
|
function routeMatcher(paths) {
|
|
7615
7618
|
const regexes = paths.map(
|
|
7616
|
-
(
|
|
7619
|
+
(path33) => path33.split("/").map((c) => c.startsWith("{") ? "(?:.+?)" : c).join("/")
|
|
7617
7620
|
);
|
|
7618
7621
|
const regex2 = `^(?:${regexes.map((r) => `(?:${r})`).join("|")})[^/]*$`;
|
|
7619
7622
|
return new RegExp(regex2, "i");
|
|
@@ -10941,16 +10944,16 @@ function isAllSchemas(schema) {
|
|
|
10941
10944
|
}
|
|
10942
10945
|
function buildSchemaQuery(schema) {
|
|
10943
10946
|
const cols = "c.table_schema, c.table_name, c.column_name, c.data_type";
|
|
10944
|
-
const
|
|
10947
|
+
const join34 = "FROM information_schema.columns c JOIN pg_tables t ON c.table_name = t.tablename AND c.table_schema = t.schemaname ";
|
|
10945
10948
|
if (isAllSchemas(schema)) {
|
|
10946
10949
|
return {
|
|
10947
|
-
text: `SELECT ${cols} ` +
|
|
10950
|
+
text: `SELECT ${cols} ` + join34 + `WHERE ${SYSTEM_SCHEMA_FILTER} ORDER BY c.table_schema, c.table_name, c.ordinal_position`,
|
|
10948
10951
|
values: []
|
|
10949
10952
|
};
|
|
10950
10953
|
}
|
|
10951
10954
|
const one = (schema ?? "").trim() || "public";
|
|
10952
10955
|
return {
|
|
10953
|
-
text: `SELECT ${cols} ` +
|
|
10956
|
+
text: `SELECT ${cols} ` + join34 + "WHERE c.table_schema = $1 ORDER BY c.table_name, c.ordinal_position",
|
|
10954
10957
|
values: [one]
|
|
10955
10958
|
};
|
|
10956
10959
|
}
|
|
@@ -11111,7 +11114,7 @@ async function withLakebaseRollback(opts, fn) {
|
|
|
11111
11114
|
// scripts/lakebase/create-project.ts
|
|
11112
11115
|
init_esm_shims();
|
|
11113
11116
|
import * as fs18 from "fs";
|
|
11114
|
-
import * as
|
|
11117
|
+
import * as path18 from "path";
|
|
11115
11118
|
|
|
11116
11119
|
// scripts/lakebase/project-verify.ts
|
|
11117
11120
|
init_esm_shims();
|
|
@@ -12865,6 +12868,7 @@ async function removeRunner(args) {
|
|
|
12865
12868
|
|
|
12866
12869
|
// scripts/util/ci-secrets.ts
|
|
12867
12870
|
init_esm_shims();
|
|
12871
|
+
import * as path16 from "path";
|
|
12868
12872
|
|
|
12869
12873
|
// scripts/github/secrets.ts
|
|
12870
12874
|
init_esm_shims();
|
|
@@ -12974,13 +12978,40 @@ async function getOwnerRepo(cwd) {
|
|
|
12974
12978
|
|
|
12975
12979
|
// scripts/util/ci-secrets.ts
|
|
12976
12980
|
var REQUIRED_CI_SECRETS = ["DATABRICKS_HOST", "LAKEBASE_PROJECT_ID", "DATABRICKS_TOKEN"];
|
|
12981
|
+
var CI_TOKEN_LIFETIME_SECONDS = 7776e3;
|
|
12982
|
+
var CI_TOKEN_REMINT_MARGIN_SECONDS = 86400;
|
|
12983
|
+
function ciTokenComment(ownerRepo) {
|
|
12984
|
+
const repoName = ownerRepo.includes("/") ? ownerRepo.slice(ownerRepo.lastIndexOf("/") + 1) : ownerRepo;
|
|
12985
|
+
return `GitHub Actions (${repoName})`;
|
|
12986
|
+
}
|
|
12977
12987
|
async function missingCiSecrets(ownerRepo) {
|
|
12978
12988
|
const present = new Set(await listSecretNames(ownerRepo));
|
|
12979
12989
|
return REQUIRED_CI_SECRETS.filter((n) => !present.has(n));
|
|
12980
12990
|
}
|
|
12991
|
+
async function mintCiToken(args) {
|
|
12992
|
+
try {
|
|
12993
|
+
const raw = await runDatabricks(
|
|
12994
|
+
["tokens", "create", "--comment", args.comment, "--lifetime-seconds", String(args.lifetimeSeconds), "-o", "json"],
|
|
12995
|
+
{ host: args.databricksHost, cwd: args.projectDir, timeout: 3e4 }
|
|
12996
|
+
);
|
|
12997
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
|
|
12998
|
+
const token = parsed.token_value || parsed.token || "";
|
|
12999
|
+
if (token) return token;
|
|
13000
|
+
} catch {
|
|
13001
|
+
}
|
|
13002
|
+
try {
|
|
13003
|
+
const raw = await runDatabricks(["auth", "token", "-o", "json"], {
|
|
13004
|
+
host: args.databricksHost,
|
|
13005
|
+
cwd: args.projectDir,
|
|
13006
|
+
timeout: 3e4
|
|
13007
|
+
});
|
|
13008
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("{"))));
|
|
13009
|
+
return parsed.access_token || "";
|
|
13010
|
+
} catch {
|
|
13011
|
+
return "";
|
|
13012
|
+
}
|
|
13013
|
+
}
|
|
12981
13014
|
async function syncCiSecrets(args) {
|
|
12982
|
-
const lifetime = args.lifetimeSeconds ?? 86400;
|
|
12983
|
-
const comment = args.comment ?? "GitHub Actions CI";
|
|
12984
13015
|
const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
|
|
12985
13016
|
if (!ownerRepo) {
|
|
12986
13017
|
throw new Error("Could not resolve GitHub repository from git remote");
|
|
@@ -12991,27 +13022,104 @@ async function syncCiSecrets(args) {
|
|
|
12991
13022
|
if (!args.lakebaseProjectId) {
|
|
12992
13023
|
throw new Error("syncCiSecrets: lakebaseProjectId is required");
|
|
12993
13024
|
}
|
|
13025
|
+
const lifetime = args.lifetimeSeconds ?? CI_TOKEN_LIFETIME_SECONDS;
|
|
13026
|
+
const comment = args.comment ?? ciTokenComment(ownerRepo);
|
|
12994
13027
|
const secrets = {
|
|
12995
13028
|
DATABRICKS_HOST: args.databricksHost,
|
|
12996
13029
|
LAKEBASE_PROJECT_ID: args.lakebaseProjectId
|
|
12997
13030
|
};
|
|
13031
|
+
const token = await mintCiToken({
|
|
13032
|
+
databricksHost: args.databricksHost,
|
|
13033
|
+
projectDir: args.projectDir,
|
|
13034
|
+
comment,
|
|
13035
|
+
lifetimeSeconds: lifetime
|
|
13036
|
+
});
|
|
13037
|
+
if (token) secrets.DATABRICKS_TOKEN = token;
|
|
13038
|
+
await setRepoSecrets(ownerRepo, secrets);
|
|
13039
|
+
}
|
|
13040
|
+
async function ciTokenExpiry(args) {
|
|
13041
|
+
const comment = ciTokenComment(args.ownerRepo);
|
|
13042
|
+
let raw;
|
|
12998
13043
|
try {
|
|
12999
|
-
|
|
13000
|
-
|
|
13001
|
-
|
|
13002
|
-
|
|
13003
|
-
|
|
13004
|
-
const token = parsed.token_value || parsed.token || "";
|
|
13005
|
-
if (token) secrets.DATABRICKS_TOKEN = token;
|
|
13044
|
+
raw = await runDatabricks(["tokens", "list", "-o", "json"], {
|
|
13045
|
+
host: args.databricksHost,
|
|
13046
|
+
cwd: args.projectDir,
|
|
13047
|
+
timeout: 3e4
|
|
13048
|
+
});
|
|
13006
13049
|
} catch {
|
|
13050
|
+
return null;
|
|
13051
|
+
}
|
|
13052
|
+
let infos;
|
|
13053
|
+
try {
|
|
13054
|
+
const parsed = JSON.parse(raw.slice(Math.max(0, raw.indexOf("["))));
|
|
13055
|
+
infos = Array.isArray(parsed) ? parsed : [];
|
|
13056
|
+
} catch {
|
|
13057
|
+
return null;
|
|
13058
|
+
}
|
|
13059
|
+
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);
|
|
13060
|
+
if (expiries.length === 0) return null;
|
|
13061
|
+
return Math.max(...expiries);
|
|
13062
|
+
}
|
|
13063
|
+
async function ensureCiSecretsFresh(args) {
|
|
13064
|
+
const now = args.now ?? Date.now;
|
|
13065
|
+
const marginMs = (args.marginSeconds ?? CI_TOKEN_REMINT_MARGIN_SECONDS) * 1e3;
|
|
13066
|
+
const ownerRepo = args.ownerRepo ?? await getOwnerRepo(args.projectDir);
|
|
13067
|
+
if (!ownerRepo) {
|
|
13068
|
+
throw new Error("Could not resolve GitHub repository from git remote");
|
|
13069
|
+
}
|
|
13070
|
+
const sync = () => syncCiSecrets({
|
|
13071
|
+
projectDir: args.projectDir,
|
|
13072
|
+
databricksHost: args.databricksHost,
|
|
13073
|
+
lakebaseProjectId: args.lakebaseProjectId,
|
|
13074
|
+
ownerRepo
|
|
13075
|
+
});
|
|
13076
|
+
const missing = await missingCiSecrets(ownerRepo);
|
|
13077
|
+
if (missing.length > 0) {
|
|
13078
|
+
await sync();
|
|
13079
|
+
return { action: "provisioned", reason: `CI secret(s) were missing (${missing.join(", ")}); provisioned.` };
|
|
13080
|
+
}
|
|
13081
|
+
const expiry = await ciTokenExpiry({ projectDir: args.projectDir, databricksHost: args.databricksHost, ownerRepo });
|
|
13082
|
+
if (expiry === null) {
|
|
13083
|
+
await sync();
|
|
13084
|
+
return { action: "reminted", reason: "no live CI token found (expired or minted under a different identity); re-minted." };
|
|
13085
|
+
}
|
|
13086
|
+
if (expiry !== Number.POSITIVE_INFINITY && expiry < now() + marginMs) {
|
|
13087
|
+
await sync();
|
|
13088
|
+
const hrs = Math.max(0, Math.round((expiry - now()) / 36e5));
|
|
13089
|
+
return { action: "reminted", reason: `CI token expires in ~${hrs}h (within the re-mint margin); re-minted.` };
|
|
13090
|
+
}
|
|
13091
|
+
return { action: "ok", reason: "CI token is current." };
|
|
13092
|
+
}
|
|
13093
|
+
async function ensureCiSecretsFreshFromEnv(projectDir, opts) {
|
|
13094
|
+
const envPath = path16.join(projectDir, ".env");
|
|
13095
|
+
const databricksHost = readEnvVar(envPath, "DATABRICKS_HOST");
|
|
13096
|
+
const lakebaseProjectId = readEnvVar(envPath, "LAKEBASE_PROJECT_ID");
|
|
13097
|
+
if (!databricksHost || !lakebaseProjectId) {
|
|
13098
|
+
return {
|
|
13099
|
+
action: "skipped",
|
|
13100
|
+
reason: "CI-auth preflight skipped: .env is missing DATABRICKS_HOST / LAKEBASE_PROJECT_ID."
|
|
13101
|
+
};
|
|
13102
|
+
}
|
|
13103
|
+
try {
|
|
13104
|
+
return await ensureCiSecretsFresh({
|
|
13105
|
+
projectDir,
|
|
13106
|
+
databricksHost,
|
|
13107
|
+
lakebaseProjectId,
|
|
13108
|
+
ownerRepo: opts?.ownerRepo,
|
|
13109
|
+
marginSeconds: opts?.marginSeconds
|
|
13110
|
+
});
|
|
13111
|
+
} catch (err) {
|
|
13112
|
+
return {
|
|
13113
|
+
action: "failed",
|
|
13114
|
+
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.`
|
|
13115
|
+
};
|
|
13007
13116
|
}
|
|
13008
|
-
await setRepoSecrets(ownerRepo, secrets);
|
|
13009
13117
|
}
|
|
13010
13118
|
|
|
13011
13119
|
// scripts/lakebase/scm-workflow-state.ts
|
|
13012
13120
|
init_esm_shims();
|
|
13013
13121
|
import * as fs17 from "fs";
|
|
13014
|
-
import * as
|
|
13122
|
+
import * as path17 from "path";
|
|
13015
13123
|
import { execFileSync as execFileSync6 } from "child_process";
|
|
13016
13124
|
function isGitTracked(projectDir, rel) {
|
|
13017
13125
|
try {
|
|
@@ -13030,7 +13138,7 @@ function ensureWorkflowStateUntracked(projectDir) {
|
|
|
13030
13138
|
} catch {
|
|
13031
13139
|
}
|
|
13032
13140
|
try {
|
|
13033
|
-
const gitignore =
|
|
13141
|
+
const gitignore = path17.join(projectDir, ".gitignore");
|
|
13034
13142
|
const existing = fs17.existsSync(gitignore) ? fs17.readFileSync(gitignore, "utf8") : "";
|
|
13035
13143
|
if (!existing.split("\n").some((l) => l.trim() === rel)) {
|
|
13036
13144
|
const sep4 = existing === "" || existing.endsWith("\n") ? "" : "\n";
|
|
@@ -13058,7 +13166,7 @@ var STATE_INDEX = SCM_STATES.reduce(
|
|
|
13058
13166
|
);
|
|
13059
13167
|
var STATE_FILE_REL = ".lakebase/workflow-state.json";
|
|
13060
13168
|
function stateFilePath(projectDir) {
|
|
13061
|
-
return
|
|
13169
|
+
return path17.join(projectDir, STATE_FILE_REL);
|
|
13062
13170
|
}
|
|
13063
13171
|
function readWorkflowState(projectDir) {
|
|
13064
13172
|
const p = stateFilePath(projectDir);
|
|
@@ -13098,7 +13206,7 @@ function writeWorkflowState(projectDir, state) {
|
|
|
13098
13206
|
${summary}`);
|
|
13099
13207
|
}
|
|
13100
13208
|
ensureWorkflowStateUntracked(projectDir);
|
|
13101
|
-
const dir =
|
|
13209
|
+
const dir = path17.join(projectDir, ".lakebase");
|
|
13102
13210
|
fs17.mkdirSync(dir, { recursive: true });
|
|
13103
13211
|
const target = stateFilePath(projectDir);
|
|
13104
13212
|
const tmp = `${target}.tmp`;
|
|
@@ -13329,7 +13437,7 @@ function orderForOutput(state) {
|
|
|
13329
13437
|
async function createProject(input, progress) {
|
|
13330
13438
|
const report = progress ?? (() => {
|
|
13331
13439
|
});
|
|
13332
|
-
const projectDir =
|
|
13440
|
+
const projectDir = path18.join(input.parentDir, input.projectName);
|
|
13333
13441
|
const lakebaseProjectId = input.projectName;
|
|
13334
13442
|
const host = input.databricksHost.replace(/\/+$/, "");
|
|
13335
13443
|
const useGithub = input.createGithubRepo !== false;
|
|
@@ -13490,8 +13598,6 @@ Last probe error:
|
|
|
13490
13598
|
projectDir,
|
|
13491
13599
|
databricksHost: host,
|
|
13492
13600
|
lakebaseProjectId,
|
|
13493
|
-
comment: "GitHub Actions CI",
|
|
13494
|
-
lifetimeSeconds: 86400,
|
|
13495
13601
|
ownerRepo: fullRepoName
|
|
13496
13602
|
});
|
|
13497
13603
|
const missing = await missingCiSecrets(fullRepoName);
|
|
@@ -13558,9 +13664,9 @@ Last probe error:
|
|
|
13558
13664
|
const scmRef = envRef || (ver !== "unknown" ? `v${ver}` : "");
|
|
13559
13665
|
if (scmRef) {
|
|
13560
13666
|
try {
|
|
13561
|
-
const dir =
|
|
13667
|
+
const dir = path18.join(projectDir, ".lakebase");
|
|
13562
13668
|
fs18.mkdirSync(dir, { recursive: true });
|
|
13563
|
-
fs18.writeFileSync(
|
|
13669
|
+
fs18.writeFileSync(path18.join(dir, "scm-utils-ref"), `${scmRef}
|
|
13564
13670
|
`, "utf8");
|
|
13565
13671
|
} catch (err) {
|
|
13566
13672
|
warnings.push(`Substrate ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13571,9 +13677,9 @@ Last probe error:
|
|
|
13571
13677
|
const kitRef = process.env.LAKEBASE_KIT_REF?.trim();
|
|
13572
13678
|
if (kitRef) {
|
|
13573
13679
|
try {
|
|
13574
|
-
const dir =
|
|
13680
|
+
const dir = path18.join(projectDir, ".lakebase");
|
|
13575
13681
|
fs18.mkdirSync(dir, { recursive: true });
|
|
13576
|
-
fs18.writeFileSync(
|
|
13682
|
+
fs18.writeFileSync(path18.join(dir, "kit-ref"), `${kitRef}
|
|
13577
13683
|
`, "utf8");
|
|
13578
13684
|
} catch (err) {
|
|
13579
13685
|
warnings.push(`Kit ref pin failed (advisory): ${err instanceof Error ? err.message : String(err)}.`);
|
|
@@ -13655,7 +13761,7 @@ Last probe error:
|
|
|
13655
13761
|
init_esm_shims();
|
|
13656
13762
|
import * as cp5 from "child_process";
|
|
13657
13763
|
import * as fs19 from "fs";
|
|
13658
|
-
import * as
|
|
13764
|
+
import * as path19 from "path";
|
|
13659
13765
|
async function adoptLakebaseProject(args) {
|
|
13660
13766
|
const warnings = [];
|
|
13661
13767
|
const filesWritten = [];
|
|
@@ -13664,7 +13770,7 @@ async function adoptLakebaseProject(args) {
|
|
|
13664
13770
|
if (!fs19.existsSync(args.projectDir)) {
|
|
13665
13771
|
throw new Error(`adoptLakebaseProject: project directory does not exist: ${args.projectDir}`);
|
|
13666
13772
|
}
|
|
13667
|
-
if (!fs19.existsSync(
|
|
13773
|
+
if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
|
|
13668
13774
|
throw new Error(
|
|
13669
13775
|
`adoptLakebaseProject: ${args.projectDir} is not a git repo. Run \`git init\` first, or pass an existing repo path.`
|
|
13670
13776
|
);
|
|
@@ -13730,7 +13836,7 @@ async function adoptLakebaseProject(args) {
|
|
|
13730
13836
|
};
|
|
13731
13837
|
}
|
|
13732
13838
|
function assertEnvCompatibility(projectDir, expectedProjectId) {
|
|
13733
|
-
const envPath =
|
|
13839
|
+
const envPath = path19.join(projectDir, ".env");
|
|
13734
13840
|
if (!fs19.existsSync(envPath)) return;
|
|
13735
13841
|
const content = fs19.readFileSync(envPath, "utf8");
|
|
13736
13842
|
const match = content.match(/^LAKEBASE_PROJECT_ID\s*=\s*(.+?)\s*$/m);
|
|
@@ -13746,7 +13852,7 @@ function assertAdoptionPreflight(args) {
|
|
|
13746
13852
|
if (!fs19.existsSync(args.projectDir)) {
|
|
13747
13853
|
throw new Error(`assertAdoptionPreflight: project directory does not exist: ${args.projectDir}`);
|
|
13748
13854
|
}
|
|
13749
|
-
if (!fs19.existsSync(
|
|
13855
|
+
if (!fs19.existsSync(path19.join(args.projectDir, ".git"))) {
|
|
13750
13856
|
throw new Error(
|
|
13751
13857
|
`assertAdoptionPreflight: ${args.projectDir} is not a git repo.`
|
|
13752
13858
|
);
|
|
@@ -13760,7 +13866,7 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
13760
13866
|
cp5.execSync("git init --quiet", { cwd: opts.dir, stdio: "pipe" });
|
|
13761
13867
|
if (opts.packageJson) {
|
|
13762
13868
|
fs19.writeFileSync(
|
|
13763
|
-
|
|
13869
|
+
path19.join(opts.dir, "package.json"),
|
|
13764
13870
|
JSON.stringify(opts.packageJson, null, 2) + "\n"
|
|
13765
13871
|
);
|
|
13766
13872
|
}
|
|
@@ -13769,7 +13875,7 @@ function _testMakeBrownfieldFixture(opts) {
|
|
|
13769
13875
|
// scripts/lakebase/infra-runner.ts
|
|
13770
13876
|
init_esm_shims();
|
|
13771
13877
|
import * as fs27 from "fs";
|
|
13772
|
-
import * as
|
|
13878
|
+
import * as path28 from "path";
|
|
13773
13879
|
|
|
13774
13880
|
// scripts/lakebase/schema-diff.ts
|
|
13775
13881
|
init_esm_shims();
|
|
@@ -13966,12 +14072,12 @@ function dbcli6(args) {
|
|
|
13966
14072
|
// scripts/lakebase/schema-migrate.ts
|
|
13967
14073
|
init_esm_shims();
|
|
13968
14074
|
import * as fs26 from "fs";
|
|
13969
|
-
import * as
|
|
14075
|
+
import * as path27 from "path";
|
|
13970
14076
|
|
|
13971
14077
|
// scripts/lakebase/migration-layout.ts
|
|
13972
14078
|
init_esm_shims();
|
|
13973
14079
|
import * as fs20 from "fs";
|
|
13974
|
-
import * as
|
|
14080
|
+
import * as path20 from "path";
|
|
13975
14081
|
var MIGRATION_LANGUAGES = [
|
|
13976
14082
|
"java",
|
|
13977
14083
|
"kotlin",
|
|
@@ -13987,13 +14093,13 @@ var MIGRATION_DEFAULTS = {
|
|
|
13987
14093
|
unknown: { path: "src/main/resources/db/migration", pattern: /^V\d+.*\.sql$/i, glob: "*.sql" }
|
|
13988
14094
|
};
|
|
13989
14095
|
function detectLanguageAt(dir) {
|
|
13990
|
-
if (fs20.existsSync(
|
|
13991
|
-
const kotlinDir =
|
|
14096
|
+
if (fs20.existsSync(path20.join(dir, "pom.xml"))) {
|
|
14097
|
+
const kotlinDir = path20.join(dir, "src", "main", "kotlin");
|
|
13992
14098
|
if (fs20.existsSync(kotlinDir)) {
|
|
13993
14099
|
return "kotlin";
|
|
13994
14100
|
}
|
|
13995
14101
|
try {
|
|
13996
|
-
const pom = fs20.readFileSync(
|
|
14102
|
+
const pom = fs20.readFileSync(path20.join(dir, "pom.xml"), "utf-8");
|
|
13997
14103
|
if (pom.includes("kotlin-maven-plugin")) {
|
|
13998
14104
|
return "kotlin";
|
|
13999
14105
|
}
|
|
@@ -14001,10 +14107,10 @@ function detectLanguageAt(dir) {
|
|
|
14001
14107
|
}
|
|
14002
14108
|
return "java";
|
|
14003
14109
|
}
|
|
14004
|
-
if (fs20.existsSync(
|
|
14110
|
+
if (fs20.existsSync(path20.join(dir, "pyproject.toml")) || fs20.existsSync(path20.join(dir, "requirements.txt")) || fs20.existsSync(path20.join(dir, "alembic.ini"))) {
|
|
14005
14111
|
return "python";
|
|
14006
14112
|
}
|
|
14007
|
-
if (fs20.existsSync(
|
|
14113
|
+
if (fs20.existsSync(path20.join(dir, "package.json"))) {
|
|
14008
14114
|
return "nodejs";
|
|
14009
14115
|
}
|
|
14010
14116
|
return "unknown";
|
|
@@ -14025,14 +14131,14 @@ function resolveMigrationLanguage(projectDir, configuredMigrationPath, override)
|
|
|
14025
14131
|
if (!rel) {
|
|
14026
14132
|
return "unknown";
|
|
14027
14133
|
}
|
|
14028
|
-
const rootResolved =
|
|
14029
|
-
let dir =
|
|
14030
|
-
while (dir === rootResolved || dir.startsWith(rootResolved +
|
|
14134
|
+
const rootResolved = path20.resolve(projectDir);
|
|
14135
|
+
let dir = path20.resolve(projectDir, rel);
|
|
14136
|
+
while (dir === rootResolved || dir.startsWith(rootResolved + path20.sep)) {
|
|
14031
14137
|
const lang = detectLanguageAt(dir);
|
|
14032
14138
|
if (lang !== "unknown") {
|
|
14033
14139
|
return lang;
|
|
14034
14140
|
}
|
|
14035
|
-
const parent =
|
|
14141
|
+
const parent = path20.dirname(dir);
|
|
14036
14142
|
if (parent === dir) {
|
|
14037
14143
|
break;
|
|
14038
14144
|
}
|
|
@@ -14066,17 +14172,17 @@ function resolveMigrationLayout(args) {
|
|
|
14066
14172
|
// scripts/lakebase/adapters/alembic-adapter.ts
|
|
14067
14173
|
init_esm_shims();
|
|
14068
14174
|
import * as fs22 from "fs";
|
|
14069
|
-
import * as
|
|
14175
|
+
import * as path22 from "path";
|
|
14070
14176
|
|
|
14071
14177
|
// scripts/lakebase/schema-migrate-runners/alembic.ts
|
|
14072
14178
|
init_esm_shims();
|
|
14073
14179
|
import { spawn as spawn5 } from "child_process";
|
|
14074
14180
|
import * as fs21 from "fs";
|
|
14075
|
-
import * as
|
|
14181
|
+
import * as path21 from "path";
|
|
14076
14182
|
function resolveAlembicBin(projectDir) {
|
|
14077
14183
|
const candidates = [
|
|
14078
|
-
|
|
14079
|
-
|
|
14184
|
+
path21.join(projectDir, ".venv", "bin", "alembic"),
|
|
14185
|
+
path21.join(projectDir, "venv", "bin", "alembic")
|
|
14080
14186
|
];
|
|
14081
14187
|
for (const candidate of candidates) {
|
|
14082
14188
|
try {
|
|
@@ -14090,7 +14196,7 @@ function spawnAlembic(projectDir, args, dsn) {
|
|
|
14090
14196
|
return new Promise((resolve2, reject) => {
|
|
14091
14197
|
const bin = resolveAlembicBin(projectDir);
|
|
14092
14198
|
const env = { ...process.env };
|
|
14093
|
-
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(
|
|
14199
|
+
env.PYTHONPATH = [projectDir, process.env.PYTHONPATH].filter(Boolean).join(path21.delimiter);
|
|
14094
14200
|
if (dsn) env.DATABASE_URL = dsn;
|
|
14095
14201
|
const child = spawn5(bin, args, {
|
|
14096
14202
|
cwd: projectDir,
|
|
@@ -14138,10 +14244,10 @@ async function createAlembicRevision(opts) {
|
|
|
14138
14244
|
const m = stdout.match(/Generating\s+(\S+\.py)/);
|
|
14139
14245
|
if (m) return m[1].trim();
|
|
14140
14246
|
for (const rel of ["migrations/versions", "alembic/versions"]) {
|
|
14141
|
-
const dir =
|
|
14247
|
+
const dir = path21.join(opts.projectDir, rel);
|
|
14142
14248
|
if (!fs21.existsSync(dir)) continue;
|
|
14143
14249
|
const hit = fs21.readdirSync(dir).find((f) => f.startsWith(`${opts.revId}_`) && f.endsWith(".py"));
|
|
14144
|
-
if (hit) return
|
|
14250
|
+
if (hit) return path21.join(dir, hit);
|
|
14145
14251
|
}
|
|
14146
14252
|
throw new SchemaMigrationError(
|
|
14147
14253
|
`alembic revision succeeded but the created file could not be located.
|
|
@@ -14276,8 +14382,8 @@ async function buildDsn2(args) {
|
|
|
14276
14382
|
}
|
|
14277
14383
|
function findVersionsDir(projectDir) {
|
|
14278
14384
|
const candidates = [
|
|
14279
|
-
|
|
14280
|
-
|
|
14385
|
+
path22.join(projectDir, "migrations", "versions"),
|
|
14386
|
+
path22.join(projectDir, "alembic", "versions")
|
|
14281
14387
|
];
|
|
14282
14388
|
return candidates.find((p) => fs22.existsSync(p));
|
|
14283
14389
|
}
|
|
@@ -14309,9 +14415,9 @@ var AlembicAdapter = {
|
|
|
14309
14415
|
* here. Callers can still force-select via project.yaml#migration_tool.
|
|
14310
14416
|
*/
|
|
14311
14417
|
detect(projectDir) {
|
|
14312
|
-
if (fs22.existsSync(
|
|
14313
|
-
if (fs22.existsSync(
|
|
14314
|
-
if (fs22.existsSync(
|
|
14418
|
+
if (fs22.existsSync(path22.join(projectDir, "alembic.ini"))) return true;
|
|
14419
|
+
if (fs22.existsSync(path22.join(projectDir, "migrations", "env.py"))) return true;
|
|
14420
|
+
if (fs22.existsSync(path22.join(projectDir, "alembic", "env.py"))) return true;
|
|
14315
14421
|
return false;
|
|
14316
14422
|
},
|
|
14317
14423
|
async apply(args) {
|
|
@@ -14417,7 +14523,7 @@ var AlembicAdapter = {
|
|
|
14417
14523
|
autogenerate: !!args.autogenerate,
|
|
14418
14524
|
dsn
|
|
14419
14525
|
});
|
|
14420
|
-
return { status: "ok", version: revId, filename:
|
|
14526
|
+
return { status: "ok", version: revId, filename: path22.basename(created), path: created };
|
|
14421
14527
|
} catch (err) {
|
|
14422
14528
|
return {
|
|
14423
14529
|
status: "error",
|
|
@@ -14434,7 +14540,7 @@ var AlembicAdapter = {
|
|
|
14434
14540
|
if (heads.length <= 1) return { status: "noop", headsBefore: heads };
|
|
14435
14541
|
if (args.dryRun) return { status: "ok", headsBefore: heads };
|
|
14436
14542
|
const created = await mergeAlembicHeads(args.projectDir, args.message ?? "merge heads");
|
|
14437
|
-
const mergeRevision =
|
|
14543
|
+
const mergeRevision = path22.basename(created).replace(/\.py$/, "").split("_")[0];
|
|
14438
14544
|
return { status: "ok", headsBefore: heads, mergeRevision, path: created };
|
|
14439
14545
|
} catch (err) {
|
|
14440
14546
|
return {
|
|
@@ -14450,12 +14556,12 @@ registerSchemaMigrationAdapter(AlembicAdapter);
|
|
|
14450
14556
|
// scripts/lakebase/adapters/flyway-adapter.ts
|
|
14451
14557
|
init_esm_shims();
|
|
14452
14558
|
import * as fs23 from "fs";
|
|
14453
|
-
import * as
|
|
14559
|
+
import * as path24 from "path";
|
|
14454
14560
|
|
|
14455
14561
|
// scripts/lakebase/schema-migrate-runners/flyway.ts
|
|
14456
14562
|
init_esm_shims();
|
|
14457
14563
|
import { spawn as spawn6 } from "child_process";
|
|
14458
|
-
import * as
|
|
14564
|
+
import * as path23 from "path";
|
|
14459
14565
|
function dsnToFlywayEnv(dsn) {
|
|
14460
14566
|
const u = new URL(dsn);
|
|
14461
14567
|
const user = decodeURIComponent(u.username);
|
|
@@ -14465,7 +14571,7 @@ function dsnToFlywayEnv(dsn) {
|
|
|
14465
14571
|
return { url, user, password };
|
|
14466
14572
|
}
|
|
14467
14573
|
function migrationsLocation(projectDir) {
|
|
14468
|
-
return `filesystem:${
|
|
14574
|
+
return `filesystem:${path23.join(projectDir, "src", "main", "resources", "db", "migration")}`;
|
|
14469
14575
|
}
|
|
14470
14576
|
function runFlyway(ctx, args) {
|
|
14471
14577
|
const { url, user, password } = dsnToFlywayEnv(ctx.dsn);
|
|
@@ -14566,7 +14672,7 @@ async function statusFlyway(ctx) {
|
|
|
14566
14672
|
if (state === "SUCCESS" || state === "BASELINE") {
|
|
14567
14673
|
current = m.version;
|
|
14568
14674
|
} else if (state === "PENDING") {
|
|
14569
|
-
const filename = m.filepath ?
|
|
14675
|
+
const filename = m.filepath ? path23.basename(m.filepath) : `V${m.version}__migration.sql`;
|
|
14570
14676
|
pending.push({
|
|
14571
14677
|
version: m.version,
|
|
14572
14678
|
filename,
|
|
@@ -14589,7 +14695,7 @@ async function buildDsn3(args) {
|
|
|
14589
14695
|
return result.url;
|
|
14590
14696
|
}
|
|
14591
14697
|
function listFlywayFiles(projectDir) {
|
|
14592
|
-
const dir =
|
|
14698
|
+
const dir = path24.join(projectDir, "src", "main", "resources", "db", "migration");
|
|
14593
14699
|
if (!fs23.existsSync(dir)) return [];
|
|
14594
14700
|
const files = fs23.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
14595
14701
|
return files.map((filename) => {
|
|
@@ -14614,7 +14720,7 @@ var FlywayAdapter = {
|
|
|
14614
14720
|
id: "flyway",
|
|
14615
14721
|
languages: ["java", "kotlin"],
|
|
14616
14722
|
detect(projectDir) {
|
|
14617
|
-
return fs23.existsSync(
|
|
14723
|
+
return fs23.existsSync(path24.join(projectDir, "pom.xml"));
|
|
14618
14724
|
},
|
|
14619
14725
|
async apply(args) {
|
|
14620
14726
|
const dsn = await buildDsn3(args);
|
|
@@ -14672,12 +14778,12 @@ var FlywayAdapter = {
|
|
|
14672
14778
|
// optional-protocol shape makes this additive.
|
|
14673
14779
|
async newMigration(args) {
|
|
14674
14780
|
try {
|
|
14675
|
-
const dir =
|
|
14781
|
+
const dir = path24.join(args.projectDir, "src", "main", "resources", "db", "migration");
|
|
14676
14782
|
fs23.mkdirSync(dir, { recursive: true });
|
|
14677
14783
|
const version = migrationTimestamp();
|
|
14678
14784
|
const slug = migrationSlug2(args.slug);
|
|
14679
14785
|
const filename = `V${version}__${slug}.sql`;
|
|
14680
|
-
const full =
|
|
14786
|
+
const full = path24.join(dir, filename);
|
|
14681
14787
|
if (fs23.existsSync(full)) throw new Error(`${filename} already exists`);
|
|
14682
14788
|
fs23.writeFileSync(
|
|
14683
14789
|
full,
|
|
@@ -14703,17 +14809,17 @@ registerSchemaMigrationAdapter(FlywayAdapter);
|
|
|
14703
14809
|
// scripts/lakebase/adapters/knex-adapter.ts
|
|
14704
14810
|
init_esm_shims();
|
|
14705
14811
|
import * as fs25 from "fs";
|
|
14706
|
-
import * as
|
|
14812
|
+
import * as path26 from "path";
|
|
14707
14813
|
|
|
14708
14814
|
// scripts/lakebase/schema-migrate-runners/knex.ts
|
|
14709
14815
|
init_esm_shims();
|
|
14710
14816
|
import { spawn as spawn7 } from "child_process";
|
|
14711
14817
|
import * as fs24 from "fs";
|
|
14712
|
-
import * as
|
|
14818
|
+
import * as path25 from "path";
|
|
14713
14819
|
var KNEXFILE_VARIANTS = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14714
14820
|
function findKnexfile(projectDir) {
|
|
14715
14821
|
for (const name of KNEXFILE_VARIANTS) {
|
|
14716
|
-
const p =
|
|
14822
|
+
const p = path25.join(projectDir, name);
|
|
14717
14823
|
if (fs24.existsSync(p)) return p;
|
|
14718
14824
|
}
|
|
14719
14825
|
return void 0;
|
|
@@ -14866,7 +14972,7 @@ async function buildDsn4(args) {
|
|
|
14866
14972
|
}
|
|
14867
14973
|
var KNEXFILE_VARIANTS2 = ["knexfile.js", "knexfile.ts", "knexfile.mjs", "knexfile.cjs"];
|
|
14868
14974
|
function listKnexFiles(projectDir) {
|
|
14869
|
-
const dir =
|
|
14975
|
+
const dir = path26.join(projectDir, "migrations");
|
|
14870
14976
|
if (!fs25.existsSync(dir)) return [];
|
|
14871
14977
|
const files = fs25.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
14872
14978
|
return files.map((filename) => {
|
|
@@ -14888,7 +14994,7 @@ var KnexAdapter = {
|
|
|
14888
14994
|
* project.yaml#migration_tool.
|
|
14889
14995
|
*/
|
|
14890
14996
|
detect(projectDir) {
|
|
14891
|
-
return KNEXFILE_VARIANTS2.some((name) => fs25.existsSync(
|
|
14997
|
+
return KNEXFILE_VARIANTS2.some((name) => fs25.existsSync(path26.join(projectDir, name)));
|
|
14892
14998
|
},
|
|
14893
14999
|
async apply(args) {
|
|
14894
15000
|
const dsn = await buildDsn4(args);
|
|
@@ -14961,9 +15067,9 @@ var KnexAdapter = {
|
|
|
14961
15067
|
async newMigration(args) {
|
|
14962
15068
|
try {
|
|
14963
15069
|
const created = await createKnexMigration({ projectDir: args.projectDir, slug: migrationSlug2(args.slug) });
|
|
14964
|
-
const stem =
|
|
15070
|
+
const stem = path26.basename(created).replace(/\.(js|ts)$/, "");
|
|
14965
15071
|
const version = stem.match(/^(\d{14})_/)?.[1] ?? stem;
|
|
14966
|
-
return { status: "ok", version, filename:
|
|
15072
|
+
return { status: "ok", version, filename: path26.basename(created), path: created };
|
|
14967
15073
|
} catch (err) {
|
|
14968
15074
|
return {
|
|
14969
15075
|
status: "error",
|
|
@@ -15020,7 +15126,7 @@ function listSchemaMigrations(args = {}) {
|
|
|
15020
15126
|
}
|
|
15021
15127
|
}
|
|
15022
15128
|
function listFlywayMigrations(projectDir) {
|
|
15023
|
-
const dir =
|
|
15129
|
+
const dir = path27.join(projectDir, "src", "main", "resources", "db", "migration");
|
|
15024
15130
|
if (!fs26.existsSync(dir)) return [];
|
|
15025
15131
|
const files = fs26.readdirSync(dir).filter((f) => /^V\d+(\.\d+)*__.+\.sql$/.test(f));
|
|
15026
15132
|
return files.map((filename) => {
|
|
@@ -15032,8 +15138,8 @@ function listFlywayMigrations(projectDir) {
|
|
|
15032
15138
|
}
|
|
15033
15139
|
function listAlembicMigrations(projectDir) {
|
|
15034
15140
|
const candidates = [
|
|
15035
|
-
|
|
15036
|
-
|
|
15141
|
+
path27.join(projectDir, "migrations", "versions"),
|
|
15142
|
+
path27.join(projectDir, "alembic", "versions")
|
|
15037
15143
|
];
|
|
15038
15144
|
const dir = candidates.find((p) => fs26.existsSync(p));
|
|
15039
15145
|
if (!dir) return [];
|
|
@@ -15047,7 +15153,7 @@ function listAlembicMigrations(projectDir) {
|
|
|
15047
15153
|
}).sort((a, b) => a.filename.localeCompare(b.filename));
|
|
15048
15154
|
}
|
|
15049
15155
|
function listKnexMigrations(projectDir) {
|
|
15050
|
-
const dir =
|
|
15156
|
+
const dir = path27.join(projectDir, "migrations");
|
|
15051
15157
|
if (!fs26.existsSync(dir)) return [];
|
|
15052
15158
|
const files = fs26.readdirSync(dir).filter((f) => (f.endsWith(".js") || f.endsWith(".ts")) && !f.startsWith("."));
|
|
15053
15159
|
return files.map((filename) => {
|
|
@@ -15225,7 +15331,7 @@ async function runInfraSuite(args) {
|
|
|
15225
15331
|
duration_ms: Date.now() - start
|
|
15226
15332
|
};
|
|
15227
15333
|
if (args.junitOutput) {
|
|
15228
|
-
fs27.mkdirSync(
|
|
15334
|
+
fs27.mkdirSync(path28.dirname(args.junitOutput), { recursive: true });
|
|
15229
15335
|
fs27.writeFileSync(args.junitOutput, formatJUnit(result), "utf8");
|
|
15230
15336
|
}
|
|
15231
15337
|
return result;
|
|
@@ -15273,7 +15379,7 @@ function escapeXml(s) {
|
|
|
15273
15379
|
// scripts/lakebase/scm-claim-feature.ts
|
|
15274
15380
|
init_esm_shims();
|
|
15275
15381
|
import * as fs28 from "fs";
|
|
15276
|
-
import * as
|
|
15382
|
+
import * as path29 from "path";
|
|
15277
15383
|
var ScmClaimError = class extends Error {
|
|
15278
15384
|
constructor(message, code) {
|
|
15279
15385
|
super(message);
|
|
@@ -15330,7 +15436,7 @@ async function claimFeatureBranch(args) {
|
|
|
15330
15436
|
const current = readWorkflowState(args.projectDir);
|
|
15331
15437
|
if (!current) {
|
|
15332
15438
|
throw new ScmClaimError(
|
|
15333
|
-
`No SCM workflow state found at ${
|
|
15439
|
+
`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
15440
|
"no-state-file"
|
|
15335
15441
|
);
|
|
15336
15442
|
}
|
|
@@ -15435,7 +15541,7 @@ function alreadyClaimedSentinel(state) {
|
|
|
15435
15541
|
}
|
|
15436
15542
|
function workflowStateFileExists(projectDir) {
|
|
15437
15543
|
return fs28.existsSync(
|
|
15438
|
-
|
|
15544
|
+
path29.join(projectDir, ".lakebase/workflow-state.json")
|
|
15439
15545
|
);
|
|
15440
15546
|
}
|
|
15441
15547
|
|
|
@@ -15699,6 +15805,7 @@ async function preparePr(args) {
|
|
|
15699
15805
|
"no-github-remote"
|
|
15700
15806
|
);
|
|
15701
15807
|
}
|
|
15808
|
+
const ciFreshness = await ensureCiSecretsFreshFromEnv(args.projectDir, { ownerRepo });
|
|
15702
15809
|
const now = (args.now ?? (() => /* @__PURE__ */ new Date()))();
|
|
15703
15810
|
let prUrl = args.prUrlOverride ?? "";
|
|
15704
15811
|
let prCreated = false;
|
|
@@ -15743,7 +15850,7 @@ async function preparePr(args) {
|
|
|
15743
15850
|
pushed_at: now.toISOString()
|
|
15744
15851
|
};
|
|
15745
15852
|
writeWorkflowState(args.projectDir, next);
|
|
15746
|
-
return { state: next, prUrl, prCreated };
|
|
15853
|
+
return { state: next, prUrl, prCreated, ciFreshness };
|
|
15747
15854
|
}
|
|
15748
15855
|
async function ensureAheadOfParent(cwd, branch, parent) {
|
|
15749
15856
|
try {
|
|
@@ -15923,11 +16030,11 @@ async function pushCurrentBranchForPr(args) {
|
|
|
15923
16030
|
// scripts/lakebase/workflow-drift.ts
|
|
15924
16031
|
init_esm_shims();
|
|
15925
16032
|
import * as fs29 from "fs";
|
|
15926
|
-
import * as
|
|
16033
|
+
import * as path30 from "path";
|
|
15927
16034
|
function findKitTemplatesDir(start) {
|
|
15928
16035
|
let dir = start;
|
|
15929
16036
|
for (let i = 0; i < 6; i++) {
|
|
15930
|
-
const candidate =
|
|
16037
|
+
const candidate = path30.join(
|
|
15931
16038
|
dir,
|
|
15932
16039
|
"templates",
|
|
15933
16040
|
"project",
|
|
@@ -15936,7 +16043,7 @@ function findKitTemplatesDir(start) {
|
|
|
15936
16043
|
"workflows"
|
|
15937
16044
|
);
|
|
15938
16045
|
if (fs29.existsSync(candidate)) return candidate;
|
|
15939
|
-
const parent =
|
|
16046
|
+
const parent = path30.dirname(dir);
|
|
15940
16047
|
if (parent === dir) break;
|
|
15941
16048
|
dir = parent;
|
|
15942
16049
|
}
|
|
@@ -15960,13 +16067,13 @@ function unifiedDiff(name, projectContent, templateContent) {
|
|
|
15960
16067
|
return out.join("\n");
|
|
15961
16068
|
}
|
|
15962
16069
|
function detectWorkflowDrift(args) {
|
|
15963
|
-
const projectWorkflowsDir =
|
|
16070
|
+
const projectWorkflowsDir = path30.join(
|
|
15964
16071
|
args.projectDir,
|
|
15965
16072
|
".github",
|
|
15966
16073
|
"workflows"
|
|
15967
16074
|
);
|
|
15968
|
-
const here =
|
|
15969
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16075
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16076
|
+
const kitWorkflowsDir = args.kitDir ? path30.join(
|
|
15970
16077
|
args.kitDir,
|
|
15971
16078
|
"templates",
|
|
15972
16079
|
"project",
|
|
@@ -15981,8 +16088,8 @@ function detectWorkflowDrift(args) {
|
|
|
15981
16088
|
const files = [];
|
|
15982
16089
|
for (const name of templateFiles) {
|
|
15983
16090
|
seen.add(name);
|
|
15984
|
-
const projectPath2 =
|
|
15985
|
-
const templatePath =
|
|
16091
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16092
|
+
const templatePath = path30.join(kitWorkflowsDir, name);
|
|
15986
16093
|
if (!fs29.existsSync(projectPath2)) {
|
|
15987
16094
|
files.push({ name, status: "missing" });
|
|
15988
16095
|
continue;
|
|
@@ -16019,10 +16126,10 @@ function detectWorkflowDrift(args) {
|
|
|
16019
16126
|
function readKitVersion(kitWorkflowsDir) {
|
|
16020
16127
|
let dir = kitWorkflowsDir;
|
|
16021
16128
|
for (let i = 0; i < 5; i++) {
|
|
16022
|
-
dir =
|
|
16129
|
+
dir = path30.dirname(dir);
|
|
16023
16130
|
}
|
|
16024
16131
|
try {
|
|
16025
|
-
const raw = fs29.readFileSync(
|
|
16132
|
+
const raw = fs29.readFileSync(path30.join(dir, "package.json"), "utf-8");
|
|
16026
16133
|
const pkg = JSON.parse(raw);
|
|
16027
16134
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16028
16135
|
} catch {
|
|
@@ -16039,7 +16146,7 @@ var COMMAND_HOOK_FILE_PATTERN = /\.(pre|post)-hook\.md$/;
|
|
|
16039
16146
|
function findKitCommandsDir(start) {
|
|
16040
16147
|
let dir = start;
|
|
16041
16148
|
for (let i = 0; i < 6; i++) {
|
|
16042
|
-
const candidate =
|
|
16149
|
+
const candidate = path30.join(
|
|
16043
16150
|
dir,
|
|
16044
16151
|
"templates",
|
|
16045
16152
|
"project",
|
|
@@ -16048,7 +16155,7 @@ function findKitCommandsDir(start) {
|
|
|
16048
16155
|
"commands"
|
|
16049
16156
|
);
|
|
16050
16157
|
if (fs29.existsSync(candidate)) return candidate;
|
|
16051
|
-
const parent =
|
|
16158
|
+
const parent = path30.dirname(dir);
|
|
16052
16159
|
if (parent === dir) break;
|
|
16053
16160
|
dir = parent;
|
|
16054
16161
|
}
|
|
@@ -16061,9 +16168,9 @@ function parsePinnedVersion(content) {
|
|
|
16061
16168
|
return m ? m[1] : void 0;
|
|
16062
16169
|
}
|
|
16063
16170
|
function detectCommandDrift(args) {
|
|
16064
|
-
const projectCommandsDir =
|
|
16065
|
-
const here =
|
|
16066
|
-
const kitCommandsDir = args.kitDir ?
|
|
16171
|
+
const projectCommandsDir = path30.join(args.projectDir, ".claude", "commands");
|
|
16172
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16173
|
+
const kitCommandsDir = args.kitDir ? path30.join(args.kitDir, "templates", "project", "common", ".claude", "commands") : findKitCommandsDir(here);
|
|
16067
16174
|
const kitVersion = readKitVersionFromCommandsDir(kitCommandsDir);
|
|
16068
16175
|
const templateFiles = fs29.existsSync(kitCommandsDir) ? fs29.readdirSync(kitCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
16069
16176
|
const projectFiles = fs29.existsSync(projectCommandsDir) ? fs29.readdirSync(projectCommandsDir).filter((f) => f.endsWith(".md") && !COMMAND_HOOK_FILE_PATTERN.test(f)) : [];
|
|
@@ -16071,8 +16178,8 @@ function detectCommandDrift(args) {
|
|
|
16071
16178
|
const files = [];
|
|
16072
16179
|
for (const name of templateFiles) {
|
|
16073
16180
|
seen.add(name);
|
|
16074
|
-
const projectPath2 =
|
|
16075
|
-
const templatePath =
|
|
16181
|
+
const projectPath2 = path30.join(projectCommandsDir, name);
|
|
16182
|
+
const templatePath = path30.join(kitCommandsDir, name);
|
|
16076
16183
|
const templateRaw = fs29.readFileSync(templatePath, "utf8");
|
|
16077
16184
|
if (!fs29.existsSync(projectPath2)) {
|
|
16078
16185
|
files.push({ name, status: "missing", kit_version: kitVersion });
|
|
@@ -16116,10 +16223,10 @@ function detectCommandDrift(args) {
|
|
|
16116
16223
|
function readKitVersionFromCommandsDir(kitCommandsDir) {
|
|
16117
16224
|
let dir = kitCommandsDir;
|
|
16118
16225
|
for (let i = 0; i < 5; i++) {
|
|
16119
|
-
dir =
|
|
16226
|
+
dir = path30.dirname(dir);
|
|
16120
16227
|
}
|
|
16121
16228
|
try {
|
|
16122
|
-
const raw = fs29.readFileSync(
|
|
16229
|
+
const raw = fs29.readFileSync(path30.join(dir, "package.json"), "utf-8");
|
|
16123
16230
|
const pkg = JSON.parse(raw);
|
|
16124
16231
|
return typeof pkg.version === "string" ? pkg.version : "unknown";
|
|
16125
16232
|
} catch {
|
|
@@ -16136,13 +16243,13 @@ function detectScaffoldedDrift(args) {
|
|
|
16136
16243
|
};
|
|
16137
16244
|
}
|
|
16138
16245
|
function updateWorkflows(args) {
|
|
16139
|
-
const projectWorkflowsDir =
|
|
16246
|
+
const projectWorkflowsDir = path30.join(
|
|
16140
16247
|
args.projectDir,
|
|
16141
16248
|
".github",
|
|
16142
16249
|
"workflows"
|
|
16143
16250
|
);
|
|
16144
|
-
const here =
|
|
16145
|
-
const kitWorkflowsDir = args.kitDir ?
|
|
16251
|
+
const here = path30.dirname(new URL(import.meta.url).pathname);
|
|
16252
|
+
const kitWorkflowsDir = args.kitDir ? path30.join(
|
|
16146
16253
|
args.kitDir,
|
|
16147
16254
|
"templates",
|
|
16148
16255
|
"project",
|
|
@@ -16163,8 +16270,8 @@ function updateWorkflows(args) {
|
|
|
16163
16270
|
const files = [];
|
|
16164
16271
|
for (const name of templateFiles) {
|
|
16165
16272
|
seen.add(name);
|
|
16166
|
-
const projectPath2 =
|
|
16167
|
-
const templatePath =
|
|
16273
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16274
|
+
const templatePath = path30.join(kitWorkflowsDir, name);
|
|
16168
16275
|
const templateRaw = fs29.readFileSync(templatePath, "utf-8");
|
|
16169
16276
|
const desired = substitute ? applyPlaceholders(templateRaw, version) : templateRaw;
|
|
16170
16277
|
const existed = fs29.existsSync(projectPath2);
|
|
@@ -16185,7 +16292,7 @@ function updateWorkflows(args) {
|
|
|
16185
16292
|
if (pruneExtras) {
|
|
16186
16293
|
for (const name of projectFiles) {
|
|
16187
16294
|
if (seen.has(name)) continue;
|
|
16188
|
-
const projectPath2 =
|
|
16295
|
+
const projectPath2 = path30.join(projectWorkflowsDir, name);
|
|
16189
16296
|
if (!dryRun) {
|
|
16190
16297
|
fs29.unlinkSync(projectPath2);
|
|
16191
16298
|
}
|
|
@@ -16372,6 +16479,15 @@ async function mergeFeature(args) {
|
|
|
16372
16479
|
);
|
|
16373
16480
|
}
|
|
16374
16481
|
}
|
|
16482
|
+
{
|
|
16483
|
+
const ensure = args.ensureCiFresh ?? ((repo) => ensureCiSecretsFreshFromEnv(args.projectDir, { ownerRepo: repo }));
|
|
16484
|
+
try {
|
|
16485
|
+
const r = await ensure(ownerRepo);
|
|
16486
|
+
if (r.action !== "ok" && r.action !== "skipped") preflightNotes.push(`CI-auth preflight: ${r.reason}`);
|
|
16487
|
+
} catch (err) {
|
|
16488
|
+
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.`);
|
|
16489
|
+
}
|
|
16490
|
+
}
|
|
16375
16491
|
{
|
|
16376
16492
|
const fetchState = args.fetchPrState ?? ((o, h) => getPullRequest(o, h));
|
|
16377
16493
|
const prState = await fetchState(ownerRepo, current.branch).catch(() => void 0);
|
|
@@ -16777,11 +16893,11 @@ function parentForTopology(t, defaultLeaf) {
|
|
|
16777
16893
|
// scripts/lakebase/scm-doctor.ts
|
|
16778
16894
|
init_esm_shims();
|
|
16779
16895
|
import * as fs30 from "fs";
|
|
16780
|
-
import * as
|
|
16896
|
+
import * as path31 from "path";
|
|
16781
16897
|
var FEATURE_PREFIX = "feature/";
|
|
16782
16898
|
var TIER_LEAFS2 = DEFAULT_PROTECTED_TIER_NAMES;
|
|
16783
16899
|
function readEnv(projectDir) {
|
|
16784
|
-
const envPath =
|
|
16900
|
+
const envPath = path31.join(projectDir, ".env");
|
|
16785
16901
|
const out = /* @__PURE__ */ new Map();
|
|
16786
16902
|
if (!fs30.existsSync(envPath)) return out;
|
|
16787
16903
|
const lines = fs30.readFileSync(envPath, "utf8").split("\n");
|
|
@@ -16839,7 +16955,7 @@ async function runDoctor(args, deps = {}) {
|
|
|
16839
16955
|
}
|
|
16840
16956
|
for (const wf of ["pr.yml", "merge.yml"]) {
|
|
16841
16957
|
try {
|
|
16842
|
-
const p =
|
|
16958
|
+
const p = path31.join(projectDir, ".github", "workflows", wf);
|
|
16843
16959
|
if (!fs30.existsSync(p)) continue;
|
|
16844
16960
|
const body = fs30.readFileSync(p, "utf8");
|
|
16845
16961
|
if (/lakebase-scm-utils#v\d/.test(body)) {
|
|
@@ -17056,7 +17172,7 @@ async function fixFinding(args) {
|
|
|
17056
17172
|
);
|
|
17057
17173
|
}
|
|
17058
17174
|
const sanitized = sanitizeBranchName(branch);
|
|
17059
|
-
const envFile =
|
|
17175
|
+
const envFile = path31.join(args.projectDir, ".env");
|
|
17060
17176
|
updateEnvConnection({
|
|
17061
17177
|
envPath: envFile,
|
|
17062
17178
|
projectId: readEnvVar(envFile, "LAKEBASE_PROJECT_ID") ?? "",
|
|
@@ -17159,10 +17275,10 @@ function shellEscape3(s) {
|
|
|
17159
17275
|
// scripts/lakebase/doctor.ts
|
|
17160
17276
|
init_esm_shims();
|
|
17161
17277
|
import * as fs31 from "fs";
|
|
17162
|
-
import * as
|
|
17278
|
+
import * as path32 from "path";
|
|
17163
17279
|
import * as cp6 from "child_process";
|
|
17164
17280
|
function readEnvFile(projectDir) {
|
|
17165
|
-
const envPath =
|
|
17281
|
+
const envPath = path32.join(projectDir, ".env");
|
|
17166
17282
|
if (!fs31.existsSync(envPath)) return {};
|
|
17167
17283
|
const out = {};
|
|
17168
17284
|
for (const line of fs31.readFileSync(envPath, "utf8").split("\n")) {
|
|
@@ -17420,7 +17536,7 @@ function checkEnv(projectDir) {
|
|
|
17420
17536
|
name: "env-file",
|
|
17421
17537
|
status: "warn",
|
|
17422
17538
|
message: ".env not found",
|
|
17423
|
-
detail: { projectDir, envPath:
|
|
17539
|
+
detail: { projectDir, envPath: path32.join(projectDir, ".env") },
|
|
17424
17540
|
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
17541
|
};
|
|
17426
17542
|
}
|
|
@@ -17906,6 +18022,7 @@ export {
|
|
|
17906
18022
|
deleteBranch,
|
|
17907
18023
|
deleteLakebaseProject,
|
|
17908
18024
|
deletePairedBranch,
|
|
18025
|
+
deleteProjectArgs,
|
|
17909
18026
|
deployClaudeAgents,
|
|
17910
18027
|
deployClaudeCommands,
|
|
17911
18028
|
deployClaudeSettings,
|