• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mozilla / mozregression / 10833969657

12 Sep 2024 03:28PM CUT coverage: 89.188%. First build
10833969657

Pull #1812

github

web-flow
Merge a630e412a into c39e24675
Pull Request #1812: cli, fetch_configs, gui: use arch to construct build regex (bug 1917418)

32 of 44 new or added lines in 2 files covered. (72.73%)

2516 of 2821 relevant lines covered (89.19%)

0.89 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

93.22
/mozregression/fetch_configs.py
1
"""
2
This module defines the configuration needed for nightly and integration
3
fetching for each application. This configuration is a base block
4
for everything done in mozregression since it holds information
5
about how to get information about builds for a given application.
6

7
The public entry point in there is :func:`create_config`, which
8
creates an returns a fetch configuration. the configuration will
9
be an instance of :class:`CommonConfig`, possibly using the mixins
10
:class:`NightlyConfigMixin` and/or :class:`IntegrationConfigMixin`.
11
<
12
Example to create a configuration for firefox on linux 64: ::
13

14
  fetch_config = create_config('firefox', 'linux', 64)
15

16
You can also use the variable *REGISTRY* defined in this module to get a
17
list of application names that can be used to build a configuration. This is
18
an instance of :class:`ClassRegistry`. Example: ::
19

20
  print REGISTRY.names()
21
"""
22

23
from __future__ import absolute_import
1✔
24

25
import datetime
1✔
26
import re
1✔
27
from abc import ABCMeta, abstractmethod
1✔
28

29
from mozlog import get_proxy_logger
1✔
30

31
from mozregression import branches, errors
1✔
32
from mozregression.class_registry import ClassRegistry
1✔
33
from mozregression.config import ARCHIVE_BASE_URL
1✔
34
from mozregression.dates import to_utc_timestamp
1✔
35

36
LOG = get_proxy_logger(__name__)
1✔
37

38
# switch from fennec api-11 to api-15 on taskcluster
39
# appeared on this date for m-c.
40
TIMESTAMP_FENNEC_API_15 = to_utc_timestamp(datetime.datetime(2016, 1, 29, 0, 30, 13))
1✔
41

42
# switch from fennec api-15 to api-16 on taskcluster
43
# appeared on this date for m-c.
44
TIMESTAMP_FENNEC_API_16 = to_utc_timestamp(datetime.datetime(2017, 8, 29, 18, 28, 36))
1✔
45

46
# switch from geckoview api-16 to arm
47
TIMESTAMP_GECKOVIEW_ARM = to_utc_timestamp(datetime.datetime(2021, 6, 5, 3, 56, 19))
1✔
48

49

50
def infer_arch_from_bits(os, bits, processor):
1✔
51
    if bits == 64:
1✔
52
        if processor == "aarch64":
1✔
53
            return processor
1✔
54
        else:
55
            return "x86_64"
1✔
56
    else:
57
        return "x86"
1✔
58

59

60
def get_build_regex(
1✔
61
    name, os, bits, processor, platprefix=r".*", platsuffix="", with_ext=True, arch=None
62
):
63
    """
64
    Returns a string regexp that can match a build filename.
65

66
    :param name: must be the beginning of the filename to match
67
    :param os: the os, as returned by mozinfo.os
68
    :param bits: the bits information of the build. Either 32 or 64.
69
    :param processor: the architecture of the build. Only one that alters
70
                      results is aarch64.
71
    :param platprefix: optional prefix before the platform
72
    :param platsuffix: optional suffix after the platform
73
    :param with_ext: if True, the build extension will be appended (either
74
                     .zip, .tar.bz2 or .dmg depending on the os).
75
    :param arch: optional arch, either x86, x86_64, aarch64. Inferred from bits if not given.
76
    """
77
    if arch is None:
1✔
78
        arch = infer_arch_from_bits(os, bits, processor)
1✔
79

80
    if os == "win":
1✔
81
        if arch == "aarch64":
1✔
82
            platform = r"win64-aarch64"
1✔
83
        elif arch == "x86_64":
1✔
84
            platform = r"win64(-x86_64)?"
1✔
85
        else:
86
            platform = r"win32"
1✔
87
        ext = r"\.zip"
1✔
88
    elif os == "linux":
1✔
89
        if arch == "aarch64":
1✔
90
            platform, ext = r"linux-aarch64", r"\.tar.bz2"
1✔
91
        elif arch == "x86_64":
1✔
92
            platform, ext = r"linux-x86_64", r"\.tar.bz2"
1✔
93
        else:
94
            platform, ext = r"linux-i686", r"\.tar.bz2"
1✔
95
    elif os == "mac":
1✔
96
        platform, ext = r"mac.*", r"\.dmg"
1✔
97
    else:
98
        raise errors.MozRegressionError(
1✔
99
            "mozregression supports linux, mac and windows but your" " os is reported as '%s'." % os
100
        )
101

102
    # New taskcluster builds now just name the binary archive 'target', so
103
    # that is added as one possibility in the regex.
104
    regex = "(target|%s%s%s%s)" % (name, platprefix, platform, platsuffix)
1✔
105
    if with_ext:
1✔
106
        return "%s%s" % (regex, ext)
1✔
107
    else:
108
        return regex
1✔
109

110

111
class CommonConfig(object):
1✔
112
    """
113
    Define the configuration for both nightly and integration fetching.
114
    """
115

116
    BUILD_TYPES = ("opt",)  # only opt allowed by default
1✔
117
    BUILD_TYPE_FALLBACKS = {}
1✔
118
    app_name = None
1✔
119

120
    def __init__(self, os, bits, processor, arch):
1✔
121
        self.os = os
1✔
122
        self.bits = bits
1✔
123
        self.processor = processor
1✔
124
        self.set_arch(arch)
1✔
125
        self.repo = None
1✔
126
        self.set_build_type("opt")
1✔
127
        self._used_build_index = 0
1✔
128

129
    @property
1✔
130
    def build_type(self):
1✔
131
        """
132
        Returns the currently selected build type, which can change if there
133
        are fallbacks specified.
134
        """
135
        return self.build_types[self._used_build_index]
1✔
136

137
    def _inc_used_build(self):
1✔
138
        """
139
        Increments the index into the build_types indicating the currently
140
        selected build type.
141
        """
142
        self._used_build_index = (
1✔
143
            # Need to be careful not to overflow the list
144
            (self._used_build_index + 1)
145
            % len(self.build_types)
146
        )
147

148
    def build_regex(self):
1✔
149
        """
150
        Returns a string regex that can match a build file on the servers.
151
        """
NEW
152
        return (
×
153
            get_build_regex(self.app_name, self.os, self.bits, self.processor, arch=self.arch) + "$"
154
        )
155

156
    def build_info_regex(self):
1✔
157
        """
158
        Returns a string regex that can match a build info file (txt)
159
        on the servers.
160
        """
161
        return (
1✔
162
            get_build_regex(
163
                self.app_name, self.os, self.bits, self.processor, with_ext=False, arch=self.arch
164
            )
165
            + r"\.txt$"
166
        )
167

168
    def is_nightly(self):
1✔
169
        """
170
        Returns True if the configuration can be used for nightly fetching.
171
        """
172
        return isinstance(self, NightlyConfigMixin)
×
173

174
    def is_integration(self):
1✔
175
        """
176
        Returns True if the configuration can be used for integration fetching.
177
        """
178
        return isinstance(self, IntegrationConfigMixin)
1✔
179

180
    def available_bits(self):
1✔
181
        """
182
        Returns the no. of bits of the OS for which the application should
183
        run.
184
        """
185
        return (32, 64)
×
186

187
    def available_archs(self):
1✔
188
        """
189
        Returns the available architectures for this application.
190
        """
191
        return []
×
192

193
    def set_arch(self, arch):
1✔
194
        """
195
        Set the target build architecture for the application.
196
        """
197
        self.arch = arch
1✔
198

199
    def available_build_types(self):
1✔
200
        res = []
1✔
201
        for available in self.BUILD_TYPES:
1✔
202
            match = re.match(r"(.+)\[(.+)\]", available)
1✔
203
            if match:
1✔
204
                suffix = "-aarch64" if self.processor == "aarch64" and self.bits == 64 else ""
1✔
205
                available = match.group(1)
1✔
206
                platforms = match.group(2)
1✔
207
                if "{}{}{}".format(self.os, self.bits, suffix) not in platforms.split(","):
1✔
208
                    available = None
1✔
209
            if available:
1✔
210
                res.append(available)
1✔
211
        return res
1✔
212

213
    def set_build_type(self, build_type):
1✔
214
        """
215
        Define the build type (opt, debug, asan...).
216

217
        :raises: MozRegressionError on error.
218
        """
219
        if build_type in self.available_build_types():
1✔
220
            fallbacks = self.BUILD_TYPE_FALLBACKS.get(build_type)
1✔
221
            self.build_types = (build_type,) + fallbacks if fallbacks else (build_type,)
1✔
222
            return
1✔
223
        raise errors.MozRegressionError(
1✔
224
            "Unable to find a suitable build type %r." % str(build_type)
225
        )
226

227
    def set_repo(self, repo):
1✔
228
        """
229
        Allow to define the repo name.
230

231
        If not set or set to None, default repos would be used (see
232
        :meth:`get_nightly_repo` and :attr:`integration_branch`)
233
        """
234
        self.repo = branches.get_name(repo) if repo else None
1✔
235

236
    def should_use_archive(self):
1✔
237
        """
238
        Returns True if we should use the archive as an initial bisection
239
        method (archive.mozilla.org has a much longer retention period than
240
        taskcluster).
241

242
        Note that this method relies on the repo and build type defined.
243
        """
244
        # we can find the asan builds (firefox and jsshell) in archives.m.o
245
        return not (
1✔
246
            branches.get_category(self.repo) in ("integration", "try", "releases")
247
            or self.build_type not in ("opt", "asan", "shippable")
248
        )
249

250
    def extra_persist_part(self):
1✔
251
        """
252
        Allow to add a part in the generated persist file name to distinguish
253
        different builds that might be produced by a single config. Returns an
254
        empty string by default.
255
        """
256
        return ""
1✔
257

258

259
class NightlyConfigMixin(metaclass=ABCMeta):
1✔
260
    """
261
    Define the nightly-related required configuration to find nightly builds.
262

263
    A nightly build url is divided in 2 parts here:
264

265
    1. the base part as returned by :meth:`get_nightly_base_url`
266
    2. the final part, which can be found using :meth:`get_nighly_repo_regex`
267

268
    The final part contains a repo name, which is returned by
269
    :meth:`get_nightly_repo`.
270

271
    Note that subclasses must implement :meth:`_get_nightly_repo` to
272
    provide a default value.
273
    """
274

275
    archive_base_url = ARCHIVE_BASE_URL
1✔
276
    nightly_base_repo_name = "firefox"
1✔
277
    nightly_repo = None
1✔
278
    has_build_info = True
1✔
279

280
    def set_base_url(self, url):
1✔
281
        self.archive_base_url = url.rstrip("/")
1✔
282

283
    def get_nightly_base_url(self, date):
1✔
284
        """
285
        Returns the base part of the nightly build url for a given date.
286
        """
287
        return "%s/%s/nightly/%04d/%02d/" % (
1✔
288
            self.archive_base_url,
289
            self.nightly_base_repo_name,
290
            date.year,
291
            date.month,
292
        )
293

294
    def get_nightly_info_url(self, url):
1✔
295
        """
296
        Returns the url for the folder to find the build info .txt
297
        """
298
        return url
×
299

300
    def get_nightly_repo(self, date):
1✔
301
        """
302
        Returns the repo name for a given date.
303
        """
304
        if isinstance(date, datetime.datetime):
1✔
305
            date = date.date()
1✔
306
        return self.repo or self._get_nightly_repo(date)
1✔
307

308
    @abstractmethod
1✔
309
    def _get_nightly_repo(self, date):
1✔
310
        """
311
        Returns a default repo name for a given date.
312
        """
313
        raise NotImplementedError
314

315
    def get_nightly_repo_regex(self, date):
1✔
316
        """
317
        Returns a string regex that can match the last folder name for a given
318
        date.
319
        """
320
        return self._get_nightly_repo_regex(date, self.get_nightly_repo(date))
1✔
321

322
    def _get_nightly_repo_regex(self, date, repo):
1✔
323
        if isinstance(date, datetime.datetime):
1✔
324
            return r"/%04d-%02d-%02d-%02d-%02d-%02d-%s/$" % (
1✔
325
                date.year,
326
                date.month,
327
                date.day,
328
                date.hour,
329
                date.minute,
330
                date.second,
331
                repo,
332
            )
333
        return r"/%04d-%02d-%02d-[\d-]+%s/$" % (date.year, date.month, date.day, repo)
1✔
334

335
    def can_go_integration(self):
1✔
336
        """
337
        Indicate if we can bisect integration from this nightly config.
338
        """
339
        return self.is_integration()
1✔
340

341

342
class FirefoxNightlyConfigMixin(NightlyConfigMixin):
1✔
343
    def _get_nightly_repo(self, date):
1✔
344
        if date < datetime.date(2008, 6, 17):
1✔
345
            return "trunk"
1✔
346
        else:
347
            return "mozilla-central"
1✔
348

349

350
class FirefoxL10nNightlyConfigMixin(NightlyConfigMixin):
1✔
351
    has_build_info = False
1✔
352
    oldest_builds = datetime.date(2015, 10, 19)
1✔
353

354
    def _get_nightly_repo(self, date):
1✔
355
        if date < self.oldest_builds:
1✔
356
            raise errors.MozRegressionError(
1✔
357
                "firefox-l10n builds not available before {}".format(self.oldest_builds)
358
            )
359
        else:
360
            return "mozilla-central-l10n"
1✔
361

362
    def get_nightly_info_url(self, url):
1✔
363
        return url.replace("-l10n/", "/")
×
364

365

366
class ThunderbirdNightlyConfigMixin(NightlyConfigMixin):
1✔
367
    nightly_base_repo_name = "thunderbird"
1✔
368

369
    def _get_nightly_repo(self, date):
1✔
370
        # sneaking this in here
371
        if self.os == "win" and date < datetime.date(2010, 3, 18):
1✔
372
            # no .zip package for Windows, can't use the installer
373
            raise errors.WinTooOldBuildError()
1✔
374

375
        if date < datetime.date(2008, 7, 26):
1✔
376
            return "trunk"
1✔
377
        elif date < datetime.date(2009, 1, 9):
1✔
378
            return "comm-central"
1✔
379
        elif date < datetime.date(2010, 8, 21):
1✔
380
            return "comm-central-trunk"
1✔
381
        else:
382
            return "comm-central"
1✔
383

384

385
class ThunderbirdL10nNightlyConfigMixin(ThunderbirdNightlyConfigMixin):
1✔
386
    has_build_info = False
1✔
387
    oldest_builds = datetime.date(2015, 10, 8)
1✔
388

389
    def _get_nightly_repo(self, date):
1✔
390
        if date < self.oldest_builds:
1✔
391
            raise errors.MozRegressionError(
1✔
392
                "thunderbird-l10n builds not available before {}".format(self.oldest_builds)
393
            )
394
        return "comm-central-l10n"
1✔
395

396

397
class FennecNightlyConfigMixin(NightlyConfigMixin):
1✔
398
    nightly_base_repo_name = "mobile"
1✔
399

400
    def _get_nightly_repo(self, date):
1✔
401
        return "mozilla-central"
1✔
402

403
    def get_nightly_repo_regex(self, date):
1✔
404
        repo = self.get_nightly_repo(date)
1✔
405
        if repo in ("mozilla-central",):
1✔
406
            if date < datetime.date(2014, 12, 6):
1✔
407
                repo += "-android"
1✔
408
            elif date < datetime.date(2014, 12, 13):
1✔
409
                repo += "-android-api-10"
1✔
410
            elif date < datetime.date(2016, 1, 29):
1✔
411
                repo += "-android-api-11"
1✔
412
            elif date < datetime.date(2017, 8, 30):
1✔
413
                repo += "-android-api-15"
1✔
414
            else:
415
                repo += "-android-api-16"
1✔
416
        return self._get_nightly_repo_regex(date, repo)
1✔
417

418

419
class FenixNightlyConfigMixin(NightlyConfigMixin):
1✔
420
    nightly_base_repo_name = "fenix"
1✔
421
    arch_regex_bits = ""
1✔
422

423
    def _get_nightly_repo(self, date):
1✔
424
        return "fenix"
1✔
425

426
    def get_nightly_repo_regex(self, date):
1✔
427
        repo = self.get_nightly_repo(date)
1✔
428
        repo += self.arch_regex_bits  # e.g., ".*arm64.*".
1✔
429
        return self._get_nightly_repo_regex(date, repo)
1✔
430

431

432
class FocusNightlyConfigMixin(FenixNightlyConfigMixin):
1✔
433
    nightly_base_repo_name = "focus"
1✔
434

435
    def _get_nightly_repo(self, date):
1✔
436
        return "focus"
1✔
437

438

439
class IntegrationConfigMixin(metaclass=ABCMeta):
1✔
440
    """
441
    Define the integration-related required configuration.
442
    """
443

444
    default_integration_branch = "mozilla-central"
1✔
445
    _tk_credentials = None
1✔
446

447
    @property
1✔
448
    def integration_branch(self):
1✔
449
        return self.repo or self.default_integration_branch
1✔
450

451
    def tk_route(self, push):
1✔
452
        """
453
        Returns the first taskcluster route for a specific changeset
454
        """
455
        return next(self.tk_routes(push))
1✔
456

457
    @abstractmethod
1✔
458
    def tk_routes(self, push):
1✔
459
        """
460
        Returns a generator of taskcluster routes for a specific changeset.
461
        """
462
        raise NotImplementedError
463

464
    def integration_persist_part(self):
1✔
465
        """
466
        Allow to add a part in the generated persist file name to distinguish
467
        builds. Returns an empty string by default, or 'debug' if build type
468
        is debug.
469
        """
470
        return self.build_type if self.build_type != "opt" else ""
1✔
471

472
    def tk_needs_auth(self):
1✔
473
        """
474
        Returns True if we need taskcluster credentials
475
        """
476
        return False
1✔
477

478
    def set_tk_credentials(self, creds):
1✔
479
        """
480
        Define the credentials required to download private builds on
481
        TaskCluster.
482
        """
483
        self._tk_credentials = creds
×
484

485
    def tk_options(self):
1✔
486
        """
487
        Returns the takcluster options, including the credentials required to
488
        download private artifacts.
489
        """
490
        tk_options = {"rootUrl": "https://firefox-ci-tc.services.mozilla.com"}
1✔
491
        if self.tk_needs_auth():
1✔
492
            tk_options.update({"credentials": self._tk_credentials})
×
493
        return tk_options
1✔
494

495

496
def _common_tk_part(integration_conf):
1✔
497
    # private method to avoid copy/paste for building taskcluster route part.
498
    if integration_conf.os == "linux":
1✔
499
        part = "linux"
1✔
500
        if integration_conf.bits == 64:
1✔
501
            part += str(integration_conf.bits)
1✔
502
    elif integration_conf.os == "mac":
1✔
503
        part = "macosx64"
1✔
504
    else:
505
        # windows
506
        part = "{}{}".format(integration_conf.os, integration_conf.bits)
1✔
507
        if integration_conf.processor == "aarch64" and integration_conf.bits == 64:
1✔
508
            part += "-aarch64"
1✔
509
    return part
1✔
510

511

512
class FirefoxIntegrationConfigMixin(IntegrationConfigMixin):
1✔
513
    def tk_routes(self, push):
1✔
514
        for build_type in self.build_types:
1✔
515
            yield "gecko.v2.{}{}.revision.{}.firefox.{}-{}".format(
1✔
516
                self.integration_branch,
517
                ".shippable" if build_type == "shippable" else "",
518
                push.changeset,
519
                _common_tk_part(self),
520
                "opt" if build_type == "shippable" else build_type,
521
            )
522
            self._inc_used_build()
1✔
523
        return
1✔
524

525

526
class FennecIntegrationConfigMixin(IntegrationConfigMixin):
1✔
527
    tk_name = "android-api-11"
1✔
528

529
    def tk_routes(self, push):
1✔
530
        tk_name = self.tk_name
1✔
531
        if tk_name == "android-api-11":
1✔
532
            if push.timestamp >= TIMESTAMP_GECKOVIEW_ARM:
1✔
533
                tk_name = "android-arm"
×
534
            elif push.timestamp >= TIMESTAMP_FENNEC_API_16:
1✔
535
                tk_name = "android-api-16"
1✔
536
            elif push.timestamp >= TIMESTAMP_FENNEC_API_15:
1✔
537
                tk_name = "android-api-15"
1✔
538
        for build_type in self.build_types:
1✔
539
            yield "gecko.v2.{}{}.revision.{}.mobile.{}-{}".format(
1✔
540
                self.integration_branch,
541
                ".shippable" if build_type == "shippable" else "",
542
                push.changeset,
543
                tk_name,
544
                "opt" if build_type == "shippable" else build_type,
545
            )
546
            self._inc_used_build()
×
547
        return
×
548

549

550
class ThunderbirdIntegrationConfigMixin(IntegrationConfigMixin):
1✔
551
    default_integration_branch = "comm-central"
1✔
552

553
    def tk_routes(self, push):
1✔
554
        for build_type in self.build_types:
1✔
555
            yield "comm.v2.{}.revision.{}.thunderbird.{}-{}".format(
1✔
556
                self.integration_branch,
557
                push.changeset,
558
                _common_tk_part(self),
559
                build_type,
560
            )
561
            self._inc_used_build()
×
562
        return
×
563

564

565
# ------------ full config implementations ------------
566

567

568
REGISTRY = ClassRegistry("app_name")
1✔
569

570

571
def create_config(name, os, bits, processor, arch=None):
1✔
572
    """
573
    Create and returns a configuration for the given name.
574

575
    :param name: application name, such as 'firefox'
576
    :param os: os name, e.g 'linux', 'win' or 'mac'
577
    :param bits: the bit of the os as an int, e.g 32 or 64. Can be None
578
                 if the bits do not make sense (e.g. fennec)
579
    :param processor: processor family, e.g 'x86', 'x86_64', 'ppc', 'ppc64' or
580
                      'aarch64'
581
    :param arch: architecture of the target build. e.g. From a linux64 machine
582
                 you can run an ARM GVE build (default) or an x86_64 build,
583
                 this is controlled by the arch parameter.
584
    """
585
    return REGISTRY.get(name)(os, bits, processor, arch)
1✔
586

587

588
class L10nMixin:
1✔
589
    def set_lang(self, lang):
1✔
590
        LOG.info("setting lang to {}".format(lang))
1✔
591
        self.lang = lang
1✔
592

593
    def build_regex(self):
1✔
594
        return (
1✔
595
            get_build_regex(
596
                self.app_name,
597
                self.os,
598
                self.bits,
599
                self.processor,
600
                platprefix=r".*\." + self.lang + r"\.",
601
                arch=self.arch,
602
            )
603
            + "$"
604
        )
605

606

607
@REGISTRY.register("firefox")
1✔
608
class FirefoxConfig(CommonConfig, FirefoxNightlyConfigMixin, FirefoxIntegrationConfigMixin):
1✔
609
    BUILD_TYPES = (
1✔
610
        "shippable",
611
        "opt",
612
        "pgo[linux32,linux64,win32,win64]",
613
        "debug",
614
        "asan[linux64]",
615
        "asan-debug[linux64]",
616
    )
617
    BUILD_TYPE_FALLBACKS = {
1✔
618
        "shippable": ("opt", "pgo"),
619
        "opt": ("shippable", "pgo"),
620
    }
621

622
    def __init__(self, os, bits, processor, arch):
1✔
623
        super(FirefoxConfig, self).__init__(os, bits, processor, arch)
1✔
624
        self.set_build_type("shippable")
1✔
625

626
    def build_regex(self):
1✔
627
        return (
1✔
628
            get_build_regex(
629
                self.app_name,
630
                self.os,
631
                self.bits,
632
                self.processor,
633
                platsuffix="-asan-reporter" if "asan" in self.build_type else "",
634
                arch=self.arch,
635
            )
636
            + "$"
637
        )
638

639
    def available_bits(self):
1✔
640
        """
641
        Returns the available bits for this application.
642
        """
NEW
643
        return ()
×
644

645
    def available_archs(self):
1✔
646
        """
647
        Returns the available architectures for this application.
648
        """
NEW
649
        return ["x86", "x86_64", "aarch64"]
×
650

651

652
@REGISTRY.register("firefox-l10n", attr_value="firefox")
1✔
653
class FirefoxL10nConfig(L10nMixin, FirefoxL10nNightlyConfigMixin, CommonConfig):
1✔
654
    def available_bits(self):
1✔
655
        """
656
        Returns the available bits for this application.
657
        """
NEW
658
        return ()
×
659

660
    def available_archs(self):
1✔
661
        """
662
        Returns the available architectures for this application.
663
        """
NEW
664
        return ["x86", "x86_64", "aarch64"]
×
665

666

667
@REGISTRY.register("thunderbird")
1✔
668
class ThunderbirdConfig(
1✔
669
    CommonConfig, ThunderbirdNightlyConfigMixin, ThunderbirdIntegrationConfigMixin
670
):
671
    pass
672

673

674
@REGISTRY.register("thunderbird-l10n", attr_value="thunderbird")
1✔
675
class ThunderbirdL10nConfig(L10nMixin, ThunderbirdL10nNightlyConfigMixin, CommonConfig):
1✔
676
    pass
677

678

679
@REGISTRY.register("fennec")
1✔
680
class FennecConfig(CommonConfig, FennecNightlyConfigMixin, FennecIntegrationConfigMixin):
1✔
681
    BUILD_TYPES = ("shippable", "opt", "pgo", "debug")
1✔
682
    BUILD_TYPE_FALLBACKS = {
1✔
683
        "shippable": ("opt", "pgo"),
684
        "opt": ("shippable", "pgo"),
685
    }
686

687
    def build_regex(self):
1✔
688
        return r"(target|fennec-.*)\.apk"
1✔
689

690
    def build_info_regex(self):
1✔
691
        return r"(target|fennec-.*)\.txt"
1✔
692

693
    def available_bits(self):
1✔
694
        return ()
×
695

696

697
@REGISTRY.register("fenix")
1✔
698
class FenixConfig(CommonConfig, FenixNightlyConfigMixin):
1✔
699
    def build_regex(self):
1✔
700
        return r"fenix-.+\.apk"
1✔
701

702
    def available_bits(self):
1✔
703
        return ()
×
704

705
    def available_archs(self):
1✔
706
        return [
×
707
            "arm64-v8a",
708
            "armeabi-v7a",
709
            "x86",
710
            "x86_64",
711
        ]
712

713
    def set_arch(self, arch):
1✔
714
        CommonConfig.set_arch(self, arch)
1✔
715
        # Map "arch" value to one that can be used in the nightly repo regex lookup.
716
        mapping = {
1✔
717
            "arm64-v8a": "-.+-android-arm64-v8a",
718
            "armeabi-v7a": "-.+-android-armeabi-v7a",
719
            "x86": "-.+-android-x86",
720
            "x86_64": "-.+-android-x86_64",
721
        }
722
        self.arch_regex_bits = mapping.get(self.arch, "")
1✔
723

724
    def should_use_archive(self):
1✔
725
        return True
×
726

727

728
@REGISTRY.register("focus")
1✔
729
class FocusConfig(FenixConfig, FocusNightlyConfigMixin):
1✔
730
    def build_regex(self):
1✔
731
        return r"focus-.+\.apk"
1✔
732

733

734
@REGISTRY.register("gve")
1✔
735
class GeckoViewExampleConfig(CommonConfig, FennecNightlyConfigMixin, FennecIntegrationConfigMixin):
1✔
736
    BUILD_TYPES = ("shippable", "opt", "debug")
1✔
737
    BUILD_TYPE_FALLBACKS = {
1✔
738
        "shippable": ("opt",),
739
        "opt": ("shippable",),
740
    }
741

742
    def build_regex(self):
1✔
743
        return r"geckoview_example\.apk"
1✔
744

745
    def build_info_regex(self):
1✔
746
        return r"(target|fennec-.*)\.txt"
1✔
747

748
    def available_bits(self):
1✔
749
        return ()
×
750

751
    def available_archs(self):
1✔
752
        return ["arm", "x86_64", "aarch64"]
×
753

754
    def set_arch(self, arch):
1✔
755
        CommonConfig.set_arch(self, arch)
1✔
756
        if arch == "aarch64":
1✔
757
            self.tk_name = "android-aarch64"
1✔
758
        elif arch == "x86_64":
1✔
759
            self.tk_name = "android-x86_64"
1✔
760
        else:
761
            self.tk_name = "android-api-11"
1✔
762

763
    def should_use_archive(self):
1✔
764
        # GVE is not on archive.mozilla.org, only on taskcluster
765
        return False
×
766

767
    def extra_persist_part(self):
1✔
768
        if self.arch is None:
1✔
769
            return "arm"
1✔
770
        else:
771
            return self.arch
1✔
772

773

774
@REGISTRY.register("jsshell", disable_in_gui=True)
1✔
775
class JsShellConfig(FirefoxConfig):
1✔
776
    def build_info_regex(self):
1✔
777
        # the info file is the one for firefox
778
        return (
1✔
779
            get_build_regex(
780
                "firefox", self.os, self.bits, self.processor, with_ext=False, arch=self.arch
781
            )
782
            + r"\.txt$"
783
        )
784

785
    def build_regex(self):
1✔
786
        arch = self.arch
1✔
787
        if arch is None:
1✔
788
            arch = infer_arch_from_bits(self.os, self.bits, self.processor)
1✔
789

790
        if self.os == "linux":
1✔
791
            if arch == "aarch64":
1✔
792
                part = "linux-aarch64"
1✔
793
            elif arch == "x86_64":
1✔
794
                part = "linux-x86_64"
1✔
795
            else:
796
                part = "linux-i686"
1✔
797
        elif self.os == "win":
1✔
798
            if arch == "aarch64":
1✔
799
                part = "win64-aarch64"
1✔
800
            elif arch == "x86_64":
1✔
801
                part = "win64(-x86_64)?"
1✔
802
            else:
803
                part = "win32"
1✔
804
        else:
805
            part = "mac"
1✔
806
        psuffix = "-asan" if "asan" in self.build_type else ""
1✔
807
        return r"jsshell-%s%s\.zip$" % (part, psuffix)
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc