mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-25 21:29:14 +02:00
fix(gitlab): Use start_branch for file creation if branch doesn't exist already (#4792)
Creating files on a new branch is only possible with the API if `start_branch` is given otherwise the API returns: > You can only create or edit files when you are on a branch Fixes https://github.com/goreleaser/goreleaser/issues/4543 --------- Co-authored-by: Carlos Alexandro Becker <caarlos0@users.noreply.github.com>
This commit is contained in:
parent
4015fa32bc
commit
fd40f5d772
@ -98,6 +98,24 @@ func (c *gitlabClient) getDefaultBranch(_ *context.Context, repo Repo) (string,
|
||||
return p.DefaultBranch, nil
|
||||
}
|
||||
|
||||
// checkBranchExists checks if a branch exists
|
||||
func (c *gitlabClient) checkBranchExists(_ *context.Context, repo Repo, branch string) (bool, error) {
|
||||
projectID := repo.Name
|
||||
if repo.Owner != "" {
|
||||
projectID = repo.Owner + "/" + projectID
|
||||
}
|
||||
|
||||
// Verify if branch exists
|
||||
_, res, err := c.client.Branches.GetBranch(projectID, branch)
|
||||
if err != nil && res.StatusCode != 404 {
|
||||
log.WithError(err).
|
||||
Error("error verify branch existence")
|
||||
return false, err
|
||||
}
|
||||
|
||||
return res.StatusCode != 404, nil
|
||||
}
|
||||
|
||||
// CloseMilestone closes a given milestone.
|
||||
func (c *gitlabClient) CloseMilestone(_ *context.Context, repo Repo, title string) error {
|
||||
milestone, err := c.getMilestoneByTitle(repo, title)
|
||||
@ -135,57 +153,72 @@ func (c *gitlabClient) CreateFile(
|
||||
commitAuthor config.CommitAuthor,
|
||||
repo Repo,
|
||||
content []byte, // the content of the formula.rb
|
||||
path, // the path to the formula.rb
|
||||
fileName, // the path to the formula.rb
|
||||
message string, // the commit msg
|
||||
) error {
|
||||
fileName := path
|
||||
|
||||
projectID := repo.Name
|
||||
if repo.Owner != "" {
|
||||
projectID = repo.Owner + "/" + projectID
|
||||
}
|
||||
|
||||
// Use the project default branch if we can get it...otherwise, just use
|
||||
// 'master'
|
||||
var branch, ref string
|
||||
log.
|
||||
WithField("projectID", projectID).
|
||||
Debug("project id")
|
||||
|
||||
var branch, defaultBranch string
|
||||
var branchExists bool
|
||||
var err error
|
||||
// Use the branch if given one
|
||||
if repo.Branch != "" {
|
||||
branch = repo.Branch
|
||||
branchExists, err = c.checkBranchExists(ctx, repo, branch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Retrieving default branch because we need it for `start_branch`
|
||||
if !branchExists {
|
||||
defaultBranch, err = c.getDefaultBranch(ctx, repo)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
log.
|
||||
WithField("projectID", projectID).
|
||||
WithField("branch", branch).
|
||||
WithField("branchExists", branchExists).
|
||||
Debug("using given branch")
|
||||
} else {
|
||||
// Try to get the default branch from the Git provider
|
||||
branch, err = c.getDefaultBranch(ctx, repo)
|
||||
if err != nil {
|
||||
// Fall back to 'master' 😭
|
||||
log.
|
||||
WithField("fileName", fileName).
|
||||
WithField("projectID", projectID).
|
||||
WithField("requestedBranch", branch).
|
||||
WithError(err).
|
||||
Warn("error checking for default branch, using master")
|
||||
ref = "master"
|
||||
branch = "master"
|
||||
return err
|
||||
}
|
||||
|
||||
defaultBranch = branch
|
||||
branchExists = true
|
||||
|
||||
log.
|
||||
WithField("projectID", projectID).
|
||||
WithField("branch", branch).
|
||||
Debug("no branch given, using default branch")
|
||||
}
|
||||
ref = branch
|
||||
opts := &gitlab.GetFileOptions{Ref: &ref}
|
||||
castedContent := string(content)
|
||||
|
||||
log.
|
||||
WithField("projectID", projectID).
|
||||
WithField("ref", ref).
|
||||
WithField("branch", branch).
|
||||
Debug("projectID at brew")
|
||||
|
||||
log.
|
||||
WithField("projectID", projectID).
|
||||
Info("pushing")
|
||||
// If the branch doesn't exist, we need to check the default branch
|
||||
// because that's what we use as `start_branch` later if the file needs
|
||||
// to be created.
|
||||
opts := &gitlab.GetFileOptions{Ref: &defaultBranch}
|
||||
if branchExists {
|
||||
opts.Ref = &branch
|
||||
}
|
||||
|
||||
// Check if the file already exists
|
||||
_, res, err := c.client.RepositoryFiles.GetFile(projectID, fileName, opts)
|
||||
if err != nil && (res == nil || res.StatusCode != 404) {
|
||||
log := log.
|
||||
WithField("fileName", fileName).
|
||||
WithField("ref", ref).
|
||||
WithField("branch", branch).
|
||||
WithField("projectID", projectID)
|
||||
if res != nil {
|
||||
log = log.WithField("statusCode", res.StatusCode)
|
||||
@ -196,24 +229,34 @@ func (c *gitlabClient) CreateFile(
|
||||
}
|
||||
|
||||
log.
|
||||
WithField("fileName", fileName).
|
||||
WithField("branch", branch).
|
||||
WithField("projectID", projectID).
|
||||
Debug("found already existing brew formula file")
|
||||
WithField("branch", branch).
|
||||
WithField("fileName", fileName).
|
||||
Info("pushing file")
|
||||
|
||||
stringContents := string(content)
|
||||
|
||||
if res.StatusCode == 404 {
|
||||
// Create a new file because it's not already there
|
||||
log.
|
||||
WithField("fileName", fileName).
|
||||
WithField("ref", ref).
|
||||
WithField("projectID", projectID).
|
||||
Debug("creating brew formula")
|
||||
WithField("branch", branch).
|
||||
WithField("fileName", fileName).
|
||||
Debug("file doesn't exist, creating it")
|
||||
|
||||
createOpts := &gitlab.CreateFileOptions{
|
||||
AuthorName: &commitAuthor.Name,
|
||||
AuthorEmail: &commitAuthor.Email,
|
||||
Content: &castedContent,
|
||||
Content: &stringContents,
|
||||
Branch: &branch,
|
||||
CommitMessage: &message,
|
||||
}
|
||||
|
||||
// Branch not found, thus Gitlab requires a "start branch" to create the file
|
||||
if !branchExists {
|
||||
createOpts.StartBranch = &defaultBranch
|
||||
}
|
||||
|
||||
fileInfo, res, err := c.client.RepositoryFiles.CreateFile(projectID, fileName, createOpts)
|
||||
if err != nil {
|
||||
log := log.
|
||||
@ -237,19 +280,26 @@ func (c *gitlabClient) CreateFile(
|
||||
return nil
|
||||
}
|
||||
|
||||
// Update the existing file
|
||||
log.
|
||||
WithField("fileName", fileName).
|
||||
WithField("ref", ref).
|
||||
WithField("branch", branch).
|
||||
WithField("projectID", projectID).
|
||||
Debug("updating brew formula")
|
||||
Debug("file exists, updating it")
|
||||
|
||||
updateOpts := &gitlab.UpdateFileOptions{
|
||||
AuthorName: &commitAuthor.Name,
|
||||
AuthorEmail: &commitAuthor.Email,
|
||||
Content: &castedContent,
|
||||
Content: &stringContents,
|
||||
Branch: &branch,
|
||||
CommitMessage: &message,
|
||||
}
|
||||
|
||||
// Branch not found, thus Gitlab requires a "start branch" to update the file
|
||||
if !branchExists {
|
||||
updateOpts.StartBranch = &defaultBranch
|
||||
}
|
||||
|
||||
updateFileInfo, res, err := c.client.RepositoryFiles.UpdateFile(projectID, fileName, updateOpts)
|
||||
if err != nil {
|
||||
log := log.
|
||||
@ -260,7 +310,7 @@ func (c *gitlabClient) CreateFile(
|
||||
log = log.WithField("statusCode", res.StatusCode)
|
||||
}
|
||||
log.WithError(err).
|
||||
Error("error updating brew formula file")
|
||||
Error("error updating file")
|
||||
return err
|
||||
}
|
||||
|
||||
@ -272,7 +322,7 @@ func (c *gitlabClient) CreateFile(
|
||||
if res != nil {
|
||||
log = log.WithField("statusCode", res.StatusCode)
|
||||
}
|
||||
log.Debug("updated brew formula file")
|
||||
log.Debug("updated file")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -488,19 +488,52 @@ func TestGitLabChangelog(t *testing.T) {
|
||||
|
||||
func TestGitLabCreateFile(t *testing.T) {
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
// Handle the test where we know the branch
|
||||
// Handle the test where we know the branch and it exists
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something/repository/branches/somebranch") {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "{}")
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something/repository/files/newfile.txt") {
|
||||
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile.txt", "branch": "somebranch" }`))
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle the test where we detect the branch
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something") {
|
||||
_, err := io.Copy(w, strings.NewReader(`{ "default_branch": "main" }`))
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something/repository/files/newfile-in-default.txt") {
|
||||
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile.txt", "branch": "main" }`))
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle the test where the branch doesn't exist already
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something/repository/branches/non-existing-branch") {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(r.URL.Path, "projects/someone/something/repository/files/newfile-on-new-branch.txt") {
|
||||
if r.Method == "POST" {
|
||||
var resBody map[string]string
|
||||
require.NoError(t, json.NewDecoder(r.Body).Decode(&resBody))
|
||||
require.Equal(t, "master", resBody["start_branch"])
|
||||
}
|
||||
_, err := io.Copy(w, strings.NewReader(`{"file_path":"newfile-on-new-branch.txt","branch":"non-existing-branch"}`))
|
||||
require.NoError(t, err)
|
||||
return
|
||||
}
|
||||
|
||||
// Handle the case with a projectID
|
||||
if strings.HasSuffix(r.URL.Path, "projects/123456789/repository/branches/main") {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
fmt.Fprint(w, "{}")
|
||||
return
|
||||
}
|
||||
if strings.HasSuffix(r.URL.Path, "projects/123456789/repository/files/newfile-projectID.txt") {
|
||||
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile-projectID.txt", "branch": "main" }`))
|
||||
require.NoError(t, err)
|
||||
@ -530,7 +563,7 @@ func TestGitLabCreateFile(t *testing.T) {
|
||||
client, err := newGitLab(ctx, "test-token")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test using an arbitrary branch
|
||||
// Test using an arbitrary existing branch
|
||||
repo := Repo{
|
||||
Owner: "someone",
|
||||
Name: "something",
|
||||
@ -550,6 +583,16 @@ func TestGitLabCreateFile(t *testing.T) {
|
||||
err = client.CreateFile(ctx, config.CommitAuthor{Name: repo.Owner}, repo, []byte("Hello there"), "newfile-in-default.txt", "test: test commit")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test creating a new branch
|
||||
repo = Repo{
|
||||
Owner: "someone",
|
||||
Name: "something",
|
||||
Branch: "non-existing-branch",
|
||||
}
|
||||
|
||||
err = client.CreateFile(ctx, config.CommitAuthor{Name: repo.Owner}, repo, []byte("Hello there"), "newfile-on-new-branch.txt", "test: test commit")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test using projectID
|
||||
repo = Repo{
|
||||
Name: "123456789",
|
||||
|
Loading…
x
Reference in New Issue
Block a user