Skip to content

Commit

Permalink
#252: Add set charts branch refs command (#271)
Browse files Browse the repository at this point in the history
* adds set charts branch refs command

* update urfave/cli to v2

* add short flags

* use urfave cli to get the github token env

* add short flags

* move branch name to after dry run

* move templated script to exec pacakge

* fix shellcheck warnings

* use sh

---------

Co-authored-by: Pedro Tashima <[email protected]>
  • Loading branch information
tashima42 and tashima42 authored Oct 13, 2023
1 parent aba9044 commit b705b0f
Show file tree
Hide file tree
Showing 4 changed files with 210 additions and 53 deletions.
1 change: 1 addition & 0 deletions cmd/rancher_release/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func main() {
listImagesRCCommand(),
checkRancherImageCommand(),
setKDMBranchReferencesCommand(),
setChartsBranchReferencesCommand(),
}
app.Flags = rootFlags

Expand Down
88 changes: 88 additions & 0 deletions cmd/rancher_release/set_chart_branch_references.go
Original file line number Diff line number Diff line change
@@ -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)
}
29 changes: 29 additions & 0 deletions exec/exec.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand All @@ -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
}
145 changes: 92 additions & 53 deletions release/rancher/rancher.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,8 @@ import (
"errors"
"io"
"net/http"
"os"
"path/filepath"
"strconv"
"strings"
"text/template"
"time"

"github.com/google/go-github/v39/github"
Expand All @@ -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
}

Expand Down Expand Up @@ -183,57 +211,68 @@ 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
}
}

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)
Expand Down

0 comments on commit b705b0f

Please sign in to comment.