1
0
mirror of https://github.com/goreleaser/goreleaser.git synced 2025-07-05 00:59:04 +02:00

feat: allow to PR homebrew taps (#3903)

closes #3485

also fixed a bug in file creation for github: it was always searching
for the file in the default branch

also, we don't need to create the file first, update does both create
and update.

TODO: implement the for krew, scoop, etc...

---------

Signed-off-by: Carlos A Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
Carlos Alexandro Becker
2023-04-06 22:58:06 -03:00
committed by GitHub
parent ed2e378c87
commit 8b1c4ead60
18 changed files with 651 additions and 118 deletions

View File

@ -21,12 +21,24 @@ import (
const DefaultGitHubDownloadURL = "https://github.com"
var (
_ Client = &githubClient{}
_ ReleaseNotesGenerator = &githubClient{}
_ PullRequestOpener = &githubClient{}
)
type githubClient struct {
client *github.Client
}
// NewGitHub returns a github client implementation.
func NewGitHub(ctx *context.Context, token string) (GitHubClient, error) {
// NewGitHubReleaseNotesGenerator returns a GitHub client that can generate
// changelogs.
func NewGitHubReleaseNotesGenerator(ctx *context.Context, token string) (ReleaseNotesGenerator, error) {
return newGitHub(ctx, token)
}
// newGitHub returns a github client implementation.
func newGitHub(ctx *context.Context, token string) (*githubClient, error) {
ts := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
@ -89,8 +101,8 @@ func (c *githubClient) Changelog(ctx *context.Context, repo Repo, prev, current
return strings.Join(log, "\n"), nil
}
// GetDefaultBranch returns the default branch of a github repo
func (c *githubClient) GetDefaultBranch(ctx *context.Context, repo Repo) (string, error) {
// getDefaultBranch returns the default branch of a github repo
func (c *githubClient) getDefaultBranch(ctx *context.Context, repo Repo) (string, error) {
p, res, err := c.client.Repositories.Get(ctx, repo.Owner, repo.Name)
if err != nil {
log.WithFields(log.Fields{
@ -128,6 +140,35 @@ func (c *githubClient) CloseMilestone(ctx *context.Context, repo Repo, title str
return err
}
func (c *githubClient) OpenPullRequest(
ctx *context.Context,
repo Repo,
base, title string,
) error {
if base == "" {
def, err := c.getDefaultBranch(ctx, repo)
if err != nil {
return err
}
base = def
}
pr, res, err := c.client.PullRequests.Create(ctx, repo.Owner, repo.Name, &github.NewPullRequest{
Title: github.String(title),
Head: github.String(repo.Branch),
Base: github.String(base),
Body: github.String("Automatically generated by [GoReleaser](https://goreleaser.com)"),
})
if err != nil {
if res.StatusCode == 422 {
log.Warn("PR already exists, doing nothing...")
return nil
}
return fmt.Errorf("could not create pull request: %w", err)
}
log.WithField("url", pr.GetHTMLURL()).Info("opened")
return nil
}
func (c *githubClient) CreateFile(
ctx *context.Context,
commitAuthor config.CommitAuthor,
@ -136,22 +177,16 @@ func (c *githubClient) CreateFile(
path,
message string,
) error {
var branch string
var err error
if repo.Branch != "" {
branch = repo.Branch
} else {
branch, err = c.GetDefaultBranch(ctx, repo)
if err != nil {
// Fall back to sdk default
log.WithFields(log.Fields{
"fileName": path,
"projectID": repo.String(),
"requestedBranch": branch,
"err": err.Error(),
}).Warn("error checking for default branch, using master")
}
defBranch, err := c.getDefaultBranch(ctx, repo)
if err != nil {
return fmt.Errorf("could not get default branch: %w", err)
}
branch := repo.Branch
if branch == "" {
branch = defBranch
}
options := &github.RepositoryContentFileOptions{
Committer: &github.CommitAuthor{
Name: github.String(commitAuthor.Name),
@ -167,36 +202,53 @@ func (c *githubClient) CreateFile(
options.Branch = &branch
}
if defBranch != branch && branch != "" {
_, res, err := c.client.Repositories.GetBranch(ctx, repo.Owner, repo.Name, branch, true)
if err != nil && (res == nil || res.StatusCode != 404) {
return fmt.Errorf("could not get branch %q: %w", branch, err)
}
if res.StatusCode == 404 {
defRef, _, err := c.client.Git.GetRef(ctx, repo.Owner, repo.Name, "refs/heads/"+defBranch)
if err != nil {
return fmt.Errorf("could not get ref %q: %w", "refs/heads/"+defBranch, err)
}
if _, _, err := c.client.Git.CreateRef(ctx, repo.Owner, repo.Name, &github.Reference{
Ref: github.String("refs/heads/" + branch),
Object: &github.GitObject{
SHA: defRef.Object.SHA,
},
}); err != nil {
return fmt.Errorf("could not create ref %q from %q: %w", "refs/heads/"+branch, defRef.Object.GetSHA(), err)
}
}
}
file, _, res, err := c.client.Repositories.GetContents(
ctx,
repo.Owner,
repo.Name,
path,
&github.RepositoryContentGetOptions{},
&github.RepositoryContentGetOptions{
Ref: branch,
},
)
if err != nil && (res == nil || res.StatusCode != 404) {
return err
return fmt.Errorf("could not get %q: %w", path, err)
}
if res.StatusCode == 404 {
_, _, err = c.client.Repositories.CreateFile(
ctx,
repo.Owner,
repo.Name,
path,
options,
)
return err
}
options.SHA = file.SHA
_, _, err = c.client.Repositories.UpdateFile(
options.SHA = github.String(file.GetSHA())
if _, _, err := c.client.Repositories.UpdateFile(
ctx,
repo.Owner,
repo.Name,
path,
options,
)
return err
); err != nil {
return fmt.Errorf("could not update %q: %w", path, err)
}
return nil
}
func (c *githubClient) CreateRelease(ctx *context.Context, body string) (string, error) {