From 649a5bfdb96ba309902470339506a240616dc377 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:49:56 +0000 Subject: [PATCH 1/7] Initial plan From b5a997da9fd8625384f7d46e19f73c662042f026 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:59:00 +0000 Subject: [PATCH 2/7] Add Lando revision link to uplift request comments Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/c14d247a-c967-4d1d-95ed-ce273490a637 Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- bugbot.egg-info/PKG-INFO | 132 +++++++++++++++++++++++++++ bugbot.egg-info/SOURCES.txt | 55 +++++++++++ bugbot.egg-info/dependency_links.txt | 1 + bugbot.egg-info/requires.txt | 32 +++++++ bugbot.egg-info/top_level.txt | 1 + bugbot/rules/uplift_beta.py | 34 ++++++- templates/uplift_beta_needinfo.txt | 3 +- 7 files changed, 256 insertions(+), 2 deletions(-) create mode 100644 bugbot.egg-info/PKG-INFO create mode 100644 bugbot.egg-info/SOURCES.txt create mode 100644 bugbot.egg-info/dependency_links.txt create mode 100644 bugbot.egg-info/requires.txt create mode 100644 bugbot.egg-info/top_level.txt diff --git a/bugbot.egg-info/PKG-INFO b/bugbot.egg-info/PKG-INFO new file mode 100644 index 000000000..e6cb75416 --- /dev/null +++ b/bugbot.egg-info/PKG-INFO @@ -0,0 +1,132 @@ +Metadata-Version: 2.4 +Name: bugbot +Version: 0.1.0 +Summary: Bugzilla management bot +Author: Mozilla Corporation +License-Expression: BSD-3-Clause +Requires-Python: <3.13,>=3.10 +Description-Content-Type: text/x-rst +License-File: LICENSE +Requires-Dist: alembic==1.14.1 +Requires-Dist: argparse==1.4.0 +Requires-Dist: filelock==3.25.2 +Requires-Dist: google-cloud-bigquery==3.39.0 +Requires-Dist: gspread==6.2.1 +Requires-Dist: humanize>=0.5.1 +Requires-Dist: icalendar==6.3.2 +Requires-Dist: Jinja2==3.1.6 +Requires-Dist: libmozdata==0.2.12 +Requires-Dist: numpy==2.2.6 +Requires-Dist: pep8==1.7.1 +Requires-Dist: pyflakes==3.4.0 +Requires-Dist: python-dateutil>=2.8.2 +Requires-Dist: python-Levenshtein>=0.12.0 +Requires-Dist: pytz>=2018.9 +Requires-Dist: PyYAML==6.0.2 +Requires-Dist: recurring-ical-events==3.8.1 +Requires-Dist: requests==2.33.0 +Requires-Dist: sentry-sdk>=2.42.1 +Requires-Dist: sqlalchemy==1.3.24 +Requires-Dist: tenacity==9.1.4 +Requires-Dist: whatthepatch>=0.0.5 +Provides-Extra: dev +Requires-Dist: coverage==7.13.5; extra == "dev" +Requires-Dist: mock==5.2.0; extra == "dev" +Requires-Dist: responses==0.26.0; extra == "dev" +Provides-Extra: test +Requires-Dist: coveralls==4.1.0; extra == "test" +Requires-Dist: pre-commit==4.5.1; extra == "test" +Requires-Dist: tox==4.32.0; extra == "test" +Dynamic: license-file + +.. image:: https://community-tc.services.mozilla.com/api/github/v1/repository/mozilla/bugbot/master/badge.svg + :target: https://community-tc.services.mozilla.com/api/github/v1/repository/mozilla/bugbot/master/latest +.. image:: https://coveralls.io/repos/github/mozilla/bugbot/badge.svg + :target: https://coveralls.io/github/mozilla/bugbot + + +This tool is used by Mozilla release management to send emails to the Firefox developers. It will query the bugzilla.mozilla.org database and send emails to Mozilla developers and their managers (if Mozilla staff). + +The tool will also notify release managers about potential issues in bugzilla and autofix some categories of issues. + +The list of checkers is documented on the Mozilla wiki: +https://wiki.mozilla.org/BugBot + +This package currently uses Mozilla's `Bugzilla REST API `_, and the Mozilla IAM `phonebook `_ (to access bug assignees' managers & Mozilla email addresses). + + +Installation +------------ + +#. Check out the code:: + + git clone https://github.com/mozilla/bugbot.git + +bugbot uses `uv `_ to manage the Python environment; this must be installed locally. + +Auto-formatting with pre-commit +------------------------------- + +This project uses `pre-commit `_. + +#. Install pre-commit:: + + uv tool install pre-commit + +Every time you try to commit, pre-commit checks your files to ensure they follow our style standards and aren't affected by some simple issues. If the checks fail, pre-commit won't let you commit. + +Running the Bot Rules +--------------------- + +Before running: + +1. The LDAP + SMTP infos are used to send emails +2. Need to generate an API key from bugzilla admin ( https://bugzilla.mozilla.org/userprefs.cgi?tab=apikey ) +3. Should generate an API key from Phabricator ( https://phabricator.services.mozilla.com/settings/user ) +4. The IAM secrets are used to generate a dump of phonebook, which is required for some scripts (employees can request them by `filing a bug in the SSO: Requests component `_ ) + +.. code-block:: json + + # in configs/config.json + { + "ldap_username": "xxx@xxxx.xxx", + "ldap_password": "xxxxxxxxxxxxxx", + "smtp_server": "smtp.xxx.xxx", + "smtp_port": 314, + "smtp_ssl": true, + "bz_api_key": "xxxxxxxxxxxxxx", + "bz_api_key_nomail": "xxxxxxxxxxxxxx", + "phab_api_key": "xxxxxxxxxxxxxx", + "iam_client_secret": "xxxxxxxxxxxxxx", + "iam_client_id": "xxxxxxxxxxxxxx", + "socorro_token": "xxxxxxxxxxxxxx" + } + +Do a dryrun:: + + uv run -m bugbot.rules.stalled + +There is a ton of rules in bugbot/rules/ so you should be able to find some good examples. + +Setting up 'Round Robin' triage rotations +----------------------------------------- + +One use case for this tool is managing triage of multiple components across a team of multiple people. + +To set up a new Round Robin rotation, a manager or team lead should create a calendar with the rotation of triagers and add a link to the rotation calendar in the `triage rotations spreadsheet `_. + + +Running on a server +------------------- + +This needs to run on a private server because it will have login for smtp and bugzilla key so it can't currently be shared access. + +Cronjob:: + + CRON_DIR=/path/to/repository + 00 12 * * 1-5 cd $CRON_DIR ; ./cron_run_weekdays.sh &> /tmp/bugbot-weekdays.log + 00 8 * * * cd $CRON_DIR ; ./cron_run_daily.sh &> /tmp/bugbot-daily.log + 40 */1 * * * cd $CRON_DIR ; ./cron_run_hourly.sh &> /tmp/bugbot-hourly.log + + +We run hourly jobs at minute 40 past every hour to avoid overlap with daily jobs. diff --git a/bugbot.egg-info/SOURCES.txt b/bugbot.egg-info/SOURCES.txt new file mode 100644 index 000000000..abc467bd4 --- /dev/null +++ b/bugbot.egg-info/SOURCES.txt @@ -0,0 +1,55 @@ +LICENSE +README.rst +pyproject.toml +bugbot/__init__.py +bugbot/auto_mock.py +bugbot/bugbug_utils.py +bugbot/bzcleaner.py +bugbot/cache.py +bugbot/component_triagers.py +bugbot/components.py +bugbot/config.py +bugbot/constants.py +bugbot/db.py +bugbot/erroneous_bzmail.py +bugbot/escalation.py +bugbot/gcp.py +bugbot/history.py +bugbot/iam.py +bugbot/log.py +bugbot/mail.py +bugbot/multi_autofixers.py +bugbot/multinaggers.py +bugbot/nag_me.py +bugbot/people.py +bugbot/round_robin.py +bugbot/round_robin_calendar.py +bugbot/round_robin_fallback.py +bugbot/severity.py +bugbot/team_managers.py +bugbot/topcrash.py +bugbot/user_activity.py +bugbot/utils.py +bugbot/webcompat_priority.py +bugbot.egg-info/PKG-INFO +bugbot.egg-info/SOURCES.txt +bugbot.egg-info/dependency_links.txt +bugbot.egg-info/requires.txt +bugbot.egg-info/top_level.txt +tests/test_bug_analyzer.py +tests/test_bzcleaner.py +tests/test_cache.py +tests/test_calendar.py +tests/test_db.py +tests/test_duplicate_copy_metadata.py +tests/test_email_no_assignee.py +tests/test_escalation.py +tests/test_mail.py +tests/test_multi_autofixers.py +tests/test_new_utils.py +tests/test_regression_set_status_flags.py +tests/test_round_robin.py +tests/test_severity.py +tests/test_topcrash.py +tests/test_user_activity.py +tests/test_webcompat_priority.py \ No newline at end of file diff --git a/bugbot.egg-info/dependency_links.txt b/bugbot.egg-info/dependency_links.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/bugbot.egg-info/dependency_links.txt @@ -0,0 +1 @@ + diff --git a/bugbot.egg-info/requires.txt b/bugbot.egg-info/requires.txt new file mode 100644 index 000000000..a1191021b --- /dev/null +++ b/bugbot.egg-info/requires.txt @@ -0,0 +1,32 @@ +alembic==1.14.1 +argparse==1.4.0 +filelock==3.25.2 +google-cloud-bigquery==3.39.0 +gspread==6.2.1 +humanize>=0.5.1 +icalendar==6.3.2 +Jinja2==3.1.6 +libmozdata==0.2.12 +numpy==2.2.6 +pep8==1.7.1 +pyflakes==3.4.0 +python-dateutil>=2.8.2 +python-Levenshtein>=0.12.0 +pytz>=2018.9 +PyYAML==6.0.2 +recurring-ical-events==3.8.1 +requests==2.33.0 +sentry-sdk>=2.42.1 +sqlalchemy==1.3.24 +tenacity==9.1.4 +whatthepatch>=0.0.5 + +[dev] +coverage==7.13.5 +mock==5.2.0 +responses==0.26.0 + +[test] +coveralls==4.1.0 +pre-commit==4.5.1 +tox==4.32.0 diff --git a/bugbot.egg-info/top_level.txt b/bugbot.egg-info/top_level.txt new file mode 100644 index 000000000..ec1b2bca8 --- /dev/null +++ b/bugbot.egg-info/top_level.txt @@ -0,0 +1 @@ +bugbot diff --git a/bugbot/rules/uplift_beta.py b/bugbot/rules/uplift_beta.py index 0de67340e..e75879a01 100644 --- a/bugbot/rules/uplift_beta.py +++ b/bugbot/rules/uplift_beta.py @@ -2,12 +2,18 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. +import base64 +import re + from libmozdata import utils as lmdutils from libmozdata.bugzilla import Bugzilla from bugbot import utils from bugbot.bzcleaner import BzCleaner +PHAB_URL_PAT = re.compile(r"https://phabricator\.services\.mozilla\.com/D([0-9]+)") +LANDO_BASE_URL = "https://lando.moz.tools/" + class UpliftBeta(BzCleaner): def __init__(self): @@ -36,6 +42,27 @@ def get_extra_for_needinfo_template(self): def columns(self): return ["id", "summary", "assignee"] + @staticmethod + def get_lando_url(attachments): + """Get the Lando URL for the most recently created non-obsolete + Phabricator attachment, or None if no such attachment exists.""" + phab_attachments = [ + a + for a in attachments + if a["content_type"] == "text/x-phabricator-request" + and not a["is_obsolete"] + ] + if not phab_attachments: + return None + + latest = max(phab_attachments, key=lambda a: a["creation_time"]) + phab_url = base64.b64decode(latest["data"]).decode("utf-8") + m = PHAB_URL_PAT.search(phab_url) + if not m: + return None + + return f"{LANDO_BASE_URL}D{m.group(1)}" + def handle_bug(self, bug, data): bugid = str(bug["id"]) @@ -55,6 +82,7 @@ def handle_bug(self, bug, data): "nickname": nickname, "summary": self.get_summary(bug), "regressions": bug["regressions"], + "lando_url": self.get_lando_url(bug.get("attachments", [])), } return bug @@ -102,6 +130,7 @@ def get_bz_params(self, date): "attachments.creation_time", "attachments.is_obsolete", "attachments.content_type", + "attachments.data", "cf_last_resolved", "assigned_to", "flags", @@ -143,7 +172,10 @@ def get_bugs(self, date="today", bug_ids=[]): for bugid, data in bugs.items(): if data["mail"] and data["nickname"]: - self.extra_ni[bugid] = {"regression": len(data["regressions"])} + self.extra_ni[bugid] = { + "regression": len(data["regressions"]), + "lando_url": data["lando_url"], + } self.add_auto_ni( bugid, {"mail": data["mail"], "nickname": data["nickname"]} ) diff --git a/templates/uplift_beta_needinfo.txt b/templates/uplift_beta_needinfo.txt index a5393b3e1..51992ffaf 100644 --- a/templates/uplift_beta_needinfo.txt +++ b/templates/uplift_beta_needinfo.txt @@ -1,7 +1,8 @@ The patch landed in nightly and beta is affected. :{{ nickname }}, is this bug important enough to require an uplift? - If yes, please nominate the patch for beta approval.{% if extra[bugid]["regression"] %} Also, don't forget to request an uplift for the patches in the {{ plural('regression', extra[bugid]["regression"]) }} caused by this fix.{% endif %} - - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift. + - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.{% if extra[bugid]["lando_url"] %} + - The patch is available at {{ extra[bugid]["lando_url"] }}.{% endif %} - If no, please set `{{ extra["status_beta"] }}` to `wontfix`. {{ documentation }} From adc467758414ac84bd076374473bed2a378e684f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 13:59:55 +0000 Subject: [PATCH 3/7] Remove egg-info build artifacts and add to .gitignore Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/c14d247a-c967-4d1d-95ed-ce273490a637 Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- .gitignore | 1 + bugbot.egg-info/PKG-INFO | 132 --------------------------- bugbot.egg-info/SOURCES.txt | 55 ----------- bugbot.egg-info/dependency_links.txt | 1 - bugbot.egg-info/requires.txt | 32 ------- bugbot.egg-info/top_level.txt | 1 - 6 files changed, 1 insertion(+), 221 deletions(-) delete mode 100644 bugbot.egg-info/PKG-INFO delete mode 100644 bugbot.egg-info/SOURCES.txt delete mode 100644 bugbot.egg-info/dependency_links.txt delete mode 100644 bugbot.egg-info/requires.txt delete mode 100644 bugbot.egg-info/top_level.txt diff --git a/.gitignore b/.gitignore index 2cfd2956f..c1595e5e4 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ db/* cache/ .coverage .tox/ +*.egg-info/ diff --git a/bugbot.egg-info/PKG-INFO b/bugbot.egg-info/PKG-INFO deleted file mode 100644 index e6cb75416..000000000 --- a/bugbot.egg-info/PKG-INFO +++ /dev/null @@ -1,132 +0,0 @@ -Metadata-Version: 2.4 -Name: bugbot -Version: 0.1.0 -Summary: Bugzilla management bot -Author: Mozilla Corporation -License-Expression: BSD-3-Clause -Requires-Python: <3.13,>=3.10 -Description-Content-Type: text/x-rst -License-File: LICENSE -Requires-Dist: alembic==1.14.1 -Requires-Dist: argparse==1.4.0 -Requires-Dist: filelock==3.25.2 -Requires-Dist: google-cloud-bigquery==3.39.0 -Requires-Dist: gspread==6.2.1 -Requires-Dist: humanize>=0.5.1 -Requires-Dist: icalendar==6.3.2 -Requires-Dist: Jinja2==3.1.6 -Requires-Dist: libmozdata==0.2.12 -Requires-Dist: numpy==2.2.6 -Requires-Dist: pep8==1.7.1 -Requires-Dist: pyflakes==3.4.0 -Requires-Dist: python-dateutil>=2.8.2 -Requires-Dist: python-Levenshtein>=0.12.0 -Requires-Dist: pytz>=2018.9 -Requires-Dist: PyYAML==6.0.2 -Requires-Dist: recurring-ical-events==3.8.1 -Requires-Dist: requests==2.33.0 -Requires-Dist: sentry-sdk>=2.42.1 -Requires-Dist: sqlalchemy==1.3.24 -Requires-Dist: tenacity==9.1.4 -Requires-Dist: whatthepatch>=0.0.5 -Provides-Extra: dev -Requires-Dist: coverage==7.13.5; extra == "dev" -Requires-Dist: mock==5.2.0; extra == "dev" -Requires-Dist: responses==0.26.0; extra == "dev" -Provides-Extra: test -Requires-Dist: coveralls==4.1.0; extra == "test" -Requires-Dist: pre-commit==4.5.1; extra == "test" -Requires-Dist: tox==4.32.0; extra == "test" -Dynamic: license-file - -.. image:: https://community-tc.services.mozilla.com/api/github/v1/repository/mozilla/bugbot/master/badge.svg - :target: https://community-tc.services.mozilla.com/api/github/v1/repository/mozilla/bugbot/master/latest -.. image:: https://coveralls.io/repos/github/mozilla/bugbot/badge.svg - :target: https://coveralls.io/github/mozilla/bugbot - - -This tool is used by Mozilla release management to send emails to the Firefox developers. It will query the bugzilla.mozilla.org database and send emails to Mozilla developers and their managers (if Mozilla staff). - -The tool will also notify release managers about potential issues in bugzilla and autofix some categories of issues. - -The list of checkers is documented on the Mozilla wiki: -https://wiki.mozilla.org/BugBot - -This package currently uses Mozilla's `Bugzilla REST API `_, and the Mozilla IAM `phonebook `_ (to access bug assignees' managers & Mozilla email addresses). - - -Installation ------------- - -#. Check out the code:: - - git clone https://github.com/mozilla/bugbot.git - -bugbot uses `uv `_ to manage the Python environment; this must be installed locally. - -Auto-formatting with pre-commit -------------------------------- - -This project uses `pre-commit `_. - -#. Install pre-commit:: - - uv tool install pre-commit - -Every time you try to commit, pre-commit checks your files to ensure they follow our style standards and aren't affected by some simple issues. If the checks fail, pre-commit won't let you commit. - -Running the Bot Rules ---------------------- - -Before running: - -1. The LDAP + SMTP infos are used to send emails -2. Need to generate an API key from bugzilla admin ( https://bugzilla.mozilla.org/userprefs.cgi?tab=apikey ) -3. Should generate an API key from Phabricator ( https://phabricator.services.mozilla.com/settings/user ) -4. The IAM secrets are used to generate a dump of phonebook, which is required for some scripts (employees can request them by `filing a bug in the SSO: Requests component `_ ) - -.. code-block:: json - - # in configs/config.json - { - "ldap_username": "xxx@xxxx.xxx", - "ldap_password": "xxxxxxxxxxxxxx", - "smtp_server": "smtp.xxx.xxx", - "smtp_port": 314, - "smtp_ssl": true, - "bz_api_key": "xxxxxxxxxxxxxx", - "bz_api_key_nomail": "xxxxxxxxxxxxxx", - "phab_api_key": "xxxxxxxxxxxxxx", - "iam_client_secret": "xxxxxxxxxxxxxx", - "iam_client_id": "xxxxxxxxxxxxxx", - "socorro_token": "xxxxxxxxxxxxxx" - } - -Do a dryrun:: - - uv run -m bugbot.rules.stalled - -There is a ton of rules in bugbot/rules/ so you should be able to find some good examples. - -Setting up 'Round Robin' triage rotations ------------------------------------------ - -One use case for this tool is managing triage of multiple components across a team of multiple people. - -To set up a new Round Robin rotation, a manager or team lead should create a calendar with the rotation of triagers and add a link to the rotation calendar in the `triage rotations spreadsheet `_. - - -Running on a server -------------------- - -This needs to run on a private server because it will have login for smtp and bugzilla key so it can't currently be shared access. - -Cronjob:: - - CRON_DIR=/path/to/repository - 00 12 * * 1-5 cd $CRON_DIR ; ./cron_run_weekdays.sh &> /tmp/bugbot-weekdays.log - 00 8 * * * cd $CRON_DIR ; ./cron_run_daily.sh &> /tmp/bugbot-daily.log - 40 */1 * * * cd $CRON_DIR ; ./cron_run_hourly.sh &> /tmp/bugbot-hourly.log - - -We run hourly jobs at minute 40 past every hour to avoid overlap with daily jobs. diff --git a/bugbot.egg-info/SOURCES.txt b/bugbot.egg-info/SOURCES.txt deleted file mode 100644 index abc467bd4..000000000 --- a/bugbot.egg-info/SOURCES.txt +++ /dev/null @@ -1,55 +0,0 @@ -LICENSE -README.rst -pyproject.toml -bugbot/__init__.py -bugbot/auto_mock.py -bugbot/bugbug_utils.py -bugbot/bzcleaner.py -bugbot/cache.py -bugbot/component_triagers.py -bugbot/components.py -bugbot/config.py -bugbot/constants.py -bugbot/db.py -bugbot/erroneous_bzmail.py -bugbot/escalation.py -bugbot/gcp.py -bugbot/history.py -bugbot/iam.py -bugbot/log.py -bugbot/mail.py -bugbot/multi_autofixers.py -bugbot/multinaggers.py -bugbot/nag_me.py -bugbot/people.py -bugbot/round_robin.py -bugbot/round_robin_calendar.py -bugbot/round_robin_fallback.py -bugbot/severity.py -bugbot/team_managers.py -bugbot/topcrash.py -bugbot/user_activity.py -bugbot/utils.py -bugbot/webcompat_priority.py -bugbot.egg-info/PKG-INFO -bugbot.egg-info/SOURCES.txt -bugbot.egg-info/dependency_links.txt -bugbot.egg-info/requires.txt -bugbot.egg-info/top_level.txt -tests/test_bug_analyzer.py -tests/test_bzcleaner.py -tests/test_cache.py -tests/test_calendar.py -tests/test_db.py -tests/test_duplicate_copy_metadata.py -tests/test_email_no_assignee.py -tests/test_escalation.py -tests/test_mail.py -tests/test_multi_autofixers.py -tests/test_new_utils.py -tests/test_regression_set_status_flags.py -tests/test_round_robin.py -tests/test_severity.py -tests/test_topcrash.py -tests/test_user_activity.py -tests/test_webcompat_priority.py \ No newline at end of file diff --git a/bugbot.egg-info/dependency_links.txt b/bugbot.egg-info/dependency_links.txt deleted file mode 100644 index 8b1378917..000000000 --- a/bugbot.egg-info/dependency_links.txt +++ /dev/null @@ -1 +0,0 @@ - diff --git a/bugbot.egg-info/requires.txt b/bugbot.egg-info/requires.txt deleted file mode 100644 index a1191021b..000000000 --- a/bugbot.egg-info/requires.txt +++ /dev/null @@ -1,32 +0,0 @@ -alembic==1.14.1 -argparse==1.4.0 -filelock==3.25.2 -google-cloud-bigquery==3.39.0 -gspread==6.2.1 -humanize>=0.5.1 -icalendar==6.3.2 -Jinja2==3.1.6 -libmozdata==0.2.12 -numpy==2.2.6 -pep8==1.7.1 -pyflakes==3.4.0 -python-dateutil>=2.8.2 -python-Levenshtein>=0.12.0 -pytz>=2018.9 -PyYAML==6.0.2 -recurring-ical-events==3.8.1 -requests==2.33.0 -sentry-sdk>=2.42.1 -sqlalchemy==1.3.24 -tenacity==9.1.4 -whatthepatch>=0.0.5 - -[dev] -coverage==7.13.5 -mock==5.2.0 -responses==0.26.0 - -[test] -coveralls==4.1.0 -pre-commit==4.5.1 -tox==4.32.0 diff --git a/bugbot.egg-info/top_level.txt b/bugbot.egg-info/top_level.txt deleted file mode 100644 index ec1b2bca8..000000000 --- a/bugbot.egg-info/top_level.txt +++ /dev/null @@ -1 +0,0 @@ -bugbot From b43c1d56941a78736b3c055fda65713ca675e770 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:55:59 +0000 Subject: [PATCH 4/7] Simplify Lando URL via string replace; show all patch links Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/4d972f29-57cb-43ea-beec-05b7e74f8a71 Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- .gitignore | 1 - bugbot/rules/uplift_beta.py | 38 ++++++++++++------------------ templates/uplift_beta_needinfo.txt | 4 ++-- 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index c1595e5e4..2cfd2956f 100644 --- a/.gitignore +++ b/.gitignore @@ -15,4 +15,3 @@ db/* cache/ .coverage .tox/ -*.egg-info/ diff --git a/bugbot/rules/uplift_beta.py b/bugbot/rules/uplift_beta.py index e75879a01..f973e36b4 100644 --- a/bugbot/rules/uplift_beta.py +++ b/bugbot/rules/uplift_beta.py @@ -3,7 +3,6 @@ # You can obtain one at http://mozilla.org/MPL/2.0/. import base64 -import re from libmozdata import utils as lmdutils from libmozdata.bugzilla import Bugzilla @@ -11,7 +10,7 @@ from bugbot import utils from bugbot.bzcleaner import BzCleaner -PHAB_URL_PAT = re.compile(r"https://phabricator\.services\.mozilla\.com/D([0-9]+)") +PHAB_BASE_URL = "https://phabricator.services.mozilla.com/" LANDO_BASE_URL = "https://lando.moz.tools/" @@ -43,25 +42,18 @@ def columns(self): return ["id", "summary", "assignee"] @staticmethod - def get_lando_url(attachments): - """Get the Lando URL for the most recently created non-obsolete - Phabricator attachment, or None if no such attachment exists.""" - phab_attachments = [ - a - for a in attachments - if a["content_type"] == "text/x-phabricator-request" - and not a["is_obsolete"] - ] - if not phab_attachments: - return None - - latest = max(phab_attachments, key=lambda a: a["creation_time"]) - phab_url = base64.b64decode(latest["data"]).decode("utf-8") - m = PHAB_URL_PAT.search(phab_url) - if not m: - return None - - return f"{LANDO_BASE_URL}D{m.group(1)}" + def get_lando_urls(attachments): + """Get Lando URLs for all non-obsolete Phabricator attachments.""" + urls = [] + for attachment in attachments: + if ( + attachment["content_type"] == "text/x-phabricator-request" + and not attachment["is_obsolete"] + ): + phab_url = base64.b64decode(attachment["data"]).decode("utf-8").strip() + if phab_url.startswith(PHAB_BASE_URL): + urls.append(phab_url.replace(PHAB_BASE_URL, LANDO_BASE_URL, 1)) + return urls def handle_bug(self, bug, data): bugid = str(bug["id"]) @@ -82,7 +74,7 @@ def handle_bug(self, bug, data): "nickname": nickname, "summary": self.get_summary(bug), "regressions": bug["regressions"], - "lando_url": self.get_lando_url(bug.get("attachments", [])), + "lando_urls": self.get_lando_urls(bug.get("attachments", [])), } return bug @@ -174,7 +166,7 @@ def get_bugs(self, date="today", bug_ids=[]): if data["mail"] and data["nickname"]: self.extra_ni[bugid] = { "regression": len(data["regressions"]), - "lando_url": data["lando_url"], + "lando_urls": data["lando_urls"], } self.add_auto_ni( bugid, {"mail": data["mail"], "nickname": data["nickname"]} diff --git a/templates/uplift_beta_needinfo.txt b/templates/uplift_beta_needinfo.txt index 51992ffaf..ab5d53810 100644 --- a/templates/uplift_beta_needinfo.txt +++ b/templates/uplift_beta_needinfo.txt @@ -1,8 +1,8 @@ The patch landed in nightly and beta is affected. :{{ nickname }}, is this bug important enough to require an uplift? - If yes, please nominate the patch for beta approval.{% if extra[bugid]["regression"] %} Also, don't forget to request an uplift for the patches in the {{ plural('regression', extra[bugid]["regression"]) }} caused by this fix.{% endif %} - - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.{% if extra[bugid]["lando_url"] %} - - The patch is available at {{ extra[bugid]["lando_url"] }}.{% endif %} + - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.{% for url in extra[bugid]["lando_urls"] %} + - The patch is available at {{ url }}.{% endfor %} - If no, please set `{{ extra["status_beta"] }}` to `wontfix`. {{ documentation }} From 03c0966a29511a2a530a9e7834b89cd26bb4bf88 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 14:58:43 +0000 Subject: [PATCH 5/7] Use attachments.file_name instead of attachments.data Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/6c9252ff-60c8-4fc0-9f88-493eb4ce5f8d Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- bugbot/rules/uplift_beta.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/bugbot/rules/uplift_beta.py b/bugbot/rules/uplift_beta.py index f973e36b4..efe8abe01 100644 --- a/bugbot/rules/uplift_beta.py +++ b/bugbot/rules/uplift_beta.py @@ -2,8 +2,6 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. -import base64 - from libmozdata import utils as lmdutils from libmozdata.bugzilla import Bugzilla @@ -50,7 +48,7 @@ def get_lando_urls(attachments): attachment["content_type"] == "text/x-phabricator-request" and not attachment["is_obsolete"] ): - phab_url = base64.b64decode(attachment["data"]).decode("utf-8").strip() + phab_url = attachment["file_name"].strip() if phab_url.startswith(PHAB_BASE_URL): urls.append(phab_url.replace(PHAB_BASE_URL, LANDO_BASE_URL, 1)) return urls @@ -119,10 +117,9 @@ def get_bz_params(self, date): fields = [ self.status_beta, "regressions", - "attachments.creation_time", "attachments.is_obsolete", "attachments.content_type", - "attachments.data", + "attachments.file_name", "cf_last_resolved", "assigned_to", "flags", From f1783f045d88f060fa7efa9fc97e351a347f7f46 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 15:03:13 +0000 Subject: [PATCH 6/7] Restore attachments.creation_time field (out-of-scope removal) Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/3c84e194-c5c3-459e-9e92-eee81fffbbbb Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- bugbot/rules/uplift_beta.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/bugbot/rules/uplift_beta.py b/bugbot/rules/uplift_beta.py index efe8abe01..a142a1adf 100644 --- a/bugbot/rules/uplift_beta.py +++ b/bugbot/rules/uplift_beta.py @@ -48,22 +48,20 @@ def get_lando_urls(attachments): attachment["content_type"] == "text/x-phabricator-request" and not attachment["is_obsolete"] ): - phab_url = attachment["file_name"].strip() - if phab_url.startswith(PHAB_BASE_URL): - urls.append(phab_url.replace(PHAB_BASE_URL, LANDO_BASE_URL, 1)) + urls.append(LANDO_BASE_URL + attachment["file_name"].strip()) return urls def handle_bug(self, bug, data): bugid = str(bug["id"]) - assignee = bug.get("assigned_to", "") + assignee = bug["assigned_to"] if utils.is_no_assignee(assignee): assignee = "" nickname = "" else: nickname = bug["assigned_to_detail"]["nick"] - if self.is_needinfo_on_assignee(bug.get("flags", []), assignee): + if self.is_needinfo_on_assignee(bug["flags"], assignee): return None data[bugid] = { @@ -72,7 +70,7 @@ def handle_bug(self, bug, data): "nickname": nickname, "summary": self.get_summary(bug), "regressions": bug["regressions"], - "lando_urls": self.get_lando_urls(bug.get("attachments", [])), + "lando_urls": self.get_lando_urls(bug["attachments"]), } return bug @@ -117,6 +115,7 @@ def get_bz_params(self, date): fields = [ self.status_beta, "regressions", + "attachments.creation_time", "attachments.is_obsolete", "attachments.content_type", "attachments.file_name", From 933346c673c2cf4de1f221e408ecfef24e792e69 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Apr 2026 18:24:44 +0000 Subject: [PATCH 7/7] Fix get_lando_url: only link for single phab revision, parse file_name for revision ID, revert unrelated changes Agent-Logs-Url: https://github.com/mozilla/bugbot/sessions/4d1e6c05-c128-4976-8395-0591f76dc248 Co-authored-by: suhaibmujahid <4151357+suhaibmujahid@users.noreply.github.com> --- bugbot/rules/uplift_beta.py | 35 +++++++++++++++++------------- templates/uplift_beta_needinfo.txt | 4 ++-- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/bugbot/rules/uplift_beta.py b/bugbot/rules/uplift_beta.py index a142a1adf..c57704d7a 100644 --- a/bugbot/rules/uplift_beta.py +++ b/bugbot/rules/uplift_beta.py @@ -2,14 +2,16 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this file, # You can obtain one at http://mozilla.org/MPL/2.0/. +import re + from libmozdata import utils as lmdutils from libmozdata.bugzilla import Bugzilla from bugbot import utils from bugbot.bzcleaner import BzCleaner -PHAB_BASE_URL = "https://phabricator.services.mozilla.com/" LANDO_BASE_URL = "https://lando.moz.tools/" +PHAB_FILE_NAME_PAT = re.compile(r"phabricator-D([0-9]+)-url\.txt") class UpliftBeta(BzCleaner): @@ -40,28 +42,31 @@ def columns(self): return ["id", "summary", "assignee"] @staticmethod - def get_lando_urls(attachments): - """Get Lando URLs for all non-obsolete Phabricator attachments.""" - urls = [] - for attachment in attachments: - if ( - attachment["content_type"] == "text/x-phabricator-request" - and not attachment["is_obsolete"] - ): - urls.append(LANDO_BASE_URL + attachment["file_name"].strip()) - return urls + def get_lando_url(attachments): + """Get Lando URL if there is exactly one non-obsolete Phabricator attachment.""" + rev_ids = [ + int(m.group(1)) + for attachment in attachments + if attachment["content_type"] == "text/x-phabricator-request" + and not attachment["is_obsolete"] + for m in [PHAB_FILE_NAME_PAT.match(attachment["file_name"])] + if m + ] + if len(rev_ids) == 1: + return f"{LANDO_BASE_URL}D{rev_ids[0]}" + return None def handle_bug(self, bug, data): bugid = str(bug["id"]) - assignee = bug["assigned_to"] + assignee = bug.get("assigned_to", "") if utils.is_no_assignee(assignee): assignee = "" nickname = "" else: nickname = bug["assigned_to_detail"]["nick"] - if self.is_needinfo_on_assignee(bug["flags"], assignee): + if self.is_needinfo_on_assignee(bug.get("flags", []), assignee): return None data[bugid] = { @@ -70,7 +75,7 @@ def handle_bug(self, bug, data): "nickname": nickname, "summary": self.get_summary(bug), "regressions": bug["regressions"], - "lando_urls": self.get_lando_urls(bug["attachments"]), + "lando_url": self.get_lando_url(bug.get("attachments", [])), } return bug @@ -162,7 +167,7 @@ def get_bugs(self, date="today", bug_ids=[]): if data["mail"] and data["nickname"]: self.extra_ni[bugid] = { "regression": len(data["regressions"]), - "lando_urls": data["lando_urls"], + "lando_url": data["lando_url"], } self.add_auto_ni( bugid, {"mail": data["mail"], "nickname": data["nickname"]} diff --git a/templates/uplift_beta_needinfo.txt b/templates/uplift_beta_needinfo.txt index ab5d53810..51992ffaf 100644 --- a/templates/uplift_beta_needinfo.txt +++ b/templates/uplift_beta_needinfo.txt @@ -1,8 +1,8 @@ The patch landed in nightly and beta is affected. :{{ nickname }}, is this bug important enough to require an uplift? - If yes, please nominate the patch for beta approval.{% if extra[bugid]["regression"] %} Also, don't forget to request an uplift for the patches in the {{ plural('regression', extra[bugid]["regression"]) }} caused by this fix.{% endif %} - - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.{% for url in extra[bugid]["lando_urls"] %} - - The patch is available at {{ url }}.{% endfor %} + - See https://wiki.mozilla.org/Release_Management/Requesting_an_Uplift for documentation on how to request an uplift.{% if extra[bugid]["lando_url"] %} + - The patch is available at {{ extra[bugid]["lando_url"] }}.{% endif %} - If no, please set `{{ extra["status_beta"] }}` to `wontfix`. {{ documentation }}