@databricks-solutions/lakebase-scm-utils 0.2.46 → 0.2.48
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/{pr-D3CteJaf.d.cts → pr-e-E4aP4j.d.cts} +6 -0
- package/dist/{pr-D3CteJaf.d.ts → pr-e-E4aP4j.d.ts} +6 -0
- package/dist/scripts/github/index.cjs +2 -0
- package/dist/scripts/github/index.d.cts +1 -1
- package/dist/scripts/github/index.d.ts +1 -1
- package/dist/scripts/github/index.js +2 -0
- package/dist/scripts/github/pr.cli.cjs +2 -0
- package/dist/scripts/github/pr.cli.js +2 -0
- package/dist/scripts/index.cjs +81 -4
- package/dist/scripts/index.d.cts +3 -3
- package/dist/scripts/index.d.ts +3 -3
- package/dist/scripts/index.js +78 -4
- 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 +87 -4
- package/dist/scripts/lakebase/index.d.cts +32 -14
- package/dist/scripts/lakebase/index.d.ts +32 -14
- package/dist/scripts/lakebase/index.js +86 -4
- 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 +131 -2
- package/dist/scripts/lakebase/scm-merge.cli.js +131 -2
- package/dist/scripts/lakebase/scm-prepare-pr.cli.cjs +2 -0
- package/dist/scripts/lakebase/scm-prepare-pr.cli.js +2 -0
- 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/scm-wait-ci.cli.cjs +8 -0
- package/dist/scripts/lakebase/scm-wait-ci.cli.js +8 -0
- package/dist/scripts/lakebase/sync-ci-secrets.cli.cjs +8610 -0
- package/dist/scripts/lakebase/sync-ci-secrets.cli.d.cts +4 -0
- package/dist/scripts/lakebase/sync-ci-secrets.cli.d.ts +4 -0
- package/dist/scripts/lakebase/sync-ci-secrets.cli.js +8597 -0
- package/dist/scripts/util/index.cjs +21 -2
- package/dist/scripts/util/index.d.cts +9 -1
- package/dist/scripts/util/index.d.ts +9 -1
- package/dist/scripts/util/index.js +19 -2
- package/package.json +3 -2
- package/scripts/github/pr.ts +8 -0
- package/scripts/lakebase/create-project.ts +14 -3
- package/scripts/lakebase/scm-merge.ts +91 -0
- package/scripts/lakebase/scm-wait-ci.ts +13 -0
- package/scripts/lakebase/sync-ci-secrets.cli.ts +122 -0
- package/scripts/util/ci-secrets.ts +14 -1
- package/templates/project/common/.gitignore.base +4 -0
- package/templates/project/common/scripts/lk +22 -4
|
@@ -393,8 +393,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
393
393
|
var cached;
|
|
394
394
|
function substrateSelfVersion() {
|
|
395
395
|
if (cached !== void 0) return cached;
|
|
396
|
-
if ("0.2.
|
|
397
|
-
cached = "0.2.
|
|
396
|
+
if ("0.2.48".length > 0) {
|
|
397
|
+
cached = "0.2.48";
|
|
398
398
|
return cached;
|
|
399
399
|
}
|
|
400
400
|
cached = "unknown";
|
|
@@ -79288,8 +79288,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
79288
79288
|
var cached;
|
|
79289
79289
|
function substrateSelfVersion() {
|
|
79290
79290
|
if (cached !== void 0) return cached;
|
|
79291
|
-
if ("0.2.
|
|
79292
|
-
cached = "0.2.
|
|
79291
|
+
if ("0.2.48".length > 0) {
|
|
79292
|
+
cached = "0.2.48";
|
|
79293
79293
|
return cached;
|
|
79294
79294
|
}
|
|
79295
79295
|
cached = "unknown";
|
|
@@ -389,8 +389,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
389
389
|
var cached;
|
|
390
390
|
function substrateSelfVersion() {
|
|
391
391
|
if (cached !== void 0) return cached;
|
|
392
|
-
if ("0.2.
|
|
393
|
-
cached = "0.2.
|
|
392
|
+
if ("0.2.48".length > 0) {
|
|
393
|
+
cached = "0.2.48";
|
|
394
394
|
return cached;
|
|
395
395
|
}
|
|
396
396
|
cached = "unknown";
|
|
@@ -79324,8 +79324,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
79324
79324
|
var cached;
|
|
79325
79325
|
function substrateSelfVersion() {
|
|
79326
79326
|
if (cached !== void 0) return cached;
|
|
79327
|
-
if ("0.2.
|
|
79328
|
-
cached = "0.2.
|
|
79327
|
+
if ("0.2.48".length > 0) {
|
|
79328
|
+
cached = "0.2.48";
|
|
79329
79329
|
return cached;
|
|
79330
79330
|
}
|
|
79331
79331
|
cached = "unknown";
|
|
@@ -427,8 +427,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
427
427
|
var cached;
|
|
428
428
|
function substrateSelfVersion() {
|
|
429
429
|
if (cached !== void 0) return cached;
|
|
430
|
-
if ("0.2.
|
|
431
|
-
cached = "0.2.
|
|
430
|
+
if ("0.2.48".length > 0) {
|
|
431
|
+
cached = "0.2.48";
|
|
432
432
|
return cached;
|
|
433
433
|
}
|
|
434
434
|
cached = "unknown";
|
|
@@ -79783,8 +79783,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
79783
79783
|
var cached;
|
|
79784
79784
|
function substrateSelfVersion() {
|
|
79785
79785
|
if (cached !== void 0) return cached;
|
|
79786
|
-
if ("0.2.
|
|
79787
|
-
cached = "0.2.
|
|
79786
|
+
if ("0.2.48".length > 0) {
|
|
79787
|
+
cached = "0.2.48";
|
|
79788
79788
|
return cached;
|
|
79789
79789
|
}
|
|
79790
79790
|
cached = "unknown";
|
|
@@ -864,8 +864,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
864
864
|
var cached;
|
|
865
865
|
function substrateSelfVersion() {
|
|
866
866
|
if (cached !== void 0) return cached;
|
|
867
|
-
if ("0.2.
|
|
868
|
-
cached = "0.2.
|
|
867
|
+
if ("0.2.48".length > 0) {
|
|
868
|
+
cached = "0.2.48";
|
|
869
869
|
return cached;
|
|
870
870
|
}
|
|
871
871
|
cached = "unknown";
|
|
@@ -88240,8 +88240,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
88240
88240
|
var cached;
|
|
88241
88241
|
function substrateSelfVersion() {
|
|
88242
88242
|
if (cached !== void 0) return cached;
|
|
88243
|
-
if ("0.2.
|
|
88244
|
-
cached = "0.2.
|
|
88243
|
+
if ("0.2.48".length > 0) {
|
|
88244
|
+
cached = "0.2.48";
|
|
88245
88245
|
return cached;
|
|
88246
88246
|
}
|
|
88247
88247
|
cached = "unknown";
|
|
@@ -9393,8 +9393,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
9393
9393
|
var cached;
|
|
9394
9394
|
function substrateSelfVersion() {
|
|
9395
9395
|
if (cached !== void 0) return cached;
|
|
9396
|
-
if ("0.2.
|
|
9397
|
-
cached = "0.2.
|
|
9396
|
+
if ("0.2.48".length > 0) {
|
|
9397
|
+
cached = "0.2.48";
|
|
9398
9398
|
return cached;
|
|
9399
9399
|
}
|
|
9400
9400
|
cached = "unknown";
|
|
@@ -86087,6 +86087,84 @@ function wrap(err, context) {
|
|
|
86087
86087
|
}
|
|
86088
86088
|
throw new GitHubPullRequestError(context);
|
|
86089
86089
|
}
|
|
86090
|
+
async function getPullRequest(ownerRepo, headBranch) {
|
|
86091
|
+
try {
|
|
86092
|
+
const { owner, repo } = parseOwnerRepo(ownerRepo);
|
|
86093
|
+
const ok = await octokit();
|
|
86094
|
+
const { data: pulls } = await ok.rest.pulls.list({
|
|
86095
|
+
owner,
|
|
86096
|
+
repo,
|
|
86097
|
+
state: "open",
|
|
86098
|
+
head: `${owner}:${headBranch}`,
|
|
86099
|
+
per_page: 1
|
|
86100
|
+
});
|
|
86101
|
+
if (pulls.length === 0) return void 0;
|
|
86102
|
+
const { data: pr } = await ok.rest.pulls.get({
|
|
86103
|
+
owner,
|
|
86104
|
+
repo,
|
|
86105
|
+
pull_number: pulls[0].number
|
|
86106
|
+
});
|
|
86107
|
+
if (pr.state !== "open") return void 0;
|
|
86108
|
+
let checks = [];
|
|
86109
|
+
let ciStatus = "pending";
|
|
86110
|
+
const headSha = pr.head?.sha;
|
|
86111
|
+
if (headSha) {
|
|
86112
|
+
try {
|
|
86113
|
+
const { data: checksData } = await ok.rest.checks.listForRef({
|
|
86114
|
+
owner,
|
|
86115
|
+
repo,
|
|
86116
|
+
ref: headSha
|
|
86117
|
+
});
|
|
86118
|
+
const runs = checksData.check_runs || [];
|
|
86119
|
+
checks = runs.map((c) => ({
|
|
86120
|
+
name: c.name || "unknown",
|
|
86121
|
+
status: (c.status || "").toUpperCase(),
|
|
86122
|
+
conclusion: (c.conclusion || "").toUpperCase(),
|
|
86123
|
+
detailsUrl: c.details_url || void 0
|
|
86124
|
+
}));
|
|
86125
|
+
ciStatus = parseCiStatus(runs);
|
|
86126
|
+
} catch {
|
|
86127
|
+
ciStatus = "pending";
|
|
86128
|
+
}
|
|
86129
|
+
}
|
|
86130
|
+
return {
|
|
86131
|
+
number: pr.number,
|
|
86132
|
+
title: pr.title,
|
|
86133
|
+
url: pr.html_url || "",
|
|
86134
|
+
state: (pr.state || "open").toUpperCase(),
|
|
86135
|
+
isDraft: pr.draft || false,
|
|
86136
|
+
ciStatus,
|
|
86137
|
+
checks,
|
|
86138
|
+
mergeable: pr.mergeable,
|
|
86139
|
+
mergeableState: pr.mergeable_state,
|
|
86140
|
+
headBranch: pr.head?.ref || headBranch,
|
|
86141
|
+
baseBranch: pr.base?.ref || "",
|
|
86142
|
+
body: pr.body || void 0,
|
|
86143
|
+
additions: pr.additions,
|
|
86144
|
+
deletions: pr.deletions,
|
|
86145
|
+
changedFiles: pr.changed_files
|
|
86146
|
+
};
|
|
86147
|
+
} catch {
|
|
86148
|
+
return void 0;
|
|
86149
|
+
}
|
|
86150
|
+
}
|
|
86151
|
+
function parseCiStatus(rawChecks) {
|
|
86152
|
+
if (rawChecks.length === 0) return "pending";
|
|
86153
|
+
const latestByName = /* @__PURE__ */ new Map();
|
|
86154
|
+
for (const c of rawChecks) {
|
|
86155
|
+
latestByName.set(c.name || "unknown", c);
|
|
86156
|
+
}
|
|
86157
|
+
const states = Array.from(latestByName.values()).map(
|
|
86158
|
+
(c) => (c.conclusion || c.status || "").toUpperCase()
|
|
86159
|
+
);
|
|
86160
|
+
if (states.some((s2) => s2 === "FAILURE" || s2 === "ERROR" || s2 === "ACTION_REQUIRED")) {
|
|
86161
|
+
return "failure";
|
|
86162
|
+
}
|
|
86163
|
+
if (states.every((s2) => s2 === "SUCCESS" || s2 === "NEUTRAL" || s2 === "SKIPPED")) {
|
|
86164
|
+
return "success";
|
|
86165
|
+
}
|
|
86166
|
+
return "pending";
|
|
86167
|
+
}
|
|
86090
86168
|
async function mergePullRequest(args) {
|
|
86091
86169
|
const method = args.method ?? "merge";
|
|
86092
86170
|
const deleteRemoteBranch = args.deleteRemoteBranch !== false;
|
|
@@ -86781,6 +86859,48 @@ function shaMigratePredicate(mergeCommitSha) {
|
|
|
86781
86859
|
return !!run.headSha && run.headSha === mergeCommitSha;
|
|
86782
86860
|
};
|
|
86783
86861
|
}
|
|
86862
|
+
var PROMOTE_RUNSTATE_CONFLICT = /(^|\/)\.consort\/(features\/[^/]+\/)?pipeline\.json$/;
|
|
86863
|
+
async function reconcilePromoteRunState(projectDir, baseBranch) {
|
|
86864
|
+
const o = { cwd: projectDir, timeout: 3e4 };
|
|
86865
|
+
const dirty = (await exec2("git status --porcelain", o).catch(() => "")).split("\n").map((l) => l.slice(3).trim()).filter(Boolean);
|
|
86866
|
+
const nonRunStateDirty = dirty.filter((p) => !p.startsWith(".consort/"));
|
|
86867
|
+
if (nonRunStateDirty.length > 0) {
|
|
86868
|
+
throw new ScmMergeError(
|
|
86869
|
+
`working tree has uncommitted non-run-state changes (${nonRunStateDirty.slice(0, 5).join(", ")}${nonRunStateDirty.length > 5 ? ", \u2026" : ""}); commit or stash before promoting.`,
|
|
86870
|
+
"promote-conflict"
|
|
86871
|
+
);
|
|
86872
|
+
}
|
|
86873
|
+
if (dirty.length > 0) {
|
|
86874
|
+
await exec2(`git add ${shellEscape(".consort")}`, o);
|
|
86875
|
+
await exec2(`git commit -m ${shellEscape("chore(run): checkpoint run state before promotion")}`, o);
|
|
86876
|
+
}
|
|
86877
|
+
await exec2(`git fetch origin ${shellEscape(baseBranch)}`, o).catch(() => {
|
|
86878
|
+
});
|
|
86879
|
+
let conflicted = false;
|
|
86880
|
+
try {
|
|
86881
|
+
await exec2(`git merge --no-ff -m ${shellEscape(`merge ${baseBranch} for promotion`)} ${shellEscape(`origin/${baseBranch}`)}`, o);
|
|
86882
|
+
} catch {
|
|
86883
|
+
conflicted = true;
|
|
86884
|
+
}
|
|
86885
|
+
if (!conflicted) return { reconciled: false };
|
|
86886
|
+
const u = (await exec2("git diff --name-only --diff-filter=U", o).catch(() => "")).split("\n").map((s2) => s2.trim()).filter(Boolean);
|
|
86887
|
+
const other = u.filter((p) => !PROMOTE_RUNSTATE_CONFLICT.test(p));
|
|
86888
|
+
if (u.length === 0 || other.length > 0) {
|
|
86889
|
+
await exec2("git merge --abort", o).catch(() => {
|
|
86890
|
+
});
|
|
86891
|
+
throw new ScmMergeError(
|
|
86892
|
+
other.length > 0 ? `promotion conflicts on non-ledger file(s): ${other.join(", ")}. Resolve the real divergence manually, then re-run the promote.` : `promotion merge failed with no resolvable conflicts; resolve manually and re-run.`,
|
|
86893
|
+
"promote-conflict"
|
|
86894
|
+
);
|
|
86895
|
+
}
|
|
86896
|
+
for (const p of u) {
|
|
86897
|
+
await exec2(`git checkout --ours -- ${shellEscape(p)}`, o);
|
|
86898
|
+
await exec2(`git add -- ${shellEscape(p)}`, o);
|
|
86899
|
+
}
|
|
86900
|
+
await exec2(`git commit -m ${shellEscape(`merge ${baseBranch} for promotion (pipeline.json ledger kept at run state)`)}`, o);
|
|
86901
|
+
await pushCurrentBranchForPr({ cwd: projectDir });
|
|
86902
|
+
return { reconciled: true, detail: `reconciled ${u.length} ledger path(s) to the run side + pushed` };
|
|
86903
|
+
}
|
|
86784
86904
|
async function defaultRefreshPromoteWorkflows(projectDir) {
|
|
86785
86905
|
const drift = detectWorkflowDrift({ projectDir });
|
|
86786
86906
|
const touched = drift.files.filter((f3) => f3.status === "drifted").map((f3) => f3.name);
|
|
@@ -86870,6 +86990,15 @@ async function mergeFeature(args) {
|
|
|
86870
86990
|
);
|
|
86871
86991
|
}
|
|
86872
86992
|
}
|
|
86993
|
+
{
|
|
86994
|
+
const fetchState = args.fetchPrState ?? ((o, h2) => getPullRequest(o, h2));
|
|
86995
|
+
const prState = await fetchState(ownerRepo, current.branch).catch(() => void 0);
|
|
86996
|
+
if (prState?.mergeableState === "dirty") {
|
|
86997
|
+
const reconcile = args.reconcileRunState ?? ((base) => reconcilePromoteRunState(args.projectDir, base));
|
|
86998
|
+
const r2 = await reconcile(gitBase);
|
|
86999
|
+
if (r2.reconciled) preflightNotes.push(`Reconciled a pipeline.json-ledger promotion conflict to the run side${r2.detail ? ` (${r2.detail})` : ""}.`);
|
|
87000
|
+
}
|
|
87001
|
+
}
|
|
86873
87002
|
let paired;
|
|
86874
87003
|
try {
|
|
86875
87004
|
paired = await mergePairedPullRequest({
|
|
@@ -88474,8 +88603,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
88474
88603
|
var cached;
|
|
88475
88604
|
function substrateSelfVersion() {
|
|
88476
88605
|
if (cached !== void 0) return cached;
|
|
88477
|
-
if ("0.2.
|
|
88478
|
-
cached = "0.2.
|
|
88606
|
+
if ("0.2.48".length > 0) {
|
|
88607
|
+
cached = "0.2.48";
|
|
88479
88608
|
return cached;
|
|
88480
88609
|
}
|
|
88481
88610
|
cached = "unknown";
|
|
@@ -8609,6 +8609,84 @@ function wrap(err, context) {
|
|
|
8609
8609
|
}
|
|
8610
8610
|
throw new GitHubPullRequestError(context);
|
|
8611
8611
|
}
|
|
8612
|
+
async function getPullRequest(ownerRepo, headBranch) {
|
|
8613
|
+
try {
|
|
8614
|
+
const { owner, repo } = parseOwnerRepo(ownerRepo);
|
|
8615
|
+
const ok = await octokit();
|
|
8616
|
+
const { data: pulls } = await ok.rest.pulls.list({
|
|
8617
|
+
owner,
|
|
8618
|
+
repo,
|
|
8619
|
+
state: "open",
|
|
8620
|
+
head: `${owner}:${headBranch}`,
|
|
8621
|
+
per_page: 1
|
|
8622
|
+
});
|
|
8623
|
+
if (pulls.length === 0) return void 0;
|
|
8624
|
+
const { data: pr } = await ok.rest.pulls.get({
|
|
8625
|
+
owner,
|
|
8626
|
+
repo,
|
|
8627
|
+
pull_number: pulls[0].number
|
|
8628
|
+
});
|
|
8629
|
+
if (pr.state !== "open") return void 0;
|
|
8630
|
+
let checks = [];
|
|
8631
|
+
let ciStatus = "pending";
|
|
8632
|
+
const headSha = pr.head?.sha;
|
|
8633
|
+
if (headSha) {
|
|
8634
|
+
try {
|
|
8635
|
+
const { data: checksData } = await ok.rest.checks.listForRef({
|
|
8636
|
+
owner,
|
|
8637
|
+
repo,
|
|
8638
|
+
ref: headSha
|
|
8639
|
+
});
|
|
8640
|
+
const runs = checksData.check_runs || [];
|
|
8641
|
+
checks = runs.map((c) => ({
|
|
8642
|
+
name: c.name || "unknown",
|
|
8643
|
+
status: (c.status || "").toUpperCase(),
|
|
8644
|
+
conclusion: (c.conclusion || "").toUpperCase(),
|
|
8645
|
+
detailsUrl: c.details_url || void 0
|
|
8646
|
+
}));
|
|
8647
|
+
ciStatus = parseCiStatus(runs);
|
|
8648
|
+
} catch {
|
|
8649
|
+
ciStatus = "pending";
|
|
8650
|
+
}
|
|
8651
|
+
}
|
|
8652
|
+
return {
|
|
8653
|
+
number: pr.number,
|
|
8654
|
+
title: pr.title,
|
|
8655
|
+
url: pr.html_url || "",
|
|
8656
|
+
state: (pr.state || "open").toUpperCase(),
|
|
8657
|
+
isDraft: pr.draft || false,
|
|
8658
|
+
ciStatus,
|
|
8659
|
+
checks,
|
|
8660
|
+
mergeable: pr.mergeable,
|
|
8661
|
+
mergeableState: pr.mergeable_state,
|
|
8662
|
+
headBranch: pr.head?.ref || headBranch,
|
|
8663
|
+
baseBranch: pr.base?.ref || "",
|
|
8664
|
+
body: pr.body || void 0,
|
|
8665
|
+
additions: pr.additions,
|
|
8666
|
+
deletions: pr.deletions,
|
|
8667
|
+
changedFiles: pr.changed_files
|
|
8668
|
+
};
|
|
8669
|
+
} catch {
|
|
8670
|
+
return void 0;
|
|
8671
|
+
}
|
|
8672
|
+
}
|
|
8673
|
+
function parseCiStatus(rawChecks) {
|
|
8674
|
+
if (rawChecks.length === 0) return "pending";
|
|
8675
|
+
const latestByName = /* @__PURE__ */ new Map();
|
|
8676
|
+
for (const c of rawChecks) {
|
|
8677
|
+
latestByName.set(c.name || "unknown", c);
|
|
8678
|
+
}
|
|
8679
|
+
const states = Array.from(latestByName.values()).map(
|
|
8680
|
+
(c) => (c.conclusion || c.status || "").toUpperCase()
|
|
8681
|
+
);
|
|
8682
|
+
if (states.some((s) => s === "FAILURE" || s === "ERROR" || s === "ACTION_REQUIRED")) {
|
|
8683
|
+
return "failure";
|
|
8684
|
+
}
|
|
8685
|
+
if (states.every((s) => s === "SUCCESS" || s === "NEUTRAL" || s === "SKIPPED")) {
|
|
8686
|
+
return "success";
|
|
8687
|
+
}
|
|
8688
|
+
return "pending";
|
|
8689
|
+
}
|
|
8612
8690
|
async function mergePullRequest(args) {
|
|
8613
8691
|
const method = args.method ?? "merge";
|
|
8614
8692
|
const deleteRemoteBranch = args.deleteRemoteBranch !== false;
|
|
@@ -9303,6 +9381,48 @@ function shaMigratePredicate(mergeCommitSha) {
|
|
|
9303
9381
|
return !!run.headSha && run.headSha === mergeCommitSha;
|
|
9304
9382
|
};
|
|
9305
9383
|
}
|
|
9384
|
+
var PROMOTE_RUNSTATE_CONFLICT = /(^|\/)\.consort\/(features\/[^/]+\/)?pipeline\.json$/;
|
|
9385
|
+
async function reconcilePromoteRunState(projectDir, baseBranch) {
|
|
9386
|
+
const o = { cwd: projectDir, timeout: 3e4 };
|
|
9387
|
+
const dirty = (await exec2("git status --porcelain", o).catch(() => "")).split("\n").map((l) => l.slice(3).trim()).filter(Boolean);
|
|
9388
|
+
const nonRunStateDirty = dirty.filter((p) => !p.startsWith(".consort/"));
|
|
9389
|
+
if (nonRunStateDirty.length > 0) {
|
|
9390
|
+
throw new ScmMergeError(
|
|
9391
|
+
`working tree has uncommitted non-run-state changes (${nonRunStateDirty.slice(0, 5).join(", ")}${nonRunStateDirty.length > 5 ? ", \u2026" : ""}); commit or stash before promoting.`,
|
|
9392
|
+
"promote-conflict"
|
|
9393
|
+
);
|
|
9394
|
+
}
|
|
9395
|
+
if (dirty.length > 0) {
|
|
9396
|
+
await exec2(`git add ${shellEscape(".consort")}`, o);
|
|
9397
|
+
await exec2(`git commit -m ${shellEscape("chore(run): checkpoint run state before promotion")}`, o);
|
|
9398
|
+
}
|
|
9399
|
+
await exec2(`git fetch origin ${shellEscape(baseBranch)}`, o).catch(() => {
|
|
9400
|
+
});
|
|
9401
|
+
let conflicted = false;
|
|
9402
|
+
try {
|
|
9403
|
+
await exec2(`git merge --no-ff -m ${shellEscape(`merge ${baseBranch} for promotion`)} ${shellEscape(`origin/${baseBranch}`)}`, o);
|
|
9404
|
+
} catch {
|
|
9405
|
+
conflicted = true;
|
|
9406
|
+
}
|
|
9407
|
+
if (!conflicted) return { reconciled: false };
|
|
9408
|
+
const u = (await exec2("git diff --name-only --diff-filter=U", o).catch(() => "")).split("\n").map((s) => s.trim()).filter(Boolean);
|
|
9409
|
+
const other = u.filter((p) => !PROMOTE_RUNSTATE_CONFLICT.test(p));
|
|
9410
|
+
if (u.length === 0 || other.length > 0) {
|
|
9411
|
+
await exec2("git merge --abort", o).catch(() => {
|
|
9412
|
+
});
|
|
9413
|
+
throw new ScmMergeError(
|
|
9414
|
+
other.length > 0 ? `promotion conflicts on non-ledger file(s): ${other.join(", ")}. Resolve the real divergence manually, then re-run the promote.` : `promotion merge failed with no resolvable conflicts; resolve manually and re-run.`,
|
|
9415
|
+
"promote-conflict"
|
|
9416
|
+
);
|
|
9417
|
+
}
|
|
9418
|
+
for (const p of u) {
|
|
9419
|
+
await exec2(`git checkout --ours -- ${shellEscape(p)}`, o);
|
|
9420
|
+
await exec2(`git add -- ${shellEscape(p)}`, o);
|
|
9421
|
+
}
|
|
9422
|
+
await exec2(`git commit -m ${shellEscape(`merge ${baseBranch} for promotion (pipeline.json ledger kept at run state)`)}`, o);
|
|
9423
|
+
await pushCurrentBranchForPr({ cwd: projectDir });
|
|
9424
|
+
return { reconciled: true, detail: `reconciled ${u.length} ledger path(s) to the run side + pushed` };
|
|
9425
|
+
}
|
|
9306
9426
|
async function defaultRefreshPromoteWorkflows(projectDir) {
|
|
9307
9427
|
const drift = detectWorkflowDrift({ projectDir });
|
|
9308
9428
|
const touched = drift.files.filter((f) => f.status === "drifted").map((f) => f.name);
|
|
@@ -9392,6 +9512,15 @@ async function mergeFeature(args) {
|
|
|
9392
9512
|
);
|
|
9393
9513
|
}
|
|
9394
9514
|
}
|
|
9515
|
+
{
|
|
9516
|
+
const fetchState = args.fetchPrState ?? ((o, h) => getPullRequest(o, h));
|
|
9517
|
+
const prState = await fetchState(ownerRepo, current.branch).catch(() => void 0);
|
|
9518
|
+
if (prState?.mergeableState === "dirty") {
|
|
9519
|
+
const reconcile = args.reconcileRunState ?? ((base) => reconcilePromoteRunState(args.projectDir, base));
|
|
9520
|
+
const r = await reconcile(gitBase);
|
|
9521
|
+
if (r.reconciled) preflightNotes.push(`Reconciled a pipeline.json-ledger promotion conflict to the run side${r.detail ? ` (${r.detail})` : ""}.`);
|
|
9522
|
+
}
|
|
9523
|
+
}
|
|
9395
9524
|
let paired;
|
|
9396
9525
|
try {
|
|
9397
9526
|
paired = await mergePairedPullRequest({
|
|
@@ -9627,8 +9756,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
9627
9756
|
var cached;
|
|
9628
9757
|
function substrateSelfVersion() {
|
|
9629
9758
|
if (cached !== void 0) return cached;
|
|
9630
|
-
if ("0.2.
|
|
9631
|
-
cached = "0.2.
|
|
9759
|
+
if ("0.2.48".length > 0) {
|
|
9760
|
+
cached = "0.2.48";
|
|
9632
9761
|
return cached;
|
|
9633
9762
|
}
|
|
9634
9763
|
cached = "unknown";
|
|
@@ -8393,6 +8393,8 @@ async function getPullRequest(ownerRepo, headBranch) {
|
|
|
8393
8393
|
isDraft: pr.draft || false,
|
|
8394
8394
|
ciStatus,
|
|
8395
8395
|
checks,
|
|
8396
|
+
mergeable: pr.mergeable,
|
|
8397
|
+
mergeableState: pr.mergeable_state,
|
|
8396
8398
|
headBranch: pr.head?.ref || headBranch,
|
|
8397
8399
|
baseBranch: pr.base?.ref || "",
|
|
8398
8400
|
body: pr.body || void 0,
|
|
@@ -8381,6 +8381,8 @@ async function getPullRequest(ownerRepo, headBranch) {
|
|
|
8381
8381
|
isDraft: pr.draft || false,
|
|
8382
8382
|
ciStatus,
|
|
8383
8383
|
checks,
|
|
8384
|
+
mergeable: pr.mergeable,
|
|
8385
|
+
mergeableState: pr.mergeable_state,
|
|
8384
8386
|
headBranch: pr.head?.ref || headBranch,
|
|
8385
8387
|
baseBranch: pr.base?.ref || "",
|
|
8386
8388
|
body: pr.body || void 0,
|
|
@@ -79288,8 +79288,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
79288
79288
|
var cached;
|
|
79289
79289
|
function substrateSelfVersion() {
|
|
79290
79290
|
if (cached !== void 0) return cached;
|
|
79291
|
-
if ("0.2.
|
|
79292
|
-
cached = "0.2.
|
|
79291
|
+
if ("0.2.48".length > 0) {
|
|
79292
|
+
cached = "0.2.48";
|
|
79293
79293
|
return cached;
|
|
79294
79294
|
}
|
|
79295
79295
|
cached = "unknown";
|
|
@@ -389,8 +389,8 @@ var PKG_NAME = "@databricks-solutions/lakebase-scm-utils";
|
|
|
389
389
|
var cached;
|
|
390
390
|
function substrateSelfVersion() {
|
|
391
391
|
if (cached !== void 0) return cached;
|
|
392
|
-
if ("0.2.
|
|
393
|
-
cached = "0.2.
|
|
392
|
+
if ("0.2.48".length > 0) {
|
|
393
|
+
cached = "0.2.48";
|
|
394
394
|
return cached;
|
|
395
395
|
}
|
|
396
396
|
cached = "unknown";
|
|
@@ -8235,6 +8235,8 @@ async function getPullRequest(ownerRepo, headBranch) {
|
|
|
8235
8235
|
isDraft: pr.draft || false,
|
|
8236
8236
|
ciStatus,
|
|
8237
8237
|
checks,
|
|
8238
|
+
mergeable: pr.mergeable,
|
|
8239
|
+
mergeableState: pr.mergeable_state,
|
|
8238
8240
|
headBranch: pr.head?.ref || headBranch,
|
|
8239
8241
|
baseBranch: pr.base?.ref || "",
|
|
8240
8242
|
body: pr.body || void 0,
|
|
@@ -8662,6 +8664,12 @@ async function waitForCi(args) {
|
|
|
8662
8664
|
if (lastPr.ciStatus === "success") {
|
|
8663
8665
|
return { done: true, value: lastPr };
|
|
8664
8666
|
}
|
|
8667
|
+
if (lastPr.mergeableState === "dirty" && lastPr.checks.length === 0) {
|
|
8668
|
+
throw new ScmWaitCiError(
|
|
8669
|
+
`PR ${lastPr.url} is CONFLICTING with ${lastPr.baseBranch} \u2014 GitHub will not dispatch CI (0 runs) until the conflict is resolved. Reconcile the branch and re-push; the synchronize event will trigger CI.`,
|
|
8670
|
+
"pr-conflicting"
|
|
8671
|
+
);
|
|
8672
|
+
}
|
|
8665
8673
|
if (lastPr.ciStatus === "failure") {
|
|
8666
8674
|
const failed = lastPr.checks.filter((c) => /(FAILURE|TIMED_OUT|CANCELLED|ACTION_REQUIRED)/i.test(c.conclusion)).map((c) => `${c.name} (${c.conclusion})`);
|
|
8667
8675
|
throw new ScmWaitCiError(
|
|
@@ -8223,6 +8223,8 @@ async function getPullRequest(ownerRepo, headBranch) {
|
|
|
8223
8223
|
isDraft: pr.draft || false,
|
|
8224
8224
|
ciStatus,
|
|
8225
8225
|
checks,
|
|
8226
|
+
mergeable: pr.mergeable,
|
|
8227
|
+
mergeableState: pr.mergeable_state,
|
|
8226
8228
|
headBranch: pr.head?.ref || headBranch,
|
|
8227
8229
|
baseBranch: pr.base?.ref || "",
|
|
8228
8230
|
body: pr.body || void 0,
|
|
@@ -8650,6 +8652,12 @@ async function waitForCi(args) {
|
|
|
8650
8652
|
if (lastPr.ciStatus === "success") {
|
|
8651
8653
|
return { done: true, value: lastPr };
|
|
8652
8654
|
}
|
|
8655
|
+
if (lastPr.mergeableState === "dirty" && lastPr.checks.length === 0) {
|
|
8656
|
+
throw new ScmWaitCiError(
|
|
8657
|
+
`PR ${lastPr.url} is CONFLICTING with ${lastPr.baseBranch} \u2014 GitHub will not dispatch CI (0 runs) until the conflict is resolved. Reconcile the branch and re-push; the synchronize event will trigger CI.`,
|
|
8658
|
+
"pr-conflicting"
|
|
8659
|
+
);
|
|
8660
|
+
}
|
|
8653
8661
|
if (lastPr.ciStatus === "failure") {
|
|
8654
8662
|
const failed = lastPr.checks.filter((c) => /(FAILURE|TIMED_OUT|CANCELLED|ACTION_REQUIRED)/i.test(c.conclusion)).map((c) => `${c.name} (${c.conclusion})`);
|
|
8655
8663
|
throw new ScmWaitCiError(
|