@magland/mochi 0.3.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 +201 -0
- package/README.md +108 -0
- package/dist/ansi.js +174 -0
- package/dist/api/admin.js +416 -0
- package/dist/api/auth.js +166 -0
- package/dist/api/backup.js +598 -0
- package/dist/api/ci.js +336 -0
- package/dist/api/contents.js +339 -0
- package/dist/api/issues.js +165 -0
- package/dist/api/pulls.js +244 -0
- package/dist/api/releases.js +83 -0
- package/dist/api/repos.js +156 -0
- package/dist/api/write.js +518 -0
- package/dist/api.js +326 -0
- package/dist/assets.js +29 -0
- package/dist/atom.js +32 -0
- package/dist/atomic.js +171 -0
- package/dist/avatar.js +81 -0
- package/dist/browse.js +630 -0
- package/dist/build-info.json +4 -0
- package/dist/ci/actionref.js +86 -0
- package/dist/ci/api.js +829 -0
- package/dist/ci/artifacts.js +201 -0
- package/dist/ci/dispatch.js +30 -0
- package/dist/ci/engine.js +1321 -0
- package/dist/ci/expr.js +526 -0
- package/dist/ci/manual.js +199 -0
- package/dist/ci/present.js +82 -0
- package/dist/ci/protocol.js +6 -0
- package/dist/ci/runners.js +256 -0
- package/dist/ci/runs.js +208 -0
- package/dist/ci/trigger.js +28 -0
- package/dist/ci/views.js +441 -0
- package/dist/ci/wake.js +194 -0
- package/dist/ci/web.js +617 -0
- package/dist/ci/workflow.js +436 -0
- package/dist/cli/admin-cmd.js +324 -0
- package/dist/cli/api-cmd.js +128 -0
- package/dist/cli/backup-cmd.js +1500 -0
- package/dist/cli/exit.js +69 -0
- package/dist/cli/input.js +64 -0
- package/dist/cli/issue-cmd.js +243 -0
- package/dist/cli/output.js +93 -0
- package/dist/cli/parse.js +317 -0
- package/dist/cli/pr-cmd.js +289 -0
- package/dist/cli/release-cmd.js +171 -0
- package/dist/cli/repo-cmd.js +763 -0
- package/dist/cli/repo.js +101 -0
- package/dist/cli/run-cmd.js +438 -0
- package/dist/cli/target.js +54 -0
- package/dist/cli-api.js +84 -0
- package/dist/compare.js +111 -0
- package/dist/config.js +212 -0
- package/dist/credentials.js +235 -0
- package/dist/deploy-cli.js +859 -0
- package/dist/deploy-runner-cli.js +592 -0
- package/dist/diff.js +171 -0
- package/dist/discussion.js +253 -0
- package/dist/egress.js +559 -0
- package/dist/filecache.js +68 -0
- package/dist/find.js +162 -0
- package/dist/forms.js +737 -0
- package/dist/git.js +547 -0
- package/dist/githttp.js +428 -0
- package/dist/html.js +87 -0
- package/dist/icons.js +101 -0
- package/dist/import-cli.js +316 -0
- package/dist/index.js +752 -0
- package/dist/issues.js +308 -0
- package/dist/issueweb.js +447 -0
- package/dist/job-cli.js +197 -0
- package/dist/jobtoken.js +96 -0
- package/dist/languages.js +383 -0
- package/dist/layout.js +100 -0
- package/dist/lfs.js +438 -0
- package/dist/lfsstore.js +425 -0
- package/dist/limit.js +259 -0
- package/dist/logo.js +61 -0
- package/dist/markdown.js +382 -0
- package/dist/migrate.js +334 -0
- package/dist/multipart.js +90 -0
- package/dist/ops.js +869 -0
- package/dist/pagescript.js +465 -0
- package/dist/perms.js +370 -0
- package/dist/pointer.js +55 -0
- package/dist/profile.js +106 -0
- package/dist/pulls.js +320 -0
- package/dist/pullweb.js +461 -0
- package/dist/redirects.js +455 -0
- package/dist/releases.js +435 -0
- package/dist/render.js +233 -0
- package/dist/runner/actions.js +448 -0
- package/dist/runner/client.js +428 -0
- package/dist/runner/context.js +247 -0
- package/dist/runner/docker.js +197 -0
- package/dist/runner/externals.js +175 -0
- package/dist/runner/job.js +290 -0
- package/dist/runner/manual-run.js +272 -0
- package/dist/runner/overrides.js +554 -0
- package/dist/runner/steps.js +571 -0
- package/dist/runner/wake.js +84 -0
- package/dist/runner-cli.js +405 -0
- package/dist/scan.js +231 -0
- package/dist/server.js +424 -0
- package/dist/session.js +267 -0
- package/dist/site.js +259 -0
- package/dist/siteshost.js +94 -0
- package/dist/source.js +90 -0
- package/dist/style.js +1295 -0
- package/dist/themes.js +369 -0
- package/dist/vault.js +442 -0
- package/dist/version.js +88 -0
- package/dist/views.js +1007 -0
- package/dist/web.js +182 -0
- package/dist/webops.js +1402 -0
- package/package.json +71 -0
package/dist/ci/runs.js
ADDED
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.runsDir = runsDir;
|
|
37
|
+
exports.createRun = createRun;
|
|
38
|
+
exports.readRun = readRun;
|
|
39
|
+
exports.writeRun = writeRun;
|
|
40
|
+
exports.isValidJobId = isValidJobId;
|
|
41
|
+
exports.readJob = readJob;
|
|
42
|
+
exports.writeJob = writeJob;
|
|
43
|
+
exports.jobLogPath = jobLogPath;
|
|
44
|
+
exports.appendJobLog = appendJobLog;
|
|
45
|
+
exports.latestRun = latestRun;
|
|
46
|
+
exports.listRuns = listRuns;
|
|
47
|
+
exports.pruneRuns = pruneRuns;
|
|
48
|
+
const fs = __importStar(require("fs"));
|
|
49
|
+
const path = __importStar(require("path"));
|
|
50
|
+
const atomic_1 = require("../atomic");
|
|
51
|
+
const layout_1 = require("../layout");
|
|
52
|
+
const scan_1 = require("../scan");
|
|
53
|
+
function runsDir(root, collection, repoName) {
|
|
54
|
+
if (!(0, scan_1.isValidName)(collection) || !(0, scan_1.isValidName)(repoName))
|
|
55
|
+
return null;
|
|
56
|
+
return (0, layout_1.repoPath)(root, collection, `${(0, scan_1.displayName)(repoName)}.runs`);
|
|
57
|
+
}
|
|
58
|
+
function runDir(root, collection, repoName, n) {
|
|
59
|
+
return path.join(runsDir(root, collection, repoName), String(n));
|
|
60
|
+
}
|
|
61
|
+
function writeJson(file, value) {
|
|
62
|
+
(0, atomic_1.writeFileAtomic)(file, JSON.stringify(value, null, 1) + '\n');
|
|
63
|
+
}
|
|
64
|
+
function readJson(file) {
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(fs.readFileSync(file, 'utf8'));
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Allocate the next run number and create its directory. mkdir is the
|
|
73
|
+
// atomicity: if two creations race, the loser's mkdir fails and it retries.
|
|
74
|
+
function createRun(root, collection, repoName, make) {
|
|
75
|
+
const base = runsDir(root, collection, repoName);
|
|
76
|
+
if (!base)
|
|
77
|
+
throw new Error('invalid repository');
|
|
78
|
+
fs.mkdirSync(base, { recursive: true });
|
|
79
|
+
for (let attempt = 0; attempt < 20; attempt++) {
|
|
80
|
+
const n = nextRunNumber(base);
|
|
81
|
+
const dir = path.join(base, String(n));
|
|
82
|
+
try {
|
|
83
|
+
fs.mkdirSync(dir);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
fs.mkdirSync(path.join(dir, 'jobs'));
|
|
89
|
+
const { run, jobs } = make(n);
|
|
90
|
+
for (const j of jobs) {
|
|
91
|
+
if (!isValidJobId(j.id))
|
|
92
|
+
throw new Error(`refusing to write a job record under the id ${j.id}`);
|
|
93
|
+
writeJson(path.join(dir, 'jobs', `${j.id}.json`), j);
|
|
94
|
+
}
|
|
95
|
+
writeJson(path.join(dir, 'run.json'), run);
|
|
96
|
+
return run;
|
|
97
|
+
}
|
|
98
|
+
throw new Error('could not allocate a run number');
|
|
99
|
+
}
|
|
100
|
+
function nextRunNumber(base) {
|
|
101
|
+
let max = 0;
|
|
102
|
+
for (const e of fs.readdirSync(base)) {
|
|
103
|
+
const n = parseInt(e, 10);
|
|
104
|
+
if (Number.isInteger(n) && String(n) === e && n > max)
|
|
105
|
+
max = n;
|
|
106
|
+
}
|
|
107
|
+
return max + 1;
|
|
108
|
+
}
|
|
109
|
+
function readRun(root, collection, repoName, n) {
|
|
110
|
+
return readJson(path.join(runDir(root, collection, repoName, n), 'run.json'));
|
|
111
|
+
}
|
|
112
|
+
function writeRun(root, collection, repoName, run) {
|
|
113
|
+
writeJson(path.join(runDir(root, collection, repoName, run.number), 'run.json'), run);
|
|
114
|
+
}
|
|
115
|
+
// Job ids reach the filesystem as a path segment, so every function that
|
|
116
|
+
// builds a path from one checks it, whatever the caller believes about where
|
|
117
|
+
// it came from. Workflow parsing enforces the same shape (workflow.ts), and
|
|
118
|
+
// this is the second lock on the same door.
|
|
119
|
+
function isValidJobId(jobId) {
|
|
120
|
+
return /^[A-Za-z0-9_][A-Za-z0-9_-]{0,110}$/.test(jobId);
|
|
121
|
+
}
|
|
122
|
+
function readJob(root, collection, repoName, n, jobId) {
|
|
123
|
+
if (!isValidJobId(jobId))
|
|
124
|
+
return null;
|
|
125
|
+
return readJson(path.join(runDir(root, collection, repoName, n), 'jobs', `${jobId}.json`));
|
|
126
|
+
}
|
|
127
|
+
function writeJob(root, collection, repoName, n, job) {
|
|
128
|
+
if (!isValidJobId(job.id))
|
|
129
|
+
throw new Error(`refusing to write a job record under the id ${job.id}`);
|
|
130
|
+
writeJson(path.join(runDir(root, collection, repoName, n), 'jobs', `${job.id}.json`), job);
|
|
131
|
+
}
|
|
132
|
+
function jobLogPath(root, collection, repoName, n, jobId) {
|
|
133
|
+
if (!isValidJobId(jobId))
|
|
134
|
+
throw new Error(`invalid job id: ${jobId}`);
|
|
135
|
+
return path.join(runDir(root, collection, repoName, n), 'jobs', `${jobId}.log`);
|
|
136
|
+
}
|
|
137
|
+
function appendJobLog(root, collection, repoName, n, jobId, ndjson) {
|
|
138
|
+
fs.appendFileSync(jobLogPath(root, collection, repoName, n, jobId), ndjson);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* The newest run, read without reading the rest. A listing of a whole vault
|
|
142
|
+
* asks this of every repository, so it finds the highest-numbered directory
|
|
143
|
+
* and reads that one file rather than parsing the hundred a repository may
|
|
144
|
+
* have kept.
|
|
145
|
+
*/
|
|
146
|
+
function latestRun(root, collection, repoName) {
|
|
147
|
+
const base = runsDir(root, collection, repoName);
|
|
148
|
+
if (!base)
|
|
149
|
+
return null;
|
|
150
|
+
let entries;
|
|
151
|
+
try {
|
|
152
|
+
entries = fs.readdirSync(base);
|
|
153
|
+
}
|
|
154
|
+
catch {
|
|
155
|
+
return null;
|
|
156
|
+
}
|
|
157
|
+
let max = 0;
|
|
158
|
+
for (const e of entries) {
|
|
159
|
+
const n = parseInt(e, 10);
|
|
160
|
+
if (Number.isInteger(n) && String(n) === e && n > max)
|
|
161
|
+
max = n;
|
|
162
|
+
}
|
|
163
|
+
return max === 0 ? null : readJson(path.join(base, String(max), 'run.json'));
|
|
164
|
+
}
|
|
165
|
+
function listRuns(root, collection, repoName) {
|
|
166
|
+
const base = runsDir(root, collection, repoName);
|
|
167
|
+
if (!base)
|
|
168
|
+
return [];
|
|
169
|
+
let entries;
|
|
170
|
+
try {
|
|
171
|
+
entries = fs.readdirSync(base);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
return [];
|
|
175
|
+
}
|
|
176
|
+
const runs = [];
|
|
177
|
+
for (const e of entries) {
|
|
178
|
+
const n = parseInt(e, 10);
|
|
179
|
+
if (!Number.isInteger(n) || String(n) !== e)
|
|
180
|
+
continue;
|
|
181
|
+
const run = readJson(path.join(base, e, 'run.json'));
|
|
182
|
+
if (run)
|
|
183
|
+
runs.push(run);
|
|
184
|
+
}
|
|
185
|
+
runs.sort((a, b) => b.number - a.number);
|
|
186
|
+
return runs;
|
|
187
|
+
}
|
|
188
|
+
// Delete completed runs beyond the retention settings. Active runs are never
|
|
189
|
+
// pruned regardless of age.
|
|
190
|
+
function pruneRuns(root, collection, repoName, retain) {
|
|
191
|
+
const base = runsDir(root, collection, repoName);
|
|
192
|
+
if (!base)
|
|
193
|
+
return;
|
|
194
|
+
const all = listRuns(root, collection, repoName);
|
|
195
|
+
const completed = all.filter((r) => r.status === 'completed');
|
|
196
|
+
const doomed = new Set();
|
|
197
|
+
completed.slice(Math.max(0, retain.runs)).forEach((r) => doomed.add(r.number));
|
|
198
|
+
if (retain.days > 0) {
|
|
199
|
+
const cutoff = Date.now() - retain.days * 24 * 60 * 60 * 1000;
|
|
200
|
+
for (const r of completed) {
|
|
201
|
+
if (new Date(r.createdAt).getTime() < cutoff)
|
|
202
|
+
doomed.add(r.number);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
for (const n of doomed) {
|
|
206
|
+
fs.rmSync(path.join(base, String(n)), { recursive: true, force: true });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.firePush = firePush;
|
|
4
|
+
const scan_1 = require("../scan");
|
|
5
|
+
// One place that turns a branch having moved into a workflow event.
|
|
6
|
+
//
|
|
7
|
+
// A commit made in the browser, a commit made over the API, and a merge are all
|
|
8
|
+
// pushes as far as workflows are concerned, and forgetting one would be a silent
|
|
9
|
+
// divergence between the interfaces: the same operation would run CI through one
|
|
10
|
+
// door and not through the other. There were two copies of this before there were
|
|
11
|
+
// two transports, which is one copy too many already.
|
|
12
|
+
const ZERO = '0'.repeat(40);
|
|
13
|
+
/**
|
|
14
|
+
* Report a branch move to the CI engine, if there is one.
|
|
15
|
+
*
|
|
16
|
+
* A failure here is logged and never allowed to affect the operation that caused
|
|
17
|
+
* it, which by this point has already been committed.
|
|
18
|
+
*/
|
|
19
|
+
function firePush(root, engine, repo, branch, before, after, actor) {
|
|
20
|
+
if (!engine)
|
|
21
|
+
return;
|
|
22
|
+
const gitRepo = (0, scan_1.findRepo)(root, repo.collection, repo.name);
|
|
23
|
+
if (!gitRepo)
|
|
24
|
+
return;
|
|
25
|
+
engine
|
|
26
|
+
.handlePush(gitRepo, { ref: `refs/heads/${branch}`, before: before ?? ZERO, after, actor })
|
|
27
|
+
.catch((e) => console.error(`CI trigger failed: ${e instanceof Error ? e.message : e}`));
|
|
28
|
+
}
|