Skip to content

Commit 1dcdcc4

Browse files
authored
plugin: support GitHub Enterprise Server as plugin source (#1751)
1 parent 9b802b1 commit 1dcdcc4

File tree

4 files changed

+118
-24
lines changed

4 files changed

+118
-24
lines changed

plugin/install.go

Lines changed: 40 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
"golang.org/x/oauth2"
1717
)
1818

19+
const defaultSourceHost = "github.com"
20+
1921
// InstallConfig is a config for plugin installation.
2022
// This is a wrapper for PluginConfig and manages naming conventions
2123
// and directory names for installation.
@@ -149,9 +151,12 @@ func (c *InstallConfig) fetchReleaseAssets() (map[string]*github.ReleaseAsset, e
149151
assets := map[string]*github.ReleaseAsset{}
150152

151153
ctx := context.Background()
152-
client := newGitHubClient(ctx)
153154

154-
log.Printf("[DEBUG] Request to https://api.github.com/repos/%s/%s/releases/tags/%s", c.SourceOwner, c.SourceRepo, c.TagName())
155+
client, err := newGitHubClient(ctx, c)
156+
if err != nil {
157+
return assets, err
158+
}
159+
155160
release, _, err := client.Repositories.GetReleaseByTag(ctx, c.SourceOwner, c.SourceRepo, c.TagName())
156161
if err != nil {
157162
return assets, err
@@ -172,9 +177,12 @@ func (c *InstallConfig) downloadToTempFile(asset *github.ReleaseAsset) (*os.File
172177
}
173178

174179
ctx := context.Background()
175-
client := newGitHubClient(ctx)
176180

177-
log.Printf("[DEBUG] Request to https://api.github.com/repos/%s/%s/releases/assets/%d", c.SourceOwner, c.SourceRepo, asset.GetID())
181+
client, err := newGitHubClient(ctx, c)
182+
if err != nil {
183+
return nil, err
184+
}
185+
178186
downloader, _, err := client.Repositories.DownloadReleaseAsset(ctx, c.SourceOwner, c.SourceRepo, asset.GetID(), http.DefaultClient)
179187
if err != nil {
180188
return nil, err
@@ -237,18 +245,27 @@ func extractFileFromZipFile(zipFile *os.File, savePath string) error {
237245
return nil
238246
}
239247

240-
func newGitHubClient(ctx context.Context) *github.Client {
241-
token := os.Getenv("GITHUB_TOKEN")
242-
if token == "" {
243-
return github.NewClient(nil)
248+
func newGitHubClient(ctx context.Context, config *InstallConfig) (*github.Client, error) {
249+
hc := &http.Client{
250+
Transport: http.DefaultTransport,
244251
}
245252

246-
log.Printf("[DEBUG] GITHUB_TOKEN set, plugin requests to the GitHub API will be authenticated")
253+
if t := os.Getenv("GITHUB_TOKEN"); t != "" {
254+
log.Printf("[DEBUG] GITHUB_TOKEN set, plugin requests to the GitHub API will be authenticated")
247255

248-
ts := oauth2.StaticTokenSource(
249-
&oauth2.Token{AccessToken: token},
250-
)
251-
return github.NewClient(oauth2.NewClient(ctx, ts))
256+
hc = oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{
257+
AccessToken: t,
258+
}))
259+
}
260+
261+
hc.Transport = &requestLoggingTransport{hc.Transport}
262+
263+
if config.SourceHost == defaultSourceHost {
264+
return github.NewClient(hc), nil
265+
}
266+
267+
baseURL := fmt.Sprintf("https://%s/", config.SourceHost)
268+
return github.NewEnterpriseClient(baseURL, baseURL, hc)
252269
}
253270

254271
func fileExt() string {
@@ -257,3 +274,13 @@ func fileExt() string {
257274
}
258275
return ""
259276
}
277+
278+
// requestLoggingTransport wraps an existing RoundTripper and prints DEBUG logs before each request
279+
type requestLoggingTransport struct {
280+
http.RoundTripper
281+
}
282+
283+
func (s *requestLoggingTransport) RoundTrip(r *http.Request) (*http.Response, error) {
284+
log.Printf("[DEBUG] Request to %s", r.URL)
285+
return s.RoundTripper.RoundTrip(r)
286+
}

plugin/install_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package plugin
22

33
import (
4+
"context"
45
"os"
56
"testing"
67

@@ -17,6 +18,7 @@ func Test_Install(t *testing.T) {
1718
Enabled: true,
1819
Version: "0.4.0",
1920
Source: "github.com/terraform-linters/tflint-ruleset-aws",
21+
SourceHost: "github.com",
2022
SourceOwner: "terraform-linters",
2123
SourceRepo: "tflint-ruleset-aws",
2224
})
@@ -40,3 +42,45 @@ func Test_Install(t *testing.T) {
4042
t.Fatalf("Installed binary name is invalid: expected=%s, got=%s", expected, info.Name())
4143
}
4244
}
45+
46+
func TestNewGitHubClient(t *testing.T) {
47+
cases := []struct {
48+
name string
49+
config *InstallConfig
50+
expected string
51+
}{
52+
{
53+
name: "default",
54+
config: &InstallConfig{
55+
PluginConfig: &tflint.PluginConfig{
56+
SourceHost: "github.com",
57+
},
58+
},
59+
expected: "https://api.github.com/",
60+
},
61+
{
62+
name: "enterprise",
63+
config: &InstallConfig{
64+
PluginConfig: &tflint.PluginConfig{
65+
SourceHost: "github.example.com",
66+
},
67+
},
68+
expected: "https://github.example.com/api/v3/",
69+
},
70+
}
71+
72+
for _, tc := range cases {
73+
tc := tc
74+
75+
t.Run(tc.name, func(t *testing.T) {
76+
client, err := newGitHubClient(context.Background(), tc.config)
77+
if err != nil {
78+
t.Fatalf("Failed to create client: %s", err)
79+
}
80+
81+
if client.BaseURL.String() != tc.expected {
82+
t.Fatalf("Unexpected API URL: want %s, got %s", tc.expected, client.BaseURL.String())
83+
}
84+
})
85+
}
86+
}

tflint/config.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ type PluginConfig struct {
101101
Body hcl.Body `hcl:",remain"`
102102

103103
// Parsed source attributes
104+
SourceHost string
104105
SourceOwner string
105106
SourceRepo string
106107
}
@@ -477,11 +478,10 @@ func (c *PluginConfig) validate() error {
477478
parts := strings.Split(c.Source, "/")
478479
// Expected `github.com/owner/repo` format
479480
if len(parts) != 3 {
480-
return fmt.Errorf("plugin `%s`: `source` is invalid. Must be in the format `github.com/owner/repo`", c.Name)
481-
}
482-
if parts[0] != "github.com" {
483-
return fmt.Errorf("plugin `%s`: `source` is invalid. Hostname must be `github.com`", c.Name)
481+
return fmt.Errorf("plugin `%s`: `source` is invalid. Must be a GitHub reference in the format `${host}/${owner}/${repo}`", c.Name)
484482
}
483+
484+
c.SourceHost = parts[0]
485485
c.SourceOwner = parts[1]
486486
c.SourceRepo = parts[2]
487487
}

tflint/config_test.go

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ plugin "baz" {
107107
Version: "0.1.0",
108108
Source: "github.com/foo/bar",
109109
SigningKey: "SIGNING_KEY",
110+
SourceHost: "github.com",
110111
SourceOwner: "foo",
111112
SourceRepo: "bar",
112113
},
@@ -276,24 +277,46 @@ plugin "foo" {
276277
}`,
277278
},
278279
errCheck: func(err error) bool {
279-
return err == nil || err.Error() != "plugin `foo`: `source` is invalid. Must be in the format `github.com/owner/repo`"
280+
return err == nil || err.Error() != "plugin `foo`: `source` is invalid. Must be a GitHub reference in the format `${host}/${owner}/${repo}`"
280281
},
281282
},
282283
{
283-
name: "plugin with invalid source host",
284-
file: "plugin_with_invalid_source_host.hcl",
284+
name: "plugin with GHES source host",
285+
file: "plugin_with_ghes_source_host.hcl",
285286
files: map[string]string{
286-
"plugin_with_invalid_source_host.hcl": `
287+
"plugin_with_ghes_source_host.hcl": `
287288
plugin "foo" {
288289
enabled = true
289290
290291
version = "0.1.0"
291-
source = "gitlab.com/foo/bar"
292+
source = "github.example.com/foo/bar"
292293
}`,
293294
},
294-
errCheck: func(err error) bool {
295-
return err == nil || err.Error() != "plugin `foo`: `source` is invalid. Hostname must be `github.com`"
295+
want: &Config{
296+
Module: false,
297+
Force: false,
298+
IgnoreModules: map[string]bool{},
299+
Varfiles: []string{},
300+
Variables: []string{},
301+
DisabledByDefault: false,
302+
Rules: map[string]*RuleConfig{},
303+
Plugins: map[string]*PluginConfig{
304+
"foo": {
305+
Name: "foo",
306+
Enabled: true,
307+
Version: "0.1.0",
308+
Source: "github.example.com/foo/bar",
309+
SourceHost: "github.example.com",
310+
SourceOwner: "foo",
311+
SourceRepo: "bar",
312+
},
313+
"terraform": {
314+
Name: "terraform",
315+
Enabled: true,
316+
},
317+
},
296318
},
319+
errCheck: neverHappend,
297320
},
298321
}
299322

0 commit comments

Comments
 (0)