Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#293: tag rancher release #315

Merged
merged 9 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 48 additions & 10 deletions cmd/rancher_release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ Results are printed in MD, and can be pasted into Slack, but formatting is trick

**Examples**

```
```sh
rancher_release list-nonmirrored-rc-images --tag v2.8.0-rc1
```

Expand All @@ -31,7 +31,7 @@ Checks if there’s an available Helm Chart and Docker images for amd64, arm and

**Examples**

```
```sh
rancher_release check-rancher-image --tag v2.8.0-rc1
```

Expand All @@ -56,24 +56,24 @@ Optional flags can be automatically set if you are inside your rancher fork. ⚠

**Examples**

```
```sh
rancher_release set-kdm-branch-refs -n dev-v2.8-september-patches --create-pr --dry-run
```

```
```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release set-kdm-branch-refs -n dev-v2.8-september-patches -p -r
```

```
```sh
rancher_release set-kdm-branch-refs --fork-path $GOPATH/src/github.com/{YOUR_USERNAME}/rancher \
--base-branch release/v2.8 \
--current-kdm-branch dev-v2.8 \
--new-kdm-branch dev-v2.8-september-patches
```

```
```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release set-kdm-branch-refs -f $GOPATH/src/github.com/{YOUR_USERNAME}/rancher -b release/v2.8 -c dev-v2.8 -n dev-v2.8-september-patches -p -u {YOUR_USERNAME}
Expand All @@ -100,33 +100,71 @@ Non-required flags can be automatically set, if you are inside your rancher fork

**Examples**

```
```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release set-charts-branch-refs --new-charts-branch dev-v2.9 --create-pr --dry-run
```

```
```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release set-charts-branch-refs -n dev-v2.9 -p -r
```

```
```sh
rancher_release set-charts-branch-refs --fork-path $GOPATH/src/github.com/{YOUR_USERNAME}/rancher \
--base-branch release/v2.8 \
--current-charts-branch dev-v2.8 \
--new-charts-branch dev-v2.9

```

```
```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release set-charts-branch-refs -f $GOPATH/src/github.com/{YOUR_USERNAME}/rancher -b release/v2.8 -c dev-v2.8 -n dev-v2.9 -p -o {YOUR_USERNAME}

```

### tag-release
Tags releases in GitHub for Rancher.

When tagging a new release using the `tag-release` command, always prefer to use the default behavior of creating as a draft and verifying the release in the UI before publishing it.
If you are running this locally, you'll need to generate a GitHub Token, use the fine-grained personal access token, scoped to only the rancher repo and with the `contents read and write` scope.


| **Flag** | **Description** | **Required** |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |
| `github-token`, `g`, `GITHUB_TOKEN` | GitHub generated token as described above. | TRUE |
| `tag`, `t` | The tag that you want to create. | TRUE |
| `remote-branch`, `b` | The branch which you want to create the tag against. | TRUE |
| `repo-owner`, `o` | Username of the rancher repo owner. Default is `rancher`, only customize this for testing purposes. | FALSE |
| `general-availability`, `a` | By default, the release will be created as a pre-release, before setting this as true, make sure it absolutely needs to be a GA release. | FALSE |
| `ignore-draft`, `d` | By default, the release will be created as a draft, so you can verify everything is correct before publishing it. | FALSE |
| `dry-run`, `r` | The release will not be created, just logged. | FALSE |

**Examples**

```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release tag-release --tag v2.8.0-rc1 --remote-branch release/v2.8 --dry-run
```

```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release tag-release --tag v2.8.0-rc1 --remote-branch release/v2.8 --repo-owner tashima42 --dry-run
```

```sh
export GITHUB_TOKEN={YOUR_GITHUB_TOKEN}

rancher_release tag-release -t v2.8.0 -b release/v2.8 -a -r
```


### label-issues

Given a release candidate, updates each GitHub issue belonging to its milestone with the tag `[zube]: To Test` and adds a comment with the prerelease version to test.
Expand Down
1 change: 1 addition & 0 deletions cmd/rancher_release/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ func main() {
setChartsBranchReferencesCommand(),
checkRancherRCDepsCommand(),
labelIssuesCommand(),
tagReleaseCommand(),
}
app.Flags = rootFlags

Expand Down
75 changes: 75 additions & 0 deletions cmd/rancher_release/tag_release.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package main

import (
"context"

"github.com/rancher/ecm-distro-tools/release/rancher"
"github.com/rancher/ecm-distro-tools/repository"
"github.com/urfave/cli/v2"
)

func tagReleaseCommand() *cli.Command {
return &cli.Command{
Name: "tag-release",
Usage: "tag a rancher release",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "github-token",
Aliases: []string{"g"},
EnvVars: []string{"GITHUB_TOKEN"},
Required: true,
},
&cli.StringFlag{
Name: "tag",
Aliases: []string{"t"},
Usage: "release tag",
Required: true,
},
&cli.StringFlag{
Name: "remote-branch",
Aliases: []string{"b"},
Usage: "rancher remote branch",
Required: true,
},
&cli.StringFlag{
Name: "repo-owner",
Aliases: []string{"o"},
Usage: "repo owner for the rancher repo, default is rancher, this is only used for testing purposes",
Value: "rancher",
Required: false,
},
&cli.BoolFlag{
Name: "general-availability",
Aliases: []string{"a"},
Usage: "by default, the release will be created as a pre-release, make sure it absolutely needs to be a GA release before setting this",
Required: false,
},
&cli.BoolFlag{
Name: "ignore-draft",
Aliases: []string{"d"},
Usage: "by default, the release will be created as a draft, so you can verify all information is correct before publishing it",
Required: false,
},
&cli.BoolFlag{
Name: "dry-run",
Aliases: []string{"r"},
Usage: "skip all changes that have side effects, like creating a release in a remote repo.",
Required: false,
},
},
Action: tagRelease,
}
}

func tagRelease(c *cli.Context) error {
token := c.String("github-token")
tag := c.String("tag")
remoteBranch := c.String("remote-branch")
repoOwner := c.String("repo-owner")
generalAvailability := c.Bool("general-availability")
ignoreDraft := c.Bool("ignore-draft")
dryRun := c.Bool("dry-run")
ctx := context.Background()
ghClient := repository.NewGithub(ctx, token)
return rancher.TagRancherRelease(ctx, ghClient, tag, remoteBranch, repoOwner, generalAvailability, ignoreDraft, dryRun)
}
77 changes: 60 additions & 17 deletions release/rancher/rancher.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,20 @@ import (
ecmHTTP "github.com/rancher/ecm-distro-tools/http"
"github.com/rancher/ecm-distro-tools/repository"
"github.com/sirupsen/logrus"
"golang.org/x/mod/semver"
"gopkg.in/yaml.v2"
)

const (
rancherOrg = "rancher"
rancherRepo = rancherOrg
rancherImagesBaseURL = "https://github.com/rancher/rancher/releases/download/"
rancherImagesFileName = "/rancher-images.txt"
rancherHelmRepositoryURL = "https://releases.rancher.com/server-charts/latest/index.yaml"

setKDMBranchReferencesScriptFileName = "set_kdm_branch_references.sh"
setChartReferencesScriptFileName = `set_chart_references.sh`
cloneCheckoutRancherScript = `#!/bin/sh
navigateCheckoutRancherScript = `#!/bin/sh
set -e

BRANCH_NAME={{ .BranchName }}
Expand Down Expand Up @@ -150,6 +153,20 @@ type HelmIndex struct {
} `yaml:"entries"`
}

type ContentLine struct {
Line int
File string
Content string
}

type Content struct {
RancherImages []ContentLine
FilesWithRC []ContentLine
MinFilesWithRC []ContentLine
ChartsWithDev []ContentLine
KDMWithDev []ContentLine
}

func ListRancherImagesRC(tag string) (string, error) {
downloadURL := rancherImagesBaseURL + tag + rancherImagesFileName
imagesFile, err := rancherImages(downloadURL)
Expand Down Expand Up @@ -257,7 +274,7 @@ func SetKDMBranchReferences(ctx context.Context, forkPath, rancherBaseBranch, ne
BranchName: branchName,
}

script := cloneCheckoutRancherScript + setKDMBranchReferencesScript + pushChangesScript
script := navigateCheckoutRancherScript + setKDMBranchReferencesScript + pushChangesScript
logrus.Info("running update files and apply updates script...")
output, err := exec.RunTemplatedScript(forkPath, setKDMBranchReferencesScriptFileName, script, data)
if err != nil {
Expand Down Expand Up @@ -291,7 +308,7 @@ func SetChartBranchReferences(ctx context.Context, forkPath, rancherBaseBranch,
DryRun: dryRun,
BranchName: branchName,
}
script := cloneCheckoutRancherScript + setChartBranchReferencesScript + pushChangesScript
script := navigateCheckoutRancherScript + setChartBranchReferencesScript + pushChangesScript
logrus.Info("running update files script")
output, err := exec.RunTemplatedScript(forkPath, setChartReferencesScriptFileName, script, data)
if err != nil {
Expand All @@ -317,6 +334,46 @@ func SetChartBranchReferences(ctx context.Context, forkPath, rancherBaseBranch,
return nil
}

func TagRancherRelease(ctx context.Context, ghClient *github.Client, tag, remoteBranch, repoOwner string, generalAvailability, ignoreDraft, dryRun bool) error {
logrus.Info("validating tag semver format")
if !semver.IsValid(tag) {
return errors.New("the tag `" + tag + "` isn't a valid semantic versioning string")
}
logrus.Info("getting remote branch information from " + repoOwner + "/" + rancherRepo)
branch, _, err := ghClient.Repositories.GetBranch(ctx, repoOwner, rancherRepo, remoteBranch, true)
if err != nil {
return err
}
logrus.Info("the latest commit on branch " + remoteBranch + " is: " + *branch.Commit.SHA)

createAsDraft := !ignoreDraft
createAsPrerelease := !generalAvailability
logrus.Info("creating release ")
ghRelease := github.RepositoryRelease{
TagName: github.String(tag),
Name: github.String(rancherReleaseName(generalAvailability, tag)),
Draft: &createAsDraft,
Prerelease: &createAsPrerelease,
GenerateReleaseNotes: github.Bool(false),
}
logrus.Infof("github release: %+v", ghRelease)
if dryRun {
logrus.Info("dry run, skipping release creation")
return nil
}
_, _, err = ghClient.Repositories.CreateRelease(ctx, repoOwner, rancherRepo, &ghRelease)
return err
}

func rancherReleaseName(generalAvailability bool, tag string) string {
releaseName := ""
if !generalAvailability {
releaseName += "Pre-release "
}
releaseName += tag
return releaseName
}

func createPRFromRancher(ctx context.Context, rancherBaseBranch, title, branchName, forkOwner string, ghClient *github.Client) error {
pull := &github.NewPullRequest{
Title: github.String(title),
Expand All @@ -329,20 +386,6 @@ func createPRFromRancher(ctx context.Context, rancherBaseBranch, title, branchNa
return err
}

type ContentLine struct {
Line int
File string
Content string
}

type Content struct {
RancherImages []ContentLine
FilesWithRC []ContentLine
MinFilesWithRC []ContentLine
ChartsWithDev []ContentLine
KDMWithDev []ContentLine
}

func CheckRancherRCDeps(ctx context.Context, local, forCi bool, org, repo, commitHash, files string) error {
var (
content Content
Expand Down
16 changes: 16 additions & 0 deletions release/rancher/rancher_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package rancher

import (
"errors"
"net/http"
"net/http/httptest"
"reflect"
Expand Down Expand Up @@ -59,3 +60,18 @@ func TestRancherHelmChartVersions(t *testing.T) {
t.Errorf("expected %v, got %v", expectedVersions, versions)
}
}

func TestRancherReleaseName(t *testing.T) {
const tag = "v2.8.0"
const expectedGAReleaseName = tag
const expectedPreReleaseName = "Pre-release " + tag

gaReleaseName := rancherReleaseName(true, tag)
if expectedGAReleaseName != gaReleaseName {
t.Error(errors.New("expected GA release name to be '" + expectedGAReleaseName + "' got '" + gaReleaseName + "' instead"))
}
preReleaseName := rancherReleaseName(false, tag)
if expectedPreReleaseName != preReleaseName {
t.Error(errors.New("expected GA release name to be '" + expectedPreReleaseName + "' got '" + preReleaseName + "' instead"))
}
}