@theholocron/holocron-plugin-github 5.0.0-alpha.184 → 5.0.0-alpha.185

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/dist/index.d.mts CHANGED
@@ -6,6 +6,7 @@ declare const resolveIssuesToken: (input?: ResolveTokenInput) => string;
6
6
  declare const resolveSyncToken: (input?: ResolveTokenInput) => string;
7
7
  declare const resolveReleaseToken: (input?: ResolveTokenInput) => string;
8
8
  declare const resolveAdminToken: (input?: ResolveTokenInput) => string;
9
+ declare const resolveSecretsToken: (input?: ResolveTokenInput) => string;
9
10
  declare const resolveDeployToken: (input?: ResolveTokenInput) => string;
10
11
  declare const resolveOrgToken: (input?: ResolveTokenInput) => string;
11
12
  //#endregion
@@ -106,9 +107,16 @@ interface SecretsOptions {
106
107
  declare class GitHubSecrets implements Secrets {
107
108
  private readonly client;
108
109
  private readonly opts;
110
+ private readonly orgClient?;
109
111
  readonly key: "secrets";
110
112
  readonly providerName = "github";
111
- constructor(client: GitHubClient, opts: SecretsOptions);
113
+ /**
114
+ * `client` handles repo and environment scopes; `orgClient`, when given, handles
115
+ * the organization scope. They differ when a dedicated org-only token exists:
116
+ * it can write org secrets but not repo ones, and `github.admin` is the reverse.
117
+ */
118
+ constructor(client: GitHubClient, opts: SecretsOptions, orgClient?: GitHubClient | undefined);
119
+ private clientFor;
112
120
  listSecrets(scope: SecretScope): Promise<string[]>;
113
121
  setSecret(scope: SecretScope, name: string, value: string): Promise<void>;
114
122
  deleteSecret(scope: SecretScope, name: string): Promise<void>;
@@ -214,7 +222,7 @@ interface PluginContext {
214
222
  repoRoot: string;
215
223
  }
216
224
  declare function source(ctx: PluginContext, orgClient?: GitHubClient): Source;
217
- declare function secrets(ctx: PluginContext): Secrets;
225
+ declare function secrets(ctx: PluginContext, orgClient?: GitHubClient): Secrets;
218
226
  declare function environments(ctx: PluginContext): Environments;
219
227
  declare function ci(ctx: PluginContext): Ci;
220
228
  declare function issues(ctx: PluginContext): Issues;
@@ -234,4 +242,4 @@ declare function createPlugin(options: GitHubPluginOptions): {
234
242
  */
235
243
  declare const AUTH_HINT: string;
236
244
  //#endregion
237
- export { AUTH_HINT, type Auth, AuthError, type CanonicalLabel, GitHubCi, type GitHubClientOptions, GitHubEnvironments, GitHubIssues, GitHubPluginOptions, GitHubSecrets, GitHubSource, type NormalizedTeamEntry, PluginContext, type ResolveTokenInput, type TeamEntry, type TeamPermission, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, ci, createFeatureResolver, createGitHubClient, createPlugin, encryptSecret, environments, issues, normalizeTeamEntry, resolveAdminToken, resolveDeployToken, resolveIssuesToken, resolveOrgToken, resolveReadToken, resolveReleaseToken, resolveSyncToken, secrets, source, syncLabels, syncTeams, verifyToken };
245
+ export { AUTH_HINT, type Auth, AuthError, type CanonicalLabel, GitHubCi, type GitHubClientOptions, GitHubEnvironments, GitHubIssues, GitHubPluginOptions, GitHubSecrets, GitHubSource, type NormalizedTeamEntry, PluginContext, type ResolveTokenInput, type TeamEntry, type TeamPermission, type VerifyTokenFailure, type VerifyTokenResult, type VerifyTokenSuccess, ci, createFeatureResolver, createGitHubClient, createPlugin, encryptSecret, environments, issues, normalizeTeamEntry, resolveAdminToken, resolveDeployToken, resolveIssuesToken, resolveOrgToken, resolveReadToken, resolveReleaseToken, resolveSecretsToken, resolveSyncToken, secrets, source, syncLabels, syncTeams, verifyToken };
package/dist/index.mjs CHANGED
@@ -26,6 +26,10 @@ const resolveAdminToken = createFeatureResolver({
26
26
  envName: "HOLOCRON_ADMIN_TOKEN",
27
27
  keyringKey: "github.admin"
28
28
  });
29
+ const resolveSecretsToken = createFeatureResolver({
30
+ envName: "HOLOCRON_SECRETS_TOKEN",
31
+ keyringKey: "github.secrets"
32
+ });
29
33
  const resolveDeployToken = createFeatureResolver({
30
34
  envName: "HOLOCRON_DEPLOY_TOKEN",
31
35
  keyringKey: "github.deploy"
@@ -376,27 +380,38 @@ async function encryptSecret(publicKeyBase64, value) {
376
380
  var GitHubSecrets = class {
377
381
  client;
378
382
  opts;
383
+ orgClient;
379
384
  key = "secrets";
380
385
  providerName = "github";
381
- constructor(client, opts) {
386
+ /**
387
+ * `client` handles repo and environment scopes; `orgClient`, when given, handles
388
+ * the organization scope. They differ when a dedicated org-only token exists:
389
+ * it can write org secrets but not repo ones, and `github.admin` is the reverse.
390
+ */
391
+ constructor(client, opts, orgClient) {
382
392
  this.client = client;
383
393
  this.opts = opts;
394
+ this.orgClient = orgClient;
395
+ }
396
+ clientFor(scope) {
397
+ return scope.kind === "organization" ? this.orgClient ?? this.client : this.client;
384
398
  }
385
399
  async listSecrets(scope) {
386
- return this.client.secrets.listSecrets(this.opts.repo, toGHScope(scope));
400
+ return this.clientFor(scope).secrets.listSecrets(this.opts.repo, toGHScope(scope));
387
401
  }
388
402
  async setSecret(scope, name, value) {
389
403
  const ghScope = toGHScope(scope);
390
- const pk = await this.client.secrets.getPublicKey(this.opts.repo, ghScope);
404
+ const client = this.clientFor(scope);
405
+ const pk = await client.secrets.getPublicKey(this.opts.repo, ghScope);
391
406
  const body = {
392
407
  encrypted_value: await encryptSecret(pk.key, value),
393
408
  key_id: pk.key_id
394
409
  };
395
410
  if (scope.kind === "organization") body.visibility = "all";
396
- await this.client.secrets.putSecret(this.opts.repo, ghScope, name, body);
411
+ await client.secrets.putSecret(this.opts.repo, ghScope, name, body);
397
412
  }
398
413
  async deleteSecret(scope, name) {
399
- await this.client.secrets.deleteSecret(this.opts.repo, toGHScope(scope), name);
414
+ await this.clientFor(scope).secrets.deleteSecret(this.opts.repo, toGHScope(scope), name);
400
415
  }
401
416
  };
402
417
  function toGHScope(scope) {
@@ -687,8 +702,8 @@ function source(ctx, orgClient) {
687
702
  fetch: ctx.options.fetch
688
703
  });
689
704
  }
690
- function secrets(ctx) {
691
- return new GitHubSecrets(ctx.client, { repo: ctx.repo });
705
+ function secrets(ctx, orgClient) {
706
+ return new GitHubSecrets(ctx.client, { repo: ctx.repo }, orgClient);
692
707
  }
693
708
  function environments(ctx) {
694
709
  return new GitHubEnvironments(ctx.client, { repo: ctx.repo });
@@ -715,6 +730,40 @@ function createPlugin(options) {
715
730
  repoRoot: options.repoRoot ?? process.cwd()
716
731
  };
717
732
  }
733
+ /** A token, or undefined when that feature token is simply not configured. */
734
+ function tryResolve(resolver) {
735
+ try {
736
+ return resolver(options);
737
+ } catch (err) {
738
+ if (err instanceof AuthError) return void 0;
739
+ throw err;
740
+ }
741
+ }
742
+ /**
743
+ * Organization secrets need an org-resource-owner token (`github.secrets`);
744
+ * repo and environment secrets need `github.admin`. Each scope prefers its own
745
+ * token and falls back to the other, so a setup with only one of them keeps
746
+ * working, and an explicit `--token` serves both. With neither configured this
747
+ * fails exactly as the admin-token capabilities do.
748
+ */
749
+ function makeSecrets() {
750
+ const secretsToken = tryResolve(resolveSecretsToken);
751
+ const adminToken = tryResolve(resolveAdminToken);
752
+ if (!secretsToken && !adminToken) resolveAdminToken(options);
753
+ const clientFor = (token) => createGitHubClient$1({
754
+ token,
755
+ baseUrl: options.baseUrl,
756
+ fetch: options.fetch
757
+ });
758
+ const repoClient = clientFor(adminToken ?? secretsToken);
759
+ const orgClient = clientFor(secretsToken ?? adminToken);
760
+ return secrets({
761
+ options,
762
+ client: repoClient,
763
+ repo: options.repo,
764
+ repoRoot: options.repoRoot ?? process.cwd()
765
+ }, orgClient);
766
+ }
718
767
  function makeOrgClient() {
719
768
  try {
720
769
  const token = resolveOrgToken(options);
@@ -732,7 +781,7 @@ function createPlugin(options) {
732
781
  capabilities: {
733
782
  source: () => source(makeCtx(resolveAdminToken), makeOrgClient()),
734
783
  ci: () => ci(makeCtx(resolveReadToken)),
735
- secrets: () => secrets(makeCtx(resolveAdminToken)),
784
+ secrets: () => makeSecrets(),
736
785
  environments: () => environments(makeCtx(resolveAdminToken)),
737
786
  issues: () => issues(makeCtx(resolveIssuesToken))
738
787
  }
@@ -744,4 +793,4 @@ function createPlugin(options) {
744
793
  */
745
794
  const AUTH_HINT = "generate fine-grained Personal Access Tokens at https://github.com/settings/tokens (one per feature — see docs/tokens.md for required scopes per operation), then run: holocron auth set github.<feature> <PAT>";
746
795
  //#endregion
747
- export { AUTH_HINT, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubSecrets, GitHubSource, ci, createFeatureResolver, createGitHubClient, createPlugin, encryptSecret, environments, issues, normalizeTeamEntry, resolveAdminToken, resolveDeployToken, resolveIssuesToken, resolveOrgToken, resolveReadToken, resolveReleaseToken, resolveSyncToken, secrets, source, syncLabels, syncTeams, verifyToken };
796
+ export { AUTH_HINT, AuthError, GitHubCi, GitHubEnvironments, GitHubIssues, GitHubSecrets, GitHubSource, ci, createFeatureResolver, createGitHubClient, createPlugin, encryptSecret, environments, issues, normalizeTeamEntry, resolveAdminToken, resolveDeployToken, resolveIssuesToken, resolveOrgToken, resolveReadToken, resolveReleaseToken, resolveSecretsToken, resolveSyncToken, secrets, source, syncLabels, syncTeams, verifyToken };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theholocron/holocron-plugin-github",
3
- "version": "5.0.0-alpha.184",
3
+ "version": "5.0.0-alpha.185",
4
4
  "description": "Holocron plugin for GitHub. Implements source, ci, secrets, environments, and issues capabilities against the GitHub REST API.",
5
5
  "keywords": [
6
6
  "ci",
@@ -52,13 +52,13 @@
52
52
  "tsx": "4.23.15",
53
53
  "typescript": "^5.9.3",
54
54
  "vitest": "^4.1.11",
55
- "@theholocron/cli": "5.0.0-alpha.184"
55
+ "@theholocron/cli": "5.0.0-alpha.185"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "@theholocron/fs-utils": "^1.16.0",
59
59
  "@theholocron/github-client": "^1.43.1",
60
60
  "@theholocron/misc-utils": "^1.16.0",
61
- "@theholocron/cli": "5.0.0-alpha.184"
61
+ "@theholocron/cli": "5.0.0-alpha.185"
62
62
  },
63
63
  "engines": {
64
64
  "node": ">=22"