diff --git a/cmd/rancher_release/main.go b/cmd/rancher_release/main.go index 1780757a..2f40522c 100644 --- a/cmd/rancher_release/main.go +++ b/cmd/rancher_release/main.go @@ -30,6 +30,7 @@ func main() { listImagesRCCommand(), checkRancherImageCommand(), setKDMBranchReferencesCommand(), + setChartsBranchReferencesCommand(), } app.Flags = rootFlags diff --git a/cmd/rancher_release/set_chart_branch_references.go b/cmd/rancher_release/set_chart_branch_references.go new file mode 100644 index 00000000..f2b57c8e --- /dev/null +++ b/cmd/rancher_release/set_chart_branch_references.go @@ -0,0 +1,88 @@ +package main + +import ( + "context" + "errors" + + "github.com/rancher/ecm-distro-tools/release/rancher" + "github.com/urfave/cli/v2" +) + +func setChartsBranchReferencesCommand() *cli.Command { + return &cli.Command{ + Name: "set-charts-branch-refs", + Usage: "set charts branch references in files", + Flags: []cli.Flag{ + &cli.StringFlag{ + Name: "fork-path", + Aliases: []string{"f"}, + Usage: "rancher repo fork directory path", + Required: true, + }, + &cli.StringFlag{ + Name: "base-branch", + Aliases: []string{"b"}, + Usage: "rancher branch to use as a base, e.g: release/v2.8", + Required: true, + }, + &cli.StringFlag{ + Name: "current-charts-branch", + Aliases: []string{"c"}, + Usage: "current branch set for charts in the repo", + Required: true, + }, + &cli.StringFlag{ + Name: "new-charts-branch", + Aliases: []string{"n"}, + Usage: "branch to be replaced in charts in the repo", + Required: true, + }, + &cli.BoolFlag{ + Name: "create-pr", + Aliases: []string{"p"}, + Usage: "if true, a PR will be created from your fork to the rancher repo base branch and a variable 'GITHUB_TOKEN' must be exported", + }, + &cli.StringFlag{ + Name: "fork-owner", + Aliases: []string{"o"}, + Usage: "github username of the owner of the fork, only required if 'create-pr' is true", + Required: false, + }, + &cli.StringFlag{ + Name: "github-token", + Aliases: []string{"g"}, + Usage: "github token", + EnvVars: []string{"GITHUB_TOKEN"}, + Required: false, + }, + &cli.BoolFlag{ + Name: "dry-run", + Aliases: []string{"r"}, + Usage: "the newly created branch won't be pushed to remote and the PR won't be created", + Required: false, + }, + }, + Action: setChartBranchReferences, + } +} + +func setChartBranchReferences(c *cli.Context) error { + forkPath := c.String("fork-path") + baseBranch := c.String("base-branch") + currentBranch := c.String("current-charts-branch") + newBranch := c.String("new-charts-branch") + createPR := c.Bool("create-pr") + forkOwner := c.String("fork-owner") + githubToken := c.String("github-token") + dryRun := c.Bool("dry-run") + if createPR { + if forkOwner == "" { + return errors.New("'create-pr' requires 'fork-owner'") + } + if githubToken == "" { + return errors.New("'create-pr' requires the 'GITHUB_TOKEN' env var") + } + } + + return rancher.SetChartBranchReferences(context.Background(), forkPath, baseBranch, currentBranch, newBranch, forkOwner, githubToken, createPR, dryRun) +} diff --git a/exec/exec.go b/exec/exec.go index 2f61ce1c..e548b230 100644 --- a/exec/exec.go +++ b/exec/exec.go @@ -3,7 +3,10 @@ package exec import ( "bytes" "errors" + "os" "os/exec" + "path/filepath" + "text/template" ) func RunCommand(dir, cmd string, args ...string) (string, error) { @@ -19,3 +22,29 @@ func RunCommand(dir, cmd string, args ...string) (string, error) { return outb.String(), nil } + +func RunTemplatedScript(path, fileName, script string, args interface{}) error { + if _, err := os.Stat(path); err != nil { + return err + } + scriptPath := filepath.Join(path, fileName) + f, err := os.Create(scriptPath) + if err != nil { + return err + } + defer f.Close() + if err := os.Chmod(scriptPath, 0755); err != nil { + return err + } + tmpl, err := template.New(script).Parse(script) + if err != nil { + return err + } + if err := tmpl.Execute(f, args); err != nil { + return err + } + if _, err := RunCommand(path, "bash", "./"+fileName); err != nil { + return err + } + return nil +} diff --git a/release/rancher/rancher.go b/release/rancher/rancher.go index d78384ac..6d2354be 100644 --- a/release/rancher/rancher.go +++ b/release/rancher/rancher.go @@ -6,11 +6,8 @@ import ( "errors" "io" "net/http" - "os" - "path/filepath" "strconv" "strings" - "text/template" "time" "github.com/google/go-github/v39/github" @@ -27,49 +24,80 @@ const ( rancherImagesFileName = "/rancher-images.txt" rancherHelmRepositoryURL = "https://releases.rancher.com/server-charts/latest/index.yaml" - setKDMBranchReferencesScriptFile = "set_kdm_branch_references.sh" - setKDMBranchReferencesScript = `#!/bin/bash -set -x + setKDMBranchReferencesScriptFileName = "set_kdm_branch_references.sh" + setChartReferencesScriptFileName = `set_chart_references.sh` + cloneCheckoutRancherScript = `#!/bin/sh +set -e -BRANCH_NAME=kdm-set-{{ .NewKDMBranch }} +BRANCH_NAME={{ .BranchName }} DRY_RUN={{ .DryRun }} -cd {{ .RancherRepoDir }} -git remote add upstream https://github.com/rancher/rancher.git +cd {{ .RancherRepoPath }} +git remote -v | grep -w upstream || git remote add upstream https://github.com/rancher/rancher.git git fetch upstream git stash -git branch -D ${BRANCH_NAME} git checkout -B ${BRANCH_NAME} upstream/{{.RancherBaseBranch}} -git clean -xfd - -if [ "$(uname)" == "Darwin" ];then - sed -i '' 's/NewSetting(\"kdm-branch\", \"{{ .CurrentKDMBranch }}\")/NewSetting(\"kdm-branch\", \"{{ .NewKDMBranch }}\")/' pkg/settings/setting.go - sed -i '' 's/CATTLE_KDM_BRANCH={{ .CurrentKDMBranch }}/CATTLE_KDM_BRANCH={{ .NewKDMBranch }}/' package/Dockerfile - sed -i '' 's/CATTLE_KDM_BRANCH={{ .CurrentKDMBranch }}/CATTLE_KDM_BRANCH={{ .NewKDMBranch }}/' Dockerfile.dapper -elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then - sed -i 's/NewSetting("kdm-branch", "{{ .CurrentKDMBranch }}")/NewSetting("kdm-branch", "{{ .NewKDMBranch }}")/' pkg/settings/setting.go - sed -i 's/CATTLE_KDM_BRANCH={{ .CurrentKDMBranch }}/CATTLE_KDM_BRANCH={{ .NewKDMBranch }}/' package/Dockerfile - sed -i 's/CATTLE_KDM_BRANCH={{ .CurrentKDMBranch }}/CATTLE_KDM_BRANCH={{ .NewKDMBranch }}/' Dockerfile.dapper -else - >&2 echo "$(uname) not supported yet" +git clean -xfd` + setKDMBranchReferencesScript = ` +OS=$(uname -s) +case ${OS} in +Darwin) + sed -i '' 's/NewSetting(\"kdm-branch\", \"{{ .CurrentBranch }}\")/NewSetting(\"kdm-branch\", \"{{ .NewBranch }}\")/' pkg/settings/setting.go + sed -i '' 's/CATTLE_KDM_BRANCH={{ .CurrentBranch }}/CATTLE_KDM_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i '' 's/CATTLE_KDM_BRANCH={{ .CurrentBranch }}/CATTLE_KDM_BRANCH={{ .NewBranch }}/' Dockerfile.dapper + ;; +Linux) + sed -i 's/NewSetting("kdm-branch", "{{ .CurrentBranch }}")/NewSetting("kdm-branch", "{{ .NewBranch }}")/' pkg/settings/setting.go + sed -i 's/CATTLE_KDM_BRANCH={{ .CurrentBranch }}/CATTLE_KDM_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i 's/CATTLE_KDM_BRANCH={{ .CurrentBranch }}/CATTLE_KDM_BRANCH={{ .NewBranch }}/' Dockerfile.dapper + ;; +*) + >&2 echo "$(OS) not supported yet" exit 1 + ;; +esac fi - git add pkg/settings/setting.go git add package/Dockerfile git add Dockerfile.dapper +git commit --all --signoff -m "update kdm branch to {{ .NewBranch }}"` + setChartBranchReferencesScript = ` +OS=$(uname -s) +case ${OS} in +Darwin) + sed -i '' 's/NewSetting(\"chart-default-branch\", \"{{ .CurrentBranch }}\")/NewSetting(\"chart-default-branch\", \"{{ .NewBranch }}\")/' pkg/settings/setting.go + sed -i '' 's/SYSTEM_CHART_DEFAULT_BRANCH={{ .CurrentBranch }}/SYSTEM_CHART_DEFAULT_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i '' 's/CHART_DEFAULT_BRANCH={{ .CurrentBranch }}/CHART_DEFAULT_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i '' 's/{SYSTEM_CHART_DEFAULT_BRANCH:-"{{ .CurrentBranch }}"}/{SYSTEM_CHART_DEFAULT_BRANCH:-"{{ .NewBranch }}"}/' scripts/package-env + ;; +Linux) + sed -i 's/NewSetting("chart-default-branch", "{{ .CurrentBranch }}")/NewSetting("chart-default-branch", "{{ .NewBranch }}")/' pkg/settings/setting.go + sed -i 's/SYSTEM_CHART_DEFAULT_BRANCH={{ .CurrentBranch }}/SYSTEM_CHART_DEFAULT_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i 's/CHART_DEFAULT_BRANCH={{ .CurrentBranch }}/CHART_DEFAULT_BRANCH={{ .NewBranch }}/' package/Dockerfile + sed -i 's/{SYSTEM_CHART_DEFAULT_BRANCH:-"{{ .CurrentBranch }}"}/{SYSTEM_CHART_DEFAULT_BRANCH:-"{{ .NewBranch }}"}/' scripts/package-env + ;; +*) + >&2 echo "$(OS) not supported yet" + exit 1 + ;; +esac -git commit --all --signoff -m "update kdm branch to {{ .NewKDMBranch }}" -if [ "${DRY_RUN}" == false ]; then +git add pkg/settings/setting.go +git add package/Dockerfile +git add scripts/package-env +git commit --all --signoff -m "update chart branch references to {{ .NewBranch }}"` + pushChangesScript = ` +if [ "${DRY_RUN}" = false ]; then git push --set-upstream origin ${BRANCH_NAME} fi` ) -type SetKDMBranchReferencesArgs struct { - RancherRepoDir string - CurrentKDMBranch string - NewKDMBranch string +type SetBranchReferencesArgs struct { + RancherRepoPath string + CurrentBranch string + NewBranch string RancherBaseBranch string + BranchName string DryRun bool } @@ -183,40 +211,51 @@ func rancherHelmChartVersions(repoURL string) ([]string, error) { } func SetKDMBranchReferences(ctx context.Context, forkPath, rancherBaseBranch, currentKDMBranch, newKDMBranch, forkOwner, githubToken string, createPR, dryRun bool) error { - if _, err := os.Stat(forkPath); err != nil { - return err - } - scriptPath := filepath.Join(forkPath, setKDMBranchReferencesScriptFile) - f, err := os.Create(scriptPath) - if err != nil { - return err + branchName := "kdm-set-" + newKDMBranch + data := SetBranchReferencesArgs{ + RancherRepoPath: forkPath, + CurrentBranch: currentKDMBranch, + NewBranch: newKDMBranch, + RancherBaseBranch: rancherBaseBranch, + DryRun: dryRun, + BranchName: branchName, } - defer f.Close() - if err := os.Chmod(scriptPath, 0755); err != nil { + script := cloneCheckoutRancherScript + setKDMBranchReferencesScript + pushChangesScript + + if err := exec.RunTemplatedScript(forkPath, setKDMBranchReferencesScriptFileName, script, data); err != nil { return err } - tmpl, err := template.New(setKDMBranchReferencesScriptFile).Parse(setKDMBranchReferencesScript) - if err != nil { - return err + + if createPR && !dryRun { + ghClient := repository.NewGithub(ctx, githubToken) + + if err := createPRFromRancher(ctx, rancherBaseBranch, "Update KDM to "+newKDMBranch, branchName, forkOwner, ghClient); err != nil { + return err + } } - data := SetKDMBranchReferencesArgs{ - RancherRepoDir: forkPath, - CurrentKDMBranch: currentKDMBranch, - NewKDMBranch: newKDMBranch, + + return nil +} + +func SetChartBranchReferences(ctx context.Context, forkPath, rancherBaseBranch, currentBranch, newBranch, forkOwner, githubToken string, createPR, dryRun bool) error { + branchName := "charts-set-" + newBranch + data := SetBranchReferencesArgs{ + RancherRepoPath: forkPath, + CurrentBranch: currentBranch, + NewBranch: newBranch, RancherBaseBranch: rancherBaseBranch, DryRun: dryRun, + BranchName: branchName, } - if err := tmpl.Execute(f, data); err != nil { - return err - } - if _, err := exec.RunCommand(forkPath, "bash", "./"+setKDMBranchReferencesScriptFile); err != nil { + script := cloneCheckoutRancherScript + setChartBranchReferencesScript + pushChangesScript + if err := exec.RunTemplatedScript(forkPath, setChartReferencesScriptFileName, script, data); err != nil { return err } if createPR && !dryRun { ghClient := repository.NewGithub(ctx, githubToken) - if err := createPRFromRancher(ctx, rancherBaseBranch, newKDMBranch, forkOwner, ghClient); err != nil { + if err := createPRFromRancher(ctx, rancherBaseBranch, "Update charts branch references to "+newBranch, branchName, forkOwner, ghClient); err != nil { return err } } @@ -224,16 +263,16 @@ func SetKDMBranchReferences(ctx context.Context, forkPath, rancherBaseBranch, cu return nil } -func createPRFromRancher(ctx context.Context, rancherBaseBranch, newKDMBranch, forkOwner string, ghClient *github.Client) error { +func createPRFromRancher(ctx context.Context, rancherBaseBranch, title, branchName, forkOwner string, ghClient *github.Client) error { const repo = "rancher" org, err := repository.OrgFromRepo(repo) if err != nil { return err } pull := &github.NewPullRequest{ - Title: github.String("Update KDM Branch to " + newKDMBranch), + Title: github.String(title), Base: github.String(rancherBaseBranch), - Head: github.String(forkOwner + ":" + "kdm-set-" + newKDMBranch), + Head: github.String(forkOwner + ":" + branchName), MaintainerCanModify: github.Bool(true), } _, _, err = ghClient.PullRequests.Create(ctx, org, repo, pull)