@theholocron/holocron-plugin-github 2.0.0-alpha.0 → 2.0.0-alpha.5
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 +23 -17
- package/dist/index.d.mts +55 -5
- package/dist/index.mjs +114 -20
- package/package.json +6 -4
package/README.md
CHANGED
|
@@ -3,13 +3,19 @@
|
|
|
3
3
|
GitHub plugin for [Holocron](../cli). Implements five capabilities
|
|
4
4
|
against the GitHub REST API:
|
|
5
5
|
|
|
6
|
-
| Capability | What this plugin does
|
|
7
|
-
| -------------- |
|
|
6
|
+
| Capability | What this plugin does |
|
|
7
|
+
| -------------- | ---------------------------------------------------------------- |
|
|
8
8
|
| `source` | Repos, rulesets, repo settings, security toggles, workflow files |
|
|
9
|
-
| `ci` | Workflow run history + status
|
|
10
|
-
| `secrets` | GH Actions secrets (repo + environment + organization)
|
|
11
|
-
| `environments` | Named deployment environments (reviewers, wait timers)
|
|
12
|
-
| `issues` | GitHub Issues as a tracker (with lifecycle slots)
|
|
9
|
+
| `ci` | Workflow run history + status |
|
|
10
|
+
| `secrets` | GH Actions secrets (repo + environment + organization) |
|
|
11
|
+
| `environments` | Named deployment environments (reviewers, wait timers) |
|
|
12
|
+
| `issues` | GitHub Issues as a tracker (with lifecycle slots) |
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
pnpm add -D @theholocron/holocron-plugin-github@alpha
|
|
18
|
+
```
|
|
13
19
|
|
|
14
20
|
## Auth
|
|
15
21
|
|
|
@@ -30,19 +36,19 @@ toggles, etc.) — silent fallback would surface as mysterious 403s.
|
|
|
30
36
|
```jsonc
|
|
31
37
|
// holocron.config.json
|
|
32
38
|
{
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
"providers": {
|
|
40
|
+
"source": "github",
|
|
41
|
+
"ci": "github",
|
|
42
|
+
"secrets": "github",
|
|
43
|
+
"environments": "github",
|
|
44
|
+
"issues": ["github", { "labels": { "inProgress": "status:in-progress", "inReview": "status:in-review" } }],
|
|
45
|
+
},
|
|
40
46
|
}
|
|
41
47
|
```
|
|
42
48
|
|
|
43
49
|
## Status
|
|
44
50
|
|
|
45
|
-
|
|
46
|
-
[
|
|
47
|
-
|
|
48
|
-
|
|
51
|
+
**`v2.0.0-alpha.0`** — published on npm under the `alpha` dist-tag.
|
|
52
|
+
[Release notes](https://github.com/theholocron/holocron/releases/tag/v2.0.0-alpha.0).
|
|
53
|
+
All five capabilities are implemented; APIs may still shift before
|
|
54
|
+
stable v2.0.0.
|
package/dist/index.d.mts
CHANGED
|
@@ -4,10 +4,13 @@ import { Auth, Ci, CiRun, CiRunFilter, Environment, Environments, Issue, IssueSe
|
|
|
4
4
|
/**
|
|
5
5
|
* Token resolution for the GitHub plugin. See README §Auth.
|
|
6
6
|
*
|
|
7
|
-
* Resolution order
|
|
7
|
+
* Resolution order (matches the standard 4-step precedence set by
|
|
8
|
+
* `.notes/tech-auth-bootstrap.spec.md`):
|
|
8
9
|
* 1. explicit `token` argument (from `--token` flag)
|
|
9
10
|
* 2. HOLOCRON_GH_TOKEN env var (preferred over GITHUB_TOKEN — clearer intent)
|
|
10
11
|
* 3. GITHUB_TOKEN env var (auto-injected in GH Actions)
|
|
12
|
+
* 4. keyring (com.theholocron.cli / "github")
|
|
13
|
+
* 5. AuthError naming all four options + the bootstrap hint
|
|
11
14
|
*
|
|
12
15
|
* No `gh auth token` fallback by design — it usually has narrower
|
|
13
16
|
* scopes than admin commands need.
|
|
@@ -20,6 +23,8 @@ interface ResolveTokenInput {
|
|
|
20
23
|
cliToken?: string;
|
|
21
24
|
/** Env vars; passed in for testability. Defaults to `process.env`. */
|
|
22
25
|
env?: NodeJS.ProcessEnv;
|
|
26
|
+
/** Keyring lookup fn; passed in for testability. Defaults to `getToken(provider)`. */
|
|
27
|
+
keyring?: (provider: string) => string | null;
|
|
23
28
|
}
|
|
24
29
|
declare function resolveToken(input?: ResolveTokenInput): string;
|
|
25
30
|
//#endregion
|
|
@@ -40,7 +45,7 @@ interface RestClientOptions {
|
|
|
40
45
|
baseUrl?: string;
|
|
41
46
|
}
|
|
42
47
|
interface RequestOptions {
|
|
43
|
-
method?:
|
|
48
|
+
method?: "GET" | "POST" | "PATCH" | "PUT" | "DELETE";
|
|
44
49
|
body?: unknown;
|
|
45
50
|
/** Skip JSON parse when true (204 No Content endpoints). */
|
|
46
51
|
expectNoContent?: boolean;
|
|
@@ -73,6 +78,7 @@ declare class GitHubSource implements Source {
|
|
|
73
78
|
private readonly owner;
|
|
74
79
|
private readonly name;
|
|
75
80
|
private readonly repoPath;
|
|
81
|
+
private readonly repoRoot;
|
|
76
82
|
private readonly workflowDir;
|
|
77
83
|
constructor(rest: GitHubRestClient, opts: SourceOptions);
|
|
78
84
|
whoami(): Promise<{
|
|
@@ -83,14 +89,18 @@ declare class GitHubSource implements Source {
|
|
|
83
89
|
createRuleset(payload: Record<string, unknown>): Promise<Ruleset>;
|
|
84
90
|
updateRuleset(id: number, payload: Record<string, unknown>): Promise<Ruleset>;
|
|
85
91
|
updateRepoSettings(settings: RepoSettings): Promise<void>;
|
|
92
|
+
protectBranch(branch: string, payload: Record<string, unknown>): Promise<void>;
|
|
86
93
|
enableVulnerabilityAlerts(): Promise<void>;
|
|
87
94
|
enableAutomatedSecurityFixes(): Promise<void>;
|
|
88
95
|
enableSecretScanning(): Promise<void>;
|
|
96
|
+
enableCodeScanning(): Promise<string>;
|
|
97
|
+
enableDependencyGraph(): Promise<void>;
|
|
89
98
|
enablePrivateVulnerabilityReporting(): Promise<void>;
|
|
90
99
|
listWorkflowFiles(): Promise<string[]>;
|
|
91
100
|
readWorkflowFile(name: string): Promise<string | null>;
|
|
92
101
|
writeWorkflowFile(name: string, contents: string): Promise<void>;
|
|
93
102
|
removeWorkflowFile(name: string): Promise<void>;
|
|
103
|
+
writeRepoFile(path: string, contents: string): Promise<void>;
|
|
94
104
|
}
|
|
95
105
|
//#endregion
|
|
96
106
|
//#region src/capabilities/secrets.d.ts
|
|
@@ -151,8 +161,15 @@ declare class GitHubCi implements Ci {
|
|
|
151
161
|
//#region src/capabilities/issues.d.ts
|
|
152
162
|
interface IssuesOptions {
|
|
153
163
|
repo: string;
|
|
154
|
-
/**
|
|
155
|
-
|
|
164
|
+
/**
|
|
165
|
+
* Lifecycle slot → status label name. Optional at construction; if
|
|
166
|
+
* omitted, capability methods that need labels (`transition`,
|
|
167
|
+
* `doctor`) degrade gracefully — `transition` throws a clear error,
|
|
168
|
+
* `doctor` reports the two label-backed slots as unresolved. This
|
|
169
|
+
* lets the plugin load in configs where the operator hasn't picked
|
|
170
|
+
* labels yet without failing the whole runtime.
|
|
171
|
+
*/
|
|
172
|
+
labels?: {
|
|
156
173
|
inProgress: string;
|
|
157
174
|
inReview: string;
|
|
158
175
|
};
|
|
@@ -185,6 +202,32 @@ declare class GitHubIssues implements Issues {
|
|
|
185
202
|
private mapIssue;
|
|
186
203
|
}
|
|
187
204
|
//#endregion
|
|
205
|
+
//#region src/verify-token.d.ts
|
|
206
|
+
/**
|
|
207
|
+
* `verifyToken` — plugin-level export used by `holocron auth set` +
|
|
208
|
+
* `holocron auth check`. Hits `GET /user` and translates the response
|
|
209
|
+
* into the normalized `VerifyTokenResult` shape.
|
|
210
|
+
*
|
|
211
|
+
* Kept as a standalone function (not a capability method) so the auth
|
|
212
|
+
* command can call it without initializing the full plugin — plugin
|
|
213
|
+
* construction requires an already-resolved token, which is exactly
|
|
214
|
+
* what we don't have yet at bootstrap time.
|
|
215
|
+
*/
|
|
216
|
+
interface VerifyTokenSuccess {
|
|
217
|
+
ok: true;
|
|
218
|
+
subject: string;
|
|
219
|
+
}
|
|
220
|
+
interface VerifyTokenFailure {
|
|
221
|
+
ok: false;
|
|
222
|
+
message: string;
|
|
223
|
+
}
|
|
224
|
+
type VerifyTokenResult = VerifyTokenSuccess | VerifyTokenFailure;
|
|
225
|
+
interface VerifyTokenOptions {
|
|
226
|
+
baseUrl?: string;
|
|
227
|
+
fetch?: typeof fetch;
|
|
228
|
+
}
|
|
229
|
+
declare function verifyToken(token: string, opts?: VerifyTokenOptions): Promise<VerifyTokenResult>;
|
|
230
|
+
//#endregion
|
|
188
231
|
//#region src/index.d.ts
|
|
189
232
|
interface GitHubPluginOptions extends ResolveTokenInput {
|
|
190
233
|
/** "owner/name" — e.g., "theholocron/holocron". Required. */
|
|
@@ -224,5 +267,12 @@ declare function createPlugin(options: GitHubPluginOptions): {
|
|
|
224
267
|
issues: () => Issues;
|
|
225
268
|
};
|
|
226
269
|
};
|
|
270
|
+
/**
|
|
271
|
+
* One-line hint printed by `holocron auth set github` when no token
|
|
272
|
+
* is supplied or the supplied token is rejected. Generate a PAT at
|
|
273
|
+
* https://github.com/settings/tokens with `repo` + `admin:repo_hook`
|
|
274
|
+
* scopes (add `admin:org` for org-level operations).
|
|
275
|
+
*/
|
|
276
|
+
declare const AUTH_HINT: string;
|
|
227
277
|
//#endregion
|
|
228
|
-
export { type Auth, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubPluginOptions, GitHubRestClient, GitHubSecrets, GitHubSource, PluginContext, ResolveTokenInput, ci, createContext, createPlugin, encryptSecret, environments, issues, resolveToken, secrets, source };
|
|
278
|
+
export { AUTH_HINT, type Auth, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubPluginOptions, GitHubRestClient, GitHubSecrets, GitHubSource, PluginContext, ResolveTokenInput, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, ci, createContext, createPlugin, encryptSecret, environments, issues, resolveToken, secrets, source, verifyToken };
|
package/dist/index.mjs
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
|
+
import { ProviderApiError, getToken } from "@theholocron/cli";
|
|
2
3
|
import { mkdir, readFile, readdir, rm, stat, writeFile } from "node:fs/promises";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
import { ProviderApiError } from "@theholocron/cli";
|
|
4
|
+
import { dirname, join } from "node:path";
|
|
5
5
|
//#region src/auth.ts
|
|
6
6
|
/**
|
|
7
7
|
* Token resolution for the GitHub plugin. See README §Auth.
|
|
8
8
|
*
|
|
9
|
-
* Resolution order
|
|
9
|
+
* Resolution order (matches the standard 4-step precedence set by
|
|
10
|
+
* `.notes/tech-auth-bootstrap.spec.md`):
|
|
10
11
|
* 1. explicit `token` argument (from `--token` flag)
|
|
11
12
|
* 2. HOLOCRON_GH_TOKEN env var (preferred over GITHUB_TOKEN — clearer intent)
|
|
12
13
|
* 3. GITHUB_TOKEN env var (auto-injected in GH Actions)
|
|
14
|
+
* 4. keyring (com.theholocron.cli / "github")
|
|
15
|
+
* 5. AuthError naming all four options + the bootstrap hint
|
|
13
16
|
*
|
|
14
17
|
* No `gh auth token` fallback by design — it usually has narrower
|
|
15
18
|
* scopes than admin commands need.
|
|
@@ -19,8 +22,9 @@ var AuthError = class extends Error {
|
|
|
19
22
|
};
|
|
20
23
|
function resolveToken(input = {}) {
|
|
21
24
|
const env = input.env ?? process.env;
|
|
22
|
-
const
|
|
23
|
-
|
|
25
|
+
const keyring = input.keyring ?? getToken;
|
|
26
|
+
const token = input.cliToken || env.HOLOCRON_GH_TOKEN || env.GITHUB_TOKEN || keyring("github");
|
|
27
|
+
if (!token) throw new AuthError("no GitHub token found. Pass --token <PAT>, set HOLOCRON_GH_TOKEN / GITHUB_TOKEN, or run: holocron auth set github <PAT>");
|
|
24
28
|
return token;
|
|
25
29
|
}
|
|
26
30
|
//#endregion
|
|
@@ -214,6 +218,7 @@ var GitHubIssues = class {
|
|
|
214
218
|
via: "closed (completed)"
|
|
215
219
|
};
|
|
216
220
|
}
|
|
221
|
+
if (!this.labels) throw new Error(`transition to \`${slot}\` requires \`labels\` in plugin options: { inProgress: '<label>', inReview: '<label>' }`);
|
|
217
222
|
const targetLabel = slot === "inProgress" ? this.labels.inProgress : this.labels.inReview;
|
|
218
223
|
const alreadyOpen = issue.state === "open";
|
|
219
224
|
const alreadyLabeled = currentStatusLabels.includes(targetLabel);
|
|
@@ -255,20 +260,19 @@ var GitHubIssues = class {
|
|
|
255
260
|
name: "open (no status label)",
|
|
256
261
|
category: "open"
|
|
257
262
|
},
|
|
258
|
-
{
|
|
263
|
+
...this.labels ? [{
|
|
259
264
|
name: `open + ${this.labels.inProgress}`,
|
|
260
265
|
category: "in-progress"
|
|
261
|
-
},
|
|
262
|
-
{
|
|
266
|
+
}, {
|
|
263
267
|
name: `open + ${this.labels.inReview}`,
|
|
264
268
|
category: "in-review"
|
|
265
|
-
},
|
|
269
|
+
}] : [],
|
|
266
270
|
{
|
|
267
271
|
name: "closed",
|
|
268
272
|
category: "done"
|
|
269
273
|
}
|
|
270
274
|
];
|
|
271
|
-
const lifecycle = [
|
|
275
|
+
const lifecycle = this.labels ? [
|
|
272
276
|
{
|
|
273
277
|
slot: "inProgress",
|
|
274
278
|
value: this.labels.inProgress,
|
|
@@ -287,6 +291,25 @@ var GitHubIssues = class {
|
|
|
287
291
|
resolved: true,
|
|
288
292
|
note: "(intrinsic — GitHub close-with-reason)"
|
|
289
293
|
}
|
|
294
|
+
] : [
|
|
295
|
+
{
|
|
296
|
+
slot: "inProgress",
|
|
297
|
+
value: null,
|
|
298
|
+
resolved: false,
|
|
299
|
+
note: "no `labels` configured in plugin options — transitions to `inProgress` will error"
|
|
300
|
+
},
|
|
301
|
+
{
|
|
302
|
+
slot: "inReview",
|
|
303
|
+
value: null,
|
|
304
|
+
resolved: false,
|
|
305
|
+
note: "no `labels` configured in plugin options — transitions to `inReview` will error"
|
|
306
|
+
},
|
|
307
|
+
{
|
|
308
|
+
slot: "done",
|
|
309
|
+
value: "closed (state_reason=completed)",
|
|
310
|
+
resolved: true,
|
|
311
|
+
note: "(intrinsic — GitHub close-with-reason)"
|
|
312
|
+
}
|
|
290
313
|
];
|
|
291
314
|
return {
|
|
292
315
|
authedAs: `${me.displayName} (${me.emailAddress ?? me.id})`,
|
|
@@ -309,10 +332,10 @@ var GitHubIssues = class {
|
|
|
309
332
|
let category = "open";
|
|
310
333
|
let statusName = raw.state === "closed" ? "closed" : "open";
|
|
311
334
|
if (raw.state === "closed") category = "done";
|
|
312
|
-
else if (statusLabels.includes(this.labels.inProgress)) {
|
|
335
|
+
else if (this.labels && statusLabels.includes(this.labels.inProgress)) {
|
|
313
336
|
category = "in-progress";
|
|
314
337
|
statusName = `open + ${this.labels.inProgress}`;
|
|
315
|
-
} else if (statusLabels.includes(this.labels.inReview)) {
|
|
338
|
+
} else if (this.labels && statusLabels.includes(this.labels.inReview)) {
|
|
316
339
|
category = "in-review";
|
|
317
340
|
statusName = `open + ${this.labels.inReview}`;
|
|
318
341
|
}
|
|
@@ -449,6 +472,7 @@ var GitHubSource = class {
|
|
|
449
472
|
owner;
|
|
450
473
|
name;
|
|
451
474
|
repoPath;
|
|
475
|
+
repoRoot;
|
|
452
476
|
workflowDir;
|
|
453
477
|
constructor(rest, opts) {
|
|
454
478
|
this.rest = rest;
|
|
@@ -456,6 +480,7 @@ var GitHubSource = class {
|
|
|
456
480
|
this.owner = owner;
|
|
457
481
|
this.name = name;
|
|
458
482
|
this.repoPath = `/repos/${owner}/${name}`;
|
|
483
|
+
this.repoRoot = opts.repoRoot;
|
|
459
484
|
this.workflowDir = join(opts.repoRoot, ".github", "workflows");
|
|
460
485
|
}
|
|
461
486
|
async whoami() {
|
|
@@ -490,6 +515,12 @@ var GitHubSource = class {
|
|
|
490
515
|
body: settings
|
|
491
516
|
});
|
|
492
517
|
}
|
|
518
|
+
async protectBranch(branch, payload) {
|
|
519
|
+
await this.rest.request(`${this.repoPath}/branches/${encodeURIComponent(branch)}/protection`, {
|
|
520
|
+
method: "PUT",
|
|
521
|
+
body: payload
|
|
522
|
+
});
|
|
523
|
+
}
|
|
493
524
|
async enableVulnerabilityAlerts() {
|
|
494
525
|
await this.rest.request(`${this.repoPath}/vulnerability-alerts`, {
|
|
495
526
|
method: "PUT",
|
|
@@ -507,7 +538,28 @@ var GitHubSource = class {
|
|
|
507
538
|
method: "PATCH",
|
|
508
539
|
body: { security_and_analysis: {
|
|
509
540
|
secret_scanning: { status: "enabled" },
|
|
510
|
-
secret_scanning_push_protection: { status: "enabled" }
|
|
541
|
+
secret_scanning_push_protection: { status: "enabled" },
|
|
542
|
+
secret_scanning_validity_checks: { status: "enabled" },
|
|
543
|
+
secret_scanning_non_provider_patterns: { status: "enabled" }
|
|
544
|
+
} }
|
|
545
|
+
});
|
|
546
|
+
}
|
|
547
|
+
async enableCodeScanning() {
|
|
548
|
+
return `run ${(await this.rest.request(`${this.repoPath}/code-scanning/default-setup`, {
|
|
549
|
+
method: "PATCH",
|
|
550
|
+
body: {
|
|
551
|
+
state: "configured",
|
|
552
|
+
query_suite: "extended",
|
|
553
|
+
threat_model: "remote_and_local"
|
|
554
|
+
}
|
|
555
|
+
})).run_id}`;
|
|
556
|
+
}
|
|
557
|
+
async enableDependencyGraph() {
|
|
558
|
+
await this.rest.request(this.repoPath, {
|
|
559
|
+
method: "PATCH",
|
|
560
|
+
body: { security_and_analysis: {
|
|
561
|
+
dependency_graph: { status: "enabled" },
|
|
562
|
+
dependency_graph_autosubmit_action: { status: "enabled" }
|
|
511
563
|
} }
|
|
512
564
|
});
|
|
513
565
|
}
|
|
@@ -545,6 +597,11 @@ var GitHubSource = class {
|
|
|
545
597
|
throw err;
|
|
546
598
|
}
|
|
547
599
|
}
|
|
600
|
+
async writeRepoFile(path, contents) {
|
|
601
|
+
const full = join(this.repoRoot, path);
|
|
602
|
+
await ensureDir(dirname(full));
|
|
603
|
+
await writeFile(full, contents, "utf8");
|
|
604
|
+
}
|
|
548
605
|
};
|
|
549
606
|
function isENOENT(err) {
|
|
550
607
|
return typeof err === "object" && err !== null && "code" in err && err.code === "ENOENT";
|
|
@@ -579,7 +636,9 @@ var GitHubRestClient = class {
|
|
|
579
636
|
constructor(opts) {
|
|
580
637
|
this.token = opts.token;
|
|
581
638
|
this.fetchImpl = opts.fetch ?? globalThis.fetch;
|
|
582
|
-
|
|
639
|
+
let url = opts.baseUrl ?? "https://api.github.com";
|
|
640
|
+
while (url.endsWith("/")) url = url.slice(0, -1);
|
|
641
|
+
this.baseUrl = url;
|
|
583
642
|
}
|
|
584
643
|
async request(path, opts = {}) {
|
|
585
644
|
const url = `${this.baseUrl}${path}`;
|
|
@@ -608,6 +667,36 @@ var GitHubRestClient = class {
|
|
|
608
667
|
}
|
|
609
668
|
};
|
|
610
669
|
//#endregion
|
|
670
|
+
//#region src/verify-token.ts
|
|
671
|
+
/**
|
|
672
|
+
* `verifyToken` — plugin-level export used by `holocron auth set` +
|
|
673
|
+
* `holocron auth check`. Hits `GET /user` and translates the response
|
|
674
|
+
* into the normalized `VerifyTokenResult` shape.
|
|
675
|
+
*
|
|
676
|
+
* Kept as a standalone function (not a capability method) so the auth
|
|
677
|
+
* command can call it without initializing the full plugin — plugin
|
|
678
|
+
* construction requires an already-resolved token, which is exactly
|
|
679
|
+
* what we don't have yet at bootstrap time.
|
|
680
|
+
*/
|
|
681
|
+
async function verifyToken(token, opts = {}) {
|
|
682
|
+
const restOpts = { token };
|
|
683
|
+
if (opts.baseUrl !== void 0) restOpts.baseUrl = opts.baseUrl;
|
|
684
|
+
if (opts.fetch !== void 0) restOpts.fetch = opts.fetch;
|
|
685
|
+
const rest = new GitHubRestClient(restOpts);
|
|
686
|
+
try {
|
|
687
|
+
const me = await rest.request("/user");
|
|
688
|
+
return {
|
|
689
|
+
ok: true,
|
|
690
|
+
subject: `user @ ${me.login ?? me.email ?? "unknown"}`
|
|
691
|
+
};
|
|
692
|
+
} catch (err) {
|
|
693
|
+
return {
|
|
694
|
+
ok: false,
|
|
695
|
+
message: err instanceof Error ? err.message : String(err)
|
|
696
|
+
};
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
//#endregion
|
|
611
700
|
//#region src/index.ts
|
|
612
701
|
function createContext(options) {
|
|
613
702
|
return {
|
|
@@ -637,11 +726,9 @@ function ci(ctx) {
|
|
|
637
726
|
return new GitHubCi(ctx.rest, { repo: ctx.repo });
|
|
638
727
|
}
|
|
639
728
|
function issues(ctx) {
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
labels: ctx.options.labels
|
|
644
|
-
});
|
|
729
|
+
const opts = { repo: ctx.repo };
|
|
730
|
+
if (ctx.options.labels !== void 0) opts.labels = ctx.options.labels;
|
|
731
|
+
return new GitHubIssues(ctx.rest, opts);
|
|
645
732
|
}
|
|
646
733
|
function createPlugin(options) {
|
|
647
734
|
const ctx = createContext(options);
|
|
@@ -656,5 +743,12 @@ function createPlugin(options) {
|
|
|
656
743
|
}
|
|
657
744
|
};
|
|
658
745
|
}
|
|
746
|
+
/**
|
|
747
|
+
* One-line hint printed by `holocron auth set github` when no token
|
|
748
|
+
* is supplied or the supplied token is rejected. Generate a PAT at
|
|
749
|
+
* https://github.com/settings/tokens with `repo` + `admin:repo_hook`
|
|
750
|
+
* scopes (add `admin:org` for org-level operations).
|
|
751
|
+
*/
|
|
752
|
+
const AUTH_HINT = "generate a Personal Access Token at https://github.com/settings/tokens (scopes: repo, admin:repo_hook — plus admin:org for org-level ops), then run: holocron auth set github <PAT>";
|
|
659
753
|
//#endregion
|
|
660
|
-
export { AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubRestClient, GitHubSecrets, GitHubSource, ci, createContext, createPlugin, encryptSecret, environments, issues, resolveToken, secrets, source };
|
|
754
|
+
export { AUTH_HINT, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubRestClient, GitHubSecrets, GitHubSource, ci, createContext, createPlugin, encryptSecret, environments, issues, resolveToken, secrets, source, verifyToken };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theholocron/holocron-plugin-github",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.5",
|
|
4
4
|
"description": "Holocron plugin for GitHub. Implements source, ci, secrets, environments, and issues capabilities against the GitHub REST API.",
|
|
5
5
|
"homepage": "https://github.com/theholocron/holocron/tree/main/packages/holocron-plugin-github#readme",
|
|
6
6
|
"bugs": "https://github.com/theholocron/holocron/issues",
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
}
|
|
22
22
|
},
|
|
23
23
|
"peerDependencies": {
|
|
24
|
-
"@theholocron/cli": "2.0.0-alpha.
|
|
24
|
+
"@theholocron/cli": "2.0.0-alpha.5"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"libsodium-wrappers": "^0.7.15"
|
|
@@ -37,7 +37,8 @@
|
|
|
37
37
|
"typescript": "^5.9.3",
|
|
38
38
|
"vitest": "^3.2.6",
|
|
39
39
|
"tsdown": "^0.22.3",
|
|
40
|
-
"
|
|
40
|
+
"tsx": "^4.22.4",
|
|
41
|
+
"@theholocron/cli": "2.0.0-alpha.5"
|
|
41
42
|
},
|
|
42
43
|
"publishConfig": {
|
|
43
44
|
"access": "public"
|
|
@@ -52,7 +53,8 @@
|
|
|
52
53
|
"typecheck": "tsc --noEmit",
|
|
53
54
|
"test": "vitest run",
|
|
54
55
|
"test:watch": "vitest",
|
|
55
|
-
"test:coverage": "vitest run --coverage"
|
|
56
|
+
"test:coverage": "vitest run --coverage",
|
|
57
|
+
"validate": "tsx scripts/validate.mjs"
|
|
56
58
|
},
|
|
57
59
|
"types": "./dist/index.d.mts"
|
|
58
60
|
}
|