package main import ( "flag" "fmt" "io" "log" "os" "github.com/pkg/errors" "github.com/tinkerbell/sandbox/cmd/bump-version/envfile" "github.com/tinkerbell/sandbox/cmd/bump-version/git" "github.com/tinkerbell/sandbox/cmd/bump-version/image" ) // Config represents the flags that you can configure // when running bump-version type Config struct { // CurrentVersionFile is the path of the envfile that // contains the current version of Tinkerbell stack. // In sandbod it is called current_versions.sh CurrentVersionFile string // Overwrite switched the output of this program from // standard output to the current_versions.sh file. Overwrite bool // Help prints the help command and exists Help bool } const help = ` bump-version is an utility that reads and update the current_version.sh file. It is designed to be used in CI/CD but it works locally as well. Note: * Osie is currently not supported Examples: Prints this -help $ bump-version -help This is how you will normally run this command. bump-version will read the specified current-version-file (./current_version.sh), it will clone the various components in memory checking the latest commit available in the default branch. The command will get and validate that a docker image is available for each component and it will print the updated current_version.sh to stdout. $ bump-version -current-version-file ./current_versions.sh This command does the same as the previous one but it overwrite the content of the original current_version file $ bump-version -overwrite ` const headerFile = `#!/bin/bash # This file is generated by an utility called bump-version in # tinkerbell/sandbox. # This file gets used from generate-env.sh but it is also used standalone by # automation that wants to get the version of the programs currently supported # in sandbox ` func main() { config := Config{} fs := flag.NewFlagSet("bump-version", flag.ContinueOnError) fs.BoolVar(&config.Help, "help", false, "Display help command and exit") fs.BoolVar(&config.Overwrite, "overwrite", false, "This commands overwrite the current_versions file instead of printing to stdout") fs.StringVar(&config.CurrentVersionFile, "current-version-file", "./current_versions.sh", "Load the current_version.sh file where the current Tinkerbell component versions are specified.") err := fs.Parse(os.Args[1:]) if err != nil { fmt.Fprint(os.Stderr, help) log.Fatalf("Err: %s\n\r", err.Error()) } if config.Help { fmt.Fprint(os.Stderr, help) os.Exit(0) } // Read the current_versions envfile myEnv, err := envfile.ReadEnvFile(config.CurrentVersionFile) if err != nil { log.Fatal(errors.Wrap(err, "Impossible to read current_file.sh")) } tag, err := getImageTagFromRepo("https://github.com/tinkerbell/tink") if err != nil { log.Fatal(errors.Wrap(err, "Impossible to get image tag from tinkerbell/tink repo")) } // Set the new versions to the current_versions.sh myEnv["TINKERBELL_TINK_SERVER_IMAGE"] = "quay.io/tinkerbell/tink:" + tag myEnv["TINKERBELL_TINK_WORKER_IMAGE"] = "quay.io/tinkerbell/tink-worker:" + tag myEnv["TINKERBELL_TINK_CLI_IMAGE"] = "quay.io/tinkerbell/tink-cli:" + tag tag, err = getImageTagFromRepo("https://github.com/tinkerbell/hegel") if err != nil { log.Fatal(errors.Wrap(err, "Impossible to get image tag from tinkerbell/hegel repo")) } myEnv["TINKERBELL_TINK_HEGEL_IMAGE"] = "quay.io/tinkerbell/hegel:" + tag tag, err = getImageTagFromRepo("https://github.com/tinkerbell/boots") if err != nil { log.Fatal(errors.Wrap(err, "Impossible to get image tag from tinkerbell/hegel repo")) } myEnv["TINKERBELL_TINK_BOOTS_IMAGE"] = "quay.io/tinkerbell/boots:" + tag out, err := envfile.Marshal(myEnv) if err != nil { log.Fatal(errors.Wrap(err, "Impossible to render new current_version envfile")) } destination := os.Stdout // if the overwrite flag is set to true change the output of the command // from stdout to the original file if config.Overwrite { f, err := os.OpenFile(config.CurrentVersionFile, os.O_WRONLY|os.O_TRUNC, 0) if err != nil { log.Fatal(errors.Wrap(err, "Error overwriting current versions envfile")) } destination = f } io.WriteString(destination, headerFile+out+"\n") } // getImageTagFromRepo is an utility function that wraps a couple of things // together that technically we need to repeat for each repo. func getImageTagFromRepo(repoName string) (string, error) { // Clone the specified repository in memory repo, err := git.Clone(repoName) if err != nil { return "", errors.Wrap(err, "Impossible to clone the repository") } // Get the latest commit from the defautl branch latestCommit, err := repo.GetHeadHash() if err != nil { return "", errors.Wrap(err, "Impossible to get commit from HEAD") } // Calculate the image tag from a commit sha tag, err := image.TagFromSha(latestCommit) if err != nil { return "", errors.Wrap(err, "Impossible to get image tag from commit") } return tag, nil }