github.go (3128B)
1 package releaser
2
3 import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 "net/http"
8 "os"
9 "strings"
10 )
11
12 var (
13 gitHubCommitsAPI = "https://api.github.com/repos/gohugoio/REPO/commits/%s"
14 gitHubRepoAPI = "https://api.github.com/repos/gohugoio/REPO"
15 gitHubContributorsAPI = "https://api.github.com/repos/gohugoio/REPO/contributors"
16 )
17
18 type gitHubAPI struct {
19 commitsAPITemplate string
20 repoAPI string
21 contributorsAPITemplate string
22 }
23
24 func newGitHubAPI(repo string) *gitHubAPI {
25 return &gitHubAPI{
26 commitsAPITemplate: strings.Replace(gitHubCommitsAPI, "REPO", repo, -1),
27 repoAPI: strings.Replace(gitHubRepoAPI, "REPO", repo, -1),
28 contributorsAPITemplate: strings.Replace(gitHubContributorsAPI, "REPO", repo, -1),
29 }
30 }
31
32 type gitHubCommit struct {
33 Author gitHubAuthor `json:"author"`
34 HTMLURL string `json:"html_url"`
35 }
36
37 type gitHubAuthor struct {
38 ID int `json:"id"`
39 Login string `json:"login"`
40 HTMLURL string `json:"html_url"`
41 AvatarURL string `json:"avatar_url"`
42 }
43
44 type gitHubRepo struct {
45 ID int `json:"id"`
46 Name string `json:"name"`
47 Description string `json:"description"`
48 HTMLURL string `json:"html_url"`
49 Stars int `json:"stargazers_count"`
50 Contributors []gitHubContributor
51 }
52
53 type gitHubContributor struct {
54 ID int `json:"id"`
55 Login string `json:"login"`
56 HTMLURL string `json:"html_url"`
57 Contributions int `json:"contributions"`
58 }
59
60 func (g *gitHubAPI) fetchCommit(ref string) (gitHubCommit, error) {
61 var commit gitHubCommit
62
63 u := fmt.Sprintf(g.commitsAPITemplate, ref)
64
65 req, err := http.NewRequest("GET", u, nil)
66 if err != nil {
67 return commit, err
68 }
69
70 err = doGitHubRequest(req, &commit)
71
72 return commit, err
73 }
74
75 func (g *gitHubAPI) fetchRepo() (gitHubRepo, error) {
76 var repo gitHubRepo
77
78 req, err := http.NewRequest("GET", g.repoAPI, nil)
79 if err != nil {
80 return repo, err
81 }
82
83 err = doGitHubRequest(req, &repo)
84 if err != nil {
85 return repo, err
86 }
87
88 var contributors []gitHubContributor
89 page := 0
90 for {
91 page++
92 var currPage []gitHubContributor
93 url := fmt.Sprintf(g.contributorsAPITemplate+"?page=%d", page)
94
95 req, err = http.NewRequest("GET", url, nil)
96 if err != nil {
97 return repo, err
98 }
99
100 err = doGitHubRequest(req, &currPage)
101 if err != nil {
102 return repo, err
103 }
104 if len(currPage) == 0 {
105 break
106 }
107
108 contributors = append(contributors, currPage...)
109
110 }
111
112 repo.Contributors = contributors
113
114 return repo, err
115 }
116
117 func doGitHubRequest(req *http.Request, v any) error {
118 addGitHubToken(req)
119
120 resp, err := http.DefaultClient.Do(req)
121 if err != nil {
122 return err
123 }
124 defer resp.Body.Close()
125
126 if isError(resp) {
127 b, _ := ioutil.ReadAll(resp.Body)
128 return fmt.Errorf("GitHub lookup failed: %s", string(b))
129 }
130
131 return json.NewDecoder(resp.Body).Decode(v)
132 }
133
134 func isError(resp *http.Response) bool {
135 return resp.StatusCode < 200 || resp.StatusCode > 299
136 }
137
138 func addGitHubToken(req *http.Request) {
139 gitHubToken := os.Getenv("GITHUB_TOKEN")
140 if gitHubToken != "" {
141 req.Header.Add("Authorization", "token "+gitHubToken)
142 }
143 }