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