def get_status_changes()

in bugbot/rules/regression_set_status_flags.py [0:0]


    def get_status_changes(self, bugs):
        bugids = {info["regressed_by"] for info in bugs.values()}
        if not bugids:
            return {}

        data = self.get_flags_from_regressing_bugs(bugids)

        filtered_bugs = {}
        for bugid, info in bugs.items():
            regressor = info["regressed_by"]
            if regressor not in data:
                logger.error(
                    "Rule %s: regressor %s is not found",
                    self.name(),
                    regressor,
                )
                # This should be OK in local environment where we don't have
                # access to all bugs, but it is not OK in production.
                continue

            regression_versions = sorted(
                v
                for v in data[regressor]
                if v.startswith("cf_status_firefox")
                and data[regressor][v] in ("fixed", "verified")
            )
            if not regression_versions:
                # don't know what to do, ignore
                continue
            if regression_versions[0].startswith("cf_status_firefox_esr"):
                # shouldn't happen: esrXX sorts after YY
                continue
            regressed_version = int(regression_versions[0][len("cf_status_firefox") :])

            fixed_versions = sorted(
                v
                for v in info
                if v.startswith("cf_status_firefox")
                and info[v] in ("fixed", "verified")
            )
            if len(fixed_versions) > 0 and fixed_versions[0].startswith(
                "cf_status_firefox_esr"
            ):
                # shouldn't happen: esrXX sorts after YY
                continue
            fixed_version = (
                int(fixed_versions[0][len("cf_status_firefox") :])
                if len(fixed_versions) > 0
                else None
            )

            # If the latest status flag is wontfix or fix-optional, we ignore
            # setting flags with the status "affected".
            is_latest_wontfix = self._is_latest_status_flag_wontfix(info)

            self.status_changes[bugid] = {}
            for channel in ("release", "beta", "central"):
                v = int(self.versions[channel])
                flag = utils.get_flag(v, "status", channel)
                info[channel] = info[flag]
                if info[flag] != "---":
                    # XXX maybe check for consistency?
                    continue
                if fixed_version is not None and v >= fixed_version:
                    # Bug was fixed in an earlier version, don't set the flag
                    continue
                if v >= regressed_version:
                    if is_latest_wontfix:
                        continue
                    self.status_changes[bugid][flag] = "affected"
                    info[channel] = "affected"
                else:
                    self.status_changes[bugid][flag] = "unaffected"
                    info[channel] = "unaffected"
                filtered_bugs[bugid] = info

            esr_versions = set([self.versions["esr"], self.versions["esr_previous"]])
            for v in esr_versions:
                info.setdefault("esr", {})
                flag = utils.get_flag(v, "status", "esr")
                if flag not in info:
                    info["esr"][f"esr{v}"] = "n/a"
                    continue
                info["esr"][f"esr{v}"] = info[flag]
                if info[flag] != "---":
                    # XXX maybe check for consistency?
                    continue
                if fixed_version is not None and int(v) >= fixed_version:
                    # Bug was fixed in an earlier version, don't set the flag
                    continue
                if data[regressor].get(flag) in ("fixed", "verified"):
                    # regressor was uplifted, so the regression affects this branch
                    if is_latest_wontfix:
                        continue
                    self.status_changes[bugid][flag] = "affected"
                    info["esr"][f"esr{v}"] = "affected"
                elif int(v) >= regressed_version:
                    # regression from before this branch, also affected
                    if is_latest_wontfix:
                        continue
                    self.status_changes[bugid][flag] = "affected"
                    info["esr"][f"esr{v}"] = "affected"
                else:
                    self.status_changes[bugid][flag] = "unaffected"
                    info["esr"][f"esr{v}"] = "unaffected"
                filtered_bugs[bugid] = info

        # NOTE: The following is temporary to test that the new code is matching
        # producing the expected results. Once we are confident with the new
        # code, we can refactor this tool to use the new code.
        # See: https://github.com/mozilla/bugbot/issues/2152
        # >>>>> Begin of the temporary code
        adjusted_bugs = (
            {
                **bug,
                "regressed_by": [bug["regressed_by"]],
            }
            for bug in bugs.values()
        )
        bugs_store = BugsStore(chain(adjusted_bugs, data.values()))
        for bug_id in bugs:
            old_code_updates = self.status_changes.get(bug_id, {})
            bug = bugs_store.get_bug_by_id(int(bug_id))
            try:
                new_code_updates = bug.detect_version_status_updates()
            except BugNotInStoreError as error:
                if self.dryrun:
                    # This should be OK in local environment where we don't have
                    # access to all bugs, but it is not OK in production.
                    continue
                raise error from None

            new_code_updates = (
                {update.flag: update.status for update in new_code_updates}
                if new_code_updates
                else {}
            )

            if old_code_updates != new_code_updates:
                logger.error(
                    "Rule %s: Mismatching status updates for bug %s: %s <--> %s",
                    self.name(),
                    bug_id,
                    old_code_updates,
                    new_code_updates,
                )
        # <<<<< End of the temporary code

        for bugid in filtered_bugs:
            regressor = bugs[bugid]["regressed_by"]
            self.status_changes[bugid]["comment"] = {
                "body": f"{self.description()} {regressor}",
                # if the regressing bug is private (security or otherwise
                # confidential), don't leak its number through our comment (the
                # regressed_by field is not public in that case)
                "is_private": bool(data[regressor].get("groups")),
            }
            self.status_changes[bugid]["keywords"] = {"add": ["regression"]}

        return filtered_bugs