redlinegate 0.0.1
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/LICENSE +21 -0
- package/README.md +188 -0
- package/commands/redline-init.md +54 -0
- package/commands/redline-verify.md +69 -0
- package/dist/bin/redline.js +605 -0
- package/dist/bin/redline.js.map +1 -0
- package/dist/commands/exempt.js +45 -0
- package/dist/commands/exempt.js.map +1 -0
- package/dist/commands/init.js +615 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/policy.js +25 -0
- package/dist/commands/policy.js.map +1 -0
- package/dist/commands/remove.js +427 -0
- package/dist/commands/remove.js.map +1 -0
- package/dist/commands/review.js +72 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/sync.js +42 -0
- package/dist/commands/sync.js.map +1 -0
- package/dist/commands/verify.js +478 -0
- package/dist/commands/verify.js.map +1 -0
- package/dist/config/redline-json.js +187 -0
- package/dist/config/redline-json.js.map +1 -0
- package/dist/core/errors.js +25 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/git.js +152 -0
- package/dist/core/git.js.map +1 -0
- package/dist/core/log.js +22 -0
- package/dist/core/log.js.map +1 -0
- package/dist/core/severity.js +16 -0
- package/dist/core/severity.js.map +1 -0
- package/dist/core/version.js +15 -0
- package/dist/core/version.js.map +1 -0
- package/dist/detect/scan.js +79 -0
- package/dist/detect/scan.js.map +1 -0
- package/dist/detect/stack.js +71 -0
- package/dist/detect/stack.js.map +1 -0
- package/dist/enforce/ladder.js +148 -0
- package/dist/enforce/ladder.js.map +1 -0
- package/dist/exempt/parse.js +86 -0
- package/dist/exempt/parse.js.map +1 -0
- package/dist/metrics/options.js +257 -0
- package/dist/metrics/options.js.map +1 -0
- package/dist/metrics/run.js +72 -0
- package/dist/metrics/run.js.map +1 -0
- package/dist/platforms/azure/client.js +53 -0
- package/dist/platforms/azure/client.js.map +1 -0
- package/dist/platforms/azure/index.js +69 -0
- package/dist/platforms/azure/index.js.map +1 -0
- package/dist/platforms/azure/install.js +917 -0
- package/dist/platforms/azure/install.js.map +1 -0
- package/dist/platforms/azure/policy-types.js +70 -0
- package/dist/platforms/azure/policy-types.js.map +1 -0
- package/dist/platforms/azure/verify.js +309 -0
- package/dist/platforms/azure/verify.js.map +1 -0
- package/dist/platforms/detect.js +40 -0
- package/dist/platforms/detect.js.map +1 -0
- package/dist/platforms/github/client.js +49 -0
- package/dist/platforms/github/client.js.map +1 -0
- package/dist/platforms/github/index.js +54 -0
- package/dist/platforms/github/index.js.map +1 -0
- package/dist/platforms/github/install.js +558 -0
- package/dist/platforms/github/install.js.map +1 -0
- package/dist/platforms/github/push.js +102 -0
- package/dist/platforms/github/push.js.map +1 -0
- package/dist/platforms/github/remote.js +36 -0
- package/dist/platforms/github/remote.js.map +1 -0
- package/dist/platforms/github/verify.js +366 -0
- package/dist/platforms/github/verify.js.map +1 -0
- package/dist/platforms/http.js +58 -0
- package/dist/platforms/http.js.map +1 -0
- package/dist/platforms/pull-request-templates.js +157 -0
- package/dist/platforms/pull-request-templates.js.map +1 -0
- package/dist/platforms/remote.js +21 -0
- package/dist/platforms/remote.js.map +1 -0
- package/dist/platforms/resolve.js +69 -0
- package/dist/platforms/resolve.js.map +1 -0
- package/dist/platforms/shape.js +19 -0
- package/dist/platforms/shape.js.map +1 -0
- package/dist/platforms/types.js +24 -0
- package/dist/platforms/types.js.map +1 -0
- package/dist/policy/checks.js +91 -0
- package/dist/policy/checks.js.map +1 -0
- package/dist/policy/diff.js +50 -0
- package/dist/policy/diff.js.map +1 -0
- package/dist/registry/discover.js +74 -0
- package/dist/registry/discover.js.map +1 -0
- package/dist/registry/serialize.js +41 -0
- package/dist/registry/serialize.js.map +1 -0
- package/dist/registry/types.js +2 -0
- package/dist/registry/types.js.map +1 -0
- package/dist/remove/host.js +294 -0
- package/dist/remove/host.js.map +1 -0
- package/dist/render/commands.js +139 -0
- package/dist/render/commands.js.map +1 -0
- package/dist/render/manifest.js +82 -0
- package/dist/render/manifest.js.map +1 -0
- package/dist/render/markers.js +166 -0
- package/dist/render/markers.js.map +1 -0
- package/dist/render/profile.js +23 -0
- package/dist/render/profile.js.map +1 -0
- package/dist/render/standards.js +169 -0
- package/dist/render/standards.js.map +1 -0
- package/dist/render/vendors.js +199 -0
- package/dist/render/vendors.js.map +1 -0
- package/dist/review/engines/api.js +95 -0
- package/dist/review/engines/api.js.map +1 -0
- package/dist/review/engines/embedded.js +20 -0
- package/dist/review/engines/embedded.js.map +1 -0
- package/dist/review/engines/types.js +2 -0
- package/dist/review/engines/types.js.map +1 -0
- package/dist/review/glob.js +29 -0
- package/dist/review/glob.js.map +1 -0
- package/dist/review/prompt.js +45 -0
- package/dist/review/prompt.js.map +1 -0
- package/dist/review/rules.js +25 -0
- package/dist/review/rules.js.map +1 -0
- package/dist/review/schema.js +84 -0
- package/dist/review/schema.js.map +1 -0
- package/dist/review/scope.js +27 -0
- package/dist/review/scope.js.map +1 -0
- package/dist/sarif/map.js +58 -0
- package/dist/sarif/map.js.map +1 -0
- package/dist/sarif/parse.js +88 -0
- package/dist/sarif/parse.js.map +1 -0
- package/dist/sarif/types.js +2 -0
- package/dist/sarif/types.js.map +1 -0
- package/dist/sync/host.js +21 -0
- package/dist/sync/host.js.map +1 -0
- package/dist/sync/plan.js +47 -0
- package/dist/sync/plan.js.map +1 -0
- package/dist/sync/render.js +57 -0
- package/dist/sync/render.js.map +1 -0
- package/dist/sync/run.js +118 -0
- package/dist/sync/run.js.map +1 -0
- package/dist/verify/host.js +52 -0
- package/dist/verify/host.js.map +1 -0
- package/dist/verify/remote.js +146 -0
- package/dist/verify/remote.js.map +1 -0
- package/package.json +52 -0
- package/platforms/azure/gate-template.yml +105 -0
- package/rulesets/redline-org-ruleset.json +46 -0
- package/rulesets/redline-ruleset.json +49 -0
- package/scripts/assign-rule-ids.mjs +129 -0
- package/scripts/build-baseline.mjs +124 -0
- package/scripts/build-correlation.mjs +74 -0
- package/scripts/build-dashboard.mjs +584 -0
- package/scripts/build-digest.mjs +164 -0
- package/scripts/build-inbox.mjs +133 -0
- package/scripts/build-registry.mjs +42 -0
- package/scripts/build-roi.mjs +181 -0
- package/scripts/check-pins.mjs +88 -0
- package/scripts/collect-telemetry.mjs +300 -0
- package/scripts/lib/__tests__/baseline.test.mjs +132 -0
- package/scripts/lib/__tests__/correlate.test.mjs +131 -0
- package/scripts/lib/__tests__/dora.test.mjs +110 -0
- package/scripts/lib/__tests__/exemptions.test.mjs +85 -0
- package/scripts/lib/__tests__/metrics-scanner.test.mjs +65 -0
- package/scripts/lib/__tests__/sarif.test.mjs +125 -0
- package/scripts/lib/__tests__/spend.test.mjs +64 -0
- package/scripts/lib/baseline.mjs +156 -0
- package/scripts/lib/correlate.mjs +125 -0
- package/scripts/lib/dora.mjs +133 -0
- package/scripts/lib/exemptions.mjs +79 -0
- package/scripts/lib/metrics.mjs +172 -0
- package/scripts/lib/rules.mjs +107 -0
- package/scripts/lib/sarif.mjs +108 -0
- package/scripts/lib/spend.mjs +69 -0
- package/scripts/measure-context.mjs +101 -0
- package/scripts/render-self.mjs +18 -0
- package/scripts/score-seeds.mjs +294 -0
- package/scripts/validate.mjs +394 -0
- package/standards/core.md +124 -0
- package/standards/manifest.json +214 -0
- package/standards/stacks/csharp.md +29 -0
- package/standards/stacks/go.md +30 -0
- package/standards/stacks/java.md +30 -0
- package/standards/stacks/javascript.md +42 -0
- package/standards/stacks/kotlin.md +27 -0
- package/standards/stacks/microservices.md +37 -0
- package/standards/stacks/nodejs.md +34 -0
- package/standards/stacks/python.md +29 -0
- package/standards/stacks/react-native.md +29 -0
- package/standards/stacks/react.md +46 -0
- package/standards/stacks/swift.md +26 -0
- package/standards/stacks/terraform.md +27 -0
- package/templates/CODEOWNERS +29 -0
- package/templates/azure/pull_request_template.md +72 -0
- package/templates/github/pull_request_template.md +72 -0
- package/templates/redline.yml +35 -0
- package/templates/repo-context.md +64 -0
- package/workflows/dashboard.yml +119 -0
- package/workflows/inbox.yml +97 -0
- package/workflows/redline-collect.yml +61 -0
- package/workflows/redline-gate.yml +301 -0
- package/workflows/redline-sync.yml +79 -0
- package/workflows/seed-canary.yml +231 -0
- package/workflows/verify-onboarding.yml +115 -0
- package/workflows/weekly-digest.yml +78 -0
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
import { createGit } from "../core/git.js";
|
|
2
|
+
import { RedlineError } from "../core/errors.js";
|
|
3
|
+
import { parseRemote } from "../platforms/detect.js";
|
|
4
|
+
import { createAzureClient } from "../platforms/azure/client.js";
|
|
5
|
+
import { createGitHubClient } from "../platforms/github/client.js";
|
|
6
|
+
import { RULESET_NAME } from "../platforms/github/install.js";
|
|
7
|
+
import { AZURE_STATUS_GENRE, AZURE_STATUS_NAME, POLICY_TYPE_NAMES, REDLINE_POLICY_MARKER, resolvePolicyTypeIds, } from "../platforms/azure/policy-types.js";
|
|
8
|
+
import { isNonNullObject, isSuccess } from "../platforms/shape.js";
|
|
9
|
+
// CONTRACT with GATE_LABELS in cli/platforms/github/install.ts: these are the
|
|
10
|
+
// three labels the gate install creates, with the descriptions it gives them.
|
|
11
|
+
// The description is what makes deletion safe. `no-adr` carries no Redline
|
|
12
|
+
// prefix at all and is exactly the name a team may already have used, and
|
|
13
|
+
// GitHub answers the install's POST with 422 either way — so the install
|
|
14
|
+
// cannot record whether it created one or found one. The description can still
|
|
15
|
+
// answer it: a label still carrying the text Redline wrote is Redline's, and
|
|
16
|
+
// one carrying anything else is the repository's own and is left in place.
|
|
17
|
+
const REDLINE_LABELS = [
|
|
18
|
+
{ name: 'no-adr', description: 'PR intentionally ships without an ADR' },
|
|
19
|
+
{ name: 'redline-exempt', description: 'Gate process checks soft-failed with reviewer sign-off' },
|
|
20
|
+
{ name: 'redline-sync', description: 'Automated standards sync from the Redline source repo' },
|
|
21
|
+
];
|
|
22
|
+
// CONTRACT with cli/platforms/github/install.ts's applyPolicy: the property it
|
|
23
|
+
// sets. GitHub removes a property value when it is PATCHed as null.
|
|
24
|
+
const REPO_PROPERTY = 'redline';
|
|
25
|
+
// CONTRACT with GATE_DEFINITION_NAME/FOLDER and GATE_YAML_FILENAME in
|
|
26
|
+
// cli/platforms/azure/install.ts. All three together are what
|
|
27
|
+
// `ensureGateBuildDefinition` uses to recognise its own definition, and the
|
|
28
|
+
// same tuple is what this file reports on.
|
|
29
|
+
const AZURE_GATE_DEFINITION = '\\Redline\\redline-gate';
|
|
30
|
+
const OUTCOME_RANK = {
|
|
31
|
+
denied: 4,
|
|
32
|
+
unknown: 3,
|
|
33
|
+
unsupported: 2,
|
|
34
|
+
already: 1,
|
|
35
|
+
applied: 0,
|
|
36
|
+
};
|
|
37
|
+
// Several host calls fold into one capability the operator reads — three label
|
|
38
|
+
// deletions, several Azure policy deletions. Ranked by how actionable the
|
|
39
|
+
// status is rather than by HTTP status number, so a definite refusal on one
|
|
40
|
+
// call is never masked by a larger number on another. Same table and same
|
|
41
|
+
// reasoning as both install adapters.
|
|
42
|
+
function worstOutcome(outcomes) {
|
|
43
|
+
const [first, ...rest] = outcomes;
|
|
44
|
+
if (!first)
|
|
45
|
+
throw new Error('worstOutcome requires at least one outcome');
|
|
46
|
+
return rest.reduce((worst, next) => (OUTCOME_RANK[next.status] > OUTCOME_RANK[worst.status] ? next : worst), first);
|
|
47
|
+
}
|
|
48
|
+
// Every DELETE below is issued only after a read confirmed the object is there,
|
|
49
|
+
// so a 404 on the delete itself is not "already gone": GitHub answers 404
|
|
50
|
+
// rather than 403 on an admin endpoint a fine-grained token cannot reach, the
|
|
51
|
+
// same reading writeOutcome takes in cli/platforms/github/install.ts. Reporting
|
|
52
|
+
// it as success would tell an operator their ruleset is gone when it is not.
|
|
53
|
+
function deleteOutcome(capability, status, detail) {
|
|
54
|
+
if (isSuccess(status))
|
|
55
|
+
return { capability, status: 'applied', detail };
|
|
56
|
+
if (status === 401 || status === 403 || status === 404) {
|
|
57
|
+
return { capability, status: 'denied', detail: `${detail} (needs repository admin)` };
|
|
58
|
+
}
|
|
59
|
+
return { capability, status: 'denied', detail: `${detail} (HTTP ${status})` };
|
|
60
|
+
}
|
|
61
|
+
// A read that did not answer. It cannot be `unknown`: `unknown` never reaches
|
|
62
|
+
// pendingAdmin (isPending is exactly `denied`), and a repository whose Redline
|
|
63
|
+
// ruleset could not even be listed has host state left behind that somebody has
|
|
64
|
+
// to go and remove. The detail says it was the read that failed, so nobody goes
|
|
65
|
+
// looking for a delete that was never attempted.
|
|
66
|
+
function unreadable(capability, status, what) {
|
|
67
|
+
return {
|
|
68
|
+
capability,
|
|
69
|
+
status: 'denied',
|
|
70
|
+
detail: `${what} could not be read (HTTP ${status}), so nothing was removed — ` +
|
|
71
|
+
'an administrator has to take it away by hand',
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function parseNamedObjects(body) {
|
|
75
|
+
if (!Array.isArray(body))
|
|
76
|
+
return null;
|
|
77
|
+
const parsed = [];
|
|
78
|
+
for (const item of body) {
|
|
79
|
+
if (!isNonNullObject(item) || typeof item['id'] !== 'number' || typeof item['name'] !== 'string') {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
parsed.push({ id: item['id'], name: item['name'] });
|
|
83
|
+
}
|
|
84
|
+
return parsed;
|
|
85
|
+
}
|
|
86
|
+
function parseLabelDescription(body) {
|
|
87
|
+
if (!isNonNullObject(body))
|
|
88
|
+
return null;
|
|
89
|
+
const description = body['description'];
|
|
90
|
+
return typeof description === 'string' ? description : '';
|
|
91
|
+
}
|
|
92
|
+
export function createGitHubWithdrawal(client) {
|
|
93
|
+
const repoPath = (ref) => `/repos/${ref.org}/${ref.repo}`;
|
|
94
|
+
async function withdrawRuleset(ref) {
|
|
95
|
+
const listed = await client.rest('GET', `${repoPath(ref)}/rulesets`);
|
|
96
|
+
if (!isSuccess(listed.status)) {
|
|
97
|
+
return unreadable('merge-policy', listed.status, `the branch rulesets on ${ref.repo}`);
|
|
98
|
+
}
|
|
99
|
+
const rulesets = parseNamedObjects(listed.body);
|
|
100
|
+
if (rulesets === null) {
|
|
101
|
+
throw new RedlineError('host', 'GitHub returned an unexpected shape for the rulesets list');
|
|
102
|
+
}
|
|
103
|
+
// By name, which is the only attribution a ruleset carries. A ruleset a
|
|
104
|
+
// human named anything else is theirs even if it requires the Redline
|
|
105
|
+
// check — that is a policy decision they made, and taking it away is not
|
|
106
|
+
// this command's to do.
|
|
107
|
+
const mine = rulesets.find((ruleset) => ruleset.name === RULESET_NAME);
|
|
108
|
+
if (!mine) {
|
|
109
|
+
return {
|
|
110
|
+
capability: 'merge-policy',
|
|
111
|
+
status: 'already',
|
|
112
|
+
detail: `no ruleset named "${RULESET_NAME}" on this repository — nothing to remove`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const deleted = await client.rest('DELETE', `${repoPath(ref)}/rulesets/${mine.id}`);
|
|
116
|
+
return deleteOutcome('merge-policy', deleted.status, `branch ruleset "${RULESET_NAME}" (and with it the required Redline check)`);
|
|
117
|
+
}
|
|
118
|
+
async function withdrawLabels(ref) {
|
|
119
|
+
const notes = [];
|
|
120
|
+
const outcomes = [];
|
|
121
|
+
for (const label of REDLINE_LABELS) {
|
|
122
|
+
const path = `${repoPath(ref)}/labels/${label.name}`;
|
|
123
|
+
const read = await client.rest('GET', path);
|
|
124
|
+
if (read.status === 404)
|
|
125
|
+
continue; // not on this repository at all
|
|
126
|
+
if (!isSuccess(read.status)) {
|
|
127
|
+
outcomes.push(unreadable('labels', read.status, `the "${label.name}" label`));
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
const description = parseLabelDescription(read.body);
|
|
131
|
+
if (description === null) {
|
|
132
|
+
throw new RedlineError('host', 'GitHub returned an unexpected shape for a label');
|
|
133
|
+
}
|
|
134
|
+
if (description !== label.description) {
|
|
135
|
+
notes.push(`the "${label.name}" label was left in place: its description is no longer the one Redline ` +
|
|
136
|
+
'wrote, so this repository has made it its own');
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
const deleted = await client.rest('DELETE', path);
|
|
140
|
+
outcomes.push(deleteOutcome('labels', deleted.status, `label "${label.name}"`));
|
|
141
|
+
}
|
|
142
|
+
if (outcomes.length === 0) {
|
|
143
|
+
return {
|
|
144
|
+
outcome: {
|
|
145
|
+
capability: 'labels',
|
|
146
|
+
status: 'already',
|
|
147
|
+
detail: 'no label still carrying a Redline description — nothing to remove',
|
|
148
|
+
},
|
|
149
|
+
notes,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
return { outcome: worstOutcome(outcomes), notes };
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
host: 'github',
|
|
156
|
+
async withdraw(ref) {
|
|
157
|
+
const ruleset = await withdrawRuleset(ref);
|
|
158
|
+
const labels = await withdrawLabels(ref);
|
|
159
|
+
// Removed by PATCHing the value to null, which is how GitHub deletes a
|
|
160
|
+
// repository property value. The registry derives the estate by walking
|
|
161
|
+
// for this property, so leaving it set is what keeps a removed repository
|
|
162
|
+
// showing up as onboarded.
|
|
163
|
+
const property = await client.rest('PATCH', `${repoPath(ref)}/properties/values`, {
|
|
164
|
+
properties: [{ property_name: REPO_PROPERTY, value: null }],
|
|
165
|
+
});
|
|
166
|
+
return {
|
|
167
|
+
outcomes: [
|
|
168
|
+
ruleset,
|
|
169
|
+
labels.outcome,
|
|
170
|
+
deleteOutcome('repo-property', property.status, `repository property "${REPO_PROPERTY}"`),
|
|
171
|
+
],
|
|
172
|
+
notes: labels.notes,
|
|
173
|
+
};
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function parsePolicyConfigurations(body) {
|
|
178
|
+
if (!isNonNullObject(body) || !Array.isArray(body['value']))
|
|
179
|
+
return null;
|
|
180
|
+
const configs = [];
|
|
181
|
+
for (const item of body['value']) {
|
|
182
|
+
if (!isNonNullObject(item) || typeof item['id'] !== 'number')
|
|
183
|
+
return null;
|
|
184
|
+
const type = item['type'];
|
|
185
|
+
if (!isNonNullObject(type) || typeof type['id'] !== 'string')
|
|
186
|
+
return null;
|
|
187
|
+
const settings = item['settings'];
|
|
188
|
+
if (!isNonNullObject(settings))
|
|
189
|
+
return null;
|
|
190
|
+
configs.push({ id: item['id'], typeId: type['id'], settings });
|
|
191
|
+
}
|
|
192
|
+
return configs;
|
|
193
|
+
}
|
|
194
|
+
export function createAzureWithdrawal(client) {
|
|
195
|
+
return {
|
|
196
|
+
host: 'azure',
|
|
197
|
+
async withdraw(ref) {
|
|
198
|
+
const project = ref.project;
|
|
199
|
+
const repoId = ref.repoId;
|
|
200
|
+
if (project === undefined || repoId === undefined) {
|
|
201
|
+
throw new RedlineError('usage', 'an Azure DevOps repository needs a project and its id');
|
|
202
|
+
}
|
|
203
|
+
const listed = await client.request('GET', `/${project}/_apis/policy/configurations`);
|
|
204
|
+
if (!isSuccess(listed.status)) {
|
|
205
|
+
return {
|
|
206
|
+
outcomes: [unreadable('merge-policy', listed.status, 'the branch policies on this project')],
|
|
207
|
+
notes: [],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
const configs = parsePolicyConfigurations(listed.body);
|
|
211
|
+
if (configs === null) {
|
|
212
|
+
throw new RedlineError('host', 'Azure DevOps returned an unexpected shape for policy configurations');
|
|
213
|
+
}
|
|
214
|
+
const types = await resolvePolicyTypeIds(client, project);
|
|
215
|
+
const statusTypeId = types[POLICY_TYPE_NAMES.status];
|
|
216
|
+
// Scoped to THIS repository, and marked as Redline's. Both halves matter:
|
|
217
|
+
// policy configurations are project-wide, so a sibling repository's
|
|
218
|
+
// Redline policies are in the same list and are not this run's to delete.
|
|
219
|
+
const coversThisRepo = (config) => {
|
|
220
|
+
const scope = config.settings['scope'];
|
|
221
|
+
if (!Array.isArray(scope))
|
|
222
|
+
return false;
|
|
223
|
+
return scope.some((entry) => isNonNullObject(entry) && entry['repositoryId'] === repoId);
|
|
224
|
+
};
|
|
225
|
+
// The displayName marker every policy `redline init` writes carries, plus
|
|
226
|
+
// the genre/name pair that identifies the gate Status policy — which
|
|
227
|
+
// predates the marker, so a repository onboarded by an earlier release is
|
|
228
|
+
// still recognised rather than abandoned. Exactly the two tests
|
|
229
|
+
// cli/platforms/azure/install.ts uses to decide a policy is its own.
|
|
230
|
+
const mine = (config) => {
|
|
231
|
+
const displayName = config.settings['displayName'];
|
|
232
|
+
if (typeof displayName === 'string' && displayName.startsWith(REDLINE_POLICY_MARKER)) {
|
|
233
|
+
return true;
|
|
234
|
+
}
|
|
235
|
+
return (config.typeId === statusTypeId &&
|
|
236
|
+
config.settings['statusGenre'] === AZURE_STATUS_GENRE &&
|
|
237
|
+
config.settings['statusName'] === AZURE_STATUS_NAME);
|
|
238
|
+
};
|
|
239
|
+
const targets = configs.filter((config) => coversThisRepo(config) && mine(config));
|
|
240
|
+
const outcomes = [];
|
|
241
|
+
for (const config of targets) {
|
|
242
|
+
const deleted = await client.request('DELETE', `/${project}/_apis/policy/configurations/${config.id}`);
|
|
243
|
+
outcomes.push(deleteOutcome('merge-policy', deleted.status, `branch policy ${config.id}`));
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
outcomes: [
|
|
247
|
+
outcomes.length === 0
|
|
248
|
+
? {
|
|
249
|
+
capability: 'merge-policy',
|
|
250
|
+
status: 'already',
|
|
251
|
+
detail: `no branch policy carrying "${REDLINE_POLICY_MARKER}" on this repository — nothing to remove`,
|
|
252
|
+
}
|
|
253
|
+
: worstOutcome(outcomes),
|
|
254
|
+
{
|
|
255
|
+
capability: 'repo-property',
|
|
256
|
+
status: 'unsupported',
|
|
257
|
+
detail: 'Azure DevOps has no repository properties, so there is none to clear',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
capability: 'labels',
|
|
261
|
+
status: 'unsupported',
|
|
262
|
+
detail: 'Azure DevOps creates pull request labels on use rather than declaring them on the ' +
|
|
263
|
+
'repository, so there is no label object to remove',
|
|
264
|
+
},
|
|
265
|
+
],
|
|
266
|
+
// Left standing on purpose. Deleting a build definition deletes its run
|
|
267
|
+
// history with it, and that history is the repository's record of what
|
|
268
|
+
// ran on which pull request — losing it is a bigger change than
|
|
269
|
+
// removing Redline. The Build Validation policy above is gone, so the
|
|
270
|
+
// definition no longer queues on anything.
|
|
271
|
+
notes: [
|
|
272
|
+
`the "${AZURE_GATE_DEFINITION}" pipeline definition is still registered and is yours to ` +
|
|
273
|
+
'delete: removing it would delete its run history too, and nothing queues it now that ' +
|
|
274
|
+
'the Build Validation policy is gone',
|
|
275
|
+
],
|
|
276
|
+
};
|
|
277
|
+
},
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* The withdrawal port for whichever host this checkout belongs to. It reads the
|
|
282
|
+
* remote the same way cli/platforms/resolve.ts does, and for the same reason —
|
|
283
|
+
* the git remote is the only thing that says which host a working tree is on.
|
|
284
|
+
*/
|
|
285
|
+
export function createHostWithdrawal(cwd, deps = {}) {
|
|
286
|
+
const gitFor = deps.gitFor ?? ((dir) => createGit(dir));
|
|
287
|
+
const identity = parseRemote(gitFor(cwd).remoteUrl());
|
|
288
|
+
if (identity.host === 'github') {
|
|
289
|
+
return createGitHubWithdrawal((deps.makeGitHubClient ?? createGitHubClient)());
|
|
290
|
+
}
|
|
291
|
+
const makeAzure = deps.makeAzureClient ?? ((org) => createAzureClient(org));
|
|
292
|
+
return createAzureWithdrawal(makeAzure(identity.org));
|
|
293
|
+
}
|
|
294
|
+
//# sourceMappingURL=host.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"host.js","sourceRoot":"","sources":["../../cli/remove/host.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { RedlineError } from "../core/errors.js";
|
|
5
|
+
import { wrapBlock } from "./markers.js";
|
|
6
|
+
import { stripBlock } from "./standards.js";
|
|
7
|
+
const FRONTMATTER = /^---\n([\s\S]*?)\n---\n?/;
|
|
8
|
+
export function loadCommands(root) {
|
|
9
|
+
const dir = join(root, 'commands');
|
|
10
|
+
return readdirSync(dir)
|
|
11
|
+
.filter((f) => f.endsWith('.md'))
|
|
12
|
+
.map((file) => {
|
|
13
|
+
const raw = readFileSync(join(dir, file), 'utf8');
|
|
14
|
+
const match = FRONTMATTER.exec(raw);
|
|
15
|
+
const description = /description:\s*(.+)/.exec(match?.[1] ?? '')?.[1]?.trim() ?? '';
|
|
16
|
+
return {
|
|
17
|
+
name: file.replace(/\.md$/, ''),
|
|
18
|
+
description,
|
|
19
|
+
body: raw.slice(match?.[0].length ?? 0).trimStart(),
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
// The header says whose it is. Nothing about the SHAPE of a frontmatter block
|
|
24
|
+
// tells Redline's apart from a human's — a team's own command file can carry an
|
|
25
|
+
// identical lone `description:` key — so recognising it by shape claimed their
|
|
26
|
+
// bytes. Marking what Redline owns is the answer markers.ts already gives for
|
|
27
|
+
// the body: an indeterminate read is not an answer, so this makes it
|
|
28
|
+
// determinate. It goes below the keys, not above them, because the tools read
|
|
29
|
+
// the first key of the block.
|
|
30
|
+
const MANAGED_BY = '# Managed by Redline; regenerate with `redline init` rather than editing here.';
|
|
31
|
+
const MANAGED_HEADER = /^# Managed by Redline\b/m;
|
|
32
|
+
const MANAGED_LINE = /^# Managed by Redline\b[^\n]*\n/m;
|
|
33
|
+
export const COMMAND_HOSTS = {
|
|
34
|
+
copilot: (cmd) => ({
|
|
35
|
+
path: `.github/prompts/${cmd.name}.prompt.md`,
|
|
36
|
+
header: `---\nmode: agent\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
|
|
37
|
+
body: cmd.body,
|
|
38
|
+
}),
|
|
39
|
+
claude: (cmd) => ({
|
|
40
|
+
path: `.claude/commands/${cmd.name}.md`,
|
|
41
|
+
header: `---\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
|
|
42
|
+
body: cmd.body,
|
|
43
|
+
}),
|
|
44
|
+
opencode: (cmd) => ({
|
|
45
|
+
path: `.opencode/command/${cmd.name}.md`,
|
|
46
|
+
header: `---\ndescription: ${cmd.description}\n${MANAGED_BY}\n---\n`,
|
|
47
|
+
body: cmd.body,
|
|
48
|
+
}),
|
|
49
|
+
cursor: (cmd) => ({ path: `.cursor/commands/${cmd.name}.md`, header: '', body: cmd.body }),
|
|
50
|
+
};
|
|
51
|
+
// What the renderer before the marker block wrote at this path: the header and
|
|
52
|
+
// the body with one blank line between them, and no attribution line, because
|
|
53
|
+
// there was none to write. Every repository already onboarded has exactly these
|
|
54
|
+
// bytes on disk, put there by Redline itself — merge-or-create is the right
|
|
55
|
+
// answer for a HUMAN's file and the wrong one for Redline's own earlier output,
|
|
56
|
+
// which would get its prompt appended to itself and run twice. Recomputed
|
|
57
|
+
// rather than pattern-matched, so it can only ever recognise a file Redline
|
|
58
|
+
// actually produced.
|
|
59
|
+
function previouslyRendered(header, body) {
|
|
60
|
+
const legacyHeader = header.replace(MANAGED_LINE, '');
|
|
61
|
+
const composed = legacyHeader === '' ? body : `${legacyHeader}\n${body}`;
|
|
62
|
+
return `${composed.trimEnd()}\n`;
|
|
63
|
+
}
|
|
64
|
+
// What `.redline.json` records for every command file Redline owns whole, and
|
|
65
|
+
// the only thing a later run compares that record against. The algorithm is
|
|
66
|
+
// therefore part of the on-disk contract: change it and every recorded
|
|
67
|
+
// identifier stops matching, which silently returns those repositories to the
|
|
68
|
+
// byte-exact fallback below.
|
|
69
|
+
export function contentId(text) {
|
|
70
|
+
return `sha256:${createHash('sha256').update(text).digest('hex')}`;
|
|
71
|
+
}
|
|
72
|
+
// `<name>` is only the filename in `commands/`, and nothing reserves that name
|
|
73
|
+
// in a consumer repository — `commands/review-pr.md` here would land on a
|
|
74
|
+
// team's own `.claude/commands/review-pr.md`. So whatever is at the path stays
|
|
75
|
+
// and Redline's half goes inside a marker block beside it. A `.claude/commands`
|
|
76
|
+
// file IS one prompt body, so `/<name>` then runs both texts concatenated; that
|
|
77
|
+
// is the accepted cost of not overwriting a human's prompt, and the markers are
|
|
78
|
+
// what keep Redline's half removable and re-renderable.
|
|
79
|
+
export function renderCommands(opts) {
|
|
80
|
+
const commands = loadCommands(opts.root);
|
|
81
|
+
const written = [];
|
|
82
|
+
const removed = [];
|
|
83
|
+
const contentIds = {};
|
|
84
|
+
for (const host of opts.hosts) {
|
|
85
|
+
if (!COMMAND_HOSTS[host]) {
|
|
86
|
+
throw new RedlineError('usage', `unknown command host "${host}". Known: ${Object.keys(COMMAND_HOSTS).join(', ')}`);
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
// Every host, not just the selected ones: a host that is no longer selected
|
|
90
|
+
// is how Redline's block gets taken back out again, which is the other half
|
|
91
|
+
// of being allowed to merge it into a file it does not own.
|
|
92
|
+
for (const [host, renderer] of Object.entries(COMMAND_HOSTS)) {
|
|
93
|
+
const selected = opts.hosts.includes(host);
|
|
94
|
+
for (const command of commands) {
|
|
95
|
+
const { path, header, body } = renderer(command);
|
|
96
|
+
const target = join(opts.out, path);
|
|
97
|
+
const current = existsSync(target) ? readFileSync(target, 'utf8') : null;
|
|
98
|
+
// Throws rather than guessing on a half-edited marker pair or a block
|
|
99
|
+
// hidden under an unclosed fence — see markers.ts. Nothing is written.
|
|
100
|
+
const outside = current === null ? null : stripBlock(current, path);
|
|
101
|
+
// Redline's to rewrite whole: the file is nothing but its block, or what
|
|
102
|
+
// sits outside the block carries Redline's own attribution line, or the
|
|
103
|
+
// file predates the block entirely and is byte-for-byte what Redline
|
|
104
|
+
// last rendered there.
|
|
105
|
+
// The recorded identifier is asked first because it is the only one of
|
|
106
|
+
// the three that does not move when `commands/<name>.md` changes here.
|
|
107
|
+
const recorded = opts.known?.[path];
|
|
108
|
+
const ownedWhole = outside === null ||
|
|
109
|
+
(outside !== current && MANAGED_HEADER.test(outside)) ||
|
|
110
|
+
(current !== null &&
|
|
111
|
+
outside === current &&
|
|
112
|
+
(recorded === contentId(current) || current === previouslyRendered(header, body)));
|
|
113
|
+
if (!selected) {
|
|
114
|
+
if (current === null || outside === current)
|
|
115
|
+
continue; // never Redline's — brownfield rule
|
|
116
|
+
if (!opts.check) {
|
|
117
|
+
if (ownedWhole)
|
|
118
|
+
rmSync(target);
|
|
119
|
+
else
|
|
120
|
+
writeFileSync(target, outside);
|
|
121
|
+
}
|
|
122
|
+
removed.push(path);
|
|
123
|
+
continue;
|
|
124
|
+
}
|
|
125
|
+
const next = wrapBlock(current === null || ownedWhole ? header : current, body, path);
|
|
126
|
+
if (current === null || ownedWhole)
|
|
127
|
+
contentIds[path] = contentId(next);
|
|
128
|
+
if (current === next)
|
|
129
|
+
continue;
|
|
130
|
+
if (!opts.check) {
|
|
131
|
+
mkdirSync(dirname(target), { recursive: true });
|
|
132
|
+
writeFileSync(target, next);
|
|
133
|
+
}
|
|
134
|
+
written.push(path);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
return { written, removed, contentIds };
|
|
138
|
+
}
|
|
139
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../../cli/render/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { RedlineError } from "../core/errors.js";
|
|
4
|
+
function isNonNullObject(value) {
|
|
5
|
+
return typeof value === 'object' && value !== null;
|
|
6
|
+
}
|
|
7
|
+
export function parseManifest(raw) {
|
|
8
|
+
if (!isNonNullObject(raw)) {
|
|
9
|
+
throw new RedlineError('usage', 'standards manifest is not a JSON object');
|
|
10
|
+
}
|
|
11
|
+
const version = raw['version'];
|
|
12
|
+
if (typeof version !== 'string') {
|
|
13
|
+
throw new RedlineError('usage', 'standards manifest is missing a string "version" field');
|
|
14
|
+
}
|
|
15
|
+
const core = raw['core'];
|
|
16
|
+
const stacks = raw['stacks'];
|
|
17
|
+
const profiles = raw['profiles'];
|
|
18
|
+
const vendors = raw['vendors'];
|
|
19
|
+
if (!isNonNullObject(core)) {
|
|
20
|
+
throw new RedlineError('usage', 'standards manifest is missing an object "core" field');
|
|
21
|
+
}
|
|
22
|
+
if (!isNonNullObject(stacks)) {
|
|
23
|
+
throw new RedlineError('usage', 'standards manifest is missing an object "stacks" field');
|
|
24
|
+
}
|
|
25
|
+
if (!isNonNullObject(profiles)) {
|
|
26
|
+
throw new RedlineError('usage', 'standards manifest is missing an object "profiles" field');
|
|
27
|
+
}
|
|
28
|
+
if (!isNonNullObject(vendors)) {
|
|
29
|
+
throw new RedlineError('usage', 'standards manifest is missing an object "vendors" field');
|
|
30
|
+
}
|
|
31
|
+
const coreTitle = core['title'];
|
|
32
|
+
const coreSource = core['source'];
|
|
33
|
+
if (typeof coreTitle !== 'string' || typeof coreSource !== 'string') {
|
|
34
|
+
throw new RedlineError('usage', 'standards manifest "core" needs string "title" and "source" fields');
|
|
35
|
+
}
|
|
36
|
+
const profileAliasesRaw = raw['profileAliases'];
|
|
37
|
+
if (profileAliasesRaw !== undefined && !isNonNullObject(profileAliasesRaw)) {
|
|
38
|
+
throw new RedlineError('usage', 'standards manifest "profileAliases" must be an object');
|
|
39
|
+
}
|
|
40
|
+
const profileAliases = (profileAliasesRaw ?? {});
|
|
41
|
+
const deterministicRaw = raw['deterministic'];
|
|
42
|
+
if (deterministicRaw !== undefined && !Array.isArray(deterministicRaw)) {
|
|
43
|
+
throw new RedlineError('usage', 'standards manifest "deterministic" must be an array of rule ids');
|
|
44
|
+
}
|
|
45
|
+
const deterministic = (deterministicRaw ?? []);
|
|
46
|
+
for (const id of deterministic) {
|
|
47
|
+
if (typeof id !== 'string') {
|
|
48
|
+
throw new RedlineError('usage', 'standards manifest "deterministic" must contain only rule ids');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return {
|
|
52
|
+
version,
|
|
53
|
+
core: { title: coreTitle, source: coreSource },
|
|
54
|
+
stacks: stacks,
|
|
55
|
+
profiles: profiles,
|
|
56
|
+
profileAliases,
|
|
57
|
+
vendors: vendors,
|
|
58
|
+
deterministic,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function errorCode(error) {
|
|
62
|
+
if (typeof error !== 'object' || error === null || !('code' in error))
|
|
63
|
+
return undefined;
|
|
64
|
+
const code = error.code;
|
|
65
|
+
return typeof code === 'string' ? code : undefined;
|
|
66
|
+
}
|
|
67
|
+
export function loadManifest(root) {
|
|
68
|
+
const path = join(root, 'standards/manifest.json');
|
|
69
|
+
let raw;
|
|
70
|
+
try {
|
|
71
|
+
raw = readFileSync(path, 'utf8');
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (errorCode(error) === 'EACCES') {
|
|
75
|
+
throw new RedlineError('permission', `permission denied reading the standards manifest at ${path}`);
|
|
76
|
+
}
|
|
77
|
+
throw new RedlineError('usage', `cannot read the standards manifest at ${path}`);
|
|
78
|
+
}
|
|
79
|
+
const parsed = JSON.parse(raw);
|
|
80
|
+
return parseManifest(parsed);
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=manifest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"manifest.js","sourceRoot":"","sources":["../../cli/render/manifest.ts"],"names":[],"mappings":"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"}
|