Skip to content

Commit 0c52f67

Browse files
authored
Merge branch 'main-enterprise' into pull-request-full-context
2 parents 2b82e20 + 41ef7a5 commit 0c52f67

33 files changed

+2967
-2025
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

README.md

Lines changed: 0 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

docs/github-action.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,13 @@ jobs:
3838
- uses: actions/checkout@v4
3939
with:
4040
repository: github/safe-settings
41-
ref: $SAFE_SETTINGS_VERSION
42-
path: $SAFE_SETTINGS_CODE_DIR
41+
ref: ${{ env.SAFE_SETTINGS_VERSION }}
42+
path: ${{ env.SAFE_SETTINGS_CODE_DIR }}
4343
- uses: actions/setup-node@v4
4444
- run: npm install
45-
working-directory: $SAFE_SETTINGS_CODE_DIR
45+
working-directory: ${{ env.SAFE_SETTINGS_CODE_DIR }}
4646
- run: npm run full-sync
47-
working-directory: $SAFE_SETTINGS_CODE_DIR
47+
working-directory: ${{ env.SAFE_SETTINGS_CODE_DIR }}
4848
env:
4949
GH_ORG: ${{ vars.SAFE_SETTINGS_GH_ORG }}
5050
APP_ID: ${{ vars.SAFE_SETTINGS_APP_ID }}

docs/github-settings/6. deployment-environments.md

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,14 @@ environments:
2727
- type: User
2828
id: 139262123
2929
deployment_branch_policy:
30-
protected_branches: true
31-
custom_branch_policies: false
30+
protected_branches: false
31+
custom_branch_policies:
32+
- names: ['main','dev']
33+
type: branch
34+
- names: ['v*.*.*']
35+
type: tag
3236
deployment_protection_rules:
33-
- app_id: 25112
37+
- app_id: 25112
3438
variables:
3539
- name: MY_AWESOME_VAR
3640
value: '845705'
@@ -43,7 +47,8 @@ environments:
4347
>[!TIP]
4448
>GitHub's API documentation defines these inputs and types:
4549
>1. [Create or update an environment](https://docs.github.com/en/rest/deployments/environments?apiVersion=2022-11-28#create-or-update-an-environment)
46-
>2. [Create an environment variable](https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-environment-variable)
50+
>2. [Create a deployment branch policy](https://docs.github.com/en/rest/deployments/branch-policies?apiVersion=2022-11-28#create-a-deployment-branch-policy)
51+
>3. [Create an environment variable](https://docs.github.com/en/rest/actions/variables?apiVersion=2022-11-28#create-an-environment-variable)
4752
4853
<table>
4954
<tr><td>
@@ -126,11 +131,11 @@ environments:
126131

127132
<details><summary>Properties of <code>deployment_branch_policy</code></summary>
128133
<br>
129-
<p>&emsp;<code>protected_branches</code><span style="color:gray;">&emsp;<i>string</i>&emsp;</span><span style="color:orange;">${\text{\color{orange}Required}}$</span></p>
130-
<p>&emsp;&emsp;Whether only branches with branch protection rules can deploy<br>&emsp;&emsp;to this environment. If <code>protected_branches</code> is <code>true</code>,<br>&emsp;&emsp;<code>custom_branch_policies</code> must be <code>false</code>; if <code>protected_branches</code><br>&emsp;&emsp;is <code>false</code>, <code>custom_branch_policies</code> must be <code>true</code>.</p>
134+
<p>&emsp;<code>protected_branches</code><span style="color:gray;">&emsp;<i>boolean</i>&emsp;</span><span style="color:orange;">${\text{\color{orange}Required}}$</span></p>
135+
<p>&emsp;&emsp;Whether only branches with branch protection rules can deploy<br>&emsp;&emsp;to this environment. If <code>protected_branches</code> is <code>true</code>,<br>&emsp;&emsp;<code>custom_branch_policies</code> must be <code>false</code>; if <code>protected_branches</code><br>&emsp;&emsp;is <code>false</code>, <code>custom_branch_policies</code> must be an object.</p>
131136

132-
<p>&emsp;<code>id</code><span style="color:gray;">&emsp;<i>integer</i>&emsp;</span></p>
133-
<p>&emsp;&emsp;Whether only branches that match the specified name patterns<br>&emsp;&emsp;can deploy to this environment. If <code>custom_branch_policies</code><br>&emsp;&emsp;is <code>true</code>, <code>protected_branches</code> must be <code>false</code>; if<br>&emsp;&emsp;<code>custom_branch_policies</code> is <code>false</code>, <code>protected_branches</code><br>&emsp;&emsp;must be <code>true</code>.</p>
137+
<p>&emsp;<code>custom_branch_policies</code><span style="color:gray;">&emsp;<i>boolean or object</i>&emsp;</span></p>
138+
<p>&emsp;&emsp;Whether only branches that match the specified name patterns<br>&emsp;&emsp;can deploy to this environment. If <code>custom_branch_policies</code><br>&emsp;&emsp;is <code>false</code>, <code>protected_branches</code> must be <code>true</code>; if<br>&emsp;&emsp;<code>custom_branch_policies</code> is an object, <code>protected_branches</code><br>&emsp;&emsp;must be <code>false</code>.</p>
134139

135140
</details>
136141

@@ -142,8 +147,12 @@ environments:
142147
- name: production
143148
...
144149
deployment_branch_policy:
145-
protected_branches: true
146-
custom_branch_policies: false
150+
protected_branches: false
151+
custom_branch_policies:
152+
- names: ['main','dev']
153+
type: branch
154+
- names: ['v*.*.*']
155+
type: tag
147156
...
148157
```
149158

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+

full-sync.js

Lines changed: 21 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,28 @@
1-
const { createProbot } = require('probot')
21
const appFn = require('./')
2+
const { FULL_SYNC_NOP } = require('./lib/env')
3+
const { createProbot } = require('probot')
4+
5+
async function performFullSync (appFn, nop) {
6+
const probot = createProbot()
7+
probot.log.info(`Starting full sync with NOP=${nop}`)
38

4-
const probot = createProbot()
5-
probot.log.info('Starting full sync.')
6-
const app = appFn(probot, {})
7-
app.syncInstallation()
8-
.then(settings => {
9-
if (settings.errors.length > 0) {
9+
try {
10+
const app = appFn(probot, {})
11+
const settings = await app.syncInstallation(nop)
12+
13+
if (settings.errors && settings.errors.length > 0) {
1014
probot.log.error('Errors occurred during full sync.')
1115
process.exit(1)
12-
} else {
13-
probot.log.info('Done with full sync.')
1416
}
15-
})
16-
.catch(error => {
17+
18+
probot.log.info('Full sync completed successfully.')
19+
} catch (error) {
1720
process.stdout.write(`Unexpected error during full sync: ${error}\n`)
1821
process.exit(1)
19-
})
22+
}
23+
}
24+
25+
performFullSync(appFn, FULL_SYNC_NOP).catch((error) => {
26+
console.error('Fatal error during full sync:', error)
27+
process.exit(1)
28+
})

index.js

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
2828
if (nop) {
2929
let filename = env.SETTINGS_FILE_PATH
3030
if (!deploymentConfig) {
31-
filename = env.DEPLOYMENT_CONFIG_FILE
31+
filename = env.DEPLOYMENT_CONFIG_FILE_PATH
3232
deploymentConfig = {}
3333
}
3434
const nopcommand = new NopCommand(filename, repo, null, e, 'ERROR')
@@ -53,7 +53,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
5353
if (nop) {
5454
let filename = env.SETTINGS_FILE_PATH
5555
if (!deploymentConfig) {
56-
filename = env.DEPLOYMENT_CONFIG_FILE
56+
filename = env.DEPLOYMENT_CONFIG_FILE_PATH
5757
deploymentConfig = {}
5858
}
5959
const nopcommand = new NopCommand(filename, repo, null, e, 'ERROR')
@@ -78,7 +78,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
7878
if (nop) {
7979
let filename = env.SETTINGS_FILE_PATH
8080
if (!deploymentConfig) {
81-
filename = env.DEPLOYMENT_CONFIG_FILE
81+
filename = env.DEPLOYMENT_CONFIG_FILE_PATH
8282
deploymentConfig = {}
8383
}
8484
const nopcommand = new NopCommand(filename, repo, null, e, 'ERROR')
@@ -104,7 +104,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
104104
if (nop) {
105105
let filename = env.SETTINGS_FILE_PATH
106106
if (!deploymentConfig) {
107-
filename = env.DEPLOYMENT_CONFIG_FILE
107+
filename = env.DEPLOYMENT_CONFIG_FILE_PATH
108108
deploymentConfig = {}
109109
}
110110
const nopcommand = new NopCommand(filename, repo, null, e, 'ERROR')
@@ -123,7 +123,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
123123
*/
124124
async function loadYamlFileSystem () {
125125
if (deploymentConfig === undefined) {
126-
const deploymentConfigPath = env.DEPLOYMENT_CONFIG_FILE
126+
const deploymentConfigPath = env.DEPLOYMENT_CONFIG_FILE_PATH
127127
if (fs.existsSync(deploymentConfigPath)) {
128128
deploymentConfig = yaml.load(fs.readFileSync(deploymentConfigPath))
129129
} else {
@@ -134,7 +134,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
134134
}
135135

136136
function getAllChangedSubOrgConfigs (payload) {
137-
const settingPattern = new Glob(`${env.CONFIG_PATH}/suborgs/*.yml`)
137+
const settingPattern = Settings.SUB_ORG_PATTERN
138138
// Changes will be an array of files that were added
139139
const added = payload.commits.map(c => {
140140
return (c.added.filter(s => {
@@ -158,7 +158,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
158158
}
159159

160160
function getAllChangedRepoConfigs (payload, owner) {
161-
const settingPattern = new Glob(`${env.CONFIG_PATH}/repos/*.yml`)
161+
const settingPattern = Settings.REPO_PATTERN
162162
// Changes will be an array of files that were added
163163
const added = payload.commits.map(c => {
164164
return (c.added.filter(s => {
@@ -230,7 +230,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
230230
}
231231
}
232232

233-
async function syncInstallation () {
233+
async function syncInstallation (nop = false) {
234234
robot.log.trace('Fetching installations')
235235
const github = await robot.auth()
236236

@@ -249,7 +249,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
249249
log: robot.log,
250250
repo: () => { return { repo: env.ADMIN_REPO, owner: installation.account.login } }
251251
}
252-
return syncAllSettings(false, context)
252+
return syncAllSettings(nop, context)
253253
}
254254
return null
255255
}
@@ -270,11 +270,11 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
270270
}
271271

272272
const settingsModified = payload.commits.find(commit => {
273-
return commit.added.includes(Settings.FILE_NAME) ||
274-
commit.modified.includes(Settings.FILE_NAME)
273+
return commit.added.includes(Settings.FILE_PATH) ||
274+
commit.modified.includes(Settings.FILE_PATH)
275275
})
276276
if (settingsModified) {
277-
robot.log.debug(`Changes in '${Settings.FILE_NAME}' detected, doing a full synch...`)
277+
robot.log.debug(`Changes in '${Settings.FILE_PATH}' detected, doing a full synch...`)
278278
return syncAllSettings(false, context)
279279
}
280280

@@ -292,7 +292,7 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
292292
}))
293293
}
294294

295-
robot.log.debug(`No changes in '${Settings.FILE_NAME}' detected, returning...`)
295+
robot.log.debug(`No changes in '${Settings.FILE_PATH}' detected, returning...`)
296296
})
297297

298298
robot.on('create', async context => {
@@ -597,21 +597,21 @@ module.exports = (robot, { getRouter }, Settings = require('./lib/settings')) =>
597597
const changes = await context.octokit.repos.compareCommitsWithBasehead(params)
598598
const files = changes.data.files.map(f => { return f.filename })
599599

600-
const settingsModified = files.includes(Settings.FILE_NAME)
600+
const settingsModified = files.includes(Settings.FILE_PATH)
601601

602602
if (settingsModified) {
603-
robot.log.debug(`Changes in '${Settings.FILE_NAME}' detected, doing a full synch...`)
603+
robot.log.debug(`Changes in '${Settings.FILE_PATH}' detected, doing a full synch...`)
604604
return syncAllSettings(true, context, context.repo(), pull_request.head.ref)
605605
}
606606

607-
const repoChanges = getChangedRepoConfigName(new Glob(`${env.CONFIG_PATH}/repos/*.yml`), files, context.repo().owner)
607+
const repoChanges = getChangedRepoConfigName(Settings.REPO_PATTERN, files, context.repo().owner)
608608
if (repoChanges.length > 0) {
609609
return Promise.all(repoChanges.map(repo => {
610610
return syncSettings(true, context, repo, pull_request.head.ref)
611611
}))
612612
}
613613

614-
const subOrgChanges = getChangedSubOrgConfigName(new Glob(`${env.CONFIG_PATH}/suborgs/*.yml`), files, context.repo().owner)
614+
const subOrgChanges = getChangedSubOrgConfigName(Settings.SUB_ORG_PATTERN, files, context.repo().owner)
615615
if (subOrgChanges.length) {
616616
return Promise.all(subOrgChanges.map(suborg => {
617617
return syncSubOrgSettings(true, context, suborg, context.repo(), pull_request.head.ref)

lib/deploymentConfig.js

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,23 @@ class DeploymentConfig {
1313
static overridevalidators = {}
1414

1515
static {
16-
const deploymentConfigPath = process.env.DEPLOYMENT_CONFIG_FILE ? process.env.DEPLOYMENT_CONFIG_FILE : 'deployment-settings.yml'
16+
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)