diff --git a/internal/client/gitea.go b/internal/client/gitea.go index 601c5f8ebc2..fabfdc31a05 100644 --- a/internal/client/gitea.go +++ b/internal/client/gitea.go @@ -21,7 +21,12 @@ type giteaClient struct { client *gitea.Client } -func getInstanceURL(apiURL string) (string, error) { +func getInstanceURL(ctx *context.Context) (string, error) { + apiURL, err := tmpl.New(ctx).Apply(ctx.Config.GiteaURLs.API) + if err != nil { + return "", fmt.Errorf("templating Gitea API URL: %w", err) + } + u, err := url.Parse(apiURL) if err != nil { return "", err @@ -36,7 +41,7 @@ func getInstanceURL(apiURL string) (string, error) { // NewGitea returns a gitea client implementation. func NewGitea(ctx *context.Context, token string) (Client, error) { - instanceURL, err := getInstanceURL(ctx.Config.GiteaURLs.API) + instanceURL, err := getInstanceURL(ctx) if err != nil { return nil, err } @@ -231,9 +236,14 @@ func (c *giteaClient) CreateRelease(ctx *context.Context, body string) (string, } func (c *giteaClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + downloadURL, err := tmpl.New(ctx).Apply(ctx.Config.GiteaURLs.Download) + if err != nil { + return "", fmt.Errorf("templating Gitea download URL: %w", err) + } + return fmt.Sprintf( "%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}", - ctx.Config.GiteaURLs.Download, + downloadURL, ctx.Config.Release.Gitea.Owner, ctx.Config.Release.Gitea.Name, ), nil diff --git a/internal/client/gitea_test.go b/internal/client/gitea_test.go index 05a47079b12..8a55e44671b 100644 --- a/internal/client/gitea_test.go +++ b/internal/client/gitea_test.go @@ -23,30 +23,82 @@ type GetInstanceURLSuite struct { func (s *GetInstanceURLSuite) TestWithScheme() { t := s.T() rootURL := "https://gitea.com" - result, err := getInstanceURL(rootURL + "/api/v1") + ctx := context.New(config.Project{ + GiteaURLs: config.GiteaURLs{ + API: rootURL + "/api/v1", + }, + }) + + result, err := getInstanceURL(ctx) require.NoError(t, err) require.Equal(t, rootURL, result) } func (s *GetInstanceURLSuite) TestParseError() { t := s.T() - host := "://wrong.gitea.com" - result, err := getInstanceURL(host) + ctx := context.New(config.Project{ + GiteaURLs: config.GiteaURLs{ + API: "://wrong.gitea.com", + }, + }) + + result, err := getInstanceURL(ctx) require.Error(t, err) require.Empty(t, result) } func (s *GetInstanceURLSuite) TestNoScheme() { t := s.T() - host := "gitea.com" - result, err := getInstanceURL(host) + ctx := context.New(config.Project{ + GiteaURLs: config.GiteaURLs{ + API: "gitea.com", + }, + }) + + result, err := getInstanceURL(ctx) require.Error(t, err) require.Empty(t, result) } func (s *GetInstanceURLSuite) TestEmpty() { t := s.T() - result, err := getInstanceURL("") + ctx := context.New(config.Project{ + GiteaURLs: config.GiteaURLs{ + API: "", + }, + }) + + result, err := getInstanceURL(ctx) + require.Error(t, err) + require.Empty(t, result) +} + +func (s *GetInstanceURLSuite) TestTemplate() { + t := s.T() + rootURL := "https://gitea.com" + ctx := context.New(config.Project{ + Env: []string{ + fmt.Sprintf("GORELEASER_TEST_GITAEA_URLS_API=%s", rootURL), + }, + GiteaURLs: config.GiteaURLs{ + API: "{{ .Env.GORELEASER_TEST_GITAEA_URLS_API }}", + }, + }) + + result, err := getInstanceURL(ctx) + require.NoError(t, err) + require.Equal(t, rootURL, result) +} + +func (s *GetInstanceURLSuite) TestTemplateMissingValue() { + t := s.T() + ctx := context.New(config.Project{ + GiteaURLs: config.GiteaURLs{ + API: "{{ .Env.GORELEASER_NOT_EXISTS }}", + }, + }) + + result, err := getInstanceURL(ctx) require.Error(t, err) require.Empty(t, result) } @@ -408,24 +460,57 @@ func TestGiteaUploadSuite(t *testing.T) { } func TestGiteaReleaseURLTemplate(t *testing.T) { - ctx := context.New(config.Project{ - GiteaURLs: config.GiteaURLs{ - API: "https://gitea.com/api/v1", - Download: "https://gitea.com", + tests := []struct { + name string + downloadURL string + wantURL string + wantErr bool + }{ + { + name: "string_url", + downloadURL: "https://gitea.com", + wantURL: "https://gitea.com/owner/name/releases/download/{{ .Tag }}/{{ .ArtifactName }}", }, - Release: config.Release{ - Gitea: config.Repo{ - Owner: "owner", - Name: "name", - }, + { + name: "download_url_template", + downloadURL: "{{ .Env.GORELEASER_TEST_GITEA_URLS_DOWNLOAD }}", + wantURL: "https://gitea.example.com/owner/name/releases/download/{{ .Tag }}/{{ .ArtifactName }}", }, - }) - client, err := NewGitea(ctx, ctx.Token) - require.NoError(t, err) - - urlTpl, err := client.ReleaseURLTemplate(ctx) - require.NoError(t, err) + { + name: "download_url_template_invalid_value", + downloadURL: "{{ .Env.GORELEASER_NOT_EXISTS }}", + wantErr: true, + }, + } - expectedURL := "https://gitea.com/owner/name/releases/download/{{ .Tag }}/{{ .ArtifactName }}" - require.Equal(t, expectedURL, urlTpl) + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ctx := context.New(config.Project{ + Env: []string{ + "GORELEASER_TEST_GITEA_URLS_DOWNLOAD=https://gitea.example.com", + }, + GiteaURLs: config.GiteaURLs{ + API: "https://gitea.com/api/v1", + Download: tt.downloadURL, + }, + Release: config.Release{ + Gitea: config.Repo{ + Owner: "owner", + Name: "name", + }, + }, + }) + client, err := NewGitea(ctx, ctx.Token) + require.NoError(t, err) + + urlTpl, err := client.ReleaseURLTemplate(ctx) + if tt.wantErr { + require.Error(t, err) + return + } + + require.NoError(t, err) + require.Equal(t, tt.wantURL, urlTpl) + }) + } } diff --git a/internal/client/github.go b/internal/client/github.go index 40dd864c49f..d6da97c29dc 100644 --- a/internal/client/github.go +++ b/internal/client/github.go @@ -40,18 +40,11 @@ func NewGitHub(ctx *context.Context, token string) (Client, error) { } base.(*http.Transport).Proxy = http.ProxyFromEnvironment httpClient.Transport.(*oauth2.Transport).Base = base + client := github.NewClient(httpClient) - if ctx.Config.GitHubURLs.API != "" { - api, err := url.Parse(ctx.Config.GitHubURLs.API) - if err != nil { - return &githubClient{}, err - } - upload, err := url.Parse(ctx.Config.GitHubURLs.Upload) - if err != nil { - return &githubClient{}, err - } - client.BaseURL = api - client.UploadURL = upload + err := overrideGitHubClientAPI(ctx, client) + if err != nil { + return &githubClient{}, err } return &githubClient{client: client}, nil @@ -181,9 +174,14 @@ func (c *githubClient) CreateRelease(ctx *context.Context, body string) (string, } func (c *githubClient) ReleaseURLTemplate(ctx *context.Context) (string, error) { + downloadURL, err := tmpl.New(ctx).Apply(ctx.Config.GitHubURLs.Download) + if err != nil { + return "", fmt.Errorf("templating GitHub download URL: %w", err) + } + return fmt.Sprintf( "%s/%s/%s/releases/download/{{ .Tag }}/{{ .ArtifactName }}", - ctx.Config.GitHubURLs.Download, + downloadURL, ctx.Config.Release.GitHub.Owner, ctx.Config.Release.GitHub.Name, ), nil @@ -251,3 +249,32 @@ func (c *githubClient) getMilestoneByTitle(ctx *context.Context, repo Repo, titl return nil, nil } + +func overrideGitHubClientAPI(ctx *context.Context, client *github.Client) error { + if ctx.Config.GitHubURLs.API == "" { + return nil + } + + apiURL, err := tmpl.New(ctx).Apply(ctx.Config.GitHubURLs.API) + if err != nil { + return fmt.Errorf("templating GitHub API URL: %w", err) + } + api, err := url.Parse(apiURL) + if err != nil { + return err + } + + uploadURL, err := tmpl.New(ctx).Apply(ctx.Config.GitHubURLs.Upload) + if err != nil { + return fmt.Errorf("templating GitHub upload URL: %w", err) + } + upload, err := url.Parse(uploadURL) + if err != nil { + return err + } + + client.BaseURL = api + client.UploadURL = upload + + return nil +} diff --git a/internal/client/github_test.go b/internal/client/github_test.go index 6069c8ca295..424d03e0f51 100644 --- a/internal/client/github_test.go +++ b/internal/client/github_test.go @@ -1,6 +1,7 @@ package client import ( + "fmt" "testing" "github.com/goreleaser/goreleaser/internal/artifact" @@ -45,6 +46,28 @@ func TestNewGitHubClient(t *testing.T) { require.EqualError(t, err, `parse "not a url:4994": first path segment in URL cannot contain colon`) }) + + t.Run("template", func(t *testing.T) { + githubURL := "https://github.mycompany.com" + ctx := context.New(config.Project{ + Env: []string{ + fmt.Sprintf("GORELEASER_TEST_GITHUB_URLS_API=%s/api", githubURL), + fmt.Sprintf("GORELEASER_TEST_GITHUB_URLS_UPLOAD=%s/upload", githubURL), + }, + GitHubURLs: config.GitHubURLs{ + API: "{{ .Env.GORELEASER_TEST_GITHUB_URLS_API }}", + Upload: "{{ .Env.GORELEASER_TEST_GITHUB_URLS_UPLOAD }}", + }, + }) + + client, err := NewGitHub(ctx, ctx.Token) + require.NoError(t, err) + + githubClient, ok := client.(*githubClient) + require.True(t, ok) + require.Equal(t, githubURL+"/api", githubClient.client.BaseURL.String()) + require.Equal(t, githubURL+"/upload", githubClient.client.UploadURL.String()) + }) } func TestGitHubUploadReleaseIDNotInt(t *testing.T) { diff --git a/internal/client/gitlab_test.go b/internal/client/gitlab_test.go index 98e628c8735..a235abfddd6 100644 --- a/internal/client/gitlab_test.go +++ b/internal/client/gitlab_test.go @@ -106,7 +106,7 @@ func TestGitLabURLsDownloadTemplate(t *testing.T) { }, { name: "download_url_template", - downloadURL: "{{ .Env.GORELEASER_TEST_GITLAB_URLS_DOWNLOADS }}", + downloadURL: "{{ .Env.GORELEASER_TEST_GITLAB_URLS_DOWNLOAD }}", wantURL: "https://gitlab.example.com/", }, { @@ -143,7 +143,7 @@ func TestGitLabURLsDownloadTemplate(t *testing.T) { ctx := context.New(config.Project{ Env: []string{ - fmt.Sprintf("GORELEASER_TEST_GITLAB_URLS_DOWNLOADS=%s", "https://gitlab.example.com"), + "GORELEASER_TEST_GITLAB_URLS_DOWNLOAD=https://gitlab.example.com", }, Release: config.Release{ GitLab: config.Repo{