@bensandee/forgejo-cli 0.6.0 → 0.6.2
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 +1 -1
- package/dist/bin.mjs +143 -230
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,7 +48,7 @@ command takes `--json`, which prints exactly one JSON document, failures include
|
|
|
48
48
|
| `pr:list` | List a repository's pull requests |
|
|
49
49
|
| `commit:status` | Read the status checks for a commit SHA, branch, tag or git ref |
|
|
50
50
|
| `issue:*` | `view`, `list`, `comment`, `create`, `update`, `download`, `label`, `unlabel`, `set-labels`, `close`, `reopen` |
|
|
51
|
-
| `pr:create` | Push the current branch and open a pull request, deriving the title and body when none is given
|
|
51
|
+
| `pr:create` | Push the current branch and open a pull request, deriving the title and body when none is given; reports no closed-issue claims, which `bst pr:create` does |
|
|
52
52
|
| `pr:update` | Push the current branch and update its open pull request |
|
|
53
53
|
| `branch:list` | List a repository's branches |
|
|
54
54
|
| `branch:delete` | Delete a branch through the API; reports the forge's reason when it refuses |
|
package/dist/bin.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { FatalError, TransientError, UnexpectedError, describeError, redact, red
|
|
|
6
6
|
import { z } from "zod";
|
|
7
7
|
import { defineCommand, renderUsage, runCommand, runMain } from "citty";
|
|
8
8
|
import { execFileSync, spawn } from "node:child_process";
|
|
9
|
-
|
|
9
|
+
// ../cli-kit/src/json.ts
|
|
10
10
|
function resolveJsonMode(rawArgs) {
|
|
11
11
|
if (!rawArgs.some(requestsJson)) return false;
|
|
12
12
|
if (rawArgs.includes("--help") || rawArgs.includes("-h")) return false;
|
|
@@ -100,8 +100,7 @@ function classifyThrown(error, verbose) {
|
|
|
100
100
|
detail
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
|
|
104
|
-
//#region ../cli-kit/src/env-file.ts
|
|
103
|
+
// ../cli-kit/src/env-file.ts
|
|
105
104
|
const ENV_FILE_VAR = "BST_ENV_FILE";
|
|
106
105
|
function loadEnvFileFromEnv() {
|
|
107
106
|
const raw = process.env[ENV_FILE_VAR]?.trim();
|
|
@@ -158,11 +157,10 @@ function loadEnvFileForBin(rawArgs, bin, io = processIo) {
|
|
|
158
157
|
return io.exit(1);
|
|
159
158
|
}
|
|
160
159
|
}
|
|
161
|
-
|
|
162
|
-
//#region src/version.ts
|
|
160
|
+
// src/version.ts
|
|
163
161
|
const parsed = z.object({ version: z.string() }).safeParse({
|
|
164
162
|
name: "@bensandee/forgejo-cli",
|
|
165
|
-
version: "0.6.
|
|
163
|
+
version: "0.6.2",
|
|
166
164
|
description: "bst-fj: Forgejo API commands without the rest of bst",
|
|
167
165
|
license: "MIT",
|
|
168
166
|
repository: {
|
|
@@ -203,14 +201,12 @@ const parsed = z.object({ version: z.string() }).safeParse({
|
|
|
203
201
|
});
|
|
204
202
|
if (!parsed.success) throw new UnexpectedError(`@bensandee/forgejo-cli's package.json has no string version.`);
|
|
205
203
|
const BST_FJ_VERSION = parsed.data.version;
|
|
206
|
-
|
|
207
|
-
//#region src/env-file-preload.ts
|
|
204
|
+
// src/env-file-preload.ts
|
|
208
205
|
const envFileLoad = loadEnvFileForBin(process.argv.slice(2), {
|
|
209
206
|
name: "bst-fj",
|
|
210
207
|
version: BST_FJ_VERSION
|
|
211
208
|
});
|
|
212
|
-
|
|
213
|
-
//#region ../cli-kit/src/logger.ts
|
|
209
|
+
// ../cli-kit/src/logger.ts
|
|
214
210
|
const RANK = {
|
|
215
211
|
error: 0,
|
|
216
212
|
warn: 1,
|
|
@@ -310,8 +306,7 @@ function createLogger(options = {}) {
|
|
|
310
306
|
});
|
|
311
307
|
}
|
|
312
308
|
const rootLogger = createLogger();
|
|
313
|
-
|
|
314
|
-
//#region ../cli-kit/src/flags.ts
|
|
309
|
+
// ../cli-kit/src/flags.ts
|
|
315
310
|
const UNIVERSAL_FLAGS = [
|
|
316
311
|
"--help",
|
|
317
312
|
"-h",
|
|
@@ -648,8 +643,7 @@ function parseLimitFlag(raw) {
|
|
|
648
643
|
if (!Number.isInteger(value) || value < 1) throw new FatalError(`--limit must be a positive integer, got "${raw}"`);
|
|
649
644
|
return value;
|
|
650
645
|
}
|
|
651
|
-
|
|
652
|
-
//#region ../cli-kit/src/output.ts
|
|
646
|
+
// ../cli-kit/src/output.ts
|
|
653
647
|
const stdout = (msg) => console.log(msg);
|
|
654
648
|
function initialState() {
|
|
655
649
|
return {
|
|
@@ -712,8 +706,7 @@ function flushJsonOutput() {
|
|
|
712
706
|
function jsonDocumentWritten() {
|
|
713
707
|
return state.wrote;
|
|
714
708
|
}
|
|
715
|
-
|
|
716
|
-
//#region ../cli-kit/src/path-probe.ts
|
|
709
|
+
// ../cli-kit/src/path-probe.ts
|
|
717
710
|
function probeCliPath(value) {
|
|
718
711
|
try {
|
|
719
712
|
const stat = statSync(value, { throwIfNoEntry: false });
|
|
@@ -723,8 +716,7 @@ function probeCliPath(value) {
|
|
|
723
716
|
return "missing";
|
|
724
717
|
}
|
|
725
718
|
}
|
|
726
|
-
|
|
727
|
-
//#region ../cli-kit/src/run.ts
|
|
719
|
+
// ../cli-kit/src/run.ts
|
|
728
720
|
function classifyWithHook(error, verbose, hook) {
|
|
729
721
|
const classified = classifyThrown(error, verbose);
|
|
730
722
|
const worded = hook?.(error);
|
|
@@ -878,8 +870,7 @@ const log = {
|
|
|
878
870
|
current.debug(message);
|
|
879
871
|
}
|
|
880
872
|
};
|
|
881
|
-
|
|
882
|
-
//#region ../forgejo/src/connection.ts
|
|
873
|
+
// ../forgejo/src/connection.ts
|
|
883
874
|
function parseGitUrl(urlStr) {
|
|
884
875
|
try {
|
|
885
876
|
const url = new URL(urlStr);
|
|
@@ -1006,14 +997,12 @@ function normalizeGitUrl(raw) {
|
|
|
1006
997
|
return null;
|
|
1007
998
|
}
|
|
1008
999
|
}
|
|
1009
|
-
|
|
1010
|
-
//#region src/describe-forge-error.ts
|
|
1000
|
+
// src/describe-forge-error.ts
|
|
1011
1001
|
function describeForgeError(error) {
|
|
1012
1002
|
if (error instanceof RepoTargetEmptyError) return "--repo was given with no repository URL (expected e.g. https://host/owner/repo).";
|
|
1013
1003
|
if (error instanceof RepoTargetMismatchError) return `--repo disagrees with the issue URL: --repo names ${error.given}, the issue URL names ${error.fromReference}.`;
|
|
1014
1004
|
}
|
|
1015
|
-
|
|
1016
|
-
//#region ../forgejo/src/fetch-retry.ts
|
|
1005
|
+
// ../forgejo/src/fetch-retry.ts
|
|
1017
1006
|
const DEFAULT_RETRY_POLICY = {
|
|
1018
1007
|
attempts: 5,
|
|
1019
1008
|
baseDelayMs: 250,
|
|
@@ -1070,13 +1059,11 @@ function fetchWithRetry(fetchImpl, policy = DEFAULT_RETRY_POLICY, defaultTimeout
|
|
|
1070
1059
|
function createForgeFetcher(policy = DEFAULT_RETRY_POLICY) {
|
|
1071
1060
|
return { fetch: fetchWithRetry((input, init) => globalThis.fetch(input, init), policy) };
|
|
1072
1061
|
}
|
|
1073
|
-
|
|
1074
|
-
//#region src/fetcher.ts
|
|
1062
|
+
// src/fetcher.ts
|
|
1075
1063
|
function cliFetcher() {
|
|
1076
1064
|
return createForgeFetcher();
|
|
1077
1065
|
}
|
|
1078
|
-
|
|
1079
|
-
//#region ../forgejo/src/errors.ts
|
|
1066
|
+
// ../forgejo/src/errors.ts
|
|
1080
1067
|
var ForgeAccessError = class extends FatalError {};
|
|
1081
1068
|
function authHeaders(conn) {
|
|
1082
1069
|
return { Authorization: `token ${conn.token}` };
|
|
@@ -1173,8 +1160,7 @@ async function throwForgejoFailure(res, operation, notFoundMessage) {
|
|
|
1173
1160
|
if (res.status === 410) throw new FatalError(`${message}\nForgejo returned 410 Gone -- issues are likely disabled on this repository; retrying will not help.`);
|
|
1174
1161
|
throw new TransientError(message);
|
|
1175
1162
|
}
|
|
1176
|
-
|
|
1177
|
-
//#region ../forgejo/src/commit-status.ts
|
|
1163
|
+
// ../forgejo/src/commit-status.ts
|
|
1178
1164
|
const CombinedStatusSchema = z.object({
|
|
1179
1165
|
state: z.string(),
|
|
1180
1166
|
statuses: z.array(z.unknown())
|
|
@@ -1297,6 +1283,7 @@ z.array(z.unknown());
|
|
|
1297
1283
|
function branchNotFoundMessage(conn, branch) {
|
|
1298
1284
|
return `Branch ${branch} not found in ${conn.repository}`;
|
|
1299
1285
|
}
|
|
1286
|
+
z.object({ full_name: z.string() });
|
|
1300
1287
|
async function getBranchHeadSha(executor, conn, branch) {
|
|
1301
1288
|
const url = `${repoBase(conn)}/branches/${encodeURIComponent(branch)}`;
|
|
1302
1289
|
const res = await executor.fetch(url, { headers: authHeaders(conn) });
|
|
@@ -1318,8 +1305,7 @@ async function branchExists(executor, conn, branch) {
|
|
|
1318
1305
|
}, branchNotFoundMessage(conn, branch));
|
|
1319
1306
|
return true;
|
|
1320
1307
|
}
|
|
1321
|
-
|
|
1322
|
-
//#region ../cli-kit/src/git.ts
|
|
1308
|
+
// ../cli-kit/src/git.ts
|
|
1323
1309
|
const BRANCH_REF_PREFIX = "refs/heads/";
|
|
1324
1310
|
const ORIGIN_READ_TIMEOUT_MS = 5e3;
|
|
1325
1311
|
function defaultGitRunner(args, cwd, options) {
|
|
@@ -1382,8 +1368,7 @@ function readPackageRepositoryUrl(cwd) {
|
|
|
1382
1368
|
if (!repo) return null;
|
|
1383
1369
|
return typeof repo === "string" ? repo : repo.url;
|
|
1384
1370
|
}
|
|
1385
|
-
|
|
1386
|
-
//#region src/connection.ts
|
|
1371
|
+
// src/connection.ts
|
|
1387
1372
|
function resolveRepoUrl(cwd) {
|
|
1388
1373
|
return resolveRepoUrlFrom(() => readOriginUrl(cwd), () => readPackageRepositoryUrl(cwd));
|
|
1389
1374
|
}
|
|
@@ -1405,8 +1390,7 @@ function requireForgejoTarget(cwd, target, githubRefusal, env = process.env) {
|
|
|
1405
1390
|
if (conn === null) throw new FatalError(githubRefusal);
|
|
1406
1391
|
return conn;
|
|
1407
1392
|
}
|
|
1408
|
-
|
|
1409
|
-
//#region ../forgejo/src/check-poll.ts
|
|
1393
|
+
// ../forgejo/src/check-poll.ts
|
|
1410
1394
|
function classifyBaseStatus(checks) {
|
|
1411
1395
|
if (!checks.parsed) return "unparseable";
|
|
1412
1396
|
if (checks.contexts.length === 0) return "no-status";
|
|
@@ -1493,16 +1477,14 @@ function renderCheckLine(check) {
|
|
|
1493
1477
|
if (check.verdict === "red" && check.targetUrl !== null) line += ` (${check.targetUrl})`;
|
|
1494
1478
|
return line;
|
|
1495
1479
|
}
|
|
1496
|
-
|
|
1497
|
-
//#region ../cli-kit/src/env-override.ts
|
|
1480
|
+
// ../cli-kit/src/env-override.ts
|
|
1498
1481
|
function envMsOverride(raw, productionMs) {
|
|
1499
1482
|
if (raw === void 0) return productionMs;
|
|
1500
1483
|
const parsed = Number(raw.trim());
|
|
1501
1484
|
if (!Number.isSafeInteger(parsed) || parsed <= 0) return productionMs;
|
|
1502
1485
|
return Math.min(parsed, productionMs);
|
|
1503
1486
|
}
|
|
1504
|
-
|
|
1505
|
-
//#region src/poll-timings.ts
|
|
1487
|
+
// src/poll-timings.ts
|
|
1506
1488
|
const DEFAULT_TIMEOUT_MS = 12e5;
|
|
1507
1489
|
const DEFAULT_INTERVAL_MS = 15e3;
|
|
1508
1490
|
const MIN_INTERVAL_MS = 5e3;
|
|
@@ -1514,15 +1496,13 @@ function resolvePollTimings(options) {
|
|
|
1514
1496
|
intervalMs: envMsOverride(process.env["BST_TEST_CHECK_POLL_INTERVAL_MS"], Math.max(requestedIntervalMs, MIN_INTERVAL_MS))
|
|
1515
1497
|
};
|
|
1516
1498
|
}
|
|
1517
|
-
|
|
1518
|
-
//#region src/sleep.ts
|
|
1499
|
+
// src/sleep.ts
|
|
1519
1500
|
function sleep(ms) {
|
|
1520
1501
|
return new Promise((resolve) => {
|
|
1521
1502
|
setTimeout(resolve, ms);
|
|
1522
1503
|
});
|
|
1523
1504
|
}
|
|
1524
|
-
|
|
1525
|
-
//#region src/commit-status.ts
|
|
1505
|
+
// src/commit-status.ts
|
|
1526
1506
|
async function resolveCommitStatusTarget(fetcher, options) {
|
|
1527
1507
|
const targetRepo = parseRepoTarget(options.repo);
|
|
1528
1508
|
const conn = requireForgejoTarget(options.cwd, targetRepo, "commit:status is Forgejo-only: GitHub Actions publishes check runs, not commit statuses. Use `gh run list` / `gh run view` instead.");
|
|
@@ -1632,8 +1612,7 @@ function renderCommitStatus(report) {
|
|
|
1632
1612
|
lines.push(summaryParts.join(" -- "));
|
|
1633
1613
|
return lines.join("\n");
|
|
1634
1614
|
}
|
|
1635
|
-
|
|
1636
|
-
//#region src/commands/commit-status.ts
|
|
1615
|
+
// src/commands/commit-status.ts
|
|
1637
1616
|
const commitStatusCommand = defineCommand({
|
|
1638
1617
|
meta: {
|
|
1639
1618
|
name: "commit:status",
|
|
@@ -1687,8 +1666,37 @@ const commitStatusCommand = defineCommand({
|
|
|
1687
1666
|
process.exitCode = report.status === "green" ? 0 : 1;
|
|
1688
1667
|
}
|
|
1689
1668
|
});
|
|
1690
|
-
|
|
1691
|
-
|
|
1669
|
+
// ../forgejo/src/closing-refs.ts
|
|
1670
|
+
const CLOSING_REF = /(?:^|[\s([])(clos(?:e|es|ed)|fix(?:es|ed)?|resolv(?:e|es|ed))(?::[ \t]*|[ \t]+)((?:[\w.-]+\/[\w.-]+)?#\d+)(?![\w-])/gim;
|
|
1671
|
+
function capitalize(word) {
|
|
1672
|
+
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
1673
|
+
}
|
|
1674
|
+
function extractClosingRefs(messages) {
|
|
1675
|
+
const byIssue = /* @__PURE__ */ new Map();
|
|
1676
|
+
for (const message of messages) for (const [, keyword, issue] of message.matchAll(CLOSING_REF)) {
|
|
1677
|
+
if (keyword === void 0 || issue === void 0) continue;
|
|
1678
|
+
const key = issue.toLowerCase();
|
|
1679
|
+
if (!byIssue.has(key)) byIssue.set(key, {
|
|
1680
|
+
text: `${capitalize(keyword)} ${issue}`,
|
|
1681
|
+
issue
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
return [...byIssue.values()];
|
|
1685
|
+
}
|
|
1686
|
+
function closedIssues(text) {
|
|
1687
|
+
return new Set(extractClosingRefs([text]).map((ref) => ref.issue.toLowerCase()));
|
|
1688
|
+
}
|
|
1689
|
+
function droppedClosingRefs(messages, body) {
|
|
1690
|
+
const closed = closedIssues(body);
|
|
1691
|
+
return extractClosingRefs(messages).filter((ref) => !closed.has(ref.issue.toLowerCase()));
|
|
1692
|
+
}
|
|
1693
|
+
function carryForwardClosingRefs(source, target) {
|
|
1694
|
+
const missing = droppedClosingRefs([source], target);
|
|
1695
|
+
if (missing.length === 0) return target;
|
|
1696
|
+
const refLines = missing.map((ref) => ref.text).join("\n");
|
|
1697
|
+
return target.trim() === "" ? refLines : `${target}\n\n${refLines}`;
|
|
1698
|
+
}
|
|
1699
|
+
// ../forgejo/src/fetcher.ts
|
|
1692
1700
|
const LONG_FETCH_TIMEOUT_MS = 6e5;
|
|
1693
1701
|
function morePagesFollow(res, pageLength, received, pageSize) {
|
|
1694
1702
|
if (pageLength === 0) return false;
|
|
@@ -1697,8 +1705,7 @@ function morePagesFollow(res, pageLength, received, pageSize) {
|
|
|
1697
1705
|
if (!Number.isSafeInteger(total) || total < 0) return pageLength >= pageSize;
|
|
1698
1706
|
return received < total;
|
|
1699
1707
|
}
|
|
1700
|
-
|
|
1701
|
-
//#region ../forgejo/src/label-provisioning.ts
|
|
1708
|
+
// ../forgejo/src/label-provisioning.ts
|
|
1702
1709
|
const LabelSchema = z.object({
|
|
1703
1710
|
id: z.number(),
|
|
1704
1711
|
name: z.string(),
|
|
@@ -1871,8 +1878,7 @@ async function deleteForgejoLabel(executor, conn, id) {
|
|
|
1871
1878
|
resource: String(id)
|
|
1872
1879
|
}, repoNotFoundMessage(conn));
|
|
1873
1880
|
}
|
|
1874
|
-
|
|
1875
|
-
//#region ../forgejo/src/issues.ts
|
|
1881
|
+
// ../forgejo/src/issues.ts
|
|
1876
1882
|
const IssueResponseSchema = z.object({
|
|
1877
1883
|
number: z.number(),
|
|
1878
1884
|
title: z.string(),
|
|
@@ -1931,13 +1937,15 @@ const DependencyResponseSchema = z.object({
|
|
|
1931
1937
|
});
|
|
1932
1938
|
z.array(DependencyResponseSchema);
|
|
1933
1939
|
function issueListParams(type, query) {
|
|
1934
|
-
const
|
|
1940
|
+
const kind = query.type ?? type;
|
|
1941
|
+
const params = new URLSearchParams(kind === "all" ? {} : { type: kind });
|
|
1935
1942
|
params.set("state", query.state);
|
|
1936
1943
|
params.set("limit", String(query.limit));
|
|
1937
1944
|
if (query.label !== void 0) params.set("labels", query.label);
|
|
1938
1945
|
if (query.page !== void 0) params.set("page", String(query.page));
|
|
1939
1946
|
if (query.since !== void 0) params.set("since", query.since);
|
|
1940
1947
|
if (query.sort !== void 0) params.set("sort", query.sort);
|
|
1948
|
+
if (query.q !== void 0) params.set("q", query.q);
|
|
1941
1949
|
return params;
|
|
1942
1950
|
}
|
|
1943
1951
|
async function fetchIssueListPage(executor, conn, params) {
|
|
@@ -2089,8 +2097,7 @@ async function setForgejoIssueState(executor, conn, number, state) {
|
|
|
2089
2097
|
}, issueNotFoundMessage(conn, number));
|
|
2090
2098
|
return normalizeIssue(parseIssueOrThrow(await res.json()));
|
|
2091
2099
|
}
|
|
2092
|
-
|
|
2093
|
-
//#region ../forgejo/src/label-sync.ts
|
|
2100
|
+
// ../forgejo/src/label-sync.ts
|
|
2094
2101
|
function resolveSyncMode(check, dryRun) {
|
|
2095
2102
|
if (check) return "check";
|
|
2096
2103
|
if (dryRun) return "dry-run";
|
|
@@ -2264,8 +2271,7 @@ function syncSummaryLines(result) {
|
|
|
2264
2271
|
failureLines: result.failures.map((failure) => `${failure.repository}: failed: ${failure.error}`)
|
|
2265
2272
|
};
|
|
2266
2273
|
}
|
|
2267
|
-
|
|
2268
|
-
//#region src/label-sets-file.ts
|
|
2274
|
+
// src/label-sets-file.ts
|
|
2269
2275
|
function readLabelSet(path, setName) {
|
|
2270
2276
|
let raw;
|
|
2271
2277
|
try {
|
|
@@ -2292,8 +2298,7 @@ function readLabelSet(path, setName) {
|
|
|
2292
2298
|
}
|
|
2293
2299
|
return specs;
|
|
2294
2300
|
}
|
|
2295
|
-
|
|
2296
|
-
//#region src/labels.ts
|
|
2301
|
+
// src/labels.ts
|
|
2297
2302
|
async function runLabelsList(fetcher, conn) {
|
|
2298
2303
|
const labels = await fetchAllForgejoLabels(fetcher, conn);
|
|
2299
2304
|
return {
|
|
@@ -2327,8 +2332,7 @@ function renderSync(result) {
|
|
|
2327
2332
|
for (const line of repoLines) rootLogger.info(line);
|
|
2328
2333
|
for (const line of failureLines) rootLogger.warn(line);
|
|
2329
2334
|
}
|
|
2330
|
-
|
|
2331
|
-
//#region src/commands/labels.ts
|
|
2335
|
+
// src/commands/labels.ts
|
|
2332
2336
|
const GITHUB_REFUSAL = "bst-fj labels requires a Forgejo repository";
|
|
2333
2337
|
const listCommand$1 = defineCommand({
|
|
2334
2338
|
meta: {
|
|
@@ -2435,8 +2439,7 @@ const labelsCommand = defineCommand({
|
|
|
2435
2439
|
sync: syncCommand
|
|
2436
2440
|
}
|
|
2437
2441
|
});
|
|
2438
|
-
|
|
2439
|
-
//#region ../forgejo/src/releases.ts
|
|
2442
|
+
// ../forgejo/src/releases.ts
|
|
2440
2443
|
const SETTLE_ATTEMPTS = 4;
|
|
2441
2444
|
const SETTLE_BASE_DELAY_MS = 2e3;
|
|
2442
2445
|
const SETTLE_MAX_DELAY_MS = 16e3;
|
|
@@ -2658,8 +2661,7 @@ z.looseObject({
|
|
|
2658
2661
|
created: z.string().nullish()
|
|
2659
2662
|
})
|
|
2660
2663
|
});
|
|
2661
|
-
|
|
2662
|
-
//#region src/commands/release-create.ts
|
|
2664
|
+
// src/commands/release-create.ts
|
|
2663
2665
|
const releaseCreateCommand = defineCommand({
|
|
2664
2666
|
meta: {
|
|
2665
2667
|
name: "release:create",
|
|
@@ -2708,8 +2710,7 @@ const releaseCreateCommand = defineCommand({
|
|
|
2708
2710
|
else rootLogger.info(`Created Forgejo release for ${args.tag}`);
|
|
2709
2711
|
}
|
|
2710
2712
|
});
|
|
2711
|
-
|
|
2712
|
-
//#region ../forgejo/src/secrets.ts
|
|
2713
|
+
// ../forgejo/src/secrets.ts
|
|
2713
2714
|
const ActionSecretListSchema = z.array(z.object({ name: z.string() }));
|
|
2714
2715
|
const SECRETS_PAGE_SIZE = 50;
|
|
2715
2716
|
const SECRETS_MAX_PAGES = 20;
|
|
@@ -2765,8 +2766,7 @@ async function deleteActionSecret(executor, conn, secretName) {
|
|
|
2765
2766
|
resource: secretName
|
|
2766
2767
|
}));
|
|
2767
2768
|
}
|
|
2768
|
-
|
|
2769
|
-
//#region src/secrets.ts
|
|
2769
|
+
// src/secrets.ts
|
|
2770
2770
|
async function runSecretsSet(fetcher, config) {
|
|
2771
2771
|
if (!isValidSecretName(config.secretName)) throw new FatalError(`Invalid secret name "${config.secretName}". A name must match [A-Za-z_][A-Za-z0-9_]* and must not start with FORGEJO_, GITEA_, GITHUB_, or a digit.`);
|
|
2772
2772
|
if (config.dryRun) {
|
|
@@ -2808,8 +2808,7 @@ async function runSecretsDelete(fetcher, config) {
|
|
|
2808
2808
|
repository: config.conn.repository
|
|
2809
2809
|
};
|
|
2810
2810
|
}
|
|
2811
|
-
|
|
2812
|
-
//#region src/commands/secrets.ts
|
|
2811
|
+
// src/commands/secrets.ts
|
|
2813
2812
|
function readSecretValue(body) {
|
|
2814
2813
|
if (body) return body;
|
|
2815
2814
|
try {
|
|
@@ -2938,8 +2937,7 @@ const secretsCommand = defineCommand({
|
|
|
2938
2937
|
delete: deleteCommand
|
|
2939
2938
|
}
|
|
2940
2939
|
});
|
|
2941
|
-
|
|
2942
|
-
//#region ../forgejo/src/user.ts
|
|
2940
|
+
// ../forgejo/src/user.ts
|
|
2943
2941
|
const AuthenticatedUserSchema = z.object({
|
|
2944
2942
|
login: z.string(),
|
|
2945
2943
|
email: z.string().nullish()
|
|
@@ -2962,8 +2960,7 @@ async function getAuthenticatedUser(executor, conn, signal = null) {
|
|
|
2962
2960
|
email: parsed.data.email || null
|
|
2963
2961
|
};
|
|
2964
2962
|
}
|
|
2965
|
-
|
|
2966
|
-
//#region ../forgejo/src/webhooks.ts
|
|
2963
|
+
// ../forgejo/src/webhooks.ts
|
|
2967
2964
|
const WebhookSchema = z.object({
|
|
2968
2965
|
id: z.number(),
|
|
2969
2966
|
type: z.string(),
|
|
@@ -3044,8 +3041,7 @@ async function searchRepos(executor, conn) {
|
|
|
3044
3041
|
return parsed.data.data;
|
|
3045
3042
|
})).map((r) => r.full_name);
|
|
3046
3043
|
}
|
|
3047
|
-
|
|
3048
|
-
//#region src/commands/webhooks.ts
|
|
3044
|
+
// src/commands/webhooks.ts
|
|
3049
3045
|
function collectGroup(label, scopeHint, status) {
|
|
3050
3046
|
if (status.status === "ok") return status.hooks.length > 0 ? {
|
|
3051
3047
|
label,
|
|
@@ -3121,8 +3117,7 @@ const webhooksCommand = defineCommand({
|
|
|
3121
3117
|
renderText(inventory, conn.serverUrl);
|
|
3122
3118
|
}
|
|
3123
3119
|
});
|
|
3124
|
-
|
|
3125
|
-
//#region ../forgejo/src/actions.ts
|
|
3120
|
+
// ../forgejo/src/actions.ts
|
|
3126
3121
|
function forgeTimestamp(value) {
|
|
3127
3122
|
if (value === null || value === void 0 || value === "") return null;
|
|
3128
3123
|
const ms = Date.parse(value);
|
|
@@ -3300,8 +3295,7 @@ async function dispatchWorkflow(executor, conn, options) {
|
|
|
3300
3295
|
inputs: options.inputs
|
|
3301
3296
|
};
|
|
3302
3297
|
}
|
|
3303
|
-
|
|
3304
|
-
//#region ../forgejo/src/actions-log.ts
|
|
3298
|
+
// ../forgejo/src/actions-log.ts
|
|
3305
3299
|
const CSI_SEQUENCE = /\u001b\[[0-?]*[ -/]*[@-~]/gu;
|
|
3306
3300
|
const OSC_SEQUENCE = /\u001b\][^\u0007]*(?:\u0007|\u001b\\)/gu;
|
|
3307
3301
|
const LONE_ESCAPE = /\u001b/gu;
|
|
@@ -3343,8 +3337,7 @@ function readActionsJobLog(text) {
|
|
|
3343
3337
|
lines
|
|
3344
3338
|
};
|
|
3345
3339
|
}
|
|
3346
|
-
|
|
3347
|
-
//#region src/ci-log.ts
|
|
3340
|
+
// src/ci-log.ts
|
|
3348
3341
|
const ACTIONS_RUN_URL = /\/actions\/runs\/(\d+)\/?(?:[?#]|$)/u;
|
|
3349
3342
|
function parseCiLogTarget(target) {
|
|
3350
3343
|
if (/^\d+$/.test(target)) return {
|
|
@@ -3435,8 +3428,7 @@ function renderCiLog(result) {
|
|
|
3435
3428
|
for (const line of result.lines) lines.push(line.at === null ? line.text : `${line.at} ${line.text}`);
|
|
3436
3429
|
return lines.join("\n");
|
|
3437
3430
|
}
|
|
3438
|
-
|
|
3439
|
-
//#region src/commands/ci-log.ts
|
|
3431
|
+
// src/commands/ci-log.ts
|
|
3440
3432
|
const ciLogCommand = defineCommand({
|
|
3441
3433
|
meta: {
|
|
3442
3434
|
name: "ci:log",
|
|
@@ -3490,8 +3482,7 @@ const ciLogCommand = defineCommand({
|
|
|
3490
3482
|
out.text(renderCiLog(result));
|
|
3491
3483
|
}
|
|
3492
3484
|
});
|
|
3493
|
-
|
|
3494
|
-
//#region src/ci-runs.ts
|
|
3485
|
+
// src/ci-runs.ts
|
|
3495
3486
|
function resolveRunsRef(ref, pr) {
|
|
3496
3487
|
if (ref !== void 0 && pr !== void 0) throw new FatalError("--ref and --pr are the same filter -- give one of them (--pr 273 for a pull request's own runs, --ref main for a branch's).");
|
|
3497
3488
|
if (pr !== void 0) {
|
|
@@ -3567,8 +3558,7 @@ function renderCiRuns(result) {
|
|
|
3567
3558
|
}
|
|
3568
3559
|
return lines.join("\n");
|
|
3569
3560
|
}
|
|
3570
|
-
|
|
3571
|
-
//#region src/commands/ci-runs.ts
|
|
3561
|
+
// src/commands/ci-runs.ts
|
|
3572
3562
|
const ciRunsCommand = defineCommand({
|
|
3573
3563
|
meta: {
|
|
3574
3564
|
name: "ci:runs",
|
|
@@ -3633,8 +3623,7 @@ const ciRunsCommand = defineCommand({
|
|
|
3633
3623
|
out.text(renderCiRuns(result));
|
|
3634
3624
|
}
|
|
3635
3625
|
});
|
|
3636
|
-
|
|
3637
|
-
//#region ../cli-kit/src/workflow-inputs.ts
|
|
3626
|
+
// ../cli-kit/src/workflow-inputs.ts
|
|
3638
3627
|
const INPUT_FLAG = "--input";
|
|
3639
3628
|
const INPUT_FLAG_EQ = "--input=";
|
|
3640
3629
|
function collectInputArgs(rawArgs) {
|
|
@@ -3661,8 +3650,7 @@ function parseInputs(raw) {
|
|
|
3661
3650
|
}
|
|
3662
3651
|
return inputs;
|
|
3663
3652
|
}
|
|
3664
|
-
|
|
3665
|
-
//#region src/workflow-dispatch.ts
|
|
3653
|
+
// src/workflow-dispatch.ts
|
|
3666
3654
|
async function runWorkflowDispatch(fetcher, options) {
|
|
3667
3655
|
const dispatched = await dispatchWorkflow(fetcher, requireForgejoTarget(options.cwd, void 0, "workflow:dispatch is Forgejo-only -- use gh workflow run on GitHub."), {
|
|
3668
3656
|
...options.repo === void 0 ? {} : { repository: options.repo },
|
|
@@ -3679,8 +3667,7 @@ async function runWorkflowDispatch(fetcher, options) {
|
|
|
3679
3667
|
inputs: dispatched.inputs
|
|
3680
3668
|
};
|
|
3681
3669
|
}
|
|
3682
|
-
|
|
3683
|
-
//#region src/registry-actions.ts
|
|
3670
|
+
// src/registry-actions.ts
|
|
3684
3671
|
const actionsSubCommands = {
|
|
3685
3672
|
"ci:log": ciLogCommand,
|
|
3686
3673
|
"ci:runs": ciRunsCommand,
|
|
@@ -3749,8 +3736,7 @@ const DirEntrySchema = z.looseObject({
|
|
|
3749
3736
|
type: z.string()
|
|
3750
3737
|
});
|
|
3751
3738
|
z.array(DirEntrySchema);
|
|
3752
|
-
|
|
3753
|
-
//#region ../forgejo/src/branches.ts
|
|
3739
|
+
// ../forgejo/src/branches.ts
|
|
3754
3740
|
const BranchEntrySchema = z.object({
|
|
3755
3741
|
name: z.string(),
|
|
3756
3742
|
protected: z.boolean().optional(),
|
|
@@ -3829,8 +3815,7 @@ async function deleteBranch(executor, conn, branch) {
|
|
|
3829
3815
|
resource: `${conn.repository}/${branch}`
|
|
3830
3816
|
});
|
|
3831
3817
|
}
|
|
3832
|
-
|
|
3833
|
-
//#region src/branch.ts
|
|
3818
|
+
// src/branch.ts
|
|
3834
3819
|
const REFUSAL_WORDS = {
|
|
3835
3820
|
forbidden: "forbidden",
|
|
3836
3821
|
locked: "locked",
|
|
@@ -3856,8 +3841,7 @@ function renderBranchList(listing) {
|
|
|
3856
3841
|
if (listing.truncated) lines.push("Listing truncated at the page cap; more branches exist.");
|
|
3857
3842
|
return lines.join("\n");
|
|
3858
3843
|
}
|
|
3859
|
-
|
|
3860
|
-
//#region src/registry-branch.ts
|
|
3844
|
+
// src/registry-branch.ts
|
|
3861
3845
|
const branchSubCommands = {
|
|
3862
3846
|
"branch:delete": defineCommand({
|
|
3863
3847
|
meta: {
|
|
@@ -3927,8 +3911,7 @@ const branchSubCommands = {
|
|
|
3927
3911
|
}
|
|
3928
3912
|
})
|
|
3929
3913
|
};
|
|
3930
|
-
|
|
3931
|
-
//#region ../cli-kit/src/body-source.ts
|
|
3914
|
+
// ../cli-kit/src/body-source.ts
|
|
3932
3915
|
function tryRead(read, label) {
|
|
3933
3916
|
try {
|
|
3934
3917
|
return read();
|
|
@@ -3948,8 +3931,7 @@ function readBodySource(body, bodyFile, options = {}) {
|
|
|
3948
3931
|
if (!existsSync(bodyFile)) throw new FatalError(`${flags.file} not found: ${bodyFile}`);
|
|
3949
3932
|
return tryRead(() => readFileSync(bodyFile, "utf-8"), `${flags.file} "${bodyFile}"`);
|
|
3950
3933
|
}
|
|
3951
|
-
|
|
3952
|
-
//#region ../forgejo/src/issue-comments.ts
|
|
3934
|
+
// ../forgejo/src/issue-comments.ts
|
|
3953
3935
|
const CommentResponseSchema = z.object({
|
|
3954
3936
|
id: z.number(),
|
|
3955
3937
|
body: z.string().nullish(),
|
|
@@ -4023,8 +4005,7 @@ async function addForgejoComment(executor, conn, number, body) {
|
|
|
4023
4005
|
}, issueNotFoundMessage(conn, number));
|
|
4024
4006
|
return normalizeComment(parseCommentOrThrow(await res.json()));
|
|
4025
4007
|
}
|
|
4026
|
-
|
|
4027
|
-
//#region ../forgejo/src/pr-title.ts
|
|
4008
|
+
// ../forgejo/src/pr-title.ts
|
|
4028
4009
|
const WIP_PREFIXES = ["WIP:", "[WIP]"];
|
|
4029
4010
|
function hasWipPrefix(title) {
|
|
4030
4011
|
return matchedWipPrefix(title) !== void 0;
|
|
@@ -4038,8 +4019,7 @@ function stripWipPrefix(title) {
|
|
|
4038
4019
|
if (prefix === void 0) return title;
|
|
4039
4020
|
return title.slice(prefix.length).trimStart();
|
|
4040
4021
|
}
|
|
4041
|
-
|
|
4042
|
-
//#region ../forgejo/src/pr.ts
|
|
4022
|
+
// ../forgejo/src/pr.ts
|
|
4043
4023
|
const CreatedPrSchema = z.object({
|
|
4044
4024
|
number: z.number(),
|
|
4045
4025
|
html_url: z.string().optional()
|
|
@@ -4075,7 +4055,10 @@ async function findOpenPr(executor, conn, head, signal = null) {
|
|
|
4075
4055
|
const PullListItemSchema = z.object({
|
|
4076
4056
|
number: z.number(),
|
|
4077
4057
|
title: z.string().nullish(),
|
|
4078
|
-
head: z.object({
|
|
4058
|
+
head: z.object({
|
|
4059
|
+
ref: z.string(),
|
|
4060
|
+
repo: z.object({ full_name: z.string() }).nullish()
|
|
4061
|
+
}),
|
|
4079
4062
|
base: z.object({ ref: z.string() }).nullish(),
|
|
4080
4063
|
state: z.enum(["open", "closed"]),
|
|
4081
4064
|
merged: z.boolean().nullish(),
|
|
@@ -4090,9 +4073,12 @@ function updatedBefore(since) {
|
|
|
4090
4073
|
return (pr) => pr.updatedAt !== null && Date.parse(pr.updatedAt) < since;
|
|
4091
4074
|
}
|
|
4092
4075
|
async function listPulls(executor, conn, options = {}) {
|
|
4076
|
+
const startPage = options.startPage ?? 1;
|
|
4077
|
+
if (!Number.isInteger(startPage) || startPage < 1) throw new FatalError(`Cannot list PRs on ${conn.repository}: startPage must be an integer of at least 1, got ${String(startPage)}`);
|
|
4078
|
+
const lastPage = startPage + PULLS_MAX_PAGES - 1;
|
|
4093
4079
|
const headers = { Authorization: `token ${conn.token}` };
|
|
4094
4080
|
const pulls = [];
|
|
4095
|
-
for (let page =
|
|
4081
|
+
for (let page = startPage; page <= lastPage; page++) {
|
|
4096
4082
|
options.signal?.throwIfAborted();
|
|
4097
4083
|
const params = new URLSearchParams({
|
|
4098
4084
|
state: options.state ?? "all",
|
|
@@ -4117,6 +4103,7 @@ async function listPulls(executor, conn, options = {}) {
|
|
|
4117
4103
|
number: pr.number,
|
|
4118
4104
|
title: pr.title ?? null,
|
|
4119
4105
|
headRef: pr.head.ref,
|
|
4106
|
+
headRepo: pr.head.repo?.full_name ?? null,
|
|
4120
4107
|
baseRef: pr.base?.ref ?? null,
|
|
4121
4108
|
state: pr.state,
|
|
4122
4109
|
merged: pr.merged ?? pr.merged_at != null,
|
|
@@ -4132,9 +4119,9 @@ async function listPulls(executor, conn, options = {}) {
|
|
|
4132
4119
|
if (options.stopWhen !== void 0 && items.some(options.stopWhen)) break;
|
|
4133
4120
|
if (options.updatedSince !== void 0 && items.some(updatedBefore(options.updatedSince))) break;
|
|
4134
4121
|
if (options.limit !== void 0 && pulls.length >= options.limit) break;
|
|
4135
|
-
if (page ===
|
|
4122
|
+
if (page === lastPage) {
|
|
4136
4123
|
log.warn(`PR listing on ${conn.repository} hit the ${String(PULLS_MAX_PAGES)}-page cap without an empty page; results may be truncated`);
|
|
4137
|
-
options.onPageCap?.();
|
|
4124
|
+
options.onPageCap?.(lastPage);
|
|
4138
4125
|
}
|
|
4139
4126
|
}
|
|
4140
4127
|
return pulls;
|
|
@@ -4306,8 +4293,7 @@ const PullReviewCommentSchema = z.object({
|
|
|
4306
4293
|
user: z.object({ login: z.string() }).nullish()
|
|
4307
4294
|
});
|
|
4308
4295
|
z.array(PullReviewCommentSchema);
|
|
4309
|
-
|
|
4310
|
-
//#region ../forgejo/src/issue-api.ts
|
|
4296
|
+
// ../forgejo/src/issue-api.ts
|
|
4311
4297
|
var IssueNumberRequiredError = class extends FatalError {
|
|
4312
4298
|
constructor() {
|
|
4313
4299
|
super("An issue number or issue URL is required.");
|
|
@@ -4334,8 +4320,7 @@ function forgejoIssueApi(fetcher, conn) {
|
|
|
4334
4320
|
pullRequest: (number) => getForgejoPrDetail(fetcher, conn, number)
|
|
4335
4321
|
};
|
|
4336
4322
|
}
|
|
4337
|
-
|
|
4338
|
-
//#region ../forgejo/src/issue-messages.ts
|
|
4323
|
+
// ../forgejo/src/issue-messages.ts
|
|
4339
4324
|
const ISSUE_LIST_JSON_HELP = "Emit one JSON document: issues ([{number, title, state, url, author, labels, createdAt, updatedAt, closedAt (null while open), isPullRequest, assignees, attachments ([{id, name, size, createdAt, downloadUrl}])}]), truncated.";
|
|
4340
4325
|
const ISSUE_CREATE_JSON_HELP = "Emit one JSON document: number, url, assignees. A dry run reports number 0 and an empty url.";
|
|
4341
4326
|
const ISSUE_STATE_JSON_HELP = "Emit one JSON document: number, url, action (close | reopen), state ({previous, current}), changed, comment? ({posted}; present only when a comment was given).";
|
|
@@ -4366,8 +4351,7 @@ function describeNoLabelsGiven(error, clearFlag) {
|
|
|
4366
4351
|
function describeAttachmentExists(error, forceFlag) {
|
|
4367
4352
|
return `"${error.filePath}" already exists -- pass ${forceFlag} to overwrite it.`;
|
|
4368
4353
|
}
|
|
4369
|
-
|
|
4370
|
-
//#region ../forgejo/src/issue-run.ts
|
|
4354
|
+
// ../forgejo/src/issue-run.ts
|
|
4371
4355
|
var NothingToUpdateError = class extends FatalError {
|
|
4372
4356
|
constructor() {
|
|
4373
4357
|
super("Nothing to change: neither a title nor a body was given.");
|
|
@@ -4623,8 +4607,7 @@ function formatIssueList(result) {
|
|
|
4623
4607
|
}
|
|
4624
4608
|
return lines.join("\n");
|
|
4625
4609
|
}
|
|
4626
|
-
|
|
4627
|
-
//#region src/issue-transport.ts
|
|
4610
|
+
// src/issue-transport.ts
|
|
4628
4611
|
function githubRefusal(command) {
|
|
4629
4612
|
return `bst-fj is Forgejo-only -- use \`gh\` or \`pnpm exec bst ${command}\` for a github.com repository.`;
|
|
4630
4613
|
}
|
|
@@ -4647,8 +4630,7 @@ function forgejoIssueTransport(cwd, target, command) {
|
|
|
4647
4630
|
target: resolved.target
|
|
4648
4631
|
};
|
|
4649
4632
|
}
|
|
4650
|
-
|
|
4651
|
-
//#region src/commands/issue-comment.ts
|
|
4633
|
+
// src/commands/issue-comment.ts
|
|
4652
4634
|
const issueCommentCommand = defineCommand({
|
|
4653
4635
|
meta: {
|
|
4654
4636
|
name: "issue:comment",
|
|
@@ -4706,8 +4688,7 @@ const issueCommentCommand = defineCommand({
|
|
|
4706
4688
|
}
|
|
4707
4689
|
}
|
|
4708
4690
|
});
|
|
4709
|
-
|
|
4710
|
-
//#region src/commands/issue-create.ts
|
|
4691
|
+
// src/commands/issue-create.ts
|
|
4711
4692
|
const issueCreateCommand = defineCommand({
|
|
4712
4693
|
meta: {
|
|
4713
4694
|
name: "issue:create",
|
|
@@ -4780,8 +4761,7 @@ const issueCreateCommand = defineCommand({
|
|
|
4780
4761
|
}
|
|
4781
4762
|
}
|
|
4782
4763
|
});
|
|
4783
|
-
|
|
4784
|
-
//#region ../forgejo/src/issue-run-download.ts
|
|
4764
|
+
// ../forgejo/src/issue-run-download.ts
|
|
4785
4765
|
function isReadableFile(filePath) {
|
|
4786
4766
|
try {
|
|
4787
4767
|
readFileSync(filePath);
|
|
@@ -4874,8 +4854,7 @@ function formatDownload(result, dryRun) {
|
|
|
4874
4854
|
for (const file of result.files) lines.push(` ${file.name} (${String(file.size)} bytes)`);
|
|
4875
4855
|
return lines.join("\n");
|
|
4876
4856
|
}
|
|
4877
|
-
|
|
4878
|
-
//#region src/commands/issue-download.ts
|
|
4857
|
+
// src/commands/issue-download.ts
|
|
4879
4858
|
const issueDownloadCommand = defineCommand({
|
|
4880
4859
|
meta: {
|
|
4881
4860
|
name: "issue:download",
|
|
@@ -4934,8 +4913,7 @@ const issueDownloadCommand = defineCommand({
|
|
|
4934
4913
|
}
|
|
4935
4914
|
}
|
|
4936
4915
|
});
|
|
4937
|
-
|
|
4938
|
-
//#region ../forgejo/src/issue-labels.ts
|
|
4916
|
+
// ../forgejo/src/issue-labels.ts
|
|
4939
4917
|
const TimelineEntrySchema = z.object({
|
|
4940
4918
|
id: z.number(),
|
|
4941
4919
|
type: z.string(),
|
|
@@ -4986,8 +4964,7 @@ async function replaceForgejoIssueLabels(executor, conn, number, labelIds) {
|
|
|
4986
4964
|
resource: `#${String(number)}`
|
|
4987
4965
|
}, issueNotFoundMessage(conn, number));
|
|
4988
4966
|
}
|
|
4989
|
-
|
|
4990
|
-
//#region ../forgejo/src/issue-run-labels.ts
|
|
4967
|
+
// ../forgejo/src/issue-run-labels.ts
|
|
4991
4968
|
async function labelIssue(resolve, request) {
|
|
4992
4969
|
const ref = parseIssueRef(request.ref);
|
|
4993
4970
|
const number = requireIssueNumber(ref);
|
|
@@ -5056,8 +5033,7 @@ function formatIssueSetLabels(result, dryRun) {
|
|
|
5056
5033
|
if (result.added.length > 0) lines.push(` ${dryRun ? "would add" : "added"}: ${result.added.join(", ")}`);
|
|
5057
5034
|
return lines.join("\n");
|
|
5058
5035
|
}
|
|
5059
|
-
|
|
5060
|
-
//#region src/commands/issue-label.ts
|
|
5036
|
+
// src/commands/issue-label.ts
|
|
5061
5037
|
function defineIssueLabelCommand(action) {
|
|
5062
5038
|
const name = action === "add" ? "issue:label" : "issue:unlabel";
|
|
5063
5039
|
return defineCommand({
|
|
@@ -5116,8 +5092,7 @@ function defineIssueLabelCommand(action) {
|
|
|
5116
5092
|
}
|
|
5117
5093
|
const issueLabelCommand = defineIssueLabelCommand("add");
|
|
5118
5094
|
const issueUnlabelCommand = defineIssueLabelCommand("remove");
|
|
5119
|
-
|
|
5120
|
-
//#region src/commands/issue-set-labels.ts
|
|
5095
|
+
// src/commands/issue-set-labels.ts
|
|
5121
5096
|
const issueSetLabelsCommand = defineCommand({
|
|
5122
5097
|
meta: {
|
|
5123
5098
|
name: "issue:set-labels",
|
|
@@ -5177,8 +5152,7 @@ const issueSetLabelsCommand = defineCommand({
|
|
|
5177
5152
|
}
|
|
5178
5153
|
}
|
|
5179
5154
|
});
|
|
5180
|
-
|
|
5181
|
-
//#region ../forgejo/src/issue-run-state.ts
|
|
5155
|
+
// ../forgejo/src/issue-run-state.ts
|
|
5182
5156
|
var EmptyCommentError = class extends FatalError {
|
|
5183
5157
|
constructor() {
|
|
5184
5158
|
super("The comment resolved to empty text.");
|
|
@@ -5274,8 +5248,7 @@ function formatIssueState(result, dryRun) {
|
|
|
5274
5248
|
}
|
|
5275
5249
|
return lines.join("\n");
|
|
5276
5250
|
}
|
|
5277
|
-
|
|
5278
|
-
//#region src/commands/issue-state.ts
|
|
5251
|
+
// src/commands/issue-state.ts
|
|
5279
5252
|
function defineIssueStateCommand(action) {
|
|
5280
5253
|
const name = action === "close" ? "issue:close" : "issue:reopen";
|
|
5281
5254
|
return defineCommand({
|
|
@@ -5351,8 +5324,7 @@ function defineIssueStateCommand(action) {
|
|
|
5351
5324
|
}
|
|
5352
5325
|
const issueCloseCommand = defineIssueStateCommand("close");
|
|
5353
5326
|
const issueReopenCommand = defineIssueStateCommand("reopen");
|
|
5354
|
-
|
|
5355
|
-
//#region src/commands/issue-list.ts
|
|
5327
|
+
// src/commands/issue-list.ts
|
|
5356
5328
|
const issueListCommand = defineCommand({
|
|
5357
5329
|
meta: {
|
|
5358
5330
|
name: "issue:list",
|
|
@@ -5410,8 +5382,7 @@ const issueListCommand = defineCommand({
|
|
|
5410
5382
|
}
|
|
5411
5383
|
}
|
|
5412
5384
|
});
|
|
5413
|
-
|
|
5414
|
-
//#region src/commands/issue-update.ts
|
|
5385
|
+
// src/commands/issue-update.ts
|
|
5415
5386
|
const issueUpdateCommand = defineCommand({
|
|
5416
5387
|
meta: {
|
|
5417
5388
|
name: "issue:update",
|
|
@@ -5482,8 +5453,7 @@ const issueUpdateCommand = defineCommand({
|
|
|
5482
5453
|
}
|
|
5483
5454
|
}
|
|
5484
5455
|
});
|
|
5485
|
-
|
|
5486
|
-
//#region src/registry-issue.ts
|
|
5456
|
+
// src/registry-issue.ts
|
|
5487
5457
|
const issueSubCommands = {
|
|
5488
5458
|
"issue:view": defineCommand({
|
|
5489
5459
|
meta: {
|
|
@@ -5536,8 +5506,7 @@ const issueSubCommands = {
|
|
|
5536
5506
|
"issue:set-labels": issueSetLabelsCommand,
|
|
5537
5507
|
"issue:download": issueDownloadCommand
|
|
5538
5508
|
};
|
|
5539
|
-
|
|
5540
|
-
//#region src/pr-checks.ts
|
|
5509
|
+
// src/pr-checks.ts
|
|
5541
5510
|
async function resolvePrChecksTarget(fetcher, options) {
|
|
5542
5511
|
const ref = parseIssueRef(options.pr);
|
|
5543
5512
|
if (options.repo !== void 0 && ref.number === void 0 && options.branch === void 0) throw new FatalError("--repo requires --pr or --branch -- the current branch of this checkout means nothing in another repository, and inferring it there would silently answer about the wrong PR.");
|
|
@@ -5711,8 +5680,7 @@ function renderPrChecks(report) {
|
|
|
5711
5680
|
lines.push(summaryParts.join(" -- "));
|
|
5712
5681
|
return lines.join("\n");
|
|
5713
5682
|
}
|
|
5714
|
-
|
|
5715
|
-
//#region src/commands/pr-checks.ts
|
|
5683
|
+
// src/commands/pr-checks.ts
|
|
5716
5684
|
const prChecksCommand = defineCommand({
|
|
5717
5685
|
meta: {
|
|
5718
5686
|
name: "pr:checks",
|
|
@@ -5776,8 +5744,7 @@ const prChecksCommand = defineCommand({
|
|
|
5776
5744
|
process.exitCode = report.status === "green" ? 0 : 1;
|
|
5777
5745
|
}
|
|
5778
5746
|
});
|
|
5779
|
-
|
|
5780
|
-
//#region ../forgejo/src/pr-close.ts
|
|
5747
|
+
// ../forgejo/src/pr-close.ts
|
|
5781
5748
|
async function closePullRequest(api, request) {
|
|
5782
5749
|
rejectEmptyComment(request.comment);
|
|
5783
5750
|
return changeState(api, request.number, {
|
|
@@ -5794,15 +5761,13 @@ function formatPrClose(result, dryRun) {
|
|
|
5794
5761
|
return lines.join("\n");
|
|
5795
5762
|
}
|
|
5796
5763
|
const PR_CLOSE_JSON_HELP = "Emit one JSON document: number, url, action (close), state ({previous, current}), changed, merged? (present only when the pull request was already closed), comment? ({posted}; present only when a comment was given).";
|
|
5797
|
-
|
|
5798
|
-
//#region ../forgejo/src/pr-number.ts
|
|
5764
|
+
// ../forgejo/src/pr-number.ts
|
|
5799
5765
|
function parsePrNumber(raw) {
|
|
5800
5766
|
const value = Number(raw);
|
|
5801
5767
|
if (!/^\d+$/.test(raw) || !Number.isSafeInteger(value) || value < 1) throw new FatalError(`Invalid pull request number "${raw}" (expected a positive integer).`);
|
|
5802
5768
|
return value;
|
|
5803
5769
|
}
|
|
5804
|
-
|
|
5805
|
-
//#region src/commands/pr-close.ts
|
|
5770
|
+
// src/commands/pr-close.ts
|
|
5806
5771
|
const prCloseCommand = defineCommand({
|
|
5807
5772
|
meta: {
|
|
5808
5773
|
name: "pr:close",
|
|
@@ -5866,39 +5831,7 @@ const prCloseCommand = defineCommand({
|
|
|
5866
5831
|
}
|
|
5867
5832
|
}
|
|
5868
5833
|
});
|
|
5869
|
-
|
|
5870
|
-
//#region ../forgejo/src/closing-refs.ts
|
|
5871
|
-
const CLOSING_REF = /(?:^|[\s([])(clos(?:e|es|ed)|fix(?:es|ed)?|resolv(?:e|es|ed))(?::[ \t]*|[ \t]+)((?:[\w.-]+\/[\w.-]+)?#\d+)(?![\w-])/gim;
|
|
5872
|
-
function capitalize(word) {
|
|
5873
|
-
return word.charAt(0).toUpperCase() + word.slice(1).toLowerCase();
|
|
5874
|
-
}
|
|
5875
|
-
function extractClosingRefs(messages) {
|
|
5876
|
-
const byIssue = /* @__PURE__ */ new Map();
|
|
5877
|
-
for (const message of messages) for (const [, keyword, issue] of message.matchAll(CLOSING_REF)) {
|
|
5878
|
-
if (keyword === void 0 || issue === void 0) continue;
|
|
5879
|
-
const key = issue.toLowerCase();
|
|
5880
|
-
if (!byIssue.has(key)) byIssue.set(key, {
|
|
5881
|
-
text: `${capitalize(keyword)} ${issue}`,
|
|
5882
|
-
issue
|
|
5883
|
-
});
|
|
5884
|
-
}
|
|
5885
|
-
return [...byIssue.values()];
|
|
5886
|
-
}
|
|
5887
|
-
function closedIssues(text) {
|
|
5888
|
-
return new Set(extractClosingRefs([text]).map((ref) => ref.issue.toLowerCase()));
|
|
5889
|
-
}
|
|
5890
|
-
function droppedClosingRefs(messages, body) {
|
|
5891
|
-
const closed = closedIssues(body);
|
|
5892
|
-
return extractClosingRefs(messages).filter((ref) => !closed.has(ref.issue.toLowerCase()));
|
|
5893
|
-
}
|
|
5894
|
-
function carryForwardClosingRefs(source, target) {
|
|
5895
|
-
const missing = droppedClosingRefs([source], target);
|
|
5896
|
-
if (missing.length === 0) return target;
|
|
5897
|
-
const refLines = missing.map((ref) => ref.text).join("\n");
|
|
5898
|
-
return target.trim() === "" ? refLines : `${target}\n\n${refLines}`;
|
|
5899
|
-
}
|
|
5900
|
-
//#endregion
|
|
5901
|
-
//#region ../forgejo/src/git.ts
|
|
5834
|
+
// ../forgejo/src/git.ts
|
|
5902
5835
|
const GIT_LOCAL_TIMEOUT_MS = 6e4;
|
|
5903
5836
|
const GIT_WRITE_TIMEOUT_MS = 3e5;
|
|
5904
5837
|
function pickDefaultBranch(override, originHead) {
|
|
@@ -6009,8 +5942,7 @@ async function pushBranch(git, cwd, branch, env, forceWithLease = false) {
|
|
|
6009
5942
|
});
|
|
6010
5943
|
if (result.exitCode !== 0) throw new FatalError(`Failed to push ${branch}: ${result.stderr || result.stdout}`);
|
|
6011
5944
|
}
|
|
6012
|
-
|
|
6013
|
-
//#region ../forgejo/src/pr-upsert.ts
|
|
5945
|
+
// ../forgejo/src/pr-upsert.ts
|
|
6014
5946
|
const COMMIT_TYPES = /* @__PURE__ */ new Set([
|
|
6015
5947
|
"feat",
|
|
6016
5948
|
"fix",
|
|
@@ -6218,8 +6150,7 @@ async function runPrUpsert(git, host, options) {
|
|
|
6218
6150
|
...shape
|
|
6219
6151
|
};
|
|
6220
6152
|
}
|
|
6221
|
-
|
|
6222
|
-
//#region ../forgejo/src/pr-upsert-messages.ts
|
|
6153
|
+
// ../forgejo/src/pr-upsert-messages.ts
|
|
6223
6154
|
function describePrModeError(error, commands) {
|
|
6224
6155
|
if (error.reason === "already-open") {
|
|
6225
6156
|
const createVerb = commands.create.split(" ").at(-1) ?? commands.create;
|
|
@@ -6298,8 +6229,7 @@ function formatPrUpdate(result, rewrites, flags) {
|
|
|
6298
6229
|
body: null
|
|
6299
6230
|
};
|
|
6300
6231
|
}
|
|
6301
|
-
|
|
6302
|
-
//#region ../forgejo/src/pr-host.ts
|
|
6232
|
+
// ../forgejo/src/pr-host.ts
|
|
6303
6233
|
function forgejoPrHost(fetcher, conn) {
|
|
6304
6234
|
return {
|
|
6305
6235
|
wipTitles: true,
|
|
@@ -6332,8 +6262,7 @@ function forgejoPrEditHost(fetcher, conn) {
|
|
|
6332
6262
|
ready: (number, write) => updatePr(fetcher, conn, number, { title: write.title })
|
|
6333
6263
|
};
|
|
6334
6264
|
}
|
|
6335
|
-
|
|
6336
|
-
//#region src/git.ts
|
|
6265
|
+
// src/git.ts
|
|
6337
6266
|
const TIMED_OUT_EXIT_CODE = 124;
|
|
6338
6267
|
const ABORTED_EXIT_CODE = 143;
|
|
6339
6268
|
function cliGit() {
|
|
@@ -6409,8 +6338,7 @@ function cliGit() {
|
|
|
6409
6338
|
});
|
|
6410
6339
|
}) };
|
|
6411
6340
|
}
|
|
6412
|
-
|
|
6413
|
-
//#region src/pr-run.ts
|
|
6341
|
+
// src/pr-run.ts
|
|
6414
6342
|
const COMMANDS = {
|
|
6415
6343
|
create: "pnpm exec bst-fj pr:create",
|
|
6416
6344
|
update: "pnpm exec bst-fj pr:update"
|
|
@@ -6444,8 +6372,7 @@ async function runForgejoPr(githubRefusal, options) {
|
|
|
6444
6372
|
});
|
|
6445
6373
|
}
|
|
6446
6374
|
}
|
|
6447
|
-
|
|
6448
|
-
//#region src/commands/pr-create.ts
|
|
6375
|
+
// src/commands/pr-create.ts
|
|
6449
6376
|
const prCreateCommand = defineCommand({
|
|
6450
6377
|
meta: {
|
|
6451
6378
|
name: "pr:create",
|
|
@@ -6486,7 +6413,7 @@ const prCreateCommand = defineCommand({
|
|
|
6486
6413
|
},
|
|
6487
6414
|
json: {
|
|
6488
6415
|
type: "boolean",
|
|
6489
|
-
description: "Emit one JSON document: action (created | updated | would-create | would-update), number (or null), url (or null), branch, base, title, body, droppedRefs? ([{text, issue}]), dryRun. A create or would-create carries droppedRefs; on a dry run, number and url are null."
|
|
6416
|
+
description: "Emit one JSON document: action (created | updated | would-create | would-update), number (or null), url (or null), branch, base, title, body, droppedRefs? ([{text, issue}]), dryRun. A create or would-create carries droppedRefs; on a dry run, number and url are null. The document carries no claims member and no claim advice line: the closed-issue claim check reads the repo's .tooling.json and is bst pr:create's alone."
|
|
6490
6417
|
},
|
|
6491
6418
|
verbose: {
|
|
6492
6419
|
type: "boolean",
|
|
@@ -6514,8 +6441,7 @@ const prCreateCommand = defineCommand({
|
|
|
6514
6441
|
if (summary.body !== null) out.text(`${summary.body.heading}\n${summary.body.text}`);
|
|
6515
6442
|
}
|
|
6516
6443
|
});
|
|
6517
|
-
|
|
6518
|
-
//#region ../forgejo/src/pr-files.ts
|
|
6444
|
+
// ../forgejo/src/pr-files.ts
|
|
6519
6445
|
const DEFAULT_LIMIT = 100;
|
|
6520
6446
|
const PrFileEntrySchema = z.object({
|
|
6521
6447
|
filename: z.string(),
|
|
@@ -6560,8 +6486,7 @@ async function readPrFilesPage(executor, conn, prNumber, page, limit) {
|
|
|
6560
6486
|
truncated: res.headers.get("x-hasmore") === "true"
|
|
6561
6487
|
};
|
|
6562
6488
|
}
|
|
6563
|
-
|
|
6564
|
-
//#region src/pr-files.ts
|
|
6489
|
+
// src/pr-files.ts
|
|
6565
6490
|
function runPrFiles(fetcher, options) {
|
|
6566
6491
|
const number = parsePrNumber(options.number);
|
|
6567
6492
|
return listAllPrFiles(fetcher, requireForgejoTarget(options.cwd, parseRepoTarget(options.repo), "pr:files is Forgejo-only -- gh pr diff --name-only already serves GitHub."), number);
|
|
@@ -6572,8 +6497,7 @@ function renderPrFiles(listing) {
|
|
|
6572
6497
|
if (listing.truncated) lines.push("Listing truncated; the pull request changes more files.");
|
|
6573
6498
|
return lines.join("\n");
|
|
6574
6499
|
}
|
|
6575
|
-
|
|
6576
|
-
//#region src/commands/pr-files.ts
|
|
6500
|
+
// src/commands/pr-files.ts
|
|
6577
6501
|
const prFilesCommand = defineCommand({
|
|
6578
6502
|
meta: {
|
|
6579
6503
|
name: "pr:files",
|
|
@@ -6612,8 +6536,7 @@ const prFilesCommand = defineCommand({
|
|
|
6612
6536
|
out.text(renderPrFiles(listing));
|
|
6613
6537
|
}
|
|
6614
6538
|
});
|
|
6615
|
-
|
|
6616
|
-
//#region src/pr-list.ts
|
|
6539
|
+
// src/pr-list.ts
|
|
6617
6540
|
function parseState(state) {
|
|
6618
6541
|
if (state === "open" || state === "closed" || state === "all") return state;
|
|
6619
6542
|
throw new FatalError(`Invalid --state "${state}" (expected open, closed, or all).`);
|
|
@@ -6650,8 +6573,7 @@ function renderPrList(result) {
|
|
|
6650
6573
|
return `#${String(pr.number)} ${statusLabel(pr)} ${branches}: ${pr.title ?? "(no title)"}${labels}${url}`;
|
|
6651
6574
|
}).join("\n");
|
|
6652
6575
|
}
|
|
6653
|
-
|
|
6654
|
-
//#region src/commands/pr-list.ts
|
|
6576
|
+
// src/commands/pr-list.ts
|
|
6655
6577
|
const prListCommand = defineCommand({
|
|
6656
6578
|
meta: {
|
|
6657
6579
|
name: "pr:list",
|
|
@@ -6694,8 +6616,7 @@ const prListCommand = defineCommand({
|
|
|
6694
6616
|
out.text(renderPrList(result));
|
|
6695
6617
|
}
|
|
6696
6618
|
});
|
|
6697
|
-
|
|
6698
|
-
//#region ../forgejo/src/pr-merge.ts
|
|
6619
|
+
// ../forgejo/src/pr-merge.ts
|
|
6699
6620
|
async function mergePr(executor, conn, prNumber, options) {
|
|
6700
6621
|
const url = `${conn.serverUrl}/api/v1/repos/${conn.repository}/pulls/${String(prNumber)}/merge`;
|
|
6701
6622
|
const body = {
|
|
@@ -6798,8 +6719,7 @@ z.object({
|
|
|
6798
6719
|
sha: z.string()
|
|
6799
6720
|
})
|
|
6800
6721
|
});
|
|
6801
|
-
|
|
6802
|
-
//#region ../forgejo/src/pr-merge-run.ts
|
|
6722
|
+
// ../forgejo/src/pr-merge-run.ts
|
|
6803
6723
|
const MERGE_METHODS = [
|
|
6804
6724
|
"merge",
|
|
6805
6725
|
"rebase",
|
|
@@ -6870,8 +6790,7 @@ async function runPrMergeCore(fetcher, conn, number, options = {}) {
|
|
|
6870
6790
|
}
|
|
6871
6791
|
};
|
|
6872
6792
|
}
|
|
6873
|
-
|
|
6874
|
-
//#region src/pr-merge.ts
|
|
6793
|
+
// src/pr-merge.ts
|
|
6875
6794
|
function parseMethod(raw) {
|
|
6876
6795
|
if (raw === void 0) return "merge";
|
|
6877
6796
|
const method = MERGE_METHODS.find((candidate) => candidate === raw);
|
|
@@ -6898,8 +6817,7 @@ function renderPrMerge(result) {
|
|
|
6898
6817
|
const what = `PR #${String(result.number)} (${result.method}) at ${result.headSha.slice(0, 12)}, checks ${result.checks}`;
|
|
6899
6818
|
return result.merged ? `Merged ${what}.` : `Dry run: would merge ${what}.`;
|
|
6900
6819
|
}
|
|
6901
|
-
|
|
6902
|
-
//#region src/commands/pr-merge.ts
|
|
6820
|
+
// src/commands/pr-merge.ts
|
|
6903
6821
|
const prMergeCommand = defineCommand({
|
|
6904
6822
|
meta: {
|
|
6905
6823
|
name: "pr:merge",
|
|
@@ -6955,8 +6873,7 @@ const prMergeCommand = defineCommand({
|
|
|
6955
6873
|
out.text(renderPrMerge(result));
|
|
6956
6874
|
}
|
|
6957
6875
|
});
|
|
6958
|
-
|
|
6959
|
-
//#region ../forgejo/src/pr-edit.ts
|
|
6876
|
+
// ../forgejo/src/pr-edit.ts
|
|
6960
6877
|
const MERGEABLE_RECHECK_DELAY_MS = 2e3;
|
|
6961
6878
|
function isOpen(live) {
|
|
6962
6879
|
return live.state === "open" && live.merged === false;
|
|
@@ -7083,8 +7000,7 @@ function renderPrReady(result) {
|
|
|
7083
7000
|
if (result.action === "would-ready") return `Dry run: pull request ${number} would stop being a draft, reading "${result.title}".`;
|
|
7084
7001
|
return `Dry run: pull request ${number} would read "${result.title}".`;
|
|
7085
7002
|
}
|
|
7086
|
-
|
|
7087
|
-
//#region src/registry-pr.ts
|
|
7003
|
+
// src/registry-pr.ts
|
|
7088
7004
|
const prSubCommands = {
|
|
7089
7005
|
"pr:checks": prChecksCommand,
|
|
7090
7006
|
"pr:close": prCloseCommand,
|
|
@@ -7249,8 +7165,7 @@ const prSubCommands = {
|
|
|
7249
7165
|
}
|
|
7250
7166
|
})
|
|
7251
7167
|
};
|
|
7252
|
-
|
|
7253
|
-
//#region src/registry.ts
|
|
7168
|
+
// src/registry.ts
|
|
7254
7169
|
const bstFjSubCommands = {
|
|
7255
7170
|
"commit:status": commitStatusCommand,
|
|
7256
7171
|
labels: labelsCommand,
|
|
@@ -7262,8 +7177,7 @@ const bstFjSubCommands = {
|
|
|
7262
7177
|
webhooks: webhooksCommand,
|
|
7263
7178
|
...issueSubCommands
|
|
7264
7179
|
};
|
|
7265
|
-
|
|
7266
|
-
//#region src/bin.ts
|
|
7180
|
+
// src/bin.ts
|
|
7267
7181
|
applyVerbosityFromArgs(process.argv.slice(2));
|
|
7268
7182
|
rootLogger.debug(describeEnvFileLoad(envFileLoad));
|
|
7269
7183
|
setForgejoLogger(rootLogger);
|
|
@@ -7275,5 +7189,4 @@ await runCli({
|
|
|
7275
7189
|
subCommands: bstFjSubCommands,
|
|
7276
7190
|
describeError: describeForgeError
|
|
7277
7191
|
});
|
|
7278
|
-
//#endregion
|
|
7279
7192
|
export {};
|