| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bufio" | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"os/exec" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"regexp" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 	"time" | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/spf13/pflag" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var opts = struct { | 
					
						
							|  |  |  | 	Version string | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 	IgnoreBranchName           bool | 
					
						
							|  |  |  | 	IgnoreUncommittedChanges   bool | 
					
						
							|  |  |  | 	IgnoreChangelogVersion     bool | 
					
						
							|  |  |  | 	IgnoreChangelogReleaseDate bool | 
					
						
							|  |  |  | 	IgnoreChangelogCurrent     bool | 
					
						
							|  |  |  | 	IgnoreDockerBuildGoVersion bool | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	OutputDir string | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | }{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var versionRegex = regexp.MustCompile(`^\d+\.\d+\.\d+$`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func init() { | 
					
						
							|  |  |  | 	pflag.BoolVar(&opts.IgnoreBranchName, "ignore-branch-name", false, "allow releasing from other branches as 'master'") | 
					
						
							|  |  |  | 	pflag.BoolVar(&opts.IgnoreUncommittedChanges, "ignore-uncommitted-changes", false, "allow uncommitted changes") | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | 	pflag.BoolVar(&opts.IgnoreChangelogVersion, "ignore-changelog-version", false, "ignore missing entry in CHANGELOG.md") | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 	pflag.BoolVar(&opts.IgnoreChangelogReleaseDate, "ignore-changelog-release-date", false, "ignore missing subdir with date in changelog/") | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | 	pflag.BoolVar(&opts.IgnoreChangelogCurrent, "ignore-changelog-current", false, "ignore check if CHANGELOG.md is up to date") | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 	pflag.BoolVar(&opts.IgnoreDockerBuildGoVersion, "ignore-docker-build-go-version", false, "ignore check if docker builder go version is up to date") | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	pflag.StringVar(&opts.OutputDir, "output-dir", "", "use `dir` as output directory") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	pflag.Parse() | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func die(f string, args ...interface{}) { | 
					
						
							|  |  |  | 	if !strings.HasSuffix(f, "\n") { | 
					
						
							|  |  |  | 		f += "\n" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	f = "\x1b[31m" + f + "\x1b[0m" | 
					
						
							|  |  |  | 	fmt.Fprintf(os.Stderr, f, args...) | 
					
						
							|  |  |  | 	os.Exit(1) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func msg(f string, args ...interface{}) { | 
					
						
							|  |  |  | 	if !strings.HasSuffix(f, "\n") { | 
					
						
							|  |  |  | 		f += "\n" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	f = "\x1b[32m" + f + "\x1b[0m" | 
					
						
							|  |  |  | 	fmt.Printf(f, args...) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func run(cmd string, args ...string) { | 
					
						
							|  |  |  | 	c := exec.Command(cmd, args...) | 
					
						
							|  |  |  | 	c.Stdout = os.Stdout | 
					
						
							|  |  |  | 	c.Stderr = os.Stderr | 
					
						
							|  |  |  | 	err := c.Run() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error running %s %s: %v", cmd, args, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | func replace(filename, from, to string) { | 
					
						
							|  |  |  | 	reg := regexp.MustCompile(from) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-02 19:36:43 +01:00
										 |  |  | 	buf, err := os.ReadFile(filename) | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error reading file %v: %v", filename, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	buf = reg.ReplaceAll(buf, []byte(to)) | 
					
						
							| 
									
										
										
										
											2022-12-02 19:36:43 +01:00
										 |  |  | 	err = os.WriteFile(filename, buf, 0644) | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error writing file %v: %v", filename, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | func rm(file string) { | 
					
						
							|  |  |  | 	err := os.Remove(file) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error removing %v: %v", file, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func rmdir(dir string) { | 
					
						
							|  |  |  | 	err := os.RemoveAll(dir) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error removing %v: %v", dir, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func mkdir(dir string) { | 
					
						
							|  |  |  | 	err := os.Mkdir(dir, 0755) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("mkdir %v: %v", dir, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func getwd() string { | 
					
						
							|  |  |  | 	pwd, err := os.Getwd() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("Getwd(): %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return pwd | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func uncommittedChanges(dirs ...string) string { | 
					
						
							|  |  |  | 	args := []string{"status", "--porcelain", "--untracked-files=no"} | 
					
						
							|  |  |  | 	if len(dirs) > 0 { | 
					
						
							|  |  |  | 		args = append(args, dirs...) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	changes, err := exec.Command("git", args...).Output() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to run command: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return string(changes) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func preCheckBranchMaster() { | 
					
						
							|  |  |  | 	if opts.IgnoreBranchName { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	branch, err := exec.Command("git", "rev-parse", "--abbrev-ref", "HEAD").Output() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error running 'git': %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-11-26 19:59:21 +01:00
										 |  |  | 	if strings.TrimSpace(string(branch)) != "master" { | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 		die("wrong branch: %s", branch) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func preCheckUncommittedChanges() { | 
					
						
							|  |  |  | 	if opts.IgnoreUncommittedChanges { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	changes := uncommittedChanges() | 
					
						
							|  |  |  | 	if len(changes) > 0 { | 
					
						
							| 
									
										
										
										
											2017-12-24 12:06:52 -05:00
										 |  |  | 		die("uncommitted changes found:\n%s\n", changes) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func preCheckVersionExists() { | 
					
						
							|  |  |  | 	buf, err := exec.Command("git", "tag", "-l").Output() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error running 'git tag -l': %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sc := bufio.NewScanner(bytes.NewReader(buf)) | 
					
						
							|  |  |  | 	for sc.Scan() { | 
					
						
							|  |  |  | 		if sc.Err() != nil { | 
					
						
							|  |  |  | 			die("error scanning version tags: %v", sc.Err()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if strings.TrimSpace(sc.Text()) == "v"+opts.Version { | 
					
						
							|  |  |  | 			die("tag v%v already exists", opts.Version) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | func preCheckChangelogCurrent() { | 
					
						
							|  |  |  | 	if opts.IgnoreChangelogCurrent { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// regenerate changelog | 
					
						
							|  |  |  | 	run("calens", "--output", "CHANGELOG.md") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// check for uncommitted changes in changelog | 
					
						
							|  |  |  | 	if len(uncommittedChanges("CHANGELOG.md")) > 0 { | 
					
						
							|  |  |  | 		msg("committing file CHANGELOG.md") | 
					
						
							|  |  |  | 		run("git", "commit", "-m", fmt.Sprintf("Generate CHANGELOG.md for %v", opts.Version), "CHANGELOG.md") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | func preCheckChangelogRelease() bool { | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 	if opts.IgnoreChangelogReleaseDate { | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 		return true | 
					
						
							| 
									
										
										
										
											2017-12-27 23:32:11 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 	for _, name := range readdir("changelog") { | 
					
						
							|  |  |  | 		if strings.HasPrefix(name, opts.Version+"_") { | 
					
						
							|  |  |  | 			return true | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2017-12-27 23:32:11 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 	return false | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-12-27 23:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | func createChangelogRelease() { | 
					
						
							|  |  |  | 	date := time.Now().Format("2006-01-02") | 
					
						
							| 
									
										
										
										
											2020-11-05 10:26:00 +01:00
										 |  |  | 	targetDir := filepath.Join("changelog", fmt.Sprintf("%s_%s", opts.Version, date)) | 
					
						
							|  |  |  | 	unreleasedDir := filepath.Join("changelog", "unreleased") | 
					
						
							|  |  |  | 	mkdir(targetDir) | 
					
						
							| 
									
										
										
										
											2017-12-27 23:32:11 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 10:26:00 +01:00
										 |  |  | 	for _, name := range readdir(unreleasedDir) { | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 		if name == ".gitignore" { | 
					
						
							|  |  |  | 			continue | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		src := filepath.Join("changelog", "unreleased", name) | 
					
						
							| 
									
										
										
										
											2020-11-05 10:26:00 +01:00
										 |  |  | 		dest := filepath.Join(targetDir, name) | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		err := os.Rename(src, dest) | 
					
						
							|  |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			die("rename %v -> %v failed: %w", src, dest, err) | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-05 10:26:00 +01:00
										 |  |  | 	run("git", "add", targetDir) | 
					
						
							|  |  |  | 	run("git", "add", "-u", unreleasedDir) | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	msg := fmt.Sprintf("Prepare changelog for %v", opts.Version) | 
					
						
							| 
									
										
										
										
											2020-11-05 10:26:00 +01:00
										 |  |  | 	run("git", "commit", "-m", msg, targetDir, unreleasedDir) | 
					
						
							| 
									
										
										
										
											2017-12-27 23:32:11 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | func preCheckChangelogVersion() { | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	if opts.IgnoreChangelogVersion { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f, err := os.Open("CHANGELOG.md") | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to open CHANGELOG.md: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2021-01-30 19:35:46 +01:00
										 |  |  | 	defer func() { | 
					
						
							|  |  |  | 		_ = f.Close() | 
					
						
							|  |  |  | 	}() | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	sc := bufio.NewScanner(f) | 
					
						
							|  |  |  | 	for sc.Scan() { | 
					
						
							|  |  |  | 		if sc.Err() != nil { | 
					
						
							|  |  |  | 			die("error scanning: %v", sc.Err()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | 		if strings.Contains(strings.TrimSpace(sc.Text()), fmt.Sprintf("Changelog for restic %v", opts.Version)) { | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 			return | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	die("CHANGELOG.md does not contain version %v", opts.Version) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 22:31:39 +01:00
										 |  |  | func preCheckDockerBuilderGoVersion() { | 
					
						
							| 
									
										
										
										
											2018-02-16 23:13:02 +01:00
										 |  |  | 	if opts.IgnoreDockerBuildGoVersion { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-16 22:31:39 +01:00
										 |  |  | 	buf, err := exec.Command("go", "version").Output() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to check local Go version: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	localVersion := strings.TrimSpace(string(buf)) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	msg("update docker container restic/builder") | 
					
						
							| 
									
										
										
										
											2018-02-16 22:31:39 +01:00
										 |  |  | 	run("docker", "pull", "restic/builder") | 
					
						
							| 
									
										
										
										
											2018-02-17 19:10:32 +01:00
										 |  |  | 	buf, err = exec.Command("docker", "run", "--rm", "restic/builder", "go", "version").Output() | 
					
						
							| 
									
										
										
										
											2018-02-16 22:31:39 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to check Go version in docker image: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	containerVersion := strings.TrimSpace(string(buf)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if localVersion != containerVersion { | 
					
						
							|  |  |  | 		die("version in docker container restic/builder is different:\n  local:     %v\n  container: %v\n", | 
					
						
							|  |  |  | 			localVersion, containerVersion) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | func generateFiles() { | 
					
						
							|  |  |  | 	msg("generate files") | 
					
						
							|  |  |  | 	run("go", "run", "build.go", "-o", "restic-generate.temp") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	mandir := filepath.Join("doc", "man") | 
					
						
							|  |  |  | 	rmdir(mandir) | 
					
						
							|  |  |  | 	mkdir(mandir) | 
					
						
							|  |  |  | 	run("./restic-generate.temp", "generate", | 
					
						
							|  |  |  | 		"--man", "doc/man", | 
					
						
							|  |  |  | 		"--zsh-completion", "doc/zsh-completion.zsh", | 
					
						
							| 
									
										
										
										
											2022-09-11 00:44:12 +02:00
										 |  |  | 		"--powershell-completion", "doc/powershell-completion.ps1", | 
					
						
							| 
									
										
										
										
											2021-03-01 13:15:59 +11:00
										 |  |  | 		"--fish-completion", "doc/fish-completion.fish", | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 		"--bash-completion", "doc/bash-completion.sh") | 
					
						
							|  |  |  | 	rm("restic-generate.temp") | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | 	run("git", "add", "doc") | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	changes := uncommittedChanges("doc") | 
					
						
							|  |  |  | 	if len(changes) > 0 { | 
					
						
							| 
									
										
										
										
											2017-12-24 12:06:52 -05:00
										 |  |  | 		msg("committing manpages and auto-completion") | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 		run("git", "commit", "-m", "Update manpages and auto-completion", "doc") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | var versionPattern = `var version = ".*"` | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const versionCodeFile = "cmd/restic/global.go" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | func updateVersion() { | 
					
						
							| 
									
										
										
										
											2022-12-02 19:36:43 +01:00
										 |  |  | 	err := os.WriteFile("VERSION", []byte(opts.Version+"\n"), 0644) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to write version to file: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | 	newVersion := fmt.Sprintf("var version = %q", opts.Version) | 
					
						
							|  |  |  | 	replace(versionCodeFile, versionPattern, newVersion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if len(uncommittedChanges("VERSION")) > 0 || len(uncommittedChanges(versionCodeFile)) > 0 { | 
					
						
							|  |  |  | 		msg("committing version files") | 
					
						
							|  |  |  | 		run("git", "commit", "-m", fmt.Sprintf("Add version for %v", opts.Version), "VERSION", versionCodeFile) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | func updateVersionDev() { | 
					
						
							|  |  |  | 	newVersion := fmt.Sprintf(`var version = "%s-dev (compiled manually)"`, opts.Version) | 
					
						
							|  |  |  | 	replace(versionCodeFile, versionPattern, newVersion) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	msg("committing cmd/restic/global.go with dev version") | 
					
						
							|  |  |  | 	run("git", "commit", "-m", fmt.Sprintf("Set development version for %v", opts.Version), "VERSION", versionCodeFile) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | func addTag() { | 
					
						
							|  |  |  | 	tagname := "v" + opts.Version | 
					
						
							|  |  |  | 	msg("add tag %v", tagname) | 
					
						
							|  |  |  | 	run("git", "tag", "-a", "-s", "-m", tagname, tagname) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | func exportTar(version, tarFilename string) { | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	cmd := fmt.Sprintf("git archive --format=tar --prefix=restic-%s/ v%s | gzip -n > %s", | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 		version, version, tarFilename) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	run("sh", "-c", cmd) | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	msg("build restic-%s.tar.gz", version) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | func extractTar(filename, outputDir string) { | 
					
						
							|  |  |  | 	msg("extract tar into %v", outputDir) | 
					
						
							|  |  |  | 	c := exec.Command("tar", "xz", "--strip-components=1", "-f", filename) | 
					
						
							|  |  |  | 	c.Stdout = os.Stdout | 
					
						
							|  |  |  | 	c.Stderr = os.Stderr | 
					
						
							|  |  |  | 	c.Dir = outputDir | 
					
						
							|  |  |  | 	err := c.Run() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error extracting tar: %v", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:45:13 +02:00
										 |  |  | func runBuild(sourceDir, outputDir, version string) { | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	msg("building binaries...") | 
					
						
							|  |  |  | 	run("docker", "run", "--rm", | 
					
						
							|  |  |  | 		"--volume", sourceDir+":/restic", | 
					
						
							|  |  |  | 		"--volume", outputDir+":/output", | 
					
						
							| 
									
										
										
										
											2018-10-13 13:45:13 +02:00
										 |  |  | 		"restic/builder", | 
					
						
							| 
									
										
										
										
											2020-03-01 11:32:36 +01:00
										 |  |  | 		"go", "run", "helpers/build-release-binaries/main.go", | 
					
						
							| 
									
										
										
										
											2018-10-13 13:45:13 +02:00
										 |  |  | 		"--version", version) | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | func readdir(dir string) []string { | 
					
						
							| 
									
										
										
										
											2022-12-02 19:42:19 +01:00
										 |  |  | 	fis, err := os.ReadDir(dir) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 		die("readdir %v failed: %v", dir, err) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	filenames := make([]string, 0, len(fis)) | 
					
						
							|  |  |  | 	for _, fi := range fis { | 
					
						
							|  |  |  | 		filenames = append(filenames, fi.Name()) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	return filenames | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | func sha256sums(inputDir, outputFile string) { | 
					
						
							|  |  |  | 	msg("runnnig sha256sum in %v", inputDir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	filenames := readdir(inputDir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f, err := os.Create(outputFile) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 		die("unable to create %v: %v", outputFile, err) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	c := exec.Command("sha256sum", filenames...) | 
					
						
							|  |  |  | 	c.Stdout = f | 
					
						
							|  |  |  | 	c.Stderr = os.Stderr | 
					
						
							|  |  |  | 	c.Dir = inputDir | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	err = c.Run() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("error running sha256sums: %v", err) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	err = f.Close() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("close %v: %v", outputFile, err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | func signFiles(filenames ...string) { | 
					
						
							|  |  |  | 	for _, filename := range filenames { | 
					
						
							|  |  |  | 		run("gpg", "--armor", "--detach-sign", filename) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:16:29 +02:00
										 |  |  | func updateDocker(outputDir, version string) string { | 
					
						
							|  |  |  | 	run("docker", "buildx", "create", "--name", "restic-release-builder", "--driver", "docker-container", "--bootstrap") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	cmds := "" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, tag := range []string{"restic/restic:latest", "restic/restic:" + version} { | 
					
						
							|  |  |  | 		cmd := fmt.Sprintf("docker buildx build --builder restic-release-builder --platform linux/386,linux/amd64,linux/arm,linux/arm64 --pull --tag %q -f docker/Dockerfile.release --build-arg VERSION=%q %q", tag, version, outputDir) | 
					
						
							|  |  |  | 		run("sh", "-c", cmd) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		cmds += cmd + " --push\n" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return cmds + "\ndocker buildx rm restic-release-builder" | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func tempdir(prefix string) string { | 
					
						
							| 
									
										
										
										
											2022-12-02 19:36:43 +01:00
										 |  |  | 	dir, err := os.MkdirTemp(getwd(), prefix) | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		die("unable to create temp dir %q: %v", prefix, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return dir | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func main() { | 
					
						
							|  |  |  | 	if len(pflag.Args()) == 0 { | 
					
						
							|  |  |  | 		die("USAGE: release-version [OPTIONS] VERSION") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	opts.Version = pflag.Args()[0] | 
					
						
							|  |  |  | 	if !versionRegex.MatchString(opts.Version) { | 
					
						
							|  |  |  | 		die("invalid new version") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	preCheckBranchMaster() | 
					
						
							|  |  |  | 	preCheckUncommittedChanges() | 
					
						
							|  |  |  | 	preCheckVersionExists() | 
					
						
							| 
									
										
										
										
											2018-02-16 22:31:39 +01:00
										 |  |  | 	preCheckDockerBuilderGoVersion() | 
					
						
							| 
									
										
										
										
											2020-11-05 09:39:06 +01:00
										 |  |  | 	if !preCheckChangelogRelease() { | 
					
						
							|  |  |  | 		createChangelogRelease() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2018-02-16 21:52:34 +01:00
										 |  |  | 	preCheckChangelogCurrent() | 
					
						
							| 
									
										
										
										
											2017-12-25 22:26:42 +01:00
										 |  |  | 	preCheckChangelogVersion() | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	if opts.OutputDir == "" { | 
					
						
							|  |  |  | 		opts.OutputDir = tempdir("build-output-") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	sourceDir := tempdir("source-") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	msg("using output dir %v", opts.OutputDir) | 
					
						
							|  |  |  | 	msg("using source dir %v", sourceDir) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 	generateFiles() | 
					
						
							|  |  |  | 	updateVersion() | 
					
						
							|  |  |  | 	addTag() | 
					
						
							| 
									
										
										
										
											2018-08-17 20:45:32 +02:00
										 |  |  | 	updateVersionDev() | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	tarFilename := filepath.Join(opts.OutputDir, fmt.Sprintf("restic-%s.tar.gz", opts.Version)) | 
					
						
							|  |  |  | 	exportTar(opts.Version, tarFilename) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	extractTar(tarFilename, sourceDir) | 
					
						
							| 
									
										
										
										
											2018-10-13 13:45:13 +02:00
										 |  |  | 	runBuild(sourceDir, opts.OutputDir, opts.Version) | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	rmdir(sourceDir) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sha256sums(opts.OutputDir, filepath.Join(opts.OutputDir, "SHA256SUMS")) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	signFiles(filepath.Join(opts.OutputDir, "SHA256SUMS"), tarFilename) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:16:29 +02:00
										 |  |  | 	dockerCmds := updateDocker(opts.OutputDir, opts.Version) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-10-13 13:05:13 +02:00
										 |  |  | 	msg("done, output dir is %v", opts.OutputDir) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 17:16:29 +02:00
										 |  |  | 	msg("now run:\n\ngit push --tags origin master\n%s\n", dockerCmds) | 
					
						
							| 
									
										
										
										
											2017-09-26 14:15:39 +02:00
										 |  |  | } |