Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add handling for github enterprise #114

Merged
merged 4 commits into from
Nov 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 15 additions & 7 deletions github.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@ type GitHub interface {
}

type GitHubClient struct {
client *github.Client
clientV4 *githubv4.Client
client *github.Client
clientV4 *githubv4.Client
isEnterprise bool

owner string
repository string
Expand Down Expand Up @@ -68,6 +69,7 @@ func NewGitHubClient(source Source) (*GitHubClient, error) {
client := github.NewClient(httpClient)

clientV4 := githubv4.NewClient(httpClient)
var isEnterprise bool

if source.GitHubAPIURL != "" {
var err error
Expand All @@ -91,10 +93,12 @@ func NewGitHubClient(source Source) (*GitHubClient, error) {
v4URL = source.GitHubAPIURL + "graphql"
}
clientV4 = githubv4.NewEnterpriseClient(v4URL, httpClient)
isEnterprise = true
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is basically saying once souce.GitHubAPIURL is provided then it is an enterprise github deployment. Is that true? Could a github deployment be public but not enterprise version?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in this one case I belive if you are providing something what is not default github api, we should consider this as github enterprise but I may be wrong there

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

at least isEnterprise = true should be set whenever NewEnterpriseClient is called

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is what is happening, when we have case with custom url, we are assuming that enterprise client will be used

}

if source.GitHubV4APIURL != "" {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should isEnterprise be set here as well? Since here you are also creating a v4 client

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

clientV4 = githubv4.NewEnterpriseClient(source.GitHubV4APIURL, httpClient)
isEnterprise = true
}

if source.GitHubUploadsURL != "" {
Expand All @@ -111,16 +115,20 @@ func NewGitHubClient(source Source) (*GitHubClient, error) {
}

return &GitHubClient{
client: client,
clientV4: clientV4,
owner: owner,
repository: source.Repository,
accessToken: source.AccessToken,
client: client,
clientV4: clientV4,
isEnterprise: isEnterprise,
owner: owner,
repository: source.Repository,
accessToken: source.AccessToken,
}, nil
}

func (g *GitHubClient) ListReleases() ([]*github.RepositoryRelease, error) {
if g.accessToken != "" {
if g.isEnterprise {
return g.listReleasesV4EnterPrice()
}
return g.listReleasesV4()
}
opt := &github.ListOptions{PerPage: 100}
Expand Down
76 changes: 73 additions & 3 deletions github_graphql.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,84 @@ import (
"context"
"encoding/base64"
"errors"
"github.com/google/go-github/v39/github"
"github.com/shurcooL/githubv4"
"regexp"
"strconv"
"time"

"github.com/google/go-github/v39/github"
"github.com/shurcooL/githubv4"
)

func (g *GitHubClient) listReleasesV4EnterPrice() ([]*github.RepositoryRelease, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you already have g.isEnterprise available in GitHubClient, so you could modify that existing list releases method instead of adding an almost identicle one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, but since it's a temporary solution, the logic of the method is almost the same, but for every reference I need to use another payload for making request, so I decided just to create new one, instead of huge if-else condition everywhere

if g.clientV4 == nil {
return nil, errors.New("github graphql is not been initialised")
}
var listReleasesEnterprise struct {
Repository struct {
Releases struct {
Edges []struct {
Node struct {
ReleaseObjectEnterprise
}
} `graphql:"edges"`
PageInfo struct {
EndCursor githubv4.String
HasNextPage bool
} `graphql:"pageInfo"`
} `graphql:"releases(first:$releasesCount, after: $releaseCursor, orderBy: {field: CREATED_AT, direction: DESC})"`
} `graphql:"repository(owner:$repositoryOwner,name:$repositoryName)"`
}

vars := map[string]interface{}{
"repositoryOwner": githubv4.String(g.owner),
"repositoryName": githubv4.String(g.repository),
"releaseCursor": (*githubv4.String)(nil),
"releasesCount": githubv4.Int(100),
}

var allReleases []*github.RepositoryRelease
for {
if err := g.clientV4.Query(context.TODO(), &listReleasesEnterprise, vars); err != nil {
return nil, err
}
for _, r := range listReleasesEnterprise.Repository.Releases.Edges {
r := r
publishedAt, _ := time.ParseInLocation(time.RFC3339, r.Node.PublishedAt.Time.Format(time.RFC3339), time.UTC)
createdAt, _ := time.ParseInLocation(time.RFC3339, r.Node.CreatedAt.Time.Format(time.RFC3339), time.UTC)
var releaseID int64
decodedID, err := base64.StdEncoding.DecodeString(r.Node.ID)
if err != nil {
return nil, err
}
re := regexp.MustCompile(`.*[^\d]`)
decodedID = re.ReplaceAll(decodedID, []byte(""))
if string(decodedID) == "" {
return nil, errors.New("bad release id from graph ql api")
}
releaseID, err = strconv.ParseInt(string(decodedID), 10, 64)
if err != nil {
return nil, err
}

allReleases = append(allReleases, &github.RepositoryRelease{
ID: &releaseID,
TagName: &r.Node.TagName,
Name: &r.Node.Name,
Prerelease: &r.Node.IsPrerelease,
Draft: &r.Node.IsDraft,
URL: &r.Node.URL,
PublishedAt: &github.Timestamp{Time: publishedAt},
CreatedAt: &github.Timestamp{Time: createdAt},
})
}
if !listReleasesEnterprise.Repository.Releases.PageInfo.HasNextPage {
break
}
vars["releaseCursor"] = listReleasesEnterprise.Repository.Releases.PageInfo.EndCursor

}
return allReleases, nil
}

func (g *GitHubClient) listReleasesV4() ([]*github.RepositoryRelease, error) {
if g.clientV4 == nil {
return nil, errors.New("github graphql is not been initialised")
Expand Down
17 changes: 7 additions & 10 deletions github_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import (
)

const (
multiPageResp = `{
multiPageRespEnterprise = `{
"data": {
"repository": {
"releases": {
Expand All @@ -25,7 +25,6 @@ const (
"node": {
"createdAt": "2010-10-01T00:58:07Z",
"id": "MDc6UmVsZWFzZTMyMDk1MTAz",
"databaseId": 32095103,
"name": "xyz",
"publishedAt": "2010-10-02T15:39:53Z",
"tagName": "xyz",
Expand All @@ -38,7 +37,6 @@ const (
"node": {
"createdAt": "2010-08-27T13:55:36Z",
"id": "MDc6UmVsZWFzZTMwMjMwNjU5",
"databaseId": 30230659,
"name": "xyz",
"publishedAt": "2010-08-27T17:18:06Z",
"tagName": "xyz",
Expand All @@ -57,7 +55,7 @@ const (
}
}`

singlePageResp = `{
singlePageRespEnterprise = `{
"data": {
"repository": {
"releases": {
Expand All @@ -66,7 +64,6 @@ const (
"node": {
"createdAt": "2010-10-10T01:01:07Z",
"id": "MDc6UmVsZWFzZTMzMjIyMjQz",
"databaseId": 33222243,
"name": "xyq",
"publishedAt": "2010-10-10T15:39:53Z",
"tagName": "xyq",
Expand Down Expand Up @@ -171,7 +168,7 @@ var _ = Describe("GitHub Client", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/graphql"),
ghttp.RespondWith(200, singlePageResp),
ghttp.RespondWith(200, singlePageRespEnterprise),
),
)

Expand All @@ -188,7 +185,7 @@ var _ = Describe("GitHub Client", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/api/graphql"),
ghttp.RespondWith(200, singlePageResp),
ghttp.RespondWith(200, singlePageRespEnterprise),
),
)

Expand Down Expand Up @@ -216,7 +213,7 @@ var _ = Describe("GitHub Client", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/graphql"),
ghttp.RespondWith(200, singlePageResp),
ghttp.RespondWith(200, singlePageRespEnterprise),
ghttp.VerifyHeaderKV("Authorization", "Bearer abc123"),
),
)
Expand Down Expand Up @@ -263,11 +260,11 @@ var _ = Describe("GitHub Client", func() {
server.AppendHandlers(
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/graphql"),
ghttp.RespondWith(200, multiPageResp),
ghttp.RespondWith(200, multiPageRespEnterprise),
),
ghttp.CombineHandlers(
ghttp.VerifyRequest("POST", "/graphql"),
ghttp.RespondWith(200, singlePageResp),
ghttp.RespondWith(200, singlePageRespEnterprise),
),
)
})
Expand Down
13 changes: 13 additions & 0 deletions model.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,16 @@ type ReleaseObject struct {
TagName string `graphql:"tagName"`
URL string `graphql:"url"`
}

// ReleaseObjectEnterprise Workaround until DatabaseId will appear in enterprise installation
kirillbilchenko marked this conversation as resolved.
Show resolved Hide resolved
// https://github.com/concourse/github-release-resource/issues/109
type ReleaseObjectEnterprise struct {
CreatedAt githubv4.DateTime `graphql:"createdAt"`
PublishedAt githubv4.DateTime `graphql:"publishedAt"`
ID string `graphql:"id"`
IsDraft bool `graphql:"isDraft"`
IsPrerelease bool `graphql:"isPrerelease"`
Name string `graphql:"name"`
TagName string `graphql:"tagName"`
URL string `graphql:"url"`
}