diff --git a/cli.go b/cli.go index fc58465..6f7ce92 100644 --- a/cli.go +++ b/cli.go @@ -15,6 +15,7 @@ import ( "github.com/google/go-github/v47/github" "github.com/mitchellh/colorstring" + "github.com/pkg/errors" "github.com/tcnksm/go-gitconfig" ) @@ -294,17 +295,24 @@ func (cli *CLI) Run(args []string) int { return ExitCodeOK } - if err != nil && err != ErrReleaseNotFound { + if !errors.Is(err, ErrReleaseNotFound) { PrintRedf(cli.errStream, "Failed to get GitHub release: %s\n", err) return ExitCodeError } } - release, err := ghr.CreateRelease(ctx, req, recreate) + release, err := ghr.GitHub.GetDraftRelease(ctx, tag) if err != nil { - PrintRedf(cli.errStream, "Failed to create GitHub release page: %s\n", err) + PrintRedf(cli.errStream, "Failed to get draft release: %s\n", err) return ExitCodeError } + if release == nil { + release, err = ghr.CreateRelease(ctx, req, recreate) + if err != nil { + PrintRedf(cli.errStream, "Failed to create GitHub release page: %s\n", err) + return ExitCodeError + } + } if replace { err := ghr.DeleteAssets(ctx, *release.ID, localAssets, parallel) diff --git a/ghr.go b/ghr.go index f9f49a7..37dceae 100644 --- a/ghr.go +++ b/ghr.go @@ -38,7 +38,7 @@ func (g *GHR) CreateRelease(ctx context.Context, req *github.RepositoryRelease, // If release is not found, then create a new release. release, err := g.GitHub.GetRelease(ctx, *req.TagName) if err != nil { - if err != ErrReleaseNotFound { + if !errors.Is(err, ErrReleaseNotFound) { return nil, errors.Wrap(err, "failed to get release") } Debugf("Release (with tag %s) not found: create a new one", diff --git a/github.go b/github.go index d3a412e..be61da1 100644 --- a/github.go +++ b/github.go @@ -26,6 +26,7 @@ var ( type GitHub interface { CreateRelease(ctx context.Context, req *github.RepositoryRelease) (*github.RepositoryRelease, error) GetRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error) + GetDraftRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error) EditRelease(ctx context.Context, releaseID int64, req *github.RepositoryRelease) (*github.RepositoryRelease, error) DeleteRelease(ctx context.Context, releaseID int64) error DeleteTag(ctx context.Context, tag string) error @@ -129,6 +130,36 @@ func (c *GitHubClient) GetRelease(ctx context.Context, tag string) (*github.Repo return release, nil } +func (c *GitHubClient) GetDraftRelease(ctx context.Context, tag string) (*github.RepositoryRelease, error) { + const perPage = 100 + for page := 1; page <= 2; page++ { + releases, res, err := c.Repositories.ListReleases(ctx, c.Owner, c.Repo, &github.ListOptions{ + PerPage: perPage, + Page: page, + }) + if err != nil { + if res == nil { + return nil, errors.Wrapf(err, "failed to get releases while getting draft release for: %s", tag) + } + // TODO(tcnksm): Handle invalid token + if res.StatusCode != http.StatusNotFound { + return nil, errors.Wrapf(err, + "get release tag: invalid status: %s", res.Status) + } + return nil, ErrReleaseNotFound + } + for _, rel := range releases { + if *rel.Draft && *rel.TagName == tag { + return rel, nil + } + } + if len(releases) < perPage { + break + } + } + return nil, nil +} + // EditRelease edit a release object within the GitHub API func (c *GitHubClient) EditRelease(ctx context.Context, releaseID int64, req *github.RepositoryRelease) (*github.RepositoryRelease, error) { var release *github.RepositoryRelease