-
Notifications
You must be signed in to change notification settings - Fork 548
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1096 from goplus/main
releaseNewVersion tool
- Loading branch information
Showing
5 changed files
with
230 additions
and
114 deletions.
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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,7 +22,10 @@ jobs: | |
go-version: ${{ matrix.go-version }} | ||
|
||
- name: Test Go+ installer | ||
run: go test -v cmd/make_test.go | ||
run: | | ||
git config --global user.email "[email protected]" | ||
git config --global user.name "build robot" | ||
go test -v cmd/make_test.go | ||
- name: Compile gop and related tools | ||
run: go install ./... | ||
|
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
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 |
---|---|---|
|
@@ -82,7 +82,6 @@ var commandExecuteEnv = initCommandExecuteEnv | |
|
||
// Always put `gop` command as the first item, as it will be referenced by below code. | ||
var gopBinFiles = []string{"gop", "gopfmt"} | ||
var versionFile = filepath.Join(gopRoot, "VERSION") | ||
|
||
const ( | ||
inWindows = (runtime.GOOS == "windows") | ||
|
@@ -97,31 +96,144 @@ func init() { | |
} | ||
} | ||
|
||
func execCommand(command string, arg ...string) (string, string, error) { | ||
type ExecCmdError struct { | ||
Err error | ||
Stderr string | ||
} | ||
|
||
func (p *ExecCmdError) Error() string { | ||
if e := p.Stderr; e != "" { | ||
return e | ||
} | ||
return p.Err.Error() | ||
} | ||
|
||
type iGitRemote interface { | ||
CheckRemoteUrl() | ||
CreateBranchFrom(branch, remote string) error | ||
PushCommits(remote, branch string) error | ||
DeleteBranch(branch string) error | ||
} | ||
|
||
type ( | ||
gitRemoteImpl struct{} | ||
gitRemoteNone struct{} | ||
) | ||
|
||
func (p *gitRemoteImpl) CheckRemoteUrl() { | ||
if getGitRemoteUrl("gop") == "" { | ||
log.Fatalln("Error: git remote gop not found, please use `git remote add gop [email protected]:goplus/gop.git`.") | ||
} | ||
} | ||
|
||
func (p *gitRemoteImpl) CreateBranchFrom(branch, remote string) (err error) { | ||
_, err = execCommand("git", "fetch", remote) | ||
if err != nil { | ||
return | ||
} | ||
execCommand("git", "branch", "-D", branch) | ||
_, err = execCommand("git", "checkout", "-b", branch, remote+"/"+branch) | ||
return | ||
} | ||
|
||
func (p *gitRemoteImpl) PushCommits(remote, branch string) error { | ||
_, err := execCommand("git", "push", remote, branch) | ||
return err | ||
} | ||
|
||
func (p *gitRemoteImpl) DeleteBranch(branch string) error { | ||
_, err := execCommand("git", "branch", "-D", branch) | ||
return err | ||
} | ||
|
||
func (p *gitRemoteNone) CheckRemoteUrl() {} | ||
func (p *gitRemoteNone) CreateBranchFrom(branch, remote string) (err error) { return nil } | ||
func (p *gitRemoteNone) PushCommits(remote, branch string) error { return nil } | ||
func (p *gitRemoteNone) DeleteBranch(branch string) error { return nil } | ||
|
||
var ( | ||
gitRemote iGitRemote = &gitRemoteImpl{} | ||
) | ||
|
||
func execCommand(command string, arg ...string) (string, error) { | ||
var stdout, stderr bytes.Buffer | ||
cmd := exec.Command(command, arg...) | ||
cmd.Stdout = &stdout | ||
cmd.Stderr = &stderr | ||
cmd.Env = commandExecuteEnv | ||
err := cmd.Run() | ||
return stdout.String(), stderr.String(), err | ||
if err != nil { | ||
err = &ExecCmdError{Err: err, Stderr: stderr.String()} | ||
} | ||
return stdout.String(), err | ||
} | ||
|
||
func getTagRev(tag string) string { | ||
const commit = "commit " | ||
stdout, err := execCommand("git", "show", tag) | ||
if err != nil || !strings.HasPrefix(stdout, commit) { | ||
return "" | ||
} | ||
data := stdout[len(commit):] | ||
if pos := strings.IndexByte(data, '\n'); pos > 0 { | ||
return data[:pos] | ||
} | ||
return "" | ||
} | ||
|
||
func getGitRemoteUrl(name string) string { | ||
stdout, err := execCommand("git", "remote", "get-url", name) | ||
if err != nil { | ||
return "" | ||
} | ||
return stdout | ||
} | ||
|
||
func getGitBranch() string { | ||
branch, _, err := execCommand("git", "rev-parse", "--abbrev-ref", "HEAD") | ||
stdout, err := execCommand("git", "rev-parse", "--abbrev-ref", "HEAD") | ||
if err != nil { | ||
return "" | ||
} | ||
return trimRight(branch) | ||
return trimRight(stdout) | ||
} | ||
|
||
func gitTag(tag string) error { | ||
_, err := execCommand("git", "tag", tag) | ||
return err | ||
} | ||
|
||
func gitTagAndPushTo(tag string, remote, branch string) error { | ||
if err := gitRemote.PushCommits(remote, branch); err != nil { | ||
return err | ||
} | ||
if err := gitTag(tag); err != nil { | ||
return err | ||
} | ||
return gitRemote.PushCommits(remote, tag) | ||
} | ||
|
||
func gitAdd(file string) error { | ||
_, err := execCommand("git", "add", file) | ||
return err | ||
} | ||
|
||
func gitCommit(msg string) error { | ||
out, err := execCommand("git", "commit", "-a", "-m", msg) | ||
if err != nil { | ||
if e := err.(*ExecCmdError); e.Stderr == "" { | ||
e.Stderr = out | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func checkoutBranch(branch string) (string, error) { | ||
_, stderr, err := execCommand("git", "checkout", branch) | ||
return stderr, err | ||
func gitCheckoutBranch(branch string) error { | ||
_, err := execCommand("git", "checkout", branch) | ||
return err | ||
} | ||
|
||
func isGitRepo() bool { | ||
gitDir, _, err := execCommand("git", "rev-parse", "--git-dir") | ||
gitDir, err := execCommand("git", "rev-parse", "--git-dir") | ||
if err != nil { | ||
return false | ||
} | ||
|
@@ -134,11 +246,11 @@ func getBuildDateTime() string { | |
} | ||
|
||
func getBuildVer() string { | ||
tagRet, tagErr, err := execCommand("git", "describe", "--tags") | ||
if err != nil || tagErr != "" { | ||
stdout, err := execCommand("git", "describe", "--tags") | ||
if err != nil { | ||
return "" | ||
} | ||
return trimRight(tagRet) | ||
return trimRight(stdout) | ||
} | ||
|
||
func getGopBuildFlags() string { | ||
|
@@ -235,8 +347,7 @@ func buildGoplusTools(useGoProxy bool) { | |
|
||
println("Installing Go+ tools...\n") | ||
os.Chdir(commandsDir) | ||
buildOutput, buildErr, err := execCommand("go", "build", "-o", gopBinPath, "-v", "-ldflags", buildFlags, "./...") | ||
print(buildErr) | ||
buildOutput, err := execCommand("go", "build", "-o", gopBinPath, "-v", "-ldflags", buildFlags, "./...") | ||
if err != nil { | ||
log.Fatalln(err) | ||
} | ||
|
@@ -249,7 +360,7 @@ func buildGoplusTools(useGoProxy bool) { | |
|
||
println("\nGo+ tools installed successfully!") | ||
|
||
if _, _, err := execCommand("gop", "version"); err != nil { | ||
if _, err := execCommand("gop", "version"); err != nil { | ||
showHelpPostInstall(installPath) | ||
} | ||
} | ||
|
@@ -275,9 +386,8 @@ func runTestcases() { | |
os.Exit(1) | ||
} | ||
|
||
testOutput, testErr, err := execCommand(gopCommand, "test", coverage, "-covermode=atomic", "./...") | ||
testOutput, err := execCommand(gopCommand, "test", coverage, "-covermode=atomic", "./...") | ||
println(testOutput) | ||
println(testErr) | ||
if err != nil { | ||
println(err.Error()) | ||
} | ||
|
@@ -331,8 +441,8 @@ func uninstall() { | |
|
||
func isInChina() bool { | ||
const prefix = "LANG=\"" | ||
out, errMsg, err := execCommand("locale") | ||
if err != nil || errMsg != "" { | ||
out, err := execCommand("locale") | ||
if err != nil { | ||
return false | ||
} | ||
if strings.HasPrefix(out, prefix) { | ||
|
@@ -344,13 +454,12 @@ func isInChina() bool { | |
|
||
// findGopVersion returns current version of gop | ||
func findGopVersion() string { | ||
versionFile := filepath.Join(gopRoot, "VERSION") | ||
// Read version from VERSION file | ||
if checkPathExist(versionFile, false) { | ||
data, err := os.ReadFile(versionFile) | ||
if err == nil { | ||
version := trimRight(string(data)) | ||
return version | ||
} | ||
data, err := os.ReadFile(versionFile) | ||
if err == nil { | ||
version := trimRight(string(data)) | ||
return version | ||
} | ||
|
||
// Read version from git repo | ||
|
@@ -364,43 +473,54 @@ func findGopVersion() string { | |
// releaseNewVersion tags the repo with provided new tag, and writes new tag into VERSION file. | ||
func releaseNewVersion(tag string) { | ||
if !isGitRepo() { | ||
log.Fatal("Error: Releasing a new version could only be operated under a git repo.") | ||
log.Fatalln("Error: Releasing a new version could only be operated under a git repo.") | ||
} | ||
gitRemote.CheckRemoteUrl() | ||
if getTagRev(tag) != "" { | ||
log.Fatalln("Error: tag already exists -", tag) | ||
} | ||
println("Start releasing new version") | ||
|
||
version := tag | ||
|
||
re := regexp.MustCompile(`^v\d+?\.\d+?`) | ||
releaseBranch := re.FindString(version) | ||
sourceBranch := getGitBranch() | ||
|
||
if releaseBranch == "" { | ||
log.Fatal("Error: A valid version should be has form: vx.y.z") | ||
log.Fatal("Error: A valid version should be has form: vX.Y.Z") | ||
} | ||
|
||
sourceBranch := getGitBranch() | ||
|
||
// Checkout to release breanch | ||
if stderr, err := checkoutBranch(releaseBranch); err != nil { | ||
log.Fatalf("Error: checkout to release branch: %s failed with error: %v.", releaseBranch, stderr) | ||
if sourceBranch != releaseBranch { | ||
if err := gitCheckoutBranch(releaseBranch); err != nil { | ||
log.Fatalf("Error: checkout to release branch: %s failed with error: %v.", releaseBranch, err) | ||
} | ||
defer func() { | ||
// Checkout back to source branch | ||
if err := gitCheckoutBranch(sourceBranch); err != nil { | ||
log.Fatalf("Error: checkout to source branch: %s failed with error: %v.", sourceBranch, err) | ||
} | ||
gitRemote.DeleteBranch(releaseBranch) | ||
}() | ||
} | ||
|
||
fmt.Printf("\nReleasing new version: %s\n\n", version) | ||
|
||
// Cache new version | ||
versionFile := filepath.Join(gopRoot, "VERSION") | ||
if err := os.WriteFile(versionFile, []byte(version), 0644); err != nil { | ||
log.Fatalf("Error: cache new version with error: %v\n", err) | ||
} | ||
|
||
// Tag the source code | ||
if _, stderr, err := execCommand("git", "tag", version); err != nil { | ||
log.Fatalf("Error: tag the source code with error: %v\n", stderr) | ||
// Commit changes | ||
gitAdd(versionFile) | ||
if err := gitCommit("release version " + version); err != nil { | ||
log.Fatalf("Error: git commit with error: %v\n", err) | ||
} | ||
|
||
// Checkout back to source branch | ||
if stderr, err := checkoutBranch(sourceBranch); err != nil { | ||
log.Fatalf("Error: checkout to source branch: %s failed with error: %v.", sourceBranch, stderr) | ||
// Tag the source code | ||
if err := gitTagAndPushTo(tag, "gop", releaseBranch); err != nil { | ||
log.Fatalf("Error: gitTagAndPushTo with error: %v\n", err) | ||
} | ||
|
||
println("End releasing new version:", tag) | ||
println("Released new version:", version) | ||
} | ||
|
||
func main() { | ||
|
@@ -409,6 +529,7 @@ func main() { | |
isUninstall := flag.Bool("uninstall", false, "Uninstall Go+") | ||
isGoProxy := flag.Bool("proxy", false, "Set GOPROXY for people in China") | ||
isAutoProxy := flag.Bool("autoproxy", false, "Check to set GOPROXY automatically") | ||
noPush := flag.Bool("nopush", false, "Don't push to remote repo") | ||
tag := flag.String("tag", "", "Release an new version with specified tag") | ||
|
||
flag.Parse() | ||
|
@@ -428,6 +549,9 @@ func main() { | |
hasActionDone := false | ||
|
||
if *tag != "" { | ||
if *noPush { | ||
gitRemote = &gitRemoteNone{} | ||
} | ||
releaseNewVersion(*tag) | ||
hasActionDone = true | ||
} | ||
|
Oops, something went wrong.