@vivswan/github-settings-as-code 2.0.1-main.1090.g15ef0c9 → 2.0.1-main.1110.g63435fc
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.
Potentially problematic release.
This version of @vivswan/github-settings-as-code might be problematic. Click here for more details.
- package/lib/pkg/cli.js +1 -1
- package/lib/pkg/index.d.ts +129 -1
- package/lib/pkg/index.js +1 -1
- package/lib/pkg/{src-BhuD5Ycj.js → src-B13lb6Pp.js} +146 -23
- package/package.json +1 -1
package/lib/pkg/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { C as SNAPSHOT_ONLY_INPUTS, E as parseSnapshotFileConfig, F as concludeMerge, I as concludeRun, Kt as redactRanges, L as failRun, Rt as GithubApi, S as SNAPSHOT_INPUTS, T as parseConfig, U as PRIVATE_REPORT_CHANNELS, Wt as maskRegistry, _ as INPUT_DECLS, d as runSnapshot, f as runSingle, j as readSettingsFile, k as runMulti, o as snapshotRepository, pt as SECTIONS, s as validateSettings, t as runMerge, tt as describeProblem, u as concludeSnapshot, v as MERGE_INPUTS, y as MERGE_ONLY_INPUTS, yt as sectionGrant } from "./src-
|
|
2
|
+
import { C as SNAPSHOT_ONLY_INPUTS, E as parseSnapshotFileConfig, F as concludeMerge, I as concludeRun, Kt as redactRanges, L as failRun, Rt as GithubApi, S as SNAPSHOT_INPUTS, T as parseConfig, U as PRIVATE_REPORT_CHANNELS, Wt as maskRegistry, _ as INPUT_DECLS, d as runSnapshot, f as runSingle, j as readSettingsFile, k as runMulti, o as snapshotRepository, pt as SECTIONS, s as validateSettings, t as runMerge, tt as describeProblem, u as concludeSnapshot, v as MERGE_INPUTS, y as MERGE_ONLY_INPUTS, yt as sectionGrant } from "./src-B13lb6Pp.js";
|
|
3
3
|
import { appendFileSync, existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname } from "node:path";
|
|
5
5
|
import { ResultAsync, err, ok } from "neverthrow";
|
package/lib/pkg/index.d.ts
CHANGED
|
@@ -2307,6 +2307,22 @@ declare const GRAPHQL_OPS: {
|
|
|
2307
2307
|
repo: string;
|
|
2308
2308
|
} | undefined;
|
|
2309
2309
|
};
|
|
2310
|
+
readonly pinsSnapshot: {
|
|
2311
|
+
readonly name: "EnvironmentPinsSnapshot";
|
|
2312
|
+
readonly kind: "read";
|
|
2313
|
+
readonly query: "query EnvironmentPinsSnapshot($owner: String!, $repo: String!, $cursor: String) { repository(owner: $owner, name: $repo) { pinnedEnvironments(first: 100, after: $cursor) { nodes { position environment { name } } pageInfo { hasNextPage endCursor } } } }";
|
|
2314
|
+
readonly connection: {
|
|
2315
|
+
readonly path: readonly ["repository", "pinnedEnvironments"];
|
|
2316
|
+
};
|
|
2317
|
+
readonly outcomes: {
|
|
2318
|
+
readonly ok: "the pinned environments with their 1-based positions, for the snapshot";
|
|
2319
|
+
};
|
|
2320
|
+
} & {
|
|
2321
|
+
readonly _variables?: {
|
|
2322
|
+
owner: string;
|
|
2323
|
+
repo: string;
|
|
2324
|
+
} | undefined;
|
|
2325
|
+
};
|
|
2310
2326
|
readonly pin: {
|
|
2311
2327
|
readonly name: "PinEnvironment";
|
|
2312
2328
|
readonly kind: "write";
|
|
@@ -2428,6 +2444,22 @@ declare const GRAPHQL: {
|
|
|
2428
2444
|
repo: string;
|
|
2429
2445
|
} | undefined;
|
|
2430
2446
|
};
|
|
2447
|
+
readonly rulesSnapshot: {
|
|
2448
|
+
readonly name: "BranchProtectionRulesSnapshot";
|
|
2449
|
+
readonly kind: "read";
|
|
2450
|
+
readonly connection: {
|
|
2451
|
+
readonly path: readonly ["repository", "branchProtectionRules"];
|
|
2452
|
+
};
|
|
2453
|
+
readonly outcomes: {
|
|
2454
|
+
readonly ok: "the repository's classic branch protection rules, for the snapshot";
|
|
2455
|
+
};
|
|
2456
|
+
readonly query: "query BranchProtectionRulesSnapshot($owner: String!, $repo: String!, $cursor: String) {\n repository(owner: $owner, name: $repo) {\n branchProtectionRules(first: 100, after: $cursor) {\n nodes {\n id\n pattern\n isAdminEnforced\n requiresLinearHistory\n allowsForcePushes\n allowsDeletions\n blocksCreations\n requiresConversationResolution\n lockBranch\n lockAllowsFetchAndMerge\n requiresCommitSignatures\n requiresStatusChecks\n requiresStrictStatusChecks\n requiredStatusCheckContexts\n requiresApprovingReviews\n requiredApprovingReviewCount\n requiresCodeOwnerReviews\n dismissesStaleReviews\n requireLastPushApproval\n requiresDeployments\n requiredDeploymentEnvironments\n bypassForcePushAllowances(first: 100) {\n nodes {\n actor {\n __typename\n ... on User { login }\n ... on Team { combinedSlug }\n ... on App { slug }\n }\n }\n pageInfo { hasNextPage }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n }\n}";
|
|
2457
|
+
} & {
|
|
2458
|
+
readonly _variables?: {
|
|
2459
|
+
owner: string;
|
|
2460
|
+
repo: string;
|
|
2461
|
+
} | undefined;
|
|
2462
|
+
};
|
|
2431
2463
|
readonly repoLookup: {
|
|
2432
2464
|
readonly name: "BranchProtectionRepository";
|
|
2433
2465
|
readonly kind: "read";
|
|
@@ -3935,6 +3967,22 @@ declare const byKey: {
|
|
|
3935
3967
|
repo: string;
|
|
3936
3968
|
} | undefined;
|
|
3937
3969
|
};
|
|
3970
|
+
readonly pinsSnapshot: {
|
|
3971
|
+
readonly name: "EnvironmentPinsSnapshot";
|
|
3972
|
+
readonly kind: "read";
|
|
3973
|
+
readonly query: "query EnvironmentPinsSnapshot($owner: String!, $repo: String!, $cursor: String) { repository(owner: $owner, name: $repo) { pinnedEnvironments(first: 100, after: $cursor) { nodes { position environment { name } } pageInfo { hasNextPage endCursor } } } }";
|
|
3974
|
+
readonly connection: {
|
|
3975
|
+
readonly path: readonly ["repository", "pinnedEnvironments"];
|
|
3976
|
+
};
|
|
3977
|
+
readonly outcomes: {
|
|
3978
|
+
readonly ok: "the pinned environments with their 1-based positions, for the snapshot";
|
|
3979
|
+
};
|
|
3980
|
+
} & {
|
|
3981
|
+
readonly _variables?: {
|
|
3982
|
+
owner: string;
|
|
3983
|
+
repo: string;
|
|
3984
|
+
} | undefined;
|
|
3985
|
+
};
|
|
3938
3986
|
readonly pin: {
|
|
3939
3987
|
readonly name: "PinEnvironment";
|
|
3940
3988
|
readonly kind: "write";
|
|
@@ -4134,6 +4182,22 @@ declare const byKey: {
|
|
|
4134
4182
|
repo: string;
|
|
4135
4183
|
} | undefined;
|
|
4136
4184
|
};
|
|
4185
|
+
readonly pinsSnapshot: {
|
|
4186
|
+
readonly name: "EnvironmentPinsSnapshot";
|
|
4187
|
+
readonly kind: "read";
|
|
4188
|
+
readonly query: "query EnvironmentPinsSnapshot($owner: String!, $repo: String!, $cursor: String) { repository(owner: $owner, name: $repo) { pinnedEnvironments(first: 100, after: $cursor) { nodes { position environment { name } } pageInfo { hasNextPage endCursor } } } }";
|
|
4189
|
+
readonly connection: {
|
|
4190
|
+
readonly path: readonly ["repository", "pinnedEnvironments"];
|
|
4191
|
+
};
|
|
4192
|
+
readonly outcomes: {
|
|
4193
|
+
readonly ok: "the pinned environments with their 1-based positions, for the snapshot";
|
|
4194
|
+
};
|
|
4195
|
+
} & {
|
|
4196
|
+
readonly _variables?: {
|
|
4197
|
+
owner: string;
|
|
4198
|
+
repo: string;
|
|
4199
|
+
} | undefined;
|
|
4200
|
+
};
|
|
4137
4201
|
readonly pin: {
|
|
4138
4202
|
readonly name: "PinEnvironment";
|
|
4139
4203
|
readonly kind: "write";
|
|
@@ -4382,6 +4446,22 @@ declare const byKey: {
|
|
|
4382
4446
|
repo: string;
|
|
4383
4447
|
} | undefined;
|
|
4384
4448
|
};
|
|
4449
|
+
readonly pinsSnapshot: {
|
|
4450
|
+
readonly name: "EnvironmentPinsSnapshot";
|
|
4451
|
+
readonly kind: "read";
|
|
4452
|
+
readonly query: "query EnvironmentPinsSnapshot($owner: String!, $repo: String!, $cursor: String) { repository(owner: $owner, name: $repo) { pinnedEnvironments(first: 100, after: $cursor) { nodes { position environment { name } } pageInfo { hasNextPage endCursor } } } }";
|
|
4453
|
+
readonly connection: {
|
|
4454
|
+
readonly path: readonly ["repository", "pinnedEnvironments"];
|
|
4455
|
+
};
|
|
4456
|
+
readonly outcomes: {
|
|
4457
|
+
readonly ok: "the pinned environments with their 1-based positions, for the snapshot";
|
|
4458
|
+
};
|
|
4459
|
+
} & {
|
|
4460
|
+
readonly _variables?: {
|
|
4461
|
+
owner: string;
|
|
4462
|
+
repo: string;
|
|
4463
|
+
} | undefined;
|
|
4464
|
+
};
|
|
4385
4465
|
readonly pin: {
|
|
4386
4466
|
readonly name: "PinEnvironment";
|
|
4387
4467
|
readonly kind: "write";
|
|
@@ -4559,6 +4639,22 @@ declare const byKey: {
|
|
|
4559
4639
|
repo: string;
|
|
4560
4640
|
} | undefined;
|
|
4561
4641
|
};
|
|
4642
|
+
readonly rulesSnapshot: {
|
|
4643
|
+
readonly name: "BranchProtectionRulesSnapshot";
|
|
4644
|
+
readonly kind: "read";
|
|
4645
|
+
readonly connection: {
|
|
4646
|
+
readonly path: readonly ["repository", "branchProtectionRules"];
|
|
4647
|
+
};
|
|
4648
|
+
readonly outcomes: {
|
|
4649
|
+
readonly ok: "the repository's classic branch protection rules, for the snapshot";
|
|
4650
|
+
};
|
|
4651
|
+
readonly query: "query BranchProtectionRulesSnapshot($owner: String!, $repo: String!, $cursor: String) {\n repository(owner: $owner, name: $repo) {\n branchProtectionRules(first: 100, after: $cursor) {\n nodes {\n id\n pattern\n isAdminEnforced\n requiresLinearHistory\n allowsForcePushes\n allowsDeletions\n blocksCreations\n requiresConversationResolution\n lockBranch\n lockAllowsFetchAndMerge\n requiresCommitSignatures\n requiresStatusChecks\n requiresStrictStatusChecks\n requiredStatusCheckContexts\n requiresApprovingReviews\n requiredApprovingReviewCount\n requiresCodeOwnerReviews\n dismissesStaleReviews\n requireLastPushApproval\n requiresDeployments\n requiredDeploymentEnvironments\n bypassForcePushAllowances(first: 100) {\n nodes {\n actor {\n __typename\n ... on User { login }\n ... on Team { combinedSlug }\n ... on App { slug }\n }\n }\n pageInfo { hasNextPage }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n }\n}";
|
|
4652
|
+
} & {
|
|
4653
|
+
readonly _variables?: {
|
|
4654
|
+
owner: string;
|
|
4655
|
+
repo: string;
|
|
4656
|
+
} | undefined;
|
|
4657
|
+
};
|
|
4562
4658
|
readonly repoLookup: {
|
|
4563
4659
|
readonly name: "BranchProtectionRepository";
|
|
4564
4660
|
readonly kind: "read";
|
|
@@ -4736,6 +4832,22 @@ declare const byKey: {
|
|
|
4736
4832
|
repo: string;
|
|
4737
4833
|
} | undefined;
|
|
4738
4834
|
};
|
|
4835
|
+
readonly rulesSnapshot: {
|
|
4836
|
+
readonly name: "BranchProtectionRulesSnapshot";
|
|
4837
|
+
readonly kind: "read";
|
|
4838
|
+
readonly connection: {
|
|
4839
|
+
readonly path: readonly ["repository", "branchProtectionRules"];
|
|
4840
|
+
};
|
|
4841
|
+
readonly outcomes: {
|
|
4842
|
+
readonly ok: "the repository's classic branch protection rules, for the snapshot";
|
|
4843
|
+
};
|
|
4844
|
+
readonly query: "query BranchProtectionRulesSnapshot($owner: String!, $repo: String!, $cursor: String) {\n repository(owner: $owner, name: $repo) {\n branchProtectionRules(first: 100, after: $cursor) {\n nodes {\n id\n pattern\n isAdminEnforced\n requiresLinearHistory\n allowsForcePushes\n allowsDeletions\n blocksCreations\n requiresConversationResolution\n lockBranch\n lockAllowsFetchAndMerge\n requiresCommitSignatures\n requiresStatusChecks\n requiresStrictStatusChecks\n requiredStatusCheckContexts\n requiresApprovingReviews\n requiredApprovingReviewCount\n requiresCodeOwnerReviews\n dismissesStaleReviews\n requireLastPushApproval\n requiresDeployments\n requiredDeploymentEnvironments\n bypassForcePushAllowances(first: 100) {\n nodes {\n actor {\n __typename\n ... on User { login }\n ... on Team { combinedSlug }\n ... on App { slug }\n }\n }\n pageInfo { hasNextPage }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n }\n}";
|
|
4845
|
+
} & {
|
|
4846
|
+
readonly _variables?: {
|
|
4847
|
+
owner: string;
|
|
4848
|
+
repo: string;
|
|
4849
|
+
} | undefined;
|
|
4850
|
+
};
|
|
4739
4851
|
readonly repoLookup: {
|
|
4740
4852
|
readonly name: "BranchProtectionRepository";
|
|
4741
4853
|
readonly kind: "read";
|
|
@@ -4922,6 +5034,22 @@ declare const byKey: {
|
|
|
4922
5034
|
repo: string;
|
|
4923
5035
|
} | undefined;
|
|
4924
5036
|
};
|
|
5037
|
+
readonly rulesSnapshot: {
|
|
5038
|
+
readonly name: "BranchProtectionRulesSnapshot";
|
|
5039
|
+
readonly kind: "read";
|
|
5040
|
+
readonly connection: {
|
|
5041
|
+
readonly path: readonly ["repository", "branchProtectionRules"];
|
|
5042
|
+
};
|
|
5043
|
+
readonly outcomes: {
|
|
5044
|
+
readonly ok: "the repository's classic branch protection rules, for the snapshot";
|
|
5045
|
+
};
|
|
5046
|
+
readonly query: "query BranchProtectionRulesSnapshot($owner: String!, $repo: String!, $cursor: String) {\n repository(owner: $owner, name: $repo) {\n branchProtectionRules(first: 100, after: $cursor) {\n nodes {\n id\n pattern\n isAdminEnforced\n requiresLinearHistory\n allowsForcePushes\n allowsDeletions\n blocksCreations\n requiresConversationResolution\n lockBranch\n lockAllowsFetchAndMerge\n requiresCommitSignatures\n requiresStatusChecks\n requiresStrictStatusChecks\n requiredStatusCheckContexts\n requiresApprovingReviews\n requiredApprovingReviewCount\n requiresCodeOwnerReviews\n dismissesStaleReviews\n requireLastPushApproval\n requiresDeployments\n requiredDeploymentEnvironments\n bypassForcePushAllowances(first: 100) {\n nodes {\n actor {\n __typename\n ... on User { login }\n ... on Team { combinedSlug }\n ... on App { slug }\n }\n }\n pageInfo { hasNextPage }\n }\n }\n pageInfo { hasNextPage endCursor }\n }\n }\n}";
|
|
5047
|
+
} & {
|
|
5048
|
+
readonly _variables?: {
|
|
5049
|
+
owner: string;
|
|
5050
|
+
repo: string;
|
|
5051
|
+
} | undefined;
|
|
5052
|
+
};
|
|
4925
5053
|
readonly repoLookup: {
|
|
4926
5054
|
readonly name: "BranchProtectionRepository";
|
|
4927
5055
|
readonly kind: "read";
|
|
@@ -5013,7 +5141,7 @@ declare const byKey: {
|
|
|
5013
5141
|
};
|
|
5014
5142
|
}>): Promise<{
|
|
5015
5143
|
value: undefined;
|
|
5016
|
-
notes:
|
|
5144
|
+
notes: string[];
|
|
5017
5145
|
} | {
|
|
5018
5146
|
value: {
|
|
5019
5147
|
name: string;
|
package/lib/pkg/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { $ as renderSnapshotYaml, A as parseSettingsDoc, At as parseReposInput, B as planRedaction, Bt as SECRET_TRANSPORT_WITHHELD, C as SNAPSHOT_ONLY_INPUTS, Ct as endpointMethod, D as DEFAULT_SETTINGS_FILE, Dt as SECTION_KEYS, E as parseSnapshotFileConfig, Et as PROBOT_PARITY_KEYS, F as concludeMerge, Ft as VISIBILITY_FILTERS, G as openReportChannel, Gt as prefixedIo, H as toPublicView, Ht as isRateLimitError, I as concludeRun, It as discoverRepos, J as MARKER_LABEL_CONFIG, Jt as resolveCentralTargets, K as ISSUE_TITLE, Kt as redactRanges, L as failRun, Lt as DEFAULT_API_VERSION, M as createVisibilityResolver, Mt as ARCHIVED_FILTERS, N as getRepoFile, Nt as DEFAULT_DISCOVERY_FILTERS, O as resolveTargets, Ot as SettingsFile, P as MERGE_RESULT, Pt as FORKS_FILTERS, Q as parseRecipient, R as PRIVATE_REPOS_POLICIES, Rt as GithubApi, S as SNAPSHOT_INPUTS, St as grantFor, T as parseConfig, Tt as DOCUMENT_DIRECTIVE_KEYS, U as PRIVATE_REPORT_CHANNELS, Ut as collectingIo, V as publicDetail, Vt as isPermissionError, W as applyMarkerInjection, Wt as maskRegistry, X as deliverArtifactReport, Xt as parseRepoSlug, Y as composeReport, Yt as dedupeTargets, Z as encryptReport, _ as INPUT_DECLS, _t as denialPosture, a as snapshotRepositories, at as preflightProbe, b as MERGE_REJECTED_INPUTS, bt as sectionOperations, c as SNAPSHOT_RESULTS, ct as validateSettingsDoc, d as runSnapshot, dt as mergeLayers, et as RERUN_ADVICE, f as runSingle, ft as stripNulls, g as FILTER_INPUTS, gt as sectionModule, h as DEFAULT_PRIVATE_REPOS, ht as allGraphqlOps, i as renderMergedYaml, it as REPO_RESULTS, j as readSettingsFile, jt as AFFILIATIONS, k as runMulti, kt as UNDECLARED_POLICY_SECTIONS, l as SNAPSHOT_SCHEMA_URL, lt as worstOf, m as readLayerFiles, mt as allEndpoints, n as applyRepository, nt as quoteList, o as snapshotRepository, ot as runForRepo, p as foldLayers, pt as SECTIONS, q as MARKER_LABEL, qt as silentIo, r as checkRepository, rt as SectionSelection, s as validateSettings, st as skippedSectionKeys, t as runMerge, tt as describeProblem, u as concludeSnapshot, ut as describeOptOut, v as MERGE_INPUTS, vt as readGating, w as SNAPSHOT_REJECTED_INPUTS, wt as endpointPath, x as MODES, xt as writeGatedReads, y as MERGE_ONLY_INPUTS, yt as sectionGrant, z as capturingIo, zt as SECRET_RESPONSE_WITHHELD } from "./src-
|
|
1
|
+
import { $ as renderSnapshotYaml, A as parseSettingsDoc, At as parseReposInput, B as planRedaction, Bt as SECRET_TRANSPORT_WITHHELD, C as SNAPSHOT_ONLY_INPUTS, Ct as endpointMethod, D as DEFAULT_SETTINGS_FILE, Dt as SECTION_KEYS, E as parseSnapshotFileConfig, Et as PROBOT_PARITY_KEYS, F as concludeMerge, Ft as VISIBILITY_FILTERS, G as openReportChannel, Gt as prefixedIo, H as toPublicView, Ht as isRateLimitError, I as concludeRun, It as discoverRepos, J as MARKER_LABEL_CONFIG, Jt as resolveCentralTargets, K as ISSUE_TITLE, Kt as redactRanges, L as failRun, Lt as DEFAULT_API_VERSION, M as createVisibilityResolver, Mt as ARCHIVED_FILTERS, N as getRepoFile, Nt as DEFAULT_DISCOVERY_FILTERS, O as resolveTargets, Ot as SettingsFile, P as MERGE_RESULT, Pt as FORKS_FILTERS, Q as parseRecipient, R as PRIVATE_REPOS_POLICIES, Rt as GithubApi, S as SNAPSHOT_INPUTS, St as grantFor, T as parseConfig, Tt as DOCUMENT_DIRECTIVE_KEYS, U as PRIVATE_REPORT_CHANNELS, Ut as collectingIo, V as publicDetail, Vt as isPermissionError, W as applyMarkerInjection, Wt as maskRegistry, X as deliverArtifactReport, Xt as parseRepoSlug, Y as composeReport, Yt as dedupeTargets, Z as encryptReport, _ as INPUT_DECLS, _t as denialPosture, a as snapshotRepositories, at as preflightProbe, b as MERGE_REJECTED_INPUTS, bt as sectionOperations, c as SNAPSHOT_RESULTS, ct as validateSettingsDoc, d as runSnapshot, dt as mergeLayers, et as RERUN_ADVICE, f as runSingle, ft as stripNulls, g as FILTER_INPUTS, gt as sectionModule, h as DEFAULT_PRIVATE_REPOS, ht as allGraphqlOps, i as renderMergedYaml, it as REPO_RESULTS, j as readSettingsFile, jt as AFFILIATIONS, k as runMulti, kt as UNDECLARED_POLICY_SECTIONS, l as SNAPSHOT_SCHEMA_URL, lt as worstOf, m as readLayerFiles, mt as allEndpoints, n as applyRepository, nt as quoteList, o as snapshotRepository, ot as runForRepo, p as foldLayers, pt as SECTIONS, q as MARKER_LABEL, qt as silentIo, r as checkRepository, rt as SectionSelection, s as validateSettings, st as skippedSectionKeys, t as runMerge, tt as describeProblem, u as concludeSnapshot, ut as describeOptOut, v as MERGE_INPUTS, vt as readGating, w as SNAPSHOT_REJECTED_INPUTS, wt as endpointPath, x as MODES, xt as writeGatedReads, y as MERGE_ONLY_INPUTS, yt as sectionGrant, z as capturingIo, zt as SECRET_RESPONSE_WITHHELD } from "./src-B13lb6Pp.js";
|
|
2
2
|
export { AFFILIATIONS, ARCHIVED_FILTERS, DEFAULT_API_VERSION, DEFAULT_DISCOVERY_FILTERS, DEFAULT_PRIVATE_REPOS, DEFAULT_SETTINGS_FILE, DOCUMENT_DIRECTIVE_KEYS, FILTER_INPUTS, FORKS_FILTERS, GithubApi, INPUT_DECLS, ISSUE_TITLE, MARKER_LABEL, MARKER_LABEL_CONFIG, MERGE_INPUTS, MERGE_ONLY_INPUTS, MERGE_REJECTED_INPUTS, MERGE_RESULT, MODES, PRIVATE_REPORT_CHANNELS, PRIVATE_REPOS_POLICIES, PROBOT_PARITY_KEYS, REPO_RESULTS, RERUN_ADVICE, SECRET_RESPONSE_WITHHELD, SECRET_TRANSPORT_WITHHELD, SECTIONS, SECTION_KEYS, SNAPSHOT_INPUTS, SNAPSHOT_ONLY_INPUTS, SNAPSHOT_REJECTED_INPUTS, SNAPSHOT_RESULTS, SNAPSHOT_SCHEMA_URL, SectionSelection, SettingsFile, UNDECLARED_POLICY_SECTIONS, VISIBILITY_FILTERS, allEndpoints, allGraphqlOps, applyMarkerInjection, applyRepository, capturingIo, checkRepository, collectingIo, composeReport, concludeMerge, concludeRun, concludeSnapshot, createVisibilityResolver, dedupeTargets, deliverArtifactReport, denialPosture, describeOptOut, describeProblem, discoverRepos, encryptReport, endpointMethod, endpointPath, failRun, foldLayers, getRepoFile, grantFor, isPermissionError, isRateLimitError, maskRegistry, mergeLayers, openReportChannel, parseConfig, parseRecipient, parseRepoSlug, parseReposInput, parseSettingsDoc, parseSnapshotFileConfig, planRedaction, prefixedIo, preflightProbe, publicDetail, quoteList, readGating, readLayerFiles, readSettingsFile, redactRanges, renderMergedYaml, renderSnapshotYaml, resolveCentralTargets, resolveTargets, runForRepo, runMerge, runMulti, runSingle, runSnapshot, sectionGrant, sectionModule, sectionOperations, silentIo, skippedSectionKeys, snapshotRepositories, snapshotRepository, stripNulls, toPublicView, validateSettings, validateSettingsDoc, worstOf, writeGatedReads };
|
|
@@ -4192,16 +4192,11 @@ const WILDCARD_KEYS = [
|
|
|
4192
4192
|
"required_deployments"
|
|
4193
4193
|
];
|
|
4194
4194
|
const WILDCARD_KEY_SET = new Set(WILDCARD_KEYS);
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4200
|
-
outcomes: {
|
|
4201
|
-
ok: "the repository's classic branch protection rules",
|
|
4202
|
-
NOT_FOUND: "the repository is not visible to the token; read as no rules"
|
|
4203
|
-
},
|
|
4204
|
-
query: `query BranchProtectionRules($owner: String!, $repo: String!, $cursor: String) {
|
|
4195
|
+
/**
|
|
4196
|
+
* The rule selection both rules reads share, so the snapshot's read cannot lag the planner's
|
|
4197
|
+
* translation tables (test/sections/graphql-queries.test.ts asserts every twin is selected).
|
|
4198
|
+
*/
|
|
4199
|
+
const RULES_SELECTION = `($owner: String!, $repo: String!, $cursor: String) {
|
|
4205
4200
|
repository(owner: $owner, name: $repo) {
|
|
4206
4201
|
branchProtectionRules(first: 100, after: $cursor) {
|
|
4207
4202
|
nodes {
|
|
@@ -4241,7 +4236,24 @@ const GRAPHQL = {
|
|
|
4241
4236
|
pageInfo { hasNextPage endCursor }
|
|
4242
4237
|
}
|
|
4243
4238
|
}
|
|
4244
|
-
}
|
|
4239
|
+
}`;
|
|
4240
|
+
const GRAPHQL = {
|
|
4241
|
+
rulesQuery: graphqlOp()({
|
|
4242
|
+
name: "BranchProtectionRules",
|
|
4243
|
+
kind: "read",
|
|
4244
|
+
connection: { path: ["repository", "branchProtectionRules"] },
|
|
4245
|
+
outcomes: {
|
|
4246
|
+
ok: "the repository's classic branch protection rules",
|
|
4247
|
+
NOT_FOUND: "the repository is not visible to the token; read as no rules"
|
|
4248
|
+
},
|
|
4249
|
+
query: `query BranchProtectionRules${RULES_SELECTION}`
|
|
4250
|
+
}),
|
|
4251
|
+
rulesSnapshot: graphqlOp()({
|
|
4252
|
+
name: "BranchProtectionRulesSnapshot",
|
|
4253
|
+
kind: "read",
|
|
4254
|
+
connection: { path: ["repository", "branchProtectionRules"] },
|
|
4255
|
+
outcomes: { ok: "the repository's classic branch protection rules, for the snapshot" },
|
|
4256
|
+
query: `query BranchProtectionRulesSnapshot${RULES_SELECTION}`
|
|
4245
4257
|
}),
|
|
4246
4258
|
repoLookup: graphqlOp()({
|
|
4247
4259
|
name: "BranchProtectionRepository",
|
|
@@ -4325,8 +4337,17 @@ function hasRoutedGraphqlKeys(protection) {
|
|
|
4325
4337
|
async function fetchRules(ctx) {
|
|
4326
4338
|
const read = await ctx.read.rulesQuery.listConnection(repoVariables(ctx));
|
|
4327
4339
|
if ("error" in read) return null;
|
|
4340
|
+
return indexRules(read.items);
|
|
4341
|
+
}
|
|
4342
|
+
/** The snapshot's read: the op tolerates no outcome, so a denial throws with the grant advice. */
|
|
4343
|
+
async function fetchRulesForSnapshot(ctx) {
|
|
4344
|
+
const read = await ctx.read.rulesSnapshot.listConnection(repoVariables(ctx));
|
|
4345
|
+
if ("error" in read) throw new Error("BUG: branches: the snapshot rules query declares no tolerated outcome, yet its read returned an error instead of throwing");
|
|
4346
|
+
return indexRules(read.items);
|
|
4347
|
+
}
|
|
4348
|
+
function indexRules(items) {
|
|
4328
4349
|
const byPattern = /* @__PURE__ */ new Map();
|
|
4329
|
-
for (const node of
|
|
4350
|
+
for (const node of items) if (typeof node === "object" && node !== null) {
|
|
4330
4351
|
const rule = node;
|
|
4331
4352
|
if (rule.bypassForcePushAllowances?.pageInfo?.hasNextPage === true) throw new Error(`branches: the live protection rule "${String(rule.pattern)}" allows more than 100 force-push bypass actors, which this section cannot read back completely; trim the live allowance list below 100 to manage it here`);
|
|
4332
4353
|
byPattern.set(String(rule.pattern), rule);
|
|
@@ -4367,6 +4388,32 @@ function classicViewOfRule(node) {
|
|
|
4367
4388
|
out.required_deployments = node.requiresDeployments === true ? { environments: Array.isArray(node.requiredDeploymentEnvironments) ? node.requiredDeploymentEnvironments : [] } : null;
|
|
4368
4389
|
return out;
|
|
4369
4390
|
}
|
|
4391
|
+
/**
|
|
4392
|
+
* The two routed keys of a LITERAL entry as the snapshot declares them: only a non-empty allowance
|
|
4393
|
+
* list and a requirement that is on. An omitted routed key leaves the live value untouched (unlike
|
|
4394
|
+
* the replacing PUT, which resets an omitted control), so the file pins what is set.
|
|
4395
|
+
*/
|
|
4396
|
+
function routedKeysSnapshot(node) {
|
|
4397
|
+
const view = classicViewOfRule(node);
|
|
4398
|
+
const out = {};
|
|
4399
|
+
const actors = view.force_push_bypassers;
|
|
4400
|
+
if (actors.length > 0) out.force_push_bypassers = actors;
|
|
4401
|
+
if (view.required_deployments !== null) out.required_deployments = view.required_deployments;
|
|
4402
|
+
return out;
|
|
4403
|
+
}
|
|
4404
|
+
/**
|
|
4405
|
+
* A WILDCARD rule as the snapshot declares it: the classic view with every control that is off
|
|
4406
|
+
* dropped and a nested null (an unset review count) omitted, so the entry carries only keys the
|
|
4407
|
+
* wildcard shape accepts and the check reads clean against the same rule.
|
|
4408
|
+
*/
|
|
4409
|
+
function wildcardSnapshot(node) {
|
|
4410
|
+
const out = {};
|
|
4411
|
+
for (const [key, value] of Object.entries(classicViewOfRule(node))) {
|
|
4412
|
+
if (value === false || value === null || Array.isArray(value) && value.length === 0) continue;
|
|
4413
|
+
out[key] = typeof value === "object" && !Array.isArray(value) ? Object.fromEntries(Object.entries(value).filter(([, inner]) => inner !== null)) : value;
|
|
4414
|
+
}
|
|
4415
|
+
return out;
|
|
4416
|
+
}
|
|
4370
4417
|
/** Shape validation already restricted a wildcard entry's keys, so an unknown key here is a bug. */
|
|
4371
4418
|
function translateWildcardProtection(protection) {
|
|
4372
4419
|
const input = {};
|
|
@@ -4696,8 +4743,14 @@ const permission$13 = { repo: ["administration"] };
|
|
|
4696
4743
|
const LiveProtection = z.looseObject({ required_signatures: z.looseObject({ enabled: z.boolean() }).optional() });
|
|
4697
4744
|
/** One item of the protected-branch listing; only the name is read (the protection is probed). */
|
|
4698
4745
|
const LiveBranchSummary = z.looseObject({ name: z.string() });
|
|
4699
|
-
/**
|
|
4700
|
-
|
|
4746
|
+
/**
|
|
4747
|
+
* A literal-pattern rule the REST reads did not surface as a protected branch: no branch of that
|
|
4748
|
+
* name exists (a pattern needs none), or its protection probe was denied. A literal entry applies
|
|
4749
|
+
* through the REST PUT, which needs the branch, so the rule is noted instead of written. The
|
|
4750
|
+
* pattern appears once and the text stays short, so the rendered header line ("# " prefixed)
|
|
4751
|
+
* stays under 256 chars for patterns up to 54 chars.
|
|
4752
|
+
*/
|
|
4753
|
+
const unreachableLiteralRuleNote = (pattern) => `branches[${pattern}]: rule kept out of the snapshot: REST read no protected branch by this name (the branch is missing, or its protection is unreadable); create the branch or fix the grant, then snapshot again`;
|
|
4701
4754
|
const WILDCARD_KEY_ERROR = (name, key) => `the wildcard entry "${name}" declares protection.${key}, which this section does not manage on wildcard rules; only the keys it can round-trip through the GraphQL rule mutations apply here: [${WILDCARD_KEYS.join(", ")}]. For actor lists and richer controls, prefer the rulesets section (the modern successor of classic protection)`;
|
|
4702
4755
|
const branchesSection = {
|
|
4703
4756
|
key: "branches",
|
|
@@ -4798,23 +4851,36 @@ const branchesSection = {
|
|
|
4798
4851
|
},
|
|
4799
4852
|
async snapshot(ctx) {
|
|
4800
4853
|
const listed = parseLive(this, ENDPOINTS$15.listProtected, z.array(LiveBranchSummary), await ctx.read.listProtected.listAll({ query: { protected: "true" } }));
|
|
4854
|
+
const rules = await fetchRulesForSnapshot(ctx);
|
|
4801
4855
|
const entries = [];
|
|
4856
|
+
const notes = [];
|
|
4802
4857
|
for (const { name } of listed) {
|
|
4803
4858
|
const probe = await ctx.read.getProtection.probeAbsent({ params: { branch: name } });
|
|
4804
4859
|
if ("missing" in probe) continue;
|
|
4860
|
+
const rule = rules.get(name);
|
|
4861
|
+
if (rule === void 0) continue;
|
|
4805
4862
|
const live = parseLive(this, ENDPOINTS$15.getProtection, LiveProtection, probe.data, `branch "${name}"`);
|
|
4806
4863
|
entries.push({
|
|
4807
4864
|
name,
|
|
4808
|
-
protection:
|
|
4865
|
+
protection: {
|
|
4866
|
+
...protectionSnapshot(live),
|
|
4867
|
+
...routedKeysSnapshot(rule)
|
|
4868
|
+
}
|
|
4809
4869
|
});
|
|
4810
4870
|
}
|
|
4871
|
+
const written = new Set(entries.map((entry) => entry.name));
|
|
4872
|
+
for (const [pattern, rule] of rules) if (isWildcardPattern(pattern)) entries.push({
|
|
4873
|
+
name: pattern,
|
|
4874
|
+
protection: wildcardSnapshot(rule)
|
|
4875
|
+
});
|
|
4876
|
+
else if (!written.has(pattern)) notes.push(unreachableLiteralRuleNote(pattern));
|
|
4811
4877
|
if (entries.length === 0) return {
|
|
4812
4878
|
value: void 0,
|
|
4813
|
-
notes
|
|
4879
|
+
notes
|
|
4814
4880
|
};
|
|
4815
4881
|
return {
|
|
4816
4882
|
value: entries,
|
|
4817
|
-
notes
|
|
4883
|
+
notes
|
|
4818
4884
|
};
|
|
4819
4885
|
}
|
|
4820
4886
|
};
|
|
@@ -6333,17 +6399,32 @@ async function planEnvironmentSecrets(ctx, section, envName, policy, entries, li
|
|
|
6333
6399
|
}
|
|
6334
6400
|
return planned;
|
|
6335
6401
|
}
|
|
6402
|
+
//#endregion
|
|
6403
|
+
//#region src/sections/environments/pins.ts
|
|
6404
|
+
/**
|
|
6405
|
+
* Pinned environments (the routed `pinned` scalar): the GraphQL operations and the pin/unpin/reorder
|
|
6406
|
+
* planning. plan() gates the call on a declared `pinned` key, so a pin-free file never touches /graphql.
|
|
6407
|
+
*/
|
|
6408
|
+
/** The pins selection both pins reads share, so the snapshot's read cannot lag the planner's. */
|
|
6409
|
+
const PINS_SELECTION = "($owner: String!, $repo: String!, $cursor: String) { repository(owner: $owner, name: $repo) { pinnedEnvironments(first: 100, after: $cursor) { nodes { position environment { name } } pageInfo { hasNextPage endCursor } } } }";
|
|
6336
6410
|
const GRAPHQL_OPS$1 = {
|
|
6337
6411
|
pins: graphqlOp()({
|
|
6338
6412
|
name: "EnvironmentPins",
|
|
6339
6413
|
kind: "read",
|
|
6340
|
-
query:
|
|
6414
|
+
query: `query EnvironmentPins${PINS_SELECTION}`,
|
|
6341
6415
|
connection: { path: ["repository", "pinnedEnvironments"] },
|
|
6342
6416
|
outcomes: {
|
|
6343
6417
|
ok: "the pinned environments with their 1-based positions",
|
|
6344
6418
|
NOT_FOUND: "the repository is not visible to the token; read as no pins (the denial surfaces on the first pin write)"
|
|
6345
6419
|
}
|
|
6346
6420
|
}),
|
|
6421
|
+
pinsSnapshot: graphqlOp()({
|
|
6422
|
+
name: "EnvironmentPinsSnapshot",
|
|
6423
|
+
kind: "read",
|
|
6424
|
+
query: `query EnvironmentPinsSnapshot${PINS_SELECTION}`,
|
|
6425
|
+
connection: { path: ["repository", "pinnedEnvironments"] },
|
|
6426
|
+
outcomes: { ok: "the pinned environments with their 1-based positions, for the snapshot" }
|
|
6427
|
+
}),
|
|
6347
6428
|
pin: graphqlOp()({
|
|
6348
6429
|
name: "PinEnvironment",
|
|
6349
6430
|
kind: "write",
|
|
@@ -6382,7 +6463,16 @@ function livePin(node) {
|
|
|
6382
6463
|
async function listLivePins(ctx) {
|
|
6383
6464
|
const listed = await ctx.read.pins.listConnection(repoVariables(ctx));
|
|
6384
6465
|
if ("error" in listed) return [];
|
|
6385
|
-
return listed.items
|
|
6466
|
+
return rankPins(listed.items);
|
|
6467
|
+
}
|
|
6468
|
+
/** The snapshot's read: the op tolerates no outcome, so a denial throws with the grant advice. */
|
|
6469
|
+
async function snapshotPins(ctx) {
|
|
6470
|
+
const listed = await ctx.read.pinsSnapshot.listConnection(repoVariables(ctx));
|
|
6471
|
+
if ("error" in listed) throw new Error("BUG: environments: the snapshot pins query declares no tolerated outcome, yet its read returned an error instead of throwing");
|
|
6472
|
+
return rankPins(listed.items).map((pin) => pin.name);
|
|
6473
|
+
}
|
|
6474
|
+
function rankPins(nodes) {
|
|
6475
|
+
return nodes.map(livePin).sort((a, b) => a.position - b.position);
|
|
6386
6476
|
}
|
|
6387
6477
|
/** Environment names are case-insensitive on GitHub. */
|
|
6388
6478
|
function pinKey(name) {
|
|
@@ -6513,9 +6603,41 @@ async function planPinned(ctx, declarations) {
|
|
|
6513
6603
|
/**
|
|
6514
6604
|
* The snapshot half of the nested seam: one environment's sub-resource lists read back in their
|
|
6515
6605
|
* declared wrapped form, each under its planner's own default policy (nestedDefaultPolicy), and
|
|
6516
|
-
* the
|
|
6606
|
+
* the pin state read off the GraphQL pins connection folded onto the entries.
|
|
6607
|
+
*/
|
|
6608
|
+
/**
|
|
6609
|
+
* The pin state folded onto the entries: the pinned environments lead, in rank order, each with
|
|
6610
|
+
* `pinned: true` (the planner reads declaration order as pin order, so any other order would plan
|
|
6611
|
+
* a reorder); the rest follow in listing order without the key, since an unpinned environment has
|
|
6612
|
+
* nothing to declare and an absent key leaves a pin untouched. A pin naming no listed environment
|
|
6613
|
+
* (matched case-insensitively, as GitHub names them) cannot be declared, and the declared pins
|
|
6614
|
+
* must lead the live list, so from that rank on no pin is declared; one note names them all.
|
|
6517
6615
|
*/
|
|
6518
|
-
|
|
6616
|
+
function withPins(entries, pins) {
|
|
6617
|
+
const byKey = new Map(entries.map((entry) => [entry.name.toLowerCase(), entry]));
|
|
6618
|
+
const leading = [];
|
|
6619
|
+
const notes = [];
|
|
6620
|
+
const unlistedAt = pins.findIndex((name) => !byKey.has(name.toLowerCase()));
|
|
6621
|
+
const declared = unlistedAt < 0 ? pins : pins.slice(0, unlistedAt);
|
|
6622
|
+
for (const name of declared) {
|
|
6623
|
+
const entry = byKey.get(name.toLowerCase());
|
|
6624
|
+
byKey.delete(name.toLowerCase());
|
|
6625
|
+
const { name: entryName, ...rest } = entry;
|
|
6626
|
+
leading.push({
|
|
6627
|
+
name: entryName,
|
|
6628
|
+
pinned: true,
|
|
6629
|
+
...rest
|
|
6630
|
+
});
|
|
6631
|
+
}
|
|
6632
|
+
if (unlistedAt >= 0) {
|
|
6633
|
+
const undeclared = pins.slice(unlistedAt + 1).map((name) => `"${name}"`);
|
|
6634
|
+
notes.push(`environments: the pinned environment "${pins[unlistedAt]}" is not in the environment listing, so its pin cannot be declared` + (undeclared.length === 0 ? "" : `; the pins ranked after it (${undeclared.join(", ")}) are left without the pinned key too, since declared pins must lead the live list`));
|
|
6635
|
+
}
|
|
6636
|
+
return {
|
|
6637
|
+
entries: [...leading, ...byKey.values()],
|
|
6638
|
+
notes
|
|
6639
|
+
};
|
|
6640
|
+
}
|
|
6519
6641
|
function wrapped(key, entries) {
|
|
6520
6642
|
return {
|
|
6521
6643
|
_undeclared: nestedDefaultPolicy(key),
|
|
@@ -6684,9 +6806,10 @@ const environmentsSection = {
|
|
|
6684
6806
|
});
|
|
6685
6807
|
notes.push(...nestedNotes);
|
|
6686
6808
|
}
|
|
6687
|
-
|
|
6809
|
+
const pinned = withPins(entries, await snapshotPins(ctx));
|
|
6810
|
+
notes.push(...pinned.notes, ...sharedSecretNotes(pinned.entries));
|
|
6688
6811
|
return {
|
|
6689
|
-
value: entries,
|
|
6812
|
+
value: pinned.entries,
|
|
6690
6813
|
notes
|
|
6691
6814
|
};
|
|
6692
6815
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vivswan/github-settings-as-code",
|
|
3
|
-
"version": "2.0.1-main.
|
|
3
|
+
"version": "2.0.1-main.1110.g63435fc",
|
|
4
4
|
"description": "GitHub Action applying declarative repository settings: rulesets, labels, branch protection, and more.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.md",
|
|
6
6
|
"type": "module",
|