mirror of
https://github.com/goreleaser/goreleaser.git
synced 2025-03-29 21:47:01 +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
|
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.
|
// CloseMilestone closes a given milestone.
|
||||||
func (c *gitlabClient) CloseMilestone(_ *context.Context, repo Repo, title string) error {
|
func (c *gitlabClient) CloseMilestone(_ *context.Context, repo Repo, title string) error {
|
||||||
milestone, err := c.getMilestoneByTitle(repo, title)
|
milestone, err := c.getMilestoneByTitle(repo, title)
|
||||||
@ -135,57 +153,72 @@ func (c *gitlabClient) CreateFile(
|
|||||||
commitAuthor config.CommitAuthor,
|
commitAuthor config.CommitAuthor,
|
||||||
repo Repo,
|
repo Repo,
|
||||||
content []byte, // the content of the formula.rb
|
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
|
message string, // the commit msg
|
||||||
) error {
|
) error {
|
||||||
fileName := path
|
|
||||||
|
|
||||||
projectID := repo.Name
|
projectID := repo.Name
|
||||||
if repo.Owner != "" {
|
if repo.Owner != "" {
|
||||||
projectID = repo.Owner + "/" + projectID
|
projectID = repo.Owner + "/" + projectID
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the project default branch if we can get it...otherwise, just use
|
log.
|
||||||
// 'master'
|
WithField("projectID", projectID).
|
||||||
var branch, ref string
|
Debug("project id")
|
||||||
|
|
||||||
|
var branch, defaultBranch string
|
||||||
|
var branchExists bool
|
||||||
var err error
|
var err error
|
||||||
// Use the branch if given one
|
// Use the branch if given one
|
||||||
if repo.Branch != "" {
|
if repo.Branch != "" {
|
||||||
branch = 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 {
|
} else {
|
||||||
// Try to get the default branch from the Git provider
|
// Try to get the default branch from the Git provider
|
||||||
branch, err = c.getDefaultBranch(ctx, repo)
|
branch, err = c.getDefaultBranch(ctx, repo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Fall back to 'master' 😭
|
return err
|
||||||
log.
|
|
||||||
WithField("fileName", fileName).
|
|
||||||
WithField("projectID", projectID).
|
|
||||||
WithField("requestedBranch", branch).
|
|
||||||
WithError(err).
|
|
||||||
Warn("error checking for default branch, using master")
|
|
||||||
ref = "master"
|
|
||||||
branch = "master"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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.
|
// If the branch doesn't exist, we need to check the default branch
|
||||||
WithField("projectID", projectID).
|
// because that's what we use as `start_branch` later if the file needs
|
||||||
WithField("ref", ref).
|
// to be created.
|
||||||
WithField("branch", branch).
|
opts := &gitlab.GetFileOptions{Ref: &defaultBranch}
|
||||||
Debug("projectID at brew")
|
if branchExists {
|
||||||
|
opts.Ref = &branch
|
||||||
log.
|
}
|
||||||
WithField("projectID", projectID).
|
|
||||||
Info("pushing")
|
|
||||||
|
|
||||||
|
// Check if the file already exists
|
||||||
_, res, err := c.client.RepositoryFiles.GetFile(projectID, fileName, opts)
|
_, res, err := c.client.RepositoryFiles.GetFile(projectID, fileName, opts)
|
||||||
if err != nil && (res == nil || res.StatusCode != 404) {
|
if err != nil && (res == nil || res.StatusCode != 404) {
|
||||||
log := log.
|
log := log.
|
||||||
WithField("fileName", fileName).
|
WithField("fileName", fileName).
|
||||||
WithField("ref", ref).
|
WithField("branch", branch).
|
||||||
WithField("projectID", projectID)
|
WithField("projectID", projectID)
|
||||||
if res != nil {
|
if res != nil {
|
||||||
log = log.WithField("statusCode", res.StatusCode)
|
log = log.WithField("statusCode", res.StatusCode)
|
||||||
@ -196,24 +229,34 @@ func (c *gitlabClient) CreateFile(
|
|||||||
}
|
}
|
||||||
|
|
||||||
log.
|
log.
|
||||||
WithField("fileName", fileName).
|
|
||||||
WithField("branch", branch).
|
|
||||||
WithField("projectID", projectID).
|
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 {
|
if res.StatusCode == 404 {
|
||||||
|
// Create a new file because it's not already there
|
||||||
log.
|
log.
|
||||||
WithField("fileName", fileName).
|
|
||||||
WithField("ref", ref).
|
|
||||||
WithField("projectID", projectID).
|
WithField("projectID", projectID).
|
||||||
Debug("creating brew formula")
|
WithField("branch", branch).
|
||||||
|
WithField("fileName", fileName).
|
||||||
|
Debug("file doesn't exist, creating it")
|
||||||
|
|
||||||
createOpts := &gitlab.CreateFileOptions{
|
createOpts := &gitlab.CreateFileOptions{
|
||||||
AuthorName: &commitAuthor.Name,
|
AuthorName: &commitAuthor.Name,
|
||||||
AuthorEmail: &commitAuthor.Email,
|
AuthorEmail: &commitAuthor.Email,
|
||||||
Content: &castedContent,
|
Content: &stringContents,
|
||||||
Branch: &branch,
|
Branch: &branch,
|
||||||
CommitMessage: &message,
|
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)
|
fileInfo, res, err := c.client.RepositoryFiles.CreateFile(projectID, fileName, createOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log := log.
|
log := log.
|
||||||
@ -237,19 +280,26 @@ func (c *gitlabClient) CreateFile(
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Update the existing file
|
||||||
log.
|
log.
|
||||||
WithField("fileName", fileName).
|
WithField("fileName", fileName).
|
||||||
WithField("ref", ref).
|
WithField("branch", branch).
|
||||||
WithField("projectID", projectID).
|
WithField("projectID", projectID).
|
||||||
Debug("updating brew formula")
|
Debug("file exists, updating it")
|
||||||
|
|
||||||
updateOpts := &gitlab.UpdateFileOptions{
|
updateOpts := &gitlab.UpdateFileOptions{
|
||||||
AuthorName: &commitAuthor.Name,
|
AuthorName: &commitAuthor.Name,
|
||||||
AuthorEmail: &commitAuthor.Email,
|
AuthorEmail: &commitAuthor.Email,
|
||||||
Content: &castedContent,
|
Content: &stringContents,
|
||||||
Branch: &branch,
|
Branch: &branch,
|
||||||
CommitMessage: &message,
|
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)
|
updateFileInfo, res, err := c.client.RepositoryFiles.UpdateFile(projectID, fileName, updateOpts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log := log.
|
log := log.
|
||||||
@ -260,7 +310,7 @@ func (c *gitlabClient) CreateFile(
|
|||||||
log = log.WithField("statusCode", res.StatusCode)
|
log = log.WithField("statusCode", res.StatusCode)
|
||||||
}
|
}
|
||||||
log.WithError(err).
|
log.WithError(err).
|
||||||
Error("error updating brew formula file")
|
Error("error updating file")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,7 +322,7 @@ func (c *gitlabClient) CreateFile(
|
|||||||
if res != nil {
|
if res != nil {
|
||||||
log = log.WithField("statusCode", res.StatusCode)
|
log = log.WithField("statusCode", res.StatusCode)
|
||||||
}
|
}
|
||||||
log.Debug("updated brew formula file")
|
log.Debug("updated file")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -488,19 +488,52 @@ func TestGitLabChangelog(t *testing.T) {
|
|||||||
|
|
||||||
func TestGitLabCreateFile(t *testing.T) {
|
func TestGitLabCreateFile(t *testing.T) {
|
||||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
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") {
|
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" }`))
|
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile.txt", "branch": "somebranch" }`))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the test where we detect the branch
|
// 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") {
|
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" }`))
|
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile.txt", "branch": "main" }`))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
return
|
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
|
// 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") {
|
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" }`))
|
_, err := io.Copy(w, strings.NewReader(`{ "file_path": "newfile-projectID.txt", "branch": "main" }`))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@ -530,7 +563,7 @@ func TestGitLabCreateFile(t *testing.T) {
|
|||||||
client, err := newGitLab(ctx, "test-token")
|
client, err := newGitLab(ctx, "test-token")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Test using an arbitrary branch
|
// Test using an arbitrary existing branch
|
||||||
repo := Repo{
|
repo := Repo{
|
||||||
Owner: "someone",
|
Owner: "someone",
|
||||||
Name: "something",
|
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")
|
err = client.CreateFile(ctx, config.CommitAuthor{Name: repo.Owner}, repo, []byte("Hello there"), "newfile-in-default.txt", "test: test commit")
|
||||||
require.NoError(t, err)
|
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
|
// Test using projectID
|
||||||
repo = Repo{
|
repo = Repo{
|
||||||
Name: "123456789",
|
Name: "123456789",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user