generated from actions/typescript-action
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
4 changed files
with
309 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/goplus/setup-goplus | ||
|
||
go 1.18 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package main | ||
|
||
import "github.com/goplus/setup-goplus/install" | ||
|
||
func main() { | ||
if err := install.InstallGop(); err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,296 @@ | ||
package install | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"path/filepath" | ||
"regexp" | ||
"sort" | ||
"strings" | ||
) | ||
|
||
const GoplusRepo = "https://github.com/goplus/gop.git" | ||
|
||
// InstallGop is the main function for installing gop | ||
func InstallGop() error { | ||
versionSpec, err := resolveVersionInput() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
tagVersions, err := fetchTags() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
// Filter and sort valid versions | ||
var validVersions []string | ||
for _, v := range tagVersions { | ||
if isValidVersion(v) { | ||
validVersions = append(validVersions, v) | ||
} | ||
} | ||
sortVersions(validVersions) | ||
|
||
var version string | ||
if versionSpec == "" || versionSpec == "latest" { | ||
version = validVersions[0] | ||
warning(fmt.Sprintf("No gop-version specified, using latest version: %s", version)) | ||
} else { | ||
version = maxSatisfying(validVersions, versionSpec) | ||
if version == "" { | ||
warning(fmt.Sprintf("No gop-version found that satisfies '%s', trying branches...", versionSpec)) | ||
branches, err := fetchBranches() | ||
if err != nil { | ||
return err | ||
} | ||
if !contains(branches, versionSpec) { | ||
return fmt.Errorf("no gop-version found that satisfies '%s' in branches or tags", versionSpec) | ||
} | ||
} | ||
} | ||
|
||
var checkoutVersion string | ||
if version != "" { | ||
info(fmt.Sprintf("Selected version %s by spec %s", version, versionSpec)) | ||
checkoutVersion = "v" + version | ||
setOutput("gop-version-verified", "true") | ||
} else { | ||
warning(fmt.Sprintf("Unable to find a version that satisfies the version spec '%s', trying branches...", versionSpec)) | ||
checkoutVersion = versionSpec | ||
setOutput("gop-version-verified", "false") | ||
} | ||
|
||
gopDir, err := cloneBranchOrTag(checkoutVersion) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
if err := install(gopDir); err != nil { | ||
return err | ||
} | ||
|
||
if version != "" { | ||
if err := checkVersion(version); err != nil { | ||
return err | ||
} | ||
} | ||
|
||
gopVersion, err := getGopVersion() | ||
if err != nil { | ||
return err | ||
} | ||
setOutput("gop-version", gopVersion) | ||
|
||
return nil | ||
} | ||
|
||
func sortVersions(versions []string) { | ||
sort.Sort(sort.Reverse(semverSort(versions))) | ||
} | ||
|
||
type semverSort []string | ||
|
||
func (s semverSort) Len() int { return len(s) } | ||
func (s semverSort) Swap(i, j int) { s[i], s[j] = s[j], s[i] } | ||
func (s semverSort) Less(i, j int) bool { return compareVersions(s[i], s[j]) } | ||
|
||
func compareVersions(a, b string) bool { | ||
aParts := strings.Split(a, ".") | ||
bParts := strings.Split(b, ".") | ||
for i := 0; i < len(aParts) && i < len(bParts); i++ { | ||
if aParts[i] != bParts[i] { | ||
return aParts[i] < bParts[i] | ||
} | ||
} | ||
return len(aParts) < len(bParts) | ||
} | ||
|
||
func isValidVersion(version string) bool { | ||
match, _ := regexp.MatchString(`^\d+\.\d+\.\d+$`, version) | ||
return match | ||
} | ||
|
||
func maxSatisfying(versions []string, spec string) string { | ||
for _, v := range versions { | ||
if strings.HasPrefix(v, spec) { | ||
return v | ||
} | ||
} | ||
return "" | ||
} | ||
|
||
func cloneBranchOrTag(versionSpec string) (string, error) { | ||
workDir := filepath.Join(os.Getenv("HOME"), "workdir") | ||
if err := os.RemoveAll(workDir); err != nil { | ||
return "", err | ||
} | ||
if err := os.MkdirAll(workDir, 0755); err != nil { | ||
return "", err | ||
} | ||
|
||
info(fmt.Sprintf("Cloning gop %s to %s ...", versionSpec, workDir)) | ||
cmd := exec.Command("git", "clone", "--depth", "1", "--branch", versionSpec, GoplusRepo) | ||
cmd.Dir = workDir | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Run(); err != nil { | ||
return "", err | ||
} | ||
info("gop cloned") | ||
return filepath.Join(workDir, "gop"), nil | ||
} | ||
|
||
func install(gopDir string) error { | ||
info(fmt.Sprintf("Installing gop %s ...", gopDir)) | ||
binDir := filepath.Join(os.Getenv("HOME"), "bin") | ||
cmd := exec.Command("go", "run", "cmd/make.go", "-install") | ||
cmd.Dir = gopDir | ||
cmd.Env = append(os.Environ(), "GOBIN="+binDir) | ||
cmd.Stdout = os.Stdout | ||
cmd.Stderr = os.Stderr | ||
if err := cmd.Run(); err != nil { | ||
return err | ||
} | ||
|
||
addToPath(binDir) | ||
info("gop installed") | ||
return nil | ||
} | ||
|
||
func checkVersion(versionSpec string) error { | ||
info(fmt.Sprintf("Testing gop %s ...", versionSpec)) | ||
actualVersion, err := getGopVersion() | ||
if err != nil { | ||
return err | ||
} | ||
if actualVersion != versionSpec { | ||
return fmt.Errorf("installed gop version %s does not match expected version %s", actualVersion, versionSpec) | ||
Check warning on line 169 in install/install.go qiniu-x / golangci-lintinstall/install.go#L169
|
||
} | ||
info(fmt.Sprintf("Installed gop version %s", actualVersion)) | ||
return nil | ||
} | ||
|
||
func getGopVersion() (string, error) { | ||
cmd := exec.Command("gop", "env", "GOPVERSION") | ||
out, err := cmd.Output() | ||
if err != nil { | ||
return "", err | ||
} | ||
return strings.TrimPrefix(strings.TrimSpace(string(out)), "v"), nil | ||
} | ||
|
||
func fetchTags() ([]string, error) { | ||
cmd := exec.Command("git", "-c", "versionsort.suffix=-", "ls-remote", "--tags", "--sort=v:refname", GoplusRepo) | ||
out, err := cmd.Output() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var versions []string | ||
for _, line := range strings.Split(string(out), "\n") { | ||
if line == "" { | ||
continue | ||
} | ||
parts := strings.Split(line, "\t") | ||
version := strings.TrimPrefix(strings.TrimPrefix(parts[1], "refs/tags/"), "v") | ||
versions = append(versions, version) | ||
} | ||
return versions, nil | ||
} | ||
|
||
func fetchBranches() ([]string, error) { | ||
cmd := exec.Command("git", "-c", "versionsort.suffix=-", "ls-remote", "--heads", "--sort=v:refname", GoplusRepo) | ||
out, err := cmd.Output() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
var branches []string | ||
for _, line := range strings.Split(string(out), "\n") { | ||
if line == "" { | ||
continue | ||
} | ||
parts := strings.Split(line, "\t") | ||
branch := strings.TrimPrefix(parts[1], "refs/heads/") | ||
branches = append(branches, branch) | ||
} | ||
return branches, nil | ||
} | ||
|
||
func resolveVersionInput() (string, error) { | ||
version := os.Getenv("INPUT_GOP_VERSION") | ||
versionFile := os.Getenv("INPUT_GOP_VERSION_FILE") | ||
|
||
if version != "" && versionFile != "" { | ||
warning("Both gop-version and gop-version-file inputs are specified, only gop-version will be used") | ||
return version, nil | ||
} | ||
|
||
if version != "" { | ||
return version, nil | ||
} | ||
|
||
if versionFile != "" { | ||
if _, err := os.Stat(versionFile); os.IsNotExist(err) { | ||
return "", fmt.Errorf("the specified gop version file at: %s does not exist", versionFile) | ||
} | ||
return parseGopVersionFile(versionFile) | ||
} | ||
|
||
return "", nil | ||
} | ||
|
||
func parseGopVersionFile(versionFilePath string) (string, error) { | ||
content, err := os.ReadFile(versionFilePath) | ||
if err != nil { | ||
return "", err | ||
} | ||
|
||
filename := filepath.Base(versionFilePath) | ||
if filename == "gop.mod" || filename == "gop.work" { | ||
re := regexp.MustCompile(`^gop (\d+(\.\d+)*)`) | ||
match := re.FindSubmatch(content) | ||
if match != nil { | ||
return string(match[1]), nil | ||
} | ||
return "", nil | ||
} | ||
|
||
return strings.TrimSpace(string(content)), nil | ||
} | ||
|
||
func setOutput(name, value string) { | ||
if outputFile := os.Getenv("GITHUB_OUTPUT"); outputFile != "" { | ||
f, _ := os.OpenFile(outputFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) | ||
fmt.Fprintf(f, "%s=%s\n", name, value) | ||
f.Close() | ||
} | ||
} | ||
|
||
func addToPath(path string) { | ||
if pathFile := os.Getenv("GITHUB_PATH"); pathFile != "" { | ||
f, _ := os.OpenFile(pathFile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) | ||
fmt.Fprintln(f, path) | ||
f.Close() | ||
} | ||
os.Setenv("PATH", path+":"+os.Getenv("PATH")) | ||
} | ||
|
||
func info(msg string) { | ||
fmt.Println(msg) | ||
} | ||
|
||
func warning(msg string) { | ||
fmt.Printf("::warning::%s\n", msg) | ||
} | ||
|
||
func contains(slice []string, item string) bool { | ||
for _, s := range slice { | ||
if s == item { | ||
return true | ||
} | ||
} | ||
return false | ||
} |