diff --git a/Makefile b/Makefile index b78235fe74..877ba952dc 100644 --- a/Makefile +++ b/Makefile @@ -254,3 +254,7 @@ ensure-locale: exporting LANG=C.UTF-8 to generate files instead.; \ fi; \ fi + +.PHONY: get-default-release-branch +get-default-release-branch: + @echo $(LATEST_EKSD_RELEASE) diff --git a/tools/version-tracker/pkg/commands/upgrade/upgrade.go b/tools/version-tracker/pkg/commands/upgrade/upgrade.go index e04d854ad8..22c5b251fb 100644 --- a/tools/version-tracker/pkg/commands/upgrade/upgrade.go +++ b/tools/version-tracker/pkg/commands/upgrade/upgrade.go @@ -136,18 +136,24 @@ func Run(upgradeOptions *types.UpgradeOptions) error { // Validate whether the given project is release-branched. var isReleaseBranched bool - var releaseBranch string var currentVersion types.Version var versionIndex int if len(targetRepo.Versions) > 1 { isReleaseBranched = true } + releaseBranch := os.Getenv(constants.ReleaseBranchEnvvar) + if releaseBranch == "" { + releaseBranch, err = getDefaultReleaseBranch(buildToolingRepoPath) + if err != nil { + return fmt.Errorf("getting default EKS Distro release branch: %v", err) + } + } if isReleaseBranched { supportedReleaseBranches, err := getSupportedReleaseBranches(buildToolingRepoPath) if err != nil { return fmt.Errorf("getting supported EKS Distro release branches: %v", err) } - releaseBranch = os.Getenv(constants.ReleaseBranchEnvvar) + versionIndex = slices.Index(supportedReleaseBranches, releaseBranch) } else { versionIndex = 0 @@ -296,7 +302,7 @@ func Run(upgradeOptions *types.UpgradeOptions) error { // If project has patches, attempt to apply them. Track failed patches and files that failed to apply, if any. if projectHasPatches { - appliedPatchesCount, failedPatch, applyFailedFiles, err := applyPatchesToRepo(projectRootFilepath, projectRepo, latestRevision, totalPatchCount) + appliedPatchesCount, failedPatch, applyFailedFiles, err := applyPatchesToRepo(projectRootFilepath, projectRepo, releaseBranch, totalPatchCount) if appliedPatchesCount == totalPatchCount { patchApplySucceeded = true } @@ -601,12 +607,12 @@ func updateUpstreamProjectsTrackerFile(projectsList *types.ProjectsList, targetR // applyPatchesToRepo runs a Make command to apply patches to the cloned repository of the project // being upgraded. -func applyPatchesToRepo(projectRootFilepath, projectRepo, latestVersion string, totalPatchCount int) (int, string, string, error) { +func applyPatchesToRepo(projectRootFilepath, projectRepo, releaseBranch string, totalPatchCount int) (int, string, string, error) { var patchesApplied int var failedPatch, failedFilesInPatch string patchApplySucceeded := true - applyPatchesCommandSequence := fmt.Sprintf("make -C %s patch-repo", projectRootFilepath) + applyPatchesCommandSequence := fmt.Sprintf("RELEASE_BRANCH=%s make -C %s patch-repo", releaseBranch, projectRootFilepath) applyPatchesCmd := exec.Command("bash", "-c", applyPatchesCommandSequence) applyPatchesOutput, err := command.ExecCommand(applyPatchesCmd) if err != nil { @@ -884,3 +890,14 @@ func updateBottlerocketHostContainerMetadata(client *gogithub.Client, projectRoo func isEKSDistroUpgrade(projectName string) bool { return projectName == "aws/eks-distro" } + +func getDefaultReleaseBranch(buildToolingRepoPath string) (string, error) { + defaultReleaseBranchCommandSequence := fmt.Sprintf("make -C %s get-default-release-branch", buildToolingRepoPath) + defaultReleaseBranchCmd := exec.Command("bash", "-c", defaultReleaseBranchCommandSequence) + defaultReleaseBranch, err := command.ExecCommand(defaultReleaseBranchCmd) + if err != nil { + return "", fmt.Errorf("running get-default-release-branch Make command: %v", err) + } + + return defaultReleaseBranch, nil +} diff --git a/tools/version-tracker/pkg/constants/constants.go b/tools/version-tracker/pkg/constants/constants.go index ea1c41953a..c41bfbce13 100644 --- a/tools/version-tracker/pkg/constants/constants.go +++ b/tools/version-tracker/pkg/constants/constants.go @@ -269,6 +269,10 @@ var ( SourceOfTruthFile: "go.mod", GoVersionSearchString: `go (1\.\d\d)`, }, + "prometheus/prometheus": { + SourceOfTruthFile: ".promu.yml", + GoVersionSearchString: `version: (1\.\d\d)`, + }, "tinkerbell/boots": { SourceOfTruthFile: "go.mod", GoVersionSearchString: `go (1\.\d\d)`, diff --git a/tools/version-tracker/pkg/github/github.go b/tools/version-tracker/pkg/github/github.go index c9ba0ddc60..832a97f27f 100644 --- a/tools/version-tracker/pkg/github/github.go +++ b/tools/version-tracker/pkg/github/github.go @@ -4,6 +4,7 @@ import ( "context" "encoding/base64" "fmt" + "net/http" "os" "path/filepath" "regexp" @@ -237,93 +238,33 @@ func getCommitForTag(allTags []*github.RepositoryTag, searchTag string) string { // GetGoVersionForLatestRevision gets the Go version used to build the latest revision of the project. func GetGoVersionForLatestRevision(client *github.Client, org, repo, latestRevision string) (string, error) { logger.V(6).Info(fmt.Sprintf("Getting Go version corresponding to latest revision %s for [%s/%s] repository", latestRevision, org, repo)) - cwd, err := os.Getwd() - if err != nil { - return "", fmt.Errorf("retrieving current working directory: %v", err) - } var goVersion string + var err error projectFullName := fmt.Sprintf("%s/%s", org, repo) if _, ok := constants.ProjectReleaseAssets[projectFullName]; ok { - release, _, err := client.Repositories.GetReleaseByTag(context.Background(), org, repo, latestRevision) + release, response, err := client.Repositories.GetReleaseByTag(context.Background(), org, repo, latestRevision) if err != nil { - return "", fmt.Errorf("calling GetReleaseByTag API for tag %s in [%s/%s] repository: %v", latestRevision, org, repo, err) - } - var tarballName, tarballUrl string - projectReleaseAsset := constants.ProjectReleaseAssets[projectFullName] - searchAssetName := projectReleaseAsset.AssetName - assetVersionReplacement := latestRevision - if constants.ProjectReleaseAssets[projectFullName].TrimLeadingVersionPrefix { - assetVersionReplacement = latestRevision[1:] - } - if strings.Count(searchAssetName, "%s") > 0 { - searchAssetName = fmt.Sprintf(searchAssetName, assetVersionReplacement) - } - if projectReleaseAsset.OverrideAssetURL != "" { - tarballName = searchAssetName - tarballUrl = projectReleaseAsset.OverrideAssetURL - if strings.Count(tarballUrl, "%s") > 0 { - tarballUrl = fmt.Sprintf(tarballUrl, assetVersionReplacement) - } - } else { - for _, asset := range release.Assets { - if *asset.Name == searchAssetName { - tarballName = *asset.Name - tarballUrl = *asset.BrowserDownloadURL - break + if response.StatusCode == http.StatusNotFound { + logger.V(6).Info(fmt.Sprintf("GitHub release for tag %s not found. Falling back to GitHub source of truth file for Go version", latestRevision)) + goVersion, err = getGoVersionFromGitHubFile(client, org, repo, projectFullName, latestRevision) + if err != nil { + return "", fmt.Errorf("getting Go version from GitHub source of truth file: %v", err) } + } else { + return "", fmt.Errorf("calling GetReleaseByTag API for tag %s in [%s/%s] repository: %v", latestRevision, org, repo, err) } - } - - tarballDownloadPath := filepath.Join(cwd, "github-release-downloads") - err = os.MkdirAll(tarballDownloadPath, 0o755) - if err != nil { - return "", fmt.Errorf("failed to create GitHub release downloads folder: %v", err) - } - tarballFilePath := filepath.Join(tarballDownloadPath, tarballName) - - err = file.Download(tarballUrl, tarballFilePath) - if err != nil { - return "", fmt.Errorf("downloading release tarball from URL [%s]: %v", tarballUrl, err) - } - - binaryName := projectReleaseAsset.BinaryName - if strings.Count(binaryName, "%s") > 0 { - binaryName = fmt.Sprintf(binaryName, assetVersionReplacement) - } - if projectReleaseAsset.Extract { - tarballFile, err := os.Open(tarballFilePath) - if err != nil { - return "", fmt.Errorf("opening tarball filepath: %v", err) - } - - err = tar.ExtractFileFromTarball(tarballDownloadPath, tarballFile, binaryName) + } else { + goVersion, err = getGoVersionFromGitHubRelease(release, projectFullName, latestRevision) if err != nil { - return "", fmt.Errorf("extracting tarball file: %v", err) + return "", fmt.Errorf("getting Go version from GitHub release assets: %v", err) } } - - binaryFilePath := filepath.Join(tarballDownloadPath, binaryName) - goVersion, err = version.GetGoVersion(binaryFilePath) - if err != nil { - return "", fmt.Errorf("getting Go version embedded in binary [%s]: %v", binaryFilePath, err) - } - - err = os.RemoveAll(tarballDownloadPath) - if err != nil { - return "", fmt.Errorf("removing tarball download path: %v", err) - } } else if _, ok := constants.ProjectGoVersionSourceOfTruth[projectFullName]; ok { - projectGoVersionSourceOfTruthFile := constants.ProjectGoVersionSourceOfTruth[projectFullName].SourceOfTruthFile - workflowContents, err := GetFileContents(client, org, repo, projectGoVersionSourceOfTruthFile, latestRevision) + goVersion, err = getGoVersionFromGitHubFile(client, org, repo, projectFullName, latestRevision) if err != nil { - return "", fmt.Errorf("getting contents of file [%s]: %v", projectGoVersionSourceOfTruthFile, err) + return "", fmt.Errorf("getting Go version from GitHub source of truth file: %v", err) } - - pattern := regexp.MustCompile(constants.ProjectGoVersionSourceOfTruth[projectFullName].GoVersionSearchString) - matches := pattern.FindStringSubmatch(string(workflowContents)) - - goVersion = matches[1] } return goVersion, nil @@ -400,3 +341,90 @@ func CreatePullRequest(client *github.Client, org, repo, title, body, baseRepoOw return nil } + +func getGoVersionFromGitHubRelease(release *github.RepositoryRelease, projectFullName, latestRevision string) (string, error) { + var tarballName, tarballUrl string + projectReleaseAsset := constants.ProjectReleaseAssets[projectFullName] + searchAssetName := projectReleaseAsset.AssetName + assetVersionReplacement := latestRevision + if constants.ProjectReleaseAssets[projectFullName].TrimLeadingVersionPrefix { + assetVersionReplacement = latestRevision[1:] + } + if strings.Count(searchAssetName, "%s") > 0 { + searchAssetName = fmt.Sprintf(searchAssetName, assetVersionReplacement) + } + if projectReleaseAsset.OverrideAssetURL != "" { + tarballName = searchAssetName + tarballUrl = projectReleaseAsset.OverrideAssetURL + if strings.Count(tarballUrl, "%s") > 0 { + tarballUrl = fmt.Sprintf(tarballUrl, assetVersionReplacement) + } + } else { + for _, asset := range release.Assets { + if *asset.Name == searchAssetName { + tarballName = *asset.Name + tarballUrl = *asset.BrowserDownloadURL + break + } + } + } + + cwd, err := os.Getwd() + if err != nil { + return "", fmt.Errorf("retrieving current working directory: %v", err) + } + + tarballDownloadPath := filepath.Join(cwd, "github-release-downloads") + err = os.MkdirAll(tarballDownloadPath, 0o755) + if err != nil { + return "", fmt.Errorf("failed to create GitHub release downloads folder: %v", err) + } + tarballFilePath := filepath.Join(tarballDownloadPath, tarballName) + + err = file.Download(tarballUrl, tarballFilePath) + if err != nil { + return "", fmt.Errorf("downloading release tarball from URL [%s]: %v", tarballUrl, err) + } + + binaryName := projectReleaseAsset.BinaryName + if strings.Count(binaryName, "%s") > 0 { + binaryName = fmt.Sprintf(binaryName, assetVersionReplacement) + } + if projectReleaseAsset.Extract { + tarballFile, err := os.Open(tarballFilePath) + if err != nil { + return "", fmt.Errorf("opening tarball filepath: %v", err) + } + + err = tar.ExtractFileFromTarball(tarballDownloadPath, tarballFile, binaryName) + if err != nil { + return "", fmt.Errorf("extracting tarball file: %v", err) + } + } + + binaryFilePath := filepath.Join(tarballDownloadPath, binaryName) + goVersion, err := version.GetGoVersion(binaryFilePath) + if err != nil { + return "", fmt.Errorf("getting Go version embedded in binary [%s]: %v", binaryFilePath, err) + } + + err = os.RemoveAll(tarballDownloadPath) + if err != nil { + return "", fmt.Errorf("removing tarball download path: %v", err) + } + + return goVersion, nil +} + +func getGoVersionFromGitHubFile(client *github.Client, org, repo, projectFullName, latestRevision string) (string, error) { + projectGoVersionSourceOfTruthFile := constants.ProjectGoVersionSourceOfTruth[projectFullName].SourceOfTruthFile + workflowContents, err := GetFileContents(client, org, repo, projectGoVersionSourceOfTruthFile, latestRevision) + if err != nil { + return "", fmt.Errorf("getting contents of file [%s]: %v", projectGoVersionSourceOfTruthFile, err) + } + + pattern := regexp.MustCompile(constants.ProjectGoVersionSourceOfTruth[projectFullName].GoVersionSearchString) + matches := pattern.FindStringSubmatch(string(workflowContents)) + + return matches[1], nil +}