looply-cli 0.5.13 → 0.5.17

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.
Files changed (44) hide show
  1. package/dist/.src-hash +1 -1
  2. package/dist/bin.d.ts.map +1 -1
  3. package/dist/bin.js +8 -0
  4. package/dist/bin.js.map +1 -1
  5. package/dist/config.d.ts +19 -1
  6. package/dist/config.d.ts.map +1 -1
  7. package/dist/config.js +29 -0
  8. package/dist/config.js.map +1 -1
  9. package/dist/daemon-cmd.d.ts.map +1 -1
  10. package/dist/daemon-cmd.js +18 -0
  11. package/dist/daemon-cmd.js.map +1 -1
  12. package/dist/heroku-api.d.ts +87 -0
  13. package/dist/heroku-api.d.ts.map +1 -0
  14. package/dist/heroku-api.js +178 -0
  15. package/dist/heroku-api.js.map +1 -0
  16. package/dist/preview-cmd.d.ts +51 -0
  17. package/dist/preview-cmd.d.ts.map +1 -0
  18. package/dist/preview-cmd.js +194 -0
  19. package/dist/preview-cmd.js.map +1 -0
  20. package/dist/preview-environments.d.ts +173 -0
  21. package/dist/preview-environments.d.ts.map +1 -0
  22. package/dist/preview-environments.js +482 -0
  23. package/dist/preview-environments.js.map +1 -0
  24. package/dist/preview-github.d.ts +63 -0
  25. package/dist/preview-github.d.ts.map +1 -0
  26. package/dist/preview-github.js +130 -0
  27. package/dist/preview-github.js.map +1 -0
  28. package/dist/preview-settings-cache.d.ts +33 -0
  29. package/dist/preview-settings-cache.d.ts.map +1 -0
  30. package/dist/preview-settings-cache.js +108 -0
  31. package/dist/preview-settings-cache.js.map +1 -0
  32. package/dist/preview-wiring.d.ts +35 -0
  33. package/dist/preview-wiring.d.ts.map +1 -0
  34. package/dist/preview-wiring.js +81 -0
  35. package/dist/preview-wiring.js.map +1 -0
  36. package/dist/run-spend-report.d.ts +55 -0
  37. package/dist/run-spend-report.d.ts.map +1 -0
  38. package/dist/run-spend-report.js +84 -0
  39. package/dist/run-spend-report.js.map +1 -0
  40. package/dist/server-client.d.ts +22 -0
  41. package/dist/server-client.d.ts.map +1 -1
  42. package/dist/server-client.js +26 -0
  43. package/dist/server-client.js.map +1 -1
  44. package/package.json +2 -2
@@ -0,0 +1,482 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MAX_PREVIEW_JOBS = exports.PREVIEW_COMMAND_TIMEOUT_MS = exports.MAX_TEARDOWN_ATTEMPTS = exports.PREVIEW_APPEAR_GRACE_MS = exports.PREVIEW_ENVIRONMENTS_FILE = void 0;
4
+ exports.filePreviewStore = filePreviewStore;
5
+ exports.memoryPreviewStore = memoryPreviewStore;
6
+ exports.netlifyDriver = netlifyDriver;
7
+ exports.herokuDriver = herokuDriver;
8
+ exports.previewUrlFromOutput = previewUrlFromOutput;
9
+ exports.commandDriver = commandDriver;
10
+ exports.redactSecrets = redactSecrets;
11
+ exports.makePreviewCommandRunner = makePreviewCommandRunner;
12
+ exports.advancePreviews = advancePreviews;
13
+ exports.providerName = providerName;
14
+ const node_child_process_1 = require("node:child_process");
15
+ const node_fs_1 = require("node:fs");
16
+ const node_path_1 = require("node:path");
17
+ const core_1 = require("@looply/core");
18
+ const delivery_rules_1 = require("./delivery-rules");
19
+ const preview_github_1 = require("./preview-github");
20
+ /**
21
+ * A DELIVERED PULL REQUEST BECOMES A PREVIEW SITE A PERSON CAN OPEN.
22
+ *
23
+ * ─────────────────────────────────────────────────────────────────────────────
24
+ * After `branch-delivery.ts` opened a goal's pull request, one pass every few
25
+ * minutes (beside `advanceDeliveries`) looks at each delivered pull request:
26
+ *
27
+ * open → the project's preview provider is asked where its preview stands
28
+ * (building / live with its address / failed), and that is recorded on
29
+ * the goal, where AutoRyn shows "Test it here →". A new commit on the
30
+ * pull request is a rebuild.
31
+ * closed → merged or not, the preview is torn down by the provider's own
32
+ * mechanism and recorded as removed.
33
+ *
34
+ * Providers (core's `preview-environment.ts` has the settings):
35
+ *
36
+ * netlify — READ ONLY. Netlify builds deploy previews itself; its commit status
37
+ * `netlify/<site>/deploy-preview` on the head names the address.
38
+ * Netlify keeps old deploy previews; closing is recorded as removed
39
+ * with that said in words.
40
+ * heroku — Heroku's review apps on the named pipeline: read through Heroku's
41
+ * API (this machine's own Heroku login) or, without one, the GitHub
42
+ * deployment Heroku reports. Created by Looply only when the setting
43
+ * says `create` (a new paid app); removed through
44
+ * `DELETE /review-apps/:id` — `heroku-api.ts` can reach no other kind of app.
45
+ * command — the project's OWN `.looply/config.yaml` `preview.command`, run
46
+ * hidden in the project folder; the last https address it prints is
47
+ * the preview. `preview.teardown` runs when the pull request closes.
48
+ *
49
+ * 🔴 NO SECRETS LEAVE THE MACHINE, AND NONE ARE LOGGED. What is recorded is a
50
+ * state, a cleaned address (scheme + host + path) and a sentence Looply wrote —
51
+ * never a command's output. The local log of a preview command
52
+ * (`run-logs/preview.log`) has credentials in URLs, `token=…`-style pairs and
53
+ * bearer tokens masked before it is written.
54
+ *
55
+ * Nothing here decides anything about the goal. It runs after the goal was met
56
+ * and its pull request opened; a failure here is a failed preview, said in
57
+ * words, and never throws.
58
+ */
59
+ /* ────────────────────────────────────────────────────────────── store ── */
60
+ exports.PREVIEW_ENVIRONMENTS_FILE = 'preview-environments.json';
61
+ function filePreviewStore(stateDir) {
62
+ const path = (0, node_path_1.join)(stateDir, exports.PREVIEW_ENVIRONMENTS_FILE);
63
+ const read = () => {
64
+ try {
65
+ const raw = JSON.parse((0, node_fs_1.readFileSync)(path, 'utf8'));
66
+ return raw.entries && typeof raw.entries === 'object' ? raw.entries : {};
67
+ }
68
+ catch {
69
+ return {};
70
+ }
71
+ };
72
+ return {
73
+ get: (goalId) => read()[goalId] ?? null,
74
+ all: () => Object.values(read()),
75
+ put(entry) {
76
+ const entries = read();
77
+ entries[entry.goalId] = entry;
78
+ (0, node_fs_1.mkdirSync)(stateDir, { recursive: true });
79
+ const tmp = `${path}.${process.pid}.tmp`;
80
+ (0, node_fs_1.writeFileSync)(tmp, `${JSON.stringify({ schema: 1, entries }, null, 2)}\n`, 'utf8');
81
+ (0, node_fs_1.renameSync)(tmp, path);
82
+ },
83
+ };
84
+ }
85
+ function memoryPreviewStore() {
86
+ const m = new Map();
87
+ return { get: (g) => (m.has(g) ? { ...m.get(g) } : null), all: () => [...m.values()].map((e) => ({ ...e })), put: (e) => void m.set(e.goalId, { ...e }) };
88
+ }
89
+ /** How long a provider is given to show any sign of a preview before it reads as failed. */
90
+ exports.PREVIEW_APPEAR_GRACE_MS = 20 * 60_000;
91
+ /** Failed teardowns before Looply stops trying and says to remove it by hand. */
92
+ exports.MAX_TEARDOWN_ATTEMPTS = 5;
93
+ /** Netlify deploy previews: read, never made, never deleted by Looply. */
94
+ function netlifyDriver(settings, reader) {
95
+ return {
96
+ provider: 'netlify',
97
+ neverAppeared: `Netlify has not reported a deploy preview for this pull request. Check that the Netlify site${settings.site ? ` ${settings.site}` : ''} is linked to this repository with deploy previews on.`,
98
+ async observe(t) {
99
+ const s = (0, preview_github_1.netlifySignal)(await reader.signals(t.headSha), settings.site);
100
+ if (s === null)
101
+ return null;
102
+ if (s.state === 'failed')
103
+ return { state: 'failed', url: null, detail: `Netlify's deploy preview failed${s.description ? `: ${clip(s.description, 200)}` : ''}` };
104
+ if (s.state !== 'live')
105
+ return { state: 'building', url: null, detail: 'Netlify is building the deploy preview' };
106
+ const url = (0, core_1.safePreviewUrl)(s.url);
107
+ return url === null
108
+ ? { state: 'failed', url: null, detail: 'Netlify reported the deploy preview without an https address' }
109
+ : { state: 'live', url, detail: null };
110
+ },
111
+ async teardown() {
112
+ return {
113
+ removed: true,
114
+ detail: 'the pull request is closed; Netlify keeps its last deploy preview at that address but no longer updates it',
115
+ };
116
+ },
117
+ };
118
+ }
119
+ /** Heroku review apps on one pipeline. */
120
+ function herokuDriver(settings, reader, heroku) {
121
+ let pipelineId;
122
+ const pid = async () => {
123
+ if (heroku === null)
124
+ return null;
125
+ if (pipelineId === undefined)
126
+ pipelineId = await heroku.pipelineId(settings.pipeline);
127
+ return pipelineId;
128
+ };
129
+ const findApp = async (t, prior) => {
130
+ const id = await pid();
131
+ if (heroku === null || id === null)
132
+ return null;
133
+ const apps = (await heroku.reviewApps(id)).filter((a) => a.status !== 'deleted');
134
+ return apps.find((a) => prior?.reviewAppId != null && a.id === prior.reviewAppId) ?? apps.find((a) => a.prNumber === t.pullNumber) ?? apps.find((a) => a.branch === t.branch) ?? null;
135
+ };
136
+ return {
137
+ provider: 'heroku',
138
+ neverAppeared: settings.create
139
+ ? `Heroku has not made a review app for this pull request on ${settings.pipeline}.`
140
+ : `Heroku has not made a review app for this pull request. Turn on automatic review apps for the ${settings.pipeline} pipeline, or let Looply ask Heroku for one (a new paid app per pull request).`,
141
+ async observe(t, prior) {
142
+ if (heroku !== null) {
143
+ if ((await pid()) === null)
144
+ return { state: 'failed', url: null, detail: `this machine's Heroku login cannot see the pipeline ${settings.pipeline}` };
145
+ const app = await findApp(t, prior);
146
+ if (app !== null)
147
+ return fromReviewApp(heroku, app);
148
+ if (settings.create) {
149
+ const source = await reader.sourceTarballUrl(t.headSha);
150
+ if (source === null)
151
+ return { state: 'failed', url: null, detail: 'GitHub gave no source download for Heroku to build the review app from' };
152
+ const made = await heroku.createReviewApp({ pipelineId: (await pid()), branch: t.branch, prNumber: t.pullNumber, sourceUrl: source, sha: t.headSha });
153
+ return { state: 'building', url: null, detail: `Looply asked Heroku for a review app on ${settings.pipeline}`, reviewAppId: made.id };
154
+ }
155
+ return null;
156
+ }
157
+ const s = (0, preview_github_1.herokuSignal)(await reader.signals(t.headSha), settings.pipeline, t.pullNumber);
158
+ if (s === null) {
159
+ return settings.create
160
+ ? { state: 'failed', url: null, detail: 'this machine has no Heroku login (HEROKU_API_KEY or `heroku login`), so Looply cannot ask Heroku for a review app' }
161
+ : null;
162
+ }
163
+ if (s.state === 'failed')
164
+ return { state: 'failed', url: null, detail: `the Heroku review app failed${s.description ? `: ${clip(s.description, 200)}` : ''}` };
165
+ if (s.state === 'inactive')
166
+ return { state: 'removed', url: null, detail: 'Heroku reports the review app inactive' };
167
+ if (s.state !== 'live')
168
+ return { state: 'building', url: null, detail: 'Heroku is building the review app' };
169
+ const url = (0, core_1.safePreviewUrl)(s.url);
170
+ return url === null ? { state: 'failed', url: null, detail: 'Heroku reported the review app without an https address' } : { state: 'live', url, detail: null };
171
+ },
172
+ async teardown(t, prior) {
173
+ if (heroku === null) {
174
+ return {
175
+ removed: true,
176
+ detail: "the pull request is closed; Heroku removes its review app when the pipeline's automatic removal is on (this machine has no Heroku login to confirm it)",
177
+ };
178
+ }
179
+ const app = await findApp(t, prior);
180
+ if (app === null)
181
+ return { removed: true, detail: 'the pull request is closed; Heroku has already removed the review app' };
182
+ if (app.status === 'deleting')
183
+ return { removed: true, detail: 'the pull request is closed; Heroku is removing the review app' };
184
+ await heroku.deleteReviewApp(app.id);
185
+ return { removed: true, detail: 'the pull request is closed; Looply removed the review app' };
186
+ },
187
+ };
188
+ }
189
+ async function fromReviewApp(heroku, app) {
190
+ if (app.status === 'errored')
191
+ return { state: 'failed', url: null, detail: `the Heroku review app failed${app.message ? `: ${app.message}` : ''}`, reviewAppId: app.id };
192
+ if (app.status !== 'created' || app.appId === null)
193
+ return { state: 'building', url: null, detail: 'Heroku is building the review app', reviewAppId: app.id };
194
+ const url = (0, core_1.safePreviewUrl)(await heroku.webUrl(app.appId));
195
+ return url === null
196
+ ? { state: 'failed', url: null, detail: 'Heroku made the review app but gave no https address for it', reviewAppId: app.id }
197
+ : { state: 'live', url, detail: null, reviewAppId: app.id };
198
+ }
199
+ /** How long a preview command may run before it is stopped and the preview reads as failed. */
200
+ exports.PREVIEW_COMMAND_TIMEOUT_MS = 30 * 60_000;
201
+ /** Preview commands building at once on this machine, per project. */
202
+ exports.MAX_PREVIEW_JOBS = 2;
203
+ /**
204
+ * The address a preview command printed: a `LOOPLY_PREVIEW_URL=https://…` line
205
+ * when there is one, else the last https address in its output; cleaned by
206
+ * core's `safePreviewUrl`. Null when it printed none.
207
+ */
208
+ function previewUrlFromOutput(stdout) {
209
+ const marked = /^\s*LOOPLY_PREVIEW_URL=(\S+)\s*$/m.exec(stdout);
210
+ if (marked)
211
+ return (0, core_1.safePreviewUrl)(marked[1]);
212
+ const all = stdout.match(/https:\/\/[^\s"'<>`]+/g) ?? [];
213
+ for (let i = all.length - 1; i >= 0; i--) {
214
+ const u = (0, core_1.safePreviewUrl)(all[i].replace(/[),.;]+$/, ''));
215
+ if (u !== null)
216
+ return u;
217
+ }
218
+ return null;
219
+ }
220
+ /**
221
+ * The project's own preview command. The build runs in the background — a
222
+ * 30-minute build must not hold up the five-minute pass — and its result is
223
+ * picked up by the next pass. A daemon restart mid-build starts it again.
224
+ */
225
+ function commandDriver(decl, run) {
226
+ const jobs = new Map();
227
+ const env = (t, extra = {}) => ({
228
+ LOOPLY_GOAL_ID: t.goalId,
229
+ LOOPLY_PREVIEW_BRANCH: t.branch,
230
+ LOOPLY_HEAD_SHA: t.headSha,
231
+ LOOPLY_PULL_REQUEST_NUMBER: String(t.pullNumber),
232
+ LOOPLY_PULL_REQUEST_URL: t.pullRequestUrl ?? '',
233
+ ...extra,
234
+ });
235
+ return {
236
+ provider: 'command',
237
+ neverAppeared: 'the preview command did not finish',
238
+ async observe(t, prior) {
239
+ if (decl.command === undefined || decl.command.trim() === '') {
240
+ return { state: 'failed', url: null, detail: "no preview command is declared (preview.command in the project's .looply/config.yaml)" };
241
+ }
242
+ // Already built this commit: nothing to run.
243
+ if (prior !== null && prior.sha === t.headSha && (prior.state === 'live' || prior.state === 'failed')) {
244
+ return { state: prior.state, url: prior.url, detail: prior.detail };
245
+ }
246
+ const job = jobs.get(t.goalId);
247
+ if (job !== undefined && job.sha === t.headSha) {
248
+ if (job.done === null)
249
+ return { state: 'building', url: null, detail: 'the preview command is running' };
250
+ jobs.delete(t.goalId);
251
+ return job.done;
252
+ }
253
+ const running = [...jobs.values()].filter((j) => j.done === null).length;
254
+ if (running >= exports.MAX_PREVIEW_JOBS)
255
+ return { state: 'building', url: null, detail: 'waiting for another preview to finish building' };
256
+ const mine = { sha: t.headSha, done: null };
257
+ jobs.set(t.goalId, mine);
258
+ void run(decl.command, env(t), exports.PREVIEW_COMMAND_TIMEOUT_MS)
259
+ .then((r) => {
260
+ if (r.code !== 0)
261
+ return { state: 'failed', url: null, detail: `the preview command exited ${r.code} (its output is in .looply/state/run-logs/preview.log on the machine)` };
262
+ const url = previewUrlFromOutput(r.stdout);
263
+ return url === null
264
+ ? { state: 'failed', url: null, detail: 'the preview command finished but printed no https address' }
265
+ : { state: 'live', url, detail: null };
266
+ })
267
+ .catch((e) => ({ state: 'failed', url: null, detail: `the preview command could not start (${clip(e.message, 120)})` }))
268
+ .then((o) => {
269
+ mine.done = o;
270
+ });
271
+ return { state: 'building', url: null, detail: 'the preview command is running' };
272
+ },
273
+ async teardown(t, prior) {
274
+ jobs.delete(t.goalId);
275
+ if (decl.teardown === undefined || decl.teardown.trim() === '') {
276
+ return { removed: true, detail: 'the pull request is closed; no preview.teardown is declared, so what the preview command made is left as it is' };
277
+ }
278
+ const r = await run(decl.teardown, env(t, { LOOPLY_PREVIEW_URL: prior.url ?? '' }), 10 * 60_000);
279
+ return r.code === 0
280
+ ? { removed: true, detail: 'the pull request is closed; the declared preview teardown finished' }
281
+ : { removed: false, detail: `the preview teardown exited ${r.code}` };
282
+ },
283
+ };
284
+ }
285
+ /* ──────────────────────────────────────────────────────────── secrets ── */
286
+ /**
287
+ * Mask what looks like a credential before a line is written to a local log:
288
+ * user:password in URLs, `token=…` / `api_key: …` / `password=…` pairs,
289
+ * `Bearer …`, and the token shapes of GitHub, Heroku and Netlify.
290
+ */
291
+ function redactSecrets(text) {
292
+ return (0, delivery_rules_1.redactUrl)(text)
293
+ .replace(/\b(Bearer|token)\s+[A-Za-z0-9._~+/=-]{12,}/gi, '$1 ***')
294
+ .replace(/\b([A-Za-z0-9_]*(?:token|secret|password|passwd|api[_-]?key|auth)[A-Za-z0-9_]*)(\s*[=:]\s*)("?)[^\s"'&]+\3/gi, '$1$2$3***$3')
295
+ .replace(/\b(gh[pousr]_[A-Za-z0-9]{20,}|github_pat_[A-Za-z0-9_]{20,}|nfp_[A-Za-z0-9]{20,}|HRKU-[A-Za-z0-9_-]{20,})\b/g, '***')
296
+ .replace(/([?&](?:sig|signature|token|key|access_token|X-Amz-Signature|X-Amz-Credential)=)[^&\s]+/gi, '$1***');
297
+ }
298
+ /**
299
+ * Run a declared preview step in the project folder, hidden, bounded, its output
300
+ * appended (secrets masked) to `.looply/state/run-logs/preview.log`.
301
+ */
302
+ function makePreviewCommandRunner(projectDir, stateDir) {
303
+ return (command, env, timeoutMs) => new Promise((resolve) => {
304
+ const logDir = (0, node_path_1.join)(stateDir, 'run-logs');
305
+ const logPath = (0, node_path_1.join)(logDir, 'preview.log');
306
+ const out = [];
307
+ const note = (s) => {
308
+ try {
309
+ (0, node_fs_1.mkdirSync)(logDir, { recursive: true });
310
+ (0, node_fs_1.appendFileSync)(logPath, redactSecrets(s), 'utf8');
311
+ }
312
+ catch {
313
+ /* the log is a convenience */
314
+ }
315
+ };
316
+ note(`\n=== ${new Date().toISOString()} ${command} (pull request ${env['LOOPLY_PULL_REQUEST_NUMBER'] ?? '?'})\n`);
317
+ let child;
318
+ try {
319
+ child = (0, node_child_process_1.spawn)(command, { cwd: projectDir, shell: true, env: { ...process.env, ...env }, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true });
320
+ }
321
+ catch (e) {
322
+ resolve({ code: -1, stdout: e.message });
323
+ return;
324
+ }
325
+ const timer = setTimeout(() => child.kill(), timeoutMs);
326
+ child.stdout?.on('data', (d) => {
327
+ const s = d.toString('utf8');
328
+ out.push(s);
329
+ note(s);
330
+ });
331
+ child.stderr?.on('data', (d) => note(d.toString('utf8')));
332
+ child.on('error', (e) => {
333
+ clearTimeout(timer);
334
+ resolve({ code: -1, stdout: e.message });
335
+ });
336
+ child.on('close', (code) => {
337
+ clearTimeout(timer);
338
+ resolve({ code: code ?? -1, stdout: out.join('').slice(-20_000) });
339
+ });
340
+ });
341
+ }
342
+ /** A delivery a preview can be for: a pull request on GitHub. */
343
+ function previewable(e) {
344
+ return e.owner !== null && e.repo !== null && e.pullNumber !== null;
345
+ }
346
+ function reportOf(p) {
347
+ return { provider: p.provider, state: p.state, url: p.url, pullRequestUrl: p.pullRequestUrl, sha: p.sha, detail: p.detail };
348
+ }
349
+ const same = (a, b) => a !== null && a.state === b.state && a.url === b.url && a.detail === b.detail && a.sha === b.sha && a.provider === b.provider;
350
+ async function save(deps, prior, next) {
351
+ deps.store.put(next);
352
+ if (same(prior, next))
353
+ return;
354
+ deps.log(`preview : ${next.goalId}: ${next.state}${next.url ? ` ${next.url}` : ''}${next.detail ? ` (${next.detail})` : ''}`);
355
+ try {
356
+ await deps.record(next.goalId, reportOf(next));
357
+ }
358
+ catch (err) {
359
+ deps.log(`preview : could not record ${next.goalId}'s preview on the server (${err.message})`);
360
+ }
361
+ }
362
+ /**
363
+ * One pass over every delivered pull request: start or read its preview while it
364
+ * is open, tear it down once it closed. Each change is recorded on the goal.
365
+ * Never throws.
366
+ */
367
+ async function advancePreviews(deps) {
368
+ for (const d of deps.deliveries.all()) {
369
+ if (!previewable(d))
370
+ continue;
371
+ const prior = deps.store.get(d.goalId);
372
+ if (prior?.state === 'removed')
373
+ continue;
374
+ // A pull request delivered and finished before any preview was made gets none now.
375
+ if (prior === null && d.done === true)
376
+ continue;
377
+ try {
378
+ await advanceOne(deps, d, prior);
379
+ }
380
+ catch (err) {
381
+ deps.log(`preview : ${d.goalId}: ${clip(err.message, 300)}`);
382
+ }
383
+ }
384
+ }
385
+ async function advanceOne(deps, d, prior) {
386
+ const settings = deps.settings();
387
+ const wanted = settings === null || settings.provider === 'none' ? null : settings.provider;
388
+ if (prior === null && wanted === null)
389
+ return;
390
+ const api = await deps.github(d.owner, d.repo);
391
+ if (api === null)
392
+ return; // no credentials right now: next pass
393
+ const pull = await api.getPull(d.pullNumber);
394
+ const at = new Date(deps.now()).toISOString();
395
+ const target = {
396
+ goalId: d.goalId,
397
+ owner: d.owner,
398
+ repo: d.repo,
399
+ pullNumber: d.pullNumber,
400
+ pullRequestUrl: d.pullRequestUrl ?? pull.url,
401
+ branch: d.branch,
402
+ headSha: pull.headSha || d.sha,
403
+ };
404
+ if (pull.state === 'closed') {
405
+ if (prior === null)
406
+ return;
407
+ const driver = deps.driver(prior.provider);
408
+ if (driver === null) {
409
+ await save(deps, prior, { ...prior, state: 'removed', detail: 'the pull request is closed', updatedAt: at });
410
+ return;
411
+ }
412
+ const attempts = (prior.teardownAttempts ?? 0) + 1;
413
+ let t;
414
+ try {
415
+ t = await driver.teardown(target, prior);
416
+ }
417
+ catch (e) {
418
+ t = { removed: false, detail: clip(e.message, 200) };
419
+ }
420
+ if (t.removed) {
421
+ await save(deps, prior, { ...prior, state: 'removed', detail: t.detail, updatedAt: at, teardownAttempts: attempts });
422
+ }
423
+ else if (attempts >= exports.MAX_TEARDOWN_ATTEMPTS) {
424
+ await save(deps, prior, { ...prior, state: 'removed', detail: `Looply could not remove the preview after ${attempts} tries (${t.detail}); remove it by hand`, updatedAt: at, teardownAttempts: attempts });
425
+ }
426
+ else {
427
+ await save(deps, prior, { ...prior, detail: `the pull request is closed; removing the preview failed, retrying (${t.detail})`, updatedAt: at, teardownAttempts: attempts });
428
+ }
429
+ return;
430
+ }
431
+ // Open. A preview already made keeps its provider until it is removed; a new one uses the setting.
432
+ const provider = prior?.provider ?? wanted;
433
+ if (provider === null)
434
+ return;
435
+ const driver = deps.driver(provider);
436
+ if (driver === null)
437
+ return;
438
+ const sameCommit = prior !== null && prior.sha === target.headSha;
439
+ const startedAt = sameCommit ? prior.startedAt : at;
440
+ const base = {
441
+ goalId: d.goalId,
442
+ provider,
443
+ state: 'building',
444
+ url: null,
445
+ detail: null,
446
+ owner: d.owner,
447
+ repo: d.repo,
448
+ pullNumber: d.pullNumber,
449
+ pullRequestUrl: target.pullRequestUrl,
450
+ branch: d.branch,
451
+ sha: target.headSha,
452
+ startedAt,
453
+ updatedAt: at,
454
+ reviewAppId: prior?.reviewAppId ?? null,
455
+ };
456
+ const seen = await driver.observe(target, sameCommit ? prior : prior === null ? null : { ...prior, sha: null });
457
+ if (seen === null) {
458
+ const waited = deps.now() - Date.parse(startedAt);
459
+ if (waited > exports.PREVIEW_APPEAR_GRACE_MS) {
460
+ await save(deps, prior, { ...base, state: 'failed', detail: driver.neverAppeared });
461
+ }
462
+ else {
463
+ await save(deps, prior, { ...base, detail: `waiting for ${providerName(provider)} to start the preview` });
464
+ }
465
+ return;
466
+ }
467
+ await save(deps, prior, {
468
+ ...base,
469
+ state: seen.state,
470
+ url: seen.url,
471
+ detail: seen.detail,
472
+ reviewAppId: seen.reviewAppId ?? base.reviewAppId ?? null,
473
+ });
474
+ }
475
+ function providerName(p) {
476
+ return p === 'netlify' ? 'Netlify' : p === 'heroku' ? 'Heroku' : 'the preview command';
477
+ }
478
+ function clip(s, n) {
479
+ const t = redactSecrets(s).replace(/\s+/g, ' ').trim();
480
+ return t.length > n ? `${t.slice(0, n - 1)}…` : t;
481
+ }
482
+ //# sourceMappingURL=preview-environments.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-environments.js","sourceRoot":"","sources":["../src/preview-environments.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * WHAT A PROVIDER ALREADY SAID ABOUT A PULL REQUEST'S PREVIEW, READ FROM GITHUB.
3
+ *
4
+ * Netlify and Heroku both report their preview builds back to GitHub on the
5
+ * pull request's head commit — Netlify as a commit status
6
+ * (`netlify/<site>/deploy-preview`, its `target_url` the preview) and as a
7
+ * deployment; Heroku review apps as a deployment whose status carries the app's
8
+ * `environment_url`. Reading those means Looply needs no Netlify credentials at
9
+ * all and no Heroku ones to FIND a preview: it is the provider's own mechanism,
10
+ * observed.
11
+ *
12
+ * Read-only: GET only, with the token `github-api.ts` already uses for pull
13
+ * requests. One write-free exception, `sourceTarballUrl`, asks GitHub for the
14
+ * short-lived download link of a commit's source — a GET that is answered with a
15
+ * redirect — which Heroku needs to build a review app Looply asked for.
16
+ */
17
+ export type SignalState = 'building' | 'live' | 'failed' | 'inactive';
18
+ export interface PreviewSignal {
19
+ readonly source: 'status' | 'deployment';
20
+ /** The status context, or the deployment's environment name. */
21
+ readonly name: string;
22
+ readonly state: SignalState;
23
+ /** Where it says the preview is (raw — `safePreviewUrl` cleans it before use). */
24
+ readonly url: string | null;
25
+ readonly description: string | null;
26
+ }
27
+ export interface GitHubPreviewReader {
28
+ /** Every preview-ish signal on `sha`: commit statuses and deployments, newest first per name. */
29
+ signals(sha: string): Promise<PreviewSignal[]>;
30
+ /** A short-lived https link to `sha`'s source tarball, for Heroku to build from; null when GitHub gives none. */
31
+ sourceTarballUrl(sha: string): Promise<string | null>;
32
+ /** The newest open pull requests (for `looply preview --dry-run`). */
33
+ openPulls(limit: number): Promise<Array<{
34
+ number: number;
35
+ url: string;
36
+ branch: string;
37
+ headSha: string;
38
+ title: string;
39
+ }>>;
40
+ }
41
+ type Fetch = (url: string, init: {
42
+ method: string;
43
+ headers: Record<string, string>;
44
+ redirect?: 'manual' | 'follow';
45
+ }) => Promise<{
46
+ status: number;
47
+ text(): Promise<string>;
48
+ headers?: {
49
+ get(name: string): string | null;
50
+ };
51
+ }>;
52
+ export declare function makeGitHubPreviewReader(deps: {
53
+ owner: string;
54
+ repo: string;
55
+ token: string;
56
+ fetch?: Fetch;
57
+ }): GitHubPreviewReader;
58
+ /** Netlify's deploy-preview signal for this pull request, if any; `site` narrows it to one site. */
59
+ export declare function netlifySignal(signals: readonly PreviewSignal[], site?: string): PreviewSignal | null;
60
+ /** Heroku's review-app deployment for pull request `n` of `pipeline`, if GitHub has one. */
61
+ export declare function herokuSignal(signals: readonly PreviewSignal[], pipeline: string, n: number): PreviewSignal | null;
62
+ export {};
63
+ //# sourceMappingURL=preview-github.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preview-github.d.ts","sourceRoot":"","sources":["../src/preview-github.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,MAAM,MAAM,WAAW,GAAG,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,UAAU,CAAC;AAEtE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,YAAY,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;IAC5B,kFAAkF;IAClF,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,mBAAmB;IAClC,iGAAiG;IACjG,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAAC;IAC/C,iHAAiH;IACjH,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACtD,sEAAsE;IACtE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC,CAAC;CAC3H;AAED,KAAK,KAAK,GAAG,CACX,GAAG,EAAE,MAAM,EACX,IAAI,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,KACtF,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE;QAAE,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;KAAE,CAAA;CAAE,CAAC,CAAC;AAE1G,wBAAgB,uBAAuB,CAAC,IAAI,EAAE;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,KAAK,CAAA;CAAE,GAAG,mBAAmB,CAyEhI;AAID,oGAAoG;AACpG,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAcpG;AAED,4FAA4F;AAC5F,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,aAAa,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAWjH"}