github-settings-as-code 3.1.0 → 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/README.md +54 -34
  2. package/dist/cmd/repo-settings.mjs +13 -0
  3. package/dist/cmd/repo-settings.mjs.map +1 -1
  4. package/dist/github/constants.d.mts +2 -0
  5. package/dist/github/constants.d.mts.map +1 -1
  6. package/dist/github/constants.mjs +2 -0
  7. package/dist/github/constants.mjs.map +1 -1
  8. package/dist/github/environments/api/get-environments.d.mts +16 -0
  9. package/dist/github/environments/api/get-environments.d.mts.map +1 -0
  10. package/dist/github/environments/api/get-environments.mjs +98 -0
  11. package/dist/github/environments/api/get-environments.mjs.map +1 -0
  12. package/dist/github/environments/api/index.d.mts +3 -0
  13. package/dist/github/environments/api/index.d.mts.map +1 -0
  14. package/dist/github/environments/api/index.mjs +3 -0
  15. package/dist/github/environments/api/index.mjs.map +1 -0
  16. package/dist/github/environments/api/set-environment.d.mts +10 -0
  17. package/dist/github/environments/api/set-environment.d.mts.map +1 -0
  18. package/dist/github/environments/api/set-environment.mjs +73 -0
  19. package/dist/github/environments/api/set-environment.mjs.map +1 -0
  20. package/dist/github/environments/apply.d.mts +11 -0
  21. package/dist/github/environments/apply.d.mts.map +1 -0
  22. package/dist/github/environments/apply.mjs +67 -0
  23. package/dist/github/environments/apply.mjs.map +1 -0
  24. package/dist/github/environments/backup.d.mts +5 -0
  25. package/dist/github/environments/backup.d.mts.map +1 -0
  26. package/dist/github/environments/backup.mjs +24 -0
  27. package/dist/github/environments/backup.mjs.map +1 -0
  28. package/dist/github/environments/constants.d.mts +354 -0
  29. package/dist/github/environments/constants.d.mts.map +1 -0
  30. package/dist/github/environments/constants.mjs +62 -0
  31. package/dist/github/environments/constants.mjs.map +1 -0
  32. package/dist/github/environments/index.d.mts +6 -0
  33. package/dist/github/environments/index.d.mts.map +1 -0
  34. package/dist/github/environments/index.mjs +6 -0
  35. package/dist/github/environments/index.mjs.map +1 -0
  36. package/dist/github/environments/read-environment-contents.d.mts +4 -0
  37. package/dist/github/environments/read-environment-contents.d.mts.map +1 -0
  38. package/dist/github/environments/read-environment-contents.mjs +32 -0
  39. package/dist/github/environments/read-environment-contents.mjs.map +1 -0
  40. package/dist/github/index.d.mts +2 -0
  41. package/dist/github/index.d.mts.map +1 -1
  42. package/dist/github/index.mjs +2 -0
  43. package/dist/github/index.mjs.map +1 -1
  44. package/dist/github/vulnerability-alerts/api/get-vulnerability-alerts.d.mts +10 -0
  45. package/dist/github/vulnerability-alerts/api/get-vulnerability-alerts.d.mts.map +1 -0
  46. package/dist/github/vulnerability-alerts/api/get-vulnerability-alerts.mjs +25 -0
  47. package/dist/github/vulnerability-alerts/api/get-vulnerability-alerts.mjs.map +1 -0
  48. package/dist/github/vulnerability-alerts/api/index.d.mts +3 -0
  49. package/dist/github/vulnerability-alerts/api/index.d.mts.map +1 -0
  50. package/dist/github/vulnerability-alerts/api/index.mjs +3 -0
  51. package/dist/github/vulnerability-alerts/api/index.mjs.map +1 -0
  52. package/dist/github/vulnerability-alerts/api/set-vulnerability-alerts.d.mts +10 -0
  53. package/dist/github/vulnerability-alerts/api/set-vulnerability-alerts.d.mts.map +1 -0
  54. package/dist/github/vulnerability-alerts/api/set-vulnerability-alerts.mjs +19 -0
  55. package/dist/github/vulnerability-alerts/api/set-vulnerability-alerts.mjs.map +1 -0
  56. package/dist/github/vulnerability-alerts/apply.d.mts +11 -0
  57. package/dist/github/vulnerability-alerts/apply.d.mts.map +1 -0
  58. package/dist/github/vulnerability-alerts/apply.mjs +47 -0
  59. package/dist/github/vulnerability-alerts/apply.mjs.map +1 -0
  60. package/dist/github/vulnerability-alerts/backup.d.mts +5 -0
  61. package/dist/github/vulnerability-alerts/backup.d.mts.map +1 -0
  62. package/dist/github/vulnerability-alerts/backup.mjs +22 -0
  63. package/dist/github/vulnerability-alerts/backup.mjs.map +1 -0
  64. package/dist/github/vulnerability-alerts/constants.d.mts +72 -0
  65. package/dist/github/vulnerability-alerts/constants.d.mts.map +1 -0
  66. package/dist/github/vulnerability-alerts/constants.mjs +21 -0
  67. package/dist/github/vulnerability-alerts/constants.mjs.map +1 -0
  68. package/dist/github/vulnerability-alerts/index.d.mts +5 -0
  69. package/dist/github/vulnerability-alerts/index.d.mts.map +1 -0
  70. package/dist/github/vulnerability-alerts/index.mjs +5 -0
  71. package/dist/github/vulnerability-alerts/index.mjs.map +1 -0
  72. package/package.json +1 -1
  73. package/src/cmd/repo-settings.mts +17 -0
  74. package/src/github/constants.mts +7 -0
  75. package/src/github/environments/api/get-environments.mts +155 -0
  76. package/src/github/environments/api/index.mts +2 -0
  77. package/src/github/environments/api/set-environment.mts +106 -0
  78. package/src/github/environments/apply.mts +87 -0
  79. package/src/github/environments/backup.mts +38 -0
  80. package/src/github/environments/constants.mts +78 -0
  81. package/src/github/environments/index.mts +5 -0
  82. package/src/github/environments/read-environment-contents.mts +53 -0
  83. package/src/github/index.mts +2 -0
  84. package/src/github/vulnerability-alerts/api/get-vulnerability-alerts.mts +31 -0
  85. package/src/github/vulnerability-alerts/api/index.mts +2 -0
  86. package/src/github/vulnerability-alerts/api/set-vulnerability-alerts.mts +31 -0
  87. package/src/github/vulnerability-alerts/apply.mts +77 -0
  88. package/src/github/vulnerability-alerts/backup.mts +36 -0
  89. package/src/github/vulnerability-alerts/constants.mts +25 -0
  90. package/src/github/vulnerability-alerts/index.mts +4 -0
package/README.md CHANGED
@@ -1,12 +1,19 @@
1
- # Github Settings as Code
1
+ # GitHub Settings as Code
2
2
 
3
- GitHub の repository 設定を JSON ファイルで管理するための CLI。
3
+ A CLI for managing a GitHub repository's settings as JSON files.
4
4
 
5
- 設定ファイルは repository root の `repo-settings/` から読む。
5
+ The settings files are read from `repo-settings/` at the repository root.
6
6
 
7
- > **v3.0.0 での破壊的変更**: 読み込み元が `github/` から `repo-settings/` に
8
- > 変わった。`git mv github repo-settings` で移行する。旧名は `.github/` の
9
- > 別名に見えて、workflow もここにあると誤解させるものだった。
7
+ > **Breaking change in v3.0.0**: the settings directory moved from `github/` to
8
+ > `repo-settings/`. Migrate with `git mv github repo-settings`. The old name
9
+ > looked like an alias of `.github/` and suggested that workflows lived there
10
+ > too.
11
+
12
+ ## Installation
13
+
14
+ ```sh
15
+ npm install -D github-settings-as-code
16
+ ```
10
17
 
11
18
  ## Usage
12
19
 
@@ -14,19 +21,19 @@ GitHub の repository 設定を JSON ファイルで管理するための CLI。
14
21
  repo-settings <command> [target] [options]
15
22
  ```
16
23
 
17
- | Command | 説明 |
18
- | -------- | -------------------------------------------- |
19
- | `apply` | ローカルの設定ファイルを GitHub に反映する |
20
- | `backup` | GitHub の現在値をローカルの `bk/` に保存する |
24
+ | Command | Description |
25
+ | -------- | ---------------------------------------------------------------- |
26
+ | `apply` | Apply the local settings files to GitHub |
27
+ | `backup` | Save the current values on GitHub to the local `bk/` directories |
21
28
 
22
- | Target | 対応するファイル | `apply` | `backup` |
23
- | ------------- | ------------------------------------------------- | ------- | -------- |
24
- | `all`(既定) | すべて | ✅ | ✅ |
25
- | `repository` | `repo-settings/repository-settings/settings.json` | ✅ | ✅ |
26
- | `rulesets` | `repo-settings/rulesets/*.json` | ✅ | ✅ |
27
- | `variables` | repository variables | ✅ | — |
28
- | `actions` | `repo-settings/actions-settings/settings.json` | ✅ | ✅ |
29
- | `pages` | `repo-settings/pages/settings.json` | ✅ | ✅ |
29
+ | Target | Files | `apply` | `backup` |
30
+ | --------------- | ------------------------------------------------- | ------- | -------- |
31
+ | `all` (default) | All of the below | ✅ | ✅ |
32
+ | `repository` | `repo-settings/repository-settings/settings.json` | ✅ | ✅ |
33
+ | `rulesets` | `repo-settings/rulesets/*.json` | ✅ | ✅ |
34
+ | `variables` | Repository variables | ✅ | — |
35
+ | `actions` | `repo-settings/actions-settings/settings.json` | ✅ | ✅ |
36
+ | `pages` | `repo-settings/pages/settings.json` | ✅ | ✅ |
30
37
 
31
38
  ```sh
32
39
  repo-settings apply
@@ -35,34 +42,47 @@ repo-settings backup
35
42
  repo-settings apply --owner noshiro-pf --repo ts-repo-utils
36
43
  ```
37
44
 
38
- ## 対象 repository の解決
45
+ Each `backup` is written to a `bk/` directory next to the settings file it
46
+ mirrors (for example `repo-settings/rulesets/bk/`). `apply` reads the values
47
+ back from GitHub afterwards and rewrites the local files with what was actually
48
+ applied.
49
+
50
+ ## Resolving the target repository
39
51
 
40
- 以下の順で決まる。通常は `git remote` から決まるため、どちらの指定も不要。
52
+ The target is resolved in the following order. It is normally derived from
53
+ `git remote`, so neither option is usually needed.
41
54
 
42
- 1. コマンドライン引数 `--owner` / `--repo`
43
- 2. 環境変数 `OWNER` / `REPO_NAME`
55
+ 1. The command-line options `--owner` / `--repo`
56
+ 2. The environment variables `OWNER` / `REPO_NAME`
44
57
  3. `git remote get-url origin`
45
- 4. `package.json` の `name`( repository 名のみ )
58
+ 4. The `name` field of `package.json` (repository name only)
59
+
60
+ ## Authentication
46
61
 
47
- ## 認証
62
+ The token is resolved in the following order. Locally, nothing needs to be
63
+ configured once you have run `gh auth login`.
48
64
 
49
- 以下の順で解決される。ローカルでは `gh auth login` 済みであれば設定不要。
65
+ 1. The environment variables `GITHUB_APP_TOKEN` / `GH_TOKEN` /
66
+ `PERSONAL_ACCESS_TOKEN`
67
+ 2. `gh auth token` (the gh CLI's login)
50
68
 
51
- 1. 環境変数 `GITHUB_APP_TOKEN` / `GH_TOKEN` / `PERSONAL_ACCESS_TOKEN`
52
- 2. `gh auth token`( gh CLI のログイン情報 )
69
+ `GITHUB_TOKEN` is deliberately not read. In GitHub Actions it may hold the
70
+ default token, which lacks the Administration permission.
53
71
 
54
- CI では GitHub App の installation token を `GH_TOKEN` に渡す。 repository
55
- 設定・ruleset の操作には **Administration** 権限が必要で、既定の `GITHUB_TOKEN`
56
- では権限が足りない(`permissions:` に `administration` は存在しない)。
72
+ In CI, pass a GitHub App installation token as `GH_TOKEN`. Changing repository
73
+ settings and rulesets requires the **Administration** permission, which the
74
+ default `GITHUB_TOKEN` cannot be granted (`administration` is not a valid key
75
+ under `permissions:`).
57
76
 
58
- ## 管理できる設定
77
+ ## Managed settings
59
78
 
60
- | ファイル | GitHub 上の場所 |
79
+ | File | Location on GitHub |
61
80
  | ------------------------------------------------- | --------------------------------------- |
62
81
  | `repo-settings/repository-settings/settings.json` | Settings > General |
63
82
  | `repo-settings/rulesets/*.json` | Settings > Rules > Rulesets |
64
83
  | `repo-settings/actions-settings/settings.json` | Settings > Actions > General |
65
84
  | `repo-settings/pages/settings.json` | Settings > Pages > Build and deployment |
66
85
 
67
- `repo-settings/pages/settings.json` を置いていない repository では Pages の操作を行わない
68
- ( Pages を使わない repository で誤って有効化しないため )。
86
+ In a repository without `repo-settings/pages/settings.json`, Pages is left
87
+ untouched, so that a repository that does not use Pages never has it enabled by
88
+ mistake.
@@ -19,6 +19,9 @@ const HELP = dedent `
19
19
  variables repository variables ( apply のみ )
20
20
  actions repo-settings/actions-settings/settings.json
21
21
  pages repo-settings/pages/settings.json
22
+ environments repo-settings/environments/*.json
23
+ vulnerability-alerts
24
+ repo-settings/vulnerability-alerts/settings.json
22
25
 
23
26
  Options:
24
27
  --owner <owner> 対象の owner
@@ -47,6 +50,8 @@ const TARGETS = [
47
50
  'variables',
48
51
  'actions',
49
52
  'pages',
53
+ 'environments',
54
+ 'vulnerability-alerts',
50
55
  ];
51
56
  const COMMAND_SET = new Set(COMMANDS);
52
57
  const isCommand = (value) => COMMAND_SET.has(value);
@@ -93,12 +98,16 @@ const runners = {
93
98
  await github.applyRepositorySettings();
94
99
  await github.applyActionsSettings();
95
100
  await github.applyPagesSettings();
101
+ await github.applyEnvironments();
102
+ await github.applyVulnerabilityAlerts();
96
103
  },
97
104
  repository: github.applyRepositorySettings,
98
105
  rulesets: github.applyRulesets,
99
106
  variables: github.applyVariables,
100
107
  actions: github.applyActionsSettings,
101
108
  pages: github.applyPagesSettings,
109
+ environments: github.applyEnvironments,
110
+ 'vulnerability-alerts': github.applyVulnerabilityAlerts,
102
111
  },
103
112
  backup: {
104
113
  all: async () => {
@@ -106,11 +115,15 @@ const runners = {
106
115
  await github.backupRepositorySettings();
107
116
  await github.backupActionsSettings();
108
117
  await github.backupPagesSettings();
118
+ await github.backupEnvironments();
119
+ await github.backupVulnerabilityAlerts();
109
120
  },
110
121
  repository: github.backupRepositorySettings,
111
122
  rulesets: github.backupRulesets,
112
123
  actions: github.backupActionsSettings,
113
124
  pages: github.backupPagesSettings,
125
+ environments: github.backupEnvironments,
126
+ 'vulnerability-alerts': github.backupVulnerabilityAlerts,
114
127
  },
115
128
  };
116
129
  const runner = runners[commandArg][targetArg];
@@ -1 +1 @@
1
- {"version":3,"file":"repo-settings.mjs","sourceRoot":"","sources":["../../src/cmd/repo-settings.mts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"repo-settings.mjs","sourceRoot":"","sources":["../../src/cmd/repo-settings.mts"],"names":[],"mappings":";AAEA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAC5B,OAAO,eAAe,CAAC;AACvB,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AAGpC,MAAM,IAAI,GAAG,MAAM,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsClB,CAAC;AAEF,MAAM,QAAQ,GAAG,CAAC,OAAO,EAAE,QAAQ,CAAU,CAAC;AAI9C,MAAM,OAAO,GAAG;IACd,KAAK;IACL,YAAY;IACZ,UAAU;IACV,WAAW;IACX,SAAS;IACT,OAAO;IACP,cAAc;IACd,sBAAsB;CACd,CAAC;AAIX,MAAM,WAAW,GAAwB,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;AAE3D,MAAM,SAAS,GAAG,CAAC,KAAa,EAAoB,EAAE,CAAC,WAAW,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAE9E,MAAM,UAAU,GAAwB,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;AAEzD,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAmB,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;AAE3E,0CAA0C;AAC1C,gDAAgD;AAChD,MAAM,IAAI,GAA+B,CAAC,OAAO,EAAE,EAAE;IACnD,OAAO,CAAC,KAAK,CAAC,KAAK,OAAO,EAAE,CAAC,CAAC;IAE9B,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAElB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAEpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AAEF,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC;IAC7C,IAAI,EAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC;IAC/B,OAAO,EAAE;QACP,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACzB,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE;QACxB,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,EAAE;KACtD;IACD,MAAM,EAAE,KAAK;IACb,gBAAgB,EAAE,IAAI;CACvB,CAAC,CAAC;AAEH,IAAI,MAAM,CAAC,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC;IACrD,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEnB,0EAA0E;IAC1E,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,CAAC,UAAU,EAAE,SAAS,GAAG,KAAK,CAAC,GAAG,WAAW,CAAC;AAEpD,IAAI,UAAU,KAAK,SAAS,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,EAAE,CAAC;IACvD,IAAI,CAAC,qBAAqB,UAAU,IAAI,EAAE,GAAG,CAAC,CAAC;AACjD,CAAC;AAED,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;IACzB,IAAI,CAAC,oBAAoB,SAAS,GAAG,CAAC,CAAC;AACzC,CAAC;AAED,wDAAwD;AACxD,oCAAoC;AACpC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;AAEnD,MAAM,OAAO,GAGT;IACF,KAAK,EAAE;QACL,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;YAE9B,MAAM,MAAM,CAAC,aAAa,EAAE,CAAC;YAE7B,MAAM,MAAM,CAAC,uBAAuB,EAAE,CAAC;YAEvC,MAAM,MAAM,CAAC,oBAAoB,EAAE,CAAC;YAEpC,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAElC,MAAM,MAAM,CAAC,iBAAiB,EAAE,CAAC;YAEjC,MAAM,MAAM,CAAC,wBAAwB,EAAE,CAAC;QAC1C,CAAC;QACD,UAAU,EAAE,MAAM,CAAC,uBAAuB;QAC1C,QAAQ,EAAE,MAAM,CAAC,aAAa;QAC9B,SAAS,EAAE,MAAM,CAAC,cAAc;QAChC,OAAO,EAAE,MAAM,CAAC,oBAAoB;QACpC,KAAK,EAAE,MAAM,CAAC,kBAAkB;QAChC,YAAY,EAAE,MAAM,CAAC,iBAAiB;QACtC,sBAAsB,EAAE,MAAM,CAAC,wBAAwB;KACxD;IACD,MAAM,EAAE;QACN,GAAG,EAAE,KAAK,IAAI,EAAE;YACd,MAAM,MAAM,CAAC,cAAc,EAAE,CAAC;YAE9B,MAAM,MAAM,CAAC,wBAAwB,EAAE,CAAC;YAExC,MAAM,MAAM,CAAC,qBAAqB,EAAE,CAAC;YAErC,MAAM,MAAM,CAAC,mBAAmB,EAAE,CAAC;YAEnC,MAAM,MAAM,CAAC,kBAAkB,EAAE,CAAC;YAElC,MAAM,MAAM,CAAC,yBAAyB,EAAE,CAAC;QAC3C,CAAC;QACD,UAAU,EAAE,MAAM,CAAC,wBAAwB;QAC3C,QAAQ,EAAE,MAAM,CAAC,cAAc;QAC/B,OAAO,EAAE,MAAM,CAAC,qBAAqB;QACrC,KAAK,EAAE,MAAM,CAAC,mBAAmB;QACjC,YAAY,EAAE,MAAM,CAAC,kBAAkB;QACvC,sBAAsB,EAAE,MAAM,CAAC,yBAAyB;KACzD;CACO,CAAC;AAEX,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC;AAE9C,IAAI,MAAM,KAAK,SAAS,EAAE,CAAC;IACzB,IAAI,CAAC,IAAI,UAAU,kCAAkC,SAAS,GAAG,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,MAAM,EAAE,CAAC"}
@@ -4,6 +4,8 @@ export declare const settingsJsonName = "settings.json";
4
4
  export declare const repositorySettingsDir: string;
5
5
  export declare const actionsSettingsDir: string;
6
6
  export declare const pagesSettingsDir: string;
7
+ export declare const environmentsDir: string;
8
+ export declare const vulnerabilityAlertsDir: string;
7
9
  export declare const rulesetsDir: string;
8
10
  export declare const octokitHeaders: {
9
11
  readonly 'X-GitHub-Api-Version': '2022-11-28';
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../src/github/constants.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,EAAE,MAAyB,CAAC;AAE9C,eAAO,MAAM,IAAI,EAAE,MAAwB,CAAC;AAM5C,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,eAAO,MAAM,qBAAqB,QAGjC,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAG9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAuC,CAAC;AAErE,eAAO,MAAM,WAAW,QAA0C,CAAC;AAEnE,eAAO,MAAM,cAAc;aACzB,sBAAsB,EAAE,YAAY;CAC5B,CAAC"}
1
+ {"version":3,"file":"constants.d.mts","sourceRoot":"","sources":["../../src/github/constants.mts"],"names":[],"mappings":"AAKA,eAAO,MAAM,KAAK,EAAE,MAAyB,CAAC;AAE9C,eAAO,MAAM,IAAI,EAAE,MAAwB,CAAC;AAM5C,eAAO,MAAM,gBAAgB,kBAAkB,CAAC;AAEhD,eAAO,MAAM,qBAAqB,QAGjC,CAAC;AAEF,eAAO,MAAM,kBAAkB,QAG9B,CAAC;AAEF,eAAO,MAAM,gBAAgB,QAAuC,CAAC;AAErE,eAAO,MAAM,eAAe,QAA8C,CAAC;AAE3E,eAAO,MAAM,sBAAsB,QAGlC,CAAC;AAEF,eAAO,MAAM,WAAW,QAA0C,CAAC;AAEnE,eAAO,MAAM,cAAc;aACzB,sBAAsB,EAAE,YAAY;CAC5B,CAAC"}
@@ -10,6 +10,8 @@ export const settingsJsonName = 'settings.json';
10
10
  export const repositorySettingsDir = path.resolve(settingsDir, './repository-settings');
11
11
  export const actionsSettingsDir = path.resolve(settingsDir, './actions-settings');
12
12
  export const pagesSettingsDir = path.resolve(settingsDir, './pages');
13
+ export const environmentsDir = path.resolve(settingsDir, './environments');
14
+ export const vulnerabilityAlertsDir = path.resolve(settingsDir, './vulnerability-alerts');
13
15
  export const rulesetsDir = path.resolve(settingsDir, './rulesets');
14
16
  export const octokitHeaders = {
15
17
  'X-GitHub-Api-Version': '2022-11-28',
@@ -1 +1 @@
1
- {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/github/constants.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,UAAU,GAAG,MAAM,iBAAiB,EAAE,CAAC;AAE7C,MAAM,CAAC,MAAM,KAAK,GAAW,UAAU,CAAC,KAAK,CAAC;AAE9C,MAAM,CAAC,MAAM,IAAI,GAAW,UAAU,CAAC,IAAI,CAAC;AAE5C,yEAAyE;AACzE,iEAAiE;AACjE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAC/C,WAAW,EACX,uBAAuB,CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAC5C,WAAW,EACX,oBAAoB,CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAErE,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,sBAAsB,EAAE,YAAY;CAC5B,CAAC"}
1
+ {"version":3,"file":"constants.mjs","sourceRoot":"","sources":["../../src/github/constants.mts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,UAAU,GAAG,MAAM,iBAAiB,EAAE,CAAC;AAE7C,MAAM,CAAC,MAAM,KAAK,GAAW,UAAU,CAAC,KAAK,CAAC;AAE9C,MAAM,CAAC,MAAM,IAAI,GAAW,UAAU,CAAC,IAAI,CAAC;AAE5C,yEAAyE;AACzE,iEAAiE;AACjE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,iBAAiB,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,gBAAgB,GAAG,eAAe,CAAC;AAEhD,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,CAAC,OAAO,CAC/C,WAAW,EACX,uBAAuB,CACxB,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC,OAAO,CAC5C,WAAW,EACX,oBAAoB,CACrB,CAAC;AAEF,MAAM,CAAC,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,SAAS,CAAC,CAAC;AAErE,MAAM,CAAC,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;AAE3E,MAAM,CAAC,MAAM,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAChD,WAAW,EACX,wBAAwB,CACzB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;AAEnE,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,sBAAsB,EAAE,YAAY;CAC5B,CAAC"}
@@ -0,0 +1,16 @@
1
+ import { EnvironmentSettings } from '../constants.mjs';
2
+ /**
3
+ * Settings > Environments の現在値を、宣言ファイルと同じ形にして返す。
4
+ *
5
+ * 名前順に整える。 GitHub が返す順は作成順で、環境を 1 つ足しただけで
6
+ * `bk/` の中身が並び替わると差分が読めなくなるため。
7
+ */
8
+ export declare const getAllEnvironments: () => Promise<readonly EnvironmentSettings[]>;
9
+ /** 「 Selected branches and tags 」に登録されている pattern を列挙する。 */
10
+ export declare const getDeploymentBranchPolicies: (environmentName: string) => Promise<readonly DeploymentBranchPolicy[]>;
11
+ export type DeploymentBranchPolicy = Readonly<{
12
+ id: number;
13
+ name: string;
14
+ type: 'branch' | 'tag';
15
+ }>;
16
+ //# sourceMappingURL=get-environments.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-environments.d.mts","sourceRoot":"","sources":["../../../../src/github/environments/api/get-environments.mts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,kBAAkB,QAAa,OAAO,CACjD,SAAS,mBAAmB,EAAE,CAoC/B,CAAC;AAWF,4DAA4D;AAC5D,eAAO,MAAM,2BAA2B,oBACrB,MAAM,KACtB,OAAO,CAAC,SAAS,sBAAsB,EAAE,CAkB3C,CAAC;AAEF,MAAM,MAAM,sBAAsB,GAAG,QAAQ,CAAC;IAC5C,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,QAAQ,GAAG,KAAK,CAAC;CACxB,CAAC,CAAC"}
@@ -0,0 +1,98 @@
1
+ import { Arr } from 'ts-data-forge';
2
+ import * as t from 'ts-fortress';
3
+ import { Result } from 'ts-repo-utils';
4
+ import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
5
+ import { octokit } from '../../octokit.mjs';
6
+ import { EnvironmentSettings } from '../constants.mjs';
7
+
8
+
9
+
10
+
11
+
12
+
13
+ export const getAllEnvironments = async () => {
14
+
15
+
16
+
17
+
18
+ const response = await octokit.request('GET /repos/{owner}/{repo}/environments', { owner: OWNER, repo: REPO, headers: octokitHeaders, per_page: 100 });
19
+ const environments = response.data.environments ?? [];
20
+ const settings = await Promise.all(environments.map(async (environment) => {
21
+ const policy = environment.deployment_branch_policy ?? undefined;
22
+ return EnvironmentSettings.fill({
23
+ name: environment.name,
24
+ ...parseProtectionRules(environment.protection_rules),
25
+ deployment_branch_policy: policy === undefined
26
+ ? null
27
+ : {
28
+ protected_branches: policy.protected_branches,
29
+ custom_branch_policies: policy.custom_branch_policies,
30
+ },
31
+ deployment_branch_policies: policy?.custom_branch_policies === true
32
+ ? await getDeploymentBranchPolicyNames(environment.name)
33
+ : [],
34
+ });
35
+ }));
36
+ return settings.toSorted((a, b) => a.name.localeCompare(b.name));
37
+ };
38
+
39
+ const getDeploymentBranchPolicyNames = async (environmentName) => {
40
+ const policies = await getDeploymentBranchPolicies(environmentName);
41
+ return policies.map(({ name, type }) => ({ name, type }));
42
+ };
43
+
44
+ export const getDeploymentBranchPolicies = async (environmentName) => {
45
+
46
+ const response = await octokit.request('GET /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies', {
47
+ owner: OWNER,
48
+ repo: REPO,
49
+ environment_name: environmentName,
50
+ headers: octokitHeaders,
51
+ per_page: 100,
52
+ });
53
+ return response.data.branch_policies.map((policy) => ({
54
+ id: policy.id ?? 0,
55
+ name: policy.name ?? '',
56
+ type: policy.type === 'tag' ? 'tag' : 'branch',
57
+ }));
58
+ };
59
+
60
+
61
+
62
+
63
+
64
+
65
+
66
+
67
+ const parseProtectionRules = (protectionRules) => {
68
+ const validationResult = ProtectionRules.validate(protectionRules ?? []);
69
+ if (Result.isErr(validationResult)) {
70
+ throw new Error(Arr.toUnshifted('GitHub が返した environment の protection_rules を読めませんでした。')(t.validationErrorsToMessages(validationResult.value)).join('\n'));
71
+ }
72
+ const rules = validationResult.value;
73
+ const waitTimer = rules.find((rule) => rule.type === 'wait_timer');
74
+ const requiredReviewers = rules.find((rule) => rule.type === 'required_reviewers');
75
+ return {
76
+ wait_timer: waitTimer?.wait_timer ?? 0,
77
+ prevent_self_review: requiredReviewers?.prevent_self_review ?? false,
78
+ reviewers: (requiredReviewers?.reviewers ?? []).map((entry) => ({
79
+ type: entry.type,
80
+ id: entry.reviewer.id,
81
+ })),
82
+ };
83
+ };
84
+ const ProtectionRules = t.array(t.record({
85
+ type: t.string(''),
86
+ wait_timer: t.optional(t.number(0)),
87
+ prevent_self_review: t.optional(t.boolean(false)),
88
+ reviewers: t.optional(t.array(t.record({
89
+ type: t.enumType(['User', 'Team'], {
90
+ typeName: 'EnvironmentReviewerType',
91
+ defaultValue: 'User',
92
+ }),
93
+
94
+
95
+ reviewer: t.record({ id: t.number(0) }),
96
+ }))),
97
+ }), { typeName: 'EnvironmentProtectionRules' });
98
+ //# sourceMappingURL=get-environments.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-environments.mjs","sourceRoot":"","sources":["../../../../src/github/environments/api/get-environments.mts"],"names":[],"mappings":"AACA,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,KAAK,CAAC,MAAM,aAAa,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,eAAe,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,qBAAqB,CAAC;AAClE,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD;;;;;GAKG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAErC,EAAE;IACF,0EAA0E;IAC1E,EAAE;IACF,uCAAuC;IACvC,wCAAwC;IACxC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CACpC,wCAA+D,EAC/D,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,GAAG,EAAE,CACrE,CAAC;IAEF,MAAM,YAAY,GAAG,QAAQ,CAAC,IAAI,CAAC,YAAY,IAAI,EAAE,CAAC;IAEtD,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,CAChC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE;QACrC,MAAM,MAAM,GAAG,WAAW,CAAC,wBAAwB,IAAI,SAAS,CAAC;QAEjE,OAAO,mBAAmB,CAAC,IAAI,CAAC;YAC9B,IAAI,EAAE,WAAW,CAAC,IAAI;YACtB,GAAG,oBAAoB,CAAC,WAAW,CAAC,gBAAgB,CAAC;YACrD,wBAAwB,EACtB,MAAM,KAAK,SAAS;gBAClB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC;oBACE,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;oBAC7C,sBAAsB,EAAE,MAAM,CAAC,sBAAsB;iBACtD;YACP,0BAA0B,EACxB,MAAM,EAAE,sBAAsB,KAAK,IAAI;gBACrC,CAAC,CAAC,MAAM,8BAA8B,CAAC,WAAW,CAAC,IAAI,CAAC;gBACxD,CAAC,CAAC,EAAE;SACT,CAAC,CAAC;IACL,CAAC,CAAC,CACH,CAAC;IAEF,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AACnE,CAAC,CAAC;AAEF,4CAA4C;AAC5C,MAAM,8BAA8B,GAAG,KAAK,EAC1C,eAAuB,EACiD,EAAE;IAC1E,MAAM,QAAQ,GAAG,MAAM,2BAA2B,CAAC,eAAe,CAAC,CAAC;IAEpE,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,4DAA4D;AAC5D,MAAM,CAAC,MAAM,2BAA2B,GAAG,KAAK,EAC9C,eAAuB,EACqB,EAAE;IAC9C,2FAA2F;IAC3F,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CACpC,sFAA6G,EAC7G;QACE,KAAK,EAAE,KAAK;QACZ,IAAI,EAAE,IAAI;QACV,gBAAgB,EAAE,eAAe;QACjC,OAAO,EAAE,cAAc;QACvB,QAAQ,EAAE,GAAG;KACd,CACF,CAAC;IAEF,OAAO,QAAQ,CAAC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;QACpD,EAAE,EAAE,MAAM,CAAC,EAAE,IAAI,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC,IAAI,IAAI,EAAE;QACvB,IAAI,EAAE,MAAM,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,QAAQ;KAC/C,CAAC,CAAC,CAAC;AACN,CAAC,CAAC;AAQF;;;;;;;GAOG;AACH,MAAM,oBAAoB,GAAG,CAC3B,eAAwB,EAKvB,EAAE;IACH,MAAM,gBAAgB,GAAG,eAAe,CAAC,QAAQ,CAAC,eAAe,IAAI,EAAE,CAAC,CAAC;IAEzE,IAAI,MAAM,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnC,MAAM,IAAI,KAAK,CACb,GAAG,CAAC,WAAW,CACb,uDAAuD,CACxD,CAAC,CAAC,CAAC,0BAA0B,CAAC,gBAAgB,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CACnE,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC;IAErC,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IAEnE,MAAM,iBAAiB,GAAG,KAAK,CAAC,IAAI,CAClC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,oBAAoB,CAC7C,CAAC;IAEF,OAAO;QACL,UAAU,EAAE,SAAS,EAAE,UAAU,IAAI,CAAC;QACtC,mBAAmB,EAAE,iBAAiB,EAAE,mBAAmB,IAAI,KAAK;QACpE,SAAS,EAAE,CAAC,iBAAiB,EAAE,SAAS,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;YAC9D,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,EAAE,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE;SACtB,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAC7B,CAAC,CAAC,MAAM,CAAC;IACP,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IAClB,UAAU,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACnC,mBAAmB,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACjD,SAAS,EAAE,CAAC,CAAC,QAAQ,CACnB,CAAC,CAAC,KAAK,CACL,CAAC,CAAC,MAAM,CAAC;QACP,IAAI,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE;YACjC,QAAQ,EAAE,yBAAyB;YACnC,YAAY,EAAE,MAAM;SACrB,CAAC;QACF,iDAAiD;QACjD,yCAAyC;QACzC,QAAQ,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;KACxC,CAAC,CACH,CACF;CACF,CAAC,EACF,EAAE,QAAQ,EAAE,4BAA4B,EAAE,CAC3C,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './get-environments.mjs';
2
+ export * from './set-environment.mjs';
3
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","sourceRoot":"","sources":["../../../../src/github/environments/api/index.mts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,3 @@
1
+ export * from './get-environments.mjs';
2
+ export * from './set-environment.mjs';
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","sourceRoot":"","sources":["../../../../src/github/environments/api/index.mts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { type EnvironmentSettings } from '../constants.mjs';
2
+ /**
3
+ * 環境を JSON の内容に合わせる。無ければ作られる。
4
+ *
5
+ * `PUT` は保護ルールを丸ごと置き換えるので、省いたキーは「変更しない」ではなく
6
+ * 「無効にする」になる。宣言ファイルをそのまま渡しているのはそのため —
7
+ * 部分更新にすると、ファイルから消した設定が GitHub 側に残る。
8
+ */
9
+ export declare const setEnvironment: (settings: EnvironmentSettings) => Promise<void>;
10
+ //# sourceMappingURL=set-environment.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-environment.d.mts","sourceRoot":"","sources":["../../../../src/github/environments/api/set-environment.mts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAG5D;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,aACf,mBAAmB,KAC5B,OAAO,CAAC,IAAI,CA4Bd,CAAC"}
@@ -0,0 +1,73 @@
1
+ import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
2
+ import { octokit } from '../../octokit.mjs';
3
+ import { getDeploymentBranchPolicies } from './get-environments.mjs';
4
+
5
+
6
+
7
+
8
+
9
+
10
+
11
+ export const setEnvironment = async (settings) => {
12
+
13
+ await octokit.request('PUT /repos/{owner}/{repo}/environments/{environment_name}', {
14
+ owner: OWNER,
15
+ repo: REPO,
16
+ environment_name: settings.name,
17
+ headers: octokitHeaders,
18
+ wait_timer: settings.wait_timer,
19
+ prevent_self_review: settings.prevent_self_review,
20
+ reviewers: settings.reviewers.map((reviewer) => ({
21
+ type: reviewer.type,
22
+ id: reviewer.id,
23
+ })),
24
+ deployment_branch_policy: settings.deployment_branch_policy === null
25
+ ? null
26
+ : {
27
+ protected_branches: settings.deployment_branch_policy.protected_branches,
28
+ custom_branch_policies: settings.deployment_branch_policy.custom_branch_policies,
29
+ },
30
+ });
31
+ await setDeploymentBranchPolicies(settings);
32
+ };
33
+
34
+
35
+
36
+
37
+
38
+
39
+
40
+ const keyOf = (policy) => `${policy.type}:${policy.name}`;
41
+ const setDeploymentBranchPolicies = async (settings) => {
42
+ if (settings.deployment_branch_policy?.custom_branch_policies !== true) {
43
+
44
+ return;
45
+ }
46
+ const current = await getDeploymentBranchPolicies(settings.name);
47
+ const desiredKeys = new Set(settings.deployment_branch_policies.map(keyOf));
48
+ const currentKeys = new Set(current.map(keyOf));
49
+ const toDelete = current.filter((p) => !desiredKeys.has(keyOf(p)));
50
+ const toCreate = settings.deployment_branch_policies.filter((p) => !currentKeys.has(keyOf(p)));
51
+ for (const policy of toDelete) {
52
+
53
+ await octokit.request('DELETE /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies/{branch_policy_id}', {
54
+ owner: OWNER,
55
+ repo: REPO,
56
+ environment_name: settings.name,
57
+ branch_policy_id: policy.id,
58
+ headers: octokitHeaders,
59
+ });
60
+ }
61
+ for (const policy of toCreate) {
62
+
63
+ await octokit.request('POST /repos/{owner}/{repo}/environments/{environment_name}/deployment-branch-policies', {
64
+ owner: OWNER,
65
+ repo: REPO,
66
+ environment_name: settings.name,
67
+ headers: octokitHeaders,
68
+ name: policy.name,
69
+ type: policy.type,
70
+ });
71
+ }
72
+ };
73
+ //# sourceMappingURL=set-environment.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"set-environment.mjs","sourceRoot":"","sources":["../../../../src/github/environments/api/set-environment.mts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ /**
4
+ * `repo-settings/environments/*.json` を Settings > Environments に反映する。
5
+ *
6
+ * ruleset と同じく、宣言に無い環境は消さない。 GUI で作られたものが `bk/` に
7
+ * 現れることが drift の見え方であって、 apply が黙って片付けてしまうと
8
+ * 「いつ誰が何を作ったか」を見る機会がなくなる。
9
+ */
10
+ export declare const applyEnvironments: () => Promise<void>;
11
+ //# sourceMappingURL=apply.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.d.mts","sourceRoot":"","sources":["../../../src/github/environments/apply.mts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AAWvB;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,QAAa,OAAO,CAAC,IAAI,CAgCtD,CAAC"}
@@ -0,0 +1,67 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ import * as fs from 'node:fs/promises';
4
+ import * as path from 'node:path';
5
+ import { Arr } from 'ts-data-forge';
6
+ import { isDirectlyExecuted } from 'ts-repo-utils';
7
+ import { environmentsDir } from '../constants.mjs';
8
+ import { getAllEnvironments, setEnvironment } from './api/index.mjs';
9
+ import { backupEnvironments } from './backup.mjs';
10
+ import { readEnvironmentFiles } from './read-environment-contents.mjs';
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+ export const applyEnvironments = async () => {
19
+ await backupEnvironments(false);
20
+ const environments = await readEnvironmentFiles();
21
+ for (const environment of environments) {
22
+ assertConsistent(environment);
23
+ }
24
+ for (const environment of environments) {
25
+ await setEnvironment(environment);
26
+ }
27
+
28
+ {
29
+ const applied = await getAllEnvironments();
30
+ for (const environment of applied) {
31
+ const str = JSON.stringify(environment, undefined, 2);
32
+
33
+ await fs.writeFile(path.resolve(environmentsDir, `${environment.name}.json`), str);
34
+ }
35
+
36
+
37
+
38
+ await backupEnvironments();
39
+ }
40
+ };
41
+
42
+
43
+
44
+
45
+
46
+
47
+
48
+ const assertConsistent = (environment) => {
49
+ const custom = environment.deployment_branch_policy?.custom_branch_policies === true;
50
+ if (!custom && Arr.isNonEmpty(environment.deployment_branch_policies)) {
51
+ throw new Error([
52
+ `環境 "${environment.name}": deployment_branch_policies が書かれていますが、`,
53
+ 'deployment_branch_policy.custom_branch_policies が true ではありません。',
54
+ 'pattern は "Selected branches and tags" を選んだときにしか効きません。',
55
+ ].join('\n'));
56
+ }
57
+
58
+
59
+
60
+ if (custom && environment.deployment_branch_policy.protected_branches) {
61
+ throw new Error(`環境 "${environment.name}": protected_branches と custom_branch_policies は同時に true にできません。`);
62
+ }
63
+ };
64
+ if (isDirectlyExecuted(import.meta.url)) {
65
+ await applyEnvironments();
66
+ }
67
+ //# sourceMappingURL=apply.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apply.mjs","sourceRoot":"","sources":["../../../src/github/environments/apply.mts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,GAAG,EAAE,MAAM,eAAe,CAAC;AACpC,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAElD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,IAAmB,EAAE;IACzD,MAAM,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAEhC,MAAM,YAAY,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAElD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAChC,CAAC;IAED,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,MAAM,cAAc,CAAC,WAAW,CAAC,CAAC;IACpC,CAAC;IAED,0BAA0B;IAC1B,CAAC;QACC,MAAM,OAAO,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAE3C,KAAK,MAAM,WAAW,IAAI,OAAO,EAAE,CAAC;YAClC,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YAEtD,mEAAmE;YACnE,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,GAAG,WAAW,CAAC,IAAI,OAAO,CAAC,EACzD,GAAG,CACJ,CAAC;QACJ,CAAC;QAED,qDAAqD;QACrD,oCAAoC;QACpC,gBAAgB;QAChB,MAAM,kBAAkB,EAAE,CAAC;IAC7B,CAAC;AACH,CAAC,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,gBAAgB,GAAG,CAAC,WAAgC,EAAQ,EAAE;IAClE,MAAM,MAAM,GACV,WAAW,CAAC,wBAAwB,EAAE,sBAAsB,KAAK,IAAI,CAAC;IAExE,IAAI,CAAC,MAAM,IAAI,GAAG,CAAC,UAAU,CAAC,WAAW,CAAC,0BAA0B,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CACb;YACE,OAAO,WAAW,CAAC,IAAI,0CAA0C;YACjE,iEAAiE;YACjE,wDAAwD;SACzD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IAED,+DAA+D;IAC/D,gDAAgD;IAChD,mBAAmB;IACnB,IAAI,MAAM,IAAI,WAAW,CAAC,wBAAwB,CAAC,kBAAkB,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CACb,OAAO,WAAW,CAAC,IAAI,kEAAkE,CAC1F,CAAC;IACJ,CAAC;AACH,CAAC,CAAC;AAEF,IAAI,kBAAkB,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,MAAM,iBAAiB,EAAE,CAAC;AAC5B,CAAC"}
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ /** Settings > Environments の現在値を `bk/` に保存する。 */
4
+ export declare const backupEnvironments: (fmt?: boolean) => Promise<void>;
5
+ //# sourceMappingURL=backup.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.d.mts","sourceRoot":"","sources":["../../../src/github/environments/backup.mts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AAavB,iDAAiD;AACjD,eAAO,MAAM,kBAAkB,SACxB,OAAO,KACX,OAAO,CAAC,IAAI,CAgBd,CAAC"}
@@ -0,0 +1,24 @@
1
+ #!/usr/bin/env node
2
+ import 'dotenv/config';
3
+ import * as fs from 'node:fs/promises';
4
+ import * as path from 'node:path';
5
+ import { formatUncommittedFiles, isDirectlyExecuted, makeEmptyDir, } from 'ts-repo-utils';
6
+ import { environmentsDir } from '../constants.mjs';
7
+ import { getAllEnvironments } from './api/index.mjs';
8
+ const backupDir = path.resolve(environmentsDir, './bk');
9
+
10
+ export const backupEnvironments = async (fmt = true) => {
11
+ await makeEmptyDir(backupDir);
12
+ const environments = await getAllEnvironments();
13
+ for (const environment of environments) {
14
+
15
+ await fs.writeFile(path.resolve(backupDir, `${environment.name}.json`), JSON.stringify(environment, undefined, 2));
16
+ }
17
+ if (fmt) {
18
+ await formatUncommittedFiles();
19
+ }
20
+ };
21
+ if (isDirectlyExecuted(import.meta.url)) {
22
+ await backupEnvironments();
23
+ }
24
+ //# sourceMappingURL=backup.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup.mjs","sourceRoot":"","sources":["../../../src/github/environments/backup.mts"],"names":[],"mappings":";AACA,OAAO,eAAe,CAAC;AACvB,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,YAAY,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAErD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AAExD,iDAAiD;AACjD,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EACrC,GAAG,GAAY,IAAI,EACJ,EAAE;IACjB,MAAM,YAAY,CAAC,SAAS,CAAC,CAAC;IAE9B,MAAM,YAAY,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAEhD,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;QACvC,mEAAmE;QACnE,MAAM,EAAE,CAAC,SAAS,CAChB,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,GAAG,WAAW,CAAC,IAAI,OAAO,CAAC,EACnD,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC,CAC1C,CAAC;IACJ,CAAC;IAED,IAAI,GAAG,EAAE,CAAC;QACR,MAAM,sBAAsB,EAAE,CAAC;IACjC,CAAC;AACH,CAAC,CAAC;AAEF,IAAI,kBAAkB,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACxC,MAAM,kBAAkB,EAAE,CAAC;AAC7B,CAAC"}