github-settings-as-code 3.0.1 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cmd/repo-settings.mjs +5 -5
- package/dist/github/actions-settings/api/get-actions-settings.mjs +7 -7
- package/dist/github/actions-settings/api/set-actions-settings.mjs +7 -7
- package/dist/github/actions-settings/apply.mjs +5 -5
- package/dist/github/actions-settings/backup.mjs +2 -2
- package/dist/github/actions-settings/constants.mjs +24 -24
- package/dist/github/constants.mjs +2 -2
- package/dist/github/octokit.mjs +12 -12
- package/dist/github/pages/api/get-pages-settings.mjs +6 -6
- package/dist/github/pages/api/set-pages-settings.mjs +8 -8
- package/dist/github/pages/apply.mjs +10 -10
- package/dist/github/pages/backup.mjs +2 -2
- package/dist/github/pages/constants.mjs +6 -6
- package/dist/github/repository/api/get-repository.mjs +1 -1
- package/dist/github/repository/api/update-repository.mjs +3 -3
- package/dist/github/repository/apply.mjs +14 -14
- package/dist/github/repository/backup.mjs +1 -1
- package/dist/github/repository/constants.mjs +3 -3
- package/dist/github/resolve-target-repo.mjs +24 -24
- package/dist/github/ruleset/api/create-ruleset.mjs +7 -7
- package/dist/github/ruleset/api/get-all-rulesets.mjs +3 -3
- package/dist/github/ruleset/api/get-ruleset.mjs +1 -1
- package/dist/github/ruleset/api/update-ruleset.mjs +7 -7
- package/dist/github/ruleset/apply.mjs +3 -3
- package/dist/github/ruleset/backup.mjs +1 -1
- package/dist/github/ruleset/constants.mjs +3 -3
- package/dist/github/ruleset/read-rule-set-contents.mjs +2 -2
- package/dist/github/variables/api/create-repo-variable.mjs +1 -1
- package/dist/github/variables/api/list-repo-variables.mjs +1 -1
- package/dist/github/variables/api/update-repo-variable.mjs +1 -1
- package/dist/github/variables/apply.mjs +7 -7
- package/package.json +9 -9
|
@@ -52,8 +52,8 @@ const COMMAND_SET = new Set(COMMANDS);
|
|
|
52
52
|
const isCommand = (value) => COMMAND_SET.has(value);
|
|
53
53
|
const TARGET_SET = new Set(TARGETS);
|
|
54
54
|
const isTarget = (value) => TARGET_SET.has(value);
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
|
|
56
|
+
|
|
57
57
|
const fail = (message) => {
|
|
58
58
|
console.error(`❌ ${message}`);
|
|
59
59
|
console.error('');
|
|
@@ -72,7 +72,7 @@ const { values, positionals } = util.parseArgs({
|
|
|
72
72
|
});
|
|
73
73
|
if (values.help === true || Arr.isEmpty(positionals)) {
|
|
74
74
|
console.info(HELP);
|
|
75
|
-
|
|
75
|
+
|
|
76
76
|
process.exit(values.help === true ? 0 : 1);
|
|
77
77
|
}
|
|
78
78
|
const [commandArg, targetArg = 'all'] = positionals;
|
|
@@ -82,8 +82,8 @@ if (commandArg === undefined || !isCommand(commandArg)) {
|
|
|
82
82
|
if (!isTarget(targetArg)) {
|
|
83
83
|
fail(`Unknown target: "${targetArg}"`);
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
|
|
85
|
+
|
|
86
|
+
|
|
87
87
|
const github = await import('../github/index.mjs');
|
|
88
88
|
const runners = {
|
|
89
89
|
apply: {
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
3
|
import { ActionsSettings } from '../constants.mjs';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
9
|
export const getActionsSettings = async () => {
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
const permissions = await octokit.request('GET /repos/{owner}/{repo}/actions/permissions', { owner: OWNER, repo: REPO, headers: octokitHeaders });
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
const forkPrApproval = await octokit.request('GET /repos/{owner}/{repo}/actions/permissions/fork-pr-contributor-approval', { owner: OWNER, repo: REPO, headers: octokitHeaders });
|
|
14
14
|
return ActionsSettings.fill({
|
|
15
15
|
enabled: permissions.data.enabled,
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
|
-
|
|
3
|
+
|
|
4
4
|
export const setActionsSettings = async (settings) => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
10
|
const permissionsParams = {
|
|
11
11
|
owner: OWNER,
|
|
12
12
|
repo: REPO,
|
|
@@ -16,7 +16,7 @@ export const setActionsSettings = async (settings) => {
|
|
|
16
16
|
sha_pinning_required: settings.sha_pinning_required,
|
|
17
17
|
};
|
|
18
18
|
await octokit.request('PUT /repos/{owner}/{repo}/actions/permissions', permissionsParams);
|
|
19
|
-
|
|
19
|
+
|
|
20
20
|
await octokit.request('PUT /repos/{owner}/{repo}/actions/permissions/fork-pr-contributor-approval', {
|
|
21
21
|
owner: OWNER,
|
|
22
22
|
repo: REPO,
|
|
@@ -8,24 +8,24 @@ import { actionsSettingsDir, settingsJsonName } from '../constants.mjs';
|
|
|
8
8
|
import { getActionsSettings, setActionsSettings } from './api/index.mjs';
|
|
9
9
|
import { backupActionsSettings } from './backup.mjs';
|
|
10
10
|
import { ActionsSettings } from './constants.mjs';
|
|
11
|
-
|
|
11
|
+
|
|
12
12
|
export const applyActionsSettings = async () => {
|
|
13
13
|
await backupActionsSettings(false);
|
|
14
14
|
const settings = await readSettings();
|
|
15
15
|
await setActionsSettings(settings);
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
{
|
|
18
18
|
const applied = await getActionsSettings();
|
|
19
19
|
const str = JSON.stringify(applied, undefined, 2);
|
|
20
|
-
|
|
20
|
+
|
|
21
21
|
await fs.writeFile(path.resolve(actionsSettingsDir, settingsJsonName), str);
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
await fs.writeFile(path.resolve(actionsSettingsDir, 'bk', settingsJsonName), str);
|
|
24
24
|
await formatUncommittedFiles();
|
|
25
25
|
}
|
|
26
26
|
};
|
|
27
27
|
const readSettings = async () => {
|
|
28
|
-
|
|
28
|
+
|
|
29
29
|
const settingsText = await fs.readFile(path.resolve(actionsSettingsDir, settingsJsonName), { encoding: 'utf8' });
|
|
30
30
|
const validationResult = ActionsSettings.validate(JSON.parse(settingsText));
|
|
31
31
|
if (Result.isErr(validationResult)) {
|
|
@@ -6,11 +6,11 @@ import { formatUncommittedFiles, isDirectlyExecuted, makeEmptyDir, } from 'ts-re
|
|
|
6
6
|
import { actionsSettingsDir, settingsJsonName } from '../constants.mjs';
|
|
7
7
|
import { getActionsSettings } from './api/index.mjs';
|
|
8
8
|
const backupDir = path.resolve(actionsSettingsDir, './bk');
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
export const backupActionsSettings = async (fmt = true) => {
|
|
11
11
|
await makeEmptyDir(backupDir);
|
|
12
12
|
const settings = await getActionsSettings();
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
await fs.writeFile(path.resolve(backupDir, settingsJsonName), JSON.stringify(settings, undefined, 2));
|
|
15
15
|
if (fmt) {
|
|
16
16
|
await formatUncommittedFiles();
|
|
@@ -1,35 +1,35 @@
|
|
|
1
1
|
import * as t from 'ts-fortress';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
11
|
export const ActionsSettings = t.record({
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
enabled: t.boolean(true),
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
allowed_actions: t.enumType(['all', 'local_only', 'selected'], {
|
|
16
16
|
typeName: 'AllowedActions',
|
|
17
17
|
defaultValue: 'all',
|
|
18
18
|
}),
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
|
|
25
25
|
sha_pinning_required: t.boolean(false),
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
|
|
33
33
|
fork_pr_contributor_approval_policy: t.enumType([
|
|
34
34
|
'first_time_contributors_new_to_github',
|
|
35
35
|
'first_time_contributors',
|
|
@@ -3,8 +3,8 @@ import { resolveTargetRepo } from './resolve-target-repo.mjs';
|
|
|
3
3
|
const targetRepo = await resolveTargetRepo();
|
|
4
4
|
export const OWNER = targetRepo.owner;
|
|
5
5
|
export const REPO = targetRepo.repo;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
|
|
7
|
+
|
|
8
8
|
const settingsDir = path.resolve(process.cwd(), './repo-settings');
|
|
9
9
|
export const settingsJsonName = 'settings.json';
|
|
10
10
|
export const repositorySettingsDir = path.resolve(settingsDir, './repository-settings');
|
package/dist/github/octokit.mjs
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { Octokit } from '@octokit/core';
|
|
2
2
|
import { execFileSync } from 'node:child_process';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
13
|
const resolveAuthToken = () => {
|
|
14
14
|
const fromEnv = process.env['GITHUB_APP_TOKEN'] ??
|
|
15
15
|
process.env['GH_TOKEN'] ??
|
|
@@ -18,7 +18,7 @@ const resolveAuthToken = () => {
|
|
|
18
18
|
return fromEnv;
|
|
19
19
|
}
|
|
20
20
|
try {
|
|
21
|
-
|
|
21
|
+
|
|
22
22
|
const stdout = execFileSync('gh', ['auth', 'token'], {
|
|
23
23
|
encoding: 'utf8',
|
|
24
24
|
stdio: ['ignore', 'pipe', 'ignore'],
|
|
@@ -29,7 +29,7 @@ const resolveAuthToken = () => {
|
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
catch {
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
}
|
|
34
34
|
throw new Error([
|
|
35
35
|
'GitHub のトークンが見つかりませんでした。',
|
|
@@ -2,14 +2,14 @@ import { hasKey, isRecord } from 'ts-data-forge';
|
|
|
2
2
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
3
3
|
import { octokit } from '../../octokit.mjs';
|
|
4
4
|
import { PagesSettings } from '../constants.mjs';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
10
|
export const getPagesSettings = async () => {
|
|
11
11
|
try {
|
|
12
|
-
|
|
12
|
+
|
|
13
13
|
const response = await octokit.request('GET /repos/{owner}/{repo}/pages', { owner: OWNER, repo: REPO, headers: octokitHeaders });
|
|
14
14
|
return PagesSettings.fill({ build_type: response.data.build_type });
|
|
15
15
|
}
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
3
|
import { getPagesSettings } from './get-pages-settings.mjs';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
|
|
10
10
|
export const setPagesSettings = async (settings) => {
|
|
11
11
|
const current = await getPagesSettings();
|
|
12
12
|
if (current === undefined) {
|
|
13
|
-
|
|
13
|
+
|
|
14
14
|
await octokit.request('POST /repos/{owner}/{repo}/pages', {
|
|
15
15
|
owner: OWNER,
|
|
16
16
|
repo: REPO,
|
|
@@ -22,7 +22,7 @@ export const setPagesSettings = async (settings) => {
|
|
|
22
22
|
if (current.build_type === settings.build_type) {
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
|
|
25
|
+
|
|
26
26
|
await octokit.request('PUT /repos/{owner}/{repo}/pages', {
|
|
27
27
|
owner: OWNER,
|
|
28
28
|
repo: REPO,
|
|
@@ -7,12 +7,12 @@ import { formatUncommittedFiles, isDirectlyExecuted, pathExists, Result, } from
|
|
|
7
7
|
import { pagesSettingsDir, settingsJsonName } from '../constants.mjs';
|
|
8
8
|
import { getPagesSettings, setPagesSettings } from './api/index.mjs';
|
|
9
9
|
import { PagesSettings } from './constants.mjs';
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
16
|
export const applyPagesSettings = async () => {
|
|
17
17
|
const settingsPath = path.resolve(pagesSettingsDir, settingsJsonName);
|
|
18
18
|
if (!(await pathExists(settingsPath))) {
|
|
@@ -20,22 +20,22 @@ export const applyPagesSettings = async () => {
|
|
|
20
20
|
}
|
|
21
21
|
const settings = await readSettings(settingsPath);
|
|
22
22
|
await setPagesSettings(settings);
|
|
23
|
-
|
|
23
|
+
|
|
24
24
|
{
|
|
25
25
|
const applied = await getPagesSettings();
|
|
26
26
|
if (applied === undefined) {
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
const str = JSON.stringify(applied, undefined, 2);
|
|
30
|
-
|
|
30
|
+
|
|
31
31
|
await fs.writeFile(settingsPath, str);
|
|
32
|
-
|
|
32
|
+
|
|
33
33
|
await fs.writeFile(path.resolve(pagesSettingsDir, 'bk', settingsJsonName), str);
|
|
34
34
|
await formatUncommittedFiles();
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
37
|
const readSettings = async (settingsPath) => {
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
const settingsText = await fs.readFile(settingsPath, { encoding: 'utf8' });
|
|
40
40
|
const validationResult = PagesSettings.validate(JSON.parse(settingsText));
|
|
41
41
|
if (Result.isErr(validationResult)) {
|
|
@@ -6,7 +6,7 @@ import { formatUncommittedFiles, isDirectlyExecuted, makeEmptyDir, } from 'ts-re
|
|
|
6
6
|
import { pagesSettingsDir, settingsJsonName } from '../constants.mjs';
|
|
7
7
|
import { getPagesSettings } from './api/index.mjs';
|
|
8
8
|
const backupDir = path.resolve(pagesSettingsDir, './bk');
|
|
9
|
-
|
|
9
|
+
|
|
10
10
|
export const backupPagesSettings = async (fmt = true) => {
|
|
11
11
|
await makeEmptyDir(backupDir);
|
|
12
12
|
const settings = await getPagesSettings();
|
|
@@ -14,7 +14,7 @@ export const backupPagesSettings = async (fmt = true) => {
|
|
|
14
14
|
console.warn('GitHub Pages is not enabled for this repository; skipping backup.');
|
|
15
15
|
return;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
await fs.writeFile(path.resolve(backupDir, settingsJsonName), JSON.stringify(settings, undefined, 2));
|
|
19
19
|
if (fmt) {
|
|
20
20
|
await formatUncommittedFiles();
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as t from 'ts-fortress';
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
|
|
8
8
|
export const PagesSettings = t.record({
|
|
9
9
|
build_type: t.enumType(['workflow', 'legacy'], {
|
|
10
10
|
typeName: 'PagesBuildType',
|
|
@@ -4,7 +4,7 @@ import { Result } from 'ts-repo-utils';
|
|
|
4
4
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
5
5
|
import { octokit } from '../../octokit.mjs';
|
|
6
6
|
export const getRepositorySettings = async () => {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
const getRepositoryResult = await octokit.request('GET /repos/{owner}/{repo}', {
|
|
9
9
|
owner: OWNER,
|
|
10
10
|
repo: REPO,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
3
3
|
import { octokit } from '../../octokit.mjs';
|
|
4
4
|
export const updateRepository = async ({ payload: { name, description, homepage, private: private_, visibility, security_and_analysis, has_issues, has_projects, has_wiki, has_pull_requests, pull_request_creation_policy, is_template, default_branch, allow_squash_merge, allow_merge_commit, allow_rebase_merge, allow_auto_merge, delete_branch_on_merge, allow_update_branch, use_squash_pr_title_as_default, squash_merge_commit_title, squash_merge_commit_message, merge_commit_title, merge_commit_message, archived, allow_forking, web_commit_signoff_required, }, }) => {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
await octokit.request('PATCH /repos/{owner}/{repo}', {
|
|
7
7
|
owner: OWNER,
|
|
8
8
|
repo: REPO,
|
|
@@ -12,7 +12,7 @@ export const updateRepository = async ({ payload: { name, description, homepage,
|
|
|
12
12
|
homepage,
|
|
13
13
|
private: private_,
|
|
14
14
|
visibility,
|
|
15
|
-
security_and_analysis:
|
|
15
|
+
security_and_analysis: security_and_analysis,
|
|
16
16
|
has_issues,
|
|
17
17
|
has_projects,
|
|
18
18
|
has_wiki,
|
|
@@ -14,17 +14,17 @@ export const applyRepositorySettings = async () => {
|
|
|
14
14
|
const settings = await readSettings();
|
|
15
15
|
await updateRepository({
|
|
16
16
|
payload: {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
22
22
|
security_and_analysis: settings.security_and_analysis,
|
|
23
23
|
has_issues: settings.has_issues,
|
|
24
24
|
has_projects: settings.has_projects,
|
|
25
25
|
has_wiki: settings.has_wiki,
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
|
|
27
|
+
|
|
28
28
|
allow_squash_merge: settings.allow_squash_merge,
|
|
29
29
|
allow_merge_commit: settings.allow_merge_commit,
|
|
30
30
|
allow_rebase_merge: settings.allow_rebase_merge,
|
|
@@ -36,25 +36,25 @@ export const applyRepositorySettings = async () => {
|
|
|
36
36
|
squash_merge_commit_message: settings.squash_merge_commit_message,
|
|
37
37
|
merge_commit_title: settings.merge_commit_title,
|
|
38
38
|
merge_commit_message: settings.merge_commit_message,
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
|
|
42
42
|
web_commit_signoff_required: settings.web_commit_signoff_required,
|
|
43
43
|
},
|
|
44
44
|
});
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
{
|
|
47
47
|
const repositorySettings = await getRepositorySettings();
|
|
48
48
|
const str = JSON.stringify(Obj.pick(repositorySettings, repositoryKeysToPick), undefined, 2);
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
await fs.writeFile(path.resolve(repositorySettingsDir, settingsJsonName), str);
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
await fs.writeFile(path.resolve(repositorySettingsDir, 'bk', settingsJsonName), str);
|
|
53
53
|
await formatUncommittedFiles();
|
|
54
54
|
}
|
|
55
55
|
};
|
|
56
56
|
const readSettings = async () => {
|
|
57
|
-
|
|
57
|
+
|
|
58
58
|
const settingsText = await fs.readFile(path.resolve(repositorySettingsDir, settingsJsonName), {
|
|
59
59
|
encoding: 'utf8',
|
|
60
60
|
});
|
|
@@ -11,7 +11,7 @@ const backupDir = path.resolve(repositorySettingsDir, './bk');
|
|
|
11
11
|
export const backupRepositorySettings = async (fmt = true) => {
|
|
12
12
|
await makeEmptyDir(backupDir);
|
|
13
13
|
const repositorySettings = await getRepositorySettings();
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
await fs.writeFile(path.resolve(backupDir, settingsJsonName), JSON.stringify(Obj.pick(repositorySettings, repositoryKeysToPick), undefined, 2));
|
|
16
16
|
if (fmt) {
|
|
17
17
|
await formatUncommittedFiles();
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { FullRepository, } from 'octokit-safe-types';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import * as t from 'ts-fortress';
|
|
4
4
|
const keysToPickBase = [
|
|
5
5
|
'allow_auto_merge',
|
|
@@ -37,11 +37,11 @@ const keysToDropList = [
|
|
|
37
37
|
'is_template',
|
|
38
38
|
'archived',
|
|
39
39
|
'visibility',
|
|
40
|
-
|
|
40
|
+
|
|
41
41
|
'allow_forking',
|
|
42
42
|
];
|
|
43
43
|
const keysToDrop = new Set(keysToDropList);
|
|
44
44
|
export const repositoryKeysToPick = keysToPickBase.filter((k) => !keysToDrop.has(k));
|
|
45
|
-
|
|
45
|
+
|
|
46
46
|
export const RepositoryPicked = t.pick(FullRepository, repositoryKeysToPick);
|
|
47
47
|
//# sourceMappingURL=constants.mjs.map
|
|
@@ -4,13 +4,13 @@ import * as path from 'node:path';
|
|
|
4
4
|
import * as util from 'node:util';
|
|
5
5
|
import { Arr, hasKey, isRecord, isString, Json } from 'ts-data-forge';
|
|
6
6
|
import { Result } from 'ts-repo-utils';
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
const pickString = (value) => value !== '' && isString(value) ? value : undefined;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
14
|
const fromCliArgs = () => {
|
|
15
15
|
const { values } = util.parseArgs({
|
|
16
16
|
args: Arr.skip(process.argv, 2),
|
|
@@ -30,12 +30,12 @@ const fromEnv = () => ({
|
|
|
30
30
|
owner: process.env['OWNER'],
|
|
31
31
|
repo: process.env['REPO_NAME'],
|
|
32
32
|
});
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
39
|
const fromGitRemote = () => {
|
|
40
40
|
try {
|
|
41
41
|
const url = execFileSync('git', ['remote', 'get-url', 'origin'], {
|
|
@@ -52,11 +52,11 @@ const fromGitRemote = () => {
|
|
|
52
52
|
return {};
|
|
53
53
|
}
|
|
54
54
|
};
|
|
55
|
-
|
|
55
|
+
|
|
56
56
|
const fromPackageJson = async () => {
|
|
57
57
|
const packageJsonPath = path.resolve(process.cwd(), './package.json');
|
|
58
58
|
try {
|
|
59
|
-
|
|
59
|
+
|
|
60
60
|
const packageJsonStr = await fs.readFile(packageJsonPath, {
|
|
61
61
|
encoding: 'utf8',
|
|
62
62
|
});
|
|
@@ -73,16 +73,16 @@ const fromPackageJson = async () => {
|
|
|
73
73
|
return {};
|
|
74
74
|
}
|
|
75
75
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
86
86
|
export const resolveTargetRepo = async () => {
|
|
87
87
|
const sources = [
|
|
88
88
|
fromCliArgs(),
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
3
3
|
import { octokit } from '../../octokit.mjs';
|
|
4
4
|
export const createRuleset = async ({ payload: { name, target, enforcement, bypass_actors, conditions, rules }, }) => {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
await octokit.request('POST /repos/{owner}/{repo}/rulesets',
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
{
|
|
9
9
|
owner: OWNER,
|
|
10
10
|
repo: REPO,
|
|
@@ -12,10 +12,10 @@ export const createRuleset = async ({ payload: { name, target, enforcement, bypa
|
|
|
12
12
|
name,
|
|
13
13
|
target,
|
|
14
14
|
enforcement,
|
|
15
|
-
bypass_actors:
|
|
16
|
-
conditions:
|
|
17
|
-
|
|
18
|
-
rules:
|
|
15
|
+
bypass_actors: bypass_actors,
|
|
16
|
+
conditions: conditions,
|
|
17
|
+
|
|
18
|
+
rules: rules,
|
|
19
19
|
});
|
|
20
20
|
};
|
|
21
21
|
//# sourceMappingURL=create-ruleset.mjs.map
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { GetAllRulesetsResponse, } from 'octokit-safe-types';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import * as t from 'ts-fortress';
|
|
4
4
|
import { Result } from 'ts-repo-utils';
|
|
5
5
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
6
6
|
import { octokit } from '../../octokit.mjs';
|
|
7
7
|
export const getAllRulesets = async () => {
|
|
8
|
-
|
|
8
|
+
|
|
9
9
|
const getAllRulesetsResponse = (await octokit.request('GET /repos/{owner}/{repo}/rulesets', {
|
|
10
10
|
owner: OWNER,
|
|
11
11
|
repo: REPO,
|
|
12
12
|
headers: octokitHeaders,
|
|
13
13
|
}));
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
{
|
|
16
16
|
const res = GetAllRulesetsResponse.validate(getAllRulesetsResponse.data);
|
|
17
17
|
if (Result.isErr(res)) {
|
|
@@ -4,7 +4,7 @@ import { Result } from 'ts-repo-utils';
|
|
|
4
4
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
5
5
|
import { octokit } from '../../octokit.mjs';
|
|
6
6
|
export const getRuleset = async (rulesetId) => {
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
const getRulesetResult = await octokit.request('GET /repos/{owner}/{repo}/rulesets/{ruleset_id}', {
|
|
9
9
|
owner: OWNER,
|
|
10
10
|
repo: REPO,
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
|
|
1
|
+
|
|
2
2
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
3
3
|
import { octokit } from '../../octokit.mjs';
|
|
4
4
|
export const updateRuleset = async ({ rulesetId, payload: { name, target, enforcement, bypass_actors, conditions, rules }, }) => {
|
|
5
|
-
|
|
5
|
+
|
|
6
6
|
await octokit.request('PUT /repos/{owner}/{repo}/rulesets/{ruleset_id}',
|
|
7
|
-
|
|
7
|
+
|
|
8
8
|
{
|
|
9
9
|
owner: OWNER,
|
|
10
10
|
repo: REPO,
|
|
@@ -13,10 +13,10 @@ export const updateRuleset = async ({ rulesetId, payload: { name, target, enforc
|
|
|
13
13
|
name,
|
|
14
14
|
target,
|
|
15
15
|
enforcement,
|
|
16
|
-
bypass_actors:
|
|
17
|
-
conditions:
|
|
18
|
-
|
|
19
|
-
rules:
|
|
16
|
+
bypass_actors: bypass_actors,
|
|
17
|
+
conditions: conditions,
|
|
18
|
+
|
|
19
|
+
rules: rules,
|
|
20
20
|
});
|
|
21
21
|
};
|
|
22
22
|
//# sourceMappingURL=update-ruleset.mjs.map
|
|
@@ -40,15 +40,15 @@ export const applyRulesets = async () => {
|
|
|
40
40
|
},
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
|
-
|
|
43
|
+
|
|
44
44
|
{
|
|
45
45
|
const rulesetsResult = await getAllRulesets();
|
|
46
46
|
for (const rule of rulesetsResult) {
|
|
47
47
|
const content = await getRuleset(rule.id);
|
|
48
48
|
const str = JSON.stringify(Obj.pick(content, rulesetKeysToPick), undefined, 2);
|
|
49
|
-
|
|
49
|
+
|
|
50
50
|
await fs.writeFile(path.resolve(rulesetsDir, `${rule.name}.json`), str);
|
|
51
|
-
|
|
51
|
+
|
|
52
52
|
await fs.writeFile(path.resolve(rulesetsDir, `./bk/${rule.name}.json`), str);
|
|
53
53
|
}
|
|
54
54
|
await formatUncommittedFiles();
|
|
@@ -13,7 +13,7 @@ export const backupRulesets = async (fmt = true) => {
|
|
|
13
13
|
const rulesetsResult = await getAllRulesets();
|
|
14
14
|
for (const rule of rulesetsResult) {
|
|
15
15
|
const content = await getRuleset(rule.id);
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
await fs.writeFile(path.resolve(backupDir, `${rule.name}.json`), JSON.stringify(Obj.pick(content, rulesetKeysToPick), undefined, 2));
|
|
18
18
|
}
|
|
19
19
|
if (fmt) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RepositoryRuleset, } from 'octokit-safe-types';
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import * as t from 'ts-fortress';
|
|
4
4
|
export const rulesetKeysToPick = [
|
|
5
5
|
'id',
|
|
@@ -10,7 +10,7 @@ export const rulesetKeysToPick = [
|
|
|
10
10
|
'conditions',
|
|
11
11
|
'rules',
|
|
12
12
|
];
|
|
13
|
-
|
|
14
|
-
|
|
13
|
+
|
|
14
|
+
|
|
15
15
|
export const RulesetPicked = t.pick(RepositoryRuleset, rulesetKeysToPick);
|
|
16
16
|
//# sourceMappingURL=constants.mjs.map
|
|
@@ -7,14 +7,14 @@ import { RulesetPicked } from './constants.mjs';
|
|
|
7
7
|
export const readRulesetFiles = async () => readFilesIn(rulesetsDir);
|
|
8
8
|
export const readRulesetBackupFiles = async () => readFilesIn(path.resolve(rulesetsDir, './bk'));
|
|
9
9
|
const readFilesIn = async (dir) => {
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
const files = await fs.readdir(dir, {
|
|
12
12
|
withFileTypes: true,
|
|
13
13
|
});
|
|
14
14
|
const rulesetFileContents = await Promise.all(files
|
|
15
15
|
.filter((d) => d.isFile())
|
|
16
16
|
.map((d) =>
|
|
17
|
-
|
|
17
|
+
|
|
18
18
|
fs.readFile(path.resolve(dir, d.name), {
|
|
19
19
|
encoding: 'utf8',
|
|
20
20
|
})));
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
3
|
export const createRepoVariable = async ({ name, value, }) => {
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
await octokit.request('POST /repos/{owner}/{repo}/actions/variables', {
|
|
6
6
|
owner: OWNER,
|
|
7
7
|
repo: REPO,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
3
|
export const listRepoVariables = async () => {
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
const result = await octokit.request('GET /repos/{owner}/{repo}/actions/variables', {
|
|
6
6
|
owner: OWNER,
|
|
7
7
|
repo: REPO,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { octokitHeaders, OWNER, REPO } from '../../constants.mjs';
|
|
2
2
|
import { octokit } from '../../octokit.mjs';
|
|
3
3
|
export const updateRepoVariable = async ({ name, value, }) => {
|
|
4
|
-
|
|
4
|
+
|
|
5
5
|
await octokit.request('PATCH /repos/{owner}/{repo}/actions/variables/{name}', {
|
|
6
6
|
owner: OWNER,
|
|
7
7
|
repo: REPO,
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
2
|
+
|
|
3
3
|
import 'dotenv/config';
|
|
4
4
|
import { isDirectlyExecuted } from 'ts-repo-utils';
|
|
5
5
|
import { createRepoVariable, listRepoVariables, updateRepoVariable, } from './api/index.mjs';
|
|
6
6
|
export const applyVariables = async () => {
|
|
7
7
|
const variables = [
|
|
8
8
|
{
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
|
|
10
|
+
|
|
11
11
|
name: 'REPO_SETTINGS_BOT_CLIENT_ID',
|
|
12
12
|
value: 'Iv23ctr4Lq9H3wOYRQrD',
|
|
13
13
|
},
|
|
14
14
|
{
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
19
|
name: 'REPO_AUTOMATION_BOT_CLIENT_ID',
|
|
20
20
|
value: 'Iv23lilpiDh0twq2PErv',
|
|
21
21
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "github-settings-as-code",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"keywords": [
|
|
6
6
|
"github",
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
"@octokit/core": "^7.0.8",
|
|
29
29
|
"dedent": "^1.7.2",
|
|
30
30
|
"dotenv": "^17.4.2",
|
|
31
|
-
"octokit-safe-types": "^1.2.
|
|
32
|
-
"ts-data-forge": "^14.6.
|
|
33
|
-
"ts-fortress": "^12.1.
|
|
34
|
-
"ts-repo-utils": "^10.
|
|
31
|
+
"octokit-safe-types": "^1.2.28",
|
|
32
|
+
"ts-data-forge": "^14.6.3",
|
|
33
|
+
"ts-fortress": "^12.1.1",
|
|
34
|
+
"ts-repo-utils": "^10.6.0",
|
|
35
35
|
"ts-type-forge": "^9.2.2"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
"@vitest/ui": "4.1.11",
|
|
41
41
|
"cspell": "10.1.1",
|
|
42
42
|
"eslint": "10.9.1",
|
|
43
|
-
"eslint-config-typed": "5.11.
|
|
44
|
-
"eslint-plugin-ts-data-forge": "0.
|
|
45
|
-
"eslint-plugin-ts-fortress": "1.
|
|
46
|
-
"eslint-plugin-ts-type-forge": "0.8.
|
|
43
|
+
"eslint-config-typed": "5.11.2",
|
|
44
|
+
"eslint-plugin-ts-data-forge": "0.7.0",
|
|
45
|
+
"eslint-plugin-ts-fortress": "1.2.0",
|
|
46
|
+
"eslint-plugin-ts-type-forge": "0.8.1",
|
|
47
47
|
"jiti": "2.7.0",
|
|
48
48
|
"npm-run-all2": "9.0.3",
|
|
49
49
|
"prettier": "3.9.6",
|