tines 0.0.151 → 0.0.153
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/index.js +56 -26
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3774,6 +3774,24 @@ function requirementFix(r, ref) {
|
|
|
3774
3774
|
command: `tines issues artifacts delete ${ref} ${r.artifact} && ${attach(r.type ?? "file")}`
|
|
3775
3775
|
};
|
|
3776
3776
|
}
|
|
3777
|
+
function concreteContentType(ct) {
|
|
3778
|
+
return ct !== void 0 && ct.includes("/") && !ct.endsWith("/") ? ct : void 0;
|
|
3779
|
+
}
|
|
3780
|
+
function requirementAccepts(r, type, contentType) {
|
|
3781
|
+
if (r.type !== void 0 && r.type !== type) return false;
|
|
3782
|
+
if (r.content_type === void 0) return true;
|
|
3783
|
+
if (contentType === void 0) return true;
|
|
3784
|
+
return contentType.startsWith(r.content_type);
|
|
3785
|
+
}
|
|
3786
|
+
function declaredContentType(reqs, type) {
|
|
3787
|
+
if (type !== "text" && type !== "file") return void 0;
|
|
3788
|
+
const declared = [
|
|
3789
|
+
...new Set(
|
|
3790
|
+
reqs.filter((r) => r.type === type).map((r) => concreteContentType(r.content_type)).filter((ct) => ct !== void 0)
|
|
3791
|
+
)
|
|
3792
|
+
];
|
|
3793
|
+
return declared.length === 1 ? declared[0] : void 0;
|
|
3794
|
+
}
|
|
3777
3795
|
|
|
3778
3796
|
// ../shared/src/artifact-site.ts
|
|
3779
3797
|
var ARTIFACT_SITE_LINK_TTL_MS = 60 * 60 * 1e3;
|
|
@@ -4180,6 +4198,9 @@ async function listAll(fetchPage, opts = {}) {
|
|
|
4180
4198
|
return items;
|
|
4181
4199
|
}
|
|
4182
4200
|
|
|
4201
|
+
// ../shared/src/routing.ts
|
|
4202
|
+
var INHERIT_RUNNER_ID = "*";
|
|
4203
|
+
|
|
4183
4204
|
// src/format.ts
|
|
4184
4205
|
function timestamp(ms) {
|
|
4185
4206
|
return new Date(ms).toISOString().replace("T", " ").slice(0, 19);
|
|
@@ -4290,6 +4311,9 @@ function runnerStatusLabel(runner) {
|
|
|
4290
4311
|
}
|
|
4291
4312
|
function ruleTargetsLabel(rule) {
|
|
4292
4313
|
if (rule.targets.length === 0) return "(no targets)";
|
|
4314
|
+
if (rule.targets.length === 1 && rule.targets[0]?.runner_id === "*") {
|
|
4315
|
+
return `*:${rule.targets[0].tier} (inherited runners)`;
|
|
4316
|
+
}
|
|
4293
4317
|
return rule.targets.map(
|
|
4294
4318
|
(t) => `${t.runner_name}${t.tier ? `:${t.tier}` : ""}${t.runner_status === "paused" ? " (paused)" : ""}`
|
|
4295
4319
|
).join(" \u2192 ");
|
|
@@ -5015,9 +5039,6 @@ function normalizePositional(raw) {
|
|
|
5015
5039
|
return { value: raw, stdin: false };
|
|
5016
5040
|
}
|
|
5017
5041
|
var isUrl = (v) => /^https?:\/\//.test(v);
|
|
5018
|
-
function concreteContentType(ct) {
|
|
5019
|
-
return ct !== void 0 && ct.includes("/") && !ct.endsWith("/") ? ct : void 0;
|
|
5020
|
-
}
|
|
5021
5042
|
function declaredTypes(gates) {
|
|
5022
5043
|
return [
|
|
5023
5044
|
...new Set(gates.map((g) => g.check.type).filter((t) => t !== void 0))
|
|
@@ -5045,13 +5066,6 @@ function joinTransitions(names) {
|
|
|
5045
5066
|
function fixCommand(gate, ref) {
|
|
5046
5067
|
return gate.check.fix || requirementFix(gate.check, ref).command;
|
|
5047
5068
|
}
|
|
5048
|
-
function accepts(gate, type, contentType) {
|
|
5049
|
-
const check = gate.check;
|
|
5050
|
-
if (check.type !== void 0 && check.type !== type) return false;
|
|
5051
|
-
if (check.content_type === void 0) return true;
|
|
5052
|
-
if (contentType === void 0) return true;
|
|
5053
|
-
return contentType.startsWith(check.content_type);
|
|
5054
|
-
}
|
|
5055
5069
|
function effectiveContentType(type, source, explicit, sniff) {
|
|
5056
5070
|
if (explicit !== void 0) return explicit;
|
|
5057
5071
|
if (type === "text") return "text/markdown";
|
|
@@ -5169,13 +5183,10 @@ function planPositional(name2, raw, gates, probe, flags) {
|
|
|
5169
5183
|
}
|
|
5170
5184
|
}
|
|
5171
5185
|
function gateContentType(gates, type) {
|
|
5172
|
-
|
|
5173
|
-
|
|
5174
|
-
|
|
5175
|
-
|
|
5176
|
-
)
|
|
5177
|
-
];
|
|
5178
|
-
return declared.length === 1 ? declared[0] : void 0;
|
|
5186
|
+
return declaredContentType(
|
|
5187
|
+
gates.map((g) => g.check),
|
|
5188
|
+
type
|
|
5189
|
+
);
|
|
5179
5190
|
}
|
|
5180
5191
|
function planFlags(flags, probe) {
|
|
5181
5192
|
const ct = flags.contentType;
|
|
@@ -5228,7 +5239,7 @@ function checkExistingSlot(plan, gates, ref, name2, flags, positional) {
|
|
|
5228
5239
|
}
|
|
5229
5240
|
function checkAccepted(plan, gates, ref, name2, flags, positional, sniff) {
|
|
5230
5241
|
const effective = effectiveContentType(plan.type, plan.source, plan.contentType, sniff);
|
|
5231
|
-
if (gates.some((g2) =>
|
|
5242
|
+
if (gates.some((g2) => requirementAccepts(g2.check, plan.type, effective))) return;
|
|
5232
5243
|
const label = sourceLabel(flags, positional);
|
|
5233
5244
|
const typeMatched = gates.filter((g2) => (g2.check.type ?? plan.type) === plan.type);
|
|
5234
5245
|
if (typeMatched.length > 0) {
|
|
@@ -5247,7 +5258,11 @@ function satisfiedBy(artifact, gates) {
|
|
|
5247
5258
|
const rejects = [];
|
|
5248
5259
|
for (const gate of gates) {
|
|
5249
5260
|
if (gate.check.artifact !== artifact.name) continue;
|
|
5250
|
-
if (
|
|
5261
|
+
if (requirementAccepts(
|
|
5262
|
+
gate.check,
|
|
5263
|
+
artifact.artifact_type,
|
|
5264
|
+
artifact.current_version.content_type ?? void 0
|
|
5265
|
+
)) {
|
|
5251
5266
|
satisfies.push(gate.transition);
|
|
5252
5267
|
} else {
|
|
5253
5268
|
rejects.push({ transition: gate.transition, wants: wantsLabel(gate, artifact) });
|
|
@@ -5488,6 +5503,8 @@ pinned to ${ex.pin.runner_name ?? ex.pin.runner_id}${ex.pin.tier ? `:${ex.pin.ti
|
|
|
5488
5503
|
} else if (ex.matched_rule) {
|
|
5489
5504
|
console.log(`
|
|
5490
5505
|
matched rule: ${ex.matched_rule.scope_label}`);
|
|
5506
|
+
if (ex.tier_override) console.log(`tier override: ${ex.tier_override}`);
|
|
5507
|
+
if (ex.runner_rule) console.log(`runner source: ${ex.runner_rule.scope_label}`);
|
|
5491
5508
|
}
|
|
5492
5509
|
if (ex.targets.length > 0) {
|
|
5493
5510
|
console.log("targets (preference order):");
|
|
@@ -6711,16 +6728,29 @@ function register7(program3) {
|
|
|
6711
6728
|
);
|
|
6712
6729
|
withCommon(
|
|
6713
6730
|
routing.command("set <target...>").description(
|
|
6714
|
-
"Create or replace
|
|
6731
|
+
"Create or replace a rule with <runner>[:tier] targets, or scoped '*:smartest' tier inheritance"
|
|
6715
6732
|
).option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-l, --label <name>", "scope: issue label name or id")
|
|
6716
6733
|
).action(async (targetSpecs, opts) => {
|
|
6734
|
+
const parsed = targetSpecs.map(parseTargetSpec);
|
|
6735
|
+
const wildcard = parsed.filter((target) => target.name === INHERIT_RUNNER_ID);
|
|
6736
|
+
if (wildcard.length > 0) {
|
|
6737
|
+
if (parsed.length !== 1) die("'*:tier' cannot be mixed with runner targets");
|
|
6738
|
+
if (!wildcard[0].tier)
|
|
6739
|
+
die("the '*' target requires an explicit tier, for example '*:smartest'");
|
|
6740
|
+
if (opts.project === void 0 && opts.state === void 0 && opts.label === void 0) {
|
|
6741
|
+
die("a tier-only rule requires --project, --state, or --label");
|
|
6742
|
+
}
|
|
6743
|
+
}
|
|
6717
6744
|
const api = client(opts);
|
|
6718
6745
|
const scope = await resolveRoutingScope(api, opts);
|
|
6719
6746
|
const targets = [];
|
|
6720
|
-
for (const
|
|
6721
|
-
|
|
6722
|
-
|
|
6723
|
-
|
|
6747
|
+
for (const { name: name2, tier } of parsed) {
|
|
6748
|
+
if (name2 === INHERIT_RUNNER_ID) {
|
|
6749
|
+
targets.push({ runner_id: INHERIT_RUNNER_ID, tier });
|
|
6750
|
+
} else {
|
|
6751
|
+
const runner = await resolveRunner(api, name2);
|
|
6752
|
+
targets.push(tier ? { runner_id: runner.id, tier } : { runner_id: runner.id });
|
|
6753
|
+
}
|
|
6724
6754
|
}
|
|
6725
6755
|
const { items } = await api.listRoutingRules();
|
|
6726
6756
|
const existing = items.find(
|
|
@@ -6739,7 +6769,7 @@ function register7(program3) {
|
|
|
6739
6769
|
for (const warning of rule.warnings) console.log(`warning: ${warning.message}`);
|
|
6740
6770
|
});
|
|
6741
6771
|
withCommon(
|
|
6742
|
-
routing.command("clear").description("Delete the rule at a scope (issues
|
|
6772
|
+
routing.command("clear").description("Delete the rule at a scope (matching issues are re-evaluated)").option("-p, --project <name>", "scope: project name or id").option("-s, --state <workflow/state>", "scope: workflow-qualified state").option("-l, --label <name>", "scope: issue label name or id")
|
|
6743
6773
|
).action(async (opts) => {
|
|
6744
6774
|
const api = client(opts);
|
|
6745
6775
|
const scope = await resolveRoutingScope(api, opts);
|
|
@@ -8736,7 +8766,7 @@ function queueHeadline(block) {
|
|
|
8736
8766
|
case "no_rule":
|
|
8737
8767
|
return "no matching routing rule";
|
|
8738
8768
|
case "no_targets":
|
|
8739
|
-
return "the matching rule has no targets";
|
|
8769
|
+
return "the matching rule has no effective targets";
|
|
8740
8770
|
case "ambiguous_rule":
|
|
8741
8771
|
return "two routing rules tie";
|
|
8742
8772
|
case "pin_missing":
|