Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions docs/github-settings/1. repository-settings.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ repository:
security:
enableVulnerabilityAlerts: true
enableAutomatedSecurityFixes: true
releases:
immutable: true
```

## Repository API Spec
Expand Down Expand Up @@ -414,5 +416,27 @@ repository:
...
```

</td></tr>
<tr><td>
<p><code>releases</code><span style="color:gray;">&emsp;<i>object</i>&emsp;</span></p>
<p>Settings for releases in this repository.</p>

<details><summary>Properties of <code>releases</code></summary>

<br>
<p>&emsp;<code>immutable</code><span style="color:gray;">&emsp;<i>boolean</i>&emsp;</span></p>
<p>&emsp;&emsp;Either <code>true</code> to enable release immutability (disallow assets and tags from being modified once a release is published), or <code>false</code> to disable it.</p>
<p>&emsp;&emsp;See <a href="https://docs.github.com/en/rest/repos/repos#enable-immutable-releases">Enable immutable releases</a> for more information.</p>
</details>

</td><td style="vertical-align:top">

```yaml
repository:
releases:
immutable: true
...
```

</td></tr>
</table>
5 changes: 5 additions & 0 deletions docs/sample-settings/settings.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ repository:
enableVulnerabilityAlerts: true
enableAutomatedSecurityFixes: true

# Settings for release immutability
# See https://docs.github.com/en/rest/repos/repos#enable-immutable-releases
releases:
immutable: true

# Either `true` to make the repository private, or `false` to make it public.
# If this value is changed and if org members cannot change the visibility of repos
# it would result in an error when updating a repo
Expand Down
39 changes: 38 additions & 1 deletion lib/plugins/repository.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ const ignorableFields = [
'force_create',
'auto_init',
'repo',
'archived'
'archived',
'releases'
]

module.exports = class Repository extends ErrorStash {
Expand All @@ -48,6 +49,7 @@ module.exports = class Repository extends ErrorStash {
this.settings = Object.assign({ mediaType: { previews: ['nebula-preview'] } }, settings, repo)
this.topics = this.settings.topics
this.security = this.settings.security
this.releases = this.settings.releases
this.repo = repo
this.log = log
this.nop = nop
Expand All @@ -56,6 +58,7 @@ module.exports = class Repository extends ErrorStash {
delete this.settings.topics
delete this.settings.force
delete this.settings.template
delete this.settings.releases
}

sync () {
Expand Down Expand Up @@ -109,8 +112,12 @@ module.exports = class Repository extends ErrorStash {
promises.push(updateRepoPromise.then(() => {
return this.updateAutomatedSecurityFixes(resp.data, resArray)
}))
promises.push(updateRepoPromise.then(() => {
return this.updateReleaseImmutability(resp.data, resArray)
}))
} else {
promises.push(this.updateSecurity(resp.data, resArray))
promises.push(this.updateReleaseImmutability(resp.data, resArray))
}
if (this.nop) {
return Promise.resolve(resArray)
Expand Down Expand Up @@ -315,4 +322,34 @@ module.exports = class Repository extends ErrorStash {
}
}
}

updateReleaseImmutability (repoData, resArray) {
if (this.releases?.immutable === true || this.releases?.immutable === false) {
const parms = {
owner: repoData.owner.login,
repo: repoData.name
}
if (this.releases.immutable === true) {
this.log.debug(`Enabling release immutability for owner: ${repoData.owner.login} and repo ${repoData.name}`)
if (this.nop) {
resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('PUT /repos/{owner}/{repo}/releases/immutability', parms), 'Enabling release immutability'))
return Promise.resolve(resArray)
}
return this.github.request('PUT /repos/{owner}/{repo}/releases/immutability', parms)
} else {
this.log.debug(`Disabling release immutability for owner: ${repoData.owner.login} and repo ${repoData.name}`)
if (this.nop) {
resArray.push(new NopCommand(this.constructor.name, this.repo, this.github.request.endpoint('DELETE /repos/{owner}/{repo}/releases/immutability', parms), 'Disabling release immutability'))
return Promise.resolve(resArray)
}
return this.github.request('DELETE /repos/{owner}/{repo}/releases/immutability', parms)
}
} else {
this.log.debug(`no need to update release immutability for ${repoData.name}`)
if (this.nop) {
return Promise.resolve([])
}
return Promise.resolve()
}
}
}
49 changes: 46 additions & 3 deletions test/unit/lib/plugins/repository.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,18 @@ describe('Repository', () => {
repos: {
get: jest.fn().mockResolvedValue({
data: {
topics: []
topics: [],
owner: { login: 'bkeepers' },
name: 'test'
}
}),
update: jest.fn().mockResolvedValue(),
replaceAllTopics: jest.fn().mockResolvedValue()
}
}
},
request: jest.fn().mockResolvedValue()
}
github.request.endpoint = jest.fn().mockReturnValue({})
const log = jest.fn()
log.debug = jest.fn()
log.error = jest.fn()
Expand Down Expand Up @@ -60,7 +64,7 @@ describe('Repository', () => {
})
})

it.only('syncs topics', () => {
it('syncs topics', () => {
const plugin = configure({
topics: ['foo', 'bar']
})
Expand All @@ -76,5 +80,44 @@ describe('Repository', () => {
})
})
})

it('enables release immutability', () => {
const plugin = configure({
releases: { immutable: true }
})

return plugin.sync().then(() => {
expect(github.request).toHaveBeenCalledWith(
'PUT /repos/{owner}/{repo}/releases/immutability',
{ owner: 'bkeepers', repo: 'test' }
)
})
})

it('disables release immutability', () => {
const plugin = configure({
releases: { immutable: false }
})

return plugin.sync().then(() => {
expect(github.request).toHaveBeenCalledWith(
'DELETE /repos/{owner}/{repo}/releases/immutability',
{ owner: 'bkeepers', repo: 'test' }
)
})
})

it('does not call release immutability API when releases setting is absent', () => {
const plugin = configure({
name: 'test'
})

return plugin.sync().then(() => {
expect(github.request).not.toHaveBeenCalledWith(
expect.stringMatching(/releases\/immutability/),
expect.anything()
)
})
})
})
})
Loading