dev: clean gen_github_action_config (#4847)
This commit is contained in:
parent
819ab93276
commit
bc3a56ab10
@ -3,7 +3,7 @@ module github.com/golangci/golangci-lint/scripts/gen_github_action_config
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064
|
||||
golang.org/x/oauth2 v0.21.0
|
||||
)
|
||||
|
||||
|
4
scripts/gen_github_action_config/go.sum
generated
4
scripts/gen_github_action_config/go.sum
generated
@ -1,7 +1,7 @@
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc h1:vH0NQbIDk+mJLvBliNGfcQgUmhlniWBDXC79oRxfZA0=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240120211514-18a1ae0e79dc/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064 h1:RCQBSFx5JrsbHltqTtJ+kN3U0Y3a/N/GlVdmRSoxzyE=
|
||||
github.com/shurcooL/githubv4 v0.0.0-20240429030203-be2daab69064/go.mod h1:zqMwyHmnN/eDOZOdiTohqIUKUrTFX62PNlu7IJdu0q8=
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0=
|
||||
github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE=
|
||||
golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs=
|
||||
|
@ -14,39 +14,7 @@ import (
|
||||
"golang.org/x/oauth2"
|
||||
)
|
||||
|
||||
func main() {
|
||||
if err := generate(context.Background()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generate(ctx context.Context) error {
|
||||
allReleases, err := fetchAllReleases(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch all releases: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := buildConfig(allReleases)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build config: %w", err)
|
||||
}
|
||||
|
||||
if len(os.Args) != 2 { //nolint:gomnd
|
||||
return fmt.Errorf("usage: go run .../main.go out-path.json")
|
||||
}
|
||||
outFile, err := os.Create(os.Args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output config file: %w", err)
|
||||
}
|
||||
defer outFile.Close()
|
||||
enc := json.NewEncoder(outFile)
|
||||
enc.SetIndent("", " ")
|
||||
if err = enc.Encode(cfg); err != nil {
|
||||
return fmt.Errorf("failed to json encode config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
const noPatch = -1
|
||||
|
||||
type logInfo struct {
|
||||
Warning string `json:",omitempty"`
|
||||
@ -72,16 +40,19 @@ type version struct {
|
||||
|
||||
func (v version) String() string {
|
||||
ret := fmt.Sprintf("v%d.%d", v.major, v.minor)
|
||||
|
||||
if v.patch != noPatch {
|
||||
ret += fmt.Sprintf(".%d", v.patch)
|
||||
}
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
func (v *version) isAfterOrEq(vv *version) bool {
|
||||
func (v version) isAfterOrEq(vv *version) bool {
|
||||
if v.major != vv.major {
|
||||
return v.major >= vv.major
|
||||
}
|
||||
|
||||
if v.minor != vv.minor {
|
||||
return v.minor >= vv.minor
|
||||
}
|
||||
@ -89,100 +60,6 @@ func (v *version) isAfterOrEq(vv *version) bool {
|
||||
return v.patch >= vv.patch
|
||||
}
|
||||
|
||||
const noPatch = -1
|
||||
|
||||
func parseVersion(s string) (*version, error) {
|
||||
const vPrefix = "v"
|
||||
if !strings.HasPrefix(s, vPrefix) {
|
||||
return nil, fmt.Errorf("version should start with %q", vPrefix)
|
||||
}
|
||||
s = strings.TrimPrefix(s, vPrefix)
|
||||
|
||||
parts := strings.Split(s, ".")
|
||||
|
||||
var nums []int
|
||||
for _, part := range parts {
|
||||
num, err := strconv.Atoi(part)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse version part: %w", err)
|
||||
}
|
||||
nums = append(nums, num)
|
||||
}
|
||||
|
||||
if len(nums) == 2 { //nolint:gomnd
|
||||
return &version{major: nums[0], minor: nums[1], patch: noPatch}, nil
|
||||
}
|
||||
if len(nums) == 3 { //nolint:gomnd
|
||||
return &version{major: nums[0], minor: nums[1], patch: nums[2]}, nil
|
||||
}
|
||||
|
||||
return nil, errors.New("invalid version format")
|
||||
}
|
||||
|
||||
func findLinuxAssetURL(ver *version, releaseAssets []releaseAsset) (string, error) {
|
||||
pattern := fmt.Sprintf("golangci-lint-%d.%d.%d-linux-amd64.tar.gz", ver.major, ver.minor, ver.patch)
|
||||
for _, relAsset := range releaseAssets {
|
||||
if strings.HasSuffix(relAsset.DownloadURL, pattern) {
|
||||
return relAsset.DownloadURL, nil
|
||||
}
|
||||
}
|
||||
return "", fmt.Errorf("no matched asset url for pattern %q", pattern)
|
||||
}
|
||||
|
||||
func buildConfig(releases []release) (*actionConfig, error) {
|
||||
versionToRelease := map[version]release{}
|
||||
for _, rel := range releases {
|
||||
ver, err := parseVersion(rel.TagName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse release %s version: %w", rel.TagName, err)
|
||||
}
|
||||
if _, ok := versionToRelease[*ver]; ok {
|
||||
return nil, fmt.Errorf("duplicate release %s", rel.TagName)
|
||||
}
|
||||
versionToRelease[*ver] = rel
|
||||
}
|
||||
|
||||
maxPatchReleases := map[string]version{}
|
||||
for ver := range versionToRelease {
|
||||
key := fmt.Sprintf("v%d.%d", ver.major, ver.minor)
|
||||
if mapVer, ok := maxPatchReleases[key]; !ok || ver.isAfterOrEq(&mapVer) {
|
||||
maxPatchReleases[key] = ver
|
||||
}
|
||||
}
|
||||
|
||||
minorVersionToConfig := map[string]versionConfig{}
|
||||
minAllowedVersion := version{major: 1, minor: 14, patch: 0}
|
||||
|
||||
latestVersion := version{}
|
||||
latestVersionConfig := versionConfig{}
|
||||
for minorVersionedStr, maxPatchVersion := range maxPatchReleases {
|
||||
if !maxPatchVersion.isAfterOrEq(&minAllowedVersion) {
|
||||
minorVersionToConfig[minorVersionedStr] = versionConfig{
|
||||
Error: fmt.Sprintf("golangci-lint version '%s' isn't supported: we support only %s and later versions",
|
||||
minorVersionedStr, minAllowedVersion),
|
||||
}
|
||||
continue
|
||||
}
|
||||
maxPatchVersion := maxPatchVersion
|
||||
assetURL, err := findLinuxAssetURL(&maxPatchVersion, versionToRelease[maxPatchVersion].ReleaseAssets.Nodes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find linux asset url for release %s: %w", maxPatchVersion, err)
|
||||
}
|
||||
minorVersionToConfig[minorVersionedStr] = versionConfig{
|
||||
TargetVersion: maxPatchVersion.String(),
|
||||
AssetURL: assetURL,
|
||||
}
|
||||
if maxPatchVersion.isAfterOrEq(&latestVersion) {
|
||||
latestVersion = maxPatchVersion
|
||||
latestVersionConfig.TargetVersion = maxPatchVersion.String()
|
||||
latestVersionConfig.AssetURL = assetURL
|
||||
}
|
||||
}
|
||||
minorVersionToConfig["latest"] = latestVersionConfig
|
||||
|
||||
return &actionConfig{MinorVersionToConfig: minorVersionToConfig}, nil
|
||||
}
|
||||
|
||||
type release struct {
|
||||
TagName string
|
||||
ReleaseAssets struct {
|
||||
@ -194,14 +71,51 @@ type releaseAsset struct {
|
||||
DownloadURL string
|
||||
}
|
||||
|
||||
func main() {
|
||||
if err := generate(context.Background()); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func generate(ctx context.Context) error {
|
||||
if len(os.Args) != 2 {
|
||||
return fmt.Errorf("usage: go run .../main.go out-path.json")
|
||||
}
|
||||
|
||||
allReleases, err := fetchAllReleases(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch all releases: %w", err)
|
||||
}
|
||||
|
||||
cfg, err := buildConfig(allReleases)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to build config: %w", err)
|
||||
}
|
||||
|
||||
outFile, err := os.Create(os.Args[1])
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create output config file: %w", err)
|
||||
}
|
||||
|
||||
defer outFile.Close()
|
||||
|
||||
enc := json.NewEncoder(outFile)
|
||||
enc.SetIndent("", " ")
|
||||
|
||||
if err = enc.Encode(cfg); err != nil {
|
||||
return fmt.Errorf("failed to json encode config: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func fetchAllReleases(ctx context.Context) ([]release, error) {
|
||||
githubToken := os.Getenv("GITHUB_TOKEN")
|
||||
if githubToken == "" {
|
||||
return nil, errors.New("no GITHUB_TOKEN environment variable")
|
||||
}
|
||||
src := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})
|
||||
httpClient := oauth2.NewClient(ctx, src)
|
||||
client := githubv4.NewClient(httpClient)
|
||||
|
||||
client := githubv4.NewClient(oauth2.NewClient(ctx, oauth2.StaticTokenSource(&oauth2.Token{AccessToken: githubToken})))
|
||||
|
||||
var q struct {
|
||||
Repository struct {
|
||||
@ -227,13 +141,121 @@ func fetchAllReleases(ctx context.Context) ([]release, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to fetch releases page from GitHub: %w", err)
|
||||
}
|
||||
|
||||
releases := q.Repository.Releases
|
||||
allReleases = append(allReleases, releases.Nodes...)
|
||||
|
||||
if !releases.PageInfo.HasNextPage {
|
||||
break
|
||||
}
|
||||
|
||||
vars["releasesCursor"] = githubv4.NewString(releases.PageInfo.EndCursor)
|
||||
}
|
||||
|
||||
return allReleases, nil
|
||||
}
|
||||
|
||||
func buildConfig(releases []release) (*actionConfig, error) {
|
||||
versionToRelease := map[version]release{}
|
||||
|
||||
for _, rel := range releases {
|
||||
ver, err := parseVersion(rel.TagName)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse release %s version: %w", rel.TagName, err)
|
||||
}
|
||||
|
||||
if _, ok := versionToRelease[*ver]; ok {
|
||||
return nil, fmt.Errorf("duplicate release %s", rel.TagName)
|
||||
}
|
||||
|
||||
versionToRelease[*ver] = rel
|
||||
}
|
||||
|
||||
maxPatchReleases := map[string]version{}
|
||||
|
||||
for ver := range versionToRelease {
|
||||
key := fmt.Sprintf("v%d.%d", ver.major, ver.minor)
|
||||
|
||||
if mapVer, ok := maxPatchReleases[key]; !ok || ver.isAfterOrEq(&mapVer) {
|
||||
maxPatchReleases[key] = ver
|
||||
}
|
||||
}
|
||||
|
||||
minorVersionToConfig := map[string]versionConfig{}
|
||||
minAllowedVersion := version{major: 1, minor: 14, patch: 0}
|
||||
|
||||
latestVersion := version{}
|
||||
latestVersionConfig := versionConfig{}
|
||||
|
||||
for minorVersionedStr, maxPatchVersion := range maxPatchReleases {
|
||||
if !maxPatchVersion.isAfterOrEq(&minAllowedVersion) {
|
||||
minorVersionToConfig[minorVersionedStr] = versionConfig{
|
||||
Error: fmt.Sprintf("golangci-lint version '%s' isn't supported: we support only %s and later versions",
|
||||
minorVersionedStr, minAllowedVersion),
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
maxPatchVersion := maxPatchVersion
|
||||
|
||||
assetURL, err := findLinuxAssetURL(&maxPatchVersion, versionToRelease[maxPatchVersion].ReleaseAssets.Nodes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find linux asset url for release %s: %w", maxPatchVersion, err)
|
||||
}
|
||||
|
||||
minorVersionToConfig[minorVersionedStr] = versionConfig{
|
||||
TargetVersion: maxPatchVersion.String(),
|
||||
AssetURL: assetURL,
|
||||
}
|
||||
|
||||
if maxPatchVersion.isAfterOrEq(&latestVersion) {
|
||||
latestVersion = maxPatchVersion
|
||||
latestVersionConfig.TargetVersion = maxPatchVersion.String()
|
||||
latestVersionConfig.AssetURL = assetURL
|
||||
}
|
||||
}
|
||||
|
||||
minorVersionToConfig["latest"] = latestVersionConfig
|
||||
|
||||
return &actionConfig{MinorVersionToConfig: minorVersionToConfig}, nil
|
||||
}
|
||||
|
||||
func findLinuxAssetURL(ver *version, releaseAssets []releaseAsset) (string, error) {
|
||||
pattern := fmt.Sprintf("golangci-lint-%d.%d.%d-linux-amd64.tar.gz", ver.major, ver.minor, ver.patch)
|
||||
|
||||
for _, relAsset := range releaseAssets {
|
||||
if strings.HasSuffix(relAsset.DownloadURL, pattern) {
|
||||
return relAsset.DownloadURL, nil
|
||||
}
|
||||
}
|
||||
|
||||
return "", fmt.Errorf("no matched asset url for pattern %q", pattern)
|
||||
}
|
||||
|
||||
func parseVersion(s string) (*version, error) {
|
||||
const vPrefix = "v"
|
||||
if !strings.HasPrefix(s, vPrefix) {
|
||||
return nil, fmt.Errorf("version %q should start with %q", s, vPrefix)
|
||||
}
|
||||
|
||||
parts := strings.Split(strings.TrimPrefix(s, vPrefix), ".")
|
||||
|
||||
var nums []int
|
||||
for _, part := range parts {
|
||||
num, err := strconv.Atoi(part)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse version %q: %w", s, err)
|
||||
}
|
||||
|
||||
nums = append(nums, num)
|
||||
}
|
||||
|
||||
switch len(nums) {
|
||||
case 2:
|
||||
return &version{major: nums[0], minor: nums[1], patch: noPatch}, nil
|
||||
case 3:
|
||||
return &version{major: nums[0], minor: nums[1], patch: nums[2]}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid version format: %s", s)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user