예제 #1
0
def test_firefox_version_ensures_it_does_not_have_multiple_type(
        monkeypatch, version_string):
    # Let's make sure the sanity checks detect a broken regular expression
    monkeypatch.setattr(mozilla_version.gecko, '_VALID_ENOUGH_VERSION_PATTERN',
                        _SUPER_PERMISSIVE_PATTERN)

    with pytest.raises(TooManyTypesError):
        FirefoxVersion.parse(version_string)
예제 #2
0
def test_firefox_version_ensures_it_does_not_have_multiple_type(
        monkeypatch, version_string):
    # Let's make sure the sanity checks detect a broken regular expression
    original_pattern = FirefoxVersion._VALID_ENOUGH_VERSION_PATTERN
    FirefoxVersion._VALID_ENOUGH_VERSION_PATTERN = _SUPER_PERMISSIVE_PATTERN

    with pytest.raises(TooManyTypesError):
        FirefoxVersion.parse(version_string)

    FirefoxVersion._VALID_ENOUGH_VERSION_PATTERN = original_pattern
예제 #3
0
def good_version(release):
    '''Can the version be parsed by mozilla_version

    Some ancient versions cannot be parsed by the mozilla_version module. This
    function helps to skip the versions that are not supported.
    Example versions that cannot be parsed:
    1.1, 1.1b1, 2.0.0.1
    '''
    try:
        FirefoxVersion.parse(release['version'])
        return True
    except ValueError:
        return False
예제 #4
0
def test_firefox_version_constructor_minimum_kwargs():
    assert str(FirefoxVersion(32, 0)) == '32.0'
    assert str(FirefoxVersion(32, 0, 1)) == '32.0.1'
    assert str(FirefoxVersion(32, 1, 0)) == '32.1.0'
    assert str(FirefoxVersion(32, 0, 1, 1)) == '32.0.1build1'
    assert str(FirefoxVersion(32, 0, beta_number=1)) == '32.0b1'
    assert str(FirefoxVersion(32, 0, is_nightly=True)) == '32.0a1'
    assert str(FirefoxVersion(32, 0, is_aurora_or_devedition=True)) == '32.0a2'
    assert str(FirefoxVersion(32, 0, is_esr=True)) == '32.0esr'
    assert str(FirefoxVersion(32, 0, 1, is_esr=True)) == '32.0.1esr'
def _generate_beetmover_template_args_maven(task, release_props):
    tmpl_args = {
        'artifact_id': task['payload']['artifact_id'],
        'template_key': 'maven_{}'.format(release_props['appName']),
    }

    # FIXME: this is a temporarily solution while we sanitize the payload
    # under https://github.com/mozilla-releng/beetmoverscript/issues/196
    if 'SNAPSHOT' in task['payload']['version']:
        payload_version = MavenVersion.parse(task['payload']['version'])
    else:
        payload_version = FirefoxVersion.parse(task['payload']['version'])
    # Change version number to major.minor.buildId because that's what the build task produces
    version = [
        payload_version.major_number, payload_version.minor_number,
        release_props.get('buildid', payload_version.patch_number)
    ]
    if any(number is None for number in version):
        raise TaskVerificationError(
            'At least one digit is undefined. Got: {}'.format(version))
    tmpl_args['version'] = '.'.join(str(n) for n in version)

    if isinstance(payload_version,
                  MavenVersion) and payload_version.is_snapshot:
        tmpl_args['snapshot_version'] = payload_version
        tmpl_args['date_timestamp'] = "{{date_timestamp}}"
        tmpl_args['clock_timestamp'] = "{{clock_timestamp}}"
        tmpl_args['build_number'] = "{{build_number}}"

    return tmpl_args
예제 #6
0
def _generate_beetmover_template_args_maven(task, release_props):
    tmpl_args = {
        "artifact_id": task["payload"]["artifact_id"],
        "template_key": "maven_{}".format(release_props["appName"])
    }

    # Geckoview follows the FirefoxVersion pattern
    if release_props.get("appName") == "geckoview":
        payload_version = FirefoxVersion.parse(task["payload"]["version"])
        # Change version number to major.minor.buildId because that's what the build task produces
        version = [
            payload_version.major_number, payload_version.minor_number,
            release_props["buildid"]
        ]
    else:
        payload_version = MavenVersion.parse(task["payload"]["version"])
        version = [
            payload_version.major_number, payload_version.minor_number,
            payload_version.patch_number
        ]

    if any(number is None for number in version):
        raise TaskVerificationError(
            "At least one digit is undefined. Got: {}".format(version))
    tmpl_args["version"] = ".".join(str(n) for n in version)

    # XXX: some appservices maven.zip files have a different structure,
    # encompassing only `pom` and `jar` files. We toggle that behavior in the
    # mapping by using this flag
    tmpl_args["is_jar"] = task["payload"].get("is_jar")

    return tmpl_args
예제 #7
0
def is_partner_enabled(product, version, min_version=60):
    if product == "firefox":
        firefox_version = FirefoxVersion.parse(version)
        return firefox_version.major_number >= min_version and any(
            (firefox_version.is_beta and firefox_version.beta_number >= 8,
             firefox_version.is_release, firefox_version.is_esr))

    return False
예제 #8
0
def is_eme_free_enabled(product, version):
    if product == "firefox":
        firefox_version = FirefoxVersion.parse(version)
        return any(
            (firefox_version.is_beta
             and firefox_version.beta_number >= 8, firefox_version.is_release))

    return False
예제 #9
0
def check_versions_are_successive(current_version, payload_version, product):
    """Function to check if the provided version in the payload and the existing
    one in bouncer are successive as valid versions."""
    def _successive_sanity(current_identifier, candidate_identifier):
        if current_identifier == candidate_identifier:
            err_msg = (
                "Identifiers for {} and {} can't be equal at this point "
                "in the code".format(payload_version, current_version))
            raise ScriptWorkerTaskException(err_msg)
        elif current_identifier > candidate_identifier:
            err_msg = ("In-tree version {} can't be less than current bouncer "
                       "counterpart".format(payload_version, current_version))
            raise ScriptWorkerTaskException(err_msg)
        elif (candidate_identifier - current_identifier) > 1:
            err_msg = (
                "In-tree version {} can't be greater than current bouncer "
                "by more than 1 digit".format(payload_version,
                                              current_version))
            raise ScriptWorkerTaskException(err_msg)

    # XXX: for Firefox central nightlies we need to handle the major number
    # while for Fennec nightlies on ESR we need to handle minor_number
    if product == "firefox":
        current_bouncer_version = FirefoxVersion.parse(current_version)
        candidate_version = FirefoxVersion.parse(payload_version)

        _successive_sanity(current_bouncer_version.major_number,
                           candidate_version.major_number)
    elif product == "fennec":
        # XXX: this will fail for the next ESR cut, on 75, since that will be a
        # major_number bump, but also a minor_number. But cutting ESR releases
        # can vary over time (could be 7 releases or 8 like ESR8, etc);
        # It's unrecommended to hardcode those variable window times here
        # in order to ensure the check; So for now we leave this code smell here.
        # Real fix is to centralize this operation and implement it in mozilla-version directly
        current_bouncer_version = FennecVersion.parse(current_version)
        candidate_version = FennecVersion.parse(payload_version)

        _successive_sanity(current_bouncer_version.minor_number,
                           candidate_version.minor_number)
    else:
        err_msg = "Unknown product {} in the payload".format(product)
        raise ScriptWorkerTaskException(err_msg)

    log.info("Versions are successive. All good")
예제 #10
0
def test_firefox_version_supports_released_edge_cases(version_string):
    assert str(FirefoxVersion.parse(version_string)) == version_string
    for Class in (DeveditionVersion, FennecVersion, ThunderbirdVersion):
        if Class == FennecVersion and version_string in ('33.1', '33.1build1',
                                                         '33.1build2'):
            # These edge cases also exist in Fennec
            continue
        with pytest.raises(PatternNotMatchedError):
            Class.parse(version_string)
예제 #11
0
def test_firefox_version_constructor_and_str(major_number, minor_number,
                                             patch_number, beta_number,
                                             build_number, is_nightly,
                                             is_aurora_or_devedition, is_esr,
                                             expected_output_string):
    assert str(
        FirefoxVersion(major_number=major_number,
                       minor_number=minor_number,
                       patch_number=patch_number,
                       beta_number=beta_number,
                       build_number=build_number,
                       is_nightly=is_nightly,
                       is_aurora_or_devedition=is_aurora_or_devedition,
                       is_esr=is_esr)) == expected_output_string
예제 #12
0
def test_fail_firefox_version_constructor(major_number, minor_number,
                                          patch_number, beta_number,
                                          build_number, is_nightly,
                                          is_aurora_or_devedition, is_esr,
                                          ExpectedErrorType):
    with pytest.raises(ExpectedErrorType):
        FirefoxVersion(major_number=major_number,
                       minor_number=minor_number,
                       patch_number=patch_number,
                       beta_number=beta_number,
                       build_number=build_number,
                       is_nightly=is_nightly,
                       is_aurora_or_devedition=is_aurora_or_devedition,
                       is_esr=is_esr)
예제 #13
0
def test_balrog_release_name_constructor_and_str(
        product, major_number, minor_number, patch_number, beta_number,
        build_number, is_nightly, is_aurora_or_devedition, is_esr,
        expected_output_string):
    assert str(
        BalrogReleaseName(
            product,
            FirefoxVersion(major_number=major_number,
                           minor_number=minor_number,
                           patch_number=patch_number,
                           build_number=build_number,
                           beta_number=beta_number,
                           is_nightly=is_nightly,
                           is_aurora_or_devedition=is_aurora_or_devedition,
                           is_esr=is_esr))) == expected_output_string
예제 #14
0
def test_fail_balrog_release_constructor(product, major_number, minor_number,
                                         patch_number, beta_number,
                                         build_number, is_nightly,
                                         is_aurora_or_devedition, is_esr,
                                         ExpectedErrorType):
    with pytest.raises(ExpectedErrorType):
        BalrogReleaseName(
            product,
            FirefoxVersion(major_number=major_number,
                           minor_number=minor_number,
                           patch_number=patch_number,
                           beta_number=beta_number,
                           build_number=build_number,
                           is_nightly=is_nightly,
                           is_aurora_or_devedition=is_aurora_or_devedition,
                           is_esr=is_esr))
예제 #15
0
def list_releases(product=None, branch=None, version=None, build_number=None,
                  status=['scheduled']):
    session = current_app.db.session
    releases = session.query(Release)
    if product:
        releases = releases.filter(Release.product == product)
    if branch:
        releases = releases.filter(Release.branch == branch)
    if version:
        releases = releases.filter(Release.version == version)
        if build_number:
            releases = releases.filter(Release.build_number == build_number)
    elif build_number:
        raise BadRequest(description='Filtering by build_number without version'
                         ' is not supported.')
    releases = releases.filter(Release.status.in_(status))
    releases = [r.json for r in releases.all()]
    # filter out not parsable releases, like 1.1, 1.1b1, etc
    releases = filter(good_version, releases)
    return sorted(releases, key=lambda r: FirefoxVersion.parse(r['version']))
예제 #16
0
def _generate_beetmover_template_args_maven(task, release_props):
    tmpl_args = {
        'artifact_id': task['payload']['artifact_id'],
        'template_key': 'maven_{}'.format(release_props['appName']),
    }

    # Geckoview follows the FirefoxVersion pattern
    if release_props.get('appName') == 'geckoview':
        payload_version = FirefoxVersion.parse(task['payload']['version'])
        # Change version number to major.minor.buildId because that's what the build task produces
        version = [
            payload_version.major_number,
            payload_version.minor_number,
            release_props['buildid'],
        ]
    else:
        payload_version = MavenVersion.parse(task['payload']['version'])
        version = [
            payload_version.major_number,
            payload_version.minor_number,
            payload_version.patch_number,
        ]

    if any(number is None for number in version):
        raise TaskVerificationError(
            'At least one digit is undefined. Got: {}'.format(version))
    tmpl_args['version'] = '.'.join(str(n) for n in version)

    # XXX: some appservices maven.zip files have a different structure,
    # encompassing only `pom` and `jar` files. We toggle that behavior in the
    # mapping by using this flag
    tmpl_args['is_jar'] = task['payload'].get('is_jar')

    if isinstance(payload_version,
                  MavenVersion) and payload_version.is_snapshot:
        tmpl_args['snapshot_version'] = payload_version
        tmpl_args['date_timestamp'] = "{{date_timestamp}}"
        tmpl_args['clock_timestamp'] = "{{clock_timestamp}}"
        tmpl_args['build_number'] = "{{build_number}}"

    return tmpl_args
예제 #17
0
def get_maven_version(context):
    """Extract and validate a valid Maven version"""
    version = context.task["payload"]["version"]
    release_props = context.release_props
    # TODO The following 'if' should be removed once GeckoView >= 84 is in mozilla-release.
    # This is a temporary solution to maintain compatibility while the 'version' field in
    # GeckoView's payload transitions from FirefoxVersion format to MavenVersion.
    if release_props.get("appName") == "geckoview":
        app_version = FirefoxVersion.parse(release_props["appVersion"])
        if int(app_version.major_number) < 84:
            # Change version number to major.minor.buildId because that's what the build task produces
            version = "{}.{}.{}".format(app_version.major_number,
                                        app_version.minor_number,
                                        release_props["buildid"])

    # Check that version is a valid maven version
    try:
        MavenVersion.parse(version)
    except (ValueError, PatternNotMatchedError) as e:
        raise ScriptWorkerTaskException(
            f"Version defined in the payload does not match the pattern of a MavenVersion. Got: {version}"
        ) from e

    return version
예제 #18
0
def test_firefox_version_raises_when_invalid_version_is_given(
        version_string, ExpectedErrorType):
    with pytest.raises(ExpectedErrorType):
        FirefoxVersion.parse(version_string)
예제 #19
0
from shipit_api.release import is_eme_free_enabled
from shipit_api.release import is_partner_enabled
from shipit_api.release import is_rc
from shipit_api.release import parse_version


@pytest.mark.parametrize('product, version, expectation, result', (
    ('devedition', '56.0b1', does_not_raise(),
     DeveditionVersion(56, 0, beta_number=1)),
    (Product.DEVEDITION, '56.0b1', does_not_raise(),
     DeveditionVersion(56, 0, beta_number=1)),
    ('fennec', '68.2b3', does_not_raise(), FennecVersion(68, 2,
                                                         beta_number=3)),
    (Product.FENNEC, '68.2b3', does_not_raise(),
     FennecVersion(68, 2, beta_number=3)),
    ('firefox', '45.0', does_not_raise(), FirefoxVersion(45, 0)),
    (Product.FIREFOX, '45.0', does_not_raise(), FirefoxVersion(45, 0)),
    ('thunderbird', '60.8.0', does_not_raise(), ThunderbirdVersion(60, 8, 0)),
    (Product.THUNDERBIRD, '60.8.0', does_not_raise(),
     ThunderbirdVersion(60, 8, 0)),
    ('non-existing-product', '68.0', pytest.raises(ValueError), None),
))
def test_parse_version(product, version, expectation, result):
    with expectation:
        assert parse_version(product, version) == result


@pytest.mark.parametrize('product, version, partial_updates, result', (
    ('firefox', '57.0', {
        '56.0b1': [],
        '55.0': []
예제 #20
0
from shipit_api.admin.api import get_signoff_emails
from shipit_api.admin.release import bump_version, is_eme_free_enabled, is_partner_enabled, is_rc, parse_version
from shipit_api.common.models import XPISignoff
from shipit_api.common.product import Product


@pytest.mark.parametrize(
    "product, version, expectation, result",
    (
        ("devedition", "56.0b1", does_not_raise(), DeveditionVersion(56, 0, beta_number=1)),
        (Product.DEVEDITION, "56.0b1", does_not_raise(), DeveditionVersion(56, 0, beta_number=1)),
        ("fenix", "84.0.0-beta.2", does_not_raise(), FenixVersion(84, 0, 0, beta_number=2)),
        (Product.FENIX, "84.0.0", does_not_raise(), FenixVersion(84, 0, 0)),
        ("fennec", "68.2b3", does_not_raise(), FennecVersion(68, 2, beta_number=3)),
        (Product.FENNEC, "68.2b3", does_not_raise(), FennecVersion(68, 2, beta_number=3)),
        ("firefox", "45.0", does_not_raise(), FirefoxVersion(45, 0)),
        (Product.FIREFOX, "45.0", does_not_raise(), FirefoxVersion(45, 0)),
        ("thunderbird", "60.8.0", does_not_raise(), ThunderbirdVersion(60, 8, 0)),
        (Product.THUNDERBIRD, "60.8.0", does_not_raise(), ThunderbirdVersion(60, 8, 0)),
        ("non-existing-product", "68.0", pytest.raises(ValueError), None),
        # fennec_release used to be a valid value when we moved Fennec to ESR68
        # https://github.com/mozilla/release-services/pull/2265
        # Let's be explicitly failing about it.
        ("fennec_release", "68.1.1", pytest.raises(ValueError), None),
    ),
)
def test_parse_version(product, version, expectation, result):
    with expectation:
        assert parse_version(product, version) == result

예제 #21
0
def test_firefox_version_implements_str_operator(version_string,
                                                 expected_output):
    assert str(FirefoxVersion.parse(version_string)) == expected_output
예제 #22
0
def test_firefox_version_raises_eq_operator(wrong_type):
    with pytest.raises(ValueError):
        assert FirefoxVersion.parse('32.0') == wrong_type
    # AttributeError is raised by LooseVersion and StrictVersion
    with pytest.raises((ValueError, AttributeError)):
        assert wrong_type == FirefoxVersion.parse('32.0')
예제 #23
0
def test_firefox_version_implements_remaining_comparision_operators():
    assert FirefoxVersion.parse('32.0') <= FirefoxVersion.parse('32.0')
    assert FirefoxVersion.parse('32.0') <= FirefoxVersion.parse('33.0')

    assert FirefoxVersion.parse('33.0') >= FirefoxVersion.parse('32.0')
    assert FirefoxVersion.parse('33.0') >= FirefoxVersion.parse('33.0')

    assert FirefoxVersion.parse('33.0') > FirefoxVersion.parse('32.0')
    assert not FirefoxVersion.parse('33.0') > FirefoxVersion.parse('33.0')

    assert not FirefoxVersion.parse('32.0') < FirefoxVersion.parse('32.0')

    assert FirefoxVersion.parse('33.0') != FirefoxVersion.parse('32.0')
예제 #24
0
def test_firefox_version_implements_eq_operator(equivalent_version_string):
    assert FirefoxVersion.parse('32.0') == FirefoxVersion.parse(
        equivalent_version_string)
    # raw strings are also converted
    assert FirefoxVersion.parse('32.0') == equivalent_version_string
예제 #25
0
def test_firefox_version_implements_lt_operator(previous, next):
    assert FirefoxVersion.parse(previous) < FirefoxVersion.parse(next)
예제 #26
0
def test_firefox_version_is_of_a_defined_type(version_string, expected_type):
    release = FirefoxVersion.parse(version_string)
    assert getattr(release, 'is_{}'.format(expected_type))
예제 #27
0
from shipit_api.admin.api import get_signoff_emails
from shipit_api.admin.release import bump_version, is_eme_free_enabled, is_partner_enabled, is_rc, parse_version
from shipit_api.common.models import XPISignoff
from shipit_api.common.product import Product


@pytest.mark.parametrize(
    "product, version, expectation, result",
    (
        ("devedition", "56.0b1", does_not_raise(),
         DeveditionVersion(56, 0, beta_number=1)),
        (Product.DEVEDITION, "56.0b1", does_not_raise(),
         DeveditionVersion(56, 0, beta_number=1)),
        ("pinebuild", "56.0b1", does_not_raise(),
         FirefoxVersion(56, 0, beta_number=1)),
        (Product.PINEBUILD, "56.0b1", does_not_raise(),
         FirefoxVersion(56, 0, beta_number=1)),
        ("fenix", "84.0.0-beta.2", does_not_raise(),
         FenixVersion(84, 0, 0, beta_number=2)),
        (Product.FENIX, "84.0.0", does_not_raise(), FenixVersion(84, 0, 0)),
        ("fennec", "68.2b3", does_not_raise(),
         FennecVersion(68, 2, beta_number=3)),
        (Product.FENNEC, "68.2b3", does_not_raise(),
         FennecVersion(68, 2, beta_number=3)),
        ("firefox", "45.0", does_not_raise(), FirefoxVersion(45, 0)),
        (Product.FIREFOX, "45.0", does_not_raise(), FirefoxVersion(45, 0)),
        ("thunderbird", "60.8.0", does_not_raise(), ThunderbirdVersion(
            60, 8, 0)),
        (Product.THUNDERBIRD, "60.8.0", does_not_raise(),
         ThunderbirdVersion(60, 8, 0)),
예제 #28
0
    mocker.patch.object(merges, "replace", new=noop_replace)
    mocker.patch.object(merges, "touch_clobber_file", new=sync_noop)

    await merges.apply_rebranding(config, repo_context.repo, merge_config)
    assert called_args[0] == expected


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "version_config,current_version, expected",
    (
        # central-to-beta
        ({
            "filename": "config/milestone.txt",
            "new_suffix": ""
        }, FirefoxVersion.parse("75.0a1"), "75.0"),
        ({
            "filename": "browser/config/version_display.txt",
            "new_suffix": "b1"
        }, FirefoxVersion.parse("75.0a1"), "75.0b1"),
        # beta-to-release
        ({
            "filename": "browser/config/version_display.txt",
            "new_suffix": ""
        }, FirefoxVersion.parse("75.0b9"), "75.0"),
        # bump_central
        ({
            "filename": "config/milestone.txt",
            "version_bump": "major"
        }, FirefoxVersion.parse("75.0a1"), "76.0a1"),
        ({
예제 #29
0
 def mocked_get_version(path, repo_path):
     return FirefoxVersion.parse("76.0")
예제 #30
0
    mocker.patch.object(merges, "get_version", new=mocked_get_version)
    mocker.patch.object(merges, "do_bump_version", new=noop_bump_version)
    mocker.patch.object(shutil, "copyfile", new=noop_copyfile)
    mocker.patch.object(merges, "replace", new=noop_replace)
    mocker.patch.object(merges, "touch_clobber_file", new=sync_noop)

    await merges.apply_rebranding(config, repo_context.repo, merge_config)
    assert called_args[0] == expected


@pytest.mark.asyncio
@pytest.mark.parametrize(
    "version_config,current_version, expected",
    (
        # central-to-beta
        ({"filename": "config/milestone.txt", "new_suffix": ""}, FirefoxVersion.parse("75.0a1"), "75.0"),
        ({"filename": "browser/config/version_display.txt", "new_suffix": "b1"}, FirefoxVersion.parse("75.0a1"), "75.0b1"),
        # beta-to-release
        ({"filename": "browser/config/version_display.txt", "new_suffix": ""}, FirefoxVersion.parse("75.0b9"), "75.0"),
        # bump_central
        ({"filename": "config/milestone.txt", "version_bump": "major"}, FirefoxVersion.parse("75.0a1"), "76.0a1"),
        ({"filename": "config/milestone.txt", "version_bump": "major"}, FirefoxVersion.parse("75.0"), "76.0"),
        # bump_esr
        ({"filename": "browser/config/version.txt", "version_bump": "minor"}, FirefoxVersion.parse("68.1.0"), "68.2.0"),
        ({"filename": "browser/config/version_display.txt", "version_bump": "minor"}, FirefoxVersion.parse("68.1.0esr"), "68.2.0esr"),
        ({"filename": "mobile/android/config/version-files/beta/version.txt", "version_bump": "minor"}, FennecVersion.parse("68.1"), "68.2"),
        ({"filename": "mobile/android/config/version-files/beta/version_display.txt", "version_bump": "minor"}, FennecVersion.parse("68.1b9"), "68.2b1"),
        ({"filename": "mobile/android/config/version-files/nightly/version.txt", "version_bump": "minor"}, FennecVersion.parse("68.1a1"), "68.2a1"),
        ({"filename": "mobile/android/config/version-files/release/version.txt", "version_bump": "minor"}, FennecVersion.parse("68.6.1"), "68.7.0"),
    ),
)