コード例 #1
0
async def test_bump_version_esr_dont_bump_non_esr(mocker, config, tmpdir, new_version, expect_esr_version):
    version = "52.0.1"
    repo = os.path.join(tmpdir, "repo")
    os.mkdir(repo)
    os.mkdir(os.path.join(repo, "config"))
    os.makedirs(os.path.join(repo, "browser", "config"))
    version_file = os.path.join("config", "milestone.txt")
    with open(os.path.join(repo, version_file), "w") as f:
        f.write(version)
    display_version_file = os.path.join("browser", "config", "version_display.txt")
    with open(os.path.join(repo, display_version_file), "w") as f:
        f.write(version + "esr")

    called_args = []

    async def run_command(context, *arguments, repo_path=None):
        called_args.append([tuple([context]) + arguments, {"repo_path": repo_path}])

    relative_files = [os.path.join("browser", "config", "version_display.txt"), os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    mocker.patch.object(vmanip, "run_hg_command", new=run_command)
    await vmanip.bump_version(config, {}, repo)
    assert expect_esr_version == vmanip.get_version(display_version_file, repo)
    assert new_version == vmanip.get_version(version_file, repo)
    assert len(called_args) == 1
コード例 #2
0
async def test_bump_version_esr_dont_bump_non_esr(mocker, config, tmpdir,
                                                  new_version,
                                                  expect_esr_version):
    version = "52.0.1"
    repo = os.path.join(tmpdir, "repo")
    os.mkdir(repo)
    os.mkdir(os.path.join(repo, "config"))
    os.makedirs(os.path.join(repo, "browser", "config"))
    version_file = os.path.join("config", "milestone.txt")
    with open(os.path.join(repo, version_file), "w") as f:
        f.write(version)
    display_version_file = os.path.join("browser", "config",
                                        "version_display.txt")
    with open(os.path.join(repo, display_version_file), "w") as f:
        f.write(version + "esr")

    relative_files = [
        os.path.join("browser", "config", "version_display.txt"),
        os.path.join("config", "milestone.txt")
    ]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    vcs_mock = AsyncMock()
    mocker.patch.object(vmanip, "get_vcs_module", return_value=vcs_mock)
    await vmanip.bump_version(config, {}, repo, repo_type="hg")
    assert expect_esr_version == vmanip.get_version(display_version_file, repo)
    assert new_version == vmanip.get_version(version_file, repo)
    vcs_mock.commit.assert_called_once()
コード例 #3
0
async def get_revision_info(bump_config, repo_path):
    """Query the l10n changesets from the l10n dashboard.

    Args:
        bump_config (dict): one of the dictionaries from the payload
            ``l10n_bump_info``
        repo_path (str): the path to the source repo

    Returns:
        str: the contents of the dashboard

    """
    version = get_version(bump_config["version_path"], repo_path)
    repl_dict = {
        "MAJOR_VERSION": version.major_number,
        "COMBINED_MAJOR_VERSION": version.major_number + version.minor_number
    }
    url = bump_config["revision_url"] % repl_dict
    with tempfile.NamedTemporaryFile() as fp:
        path = fp.name
        await retry_async(download_file,
                          args=(url, path),
                          retry_exceptions=(DownloadError, ))
        with open(path, "r") as fh:
            revision_info = fh.read()
    log.info("Got %s", revision_info)
    return revision_info
コード例 #4
0
async def test_bump_version_esr(mocker, repo_context, new_version,
                                expect_version):
    if not repo_context.xtest_version.endswith("esr"):
        # XXX pytest.skip raised exceptions here for some reason.
        return

    called_args = []

    async def run_command(context, *arguments, repo_path=None):
        called_args.append(
            [tuple([context]) + arguments, {
                "repo_path": repo_path
            }])

    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    mocker.patch.object(vmanip, "run_hg_command", new=run_command)
    await vmanip.bump_version(repo_context.config, repo_context.task,
                              repo_context.repo)
    assert expect_version == vmanip.get_version(relative_files[0],
                                                repo_context.repo)
    assert len(called_args) == 1
    assert "repo_path" in called_args[0][1]
    assert is_slice_in_list(("commit", "-m"), called_args[0][0])
コード例 #5
0
def create_new_version(version_config, repo_path):
    """Create the new version string used in file manipulation.

    Arguments:
        version_config (dict):
            {
                "filename": mandatory path,
                "new_suffix": string, default is to keep original.
                "version_bump": string, optional, enum 'major', 'minor'
            }

    Returns:
        string: new version string for file contents.
    """
    version = get_version(version_config["filename"], repo_path)
    if version_config.get("version_bump") == "major":
        version = version.bump("major_number")
    elif version_config.get("version_bump") == "minor":
        version = version.bump("minor_number")
    if "new_suffix" in version_config:  # '' is a valid entry
        version = attr.evolve(version,
                              is_esr=False,
                              beta_number=None,
                              is_nightly=False)
        version = f"{version}{version_config['new_suffix']}"
    else:
        version = f"{version}"
    log.info("New version is %s", version)
    return version
コード例 #6
0
async def apply_rebranding(config, repo_path, merge_config):
    """Apply changes to repo required for merge/rebranding."""
    log.info("Rebranding %s to %s", merge_config.get("from_branch"), merge_config.get("to_branch"))

    # Must collect this before any bumping.
    version = get_version(core_version_file(merge_config), repo_path)
    # Used in file replacements, further down.
    format_options = {
        "current_major_version": version.major_number,
        "next_major_version": version.major_number + 1,
        "current_weave_version": version.major_number + 2,
        "next_weave_version": version.major_number + 3,  # current_weave_version + 1
    }

    if merge_config.get("version_files"):
        for version_config in merge_config["version_files"]:
            await do_bump_version(config, repo_path, [version_config["filename"]], create_new_version(version_config, repo_path))

    for f in merge_config.get("copy_files", list()):
        shutil.copyfile(os.path.join(repo_path, f[0]), os.path.join(repo_path, f[1]))

    # Cope with bash variables in strings that we don't want to
    # be formatted in Python. We do this by ignoring {vars} we
    # aren't given keys for.
    fmt = BashFormatter()
    for f, from_, to in merge_config.get("replacements", list()):
        from_ = fmt.format(from_, **format_options)
        to = fmt.format(to, **format_options)
        replace(os.path.join(repo_path, f), from_, to)

    touch_clobber_file(config, repo_path)
コード例 #7
0
async def test_bump_version(mocker, repo_context, new_version,
                            should_append_esr):
    called_args = []

    async def run_command(context, *arguments, repo_path=None):
        called_args.append(
            [tuple([context]) + arguments, {
                "repo_path": repo_path
            }])

    test_version = new_version
    if repo_context.xtest_version.endswith("esr") and should_append_esr:
        test_version = new_version + "esr"

    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    mocker.patch.object(vmanip, "run_hg_command", new=run_command)
    await vmanip.bump_version(repo_context.config, repo_context.task,
                              repo_context.repo)
    assert test_version == vmanip.get_version(relative_files[0],
                                              repo_context.repo)
    assert len(called_args) == 1
    assert "repo_path" in called_args[0][1]
    assert is_slice_in_list(("commit", "-m"), called_args[0][0])
コード例 #8
0
async def test_bump_version_smaller_version(mocker, repo_context, new_version):
    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    vcs_mock = AsyncMock()
    mocker.patch.object(vmanip, "get_vcs_module", return_value=vcs_mock)
    await vmanip.bump_version(repo_context.config,
                              repo_context.task,
                              repo_context.repo,
                              repo_type="hg")
    assert repo_context.xtest_version == vmanip.get_version(
        relative_files[0], repo_context.repo)
    vcs_mock.commit.assert_not_called()
コード例 #9
0
async def test_bump_version_same_version(mocker, repo_context):
    called_args = []

    async def run_command(context, *arguments, repo_path=None):
        called_args.append([tuple([context]) + arguments, {"repo_path": repo_path}])

    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": repo_context.xtest_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    mocker.patch.object(vmanip, "run_hg_command", new=run_command)
    await vmanip.bump_version(repo_context.config, repo_context.task, repo_context.repo)
    assert repo_context.xtest_version == vmanip.get_version(relative_files[0], repo_context.repo)
    assert len(called_args) == 0
コード例 #10
0
async def test_bump_version_missing_file(mocker, repo_context, new_version):
    called_args = []

    async def run_command(context, *arguments, repo_path=None):
        called_args.append([tuple([context]) + arguments, {"repo_path": repo_path}])

    # Test only creates config/milestone.txt
    relative_files = [os.path.join("browser", "config", "version_display.txt"), os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    mocker.patch.object(vmanip, "run_hg_command", new=run_command)
    with pytest.raises(TaskVerificationError):
        await vmanip.bump_version(repo_context.config, repo_context.task, repo_context.repo)
    assert repo_context.xtest_version == vmanip.get_version(relative_files[1], repo_context.repo)
    assert len(called_args) == 0
コード例 #11
0
async def test_bump_version_esr(mocker, repo_context, new_version,
                                expect_version):
    if not repo_context.xtest_version.endswith("esr"):
        # XXX pytest.skip raised exceptions here for some reason.
        return

    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    vcs_mock = AsyncMock()
    mocker.patch.object(vmanip, "get_vcs_module", return_value=vcs_mock)
    await vmanip.bump_version(repo_context.config,
                              repo_context.task,
                              repo_context.repo,
                              repo_type="hg")
    assert expect_version == vmanip.get_version(relative_files[0],
                                                repo_context.repo)
    vcs_mock.commit.assert_called_once()
コード例 #12
0
async def test_bump_version_missing_file(mocker, repo_context, new_version):
    # Test only creates config/milestone.txt
    relative_files = [
        os.path.join("browser", "config", "version_display.txt"),
        os.path.join("config", "milestone.txt")
    ]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    vcs_mock = AsyncMock()
    mocker.patch.object(vmanip, "get_vcs_module", return_value=vcs_mock)
    with pytest.raises(TaskVerificationError):
        await vmanip.bump_version(repo_context.config,
                                  repo_context.task,
                                  repo_context.repo,
                                  repo_type="hg")
    assert repo_context.xtest_version == vmanip.get_version(
        relative_files[1], repo_context.repo)
    vcs_mock.commit.assert_not_called()
コード例 #13
0
async def test_bump_version(mocker, repo_context, new_version,
                            should_append_esr):
    test_version = new_version
    if repo_context.xtest_version.endswith("esr") and should_append_esr:
        test_version = new_version + "esr"

    relative_files = [os.path.join("config", "milestone.txt")]
    bump_info = {"files": relative_files, "next_version": new_version}
    mocked_bump_info = mocker.patch.object(vmanip, "get_version_bump_info")
    mocked_bump_info.return_value = bump_info
    vcs_mock = AsyncMock()
    mocker.patch.object(vmanip, "get_vcs_module", return_value=vcs_mock)
    await vmanip.bump_version(repo_context.config,
                              repo_context.task,
                              repo_context.repo,
                              repo_type="hg")
    assert test_version == vmanip.get_version(relative_files[0],
                                              repo_context.repo)
    assert vcs_mock.commit.call_args_list[0][0][
        2] == "Automatic version bump CLOSED TREE NO BUG a=release"
コード例 #14
0
async def apply_rebranding(config, repo_path, merge_config):
    """Apply changes to repo required for merge/rebranding."""
    log.info("Rebranding %s to %s", merge_config.get("from_branch"), merge_config.get("to_branch"))

    version = get_version("browser/config/version.txt", repo_path)
    current_major_version = version.major_number
    if merge_config.get("incr_major_version", False):
        version = version.bump("major_number")

    if merge_config.get("version_files"):
        next_version = f"{version.major_number}.{version.minor_number}"
        await do_bump_version(config, repo_path, merge_config["version_files"], next_version)

    if merge_config.get("version_files_suffix"):
        version = attr.evolve(version, is_esr=False, beta_number=None, is_nightly=False)
        next_version = f"{version}{merge_config.get('version_suffix')}"
        await do_bump_version(config, repo_path, merge_config["version_files_suffix"], next_version)

    for f in merge_config.get("copy_files", list()):
        shutil.copyfile(os.path.join(repo_path, f[0]), os.path.join(repo_path, f[1]))

    format_options = {
        "current_major_version": current_major_version,
        "next_major_version": version.major_number,
        "current_weave_version": current_major_version + 2,
        "next_weave_version": current_major_version + 3,  # current_weave_version + 1
    }

    # Cope with bash variables in strings that we don't want to
    # be formatted in Python. We do this by ignoring {vars} we
    # aren't given keys for.
    fmt = BashFormatter()
    for f, from_, to in merge_config.get("replacements", list()):
        from_ = fmt.format(from_, **format_options)
        to = fmt.format(to, **format_options)
        replace(os.path.join(repo_path, f), from_, to)

    touch_clobber_file(config, repo_path)
コード例 #15
0
async def do_merge(config, task, repo_path):
    """Perform a merge day operation.

    This function takes its inputs from task's payload.

    Args:
        config (dict): the running config
        task (dict): the running task
        repo_path (str): the source directory

    Raises:
        TaskverificationError: from get_merge_config if the payload is invalid.

    Returns:
        list: A list of the branches that need pushing, and the corresponding revision.
              This is unlike other actions as the list of outgoing changes is
              not related to the number of commands we've performed, but we do need
              to know which branches to push.
    """
    merge_config = get_merge_config(task)

    from_branch = merge_config.get("from_branch")
    to_branch = merge_config.get("to_branch")

    await run_hg_command(config,
                         "pull",
                         "https://hg.mozilla.org/mozilla-unified",
                         repo_path=repo_path)

    # Used if end_tag is set.
    await run_hg_command(config, "up", "-C", to_branch, repo_path=repo_path)
    to_fx_major_version = get_version("browser/config/version.txt",
                                      repo_path).major_number
    base_to_rev = await get_revision(config, repo_path, branch=to_branch)

    if from_branch:
        await run_hg_command(config,
                             "up",
                             "-C",
                             from_branch,
                             repo_path=repo_path)
        base_from_rev = await get_revision(config,
                                           repo_path,
                                           branch=from_branch)

    base_tag = merge_config.get("base_tag")
    if base_tag:
        base_tag = base_tag.format(major_version=get_version(
            "browser/config/version.txt", repo_path).major_number)
        tag_message = f"No bug - tagging {base_from_rev} with {base_tag} a=release DONTBUILD CLOSED TREE"
        await run_hg_command(config,
                             "tag",
                             "-m",
                             tag_message,
                             "-r",
                             base_from_rev,
                             "-f",
                             base_tag,
                             repo_path=repo_path)

    tagged_from_rev = await get_revision(config, repo_path, branch=".")

    # TODO This shouldn't be run on esr, according to old configs.
    # perhaps: hg push -r bookmark("release") esrNN
    # Perform the kludge-merge.
    if merge_config.get("merge_old_head", False):
        await run_hg_command(config,
                             "debugsetparents",
                             tagged_from_rev,
                             base_to_rev,
                             repo_path=repo_path)
        await run_hg_command(
            config,
            "commit",
            "-m",
            "Merge old head via |hg debugsetparents {} {}| CLOSED TREE DONTBUILD a=release"
            .format(tagged_from_rev, base_to_rev),
            repo_path=repo_path,
        )
        await preserve_tags(config, repo_path, to_branch)

    end_tag = merge_config.get("end_tag")  # tag the end of the to repo
    if end_tag:
        end_tag = end_tag.format(major_version=to_fx_major_version)
        tag_message = f"No bug - tagging {base_to_rev} with {end_tag} a=release DONTBUILD CLOSED TREE"
        await run_hg_command(config,
                             "tag",
                             "-m",
                             tag_message,
                             "-r",
                             base_to_rev,
                             "-f",
                             end_tag,
                             repo_path=repo_path)

    await apply_rebranding(config, repo_path, merge_config)

    diff_output = await run_hg_command(config,
                                       "diff",
                                       repo_path=repo_path,
                                       return_output=True)
    path = os.path.join(config["artifact_dir"], "public", "logs",
                        "{}.diff".format(to_branch))
    makedirs(os.path.dirname(path))
    with open(path, "w") as fh:
        fh.write(diff_output)

    await run_hg_command(
        config,
        "commit",
        "-m",
        "Update configs. IGNORE BROKEN CHANGESETS CLOSED TREE NO BUG a=release ba=release",
        repo_path=repo_path)
    push_revision_to = await get_revision(config, repo_path, branch=".")

    # Do we need to perform multiple pushes for the push stage? If so, return
    # what to do.
    desired_pushes = list()
    if merge_config.get("from_repo"):
        desired_pushes.append((merge_config["from_repo"], tagged_from_rev))
    if merge_config.get("to_repo"):
        desired_pushes.append((merge_config["to_repo"], push_revision_to))
    return desired_pushes
コード例 #16
0
def test_replace_ver_in_file(repo_context, new_version):
    filepath = "config/milestone.txt"
    old_ver = repo_context.xtest_version
    vmanip.replace_ver_in_file(os.path.join(repo_context.repo, filepath),
                               old_ver, new_version)
    assert new_version == vmanip.get_version(filepath, repo_context.repo)
コード例 #17
0
def test_get_version(repo_context):
    ver = vmanip.get_version("config/milestone.txt", repo_context.repo)
    assert ver == repo_context.xtest_version