GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — master ( bc55d4...3811bc )
by Fedir
02:55
created
Severity
1
// Copyright 2018 Fedir RYKHTIK. All rights reserved.
2
// Use of this source code is governed by the GNU GPL 3.0
3
// license that can be found in the LICENSE file.
4
5
// ghstat - statistical multi-criteria decision-making comparator for Github's projects.
6
package main
7
8
import (
9
	"encoding/csv"
10
	"encoding/json"
11
	"flag"
12
	"fmt"
13
	"log"
14
	"os"
15
	"path/filepath"
16
	"strings"
17
	"time"
18
19
	"github.com/fedir/ghstat/github"
20
	"github.com/fedir/ghstat/httpcache"
21
	"github.com/fedir/ghstat/timing"
22
)
23
24
func main() {
25 1
	var (
26
		clearHTTPCache         = flag.Bool("cc", false, "Clear HTTP cache")
27
		clearHTTPCacheDryRun   = flag.Bool("ccdr", false, "Clear HTTP cache (dry run)")
28
		debug                  = flag.Bool("d", false, "Debug mode")
29
		resultFileSavePath     = flag.String("f", "", "File path where result CSV file will be saved")
30
		rateLimitCheck         = flag.Bool("l", false, "Rate limit check")
31
		repositoriesKeysManual = flag.String("r", "", "Repositories keys")
32
		tmpFolder              = flag.String("t", "test_data", "Clear HTTP cache (dry run)")
33
		repositoriesKeys       = []string{}
34
	)
35 1
	flag.Parse()
36 1
	if *clearHTTPCache || *clearHTTPCacheDryRun {
37
		clearHTTPCacheFolder(*tmpFolder, *clearHTTPCacheDryRun)
38
		os.Exit(0)
39
	}
40 1
	if *rateLimitCheck {
41
		checkAndPrintRateLimit()
42
		os.Exit(0)
43
	}
44 1
	if *rateLimitCheck {
45
		checkAndPrintRateLimit()
46
		os.Exit(0)
47
	}
48 1
	if *repositoriesKeysManual != "" {
49
		repositoriesKeys = strings.Split(*repositoriesKeysManual, ",")
50
	} else {
51 1
		repositoriesKeys = []string{
52
			"astaxie/beego",
53
			"gohugoio/hugo",
54
			"gin-gonic/gin",
55
			"labstack/echo",
56
			"revel/revel",
57
			"gobuffalo/buffalo",
58
			"go-chi/chi",
59
			"kataras/iris",
60
			"zenazn/goji",
61
		}
62
	}
63 1
	csvFilePath := ""
64 1
	if *resultFileSavePath != "" {
65
		csvFilePath = *resultFileSavePath
66
	} else {
67 1
		csvFilePath = "result.csv"
68
	}
69 1
	var ghData = [][]string{}
70 1
	headers := []string{
71
		"Name",
72
		"URL",
73
		"Author",
74
		"License",
75
		"Author's followers",
76
		"Top 10 contributors followers",
77
		"Created at",
78
		"Age in days",
79
		"Total commits",
80
		"Total additions",
81
		"Total deletions",
82
		"Total code changes",
83
		"Last commit date",
84
		"Commits/day",
85
		"Medium commit size",
86
		"Stargazers",
87
		"Forks",
88
		"Contributors",
89
		"Active forkers, %",
90
		"Open issues",
91
		"Total issues",
92
		"Issue/day",
93
		"Closed issues, %",
94
		"Place",
95
	}
96 1
	ghDataColumnIndexes := map[string]int{
97
		"nameColumn":                       0,
98
		"urlColumn":                        1,
99
		"authorColumn":                     2,
100
		"licenseColumn":                    3,
101
		"authorsFollowersColumn":           4,
102
		"top10ContributorsFollowersColumn": 5,
103
		"totalAdditionsColumn":             9,
104
		"ageColumn":                        7,
105
		"totalCommitsColumn":               8,
106
		"totalDeletionsColumn":             10,
107
		"totalCodeChangesColumn":           11,
108
		"lastCommitDateColumn":             12,
109
		"commitsByDayColumn":               13,
110
		"mediCommitSizeColumn":             14,
111
		"stargazersColumn":                 15,
112
		"activeForkersColumn":              18,
113
		"issuesByDayColumn":                21,
114
		"closedIssuesPercentageColumn":     22,
115
		"totalPointsColumnIndex":           23,
116
	}
117 1
	dataChan := make(chan []string, len(repositoriesKeys))
118 1
	for _, rKey := range repositoriesKeys {
119 1
		go fillRepositoryStatistics(rKey, *tmpFolder, *debug, dataChan)
120
	}
121 1
	for range repositoriesKeys {
122 1
		ghData = append(ghData, <-dataChan)
123
	}
124 1
	greetings := rateGhData(ghData, ghDataColumnIndexes)
125 1
	fmt.Println(greetings)
126 1
	writeCsv(csvFilePath, headers, ghData)
127
}
128
129
func fillRepositoryStatistics(rKey string, tmpFolder string, debug bool, dataChan chan []string) {
130 1
	repositoryData := github.GetRepositoryStatistics(rKey, tmpFolder, debug)
131 1
	repositoryAge := int(time.Since(repositoryData.CreatedAt).Seconds() / 86400)
132 1
	authorLogin, lastCommitDate := github.GetRepositoryCommitsData(rKey, tmpFolder, debug)
133 1
	authorFollowers := 0
134 1
	if authorLogin != "" {
135 1
		authorFollowers = github.GetUserFollowers(authorLogin, tmpFolder, debug)
136
	}
137 1
	closedIssues := github.GetRepositoryClosedIssues(rKey, tmpFolder, debug)
138 1
	topContributorsFollowers, totalContributors := github.GetRepositoryContributors(rKey, tmpFolder, debug)
139 1
	activeForkersPercentage := github.GetActiveForkersPercentage(totalContributors, repositoryData.Forks)
140 1
	issueByDay := github.GetIssueByDay(closedIssues+repositoryData.OpenIssues, repositoryAge)
141 1
	closedIssuesPercentage := github.GetClosedIssuesPercentage(repositoryData.OpenIssues, int(closedIssues))
142 1
	contributionStatistics := github.GetContributionStatistics(rKey, tmpFolder, debug)
143 1
	commitsByDay := github.GetCommitsByDay(contributionStatistics.TotalCommits, repositoryAge)
144 1
	ghProjectData := []string{
145
		repositoryData.FullName,
146
		fmt.Sprintf("https://github.com/%s", repositoryData.FullName),
147
		fmt.Sprintf("%s", func(a string) string {
148 1
			if a == "" {
149 1
				a = "[Account removed]"
150
			}
151 1
			return a
152
		}(authorLogin)),
153
		fmt.Sprintf("%s", func(l string) string {
154 1
			if l == "" {
155 1
				l = "[Unknown]"
156
			}
157 1
			return l
158
		}(repositoryData.License.SPDXID)),
159
		fmt.Sprintf("%d", authorFollowers),
160
		fmt.Sprintf("%d", topContributorsFollowers),
161
		fmt.Sprintf("%d/%02d", repositoryData.CreatedAt.Year(), repositoryData.CreatedAt.Month()),
162
		fmt.Sprintf("%d", repositoryAge),
163
		fmt.Sprintf("%d", contributionStatistics.TotalCommits),
164
		fmt.Sprintf("%d", contributionStatistics.TotalAdditions),
165
		fmt.Sprintf("%d", contributionStatistics.TotalDeletions),
166
		fmt.Sprintf("%d", contributionStatistics.TotalCodeChanges),
167
		fmt.Sprintf(lastCommitDate.Format("2006-01-02 15:04:05")),
0 ignored issues
show
can't check non-constant format in call to Sprintf
Loading history...
168
		fmt.Sprintf("%.4f", commitsByDay),
169
		fmt.Sprintf("%d", contributionStatistics.MediumCommitSize),
170
		fmt.Sprintf("%d", repositoryData.Watchers),
171
		fmt.Sprintf("%d", repositoryData.Forks),
172
		fmt.Sprintf("%d", totalContributors),
173
		fmt.Sprintf("%.2f", activeForkersPercentage),
174
		fmt.Sprintf("%d", repositoryData.OpenIssues),
175
		fmt.Sprintf("%d", closedIssues+repositoryData.OpenIssues),
176
		fmt.Sprintf("%.4f", issueByDay),
177
		fmt.Sprintf("%.2f", closedIssuesPercentage),
178
		"0",
179
	}
180 1
	dataChan <- ghProjectData
181
}
182
183
func clearHTTPCacheFolder(tmpFolderPath string, dryRun bool) error {
184
	d, err := os.Open(tmpFolderPath)
185
	if err != nil {
186
		log.Fatalf("Could not open %s", tmpFolderPath)
187
	}
188
	defer d.Close()
189
	names, err := d.Readdirnames(-1)
190
	if err != nil {
191
		log.Fatalf("Could not read from %s", tmpFolderPath)
192
	}
193
	for _, name := range names {
194
		fp := filepath.Join(tmpFolderPath, name)
195
		if dryRun {
196
			fmt.Printf("Deleted %s\n", fp)
197
		} else {
198
			err = os.RemoveAll(fp)
199
			if err != nil {
200
				log.Fatalf("Could not remove %s", fp)
201
			}
202
			fmt.Printf("Deleted %s\n", fp)
203
		}
204
	}
205
	return nil
206
}
207
208
func checkAndPrintRateLimit() {
209
	type RateLimits struct {
210
		Resources struct {
211
			Core struct {
212
				Limit     int `json:"limit"`
213
				Remaining int `json:"remaining"`
214
				Reset     int `json:"reset"`
215
			} `json:"core"`
216
			Search struct {
217
				Limit     int `json:"limit"`
218
				Remaining int `json:"remaining"`
219
				Reset     int `json:"reset"`
220
			} `json:"search"`
221
			GraphQL struct {
222
				Limit     int `json:"limit"`
223
				Remaining int `json:"remaining"`
224
				Reset     int `json:"reset"`
225
			} `json:"graphql"`
226
		} `json:"resources"`
227
		Rate struct {
228
			Limit     int `json:"limit"`
229
			Remaining int `json:"remaining"`
230
			Reset     int `json:"reset"`
231
		} `json:"rate"`
232
	}
233
	url := "https://api.github.com/rate_limit"
234
	resp, statusCode, err := httpcache.MakeHTTPRequest(url)
235
	if err != nil {
236
		log.Fatalf("Error during checking rate limit : %d %v#", statusCode, err)
237
	}
238
	jsonResponse, _, _ := httpcache.ReadResp(resp)
239
	rateLimits := RateLimits{}
240
	json.Unmarshal(jsonResponse, &rateLimits)
241
	fmt.Printf("Core: %d/%d (reset in %d minutes)\n", rateLimits.Resources.Core.Remaining, rateLimits.Resources.Core.Limit, timing.GetRelativeTime(rateLimits.Resources.Core.Reset))
242
	fmt.Printf("Search: %d/%d (reset in %d minutes)\n", rateLimits.Resources.Search.Remaining, rateLimits.Resources.Search.Limit, timing.GetRelativeTime(rateLimits.Resources.Search.Reset))
243
	fmt.Printf("GraphQL: %d/%d (reset in %d minutes)\n", rateLimits.Resources.GraphQL.Remaining, rateLimits.Resources.GraphQL.Limit, timing.GetRelativeTime(rateLimits.Resources.GraphQL.Reset))
244
	fmt.Printf("Rate: %d/%d (reset in %d minutes)\n", rateLimits.Rate.Remaining, rateLimits.Rate.Limit, timing.GetRelativeTime(rateLimits.Rate.Reset))
245
}
246
247
func writeCsv(csvFilePath string, headers []string, ghData [][]string) {
248 1
	file, err := os.Create(csvFilePath)
249 1
	if err != nil {
250
		log.Fatal("Cannot create file", err)
251
	}
252 1
	defer file.Close()
253 1
	writer := csv.NewWriter(file)
254 1
	defer writer.Flush()
255 1
	err = writer.Write(headers)
256 1
	if err != nil {
257
		log.Fatal("Cannot write to file", err)
258
	}
259 1
	for _, value := range ghData {
260 1
		err := writer.Write(value)
261 1
		if err != nil {
262
			log.Fatal("Cannot write to file", err)
263
		}
264
	}
265
}
266