diff --git a/src/centpkg/cli.py b/src/centpkg/cli.py index 3ded511..3539287 100755 --- a/src/centpkg/cli.py +++ b/src/centpkg/cli.py @@ -158,27 +158,33 @@ class centpkgClient(cliClient): stream_version = self.cmd.target.split('-')[0] rhel_version = centpkg.utils.stream_mapping(stream_version) try: - active_y, in_stabilization = centpkg.utils.determine_active_y_version(rhel_version, pp_api_url) + x_version, active_y, is_beta, in_stabilization = centpkg.utils.determine_active_y_version(rhel_version, pp_api_url) except AssertionError as e: self.log.error(" Error: centpkg cannot determine the development phase.") self.log.error(" Please file an issue at https://git.centos.org/centos/centpkg") self.log.error(" Workaround: Use the --rhel-target option") self.log.error("Exiting") raise SystemExit(1) - divergent_branch = centpkg.utils.does_divergent_branch_exist( - self.cmd.repo_name, - rhel_version, - active_y, - rhel_dist_git, - pp_api_url, - "rpms") + if is_beta: + # Special case: for X.0 betas, there will never be a prior branch + # In this case, always work on the active branch. + divergent_branch = True + else: + divergent_branch = centpkg.utils.does_divergent_branch_exist( + self.cmd.repo_name, + x_version, + active_y, + rhel_dist_git, + "rpms") # Good to know if in_stabilization : self.log.info(" we are in stabilization mode.") else: self.log.info(" we are not in stabilization mode.") - if divergent_branch : + if divergent_branch and not is_beta: self.log.info(" a divergent branch was found.") + elif divergent_branch and is_beta: + self.log.info(" we are working on a beta release.") else: self.log.info(" a divergent branch was not found.") else: @@ -253,35 +259,38 @@ class centpkgClient(cliClient): stream_version = self.cmd.target.split('-')[0] rhel_version = centpkg.utils.stream_mapping(stream_version) - # Until RHEL 10.1 is starting, set 10 to latest, by setting divergent_branch to True - if stream_version == "c10s" or rhel_version == "rhel-10": + try: + x_version, active_y, is_beta, in_stabilization = centpkg.utils.determine_active_y_version(rhel_version, pp_api_url) + except AssertionError as e: + self.log.error(" Error: centpkg cannot determine the development phase.") + self.log.error(" Please file an issue at https://git.centos.org/centos/centpkg") + self.log.error(" Workaround: Use the --rhel-target option") + self.log.error("Exiting") + raise SystemExit(1) + + if is_beta: + # Special case: for X.0 betas, there will never be a prior branch + # In this case, always work on the active branch. divergent_branch = True else: - try: - active_y, in_stabilization = centpkg.utils.determine_active_y_version(rhel_version, pp_api_url) - except AssertionError as e: - self.log.error(" Error: centpkg cannot determine the development phase.") - self.log.error(" Please file an issue at https://git.centos.org/centos/centpkg") - self.log.error(" Workaround: Use the --rhel-target option") - self.log.error("Exiting") - raise SystemExit(1) divergent_branch = centpkg.utils.does_divergent_branch_exist( self.cmd.repo_name, - rhel_version, + x_version, active_y, rhel_dist_git, - pp_api_url, "rpms") - # Good to know - if divergent_branch : - self.log.info(" a divergent branch was found.") - else: - self.log.info(" a divergent branch was not found.") - if in_stabilization : - self.log.info(" we are in stabilization mode.") - else: - self.log.info(" we are not in stabilization mode.") + # Good to know + if divergent_branch and not is_beta: + self.log.info(" a divergent branch was found.") + elif divergent_branch and is_beta: + self.log.info(" we are working on a beta release.") + else: + self.log.info(" a divergent branch was not found.") + if in_stabilization : + self.log.info(" we are in stabilization mode.") + else: + self.log.info(" we are not in stabilization mode.") # Update args.custom_user_metadata if hasattr(self.args, 'custom_user_metadata') and self.args.custom_user_metadata: diff --git a/src/centpkg/utils.py b/src/centpkg/utils.py index 7438a96..a2be10d 100644 --- a/src/centpkg/utils.py +++ b/src/centpkg/utils.py @@ -285,14 +285,22 @@ def stream_mapping(csname): return "rhel-11" return None -def does_divergent_branch_exist(repo_name, rhel_version, active_y, rhel_dist_git, pp_api_url, namespace): +def does_divergent_branch_exist(repo_name, x_version, active_y, rhel_dist_git, namespace): logger = logging.getLogger(__name__) # Determine if the Y-1 branch exists for this repo - divergent_branch = "{}.{}.0".format(rhel_version, active_y - 1) + if x_version >= 10 and active_y <= 0: + # For 10.0 and later X.0 releases, check for a rhel-X.0-beta branch + divergent_branch = "rhel-{}.0-beta".format(x_version) + elif x_version <= 9: + divergent_branch = "rhel-{}.{}.0".format(x_version, active_y - 1) + else: + # Starting with RHEL 10, the branch names have dropped the extra .0 + divergent_branch = "rhel-{}.{}".format(x_version, active_y - 1) + logger.debug("Divergent branch: {}".format(divergent_branch)) - + g = gitpython.cmd.Git() try: g.ls_remote( @@ -316,56 +324,85 @@ def _datesplit(isodate): return [ int(x) for x in date_string_tuple ] -def determine_active_y_version(rhel_version, pp_api_url): +def parse_rhel_shortname(shortname): + # The shortname is in the form rhel-9-1.0 or rhel-10.0[.beta] + m = re.match( + "rhel-(?P[0-9]+)[.-](?P[0-9]+)([.]0|[.](?P.*))?", shortname + ) + if not m: + raise RuntimeError("Could not parse version from {}".format(shortname)) + + major_version = int(m.group("major")) + minor_version = int(m.group("minor")) + extra_version = m.group("extra") or None + + return major_version, minor_version, extra_version + + +def determine_active_y_version(rhel_version, api_url): """ - Returns: A 2-tuple of the active Y-stream version(int) and whether we are - in the Exception Phase(bool) + Returns: A 4-tuple containing: + 0. The major release version(int) + 1. The active Y-stream version(int) + 2. Whether the active release is the pre-X.0 beta + 3. Whether we are in the Exception Phase(bool) """ logger = logging.getLogger(__name__) - # Query the "package pages" API for the current active Y-stream release + # Phase Identifiers # Phase 230 is "Planning / Development / Testing" (AKA DevTestDoc) # Phase 450 is "Stabilization" + phase_devtestdoc = 230 + phase_stabilization = 450 + + # Query the "package pages" API for the current active Y-stream release request_params = { - "phase__in": "230,450", + "phase__in": "{},{}".format(phase_devtestdoc, phase_stabilization), "product__shortname": "rhel", "relgroup__shortname": rhel_version, "format": "json", } res = requests.get( - os.path.join(pp_api_url, "latest", "releases"), + os.path.join(api_url, "latest", "releases"), params=request_params, timeout=60, ) res.raise_for_status() payload = json.loads(res.text) - logger.debug( - "Response from PP API: {}".format(json.dumps(payload, indent=2)) - ) + logger.debug("Response from PP API: {}".format(json.dumps(payload, indent=2))) if len(payload) < 1: - raise RuntimeError("Received zero potential release matches") + # Received zero potential release matches + logger.warning("Didn't match any active releases. Assuming pre-Beta.") + + # Fake up a Beta payload + payload = [ + { + "shortname": "{}.0.beta".format(rhel_version), + "phase": phase_devtestdoc, + } + ] - release_id = -1 active_y_version = -1 + beta = False for entry in payload: shortname = entry["shortname"] - # The shortname is in the form rhel-9-1.0 + # The shortname is in the form rhel-9-1.0 or rhel-10.0[.beta] # Extract the active Y-stream version - m = re.search("(?<={}-)\d+(?=\.0)".format(rhel_version), shortname) - if not m: - raise RuntimeError( - "Could not determine active Y-stream version from shortname" - ) - y_version = int(m.group(0)) + x_version, y_version, extra_version = parse_rhel_shortname(shortname) + if y_version > active_y_version: active_y_version = y_version - release_id = entry["id"] + beta = bool(extra_version and "beta" in extra_version) in_exception_phase = entry["phase"] == 450 - logger.debug("Active Y-stream: {}, Enforcing: {}".format(active_y_version, in_exception_phase)) + logger.debug( + "Active Y-stream: {}, Enforcing: {}, Beta: {}".format( + active_y_version, in_exception_phase, beta + ) + ) - return active_y_version, in_exception_phase + return x_version, active_y_version, beta, in_exception_phase