Skip to content

Commit bc3a56a

Browse files
authored
dev: clean gen_github_action_config (#4847)
1 parent 819ab93 commit bc3a56a

File tree

3 files changed

+127
-105
lines changed

3 files changed

+127
-105
lines changed

scripts/gen_github_action_config/go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module github.com/golangci/golangci-lint/scripts/gen_github_action_config
33
go 1.21
44

55
require (
6-
github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc
6+
github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064
77
golang.org/x/oauth2 v0.21.0
88
)
99

scripts/gen_github_action_config/go.sum

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/gen_github_action_config/main.go

+124-102
Original file line numberDiff line numberDiff line change
@@ -14,39 +14,7 @@ import (
1414
"golang.org/x/oauth2"
1515
)
1616

17-
func main() {
18-
if err := generate(context.Background()); err != nil {
19-
log.Fatal(err)
20-
}
21-
}
22-
23-
func generate(ctx context.Context) error {
24-
allReleases, err := fetchAllReleases(ctx)
25-
if err != nil {
26-
return fmt.Errorf("failed to fetch all releases: %w", err)
27-
}
28-
29-
cfg, err := buildConfig(allReleases)
30-
if err != nil {
31-
return fmt.Errorf("failed to build config: %w", err)
32-
}
33-
34-
if len(os.Args) != 2 { //nolint:gomnd
35-
return fmt.Errorf("usage: go run .../main.go out-path.json")
36-
}
37-
outFile, err := os.Create(os.Args[1])
38-
if err != nil {
39-
return fmt.Errorf("failed to create output config file: %w", err)
40-
}
41-
defer outFile.Close()
42-
enc := json.NewEncoder(outFile)
43-
enc.SetIndent("", " ")
44-
if err = enc.Encode(cfg); err != nil {
45-
return fmt.Errorf("failed to json encode config: %w", err)
46-
}
47-
48-
return nil
49-
}
17+
const noPatch = -1
5018

5119
type logInfo struct {
5220
Warning string `json:",omitempty"`
@@ -72,79 +40,142 @@ type version struct {
7240

7341
func (v version) String() string {
7442
ret := fmt.Sprintf("v%d.%d", v.major, v.minor)
43+
7544
if v.patch != noPatch {
7645
ret += fmt.Sprintf(".%d", v.patch)
7746
}
47+
7848
return ret
7949
}
8050

81-
func (v *version) isAfterOrEq(vv *version) bool {
51+
func (v version) isAfterOrEq(vv *version) bool {
8252
if v.major != vv.major {
8353
return v.major >= vv.major
8454
}
55+
8556
if v.minor != vv.minor {
8657
return v.minor >= vv.minor
8758
}
8859

8960
return v.patch >= vv.patch
9061
}
9162

92-
const noPatch = -1
63+
type release struct {
64+
TagName string
65+
ReleaseAssets struct {
66+
Nodes []releaseAsset
67+
} `graphql:"releaseAssets(first: 50)"`
68+
}
9369

94-
func parseVersion(s string) (*version, error) {
95-
const vPrefix = "v"
96-
if !strings.HasPrefix(s, vPrefix) {
97-
return nil, fmt.Errorf("version should start with %q", vPrefix)
70+
type releaseAsset struct {
71+
DownloadURL string
72+
}
73+
74+
func main() {
75+
if err := generate(context.Background()); err != nil {
76+
log.Fatal(err)
9877
}
99-
s = strings.TrimPrefix(s, vPrefix)
78+
}
10079

101-
parts := strings.Split(s, ".")
80+
func generate(ctx context.Context) error {
81+
if len(os.Args) != 2 {
82+
return fmt.Errorf("usage: go run .../main.go out-path.json")
83+
}
10284

103-
var nums []int
104-
for _, part := range parts {
105-
num, err := strconv.Atoi(part)
106-
if err != nil {
107-
return nil, fmt.Errorf("failed to parse version part: %w", err)
108-
}
109-
nums = append(nums, num)
85+
allReleases, err := fetchAllReleases(ctx)
86+
if err != nil {
87+
return fmt.Errorf("failed to fetch all releases: %w", err)
11088
}
11189

112-
if len(nums) == 2 { //nolint:gomnd
113-
return &version{major: nums[0], minor: nums[1], patch: noPatch}, nil
90+
cfg, err := buildConfig(allReleases)
91+
if err != nil {
92+
return fmt.Errorf("failed to build config: %w", err)
11493
}
115-
if len(nums) == 3 { //nolint:gomnd
116-
return &version{major: nums[0], minor: nums[1], patch: nums[2]}, nil
94+
95+
outFile, err := os.Create(os.Args[1])
96+
if err != nil {
97+
return fmt.Errorf("failed to create output config file: %w", err)
11798
}
11899

119-
return nil, errors.New("invalid version format")
100+
defer outFile.Close()
101+
102+
enc := json.NewEncoder(outFile)
103+
enc.SetIndent("", " ")
104+
105+
if err = enc.Encode(cfg); err != nil {
106+
return fmt.Errorf("failed to json encode config: %w", err)
107+
}
108+
109+
return nil
120110
}
121111

122-
func findLinuxAssetURL(ver *version, releaseAssets []releaseAsset) (string, error) {
123-
pattern := fmt.Sprintf("golangci-lint-%d.%d.%d-linux-amd64.tar.gz", ver.major, ver.minor, ver.patch)
124-
for _, relAsset := range releaseAssets {
125-
if strings.HasSuffix(relAsset.DownloadURL, pattern) {
126-
return relAsset.DownloadURL, nil
112+
func fetchAllReleases(ctx context.Context) ([]release, error) {
113+
githubToken := os.Getenv("GITHUB_TOKEN")
114+
if githubToken == "" {
115+
return nil, errors.New("no GITHUB_TOKEN environment variable")
116+
}
117+
118+
client := githubv4.NewClient(oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})))
119+
120+
var q struct {
121+
Repository struct {
122+
Releases struct {
123+
Nodes []release
124+
PageInfo struct {
125+
EndCursor githubv4.String
126+
HasNextPage bool
127+
}
128+
} `graphql:"releases(first: 100, orderBy: { field: CREATED_AT, direction: DESC }, after: $releasesCursor)"`
129+
} `graphql:"repository(owner: $owner, name: $name)"`
130+
}
131+
132+
vars := map[string]any{
133+
"owner": githubv4.String("golangci"),
134+
"name": githubv4.String("golangci-lint"),
135+
"releasesCursor": (*githubv4.String)(nil),
136+
}
137+
138+
var allReleases []release
139+
for {
140+
err := client.Query(ctx, &q, vars)
141+
if err != nil {
142+
return nil, fmt.Errorf("failed to fetch releases page from GitHub: %w", err)
127143
}
144+
145+
releases := q.Repository.Releases
146+
allReleases = append(allReleases, releases.Nodes...)
147+
148+
if !releases.PageInfo.HasNextPage {
149+
break
150+
}
151+
152+
vars["releasesCursor"] = githubv4.NewString(releases.PageInfo.EndCursor)
128153
}
129-
return "", fmt.Errorf("no matched asset url for pattern %q", pattern)
154+
155+
return allReleases, nil
130156
}
131157

132158
func buildConfig(releases []release) (*actionConfig, error) {
133159
versionToRelease := map[version]release{}
160+
134161
for _, rel := range releases {
135162
ver, err := parseVersion(rel.TagName)
136163
if err != nil {
137164
return nil, fmt.Errorf("failed to parse release %s version: %w", rel.TagName, err)
138165
}
166+
139167
if _, ok := versionToRelease[*ver]; ok {
140168
return nil, fmt.Errorf("duplicate release %s", rel.TagName)
141169
}
170+
142171
versionToRelease[*ver] = rel
143172
}
144173

145174
maxPatchReleases := map[string]version{}
175+
146176
for ver := range versionToRelease {
147177
key := fmt.Sprintf("v%d.%d", ver.major, ver.minor)
178+
148179
if mapVer, ok := maxPatchReleases[key]; !ok || ver.isAfterOrEq(&mapVer) {
149180
maxPatchReleases[key] = ver
150181
}
@@ -155,6 +186,7 @@ func buildConfig(releases []release) (*actionConfig, error) {
155186

156187
latestVersion := version{}
157188
latestVersionConfig := versionConfig{}
189+
158190
for minorVersionedStr, maxPatchVersion := range maxPatchReleases {
159191
if !maxPatchVersion.isAfterOrEq(&minAllowedVersion) {
160192
minorVersionToConfig[minorVersionedStr] = versionConfig{
@@ -163,77 +195,67 @@ func buildConfig(releases []release) (*actionConfig, error) {
163195
}
164196
continue
165197
}
198+
166199
maxPatchVersion := maxPatchVersion
200+
167201
assetURL, err := findLinuxAssetURL(&maxPatchVersion, versionToRelease[maxPatchVersion].ReleaseAssets.Nodes)
168202
if err != nil {
169203
return nil, fmt.Errorf("failed to find linux asset url for release %s: %w", maxPatchVersion, err)
170204
}
205+
171206
minorVersionToConfig[minorVersionedStr] = versionConfig{
172207
TargetVersion: maxPatchVersion.String(),
173208
AssetURL: assetURL,
174209
}
210+
175211
if maxPatchVersion.isAfterOrEq(&latestVersion) {
176212
latestVersion = maxPatchVersion
177213
latestVersionConfig.TargetVersion = maxPatchVersion.String()
178214
latestVersionConfig.AssetURL = assetURL
179215
}
180216
}
217+
181218
minorVersionToConfig["latest"] = latestVersionConfig
182219

183220
return &actionConfig{MinorVersionToConfig: minorVersionToConfig}, nil
184221
}
185222

186-
type release struct {
187-
TagName string
188-
ReleaseAssets struct {
189-
Nodes []releaseAsset
190-
} `graphql:"releaseAssets(first: 50)"`
191-
}
192-
193-
type releaseAsset struct {
194-
DownloadURL string
195-
}
223+
func findLinuxAssetURL(ver *version, releaseAssets []releaseAsset) (string, error) {
224+
pattern := fmt.Sprintf("golangci-lint-%d.%d.%d-linux-amd64.tar.gz", ver.major, ver.minor, ver.patch)
196225

197-
func fetchAllReleases(ctx context.Context) ([]release, error) {
198-
githubToken := os.Getenv("GITHUB_TOKEN")
199-
if githubToken == "" {
200-
return nil, errors.New("no GITHUB_TOKEN environment variable")
226+
for _, relAsset := range releaseAssets {
227+
if strings.HasSuffix(relAsset.DownloadURL, pattern) {
228+
return relAsset.DownloadURL, nil
229+
}
201230
}
202-
src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})
203-
httpClient := oauth2.NewClient(ctx, src)
204-
client := githubv4.NewClient(httpClient)
205231

206-
var q struct {
207-
Repository struct {
208-
Releases struct {
209-
Nodes []release
210-
PageInfo struct {
211-
EndCursor githubv4.String
212-
HasNextPage bool
213-
}
214-
} `graphql:"releases(first: 100, orderBy: { field: CREATED_AT, direction: DESC }, after: $releasesCursor)"`
215-
} `graphql:"repository(owner: $owner, name: $name)"`
216-
}
232+
return "", fmt.Errorf("no matched asset url for pattern %q", pattern)
233+
}
217234

218-
vars := map[string]any{
219-
"owner": githubv4.String("golangci"),
220-
"name": githubv4.String("golangci-lint"),
221-
"releasesCursor": (*githubv4.String)(nil),
235+
func parseVersion(s string) (*version, error) {
236+
const vPrefix = "v"
237+
if !strings.HasPrefix(s, vPrefix) {
238+
return nil, fmt.Errorf("version %q should start with %q", s, vPrefix)
222239
}
223240

224-
var allReleases []release
225-
for {
226-
err := client.Query(ctx, &q, vars)
241+
parts := strings.Split(strings.TrimPrefix(s, vPrefix), ".")
242+
243+
var nums []int
244+
for _, part := range parts {
245+
num, err := strconv.Atoi(part)
227246
if err != nil {
228-
return nil, fmt.Errorf("failed to fetch releases page from GitHub: %w", err)
247+
return nil, fmt.Errorf("failed to parse version %q: %w", s, err)
229248
}
230-
releases := q.Repository.Releases
231-
allReleases = append(allReleases, releases.Nodes...)
232-
if !releases.PageInfo.HasNextPage {
233-
break
234-
}
235-
vars["releasesCursor"] = githubv4.NewString(releases.PageInfo.EndCursor)
249+
250+
nums = append(nums, num)
236251
}
237252

238-
return allReleases, nil
253+
switch len(nums) {
254+
case 2:
255+
return &version{major: nums[0], minor: nums[1], patch: noPatch}, nil
256+
case 3:
257+
return &version{major: nums[0], minor: nums[1], patch: nums[2]}, nil
258+
default:
259+
return nil, fmt.Errorf("invalid version format: %s", s)
260+
}
239261
}

0 commit comments

Comments
 (0)