Skip to content

Commit 9a51242

Browse files
authored
Merge branch 'main-enterprise' into refactor/settings-consolidation
2 parents dd9b03f + 620cf14 commit 9a51242

File tree

19 files changed

+2966
-1775
lines changed

19 files changed

+2966
-1775
lines changed

.github/workflows/create-pre-release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,15 +50,15 @@ jobs:
5050
cache: 'npm'
5151
- run: npm install
5252
- name: Set up Docker Buildx
53-
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5
53+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
5454
- name: Log in to the Container registry
5555
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
5656
with:
5757
registry: ${{ env.REGISTRY }}
5858
username: ${{ github.actor }}
5959
password: ${{ secrets.GITHUB_TOKEN }}
6060
- name: Build Docker Image Locally
61-
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
61+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
6262
with:
6363
context: .
6464
file: ./Dockerfile
@@ -85,7 +85,7 @@ jobs:
8585
commitish: ${{ github.ref }}
8686
- name: Push Docker Image
8787
if: ${{ success() }}
88-
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
88+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
8989
with:
9090
context: .
9191
file: ./Dockerfile

.github/workflows/create-release.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,15 @@ jobs:
2828
cache: "npm"
2929
- run: npm install
3030
- name: Set up Docker Buildx
31-
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5
31+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
3232
- name: Log in to the Container registry
3333
uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567
3434
with:
3535
registry: ${{ env.REGISTRY }}
3636
username: ${{ github.actor }}
3737
password: ${{ secrets.GITHUB_TOKEN }}
3838
- name: Build Docker Image Locally
39-
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
39+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
4040
with:
4141
context: .
4242
file: ./Dockerfile
@@ -59,7 +59,7 @@ jobs:
5959
bump: final
6060
- name: Push Docker Image
6161
if: ${{ success() }}
62-
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
62+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
6363
with:
6464
context: .
6565
file: ./Dockerfile

.github/workflows/rc-release.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,15 @@ jobs:
6868

6969
- name: Extract metadata
7070
id: meta
71-
uses: docker/metadata-action@369eb591f429131d6889c46b94e711f089e6ca96
71+
uses: docker/metadata-action@902fa8ec7d6ecbf8d84d538b9b233a880e428804
7272
with:
7373
images: ${{ env.REGISTRY }}/${{ github.repository_owner }}/${{ env.IMAGE_NAME }}
7474
- name: Set up QEMU
75-
uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf
75+
uses: docker/setup-qemu-action@29109295f81e9208d7d86ff1c6c12d2833863392
7676
- name: Set up Docker Buildx
77-
uses: docker/setup-buildx-action@6524bf65af31da8d45b59e8c27de4bd072b392f5
77+
uses: docker/setup-buildx-action@b5ca514318bd6ebac0fb2aedd5d36ec1b5c232a2
7878
- name: Build and push Docker image
79-
uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355
79+
uses: docker/build-push-action@471d1dc4e07e5cdedd4c2171150001c434f0b7a4
8080
with:
8181
context: .
8282
push: true

NOTICE.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
- type-fest, 0.3.1,(MIT OR CC0-1.0),
55
- type-fest, 0.6.0,(MIT OR CC0-1.0),
66
- type-fest, 0.8.1,(MIT OR CC0-1.0),
7+
- @apidevtools/json-schema-ref-parser, MIT
78
- @babel/code-frame, 7.12.13, MIT,
89
- @babel/code-frame, 7.5.5, MIT,
910
- @babel/compat-data, 7.13.11, MIT,

README.md

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
> [!NOTE]
3131
> The `suborg` and `repo` level settings directory structure cannot be customized.
3232
>
33-
> Settings files must have a `.yml` extension only. For now, the `.yaml` extension is ignored.
3433
3534

3635
## How it works
@@ -123,6 +122,46 @@ overridevalidators:
123122
124123
A sample of `deployment-settings` file is found [here](docs/sample-settings/sample-deployment-settings.yml).
125124

125+
### Custom Status Checks
126+
For branch protection rules and rulesets, you can allow for status checks to be defined outside of safe-settings together with your usual safe settings.
127+
128+
This can be defined at the org, sub-org, and repo level.
129+
130+
To configure this for branch protection rules, specify `{{EXTERNALLY_DEFINED}}` under the `contexts` keyword:
131+
```yaml
132+
branches:
133+
- name: main
134+
protection:
135+
...
136+
required_status_checks:
137+
contexts:
138+
- "{{EXTERNALLY_DEFINED}}"
139+
```
140+
141+
For rulesets, specify `{{EXTERNALLY_DEFINED}}` under the `required_status_checks` keyword:
142+
```yaml
143+
rulesets:
144+
- name: Status Checks
145+
...
146+
rules:
147+
- type: required_status_checks
148+
parameters:
149+
required_status_checks:
150+
- context: "{{EXTERNALLY_DEFINED}}"
151+
```
152+
153+
Notes:
154+
- For the same branch that is covered by multi-level branch protection rules, contexts defined at the org level are merged into the sub-org and repo level contexts, while contexts defined at the sub-org level are merged into the repo level contexts.
155+
- Rules from the sub-org level are merged into the repo level when their ruleset share the same name. Becareful not to define the same rule type in both levels as it will be rejected by GitHub.
156+
- When `{{EXTERNALLY_DEFINED}}` is defined for a new branch protection rule or ruleset configuration, they will be deployed with no status checks.
157+
- When an existing branch protection rule or ruleset configuration is amended with `{{EXTERNALLY_DEFINED}}`, the status checks in the existing rules in GitHub will remain as is.
158+
159+
> ⚠️ **Warning:**
160+
When `{{EXTERNALLY_DEFINED}}` is removed from an existing branch protection rule or ruleset configuration, the status checks in the existing rules in GitHub will revert to the checks that are defined in safe-settings. From this point onwards, all status checks configured through the GitHub UI will be reverted back to the safe-settings configuration.
161+
162+
#### Status checks inheritance across scopes
163+
Refer to [Status checks](docs/status-checks.md).
164+
126165
### Performance
127166
When there are 1000s of repos to be managed -- and there is a global settings change -- safe-settings will have to work efficiently and only make the necessary API calls.
128167

docs/github-settings/README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
| Configure branch protection rules | [Branch Protection](5.%20branch-protection.md) |
1010
| Configure deployment environments | [Deployment Environments](6.%20deployment-environments.md) |
1111
| Configure auto-link references | [AutoLinks](7.%20autolinks.md) |
12-
| Configure pre-defined labels for issues and pull requests | [Labels](8.%20labels.md) |
12+
| Configure pre-defined labels for issues and pull requests | [Labels](8.%20labels.md) |
13+

docs/status-checks.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
## Status checks inheritance across scopes
2+
3+
### Rulesets
4+
5+
The status checks between organisation and repository rulesets are independent of each together.
6+
7+
In the following examples, a common ruleset name is used at all levels. Repo1 and Repo2 are managed at the Sub-org level.
8+
9+
#### No custom checks
10+
```
11+
Org checks:
12+
Org Check
13+
Sub-org checks:
14+
Sub-org Check
15+
Repo checks for Repo2:
16+
Repo Check
17+
```
18+
19+
Status checks:
20+
- Newly deployed rules:
21+
- Org: Org Check
22+
- Repo1: Sub-org Check
23+
- Repo2: _Failed to deploy as required_status_checks can't be defined twice in both sub-org and repo level_
24+
- Updating status checks via GitHub UI:
25+
- Org: Status checks reverted back to safe settings
26+
- Repo1: Status checks reverted back to safe settings
27+
- Repo2: NA
28+
29+
#### No custom checks 2
30+
```
31+
Org checks:
32+
Org Check
33+
Sub-org checks:
34+
Sub-org Check
35+
Repo checks for Repo2:
36+
_NONE_
37+
```
38+
39+
Status checks:
40+
- Newly deployed rules:
41+
- Org: Org Check
42+
- Repo1: Sub-org Check
43+
- Repo2: _NONE_
44+
- Updating status checks via GitHub UI:
45+
- Org: Status checks reverted back to safe settings
46+
- Repo1: Status checks reverted back to safe settings
47+
- Repo2: Custom status checks are retained
48+
49+
**The remaining tests will leave Repo2 out of the Sub-org.**
50+
51+
#### Custom checks enabled at the Org and Sub-org level
52+
```
53+
Org:
54+
Org Check
55+
{{EXTERNALLY_DEFINED}}
56+
Sub-org checks:
57+
Sub-org Check
58+
{{EXTERNALLY_DEFINED}}
59+
Repo checks for Repo2:
60+
Repo Check
61+
```
62+
63+
Status checks:
64+
- Newly deployed rules:
65+
- Org: []
66+
- Repo1: []
67+
- Repo2: Repo Check
68+
- Updating status checks via GitHub UI:
69+
- Org: Custom status checks are retained
70+
- Repo1: Custom status checks are retained
71+
- Repo2: Status checks reverted back to safe settings
72+
73+
#### Custom checks enabled at the Repo level
74+
```
75+
Org:
76+
Org Check
77+
Sub-org checks:
78+
Sub-org Check
79+
Repo checks for Repo2:
80+
Repo Check
81+
{{EXTERNALLY_DEFINED}}
82+
```
83+
84+
Status checks:
85+
- Newly deployed rules:
86+
- Org: Org Check
87+
- Repo1: Sub-org Check
88+
- Repo2: []
89+
- Updating status checks via GitHub UI:
90+
- Org: Status checks reverted back to safe settings
91+
- Repo1: Status checks reverted back to safe settings
92+
- Repo2: Custom status checks are retained
93+
94+
95+
### Branch protection rules
96+
97+
In the following examples the `main` branch is protected at all levels. Repo1 and Repo2 are managed at the Sub-org level.
98+
99+
#### No custom checks
100+
```
101+
Org checks:
102+
Org Check
103+
Sub-org checks:
104+
Sub-org Check
105+
Repo checks for Repo2:
106+
Repo Check
107+
```
108+
109+
Status checks:
110+
- Newly deployed rules:
111+
- Repo1: Org Check, Sub-org Check
112+
- Repo2: Org Check, Sub-org Check, Repo Check
113+
- Updating status checks via GitHub UI:
114+
- Repo1: Status checks reverted back to safe settings
115+
- Repo2: Status checks reverted back to safe settings
116+
117+
#### Custom checks enabled at the Org level
118+
```
119+
Org:
120+
Org Check
121+
{{EXTERNALLY_DEFINED}}
122+
Sub-org checks:
123+
Sub-org Check
124+
Repo checks for Repo2:
125+
Repo Check
126+
```
127+
128+
Status checks:
129+
- Newly deployed rules:
130+
- Repo1: []
131+
- Repo2: []
132+
- Updating status checks via GitHub UI:
133+
- Repo1: Custom status checks are retained
134+
- Repo2: Custom status checks are retained
135+
136+
#### Custom checks enabled at the Sub-org level
137+
```
138+
Org:
139+
Org Check
140+
Sub-org checks:
141+
Sub-org Check
142+
{{EXTERNALLY_DEFINED}}
143+
Repo checks for Repo2:
144+
Repo Check
145+
```
146+
147+
Status checks:
148+
- Newly deployed rules:
149+
- Repo1: []
150+
- Repo2: []
151+
- Updating status checks via GitHub UI:
152+
- Repo1: Custom status checks are retained
153+
- Repo2: Custom status checks are retained
154+
155+
#### Custom checks enabled at the Repo level
156+
```
157+
Org:
158+
Org Check
159+
Sub-org checks:
160+
Sub-org Check
161+
Repo checks for Repo2:
162+
Repo Check
163+
{{EXTERNALLY_DEFINED}}
164+
```
165+
166+
Status checks:
167+
- Newly deployed rules:
168+
- Repo1: Org Check, Sub-org Check
169+
- Repo2: []
170+
- Updating status checks via GitHub UI:
171+
- Repo1: Status checks reverted back to safe settings
172+
- Repo2: Custom status checks are retained

lib/deploymentConfig.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,21 +15,21 @@ class DeploymentConfig {
1515
static {
1616
const deploymentConfigPath = env.DEPLOYMENT_CONFIG_FILE_PATH
1717
if (fs.existsSync(deploymentConfigPath)) {
18-
this.config = yaml.load(fs.readFileSync(deploymentConfigPath))
18+
this.config = yaml.load(fs.readFileSync(deploymentConfigPath)) || {}
1919
} else {
2020
this.config = { restrictedRepos: ['admin', '.github', 'safe-settings'] }
2121
}
2222

23-
const overridevalidators = this.config.overridevalidators
24-
if (this.isIterable(overridevalidators)) {
23+
const overridevalidators = this.config.overridevalidators || []
24+
if (this.isNonEmptyArray(overridevalidators)) {
2525
for (const validator of overridevalidators) {
2626
// eslint-disable-next-line no-new-func
2727
const f = new Function('baseconfig', 'overrideconfig', 'githubContext', validator.script)
2828
this.overridevalidators[validator.plugin] = { canOverride: f, error: validator.error }
2929
}
3030
}
31-
const configvalidators = this.config.configvalidators
32-
if (this.isIterable(configvalidators)) {
31+
const configvalidators = this.config.configvalidators || []
32+
if (this.isNonEmptyArray(configvalidators)) {
3333
for (const validator of configvalidators) {
3434
// eslint-disable-next-line no-new-func
3535
const f = new Function('baseconfig', 'githubContext', validator.script)
@@ -38,12 +38,8 @@ class DeploymentConfig {
3838
}
3939
}
4040

41-
static isIterable (obj) {
42-
// checks for null and undefined
43-
if (obj == null) {
44-
return false
45-
}
46-
return typeof obj[Symbol.iterator] === 'function'
41+
static isNonEmptyArray (obj) {
42+
return Array.isArray(obj) && obj.length > 0
4743
}
4844

4945
// eslint-disable-next-line no-useless-constructor

0 commit comments

Comments
 (0)