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

Command to check Rancher dependencies for a RC #286

Merged
merged 29 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
4dfe570
change repo files
johnatasr Oct 14, 2023
e0620ec
func to check all deps and command
johnatasr Oct 17, 2023
54fbdda
add test
johnatasr Oct 17, 2023
ea323c5
last adjusts
johnatasr Oct 19, 2023
0c968b8
improve code
johnatasr Oct 19, 2023
ff54210
merge
johnatasr Oct 19, 2023
df575f1
change requires
johnatasr Oct 19, 2023
98cc14d
remove necessity of repo and org
johnatasr Oct 23, 2023
b2d1773
more improves
johnatasr Oct 26, 2023
b7444fe
more adjusts
johnatasr Oct 27, 2023
e0cf846
removing logrus
johnatasr Oct 27, 2023
b4a2ec2
adjust for message
johnatasr Oct 27, 2023
7fabcf8
adjust for message
johnatasr Oct 27, 2023
81ff6cf
add template tag
johnatasr Oct 30, 2023
f6bd50d
add template
johnatasr Oct 31, 2023
4bcb215
add more changes
johnatasr Nov 1, 2023
2e6bc03
Merge remote-tracking branch 'upstream/master' into feat-racher-relea…
johnatasr Nov 14, 2023
aae5899
using regex for rancher txt files
johnatasr Nov 14, 2023
e3b512e
add docs
johnatasr Nov 15, 2023
9422eac
Update rancher.go
johnatasr Nov 16, 2023
01b8712
remove unsed commit validation
johnatasr Nov 17, 2023
d47811b
split dev deps
johnatasr Nov 17, 2023
9683343
update doc and requires
johnatasr Nov 17, 2023
28b4198
remove unsed api url
johnatasr Nov 17, 2023
1616d52
more fixes
johnatasr Nov 23, 2023
a8d361f
remove func contents
johnatasr Nov 23, 2023
04eb84f
more adjusts
johnatasr Nov 27, 2023
1b965e6
add line and content to min version
johnatasr Nov 28, 2023
0fae92f
add rancher images export in example
johnatasr Nov 28, 2023
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
64 changes: 64 additions & 0 deletions cmd/rancher_release/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,70 @@ rancher_release label-issues -t v2.8.1-rc1 --dry-run
# [Waiting for RC] -> [To Test]
```

### check-rancher-rc-deps

This command checks Rancher by the commit hash in the selected files, verifying if they contain 'rc' and 'dev' dependencies. It generates an MD-formatted file print that can be used as a release description. If necessary, the command can generate an error if these dependencies are found, ideal for use in CI pipelines. When executed in the root of the Rancher project, it checks the `rancher-images.txt` and `rancher-windows-images.txt` files.

The pattern of files to be checked includes:
- `pkg/settings/setting.go`
- `package/Dockerfile`
- `scripts/package-env`
- `Dockerfile.dapper`
- `go.mod`
- `pkg/apis/go.mod`
- `pkg/client/go.mod`

| **Flag** | **Description** | **Required** |
| ---------------- | ----------------------------------------------------------------------------------------------------- | ------------ |
| `commit`, `c` | Required commit to find the Rancher project reference that will be executed | TRUE |
| `org`, `o` | Reference organization of the commit | FALSE |
| `repo`, `r` | Reference repository of the commit | FALSE |
| `files`, `f` | List of files to be checked by the command, they are mandatory | TRUE |
| `for-ci`, `p` | With this flag, it's possible to return an error if any of the files contain 'rc' tags or 'dev' dependencies, ideal for use in integration pipelines | FALSE |

**Examples**

```
rancher_release check-rancher-rc-deps -c <HASH_COMMIT> -f Dockerfile.dapper,go.mod,/package/Dockerfile,/pkg/apis/go.mod,/pkg/settings/setting.go,/scripts/package-env
```

```
# Images with -rc

* rancher/backup-restore-operator v4.0.0-rc1 (./bin/rancher-images.txt, line 1)
* rancher/rancher v2.8.0-rc3 (./bin/rancher-windows-images.txt, line 1)
* rancher/rancher-agent v2.8.0-rc3 (./bin/rancher-windows-images.txt, line 2)
* rancher/system-agent v0.3.4-rc1-suc (./bin/rancher-windows-images.txt, line 3)

# Components with -rc

* ENV CATTLE_KDM_BRANCH=dev-v2.8 (Dockerfile.dapper, line 16)
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
* ARG SYSTEM_CHART_DEFAULT_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* ARG CHART_DEFAULT_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* ARG CATTLE_KDM_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* KDMBranch = NewSetting("kdm-branch", "dev-v2.8") (/pkg/settings/setting.go, line 84)
* ChartDefaultBranch = NewSetting("chart-default-branch", "dev-v2.8") (/pkg/settings/setting.go, line 116)
* SYSTEM_CHART_DEFAULT_BRANCH=${SYSTEM_CHART_DEFAULT_BRANCH:-"dev-v2.8"} (/scripts/package-env, line 5)
* CHART_DEFAULT_BRANCH=${CHART_DEFAULT_BRANCH:-"dev-v2.8"} (/scripts/package-env, line 7)

# Min version components with -rc

* ENV CATTLE_FLEET_MIN_VERSION=103.1.0+up0.9.0-rc.3
* ENV CATTLE_CSP_ADAPTER_MIN_VERSION=103.0.0+up3.0.0-rc1

# Components with dev-

* ENV CATTLE_KDM_BRANCH=dev-v2.8 (Dockerfile.dapper, line 16)
* ARG SYSTEM_CHART_DEFAULT_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* ARG CHART_DEFAULT_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* ARG CATTLE_KDM_BRANCH=dev-v2.8 (/package/Dockerfile, line 1)
* KDMBranch = NewSetting("kdm-branch", "dev-v2.8") (/pkg/settings/setting.go, line 84)
* ChartDefaultBranch = NewSetting("chart-default-branch", "dev-v2.8") (/pkg/settings/setting.go, line 116)
* SYSTEM_CHART_DEFAULT_BRANCH=${SYSTEM_CHART_DEFAULT_BRANCH:-"dev-v2.8"} (/scripts/package-env, line 5)
* CHART_DEFAULT_BRANCH=${CHART_DEFAULT_BRANCH:-"dev-v2.8"} (/scripts/package-env, line 7)

```

## Contributions

- File Issue with details of the problem, feature request, etc.
Expand Down
72 changes: 72 additions & 0 deletions cmd/rancher_release/check_rancher_rc_deps.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package main

import (
"errors"

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

func checkRancherRCDepsCommand() *cli.Command {
return &cli.Command{
Name: "check-rancher-rc-deps",
Usage: "check if the Rancher version specified by the commit or pre-release title does not contain development dependencies and rc tags",
Flags: []cli.Flag{
&cli.StringFlag{
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
Name: "commit",
Aliases: []string{"c"},
Usage: "last commit for a final rc",
Required: false,
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
},
&cli.StringFlag{
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
Name: "org",
Aliases: []string{"o"},
Usage: "organization name",
Required: false,
},
&cli.StringFlag{
Name: "repo",
Aliases: []string{"r"},
Usage: "rancher repository",
Required: false,
},
&cli.StringFlag{
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
Name: "files",
Aliases: []string{"f"},
Usage: "files to be checked",
Required: true,
},
&cli.BoolFlag{
Name: "for-ci",
Aliases: []string{"p"},
Usage: "export a md template also check raising a error if contains rc tags and dev deps",
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
Required: false,
},
},
Action: checkRancherRCDeps,
}
}

func checkRancherRCDeps(c *cli.Context) error {
rcCommit := c.String("commit")
rcOrg := c.String("org")
rcRepo := c.String("repo")
rcFiles := c.String("files")
forCi := c.Bool("for-ci")

if rcCommit == "" {
return errors.New("'commit hash' are required")
}
if rcFiles == "" {
return errors.New("'files' is required, e.g, --files Dockerfile.dapper,go.mod")
}
logrus.Debugf("organization: %s, repository: %s, commit: %s, files: %s",
rcOrg, rcRepo, rcCommit, rcFiles)

err := rancher.CheckRancherRCDeps(forCi, rcOrg, rcRepo, rcCommit, rcFiles)
if err != nil {
return err
}
return nil
}
1 change: 1 addition & 0 deletions cmd/rancher_release/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func main() {
checkRancherImageCommand(),
setKDMBranchReferencesCommand(),
setChartsBranchReferencesCommand(),
checkRancherRCDepsCommand(),
labelIssuesCommand(),
}
app.Flags = rootFlags
Expand Down
181 changes: 181 additions & 0 deletions release/rancher/rancher.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,17 @@ package rancher

import (
"bufio"
"bytes"
"context"
"errors"
"fmt"
"io"
"net/http"
"os"
"regexp"
"strconv"
"strings"
"text/template"
"time"

"github.com/google/go-github/v39/github"
Expand Down Expand Up @@ -102,6 +107,40 @@ if [ "${DRY_RUN}" = false ]; then
fi`
)

const templateCheckRCDevDeps = `{{- define "componentsFile" -}}
{{- if .RancherImages }}
# Images with -rc
{{range .RancherImages}}
* {{ .Content }} ({{ .File }}, line {{ .Line }})
{{- end}}
{{- end}}

# Components with -rc
{{range .FilesWithRC}}
* {{ .Content }} ({{ .File }}, line {{ .Line }})
{{- end}}

# Min version components with -rc
{{range .MinFilesWithRC}}
* {{ .Content }}
{{- end}}

# KDM References with dev branch
{{range .KDMWithDev}}
* {{ .Content }} ({{ .File }}, line {{ .Line }})
{{- end}}

# Chart References with dev branch
{{range .ChartsWithDev}}
* {{ .Content }} ({{ .File }}, line {{ .Line }})
{{- end}}
{{ end }}`

const (
rancherRepo = "rancher"
rancherOrg = rancherRepo
)

type SetBranchReferencesArgs struct {
RancherRepoPath string
NewBranch string
Expand Down Expand Up @@ -296,3 +335,145 @@ 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
WithDev []ContentLine
}

func CheckRancherRCDeps(forCi bool, org, repo, commitHash, files string) error {
var (
matchCommitMessage bool
badFiles bool
content Content
)

devDependencyPattern := regexp.MustCompile(`dev-v[0-9]+\.[0-9]+`)
rcTagPattern := regexp.MustCompile(`-rc[0-9]+`)

httpClient := ecmHTTP.NewClient(time.Second * 15)

if repo == "" {
repo = rancherRepo
}
if org == "" {
org = rancherOrg
}

//should return data if executed in rancher project root path
err := writeRancherImagesDeps(&content, rcTagPattern)
if err != nil {
return err
}

for _, filePath := range strings.Split(files, ",") {
repoContent, err := repository.ContentByFileNameAndCommit(org, repo, commitHash, filePath, &httpClient)
if err != nil {
return err
}

scanner := bufio.NewScanner(strings.NewReader(string(repoContent)))
lineNum := 1

for scanner.Scan() {
lineByte, line := formatLineByte(scanner.Text())

if devDependencyPattern.Match(lineByte) {
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
badFiles = true
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
lineContent := ContentLine{File: filePath, Line: lineNum, Content: formatContentLine(line)}
lineContentLower := strings.ToLower(lineContent.Content)
if strings.Contains(lineContentLower, "chart") {
content.ChartsWithDev = append(content.ChartsWithDev, lineContent)
}
if strings.Contains(lineContentLower, "kdm") {
content.KDMWithDev = append(content.KDMWithDev, lineContent)
}
}
if strings.Contains(filePath, "/package/Dockerfile") {
if !strings.Contains(line, "_VERSION") {
continue
}
tashima42 marked this conversation as resolved.
Show resolved Hide resolved
matches := regexp.MustCompile(`CATTLE_(\S+)_MIN_VERSION`).FindStringSubmatch(line)
if len(matches) == 2 && strings.Contains(line, "-rc") {
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
lineContent := ContentLine{Line: lineNum, File: filePath, Content: formatContentLine(line)}
content.MinFilesWithRC = append(content.MinFilesWithRC, lineContent)
}
}
if rcTagPattern.Match(lineByte) {
badFiles = true
lineContent := ContentLine{File: filePath, Line: lineNum, Content: formatContentLine(line)}
content.FilesWithRC = append(content.FilesWithRC, lineContent)
}
lineNum++
}
if err := scanner.Err(); err != nil {
return err
}
}

tmpl := template.New("rancher-release-rc-dev-deps")
tmpl = template.Must(tmpl.Parse(templateCheckRCDevDeps))
buff := bytes.NewBuffer(nil)
err = tmpl.ExecuteTemplate(buff, "componentsFile", content)
if err != nil {
return err
}

fmt.Println(buff.String())

if forCi && matchCommitMessage && badFiles {
return errors.New("check failed, some files don't match the expected dependencies for a final release candidate")
}

return nil
}

func writeRancherImagesDeps(content *Content, rcTagPattern *regexp.Regexp) error {
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
// files below were generated in build time into rancher path
imageFiles := []string{"./bin/rancher-images.txt", "./bin/rancher-windows-images.txt"}

for _, file := range imageFiles {
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
filePath, err := os.Open(file)
if err != nil {
continue
}
defer filePath.Close()

scanner := bufio.NewScanner(filePath)
lineNumber := 1
for scanner.Scan() {
lineByte, line := formatLineByte(scanner.Text())

if rcTagPattern.Match(lineByte) {
lineContent := ContentLine{Line: lineNumber, File: file, Content: formatContentLine(line)}
content.RancherImages = append(content.RancherImages, lineContent)
}
lineNumber++
}
if err := scanner.Err(); err != nil {
return err
}
}
return nil
}

func formatContentLine(line string) string {
re := regexp.MustCompile(`\s+`)
line = re.ReplaceAllString(line, " ")
return strings.TrimSpace(line)
}

func formatLineByte(line string) ([]byte, string) {
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
johnatasr marked this conversation as resolved.
Show resolved Hide resolved
line = strings.TrimSpace(line)
return []byte(line), line
}
Loading