package gomod import ( "context" "fmt" "github.com/sirupsen/logrus" "os" "os/exec" "regexp" "strings" "github.com/google/go-github/v53/github" "golang.org/x/mod/modfile" ) var githubRegexp = regexp.MustCompile(`github.com/(.*)/(.*)`) func command(url string) error { cmd := exec.Command("go", "get", "-u", url) if _, err := cmd.CombinedOutput(); err != nil { return err } return 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 } logrus.Infof("go get -u %s", mod.Mod.String()) if err := command(mod.Mod.String()); err != nil { logrus.Errorf("upgrade %s failed: %v", mod.Mod.String(), err) continue } logrus.Infof("upgrade %s success", mod.Mod.String()) } } func SingleModUpgrade(url string) { version := url + "@latest" if strings.Contains(url, "github.com") { commitID, err := getCommitID(url) if err == nil { version = url + "@" + commitID[:8] } } if err := command(version); err != nil { logrus.Errorf("upgrade %s failed: %v", version, err) return } logrus.Infof("upgrade %s success", version) } 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())) } return res[0][1], res[0][2] } 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 len(tags) == 0 && err != nil { logrus.Warnf("get tag info failed: %v, start get commit id", err) } commits, _, err := client.Repositories.ListCommits(ctx, owner, repo, &github.CommitsListOptions{ ListOptions: github.ListOptions{ Page: 0, PerPage: 1, }, }) if err != nil { return "", err } if len(commits) == 0 { return "", fmt.Errorf("get commit info empty") } return *commits[0].SHA, nil }