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

[release-0.20] Allow project upgrades on release branch #3340

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
29 changes: 27 additions & 2 deletions tools/version-tracker/pkg/commands/display/display.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import (

// Run contains the business logic to execute the `display` subcommand.
func Run(displayOptions *types.DisplayOptions) error {
// Check if branch name environment variable has been set.
branchName, ok := os.LookupEnv(constants.BranchNameEnvVar)
if !ok {
branchName = constants.MainBranchName
}

// Check if GitHub token environment variable has been set.
githubToken, ok := os.LookupEnv("GITHUB_TOKEN")
if !ok {
Expand All @@ -40,11 +46,30 @@ func Run(displayOptions *types.DisplayOptions) error {

// Clone the eks-anywhere-build-tooling repository.
buildToolingRepoPath := filepath.Join(cwd, constants.BuildToolingRepoName)
_, _, err = git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, "")
repo, headCommit, err := git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, "", branchName)
if err != nil {
return fmt.Errorf("cloning build-tooling repo: %v", err)
}

// Get the worktree corresponding to the cloned repository.
worktree, err := repo.Worktree()
if err != nil {
return fmt.Errorf("getting repo's current worktree: %v", err)
}

// Checkout the eks-anywhere-build-tooling repo at the provided branch name.
createBranch := (branchName != constants.MainBranchName)
err = git.Checkout(worktree, branchName, createBranch)
if err != nil {
return fmt.Errorf("checking out worktree at branch %s: %v", branchName, err)
}

// Reset current worktree to get a clean index.
err = git.ResetToHEAD(worktree, headCommit)
if err != nil {
return fmt.Errorf("resetting new branch to [origin/%s] HEAD: %v", branchName, err)
}

if displayOptions.ProjectName != "" {
// Validate if the project name provided exists in the repository.
if _, err := os.Stat(filepath.Join(buildToolingRepoPath, "projects", displayOptions.ProjectName)); os.IsNotExist(err) {
Expand Down Expand Up @@ -102,7 +127,7 @@ func Run(displayOptions *types.DisplayOptions) error {
}

// Get latest revision for the project from GitHub.
latestRevision, _, err := github.GetLatestRevision(client, org, repoName, currentRevision, isTrackedByCommitHash, releaseBranched)
latestRevision, _, err := github.GetLatestRevision(client, org, repoName, currentRevision, branchName, isTrackedByCommitHash, releaseBranched)
if err != nil {
return fmt.Errorf("getting latest revision from GitHub: %v", err)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ func Run() error {
return fmt.Errorf("retrieving current working directory: %v", err)
}

// Check if branch name environment variable has been set.
branchName, ok := os.LookupEnv(constants.BranchNameEnvVar)
if !ok {
branchName = constants.MainBranchName
}

// Get base repository owner environment variable if set.
baseRepoOwner := os.Getenv(constants.BaseRepoOwnerEnvvar)
if baseRepoOwner == "" {
Expand All @@ -29,7 +35,7 @@ func Run() error {

// Clone the eks-anywhere-build-tooling repository.
buildToolingRepoPath := filepath.Join(cwd, constants.BuildToolingRepoName)
_, _, err = git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, "")
_, _, err = git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, "", branchName)
if err != nil {
return fmt.Errorf("cloning build-tooling repo: %v", err)
}
Expand Down
53 changes: 36 additions & 17 deletions tools/version-tracker/pkg/commands/upgrade/upgrade.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
projectOrg := strings.Split(projectName, "/")[0]
projectRepo := strings.Split(projectName, "/")[1]

// Check if branch name environment variable has been set.
branchName, ok := os.LookupEnv(constants.BranchNameEnvVar)
if !ok {
branchName = constants.MainBranchName
}

// Check if base repository owner environment variable has been set.
baseRepoOwner, ok := os.LookupEnv(constants.BaseRepoOwnerEnvvar)
if !ok {
Expand Down Expand Up @@ -82,7 +88,7 @@ func Run(upgradeOptions *types.UpgradeOptions) error {

// Clone the eks-anywhere-build-tooling repository.
buildToolingRepoPath := filepath.Join(cwd, constants.BuildToolingRepoName)
repo, headCommit, err := git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, headRepoOwner)
repo, headCommit, err := git.CloneRepo(fmt.Sprintf(constants.BuildToolingRepoURL, baseRepoOwner), buildToolingRepoPath, headRepoOwner, branchName)
if err != nil {
return fmt.Errorf("cloning build-tooling repo: %v", err)
}
Expand All @@ -93,23 +99,36 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
return fmt.Errorf("getting repo's current worktree: %v", err)
}

// Checkout the eks-anywhere-build-tooling repo at the provided branch name.
createBranch := (branchName != constants.MainBranchName)
err = git.Checkout(worktree, branchName, createBranch)
if err != nil {
return fmt.Errorf("checking out worktree at branch %s: %v", branchName, err)
}

// Reset current worktree to get a clean index.
err = git.ResetToHEAD(worktree, headCommit)
if err != nil {
return fmt.Errorf("resetting new branch to [origin/%s] HEAD: %v", branchName, err)
}

var headBranchName, baseBranchName, commitMessage, pullRequestBody string
if isEKSDistroUpgrade(projectName) {
headBranchName = "update-eks-distro-latest-releases"
baseBranchName = constants.MainBranchName
headBranchName = fmt.Sprintf("update-eks-distro-latest-releases-%s", branchName)
baseBranchName = branchName
commitMessage = "Bump EKS Distro releases to latest"
pullRequestBody = constants.EKSDistroUpgradePullRequestBody

// Checkout a new branch to keep track of version upgrade chaneges.
err = git.Checkout(worktree, headBranchName)
err = git.Checkout(worktree, headBranchName, true)
if err != nil {
return fmt.Errorf("checking out worktree at branch %s: %v", headBranchName, err)
}

// Reset current worktree to get a clean index.
err = git.ResetToMain(worktree, headCommit)
err = git.ResetToHEAD(worktree, headCommit)
if err != nil {
return fmt.Errorf("resetting new branch to [origin/main] HEAD: %v", err)
return fmt.Errorf("resetting new branch to [origin/%s] HEAD: %v", branchName, err)
}

isUpdated, err := updateEKSDistroReleasesFile(client, buildToolingRepoPath)
Expand Down Expand Up @@ -182,11 +201,11 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
totalPatchCount = len(patchFiles)
}

headBranchName = fmt.Sprintf("update-%s-%s", projectOrg, projectRepo)
baseBranchName = constants.MainBranchName
headBranchName = fmt.Sprintf("update-%s-%s-%s", projectOrg, projectRepo, branchName)
baseBranchName = branchName
commitMessage = fmt.Sprintf("Bump %s to latest release", projectName)
if isReleaseBranched {
headBranchName = fmt.Sprintf("update-%s-%s-%s", projectOrg, projectRepo, releaseBranch)
headBranchName = fmt.Sprintf("update-%s-%s-%s-%s", projectOrg, projectRepo, releaseBranch, branchName)
commitMessage = fmt.Sprintf("Bump %s %s release branch to latest release", projectName, releaseBranch)
}

Expand All @@ -199,7 +218,7 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
}
} else {
// Get latest revision for the project from GitHub.
latestRevision, needsUpgrade, err = github.GetLatestRevision(client, projectOrg, projectRepo, currentRevision, isTrackedByCommitHash, isReleaseBranched)
latestRevision, needsUpgrade, err = github.GetLatestRevision(client, projectOrg, projectRepo, currentRevision, branchName, isTrackedByCommitHash, isReleaseBranched)
if err != nil {
return fmt.Errorf("getting latest revision from GitHub: %v", err)
}
Expand All @@ -211,15 +230,15 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
// greater than the semver of the current version.
if needsUpgrade || slices.Contains(constants.ProjectsWithUnconventionalUpgradeFlows, projectName) {
// Checkout a new branch to keep track of version upgrade chaneges.
err = git.Checkout(worktree, headBranchName)
err = git.Checkout(worktree, headBranchName, true)
if err != nil {
return fmt.Errorf("checking out worktree at branch %s: %v", headBranchName, err)
}

// Reset current worktree to get a clean index.
err = git.ResetToMain(worktree, headCommit)
err = git.ResetToHEAD(worktree, headCommit)
if err != nil {
return fmt.Errorf("resetting new branch to [origin/main] HEAD: %v", err)
return fmt.Errorf("resetting new branch to [origin/%s] HEAD: %v", branchName, err)
}

if needsUpgrade {
Expand Down Expand Up @@ -360,7 +379,7 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
}

if projectName == "kubernetes-sigs/image-builder" {
currentBottlerocketVersion, latestBottlerocketVersion, updatedBRFiles, err := updateBottlerocketVersionFiles(client, projectRootFilepath, projectPath)
currentBottlerocketVersion, latestBottlerocketVersion, updatedBRFiles, err := updateBottlerocketVersionFiles(client, projectRootFilepath, projectPath, branchName)
if err != nil {
return fmt.Errorf("updating Bottlerocket version and metadata files: %v", err)
}
Expand All @@ -376,7 +395,7 @@ func Run(upgradeOptions *types.UpgradeOptions) error {
pullRequestBody = fmt.Sprintf(constants.CombinedImageBuilderBottlerocketUpgradePullRequestBody, currentRevision, latestRevision, currentBottlerocketVersion, latestBottlerocketVersion)
}

err = git.Checkout(worktree, headBranchName)
err = git.Checkout(worktree, headBranchName, true)
if err != nil {
return fmt.Errorf("checking out worktree at branch %s: %v", headBranchName, err)
}
Expand Down Expand Up @@ -698,7 +717,7 @@ func updateCiliumImageDigestFiles(projectRootFilepath, projectPath string) ([]st
return updateCiliumFiles, nil
}

func updateBottlerocketVersionFiles(client *gogithub.Client, projectRootFilepath, projectPath string) (string, string, []string, error) {
func updateBottlerocketVersionFiles(client *gogithub.Client, projectRootFilepath, projectPath, branchName string) (string, string, []string, error) {
updatedBRFiles := []string{}
var bottlerocketReleaseMap map[string]interface{}
bottlerocketReleasesFilePath := filepath.Join(projectRootFilepath, constants.BottlerocketReleasesFile)
Expand Down Expand Up @@ -727,7 +746,7 @@ func updateBottlerocketVersionFiles(client *gogithub.Client, projectRootFilepath
}
}

latestBottlerocketVersion, needsUpgrade, err := github.GetLatestRevision(client, "bottlerocket-os", "bottlerocket", currentBottlerocketVersion, false, false)
latestBottlerocketVersion, needsUpgrade, err := github.GetLatestRevision(client, "bottlerocket-os", "bottlerocket", currentBottlerocketVersion, branchName, false, false)
if err != nil {
return "", "", nil, fmt.Errorf("getting latest Bottlerocket version from GitHub: %v", err)
}
Expand Down
3 changes: 2 additions & 1 deletion tools/version-tracker/pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (

// Constants used across the version-tracker source code.
const (
BranchNameEnvVar = "BRANCH_NAME"
BaseRepoOwnerEnvvar = "BASE_REPO_OWNER"
HeadRepoOwnerEnvvar = "HEAD_REPO_OWNER"
GitHubTokenEnvvar = "GITHUB_TOKEN"
Expand Down Expand Up @@ -42,7 +43,7 @@ const (
GithubPerPage = 100
datetimeFormat = "%Y-%m-%dT%H:%M:%SZ"
MainBranchName = "main"
BaseRepoHeadRevision = "refs/remotes/origin/main"
BaseRepoHeadRevisionPattern = "refs/remotes/origin/%s"
EKSDistroUpgradePullRequestBody = `This PR bumps EKS Distro releases to the latest available release versions.

/hold
Expand Down
14 changes: 7 additions & 7 deletions tools/version-tracker/pkg/git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import (
)

// CloneRepo clones the remote repository to a destination folder and creates a Git remote.
func CloneRepo(cloneURL, destination, headRepoOwner string) (*git.Repository, string, error) {
func CloneRepo(cloneURL, destination, headRepoOwner, branch string) (*git.Repository, string, error) {
logger.V(6).Info(fmt.Sprintf("Cloning repository [%s] to %s directory", cloneURL, destination))
progress := io.Discard
if logger.Verbosity >= 6 {
Expand All @@ -40,9 +40,9 @@ func CloneRepo(cloneURL, destination, headRepoOwner string) (*git.Repository, st
}
}

repoHeadCommit, err := repo.ResolveRevision(plumbing.Revision(constants.BaseRepoHeadRevision))
repoHeadCommit, err := repo.ResolveRevision(plumbing.Revision(fmt.Sprintf(constants.BaseRepoHeadRevisionPattern, branch)))
if err != nil {
return nil, "", fmt.Errorf("resolving revision [%s] to commit hash: %v", constants.BaseRepoHeadRevision, err)
return nil, "", fmt.Errorf("resolving revision [%s] to commit hash: %v", fmt.Sprintf(constants.BaseRepoHeadRevisionPattern, branch), err)
}
repoHeadCommitHash := strings.Split(repoHeadCommit.String(), " ")[0]

Expand All @@ -63,8 +63,8 @@ func CloneRepo(cloneURL, destination, headRepoOwner string) (*git.Repository, st
return repo, repoHeadCommitHash, nil
}

// ResetToMain hard-resets the current working tree to point to the HEAD commit of the base repository.
func ResetToMain(worktree *git.Worktree, baseRepoHeadCommit string) error {
// ResetToHEAD hard-resets the current working tree to point to the HEAD commit of the base repository.
func ResetToHEAD(worktree *git.Worktree, baseRepoHeadCommit string) error {
err := worktree.Reset(&git.ResetOptions{
Commit: plumbing.NewHash(baseRepoHeadCommit),
Mode: git.HardReset,
Expand All @@ -77,13 +77,13 @@ func ResetToMain(worktree *git.Worktree, baseRepoHeadCommit string) error {
}

// Checkout checks out the working tree at the given branch, creating a new branch if necessary.
func Checkout(worktree *git.Worktree, branch string) error {
func Checkout(worktree *git.Worktree, branch string, create bool) error {
logger.V(6).Info(fmt.Sprintf("Checking out branch [%s] in local worktree", branch))

err := worktree.Checkout(&git.CheckoutOptions{
Branch: plumbing.NewBranchReferenceName(branch),
Keep: true,
Create: true,
Create: create,
})
if err != nil {
return fmt.Errorf("checking out branch [%s]: %v", branch, err)
Expand Down
10 changes: 8 additions & 2 deletions tools/version-tracker/pkg/github/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ func GetFileContents(client *github.Client, org, repo, filePath, ref string) ([]
}

// GetLatestRevision returns the latest revision (GitHub release or tag) for a given GitHub repository.
func GetLatestRevision(client *github.Client, org, repo, currentRevision string, isTrackedUsingCommitHash, releaseBranched bool) (string, bool, error) {
func GetLatestRevision(client *github.Client, org, repo, currentRevision, branchName string, isTrackedUsingCommitHash, releaseBranched bool) (string, bool, error) {
logger.V(6).Info(fmt.Sprintf("Getting latest revision for [%s/%s] repository", org, repo))
var currentRevisionCommit, latestRevision string
needsUpgrade := false
Expand Down Expand Up @@ -158,7 +158,13 @@ func GetLatestRevision(client *github.Client, org, repo, currentRevision string,
if releaseBranched {
releaseBranch := os.Getenv(constants.ReleaseBranchEnvvar)
releaseNumber := strings.Split(releaseBranch, "-")[1]
tagRegex := regexp.MustCompile(fmt.Sprintf(`^v?1.%s.\d$`, releaseNumber))
tagRegex := regexp.MustCompile(fmt.Sprintf(`^v?1.%s.\d+$`, releaseNumber))
if !tagRegex.MatchString(tagNameForSemver) {
continue
}
}
if branchName != constants.MainBranchName {
tagRegex := regexp.MustCompile(fmt.Sprintf(`^v%d.%d.\d+`, currentRevisionSemver.Major, currentRevisionSemver.Minor))
if !tagRegex.MatchString(tagNameForSemver) {
continue
}
Expand Down