Skip to content

Commit 9dc6c51

Browse files
committed
feat: enable release immutability via GitHub API
Enable GitHub's immutable releases to lock published release assets and tags against tampering. It's enabled by default, can be disabled via setting `enableImmutableReleases` to false under `common.Repository` in .kres.yaml. Signed-off-by: Oguz Kilcan <oguz.kilcan@siderolabs.com>
1 parent f743355 commit 9dc6c51

1 file changed

Lines changed: 37 additions & 0 deletions

File tree

internal/project/common/repository.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ type Repository struct { //nolint:govet
4646
// GITHUB_TOKEN is unset, GitHub API integration is skipped entirely.
4747
DryRun bool `yaml:"dryRun,omitempty"`
4848

49+
EnableImmutableReleases bool `yaml:"enableImmutableReleases"`
4950
EnableConform bool `yaml:"enableConform"`
5051
ConformWebhookURL string `yaml:"conformWebhookURL"`
5152
ConformTypes []string `yaml:"conformTypes"`
@@ -84,6 +85,8 @@ func NewRepository(meta *meta.Options) *Repository {
8485

8586
MainBranch: meta.MainBranch,
8687

88+
EnableImmutableReleases: true,
89+
8790
EnableConform: true,
8891
ConformWebhookURL: "https://conform.dev.talos-systems.io/github",
8992
ConformTypes: []string{
@@ -198,6 +201,12 @@ func (r *Repository) CompileGitHub(client *github.Client) error {
198201
return err
199202
}
200203

204+
if r.EnableImmutableReleases {
205+
if err := r.enableImmutableReleases(client); err != nil {
206+
return err
207+
}
208+
}
209+
201210
if r.DryRun {
202211
return nil
203212
}
@@ -318,6 +327,34 @@ func (r *Repository) enableLabels(client *github.Client) error {
318327
return nil
319328
}
320329

330+
// enableImmutableReleases turns on immutable releases for the repository so that published release assets and tags can no longer be altered. Existing
331+
// releases stay mutable until republished; the setting only affects new ones.
332+
func (r *Repository) enableImmutableReleases(client *github.Client) error {
333+
if r.DryRun {
334+
fmt.Println("dry-run: repository would enable immutable releases")
335+
336+
return nil
337+
}
338+
339+
status, _, err := client.Repositories.AreImmutableReleasesEnabled(context.Background(), r.meta.GitHubOrganization, r.meta.GitHubRepository)
340+
if err != nil {
341+
return fmt.Errorf("failed to check immutable releases status: %w", err)
342+
}
343+
344+
// Already enabled directly or enforced by the org policy: nothing to do.
345+
if status.GetEnabled() || status.GetEnforcedByOwner() {
346+
return nil
347+
}
348+
349+
if _, err = client.Repositories.EnableImmutableReleases(context.Background(), r.meta.GitHubOrganization, r.meta.GitHubRepository); err != nil {
350+
return fmt.Errorf("failed to enable immutable releases: %w", err)
351+
}
352+
353+
fmt.Println("immutable releases enabled")
354+
355+
return nil
356+
}
357+
321358
func (r *Repository) buildEnforceContexts(base []string) []string {
322359
enforceContexts := base
323360

0 commit comments

Comments
 (0)