@juangadm/pre-post 1.0.0 → 1.1.0
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/README.md +99 -20
- package/dist/baseline.d.ts +119 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +316 -0
- package/dist/baseline.js.map +1 -0
- package/dist/bin/cli.js +80 -41
- package/dist/bin/cli.js.map +1 -1
- package/dist/browser.d.ts +31 -3
- package/dist/browser.d.ts.map +1 -1
- package/dist/browser.js +239 -97
- package/dist/browser.js.map +1 -1
- package/dist/commands/compare.d.ts.map +1 -1
- package/dist/commands/compare.js +21 -3
- package/dist/commands/compare.js.map +1 -1
- package/dist/commands/detect.d.ts +5 -0
- package/dist/commands/detect.d.ts.map +1 -1
- package/dist/commands/detect.js +4 -1
- package/dist/commands/detect.js.map +1 -1
- package/dist/commands/doctor.d.ts +32 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +90 -9
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/login.js +1 -1
- package/dist/commands/pr.d.ts +4 -0
- package/dist/commands/pr.d.ts.map +1 -1
- package/dist/commands/pr.js +150 -50
- package/dist/commands/pr.js.map +1 -1
- package/dist/commands/prune.js +1 -1
- package/dist/commands/prune.js.map +1 -1
- package/dist/comparison.d.ts +104 -0
- package/dist/comparison.d.ts.map +1 -0
- package/dist/comparison.js +236 -0
- package/dist/comparison.js.map +1 -0
- package/dist/config.d.ts +12 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +25 -3
- package/dist/config.js.map +1 -1
- package/dist/deployments.d.ts +71 -0
- package/dist/deployments.d.ts.map +1 -0
- package/dist/deployments.js +204 -0
- package/dist/deployments.js.map +1 -0
- package/dist/diff-pool.d.ts.map +1 -1
- package/dist/diff-pool.js +5 -2
- package/dist/diff-pool.js.map +1 -1
- package/dist/diff-worker.d.ts +3 -0
- package/dist/diff-worker.d.ts.map +1 -1
- package/dist/diff-worker.js +1 -0
- package/dist/diff-worker.js.map +1 -1
- package/dist/diff.d.ts +10 -0
- package/dist/diff.d.ts.map +1 -1
- package/dist/diff.js +117 -7
- package/dist/diff.js.map +1 -1
- package/dist/doctor.d.ts +42 -1
- package/dist/doctor.d.ts.map +1 -1
- package/dist/doctor.js +73 -7
- package/dist/doctor.js.map +1 -1
- package/dist/git.d.ts +41 -3
- package/dist/git.d.ts.map +1 -1
- package/dist/git.js +103 -7
- package/dist/git.js.map +1 -1
- package/dist/github.d.ts +92 -2
- package/dist/github.d.ts.map +1 -1
- package/dist/github.js +191 -20
- package/dist/github.js.map +1 -1
- package/dist/landing.d.ts +48 -0
- package/dist/landing.d.ts.map +1 -0
- package/dist/landing.js +93 -0
- package/dist/landing.js.map +1 -0
- package/dist/pkg.d.ts +9 -0
- package/dist/pkg.d.ts.map +1 -1
- package/dist/pkg.js +14 -0
- package/dist/pkg.js.map +1 -1
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +49 -26
- package/dist/report.js.map +1 -1
- package/dist/routes.d.ts +27 -0
- package/dist/routes.d.ts.map +1 -1
- package/dist/routes.js +98 -23
- package/dist/routes.js.map +1 -1
- package/dist/run.d.ts +88 -8
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +214 -26
- package/dist/run.js.map +1 -1
- package/dist/sameness.d.ts +91 -0
- package/dist/sameness.d.ts.map +1 -0
- package/dist/sameness.js +157 -0
- package/dist/sameness.js.map +1 -0
- package/dist/sessions.d.ts.map +1 -1
- package/dist/sessions.js +7 -1
- package/dist/sessions.js.map +1 -1
- package/dist/shift.d.ts +67 -0
- package/dist/shift.d.ts.map +1 -0
- package/dist/shift.js +184 -0
- package/dist/shift.js.map +1 -0
- package/dist/types.d.ts +67 -5
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/url.d.ts +12 -0
- package/dist/url.d.ts.map +1 -0
- package/dist/url.js +30 -0
- package/dist/url.js.map +1 -0
- package/package.json +1 -1
- package/skill/SKILL.md +40 -7
package/dist/doctor.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* exactly one sentence telling the human what to do.
|
|
5
5
|
*/
|
|
6
6
|
import { getBrowser, launchBrowserOrInstall } from './browser.js';
|
|
7
|
-
import { hostOf } from './
|
|
7
|
+
import { hostOf } from './url.js';
|
|
8
8
|
import { BrowserNotFoundError, NeedsHumanError, isVercelResponse } from './errors.js';
|
|
9
9
|
export { NeedsHumanError } from './errors.js';
|
|
10
10
|
const INSTALL_HINT = 'Run: npx playwright-core install chromium-headless-shell (or set PLAYWRIGHT_CHROMIUM_EXECUTABLE_PATH), then re-run.';
|
|
@@ -37,14 +37,79 @@ export async function launchHeadedBrowser() {
|
|
|
37
37
|
explainBrowserFailure(err);
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
const DEV_PORTS = [3000, 3001, 3002, 5173, 5174, 4173, 4321, 8080, 8000, 5000, 4200];
|
|
41
40
|
/**
|
|
42
|
-
*
|
|
41
|
+
* Ports worth asking, most likely first: the winner is the earliest that
|
|
42
|
+
* answers, so order is only ever a tie-break between two live servers.
|
|
43
|
+
*
|
|
44
|
+
* Order is not what keeps AirPlay out — `looksLikeDevServer` is, on every
|
|
45
|
+
* platform and at any position. 5000 sits last because on macOS it usually
|
|
46
|
+
* belongs to AirPlay Receiver rather than to a dev server, so it is the
|
|
47
|
+
* weakest guess in the list, not because being last protects anything. 7000,
|
|
48
|
+
* its sibling, is left out entirely: no framework defaults to it, so it has
|
|
49
|
+
* nothing to weigh against the noise.
|
|
43
50
|
*/
|
|
51
|
+
const DEV_PORTS = [3000, 3001, 3002, 5173, 5174, 4173, 4321, 8080, 8000, 4200, 5000];
|
|
52
|
+
/** An HTML document. `probeUrl` has already lowercased and dropped parameters. */
|
|
53
|
+
function isHtml(contentType) {
|
|
54
|
+
return contentType === 'text/html' || contentType === 'application/xhtml+xml';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Is this a dev server, or just something listening?
|
|
58
|
+
*
|
|
59
|
+
* A reachable socket used to be enough, and it is not: on macOS, AirPlay
|
|
60
|
+
* Receiver holds port 5000 and answers every request 403 with no body. The
|
|
61
|
+
* probe adopted it, the 403 was read as access control, and the run advised
|
|
62
|
+
* signing in to a system service — in place of "no dev server is running",
|
|
63
|
+
* which is the one thing that was true. It bit precisely when nothing else was
|
|
64
|
+
* listening, the case the message exists to describe.
|
|
65
|
+
*
|
|
66
|
+
* So the bar is a plausible *app* response, not a reachable port:
|
|
67
|
+
*
|
|
68
|
+
* - 401/403 never qualifies. That is a wall or a stranger; either way there is
|
|
69
|
+
* no site behind it to capture, and inferring a dev server from one is how
|
|
70
|
+
* the above happened.
|
|
71
|
+
* - A redirect does. Locale prefixes and trailing slashes make it ordinary, and
|
|
72
|
+
* there is no body to inspect, so the status is all there is to go on. If it
|
|
73
|
+
* leads somewhere sign-in shaped, `landing.ts` catches that at capture time
|
|
74
|
+
* with a message about the wall rather than about ports.
|
|
75
|
+
* - Anything else has to have served an HTML document. This deliberately keeps
|
|
76
|
+
* a 404 or a 500 that renders a page: a dev server with no `/` route, or one
|
|
77
|
+
* with a compile error, is still the dev server, and refusing it would send
|
|
78
|
+
* someone hunting for a server they are already running.
|
|
79
|
+
*/
|
|
80
|
+
export function looksLikeDevServer(result) {
|
|
81
|
+
const { status, contentType } = result;
|
|
82
|
+
if (status === null)
|
|
83
|
+
return false;
|
|
84
|
+
if (status === 401 || status === 403)
|
|
85
|
+
return false;
|
|
86
|
+
if (status >= 300 && status < 400)
|
|
87
|
+
return true;
|
|
88
|
+
return isHtml(contentType);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Probe the usual ports and say what was found *and* what was passed over.
|
|
92
|
+
*
|
|
93
|
+
* `doctor` reports the ignored ports because "nothing on the usual ports" is
|
|
94
|
+
* confusing when something is plainly listening on one of them.
|
|
95
|
+
*/
|
|
96
|
+
export async function scanDevServers(ports = DEV_PORTS) {
|
|
97
|
+
const results = await Promise.all(ports.map(async (port) => ({
|
|
98
|
+
port,
|
|
99
|
+
...(await probeUrl(`http://localhost:${port}/`, {}, { timeoutMs: 1500, redirect: 'manual' })),
|
|
100
|
+
})));
|
|
101
|
+
const scan = { url: null, ignored: [] };
|
|
102
|
+
for (const result of results) {
|
|
103
|
+
if (looksLikeDevServer(result))
|
|
104
|
+
scan.url ??= `http://localhost:${result.port}`;
|
|
105
|
+
else if (result.status !== null)
|
|
106
|
+
scan.ignored.push({ port: result.port, status: result.status });
|
|
107
|
+
}
|
|
108
|
+
return scan;
|
|
109
|
+
}
|
|
110
|
+
/** Find a running local dev server. Returns its base URL or null. */
|
|
44
111
|
export async function detectDevServer(ports = DEV_PORTS) {
|
|
45
|
-
|
|
46
|
-
const hit = results.find(r => r.status !== null);
|
|
47
|
-
return hit ? `http://localhost:${hit.p}` : null;
|
|
112
|
+
return (await scanDevServers(ports)).url;
|
|
48
113
|
}
|
|
49
114
|
/**
|
|
50
115
|
* Probe a base URL with the headers we will use for capture.
|
|
@@ -52,7 +117,8 @@ export async function detectDevServer(ports = DEV_PORTS) {
|
|
|
52
117
|
export async function probeUrl(url, headers = {}, options = {}) {
|
|
53
118
|
try {
|
|
54
119
|
const res = await fetch(url, { method: 'GET', headers, redirect: options.redirect ?? 'follow', signal: AbortSignal.timeout(options.timeoutMs ?? 10_000) });
|
|
55
|
-
|
|
120
|
+
const contentType = res.headers.get('content-type')?.split(';')[0].trim().toLowerCase();
|
|
121
|
+
return { status: res.status, vercel: isVercelResponse(res.headers), contentType: contentType || undefined };
|
|
56
122
|
}
|
|
57
123
|
catch {
|
|
58
124
|
return { status: null, vercel: false };
|
package/dist/doctor.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,oBAAoB,EAAmB,eAAe,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvG,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,YAAY,GAAG,uHAAuH,CAAC;AAE7I,SAAS,qBAAqB,CAAC,GAAY;IACzC,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;QACxC,MAAM,IAAI,eAAe,CACvB,GAAG,CAAC,SAAS;YACX,CAAC,CAAC,6CAA6C,YAAY,EAAE;YAC7D,CAAC,CAAC,kDAAkD,YAAY,EAAE,CACrE,CAAC;IACJ,CAAC;IACD,MAAM,GAAG,CAAC;AACZ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,CAAC;QACH,MAAM,UAAU,EAAE,CAAC;IACrB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,CAAC;QACH,OAAO,MAAM,sBAAsB,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;IAC3D,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,qBAAqB,CAAC,GAAG,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC;AAED,MAAM,SAAS,GAAG,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;AAErF
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../src/doctor.ts"],"names":[],"mappings":"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"}
|
package/dist/git.d.ts
CHANGED
|
@@ -15,9 +15,47 @@ export declare function resolveOwnerRepo(cwd?: string): string;
|
|
|
15
15
|
export declare function defaultBranch(cwd?: string): string;
|
|
16
16
|
/** Merge base between HEAD and the default branch, or null when unknown. */
|
|
17
17
|
export declare function mergeBase(cwd?: string): string | null;
|
|
18
|
+
/** True when this clone was made with --depth, so its history may be missing. */
|
|
19
|
+
export declare function isShallow(cwd?: string): boolean;
|
|
20
|
+
/** The branch this work forked from: the CI hint first, then origin's default. */
|
|
21
|
+
export declare function baseBranchName(cwd?: string): string;
|
|
18
22
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
23
|
+
* git's empty tree. Diffing against it lists every tracked file, which is the
|
|
24
|
+
* honest answer in a repository whose first commit has not happened yet.
|
|
21
25
|
*/
|
|
22
|
-
export declare
|
|
26
|
+
export declare const EMPTY_TREE = "4b825dc642cb6eb9a060e54bf8d69288fbee4904";
|
|
27
|
+
/** What a run diffs against, and how it was found. */
|
|
28
|
+
export interface BaseResolution {
|
|
29
|
+
/** The commit the working tree is compared with. */
|
|
30
|
+
sha: string;
|
|
31
|
+
source: 'explicit' | 'merge-base' | 'fetched' | 'head';
|
|
32
|
+
/** The base branch it came from, when one is known. */
|
|
33
|
+
branch?: string;
|
|
34
|
+
}
|
|
35
|
+
export interface ResolveBaseOptions {
|
|
36
|
+
/** A ref the caller named; it wins outright. */
|
|
37
|
+
explicit?: string;
|
|
38
|
+
/** Allow one network fetch to repair a shallow clone. Default true. */
|
|
39
|
+
fetch?: boolean;
|
|
40
|
+
log?: (msg: string) => void;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* The commit this branch forked from, or null when that cannot be established.
|
|
44
|
+
*
|
|
45
|
+
* Null is a real answer and callers must treat it as one: diffing against HEAD
|
|
46
|
+
* instead reports only uncommitted work, so a branch whose changes are
|
|
47
|
+
* committed comes back as "nothing changed" — the wrong answer, stated
|
|
48
|
+
* confidently.
|
|
49
|
+
*/
|
|
50
|
+
export declare function resolveBase(cwd?: string, opts?: ResolveBaseOptions): BaseResolution | null;
|
|
51
|
+
/** `resolveBase`, with the one sentence a human needs when it comes back null. */
|
|
52
|
+
export declare function requireBase(cwd: string, opts?: ResolveBaseOptions): BaseResolution;
|
|
53
|
+
/**
|
|
54
|
+
* Files changed relative to `diffTarget`, plus anything staged, unstaged, or
|
|
55
|
+
* untracked. Paths are relative to the repo root.
|
|
56
|
+
*
|
|
57
|
+
* The target is required: working it out is `resolveBase`'s job, because
|
|
58
|
+
* guessing it wrong here is silent and reports an empty diff.
|
|
59
|
+
*/
|
|
60
|
+
export declare function changedFiles(cwd: string, diffTarget: string): string[];
|
|
23
61
|
//# sourceMappingURL=git.d.ts.map
|
package/dist/git.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,GAAG,SAAgB,GAAG,MAAM,CAE/D;AAUD,wBAAgB,QAAQ,CAAC,GAAG,SAAgB,GAAG,MAAM,CAIpD;AAED,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGzD;AAED,wBAAgB,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEnD;AAED;;;GAGG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAK/D;AAED,wBAAgB,gBAAgB,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CASrD;AAED,+DAA+D;AAC/D,wBAAgB,aAAa,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CASlD;AAED,4EAA4E;AAC5E,wBAAgB,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAErD;AAOD,iFAAiF;AACjF,wBAAgB,SAAS,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAE/C;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAKnD;AAyBD;;;GAGG;AACH,eAAO,MAAM,UAAU,6CAA6C,CAAC;AAErE,sDAAsD;AACtD,MAAM,WAAW,cAAc;IAC7B,oDAAoD;IACpD,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,GAAG,YAAY,GAAG,SAAS,GAAG,MAAM,CAAC;IACvD,uDAAuD;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,gDAAgD;IAChD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uEAAuE;IACvE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;CAC7B;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,GAAG,SAAgB,EAAE,IAAI,GAAE,kBAAuB,GAAG,cAAc,GAAG,IAAI,CA8BrG;AAED,kFAAkF;AAClF,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,kBAAuB,GAAG,cAAc,CAStF;AAMD;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,EAAE,CAStE"}
|
package/dist/git.js
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
* Thin git helpers. Every call is a single short-lived subprocess.
|
|
3
3
|
*/
|
|
4
4
|
import { execFileSync } from 'child_process';
|
|
5
|
+
import { NeedsHumanError } from './errors.js';
|
|
5
6
|
export function git(args, cwd = process.cwd()) {
|
|
6
7
|
return execFileSync('git', args, { cwd, encoding: 'utf-8', stdio: ['ignore', 'pipe', 'pipe'] }).trim();
|
|
7
8
|
}
|
|
@@ -62,21 +63,116 @@ export function defaultBranch(cwd) {
|
|
|
62
63
|
}
|
|
63
64
|
/** Merge base between HEAD and the default branch, or null when unknown. */
|
|
64
65
|
export function mergeBase(cwd) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
return mergeBaseWith(defaultBranch(cwd), cwd);
|
|
67
|
+
}
|
|
68
|
+
function mergeBaseWith(branch, cwd) {
|
|
69
|
+
return tryGit(['merge-base', `origin/${branch}`, 'HEAD'], cwd)
|
|
70
|
+
|| tryGit(['merge-base', branch, 'HEAD'], cwd);
|
|
71
|
+
}
|
|
72
|
+
/** True when this clone was made with --depth, so its history may be missing. */
|
|
73
|
+
export function isShallow(cwd) {
|
|
74
|
+
return tryGit(['rev-parse', '--is-shallow-repository'], cwd) === 'true';
|
|
75
|
+
}
|
|
76
|
+
/** The branch this work forked from: the CI hint first, then origin's default. */
|
|
77
|
+
export function baseBranchName(cwd) {
|
|
78
|
+
// GitHub Actions sets this on pull_request events, and it is more reliable
|
|
79
|
+
// than origin/HEAD in a checkout that has neither.
|
|
80
|
+
const env = process.env.GITHUB_BASE_REF?.trim();
|
|
81
|
+
return env || defaultBranch(cwd);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Make the base branch reachable in a clone that does not have it.
|
|
85
|
+
*
|
|
86
|
+
* Sandbox and web environments check a branch out with `--depth 1
|
|
87
|
+
* --single-branch`, which leaves no origin/<base> ref and no shared history to
|
|
88
|
+
* fork from. Widen in three steps, stopping as soon as a merge base appears, so
|
|
89
|
+
* the common case costs one shallow fetch rather than the whole history.
|
|
90
|
+
*/
|
|
91
|
+
function fetchBase(branch, cwd) {
|
|
92
|
+
const refspec = `+refs/heads/${branch}:refs/remotes/origin/${branch}`;
|
|
93
|
+
const attempts = [
|
|
94
|
+
['fetch', '--no-tags', '--depth=50', 'origin', refspec],
|
|
95
|
+
['fetch', '--no-tags', '--deepen=200', 'origin', refspec],
|
|
96
|
+
['fetch', '--no-tags', '--unshallow', 'origin', refspec],
|
|
97
|
+
];
|
|
98
|
+
for (const args of attempts) {
|
|
99
|
+
// A deepen or unshallow against a complete clone is an error, not a result.
|
|
100
|
+
if (tryGit(args, cwd) === null)
|
|
101
|
+
continue;
|
|
102
|
+
if (mergeBaseWith(branch, cwd))
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* git's empty tree. Diffing against it lists every tracked file, which is the
|
|
109
|
+
* honest answer in a repository whose first commit has not happened yet.
|
|
110
|
+
*/
|
|
111
|
+
export const EMPTY_TREE = '4b825dc642cb6eb9a060e54bf8d69288fbee4904';
|
|
112
|
+
/**
|
|
113
|
+
* The commit this branch forked from, or null when that cannot be established.
|
|
114
|
+
*
|
|
115
|
+
* Null is a real answer and callers must treat it as one: diffing against HEAD
|
|
116
|
+
* instead reports only uncommitted work, so a branch whose changes are
|
|
117
|
+
* committed comes back as "nothing changed" — the wrong answer, stated
|
|
118
|
+
* confidently.
|
|
119
|
+
*/
|
|
120
|
+
export function resolveBase(cwd = process.cwd(), opts = {}) {
|
|
121
|
+
if (opts.explicit) {
|
|
122
|
+
const sha = tryGit(['rev-parse', '--verify', '--quiet', `${opts.explicit}^{commit}`], cwd);
|
|
123
|
+
if (!sha)
|
|
124
|
+
throw new NeedsHumanError(`--base ${opts.explicit} is not a commit in this repository.`);
|
|
125
|
+
return { sha, source: 'explicit' };
|
|
126
|
+
}
|
|
127
|
+
// No commits yet: everything in the tree is new, and there is nothing to
|
|
128
|
+
// fork from. Not a failure — a repository at its very beginning.
|
|
129
|
+
if (!headSha(cwd))
|
|
130
|
+
return { sha: EMPTY_TREE, source: 'head' };
|
|
131
|
+
const branch = baseBranchName(cwd);
|
|
132
|
+
const local = mergeBaseWith(branch, cwd);
|
|
133
|
+
if (local)
|
|
134
|
+
return { sha: local, source: 'merge-base', branch };
|
|
135
|
+
if (opts.fetch !== false) {
|
|
136
|
+
opts.log?.(`No local history for ${branch}; fetching it to see what this branch changed.`);
|
|
137
|
+
if (fetchBase(branch, cwd)) {
|
|
138
|
+
const sha = mergeBaseWith(branch, cwd);
|
|
139
|
+
if (sha)
|
|
140
|
+
return { sha, source: 'fetched', branch };
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// Standing on the base branch with nothing to fork from: the change under
|
|
144
|
+
// review is whatever is uncommitted, which is what diffing HEAD reports.
|
|
145
|
+
if (currentBranch(cwd) === branch) {
|
|
146
|
+
const head = headSha(cwd);
|
|
147
|
+
if (head)
|
|
148
|
+
return { sha: head, source: 'head', branch };
|
|
149
|
+
}
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
/** `resolveBase`, with the one sentence a human needs when it comes back null. */
|
|
153
|
+
export function requireBase(cwd, opts = {}) {
|
|
154
|
+
const base = resolveBase(cwd, opts);
|
|
155
|
+
if (base)
|
|
156
|
+
return base;
|
|
157
|
+
const branch = baseBranchName(cwd);
|
|
158
|
+
throw new NeedsHumanError(`Cannot tell what this branch changed: this clone shares no history with ${branch}` +
|
|
159
|
+
`${isShallow(cwd) ? ' (it is a shallow checkout)' : ''}. ` +
|
|
160
|
+
`Run \`git fetch origin ${branch}\`, or pass --base <ref>.`);
|
|
68
161
|
}
|
|
69
162
|
function lines(out) {
|
|
70
163
|
return out ? out.split('\n').map(l => l.trim()).filter(Boolean) : [];
|
|
71
164
|
}
|
|
72
165
|
/**
|
|
73
|
-
* Files changed
|
|
74
|
-
*
|
|
166
|
+
* Files changed relative to `diffTarget`, plus anything staged, unstaged, or
|
|
167
|
+
* untracked. Paths are relative to the repo root.
|
|
168
|
+
*
|
|
169
|
+
* The target is required: working it out is `resolveBase`'s job, because
|
|
170
|
+
* guessing it wrong here is silent and reports an empty diff.
|
|
75
171
|
*/
|
|
76
|
-
export function changedFiles(cwd
|
|
172
|
+
export function changedFiles(cwd, diffTarget) {
|
|
77
173
|
const files = new Set();
|
|
78
174
|
const root = repoRoot(cwd);
|
|
79
|
-
const target = diffTarget
|
|
175
|
+
const target = diffTarget;
|
|
80
176
|
lines(tryGit(['diff', '--name-only', target], root)).forEach(f => files.add(f));
|
|
81
177
|
lines(tryGit(['diff', '--name-only', '--cached'], root)).forEach(f => files.add(f));
|
|
82
178
|
lines(tryGit(['diff', '--name-only'], root)).forEach(f => files.add(f));
|
package/dist/git.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"git.js","sourceRoot":"","sources":["../src/git.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,UAAU,GAAG,CAAC,IAAc,EAAE,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IACrD,OAAO,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;AACzG,CAAC;AAED,SAAS,MAAM,CAAC,IAAc,EAAE,GAAY;IAC1C,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,QAAQ,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE;IAC1C,MAAM,IAAI,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,iBAAiB,CAAC,EAAE,GAAG,CAAC,CAAC;IAC3D,IAAI,CAAC,IAAI;QAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,MAAM,CAAC,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,cAAc,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;IAC7D,OAAO,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACtC,CAAC;AAED,MAAM,UAAU,OAAO,CAAC,GAAY;IAClC,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,SAAiB;IAC9C,MAAM,GAAG,GAAG,SAAS,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAC5E,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC;IACvB,MAAM,QAAQ,GAAG,SAAS,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;IACpE,OAAO,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AACvC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,GAAY;IAC3C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IACjE,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC;IACpB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,QAAQ,CAAC,EAAE,GAAG,CAAC,CAAC;IACzD,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAChD,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,KAAK,CAAC,6DAA6D,CAAC,CAAC;IACjF,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,+DAA+D;AAC/D,MAAM,UAAU,aAAa,CAAC,GAAY;IACxC,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,cAAc,EAAE,SAAS,EAAE,0BAA0B,CAAC,EAAE,GAAG,CAAC,CAAC;IACjF,IAAI,GAAG;QAAE,OAAO,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,CAAC;QACzB,cAAc,EAAE,2BAA2B;QAC3C,0BAA0B,EAAE,4BAA4B,EAAE,iBAAiB,EAAE,mBAAmB;KACjG,EAAE,GAAG,CAAC,CAAC,CAAC;IACT,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACjD,OAAO,KAAK,IAAI,MAAM,CAAC;AACzB,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,aAAa,CAAC,aAAa,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;AAChD,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,GAAY;IACjD,OAAO,MAAM,CAAC,CAAC,YAAY,EAAE,UAAU,MAAM,EAAE,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC;WACzD,MAAM,CAAC,CAAC,YAAY,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,CAAC,CAAC;AACnD,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,SAAS,CAAC,GAAY;IACpC,OAAO,MAAM,CAAC,CAAC,WAAW,EAAE,yBAAyB,CAAC,EAAE,GAAG,CAAC,KAAK,MAAM,CAAC;AAC1E,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,2EAA2E;IAC3E,mDAAmD;IACnD,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO,GAAG,IAAI,aAAa,CAAC,GAAG,CAAC,CAAC;AACnC,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,SAAS,CAAC,MAAc,EAAE,GAAY;IAC7C,MAAM,OAAO,GAAG,eAAe,MAAM,wBAAwB,MAAM,EAAE,CAAC;IACtE,MAAM,QAAQ,GAAG;QACf,CAAC,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,OAAO,CAAC;QACvD,CAAC,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,QAAQ,EAAE,OAAO,CAAC;QACzD,CAAC,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,QAAQ,EAAE,OAAO,CAAC;KACzD,CAAC;IACF,KAAK,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;QAC5B,4EAA4E;QAC5E,IAAI,MAAM,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,IAAI;YAAE,SAAS;QACzC,IAAI,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC;YAAE,OAAO,IAAI,CAAC;IAC9C,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,0CAA0C,CAAC;AAmBrE;;;;;;;GAOG;AACH,MAAM,UAAU,WAAW,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,EAAE,OAA2B,EAAE;IAC5E,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAClB,MAAM,GAAG,GAAG,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,QAAQ,WAAW,CAAC,EAAE,GAAG,CAAC,CAAC;QAC3F,IAAI,CAAC,GAAG;YAAE,MAAM,IAAI,eAAe,CAAC,UAAU,IAAI,CAAC,QAAQ,sCAAsC,CAAC,CAAC;QACnG,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACrC,CAAC;IAED,yEAAyE;IACzE,iEAAiE;IACjE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,GAAG,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IAE9D,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,KAAK,GAAG,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACzC,IAAI,KAAK;QAAE,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,CAAC;IAE/D,IAAI,IAAI,CAAC,KAAK,KAAK,KAAK,EAAE,CAAC;QACzB,IAAI,CAAC,GAAG,EAAE,CAAC,wBAAwB,MAAM,gDAAgD,CAAC,CAAC;QAC3F,IAAI,SAAS,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,aAAa,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;YACvC,IAAI,GAAG;gBAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,CAAC;QACrD,CAAC;IACH,CAAC;IAED,0EAA0E;IAC1E,yEAAyE;IACzE,IAAI,aAAa,CAAC,GAAG,CAAC,KAAK,MAAM,EAAE,CAAC;QAClC,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,IAAI;YAAE,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;IACzD,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,OAA2B,EAAE;IACpE,MAAM,IAAI,GAAG,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IACpC,IAAI,IAAI;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,MAAM,GAAG,cAAc,CAAC,GAAG,CAAC,CAAC;IACnC,MAAM,IAAI,eAAe,CACvB,2EAA2E,MAAM,EAAE;QACnF,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC,CAAC,EAAE,IAAI;QAC1D,0BAA0B,MAAM,2BAA2B,CAC5D,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,GAAkB;IAC/B,OAAO,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACvE,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,GAAW,EAAE,UAAkB;IAC1D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC3B,MAAM,MAAM,GAAG,UAAU,CAAC;IAC1B,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAChF,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpF,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,aAAa,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACxE,KAAK,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,oBAAoB,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC"}
|
package/dist/github.d.ts
CHANGED
|
@@ -9,15 +9,90 @@
|
|
|
9
9
|
*/
|
|
10
10
|
export { GitHubError } from './errors.js';
|
|
11
11
|
export declare const API_BASE: string;
|
|
12
|
+
/** Where a token came from. Which one it is decides how a rejection is fixed. */
|
|
13
|
+
export type TokenSource = 'GH_TOKEN' | 'GITHUB_TOKEN' | 'gh';
|
|
14
|
+
export interface FoundToken {
|
|
15
|
+
token: string;
|
|
16
|
+
source: TokenSource;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The token this run will use, and where it came from.
|
|
20
|
+
*
|
|
21
|
+
* The source is not bookkeeping: the env vars take precedence over the `gh`
|
|
22
|
+
* CLI, so advice aimed at the wrong one is advice that cannot work. Someone
|
|
23
|
+
* whose `GH_TOKEN` is refused gains nothing from `gh auth login`, because the
|
|
24
|
+
* variable still wins on the next run.
|
|
25
|
+
*/
|
|
26
|
+
export declare function findToken(): FoundToken | null;
|
|
12
27
|
export declare function getToken(): string | null;
|
|
13
|
-
/** A token, or the one sentence telling the human how to get one. */
|
|
14
|
-
export declare function requireToken(purpose?: string):
|
|
28
|
+
/** A token and its source, or the one sentence telling the human how to get one. */
|
|
29
|
+
export declare function requireToken(purpose?: string): FoundToken;
|
|
15
30
|
export declare class GitHub {
|
|
16
31
|
private readonly token;
|
|
17
32
|
private readonly base;
|
|
18
33
|
constructor(token: string, base?: string);
|
|
19
34
|
request<T = any>(method: string, path: string, body?: unknown): Promise<T>;
|
|
20
35
|
}
|
|
36
|
+
/** What one write attempt established about this token's access to a repository. */
|
|
37
|
+
export type WriteAccess =
|
|
38
|
+
/** The token wrote an object. It may still be refused a ref by a ruleset. */
|
|
39
|
+
{
|
|
40
|
+
writable: true;
|
|
41
|
+
}
|
|
42
|
+
/** GitHub refused the write. Nothing this run publishes will land. */
|
|
43
|
+
| {
|
|
44
|
+
writable: false;
|
|
45
|
+
reason: 'rejected';
|
|
46
|
+
}
|
|
47
|
+
/** Nobody answered, or answered something that is not about access. */
|
|
48
|
+
| {
|
|
49
|
+
writable: false;
|
|
50
|
+
reason: 'unknown';
|
|
51
|
+
detail: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Can this token write to `ownerRepo`?
|
|
55
|
+
*
|
|
56
|
+
* `getToken()` checks that a token exists, which is a different question. A
|
|
57
|
+
* GitHub Actions job that maps `secrets.GITHUB_TOKEN` gets one that reads
|
|
58
|
+
* everything this tool reads and writes nothing: measured on this repository,
|
|
59
|
+
* `GET /repos/juangadm/pre-post` answers 200 with `permissions.push: false`
|
|
60
|
+
* and `POST .../git/blobs` answers 403. Those reads are the ones `pr` makes
|
|
61
|
+
* before it captures, so without this the run spends its screenshots first and
|
|
62
|
+
* discovers the refusal after.
|
|
63
|
+
*
|
|
64
|
+
* The probe is the first write `publishAssets` makes, on the one piece of
|
|
65
|
+
* content that cannot add anything: the empty blob already exists in every
|
|
66
|
+
* repository, so a successful call stores nothing new. A read cannot stand in
|
|
67
|
+
* for it — `permissions.push` describes the account's access to the repository,
|
|
68
|
+
* not the scopes the token carries, so it can report `true` for a credential
|
|
69
|
+
* the write still refuses. That is the confident all-clear this check exists to
|
|
70
|
+
* avoid, which is why it writes.
|
|
71
|
+
*
|
|
72
|
+
* What it proves is bounded: the token may write objects. Creating the assets
|
|
73
|
+
* *ref* is a separate permission a ruleset can refuse, so `writable: true` is
|
|
74
|
+
* "not this failure", never "the publish will work".
|
|
75
|
+
*/
|
|
76
|
+
export declare function checkWriteAccess(gh: GitHub, ownerRepo: string): Promise<WriteAccess>;
|
|
77
|
+
/**
|
|
78
|
+
* The one thing to do about a token that cannot publish.
|
|
79
|
+
*
|
|
80
|
+
* It follows the credential that was actually chosen, not just the
|
|
81
|
+
* environment. Being inside a runner does not make `permissions:` the fix: a
|
|
82
|
+
* workflow that sets `GH_TOKEN` to a PAT is refused by that PAT, and rewriting
|
|
83
|
+
* the job's permissions changes only the `GITHUB_TOKEN` the run never reaches.
|
|
84
|
+
* The same holds the other way round on a laptop, where `gh auth login` cannot
|
|
85
|
+
* help while an env var is shadowing it.
|
|
86
|
+
*
|
|
87
|
+
* The runner sentence names both permissions, though only `contents` is what
|
|
88
|
+
* this check tested. Naming `contents` alone would be advice that fails on its
|
|
89
|
+
* own terms: a `permissions:` block sets every scope it omits to none, so
|
|
90
|
+
* following it leaves a token that uploads the screenshots and is then refused
|
|
91
|
+
* the PR description — measured on this repository, `PATCH /pulls/23` answers
|
|
92
|
+
* 403 with only `contents: write` and 200 with `pull-requests: write` beside it.
|
|
93
|
+
* A second trip through a full capture is not worth the tighter sentence.
|
|
94
|
+
*/
|
|
95
|
+
export declare function cannotPublishHint(ownerRepo: string, source: TokenSource): string;
|
|
21
96
|
export interface PullRequestRef {
|
|
22
97
|
number: number;
|
|
23
98
|
html_url: string;
|
|
@@ -27,6 +102,7 @@ export interface PullRequestRef {
|
|
|
27
102
|
};
|
|
28
103
|
base: {
|
|
29
104
|
ref: string;
|
|
105
|
+
sha: string;
|
|
30
106
|
};
|
|
31
107
|
title: string;
|
|
32
108
|
}
|
|
@@ -60,6 +136,20 @@ export interface CommentResult {
|
|
|
60
136
|
* Create or update the single pre-post comment on a PR, identified by `marker`.
|
|
61
137
|
*/
|
|
62
138
|
export declare function upsertStickyComment(gh: GitHub, ownerRepo: string, prNumber: number, body: string, marker: string): Promise<CommentResult>;
|
|
139
|
+
export interface DescriptionResult {
|
|
140
|
+
html_url: string;
|
|
141
|
+
/** False when the PR body could not be edited and nothing was written. */
|
|
142
|
+
updated: boolean;
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Write `body` into a marked block in the PR description, replacing the block
|
|
146
|
+
* from a previous run. The description is where reviewers look first, so this
|
|
147
|
+
* is preferred over a comment.
|
|
148
|
+
*
|
|
149
|
+
* Returns updated: false when the token cannot edit the PR (a fork, or no write
|
|
150
|
+
* access), so the caller can fall back to a comment instead of failing.
|
|
151
|
+
*/
|
|
152
|
+
export declare function upsertPrDescription(gh: GitHub, ownerRepo: string, prNumber: number, body: string, marker: string): Promise<DescriptionResult>;
|
|
63
153
|
export interface PruneResult {
|
|
64
154
|
removed: string[];
|
|
65
155
|
kept: string[];
|
package/dist/github.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE1C,eAAO,MAAM,QAAQ,QAAyD,CAAC;AAE/E,wBAAgB,QAAQ,IAAI,MAAM,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"github.d.ts","sourceRoot":"","sources":["../src/github.ts"],"names":[],"mappings":"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"}
|