Skip to content

Commit

Permalink
feat: support templates for gitlab_urls config
Browse files Browse the repository at this point in the history
Background
---
When a git repository is hosted in multiple GitLab instances the
`.goreleaser.yml` needs to take in consideration both APIs endpoints. At
the moment it defaults to GitLab.com and you can override it with
`gitlab_urls` however this forces you to only support 1 GitLab instance.

We need this for
https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/14122
where we have a tool that is developed on GitLab.com but then mirrored
to an internal GitLab instance since we need it to operate GitLab.com
even when it's down.

Solution
---
Support templates like `{{ .Env.CI_SERVER_URL }}` for the
`gitlab_urls.api` and `gitlab_urls.download` so it can use envirionment
variables.
  • Loading branch information
stevexuereb committed Sep 7, 2021
1 parent 7d22a32 commit e8d07a9
Show file tree
Hide file tree
Showing 2 changed files with 153 additions and 2 deletions.
13 changes: 11 additions & 2 deletions internal/client/gitlab.go
Expand Up @@ -35,7 +35,12 @@ func NewGitLab(ctx *context.Context, token string) (Client, error) {
}),
}
if ctx.Config.GitLabURLs.API != "" {
options = append(options, gitlab.WithBaseURL(ctx.Config.GitLabURLs.API))
apiURL, err := tmpl.New(ctx).Apply(ctx.Config.GitLabURLs.API)
if err != nil {
return nil, fmt.Errorf("templating GitLab API URL: %w", err)
}

options = append(options, gitlab.WithBaseURL(apiURL))
}
client, err := gitlab.NewClient(token, options...)
if err != nil {
Expand Down Expand Up @@ -326,7 +331,11 @@ func (c *gitlabClient) Upload(
return err
}

gitlabBaseURL := ctx.Config.GitLabURLs.Download
gitlabBaseURL, err := tmpl.New(ctx).Apply(ctx.Config.GitLabURLs.Download)
if err != nil {
return fmt.Errorf("templating GitLab Download URL: %w", err)
}

linkURL := gitlabBaseURL + "/" + projectDetails.PathWithNamespace + projectFile.URL
name := artifact.Name
filename := "/" + name
Expand Down
142 changes: 142 additions & 0 deletions internal/client/gitlab_test.go
@@ -1,8 +1,16 @@
package client

import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/http/httptest"
"os"
"strings"
"testing"

"github.com/goreleaser/goreleaser/internal/artifact"
"github.com/goreleaser/goreleaser/pkg/config"
"github.com/goreleaser/goreleaser/pkg/context"
"github.com/stretchr/testify/require"
Expand Down Expand Up @@ -30,3 +38,137 @@ func TestGitLabReleaseURLTemplate(t *testing.T) {
expectedURL := "https://gitlab.com/owner/name/-/releases/{{ .Tag }}/downloads/{{ .ArtifactName }}"
require.Equal(t, expectedURL, urlTpl)
}

func TestGitLabURLsAPITemplate(t *testing.T) {
tests := []struct {
name string
apiURL string
wantHost string
}{
{
name: "default_values",
wantHost: "gitlab.com",
},
{
name: "speicifed_api_env_key",
apiURL: "https://gitlab.example.com",
wantHost: "gitlab.example.com",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
envs := []string{}
gitlabURLs := config.GitLabURLs{}

if tt.apiURL != "" {
envs = append(envs, fmt.Sprintf("GORELEASER_TEST_GITLAB_URLS_API=%s", tt.apiURL))
gitlabURLs.API = "{{ .Env.GORELEASER_TEST_GITLAB_URLS_API }}"
}

ctx := context.New(config.Project{
Env: envs,
GitLabURLs: gitlabURLs,
})

client, err := NewGitLab(ctx, ctx.Token)
require.NoError(t, err)

gitlabClient, ok := client.(*gitlabClient)
require.True(t, ok)

require.Equal(t, tt.wantHost, gitlabClient.client.BaseURL().Host)
})
}

t.Run("no_env_specified", func(t *testing.T) {
ctx := context.New(config.Project{
GitLabURLs: config.GitLabURLs{
API: "{{ .Env.GORELEASER_NOT_EXISTS }}",
},
})

_, err := NewGitLab(ctx, ctx.Token)
require.Error(t, err)
})
}

func TestGitLabURLsDownloadTemplate(t *testing.T) {
tests := []struct {
name string
downloadURL string
wantURL string
wantErr bool
}{
{
name: "empty_download_url",
wantURL: "/",
},
{
name: "download_url_template",
downloadURL: "{{ .Env.GORELEASER_TEST_GITLAB_URLS_DOWNLOADS }}",
wantURL: "https://gitlab.example.com/",
},
{
name: "download_url_template_invalid_value",
downloadURL: "{{ .Eenv.GORELEASER_NOT_EXISTS }}",
wantErr: true,
},
{
name: "download_url_string",
downloadURL: "https://gitlab.acme.example.com",
wantURL: "https://gitlab.acme.example.com/",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
defer fmt.Fprint(w, "{}")
defer w.WriteHeader(http.StatusOK)
defer r.Body.Close()

if !strings.Contains(r.URL.Path, "assets/links") {
io.Copy(io.Discard, r.Body)
return
}

b, err := io.ReadAll(r.Body)
require.NoError(t, err)
reqBody := map[string]interface{}{}
json.Unmarshal(b, &reqBody)
require.Equal(t, tt.wantURL, reqBody["url"])
}))
defer srv.Close()

ctx := context.New(config.Project{
Env: []string{
fmt.Sprintf("GORELEASER_TEST_GITLAB_URLS_DOWNLOADS=%s", "https://gitlab.example.com"),
},
Release: config.Release{
GitLab: config.Repo{
Owner: "test",
Name: "test",
},
},
GitLabURLs: config.GitLabURLs{
API: srv.URL,
Download: tt.downloadURL,
},
})

tmpFile, err := os.CreateTemp(t.TempDir(), "")
require.NoError(t, err)

client, err := NewGitLab(ctx, ctx.Token)
require.NoError(t, err)

err = client.Upload(ctx, "1234", &artifact.Artifact{Name: "test", Path: "some-path"}, tmpFile)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
})
}
}

0 comments on commit e8d07a9

Please sign in to comment.