Skip to content

Commit 364a230

Browse files
authored
fix(gitlab): Actually support GITLAB_TOKEN (#613)
The GitLab forge was rejecting use of the GITLAB_TOKEN env var for authentication despite advertising support for it. The issue was that the client constructor was exploding when the auth type was `AuthTypeEnvironmentVariable` because it was not in the list of known auth types. Fix this by adding a case for it, and add tests to verify. Resolves #612
1 parent b7e4073 commit 364a230

File tree

4 files changed

+92
-10
lines changed

4 files changed

+92
-10
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
kind: Fixed
2+
body: 'gitlab: Fix rejection of `GITLAB_TOKEN` environment variable for authentication.'
3+
time: 2025-03-05T21:55:37.669148-08:00

internal/forge/gitlab/client.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,12 @@ type gitlabClient struct {
1717
}
1818

1919
func newGitLabClient(ctx context.Context, baseURL string, tok *AuthenticationToken) (*gitlabClient, error) {
20-
var newClient func(string, ...gitlab.ClientOptionFunc) (*gitlab.Client, error)
20+
newClient := gitlab.NewClient
2121
accessToken := tok.AccessToken
2222
switch tok.AuthType {
23-
case AuthTypePAT:
24-
newClient = gitlab.NewClient
23+
case AuthTypePAT, AuthTypeEnvironmentVariable:
24+
// no need to change anything
25+
2526
case AuthTypeGitLabCLI:
2627
// For GitLab CLI, AccessToken will be empty.
2728
token, err := newGitLabCLI("").Token(ctx, tok.Hostname)
@@ -30,11 +31,11 @@ func newGitLabClient(ctx context.Context, baseURL string, tok *AuthenticationTok
3031
}
3132

3233
accessToken = token
33-
fallthrough
34+
fallthrough // also needs a different client constructor
35+
3436
case AuthTypeOAuth2:
37+
// Needs a different client constructor.
3538
newClient = gitlab.NewOAuthClient
36-
default:
37-
return nil, fmt.Errorf("unknown auth type: %d", tok.AuthType)
3839
}
3940

4041
must.NotBeBlankf(accessToken,
Lines changed: 80 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,82 @@
11
package gitlab
22

3-
// GitlabClient is a GitLab client exported for testing.
4-
type GitlabClient = gitlabClient
3+
import (
4+
"encoding/json"
5+
"net/http"
6+
"net/http/httptest"
7+
"testing"
8+
9+
"github.com/stretchr/testify/assert"
10+
"github.com/stretchr/testify/require"
11+
gitlab "gitlab.com/gitlab-org/api/client-go"
12+
)
13+
14+
// Client is a GitLab client exported for testing.
15+
type Client = gitlabClient
16+
17+
func TestNewGitLabClient_authMethods(t *testing.T) {
18+
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
19+
enc := json.NewEncoder(w)
20+
enc.SetIndent("", " ")
21+
switch r.URL.Path {
22+
case "/api/v4/user":
23+
var u gitlab.User
24+
switch {
25+
case r.Header.Get("Private-Token") == "personal-access-token":
26+
u.Username = "pat-user"
27+
28+
case r.Header.Get("Private-Token") == "pat-from-env":
29+
u.Username = "pat-from-env-user"
30+
31+
case r.Header.Get("Authorization") == "Bearer oauth2-token":
32+
u.Username = "oauth2-user"
33+
34+
default:
35+
t.Errorf("unknown request: %v %v", r.Method, r.URL.Path)
36+
t.Errorf("headers: %v", r.Header)
37+
}
38+
39+
assert.NoError(t, enc.Encode(u))
40+
41+
default:
42+
t.Errorf("unknown request: %v %v", r.Method, r.URL.Path)
43+
}
44+
}))
45+
defer srv.Close()
46+
47+
t.Run("PAT", func(t *testing.T) {
48+
client, err := newGitLabClient(t.Context(), srv.URL, &AuthenticationToken{
49+
AuthType: AuthTypePAT,
50+
AccessToken: "personal-access-token",
51+
})
52+
require.NoError(t, err)
53+
54+
u, _, err := client.Users.CurrentUser(gitlab.WithContext(t.Context()))
55+
require.NoError(t, err)
56+
assert.Equal(t, "pat-user", u.Username)
57+
})
58+
59+
t.Run("OAuth2", func(t *testing.T) {
60+
client, err := newGitLabClient(t.Context(), srv.URL, &AuthenticationToken{
61+
AuthType: AuthTypeOAuth2,
62+
AccessToken: "oauth2-token",
63+
})
64+
require.NoError(t, err)
65+
66+
u, _, err := client.Users.CurrentUser(gitlab.WithContext(t.Context()))
67+
require.NoError(t, err)
68+
assert.Equal(t, "oauth2-user", u.Username)
69+
})
70+
71+
t.Run("EnvironmentVariable", func(t *testing.T) {
72+
client, err := newGitLabClient(t.Context(), srv.URL, &AuthenticationToken{
73+
AuthType: AuthTypeEnvironmentVariable,
74+
AccessToken: "pat-from-env",
75+
})
76+
require.NoError(t, err)
77+
78+
u, _, err := client.Users.CurrentUser(gitlab.WithContext(t.Context()))
79+
require.NoError(t, err)
80+
assert.Equal(t, "pat-from-env-user", u.Username)
81+
})
82+
}

internal/forge/gitlab/integration_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ func newRecorder(t *testing.T, name string) *recorder.Recorder {
7777

7878
func newGitLabClient(
7979
httpClient *http.Client,
80-
) *gitlab.GitlabClient {
80+
) *gitlab.Client {
8181
tok, exists := os.LookupEnv("GITLAB_TOKEN")
8282
var token string
8383
if !exists {
@@ -86,7 +86,7 @@ func newGitLabClient(
8686
token = tok
8787
}
8888
client, _ := gogitlab.NewClient(token, gogitlab.WithHTTPClient(httpClient))
89-
return &gitlab.GitlabClient{
89+
return &gitlab.Client{
9090
MergeRequests: client.MergeRequests,
9191
Notes: client.Notes,
9292
ProjectTemplates: client.ProjectTemplates,

0 commit comments

Comments
 (0)