From 4ab3bd6f7e8bff7719c6c8756bfd8a86126a8616 Mon Sep 17 00:00:00 2001 From: Horst Gutmann Date: Tue, 28 Mar 2023 16:19:46 +0200 Subject: [PATCH] CI: Allow overwriting of existing GitHub release assets (#65127) * CI: Allow overwriting of existing GitHub release assets This closes #63698 * Use c for *cli.Context in publishgithub.go --- pkg/build/cmd/publishgithub.go | 62 +++++++++++++++++++++-------- pkg/build/cmd/publishgithub_test.go | 12 ++++++ pkg/build/config/genmetadata.go | 2 +- 3 files changed, 58 insertions(+), 18 deletions(-) diff --git a/pkg/build/cmd/publishgithub.go b/pkg/build/cmd/publishgithub.go index c59b1471ae4..610b702d7c7 100644 --- a/pkg/build/cmd/publishgithub.go +++ b/pkg/build/cmd/publishgithub.go @@ -19,6 +19,8 @@ type githubRepositoryService interface { GetReleaseByTag(ctx context.Context, owner string, repo string, tag string) (*github.RepositoryRelease, *github.Response, error) CreateRelease(ctx context.Context, owner string, repo string, release *github.RepositoryRelease) (*github.RepositoryRelease, *github.Response, error) UploadReleaseAsset(ctx context.Context, owner string, repo string, id int64, opt *github.UploadOptions, file *os.File) (*github.ReleaseAsset, *github.Response, error) + DeleteReleaseAsset(ctx context.Context, owner string, repo string, id int64) (*github.Response, error) + ListReleaseAssets(ctx context.Context, owner string, repo string, id int64, opt *github.ListOptions) ([]*github.ReleaseAsset, *github.Response, error) } type githubRepo struct { @@ -41,9 +43,10 @@ var ( errReleaseNotFound = errors.New(`release not found, use "--create" to create the release`) ) -func PublishGithub(ctx *cli.Context) error { +func PublishGithub(c *cli.Context) error { + ctx := c.Context token := os.Getenv("GH_TOKEN") - f, err := getPublishGithubFlags(ctx) + f, err := getPublishGithubFlags(c) if err != nil { return err } @@ -57,18 +60,18 @@ func PublishGithub(ctx *cli.Context) error { } if f.dryRun { - return runPublishGithubDryRun(f, token, ctx) + return runPublishGithubDryRun(f, token, c) } - client := newGithubClient(ctx.Context, token) - release, res, err := client.GetReleaseByTag(ctx.Context, f.repo.owner, f.repo.name, f.tag) + client := newGithubClient(ctx, token) + release, res, err := client.GetReleaseByTag(ctx, f.repo.owner, f.repo.name, f.tag) if err != nil && res.StatusCode != 404 { return err } if release == nil { if f.create { - release, _, err = client.CreateRelease(ctx.Context, f.repo.owner, f.repo.name, &github.RepositoryRelease{TagName: &f.tag}) + release, _, err = client.CreateRelease(ctx, f.repo.owner, f.repo.name, &github.RepositoryRelease{TagName: &f.tag}) if err != nil { return err } @@ -83,7 +86,32 @@ func PublishGithub(ctx *cli.Context) error { return err } - asset, _, err := client.UploadReleaseAsset(ctx.Context, f.repo.owner, f.repo.name, *release.ID, &github.UploadOptions{Name: artifactName}, file) + assetsPage := 1 + foundAsset := false + for { + assets, resp, err := client.ListReleaseAssets(ctx, f.repo.owner, f.repo.name, *release.ID, &github.ListOptions{ + Page: assetsPage, + }) + if err != nil { + return err + } + for _, asset := range assets { + if asset.GetName() == artifactName { + fmt.Printf("Found existing artifact with the name '%s'. Deleting that now.\n", artifactName) + if _, err := client.DeleteReleaseAsset(ctx, f.repo.owner, f.repo.name, asset.GetID()); err != nil { + return fmt.Errorf("failed to delete already existing asset: %w", err) + } + foundAsset = true + break + } + } + if resp.NextPage <= assetsPage || foundAsset { + break + } + assetsPage = resp.NextPage + } + + asset, _, err := client.UploadReleaseAsset(ctx, f.repo.owner, f.repo.name, *release.ID, &github.UploadOptions{Name: artifactName}, file) if err != nil { return err } @@ -101,21 +129,21 @@ func githubRepositoryClient(ctx context.Context, token string) githubRepositoryS return client.Repositories } -func getPublishGithubFlags(ctx *cli.Context) (*publishGithubFlags, error) { - metadata, err := config.GenerateMetadata(ctx) +func getPublishGithubFlags(c *cli.Context) (*publishGithubFlags, error) { + metadata, err := config.GenerateMetadata(c) if err != nil { return nil, err } - tag := ctx.Value("tag").(string) + tag := c.Value("tag").(string) if tag == "" && metadata.GrafanaVersion != "" { tag = fmt.Sprintf("v%s", metadata.GrafanaVersion) } - fullRepo := ctx.Value("repo").(string) - dryRun := ctx.Value("dry-run").(bool) + fullRepo := c.Value("repo").(string) + dryRun := c.Value("dry-run").(bool) owner := strings.Split(fullRepo, "/")[0] name := strings.Split(fullRepo, "/")[1] - create := ctx.Value("create").(bool) - artifactPath := ctx.Value("path").(string) + create := c.Value("create").(bool) + artifactPath := c.Value("path").(string) if artifactPath == "" { artifactPath = fmt.Sprintf("grafana-enterprise2-%s-amd64.img", metadata.GrafanaVersion) fmt.Printf("path argument is not provided, resolving to default %s...\n", artifactPath) @@ -132,10 +160,10 @@ func getPublishGithubFlags(ctx *cli.Context) (*publishGithubFlags, error) { }, nil } -func runPublishGithubDryRun(f *publishGithubFlags, token string, ctx *cli.Context) error { - client := newGithubClient(ctx.Context, token) +func runPublishGithubDryRun(f *publishGithubFlags, token string, c *cli.Context) error { + client := newGithubClient(c.Context, token) fmt.Println("Dry-Run: Retrieving release on repository by tag") - release, res, err := client.GetReleaseByTag(ctx.Context, f.repo.owner, f.repo.name, f.tag) + release, res, err := client.GetReleaseByTag(c.Context, f.repo.owner, f.repo.name, f.tag) if err != nil && res.StatusCode != 404 { fmt.Println("Dry-Run: Github communication error:\n", err) return nil diff --git a/pkg/build/cmd/publishgithub_test.go b/pkg/build/cmd/publishgithub_test.go index 6c9b0b18934..698b8048a05 100644 --- a/pkg/build/cmd/publishgithub_test.go +++ b/pkg/build/cmd/publishgithub_test.go @@ -224,3 +224,15 @@ func (m *mockGithubRepositoryServiceImpl) UploadReleaseAsset(ctx context.Context assetUrl := "testurl.com.br" return &github.ReleaseAsset{Name: &assetName, BrowserDownloadURL: &assetUrl}, &github.Response{}, m.uploadErr } + +func (m *mockGithubRepositoryServiceImpl) DeleteReleaseAsset(ctx context.Context, owner string, repo string, id int64) (*github.Response, error) { + return nil, nil +} + +func (m *mockGithubRepositoryServiceImpl) ListReleaseAssets(ctx context.Context, owner string, repo string, id int64, opts *github.ListOptions) ([]*github.ReleaseAsset, *github.Response, error) { + resp := github.Response{} + resp.LastPage = 1 + resp.FirstPage = 1 + resp.NextPage = 0 + return []*github.ReleaseAsset{}, &resp, nil +} diff --git a/pkg/build/config/genmetadata.go b/pkg/build/config/genmetadata.go index 74ffde8f201..f79094c5979 100644 --- a/pkg/build/config/genmetadata.go +++ b/pkg/build/config/genmetadata.go @@ -84,7 +84,7 @@ func GenerateMetadata(c *cli.Context) (Metadata, error) { CurrentCommit: currentCommit, } - fmt.Printf("building Grafana version: %s, release mode: %+v", metadata.GrafanaVersion, metadata.ReleaseMode) + fmt.Printf("building Grafana version: %s, release mode: %+v\n", metadata.GrafanaVersion, metadata.ReleaseMode) return metadata, nil }