예제 #1
0
def test_via_Repo_class(
    temp_repo,
    capsys,
    file_regression: FileRegressionFixture,
    data_regression: DataRegressionFixture,
    monkeypatch,
    example_config,
):

    with in_directory(temp_repo.path):
        (temp_repo.path / "repo_helper.yml").write_text(example_config)
        (temp_repo.path / "requirements.txt").touch()
        (temp_repo.path / "tests").maybe_make()
        (temp_repo.path / "tests" / "requirements.txt").touch()
        (temp_repo.path / "README.rst").touch()
        (temp_repo.path / "doc-source").mkdir()
        (temp_repo.path / "doc-source" / "index.rst").touch()
        (temp_repo.path / ".pre-commit-config.yaml").touch()

        rh = RepoHelper(temp_repo.path)
        rh.load_settings()
        managed_files = rh.run()

    data_regression.check(sorted(managed_files))

    assert capsys.readouterr().out == ''
    assert capsys.readouterr().err == ''
예제 #2
0
def run_repo_helper(
    path,
    force: bool,
    initialise: bool,
    commit: Optional[bool],
    message: str,
    enable_pre_commit: bool = True,
) -> int:
    """
	Run repo_helper.

	:param path: The repository path.
	:param force: Whether to force the operation if the repository is not clean.
	:param initialise: Whether to initialise the repository.
	:param commit: Whether to commit unchanged files.
	:param message: The commit message.
	:param enable_pre_commit: Whether to install and configure pre-commit. Default :py:obj`True`.
	"""

    # this package
    from repo_helper.cli.commands.init import init_repo
    from repo_helper.core import RepoHelper
    from repo_helper.utils import easter_egg

    try:
        rh = RepoHelper(path)
        rh.load_settings()
    except FileNotFoundError as e:
        error_block = textwrap.indent(str(e), '\t')
        raise abort(
            f"Unable to run 'repo_helper'.\nThe error was:\n{error_block}")

    if not assert_clean(rh.target_repo,
                        allow_config=("repo_helper.yml", "git_helper.yml")):
        if force:
            click.echo(Fore.RED("Proceeding anyway"), err=True)
        else:
            return 1

    if initialise:
        r = Repo(rh.target_repo)
        for filename in init_repo(rh.target_repo, rh.templates):
            r.stage(os.path.normpath(filename))

    managed_files = rh.run()

    try:
        commit_changed_files(
            repo_path=rh.target_repo,
            managed_files=managed_files,
            commit=commit,
            message=message.encode("UTF-8"),
            enable_pre_commit=enable_pre_commit,
        )
    except CommitError as e:
        indented_error = '\n'.join(f"\t{line}"
                                   for line in textwrap.wrap(str(e)))
        click.echo(
            f"Unable to commit changes. The error was:\n\n{indented_error}",
            err=True)
        return 1

    easter_egg()

    return 0
예제 #3
0
def update_repository(repository: Dict, recreate: bool = False) -> int:
    """
	Run the updater for the given repository.

	:param repository:
	:param recreate:
	"""

    # TODO: rebase
    # TODO: if branch already exists and PR has been merged, abort

    db_repository: Repository = get_db_repository(
        repo_id=repository["id"],
        owner=repository["owner"]["login"],
        name=repository["name"],
    )

    last_pr_date = datetime.fromtimestamp(db_repository.last_pr or 200)
    now = datetime.now()
    if not recreate and last_pr_date.day == now.day and last_pr_date.month == now.month:
        print(
            f"A PR for {db_repository.fullname} has already been created today. Skipping."
        )
        return 1

    owner = repository["owner"]["login"]
    repository_name = repository["name"]

    # Log in as the app
    context_switcher.login_as_app()

    # Log in as installation
    installation_id = context_switcher.login_as_repo_installation(
        owner=owner, repository=repository_name)

    github_repo: GitHubRepository = client.repository(owner, repository_name)

    # Ensure 'repo_helper.yml' exists
    try:
        github_repo.file_contents("repo_helper.yml")
    except NotFoundError:
        print(
            f"repo_helper.yml not found in the repository {repository['owner']['login']}/{repository['name']}"
        )
        return 1

    with TemporaryDirectory() as tmpdir:

        # Clone to tmpdir
        repo = clone(repository["html_url"], tmpdir)

        if recreate:
            # Delete any existing branch and create again from master
            recreate_branch(repo)
        elif f"refs/remotes/origin/{BRANCH_NAME}".encode("UTF-8") in dict(
                repo.refs):
            checkout_branch(repo)
        else:
            # Switch to new branch
            create_branch(repo)

        # Update files
        try:
            rh = RepoHelper(tmpdir)
            rh.load_settings()
        except FileNotFoundError as e:
            error_block = indent(str(e), '\t')
            print(
                f"Unable to run 'repo_helper'.\nThe error was:\n{error_block}")

        managed_files = rh.run()
        staged_files = stage_changes(repo.path, managed_files)

        if not staged_files and recreate:
            # Everything is up to date, close PR.
            close_pr(owner, repository_name)
            return 0

        try:
            if not commit_changed_files(
                    repo_path=rh.target_repo,
                    managed_files=managed_files,
                    commit=True,
                    message=b"Updated files with 'repo_helper'.",
                    enable_pre_commit=False,
            ):
                sys.stdout.flush()
                sys.stderr.flush()
                print("Failure!")
                return 1

            sys.stdout.flush()
            sys.stderr.flush()

        except CommitError as e:
            indented_error = '\n'.join(f"\t{line}" for line in wrap(str(e)))
            print(
                f"Unable to commit changes. The error was:\n\n{indented_error}"
            )
            print("Failure!")
            return 1

        # Push
        dulwich.porcelain.push(
            repo,
            repository["html_url"],
            BRANCH_NAME.encode("UTF-8"),
            username="******",
            password=get_installation_access_token(github_repo,
                                                   installation_id),
            force=recreate,
        )

        sys.stdout.flush()
        sys.stderr.flush()

        # Create PR
        base = github_repo.default_branch
        head = f"{owner}:{BRANCH_NAME}"

        if not list(
                github_repo.pull_requests(state="open", base=base, head=head)):
            created_pr = github_repo.create_pull(
                title="[repo-helper] Configuration Update",
                base=base,
                head=head,
                body=make_pr_details(),
            )

            if created_pr is not None:
                db_repository.add_pr(int(created_pr.number))

        db_repository.last_pr = datetime.now().timestamp()
        db.session.commit()

        print("Success!")
        return 0