Skip to content

Commit 32a5ed4

Browse files
patelniketmnaveensrinivasanraghavkaul
authored andcommitted
✨ Add support for github GHES (ossf#2999)
* ✨ adding support for github GHES Signed-off-by: Niket Patel <[email protected]> * fix: lint and cleanup Signed-off-by: Niket Patel <[email protected]> * fix: flaky test Signed-off-by: Niket Patel <[email protected]> * fix: address missing host Signed-off-by: Niket Patel <[email protected]> * fix: lint error Signed-off-by: Niket Patel <[email protected]> * 🌱 Additional e2e clients/githubrepo/checkruns.go (ossf#2934) * 🌱 Additional e2e clients/githubrepo/checkruns.go - Add `net/http` and `github.com/google/go-github/v38/github` imports - Add a test for `listCheckRunsForRef` with valid ref - Add a test for `listCheckRunsForRef` with invalid ref Signed-off-by: naveensrinivasan <[email protected]> * Based on code review comments Signed-off-by: naveensrinivasan <[email protected]> * Some tweaks Signed-off-by: naveensrinivasan <[email protected]> --------- Signed-off-by: naveensrinivasan <[email protected]> Signed-off-by: Niket Patel <[email protected]> * 🌱 E2E for clients/githubrepo/contributors.go (ossf#2939) * 🌱 E2E for clients/githubrepo/contributors.go - Add an end-to-end test for `contributorsHandler` Signed-off-by: naveensrinivasan <[email protected]> * Fixed based on code review comments. Signed-off-by: naveensrinivasan <[email protected]> * Fixed codereview comment. Signed-off-by: naveensrinivasan <[email protected]> --------- Signed-off-by: naveensrinivasan <[email protected]> Signed-off-by: Niket Patel <[email protected]> * chore: add GHES instructions Signed-off-by: Niket Patel <[email protected]> * refact: use test setenv Signed-off-by: Niket Patel <[email protected]> * fix: corp unit test Signed-off-by: Niket Patel <[email protected]> --------- Signed-off-by: Niket Patel <[email protected]> Signed-off-by: naveensrinivasan <[email protected]> Signed-off-by: Niket Patel <[email protected]> Co-authored-by: Naveen <[email protected]> Co-authored-by: raghavkaul <[email protected]> Signed-off-by: Avishay <[email protected]>
1 parent fe8e735 commit 32a5ed4

File tree

5 files changed

+102
-9
lines changed

5 files changed

+102
-9
lines changed

README.md

+14
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,20 @@ RESULTS
404404
|---------|------------------------|--------------------------------|--------------------------------|---------------------------------------------------------------------------|
405405
```
406406

407+
##### Using GitHub Enterprise Server (GHES) based Repository
408+
409+
To use a GitHub Enterprise host `github.corp.com`, use the `GH_HOST` environment variable.
410+
411+
```shell
412+
# Set the GitHub Enterprise host without https prefix or slash with relevant authentication token
413+
export GH_HOST=github.corp.com
414+
export GITHUB_AUTH_TOKEN=token
415+
416+
scorecard --repo=github.corp.com/org/repo
417+
# OR without github host url
418+
scorecard --repo=org/repo
419+
```
420+
407421
##### Using a Package manager
408422

409423
For projects in the `--npm`, `--pypi`, `--rubygems`, or `--nuget` ecosystems, you have the

checker/client_test.go

+20
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ func TestGetClients(t *testing.T) { //nolint:gocognit
3939
shouldCIIBeNil bool
4040
wantErr bool
4141
experimental bool
42+
isGhHost bool
4243
}{
4344
{
4445
name: "localURI is not empty",
@@ -94,6 +95,21 @@ func TestGetClients(t *testing.T) { //nolint:gocognit
9495
wantErr: false,
9596
experimental: true,
9697
},
98+
{
99+
name: "repoURI is corp github host",
100+
args: args{
101+
ctx: context.Background(),
102+
repoURI: "https://github.corp.com/ossf/scorecard",
103+
localURI: "",
104+
},
105+
shouldOSSFuzzBeNil: false,
106+
shouldRepoClientBeNil: false,
107+
shouldVulnClientBeNil: false,
108+
shouldRepoBeNil: false,
109+
shouldCIIBeNil: false,
110+
wantErr: false,
111+
isGhHost: true,
112+
},
97113
}
98114

99115
for _, tt := range tests {
@@ -102,6 +118,10 @@ func TestGetClients(t *testing.T) { //nolint:gocognit
102118
if tt.experimental {
103119
t.Setenv("SCORECARD_EXPERIMENTAL", "true")
104120
}
121+
if tt.isGhHost {
122+
t.Setenv("GH_HOST", "github.corp.com")
123+
t.Setenv("GH_TOKEN", "PAT")
124+
}
105125
got, repoClient, ossFuzzClient, ciiClient, vulnsClient, err := GetClients(tt.args.ctx, tt.args.repoURI, tt.args.localURI, tt.args.logger) //nolint:lll
106126
if (err != nil) != tt.wantErr {
107127
t.Fatalf("GetClients() error = %v, wantErr %v", err, tt.wantErr)

clients/githubrepo/client.go

+29-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"errors"
2121
"fmt"
2222
"net/http"
23+
"os"
24+
"strings"
2325
"time"
2426

2527
"github.com/google/go-github/v38/github"
@@ -59,6 +61,8 @@ type Client struct {
5961
commitDepth int
6062
}
6163

64+
const defaultGhHost = "github.com"
65+
6266
// InitRepo sets up the GitHub repo in local storage for improving performance and GitHub token usage efficiency.
6367
func (client *Client) InitRepo(inputRepo clients.Repo, commitSHA string, commitDepth int) error {
6468
ghRepo, ok := inputRepo.(*repoURL)
@@ -126,7 +130,11 @@ func (client *Client) InitRepo(inputRepo clients.Repo, commitSHA string, commitD
126130

127131
// URI implements RepoClient.URI.
128132
func (client *Client) URI() string {
129-
return fmt.Sprintf("github.com/%s/%s", client.repourl.owner, client.repourl.repo)
133+
host, isHost := os.LookupEnv("GH_HOST")
134+
if !isHost {
135+
host = defaultGhHost
136+
}
137+
return fmt.Sprintf("%s/%s/%s", host, client.repourl.owner, client.repourl.repo)
130138
}
131139

132140
// LocalPath implements RepoClient.LocalPath.
@@ -259,8 +267,26 @@ func CreateGithubRepoClientWithTransport(ctx context.Context, rt http.RoundTripp
259267
httpClient := &http.Client{
260268
Transport: rt,
261269
}
262-
client := github.NewClient(httpClient)
263-
graphClient := githubv4.NewClient(httpClient)
270+
271+
var client *github.Client
272+
var graphClient *githubv4.Client
273+
githubHost, isGhHost := os.LookupEnv("GH_HOST")
274+
275+
if isGhHost && githubHost != defaultGhHost {
276+
githubRestURL := fmt.Sprintf("https://%s/api/v3", strings.TrimSpace(githubHost))
277+
githubGraphqlURL := fmt.Sprintf("https://%s/api/graphql", strings.TrimSpace(githubHost))
278+
279+
var err error
280+
client, err = github.NewEnterpriseClient(githubRestURL, githubRestURL, httpClient)
281+
if err != nil {
282+
panic(fmt.Errorf("error during CreateGithubRepoClientWithTransport:EnterpriseClient: %w", err))
283+
}
284+
285+
graphClient = githubv4.NewEnterpriseClient(githubGraphqlURL, httpClient)
286+
} else {
287+
client = github.NewClient(httpClient)
288+
graphClient = githubv4.NewClient(httpClient)
289+
}
264290

265291
return &Client{
266292
ctx: ctx,

clients/githubrepo/repo.go

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ package githubrepo
1717
import (
1818
"fmt"
1919
"net/url"
20+
"os"
2021
"strings"
2122

2223
"github.com/ossf/scorecard/v4/clients"
@@ -42,7 +43,11 @@ func (r *repoURL) parse(input string) error {
4243
// This will takes care for repo/owner format.
4344
// By default it will use github.com
4445
case l == two:
45-
t = "github.com/" + c[0] + "/" + c[1]
46+
githubHost, isGhHost := os.LookupEnv("GH_HOST")
47+
if !isGhHost {
48+
githubHost = "github.com"
49+
}
50+
t = githubHost + "/" + c[0] + "/" + c[1]
4651
case l >= three:
4752
t = input
4853
}
@@ -83,8 +88,10 @@ func (r *repoURL) String() string {
8388

8489
// IsValid implements Repo.IsValid.
8590
func (r *repoURL) IsValid() error {
91+
githubHost := os.Getenv("GH_HOST")
8692
switch r.host {
8793
case "github.com":
94+
case githubHost:
8895
default:
8996
return sce.WithMessage(sce.ErrorUnsupportedHost, r.host)
9097
}

clients/githubrepo/repo_test.go

+31-5
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@ import (
2020
"github.com/google/go-cmp/cmp"
2121
)
2222

23+
// nolint:paralleltest
24+
// because we are using t.Setenv.
2325
func TestRepoURL_IsValid(t *testing.T) {
24-
t.Parallel()
2526
tests := []struct {
2627
name string
2728
inputURL string
2829
expected repoURL
2930
wantErr bool
31+
ghHost bool
3032
}{
3133
{
3234
name: "Valid http address",
@@ -59,7 +61,7 @@ func TestRepoURL_IsValid(t *testing.T) {
5961
wantErr: true,
6062
},
6163
{
62-
name: "github repository",
64+
name: "Github repository",
6365
expected: repoURL{
6466
host: "github.com",
6567
owner: "foo",
@@ -69,7 +71,7 @@ func TestRepoURL_IsValid(t *testing.T) {
6971
wantErr: false,
7072
},
7173
{
72-
name: "github repository",
74+
name: "Github repository with host",
7375
expected: repoURL{
7476
host: "github.com",
7577
owner: "foo",
@@ -78,11 +80,36 @@ func TestRepoURL_IsValid(t *testing.T) {
7880
inputURL: "https://github.com/foo/kubeflow",
7981
wantErr: false,
8082
},
83+
{
84+
name: "Enterprise github repository with host",
85+
expected: repoURL{
86+
host: "github.corp.com",
87+
owner: "corpfoo",
88+
repo: "kubeflow",
89+
},
90+
inputURL: "https://github.corp.com/corpfoo/kubeflow",
91+
wantErr: false,
92+
ghHost: true,
93+
},
94+
{
95+
name: "Enterprise github repository",
96+
expected: repoURL{
97+
host: "github.corp.com",
98+
owner: "corpfoo",
99+
repo: "kubeflow",
100+
},
101+
inputURL: "corpfoo/kubeflow",
102+
wantErr: false,
103+
ghHost: true,
104+
},
81105
}
82106
for _, tt := range tests {
83107
tt := tt // Re-initializing variable so it is not changed while executing the closure below
84108
t.Run(tt.name, func(t *testing.T) {
85-
t.Parallel()
109+
if tt.ghHost {
110+
t.Setenv("GH_HOST", "github.corp.com")
111+
}
112+
86113
r := repoURL{
87114
host: tt.expected.host,
88115
owner: tt.expected.owner,
@@ -97,7 +124,6 @@ func TestRepoURL_IsValid(t *testing.T) {
97124
if !tt.wantErr && !cmp.Equal(tt.expected, r, cmp.AllowUnexported(repoURL{})) {
98125
t.Errorf("Got diff: %s", cmp.Diff(tt.expected, r))
99126
}
100-
101127
if !cmp.Equal(r.Host(), tt.expected.host) {
102128
t.Errorf("%s expected host: %s got host %s", tt.inputURL, tt.expected.host, r.Host())
103129
}

0 commit comments

Comments
 (0)