@tablation/crew 0.19.3 → 0.19.5
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/cli.js +64 -16
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -2706,7 +2706,9 @@ function pushTag(cwd, remote, tag) {
|
|
|
2706
2706
|
git(cwd, ["push", remote, tag]);
|
|
2707
2707
|
}
|
|
2708
2708
|
function fetchRemote(cwd, remote = "origin") {
|
|
2709
|
-
|
|
2709
|
+
if (gitOk(cwd, ["fetch", "--prune", "--quiet", remote]) === null) return false;
|
|
2710
|
+
gitOk(cwd, ["fetch", "--quiet", remote, "refs/tags/*:refs/tags/*"]);
|
|
2711
|
+
return true;
|
|
2710
2712
|
}
|
|
2711
2713
|
function remoteConfigured(cwd, remote = "origin") {
|
|
2712
2714
|
return gitOk(cwd, ["remote", "get-url", remote]) !== null;
|
|
@@ -6432,6 +6434,15 @@ function describeUnplaceable(unplaceable, verifiedStatus) {
|
|
|
6432
6434
|
}
|
|
6433
6435
|
return notes;
|
|
6434
6436
|
}
|
|
6437
|
+
var unplaceableReported = /* @__PURE__ */ new Set();
|
|
6438
|
+
function reportUnplaceable(routeName, unplaceable, verified, emit) {
|
|
6439
|
+
if (unplaceableReported.has(routeName)) return;
|
|
6440
|
+
unplaceableReported.add(routeName);
|
|
6441
|
+
for (const note of describeUnplaceable(unplaceable, verified)) {
|
|
6442
|
+
if (note.level === "warn") emit.warn(note.message, { step: "release" });
|
|
6443
|
+
else emit.emit(note.message, { step: "release" });
|
|
6444
|
+
}
|
|
6445
|
+
}
|
|
6435
6446
|
function checkGuards(cwd, base = "main") {
|
|
6436
6447
|
const branch = currentBranch(cwd);
|
|
6437
6448
|
if (branch !== base) {
|
|
@@ -6561,6 +6572,7 @@ ${section}`;
|
|
|
6561
6572
|
}
|
|
6562
6573
|
return [...lines.slice(0, anchor), section, ...lines.slice(anchor)].join("\n");
|
|
6563
6574
|
}
|
|
6575
|
+
var RELEASE_COMMIT_SUBJECT = /^Release \S+$/;
|
|
6564
6576
|
function decideRelease(cwd, tickets, contract, opts = {}) {
|
|
6565
6577
|
const pattern = opts.tagPattern ?? "v*";
|
|
6566
6578
|
const base = opts.base ?? "main";
|
|
@@ -6570,6 +6582,7 @@ function decideRelease(cwd, tickets, contract, opts = {}) {
|
|
|
6570
6582
|
const head = resolve2(cwd, "HEAD") ?? "";
|
|
6571
6583
|
const merges = block ? [] : planMerge(cwd, tickets, contract, lastReleased, opts.branchFor ?? ((t) => branchForIssue(cwd, t.issue_id)), base);
|
|
6572
6584
|
const unreleasedCommits = lastReleased ? countCommits(cwd, `${lastReleased}..HEAD`) : 0;
|
|
6585
|
+
const unreleasedWork = lastReleased ? (gitOk(cwd, ["log", "--format=%s", `${lastReleased}..HEAD`]) ?? "").split("\n").filter((l) => l && !RELEASE_COMMIT_SUBJECT.test(l)).length : 0;
|
|
6573
6586
|
return {
|
|
6574
6587
|
block,
|
|
6575
6588
|
merges,
|
|
@@ -6577,10 +6590,14 @@ function decideRelease(cwd, tickets, contract, opts = {}) {
|
|
|
6577
6590
|
lastTag,
|
|
6578
6591
|
lastReleased,
|
|
6579
6592
|
unreleasedCommits,
|
|
6580
|
-
upToDate: lastReleased === head,
|
|
6593
|
+
upToDate: lastReleased === head || lastReleased !== null && unreleasedWork === 0,
|
|
6581
6594
|
unseeded: lastTag === null
|
|
6582
6595
|
};
|
|
6583
6596
|
}
|
|
6597
|
+
function releaseIdle(i) {
|
|
6598
|
+
if (i.force || i.external || i.unseeded || !i.upToDate || i.unstamped > 0) return false;
|
|
6599
|
+
return !i.tickets.some((t) => t.status === i.verifiedStatus);
|
|
6600
|
+
}
|
|
6584
6601
|
var renderTag = (template, version) => template.replace(/\{version\}/g, version);
|
|
6585
6602
|
|
|
6586
6603
|
// src/stamp.ts
|
|
@@ -7489,7 +7506,8 @@ async function mergeAndRelease(o, decision, fresh, releaseBranch) {
|
|
|
7489
7506
|
o.emit.emit(`tagged ${tag}`);
|
|
7490
7507
|
}
|
|
7491
7508
|
}
|
|
7492
|
-
|
|
7509
|
+
const tagIsCiTrigger = o.repo.release.mode === "ci_manual" || o.repo.release.mode === "ci_auto";
|
|
7510
|
+
if (tag && (tagIsCiTrigger || remoteConfigured(o.cwd, o.repo.branch.remote))) {
|
|
7493
7511
|
if (o.dryRun) {
|
|
7494
7512
|
o.emit.emit(`would push tag ${tag} to ${o.repo.branch.remote}`);
|
|
7495
7513
|
} else {
|
|
@@ -7497,8 +7515,12 @@ async function mergeAndRelease(o, decision, fresh, releaseBranch) {
|
|
|
7497
7515
|
pushTag(o.cwd, o.repo.branch.remote, tag);
|
|
7498
7516
|
o.emit.emit(`pushed tag ${tag} to ${o.repo.branch.remote}`);
|
|
7499
7517
|
} catch (e) {
|
|
7500
|
-
|
|
7501
|
-
|
|
7518
|
+
const msg = `failed to push tag ${tag} to ${o.repo.branch.remote} \u2014 ${e.message}`;
|
|
7519
|
+
if (tagIsCiTrigger) {
|
|
7520
|
+
o.emit.error(msg);
|
|
7521
|
+
return { merged, conflicts, unbuildable, version, tag, deployed, integrated, decision, stopped: "tag push failed" };
|
|
7522
|
+
}
|
|
7523
|
+
o.emit.warn(`${msg}; other ships will not see this release marker`);
|
|
7502
7524
|
}
|
|
7503
7525
|
}
|
|
7504
7526
|
}
|
|
@@ -10517,15 +10539,8 @@ if (command === "passenger-sync-daemon") {
|
|
|
10517
10539
|
const out = refreshBaseBranch(r.dir, remote, base, true);
|
|
10518
10540
|
const unsafe = baseBranchUnsafe(out);
|
|
10519
10541
|
return { action: out.action, unsafe, detail: unsafe ? describeUnsafeBase(out, remote, base) : out.detail };
|
|
10520
|
-
}, reportUnplaceable = function(c, unplaceable, verified, emit2) {
|
|
10521
|
-
if (unplaceableReported.has(c.route)) return;
|
|
10522
|
-
unplaceableReported.add(c.route);
|
|
10523
|
-
for (const note of describeUnplaceable(unplaceable, verified)) {
|
|
10524
|
-
if (note.level === "warn") emit2.warn(note.message, { step: "release" });
|
|
10525
|
-
else emit2.emit(note.message, { step: "release" });
|
|
10526
|
-
}
|
|
10527
10542
|
};
|
|
10528
|
-
requireArmed2 = requireArmed, parseTicketNumber2 = parseTicketNumber, passengerApiKeys2 = passengerApiKeys, endpointApiFor2 = endpointApiFor, endpointReconcileDeps2 = endpointReconcileDeps, releaseRefused2 = releaseRefused, baseHealth2 = baseHealth
|
|
10543
|
+
requireArmed2 = requireArmed, parseTicketNumber2 = parseTicketNumber, passengerApiKeys2 = passengerApiKeys, endpointApiFor2 = endpointApiFor, endpointReconcileDeps2 = endpointReconcileDeps, releaseRefused2 = releaseRefused, baseHealth2 = baseHealth;
|
|
10529
10544
|
let cfg;
|
|
10530
10545
|
let firstRun;
|
|
10531
10546
|
try {
|
|
@@ -10659,6 +10674,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
10659
10674
|
}
|
|
10660
10675
|
async function releaseFleet(opts = {}) {
|
|
10661
10676
|
if (releaseRefused()) return;
|
|
10677
|
+
precheckTickets.clear();
|
|
10662
10678
|
const summaries = [];
|
|
10663
10679
|
if (!dryRun) state.releaseHeartbeat().touch();
|
|
10664
10680
|
for (const c of cfg.routes) {
|
|
@@ -10670,6 +10686,7 @@ if (command === "passenger-sync-daemon") {
|
|
|
10670
10686
|
}
|
|
10671
10687
|
async function releaseTargets(opts = {}) {
|
|
10672
10688
|
if (releaseRefused()) return;
|
|
10689
|
+
precheckTickets.clear();
|
|
10673
10690
|
const only = value("repo");
|
|
10674
10691
|
const targets = reposOf(route);
|
|
10675
10692
|
const chosen = only ? targets.filter((t) => t.name === only) : targets;
|
|
@@ -10906,7 +10923,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10906
10923
|
}
|
|
10907
10924
|
return `${who2}; ${lock2}`;
|
|
10908
10925
|
}
|
|
10909
|
-
const
|
|
10926
|
+
const precheckTickets = /* @__PURE__ */ new Map();
|
|
10910
10927
|
async function releasePhase(c, target, opts = {}) {
|
|
10911
10928
|
const scope = releaseLockScope(c.route, target.name);
|
|
10912
10929
|
const remit = emit.forRoute(c.route);
|
|
@@ -10941,6 +10958,38 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10941
10958
|
}
|
|
10942
10959
|
if (!dryRun && !c.enabled) return { scope, tests: "skipped", outcome: "skipped", detail: "route not enabled" };
|
|
10943
10960
|
const tracker = new Tracker(c, cfg.ship);
|
|
10961
|
+
if (!dryRun) {
|
|
10962
|
+
const force2 = command === "deploy" || flag("force");
|
|
10963
|
+
let seen = precheckTickets.get(c.route);
|
|
10964
|
+
if (!seen) precheckTickets.set(c.route, seen = tracker.openTickets());
|
|
10965
|
+
const { byRepo: preByRepo, unplaceable: preUnplaceable } = ticketsByRepo(c, await seen);
|
|
10966
|
+
const pre = preByRepo.get(target.name) ?? [];
|
|
10967
|
+
reportUnplaceable(c.route, preUnplaceable, tracker.contract.statuses.verified, remit);
|
|
10968
|
+
const d = decideRelease(target.dir, pre, tracker.contract, {
|
|
10969
|
+
tagPattern: repo.release.tagPattern ?? "v*",
|
|
10970
|
+
base: repo.branch.base
|
|
10971
|
+
});
|
|
10972
|
+
const unstamped = planReleasedBranches(
|
|
10973
|
+
target.dir,
|
|
10974
|
+
pre,
|
|
10975
|
+
tracker.contract,
|
|
10976
|
+
(t) => locateBranchForTicket(target.dir, repo, t)?.branch ?? null,
|
|
10977
|
+
repo.branch.base,
|
|
10978
|
+
repo.release.tagPattern ?? "v*"
|
|
10979
|
+
).length;
|
|
10980
|
+
if (releaseIdle({
|
|
10981
|
+
tickets: pre,
|
|
10982
|
+
verifiedStatus: tracker.contract.statuses.verified,
|
|
10983
|
+
force: force2,
|
|
10984
|
+
external: repo.release.mode === "external",
|
|
10985
|
+
upToDate: d.upToDate,
|
|
10986
|
+
unseeded: d.unseeded,
|
|
10987
|
+
unstamped
|
|
10988
|
+
})) {
|
|
10989
|
+
remit.emit(`${target.name}: nothing verified \u2014 not locking`, { step: "release" });
|
|
10990
|
+
return { scope, tests: "skipped", outcome: "skipped", detail: "nothing verified \u2014 not locking" };
|
|
10991
|
+
}
|
|
10992
|
+
}
|
|
10944
10993
|
if (!dryRun) {
|
|
10945
10994
|
const holderLabel = `${cfg.ship.name}:${process.pid}`;
|
|
10946
10995
|
const got = await tracker.acquireBoardLock(scope, holderLabel, RELEASE_LOCK_TTL_MS);
|
|
@@ -10963,7 +11012,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
10963
11012
|
const all = await tracker.openTickets();
|
|
10964
11013
|
const { byRepo, unplaceable } = ticketsByRepo(c, all);
|
|
10965
11014
|
const tickets = byRepo.get(target.name) ?? [];
|
|
10966
|
-
reportUnplaceable(c, unplaceable, tracker.contract.statuses.verified, remit);
|
|
11015
|
+
reportUnplaceable(c.route, unplaceable, tracker.contract.statuses.verified, remit);
|
|
10967
11016
|
const outcome = await runRelease({
|
|
10968
11017
|
cwd: target.dir,
|
|
10969
11018
|
repo,
|
|
@@ -13249,4 +13298,3 @@ var endpointApiFor2;
|
|
|
13249
13298
|
var endpointReconcileDeps2;
|
|
13250
13299
|
var releaseRefused2;
|
|
13251
13300
|
var baseHealth2;
|
|
13252
|
-
var reportUnplaceable2;
|
package/package.json
CHANGED