From 1d428d1a2338b2053dd9e596ff88682c48f2eeb1 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 10 Jul 2026 16:13:55 -0400 Subject: [PATCH 01/25] branches: add esr branch support (bug 2048638) --- mozregression/branches.py | 13 +++++++++++-- tests/unit/test_branches.py | 6 ++++++ 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/mozregression/branches.py b/mozregression/branches.py index 976cb4e60..e4749f38f 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -12,7 +12,7 @@ from mozregression.errors import MozRegressionError LOG = get_proxy_logger("Branches") - +RE_ESR = re.compile(r"^(?:mozilla-)?esr(\d+)$", re.I) class Branches(object): DEFAULT_REPO_URL = "https://hg.mozilla.org/" @@ -38,12 +38,21 @@ def set_alias(self, alias, branch_name): self._aliases[alias] = branch_name def get_url(self, branch_name_or_alias): + name = self.get_name(branch_name_or_alias) try: - return self._branches[self.get_name(branch_name_or_alias)] + return self._branches[name] except KeyError: + if RE_ESR.match(name): + return self.DEFAULT_REPO_URL + "releases/mozilla-esr%s" % RE_ESR.match( + name + ).group(1) raise MozRegressionError("No such branch '%s'." % branch_name_or_alias) def get_name(self, branch_name_or_alias): + if branch_name_or_alias: + match = RE_ESR.match(branch_name_or_alias) + if match: + return "mozilla-esr%s" % match.group(1) return self._aliases.get(branch_name_or_alias) or branch_name_or_alias def get_category(self, branch_name_or_alias): diff --git a/tests/unit/test_branches.py b/tests/unit/test_branches.py index cade541c3..994aaead7 100644 --- a/tests/unit/test_branches.py +++ b/tests/unit/test_branches.py @@ -13,6 +13,8 @@ ("mozilla-central", "mozilla-central"), ("mozilla-central", "m-c"), ("unknown", "unknown"), + ("mozilla-esr140", "esr140"), + ("mozilla-esr140", "mozilla-esr140"), ], ) def test_branch_name(branch, alias): @@ -25,6 +27,8 @@ def test_branch_name(branch, alias): ("m-c", "https://hg.mozilla.org/mozilla-central"), ("m-i", "https://hg.mozilla.org/integration/mozilla-inbound"), ("mozilla-beta", "https://hg.mozilla.org/releases/mozilla-beta"), + ("mozilla-esr140", "https://hg.mozilla.org/releases/mozilla-esr140"), + ("esr140", "https://hg.mozilla.org/releases/mozilla-esr140"), ], ) def test_get_urls(branch, url): @@ -63,6 +67,8 @@ def test_get_url_unknown_branch(): ("mozilla-beta", "releases"), ("", None), (None, None), + ("mozilla-esr140", None), + ("esr140", None), ], ) def test_get_category(name, expected): From ee89511601d87a65b3c380728e1498f344158394 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Tue, 14 Jul 2026 10:38:59 -0400 Subject: [PATCH 02/25] fix linting --- mozregression/branches.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mozregression/branches.py b/mozregression/branches.py index e4749f38f..3e88c30df 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -14,6 +14,7 @@ LOG = get_proxy_logger("Branches") RE_ESR = re.compile(r"^(?:mozilla-)?esr(\d+)$", re.I) + class Branches(object): DEFAULT_REPO_URL = "https://hg.mozilla.org/" @@ -43,9 +44,9 @@ def get_url(self, branch_name_or_alias): return self._branches[name] except KeyError: if RE_ESR.match(name): - return self.DEFAULT_REPO_URL + "releases/mozilla-esr%s" % RE_ESR.match( - name - ).group(1) + return self.DEFAULT_REPO_URL + "releases/mozilla-esr%s" % RE_ESR.match(name).group( + 1 + ) raise MozRegressionError("No such branch '%s'." % branch_name_or_alias) def get_name(self, branch_name_or_alias): From 8f3bbdf2f21e66d2d68579f9a181a062e2946985 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Tue, 14 Jul 2026 11:25:09 -0400 Subject: [PATCH 03/25] add help text to gui --- gui/mozregui/ui/intro.ui | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/gui/mozregui/ui/intro.ui b/gui/mozregui/ui/intro.ui index 13a189e32..260a25d1d 100644 --- a/gui/mozregui/ui/intro.ui +++ b/gui/mozregui/ui/intro.ui @@ -60,6 +60,16 @@ Choose a build type you want. + + + + + Hint: To choose an ESR branch, type mozilla-esrXXX or esrXXX and continue. + + + color: gray; font-size: 10px; + + @@ -81,7 +91,7 @@ - + enter the code of the lang you want a build for @@ -91,7 +101,7 @@ - + Lang code such as he, ar, zh-TW @@ -101,7 +111,7 @@ - + enter a URL to pass to the app @@ -111,7 +121,7 @@ - + URL such as example.org, https://mozilla.org, about:logo From 53b2caa9734217b13acb46c3b3c6a22c4e803292 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Wed, 15 Jul 2026 13:23:15 -0400 Subject: [PATCH 04/25] make esr branches' category releases --- mozregression/branches.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mozregression/branches.py b/mozregression/branches.py index 3e88c30df..8bcbe723b 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -61,6 +61,8 @@ def get_category(self, branch_name_or_alias): for cat, names in self._categories.items(): if name in names: return cat + if RE_ESR.match(name): + return "releases" def create_branches(): From 37378d021fee9293534ddd1c98f52b29124dc681 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Wed, 15 Jul 2026 13:29:30 -0400 Subject: [PATCH 05/25] add early exit when name is none --- CLAUDE.md | 187 ++++++++++++++++++++++++++++++++++++++ mozregression/branches.py | 2 +- 2 files changed, 188 insertions(+), 1 deletion(-) create mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..93a9d1b99 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,187 @@ +I am a 3rd year computer engineering student intern and am new to the codebase +# Git and Version Control + +For small tasks, avoid creating commits and simply write to the working copy. + +For larger tasks, create very small commits as you go. Each commit should have a concise, descriptive commit message. Prefer shorter and more concise to longer, I will ask for a longer commit message if need be. + +Never ever add any attribution to commit message. No `Co-Authored-By:` trailers, for any reason (giving attribution to Claude or another user). + +Commit messages have a maximum 88-character line length. + +# General Coding Practices + +## Single-letter variable names + +Never use Single-letter variable names. Even in loops and other places, always find a better variable name. + +## Comments + +### Comment Verbosity + +Comments should be 1-3 sentences in length at maximum. If a comment does not provide enough detail I will explicitly ask for more information or a longer comment. + +### Use full grammar and punctuation for comments + +Always use proper English when writing code comments. For example, rewrite a comment like `# this is not great` to `# This is not great.`. + +### Wrap code in backticks (`) + +In comments, test code, assert strings and other places, references to code should be wrapped in backticks. + +For example, this code block: + +```python +# Only return when validate is true. +if validate(): + return True +``` + +should be re-written like so: + +```python +# Only return when `validate` is `True`. +if validate(): + return True +``` + +### Comments vs Debug logging statements + +In contexts with logging, instead of writing comments we should add debug-level log statements. For example, this code: + +```python +# Send the request. +requests.get("https://example.com") +``` + +could instead be written like: + +```python +logger.debug("Sending the request.") +requests.get("https://example.com") +``` + +This allows the code to have clearly labelled sections, and allows us to see detailled logging when increasing the log level to DEBUG. + +## Stepdown Readability + +Stepdown readability should be used to organize code everywhere is it appropriate. + +# Python + +## Imports + +Always add imports at the beginning of the file. Do not add imports unless absolutely necessary, and if it is necessary, add a comment explaining why the imports cannot be added at the top of the file. + +For example, code like this: + +```python +import sys + +def func(): + from package import blah + blah() +``` + +should instead become: + +```python +import sys +from package import blah + +def func(): + blah() +``` + +or there should be an explanation: + +```python +import sys + +def func(): + # Importing blah at the module level causes lazy-loading issues. + from package import blah + blah() +``` + +## Testing `assert` statements + +When writing tests with `pytest`, every `assert` statement should include an assert string which describes the test. +This keeps a plain-English description of the intention of the test close to the test itself, and gives better feedback when a test fails. + +If you would typically write a comment near the `assert` statement, it should instead be re-written to be the assert statement. + +For example, a test like this: + +```python +# Check that `method_call` returns `True`. +assert method_call() is True +``` + +should instead be written like: + +```python +assert method_call() is True, "`method_call` should return `True`." +``` + +## In Python Nothing Is Private + +In Python, no function is truly private. I have worked on codebases where there were "private" methods before, and in practice engineers +will simply use the private method since there is nothing stopping them from doign so. Using underscore-prefix to define "private" methods is +silly and makes the code look messy. + +Always define methods as public (ie without underscore-prefix) unless explicitly asked to for some reason. + +## Count Variables in For-loops + +Code like this: + +```python +count = 0 +for thing in things: + blah() + count += 1 +``` + +can always be replaced with `enumerate`: + +```python +for count, thing in enumerate(things): + blah() +``` + +In general, you should never have to maintain a `count` variable. + +## Docstrings Always Have a Single Title Line + +The first line of a docstring is always a single line, with an empty line after it. + +Bad: + +```python +def example(): + """Bug 2004368: a broken `jj` config surfaces the real error, not + "Not a repository". + + More content. + """ + ... +``` + +Good: + +```python +def test_jj_broken_config_surfaces_error(monkeypatch, jj_colocated_repo_path, tmp_path): + """Bug 2004368: a broken `jj` config surfaces the real error, not "Not a repository". + + More content. + """ + ... +``` + + +# Environment + +## Searching + +- When searching for code in a given repository, use `rg` to find content of files. Use `fd` to find specific files. diff --git a/mozregression/branches.py b/mozregression/branches.py index 8bcbe723b..88c636607 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -61,7 +61,7 @@ def get_category(self, branch_name_or_alias): for cat, names in self._categories.items(): if name in names: return cat - if RE_ESR.match(name): + if name and RE_ESR.match(name): return "releases" From 5906f8f245b0152a57b1395901c83e34133ab460 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Wed, 15 Jul 2026 13:29:55 -0400 Subject: [PATCH 06/25] switch esr branch category to release in tests --- tests/unit/test_branches.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/test_branches.py b/tests/unit/test_branches.py index 994aaead7..0a9a97866 100644 --- a/tests/unit/test_branches.py +++ b/tests/unit/test_branches.py @@ -67,8 +67,8 @@ def test_get_url_unknown_branch(): ("mozilla-beta", "releases"), ("", None), (None, None), - ("mozilla-esr140", None), - ("esr140", None), + ("mozilla-esr140", "releases"), + ("esr140", "releases"), ], ) def test_get_category(name, expected): From 67005e3cd9596ad2303dfd62877dfe72e23da77f Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 15:27:35 -0400 Subject: [PATCH 07/25] update regex to work with comm branches. default to mozilla for bare esr --- mozregression/branches.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/mozregression/branches.py b/mozregression/branches.py index 88c636607..3b3489e81 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -12,7 +12,7 @@ from mozregression.errors import MozRegressionError LOG = get_proxy_logger("Branches") -RE_ESR = re.compile(r"^(?:mozilla-)?esr(\d+)$", re.I) +RE_ESR = re.compile(r"^(?:(mozilla|comm)-)?esr(\d+)$", re.I) class Branches(object): @@ -44,16 +44,17 @@ def get_url(self, branch_name_or_alias): return self._branches[name] except KeyError: if RE_ESR.match(name): - return self.DEFAULT_REPO_URL + "releases/mozilla-esr%s" % RE_ESR.match(name).group( - 1 - ) + url = self.DEFAULT_REPO_URL + "releases/%s" % name + return url raise MozRegressionError("No such branch '%s'." % branch_name_or_alias) def get_name(self, branch_name_or_alias): if branch_name_or_alias: match = RE_ESR.match(branch_name_or_alias) if match: - return "mozilla-esr%s" % match.group(1) + # A bare `esr` defaults to the Firefox (`mozilla`) repository. + prefix = match.group(1) or "mozilla" + return "%s-esr%s" % (prefix.lower(), match.group(2)) return self._aliases.get(branch_name_or_alias) or branch_name_or_alias def get_category(self, branch_name_or_alias): From 1f6ef9af2aa2299554958213448eff665f0c7cf5 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 15:30:21 -0400 Subject: [PATCH 08/25] add build type = shippable to comm release, beta, and esr branches --- mozregression/fetch_configs.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 9e1bb16fb..b06b01d69 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -559,11 +559,12 @@ class ThunderbirdIntegrationConfigMixin(IntegrationConfigMixin): def tk_routes(self, push): for build_type in self.build_types: - yield "comm.v2.{}.revision.{}.thunderbird.{}-{}".format( + yield "comm.v2.{}{}.revision.{}.thunderbird.{}-{}".format( self.integration_branch, + ".shippable" if build_type == "shippable" else "", push.changeset, _common_tk_part(self), - build_type, + "opt" if build_type == "shippable" else build_type, ) self._inc_used_build() return @@ -675,7 +676,18 @@ def available_archs(self): class ThunderbirdConfig( CommonConfig, ThunderbirdNightlyConfigMixin, ThunderbirdIntegrationConfigMixin ): - pass + BUILD_TYPES = ( + "shippable", + "opt", + "debug", + ) + BUILD_TYPE_FALLBACKS = { + "shippable": ("opt",), + "opt": ("shippable", ), + } + def __init__(self, os, bits, processor, arch): + super(ThunderbirdConfig, self).__init__(os, bits, processor, arch) + self.set_build_type("shippable") @REGISTRY.register("thunderbird-l10n", attr_value="thunderbird") From b786087b5957fc3c8c739ec470464da4e879c82c Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 15:30:46 -0400 Subject: [PATCH 09/25] make comm replace default mozilla if thunderbird is app --- mozregression/fetch_configs.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index b06b01d69..97f5466dd 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -238,7 +238,15 @@ def set_repo(self, repo): If not set or set to None, default repos would be used (see :meth:`get_nightly_repo` and :attr:`integration_branch`) """ - self.repo = branches.get_name(repo) if repo else None + if repo: + name = branches.get_name(repo) + if self.app_name == "thunderbird" and name.startswith("mozilla"): + self.repo = name.replace("mozilla", "comm") + else: + self.repo = name + else: + self.repo = None + def should_use_archive(self): """ From 24e31674930295c7167102cdae56ce4b5d372098 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 15:39:14 -0400 Subject: [PATCH 10/25] fix linting --- mozregression/fetch_configs.py | 4 ++-- tests/unit/test_branches.py | 1 + tests/unit/test_fetch_configs.py | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 97f5466dd..0009484fb 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -247,7 +247,6 @@ def set_repo(self, repo): else: self.repo = None - def should_use_archive(self): """ Returns True if we should use the archive as an initial bisection @@ -691,8 +690,9 @@ class ThunderbirdConfig( ) BUILD_TYPE_FALLBACKS = { "shippable": ("opt",), - "opt": ("shippable", ), + "opt": ("shippable",), } + def __init__(self, os, bits, processor, arch): super(ThunderbirdConfig, self).__init__(os, bits, processor, arch) self.set_build_type("shippable") diff --git a/tests/unit/test_branches.py b/tests/unit/test_branches.py index 0a9a97866..899df54ba 100644 --- a/tests/unit/test_branches.py +++ b/tests/unit/test_branches.py @@ -69,6 +69,7 @@ def test_get_url_unknown_branch(): (None, None), ("mozilla-esr140", "releases"), ("esr140", "releases"), + ("comm-esr140", "releases"), ], ) def test_get_category(name, expected): diff --git a/tests/unit/test_fetch_configs.py b/tests/unit/test_fetch_configs.py index bb0c50b14..ed0949edd 100644 --- a/tests/unit/test_fetch_configs.py +++ b/tests/unit/test_fetch_configs.py @@ -518,7 +518,7 @@ def test_aarch64_build_types(self): "x86_64", "comm-beta", TIMESTAMP_TEST, - "comm.v2.comm-beta.revision.%s.thunderbird.linux64-opt" % CHSET, + "comm.v2.comm-beta.shippable.revision.%s.thunderbird.linux64-opt" % CHSET, ), ], ) From 3a4bd1b484280cf963865606427ec05dd2ab98b7 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:17:38 -0400 Subject: [PATCH 11/25] make default build type opt for comm-central --- mozregression/fetch_configs.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 0009484fb..f9f694e11 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -568,10 +568,15 @@ def tk_routes(self, push): for build_type in self.build_types: yield "comm.v2.{}{}.revision.{}.thunderbird.{}-{}".format( self.integration_branch, - ".shippable" if build_type == "shippable" else "", + ( + ".shippable" + if self.integration_branch != "comm-central" + or (self.integration_branch == "comm-central" and build_type == "shippable") + else "" + ), push.changeset, _common_tk_part(self), - "opt" if build_type == "shippable" else build_type, + "opt", ) self._inc_used_build() return @@ -686,7 +691,6 @@ class ThunderbirdConfig( BUILD_TYPES = ( "shippable", "opt", - "debug", ) BUILD_TYPE_FALLBACKS = { "shippable": ("opt",), @@ -695,7 +699,7 @@ class ThunderbirdConfig( def __init__(self, os, bits, processor, arch): super(ThunderbirdConfig, self).__init__(os, bits, processor, arch) - self.set_build_type("shippable") + pass @REGISTRY.register("thunderbird-l10n", attr_value="thunderbird") From afd4789f8d9c95e8ef7fc06a47747537c35e7e3c Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:18:19 -0400 Subject: [PATCH 12/25] add shippable tk route w build type test for comm central --- tests/unit/test_fetch_configs.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/unit/test_fetch_configs.py b/tests/unit/test_fetch_configs.py index ed0949edd..b572eefeb 100644 --- a/tests/unit/test_fetch_configs.py +++ b/tests/unit/test_fetch_configs.py @@ -566,6 +566,15 @@ def test_tk_route(app, os, bits, processor, repo, push_date, expected): "shippable", "gecko.v2.mozilla-central.shippable.revision.%s.mobile.android-api-16-opt" % CHSET, ), + # thunderbird + ( + "thunderbird", + "win", + 32, + "x86_64", + "shippable", + "comm.v2.comm-central.shippable.revision.%s.thunderbird.win32-opt" % CHSET, + ), ], ) def test_tk_route_with_build_type(app, os, bits, processor, build_type, expected): From 32615e28a3fa29b3452c657a030b46ec6cc95efd Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:37:56 -0400 Subject: [PATCH 13/25] catch more corner cases with bare esr --- mozregression/branches.py | 10 ++++++---- mozregression/fetch_configs.py | 9 +++++++-- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/mozregression/branches.py b/mozregression/branches.py index 3b3489e81..7a334d660 100644 --- a/mozregression/branches.py +++ b/mozregression/branches.py @@ -12,7 +12,7 @@ from mozregression.errors import MozRegressionError LOG = get_proxy_logger("Branches") -RE_ESR = re.compile(r"^(?:(mozilla|comm)-)?esr(\d+)$", re.I) +RE_ESR = re.compile(r"^(?:(mozilla-|comm-))?esr(\d+)$", re.I) class Branches(object): @@ -52,9 +52,11 @@ def get_name(self, branch_name_or_alias): if branch_name_or_alias: match = RE_ESR.match(branch_name_or_alias) if match: - # A bare `esr` defaults to the Firefox (`mozilla`) repository. - prefix = match.group(1) or "mozilla" - return "%s-esr%s" % (prefix.lower(), match.group(2)) + prefix = match.group(1) + if prefix: + return "%sesr%s" % (prefix, match.group(2)) + else: + return "esr%s" % match.group(2) return self._aliases.get(branch_name_or_alias) or branch_name_or_alias def get_category(self, branch_name_or_alias): diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index f9f694e11..94637785c 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -240,8 +240,13 @@ def set_repo(self, repo): """ if repo: name = branches.get_name(repo) - if self.app_name == "thunderbird" and name.startswith("mozilla"): - self.repo = name.replace("mozilla", "comm") + if self.app_name == "thunderbird" and name.startswith("esr"): + self.repo = "comm-" + name + elif self.app_name == "firefox" and name.startswith("esr"): + self.repo = "mozilla-" + name + elif name.startswith("esr"): + # A bare `esr` defaults to the Firefox (`mozilla`) repository. + self.repo = "mozilla-" + name else: self.repo = name else: From 8acc139c66d1863f53a7be506df9c1f5b2a477b7 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:38:14 -0400 Subject: [PATCH 14/25] simplify help text --- gui/mozregui/ui/intro.ui | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gui/mozregui/ui/intro.ui b/gui/mozregui/ui/intro.ui index 260a25d1d..282f6db76 100644 --- a/gui/mozregui/ui/intro.ui +++ b/gui/mozregui/ui/intro.ui @@ -64,7 +64,7 @@ - Hint: To choose an ESR branch, type mozilla-esrXXX or esrXXX and continue. + Hint: To choose an ESR branch, select target app and enter esrXXX. color: gray; font-size: 10px; From 2c22584448273c0b5260d766eeba0e1111a28627 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:45:49 -0400 Subject: [PATCH 15/25] remove obsolete tests --- tests/unit/test_branches.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/unit/test_branches.py b/tests/unit/test_branches.py index 899df54ba..c72d4809e 100644 --- a/tests/unit/test_branches.py +++ b/tests/unit/test_branches.py @@ -13,7 +13,6 @@ ("mozilla-central", "mozilla-central"), ("mozilla-central", "m-c"), ("unknown", "unknown"), - ("mozilla-esr140", "esr140"), ("mozilla-esr140", "mozilla-esr140"), ], ) @@ -28,7 +27,6 @@ def test_branch_name(branch, alias): ("m-i", "https://hg.mozilla.org/integration/mozilla-inbound"), ("mozilla-beta", "https://hg.mozilla.org/releases/mozilla-beta"), ("mozilla-esr140", "https://hg.mozilla.org/releases/mozilla-esr140"), - ("esr140", "https://hg.mozilla.org/releases/mozilla-esr140"), ], ) def test_get_urls(branch, url): From 9de2176e7e0373ff82325b19ce5d8d5eeb0c7f12 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Thu, 16 Jul 2026 17:46:12 -0400 Subject: [PATCH 16/25] fix linting --- mozregression/fetch_configs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 94637785c..605dc34c3 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -245,7 +245,7 @@ def set_repo(self, repo): elif self.app_name == "firefox" and name.startswith("esr"): self.repo = "mozilla-" + name elif name.startswith("esr"): - # A bare `esr` defaults to the Firefox (`mozilla`) repository. + # A bare `esr` defaults to the Firefox (`mozilla`) repository. self.repo = "mozilla-" + name else: self.repo = name From 94e90f00740424a19f94ef835e4a1a27dc30cb34 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 12:21:16 -0400 Subject: [PATCH 17/25] delete claude.md --- CLAUDE.md | 187 ------------------------------------------------------ 1 file changed, 187 deletions(-) delete mode 100644 CLAUDE.md diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 93a9d1b99..000000000 --- a/CLAUDE.md +++ /dev/null @@ -1,187 +0,0 @@ -I am a 3rd year computer engineering student intern and am new to the codebase -# Git and Version Control - -For small tasks, avoid creating commits and simply write to the working copy. - -For larger tasks, create very small commits as you go. Each commit should have a concise, descriptive commit message. Prefer shorter and more concise to longer, I will ask for a longer commit message if need be. - -Never ever add any attribution to commit message. No `Co-Authored-By:` trailers, for any reason (giving attribution to Claude or another user). - -Commit messages have a maximum 88-character line length. - -# General Coding Practices - -## Single-letter variable names - -Never use Single-letter variable names. Even in loops and other places, always find a better variable name. - -## Comments - -### Comment Verbosity - -Comments should be 1-3 sentences in length at maximum. If a comment does not provide enough detail I will explicitly ask for more information or a longer comment. - -### Use full grammar and punctuation for comments - -Always use proper English when writing code comments. For example, rewrite a comment like `# this is not great` to `# This is not great.`. - -### Wrap code in backticks (`) - -In comments, test code, assert strings and other places, references to code should be wrapped in backticks. - -For example, this code block: - -```python -# Only return when validate is true. -if validate(): - return True -``` - -should be re-written like so: - -```python -# Only return when `validate` is `True`. -if validate(): - return True -``` - -### Comments vs Debug logging statements - -In contexts with logging, instead of writing comments we should add debug-level log statements. For example, this code: - -```python -# Send the request. -requests.get("https://example.com") -``` - -could instead be written like: - -```python -logger.debug("Sending the request.") -requests.get("https://example.com") -``` - -This allows the code to have clearly labelled sections, and allows us to see detailled logging when increasing the log level to DEBUG. - -## Stepdown Readability - -Stepdown readability should be used to organize code everywhere is it appropriate. - -# Python - -## Imports - -Always add imports at the beginning of the file. Do not add imports unless absolutely necessary, and if it is necessary, add a comment explaining why the imports cannot be added at the top of the file. - -For example, code like this: - -```python -import sys - -def func(): - from package import blah - blah() -``` - -should instead become: - -```python -import sys -from package import blah - -def func(): - blah() -``` - -or there should be an explanation: - -```python -import sys - -def func(): - # Importing blah at the module level causes lazy-loading issues. - from package import blah - blah() -``` - -## Testing `assert` statements - -When writing tests with `pytest`, every `assert` statement should include an assert string which describes the test. -This keeps a plain-English description of the intention of the test close to the test itself, and gives better feedback when a test fails. - -If you would typically write a comment near the `assert` statement, it should instead be re-written to be the assert statement. - -For example, a test like this: - -```python -# Check that `method_call` returns `True`. -assert method_call() is True -``` - -should instead be written like: - -```python -assert method_call() is True, "`method_call` should return `True`." -``` - -## In Python Nothing Is Private - -In Python, no function is truly private. I have worked on codebases where there were "private" methods before, and in practice engineers -will simply use the private method since there is nothing stopping them from doign so. Using underscore-prefix to define "private" methods is -silly and makes the code look messy. - -Always define methods as public (ie without underscore-prefix) unless explicitly asked to for some reason. - -## Count Variables in For-loops - -Code like this: - -```python -count = 0 -for thing in things: - blah() - count += 1 -``` - -can always be replaced with `enumerate`: - -```python -for count, thing in enumerate(things): - blah() -``` - -In general, you should never have to maintain a `count` variable. - -## Docstrings Always Have a Single Title Line - -The first line of a docstring is always a single line, with an empty line after it. - -Bad: - -```python -def example(): - """Bug 2004368: a broken `jj` config surfaces the real error, not - "Not a repository". - - More content. - """ - ... -``` - -Good: - -```python -def test_jj_broken_config_surfaces_error(monkeypatch, jj_colocated_repo_path, tmp_path): - """Bug 2004368: a broken `jj` config surfaces the real error, not "Not a repository". - - More content. - """ - ... -``` - - -# Environment - -## Searching - -- When searching for code in a given repository, use `rg` to find content of files. Use `fd` to find specific files. From 98c604cd843a0d9ef61882fbb5a1bdbb8f865309 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 12:23:46 -0400 Subject: [PATCH 18/25] remove startswith repetition --- mozregression/fetch_configs.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 605dc34c3..f5529afc5 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -240,11 +240,12 @@ def set_repo(self, repo): """ if repo: name = branches.get_name(repo) - if self.app_name == "thunderbird" and name.startswith("esr"): + is_esr = name.startswith("esr") + if self.app_name == "thunderbird" and is_esr: self.repo = "comm-" + name - elif self.app_name == "firefox" and name.startswith("esr"): + elif self.app_name == "firefox" and is_esr: self.repo = "mozilla-" + name - elif name.startswith("esr"): + elif is_esr: # A bare `esr` defaults to the Firefox (`mozilla`) repository. self.repo = "mozilla-" + name else: From 882b42c49bb25fc8f5f39eaba90cff239f9353c9 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 12:25:29 -0400 Subject: [PATCH 19/25] remove old init --- mozregression/fetch_configs.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index f5529afc5..704ca24af 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -704,7 +704,6 @@ class ThunderbirdConfig( } def __init__(self, os, bits, processor, arch): - super(ThunderbirdConfig, self).__init__(os, bits, processor, arch) pass From 8584fc10bdf9a7481f5b1a801b90d8f4407f8086 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 13:27:54 -0400 Subject: [PATCH 20/25] remove stray init --- mozregression/fetch_configs.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 704ca24af..14862ffa4 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -703,8 +703,7 @@ class ThunderbirdConfig( "opt": ("shippable",), } - def __init__(self, os, bits, processor, arch): - pass + pass @REGISTRY.register("thunderbird-l10n", attr_value="thunderbird") From 556485656c7f74fa799743561d8a83606baf7f75 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 14:40:46 -0400 Subject: [PATCH 21/25] remove redundant tk-route construction for comm-central. comm-central uses nightly path, not taskcluster. --- mozregression/fetch_configs.py | 1 - tests/unit/test_fetch_configs.py | 18 ------------------ 2 files changed, 19 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 14862ffa4..f34a4d3af 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -577,7 +577,6 @@ def tk_routes(self, push): ( ".shippable" if self.integration_branch != "comm-central" - or (self.integration_branch == "comm-central" and build_type == "shippable") else "" ), push.changeset, diff --git a/tests/unit/test_fetch_configs.py b/tests/unit/test_fetch_configs.py index b572eefeb..18f50d471 100644 --- a/tests/unit/test_fetch_configs.py +++ b/tests/unit/test_fetch_configs.py @@ -502,15 +502,6 @@ def test_aarch64_build_types(self): "gecko.v2.mozilla-central.revision.%s.mobile.android-api-16-opt" % CHSET, ), # thunderbird - ( - "thunderbird", - "win", - 32, - "x86_64", - "comm-central", - TIMESTAMP_TEST, - "comm.v2.comm-central.revision.%s.thunderbird.win32-opt" % CHSET, - ), ( "thunderbird", "linux", @@ -566,15 +557,6 @@ def test_tk_route(app, os, bits, processor, repo, push_date, expected): "shippable", "gecko.v2.mozilla-central.shippable.revision.%s.mobile.android-api-16-opt" % CHSET, ), - # thunderbird - ( - "thunderbird", - "win", - 32, - "x86_64", - "shippable", - "comm.v2.comm-central.shippable.revision.%s.thunderbird.win32-opt" % CHSET, - ), ], ) def test_tk_route_with_build_type(app, os, bits, processor, build_type, expected): From 98c748b26c9119456303e00b2497ef0d30b3dc31 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 15:09:30 -0400 Subject: [PATCH 22/25] add esr instructions in docs --- docs/documentation/usage.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/documentation/usage.md b/docs/documentation/usage.md index 577d92d7f..1af4044ae 100644 --- a/docs/documentation/usage.md +++ b/docs/documentation/usage.md @@ -90,6 +90,10 @@ to date list of available options. mozregression --repo mozilla-aurora +- Bisecting from a ESR branch + + mozregression --repo esr140 + - Bisecting inbound directly mozregression --good 8850aa0f --bad 2a193b7f From 549b535f3062274874824bf59434b0f4d8c61a23 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 15:16:25 -0400 Subject: [PATCH 23/25] fix linting --- mozregression/fetch_configs.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index f34a4d3af..38ad753aa 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -574,11 +574,7 @@ def tk_routes(self, push): for build_type in self.build_types: yield "comm.v2.{}{}.revision.{}.thunderbird.{}-{}".format( self.integration_branch, - ( - ".shippable" - if self.integration_branch != "comm-central" - else "" - ), + (".shippable" if self.integration_branch != "comm-central" else ""), push.changeset, _common_tk_part(self), "opt", From fad17ec756c63ac538c18ff1d3dc1460f42ad552 Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 15:59:25 -0400 Subject: [PATCH 24/25] add back comm-central shippable check --- mozregression/fetch_configs.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mozregression/fetch_configs.py b/mozregression/fetch_configs.py index 38ad753aa..14862ffa4 100644 --- a/mozregression/fetch_configs.py +++ b/mozregression/fetch_configs.py @@ -574,7 +574,12 @@ def tk_routes(self, push): for build_type in self.build_types: yield "comm.v2.{}{}.revision.{}.thunderbird.{}-{}".format( self.integration_branch, - (".shippable" if self.integration_branch != "comm-central" else ""), + ( + ".shippable" + if self.integration_branch != "comm-central" + or (self.integration_branch == "comm-central" and build_type == "shippable") + else "" + ), push.changeset, _common_tk_part(self), "opt", From c45c338d074ba394e59cbb8793c621c7c4d7cc8f Mon Sep 17 00:00:00 2001 From: Magnolia Liu Date: Fri, 17 Jul 2026 16:09:43 -0400 Subject: [PATCH 25/25] add back tk_route tests --- tests/unit/test_fetch_configs.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/tests/unit/test_fetch_configs.py b/tests/unit/test_fetch_configs.py index 18f50d471..b572eefeb 100644 --- a/tests/unit/test_fetch_configs.py +++ b/tests/unit/test_fetch_configs.py @@ -502,6 +502,15 @@ def test_aarch64_build_types(self): "gecko.v2.mozilla-central.revision.%s.mobile.android-api-16-opt" % CHSET, ), # thunderbird + ( + "thunderbird", + "win", + 32, + "x86_64", + "comm-central", + TIMESTAMP_TEST, + "comm.v2.comm-central.revision.%s.thunderbird.win32-opt" % CHSET, + ), ( "thunderbird", "linux", @@ -557,6 +566,15 @@ def test_tk_route(app, os, bits, processor, repo, push_date, expected): "shippable", "gecko.v2.mozilla-central.shippable.revision.%s.mobile.android-api-16-opt" % CHSET, ), + # thunderbird + ( + "thunderbird", + "win", + 32, + "x86_64", + "shippable", + "comm.v2.comm-central.shippable.revision.%s.thunderbird.win32-opt" % CHSET, + ), ], ) def test_tk_route_with_build_type(app, os, bits, processor, build_type, expected):