gomod/gomod.go

143 lines
3.3 KiB
Go

package gomod
import (
"context"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"github.com/google/go-github/v56/github"
"github.com/sirupsen/logrus"
"golang.org/x/mod/modfile"
)
const (
defaultVersion = "latest"
)
var (
githubRegexp = regexp.MustCompile(`github.com/(.*?)/(.*)`)
genericWhitelist = []string{
"google.golang.org",
}
)
func upgrade(url string) (newUrl string, err error) {
var version = defaultVersion
if strings.Contains(url, "github.com") {
commitID, err := getCommitID(url)
if err != nil {
logrus.WithField("url", url).Warnf("get github commit id failed, use default version: %v", err)
} else {
version = commitID
}
}
if version == defaultVersion && !ElemIn(genericWhitelist, url) {
v, err := lsRemote.setUrl(url).getLatestTagOrCommitID()
if err != nil {
logrus.WithField("url", url).Warnf("get git ls-remote info failed, use default version: %v", err)
} else {
version = v
}
}
versionUrl := url + "@" + version
cmd := exec.Command("go", "get", "-u", versionUrl)
if _, err := cmd.CombinedOutput(); err != nil {
return "", err
}
return versionUrl, nil
}
func AllModUpgrade() {
modFileData, err := os.ReadFile("go.mod")
if err != nil {
logrus.Errorf("read go.mod file failed: %v", err)
return
}
modFile, err := modfile.Parse("go.mod", modFileData, nil)
if err != nil {
logrus.Errorf("parse go.mod file failed: %v", err)
return
}
for _, mod := range modFile.Require {
if mod.Indirect {
continue
}
versionUrl, err := upgrade(mod.Mod.Path)
if err != nil {
logrus.WithField("url", mod.Mod.Path).Errorf("upgrade failed: %v", err)
continue
}
logrus.WithField("url", versionUrl).Infof("upgrade success")
}
tidy()
}
func SingleModUpgrade(url string) {
versionUrl, err := upgrade(url)
if err != nil {
logrus.WithField("url", url).Errorf("upgrade failed: %v", err)
return
}
logrus.WithField("url", versionUrl).Infof("upgrade success")
tidy()
}
func parseUrl(url string) (owner, repo string) {
res := githubRegexp.FindAllStringSubmatch(url, -1)
if len(res) != 1 {
logrus.Panicf(fmt.Sprintf("%s url no match github url rule: %s", url, githubRegexp.String()))
}
if len(res[0]) != 3 {
logrus.Panicf(fmt.Sprintf("%s url no match github url rule: %s", url, githubRegexp.String()))
}
owner = res[0][1]
repo = res[0][2]
if repoA := strings.Split(repo, "/"); len(repoA) > 1 {
repo = repoA[0]
}
return owner, repo
}
func getCommitID(url string) (string, error) {
owner, repo := parseUrl(url)
client := github.NewClient(nil)
ctx := context.Background()
tags, _, err := client.Repositories.ListTags(ctx, owner, repo, &github.ListOptions{
Page: 0,
PerPage: 1,
})
if err != nil {
logrus.WithField("url", url).Warnf("get tag info failed: %v, start get commit id", err)
}
if len(tags) != 0 {
return tags[0].GetName(), nil
}
// get latest commit id
commits, _, err := client.Repositories.ListCommits(ctx, owner, repo, &github.CommitsListOptions{
ListOptions: github.ListOptions{
Page: 0,
PerPage: 1,
},
})
if err != nil {
logrus.WithField("url", url).Errorf("get latest commit failed: %v", err)
return "", err
}
if len(commits) == 0 {
return "", fmt.Errorf("get commit info empty")
}
return *commits[0].SHA, nil
}
func tidy() {
cmd := exec.Command("go", "mod", "tidy")
_ = cmd.Run()
}