-
Notifications
You must be signed in to change notification settings - Fork 2
/
github.go
140 lines (118 loc) · 3.11 KB
/
github.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
package updater
import (
"context"
"errors"
"net/http"
"time"
"github.com/shurcooL/githubv4"
"golang.org/x/oauth2"
)
type (
// GithubLocator struct encapsulates information about github repo
GithubLocator struct {
client *githubv4.Client
owner string
repo string
acceptRelease ReleaseFilter
acceptAsset AssetFilter
}
ghReleaseAsset struct {
Name githubv4.String
URL githubv4.String
}
ghRelease struct {
Name githubv4.String
IsDraft githubv4.Boolean
IsPrerelease githubv4.Boolean
ReleaseAssets struct {
Nodes []ghReleaseAsset
} `graphql:"releaseAssets(first: 20)"`
}
queryRepoReleases struct {
Repository *struct {
Releases struct {
PageInfo struct {
EndCursor githubv4.String
HasNextPage githubv4.Boolean
}
Nodes []ghRelease
} `graphql:"releases(first: 50, after: $releaseCursor, orderBy: {field:CREATED_AT, direction: DESC})"`
} `graphql:"repository(owner: $repositoryOwner, name: $repositoryName)"`
}
)
var (
// ErrNoRepository error is returned is the repository is not found or user token has no access to it
ErrNoRepository = errors.New("no repository")
)
// NewGithubClient creates new github locator instance
func NewGithubClient(
owner string,
repository string,
token string,
releaseFilter ReleaseFilter,
assetFilter AssetFilter,
connectionTimeout time.Duration,
) *GithubLocator {
var httpClient *http.Client
if token != "" {
src := oauth2.StaticTokenSource(
&oauth2.Token{AccessToken: token},
)
httpClient = oauth2.NewClient(context.Background(), src)
httpClient.Timeout = connectionTimeout
}
if httpClient == nil {
httpClient = &http.Client{Timeout: connectionTimeout}
}
client := githubv4.NewClient(httpClient)
return &GithubLocator{
client: client,
owner: owner,
repo: repository,
acceptRelease: releaseFilter,
acceptAsset: assetFilter,
}
}
// ListReleases returns available GH releases list
func (g *GithubLocator) ListReleases(amount int) ([]Release, error) {
variables := map[string]interface{}{
"repositoryOwner": githubv4.String(g.owner),
"repositoryName": githubv4.String(g.repo),
"releaseCursor": (*githubv4.String)(nil), // Null after argument to get first page.
}
var query queryRepoReleases
var releases []Release
for {
if err := g.client.Query(context.TODO(), &query, variables); err != nil {
return nil, err
}
if query.Repository == nil {
return nil, ErrNoRepository
}
for _, release := range query.Repository.Releases.Nodes {
if !g.acceptRelease(string(release.Name), bool(release.IsDraft), bool(release.IsPrerelease)) {
continue
}
for _, asset := range release.ReleaseAssets.Nodes {
if !g.acceptAsset(string(asset.Name)) {
continue
}
releases = append(
releases,
Release{
Name: string(release.Name),
Asset: string(asset.Name),
URL: string(asset.URL),
},
)
break
}
}
if query.Repository.Releases.PageInfo.HasNextPage {
variables["releaseCursor"] = githubv4.NewString(query.Repository.Releases.PageInfo.EndCursor)
continue
}
break
}
return releases, nil
}