Beispiel #1
0
def test_github_example_matches(
        path: str, expected: List[Tuple[Literal["USERNAME", "EMAIL", "TEAM"],
                                        str]]) -> None:
    owners = CodeOwners(EXAMPLE)
    actual = owners.of(path)
    assert (actual == expected
            ), f"mismatch for {path}, expected: {expected}, got: {actual}"
Beispiel #2
0
def test_specific_pattern_path_matching(name: str, pattern: str,
                                        paths: Dict[str, bool]) -> None:
    assert paths
    for path, expected in paths.items():
        owners = CodeOwners(f"{pattern}  @js-user")
        matches = owners.of(path) == [("USERNAME", "@js-user")]
        regex, *_ = owners.paths[0]
        assert (
            matches == expected
        ), f"""{pattern} {regex} {"matches" if expected else "shouldn't match"} {path}"""
Beispiel #3
0
def test_codeowners(pattern, expected):
    # for some reason the codeowners library does not publish all the wheels
    # for Mac and Windows. Eventually we could write our own codeowners parser,
    # but for now it is good enough. If codeowners is not installed, this test
    # will be skipped
    try:
        from codeowners import CodeOwners
    except:
        pytest.skip("Skipping as codeowners not installed.")

    with open(".github/CODEOWNERS") as f:
        owners = CodeOwners(f.read())
        assert set(owners.of(pattern)) == expected
Beispiel #4
0
async def conclude_reviewer_list(owner: str = None,
                                 repo: str = None) -> typing.List[str]:
    """Conclude on a set of Reviewers (their GitHub user id) that could be assigned to a Pull Request."""
    reviewers = []
    github_api = None

    if owner is None or repo is None:
        return None

    try:
        github_api = RUNTIME_CONTEXT.app_installation_client
    except Exception:
        access_token = GitHubOAuthToken(os.environ["GITHUB_ACCESS_TOKEN"])
        github_api = RawGitHubAPI(access_token, user_agent="sesheta-actions")

    try:
        codeowners = await github_api.getitem(
            f"/repos/{owner}/{repo}/contents/.github/CODEOWNERS")
        codeowners_content = base64.b64decode(
            codeowners["content"]).decode("utf-8")

        code_owner = CodeOwners(codeowners_content)
        for owner in code_owner.of("."):
            reviewers.append(owner[1][1:])  # remove the @

    except gidgethub.HTTPException as http_exception:  # if there is no CODEOWNERS, lets have some sane defaults
        if http_exception.status_code == 404:
            if owner.lower() == "thoth-station":
                reviewers.append("fridex")
                reviewers.append("pacospace")
            if "prometheus" in repo.lower():
                reviewers.append("4n4nd")
                reviewers.append("MichaelClifford")
            if "log-" in repo.lower():
                reviewers.append("zmhassan")
                reviewers.append("4n4nd")
        else:
            _LOGGER.error(http_exception)
            return None

    except Exception as err:  # on any other Error, we can not generate a reviewers list
        _LOGGER.error(str(err))
        return None

    _LOGGER.debug(f"final reviewers: '{reviewers}'")

    return reviewers
Beispiel #5
0
def main():
    app_id = os.getenv('GITHUB_APP_ID')
    private_key = os.getenv('GITHUB_PRIVATE_KEY').encode('utf-8')
    organization_name, repository_name = os.getenv('PROJECT').split('/')
    pull_request_id = os.getenv('PULL_REQUEST_ID')

    github_app = github.GitHub()
    github_app.login_as_app(private_key, app_id)
    app_slug = github_app.authenticated_app().slug

    github_installation = github.GitHub()
    github_installation.login_as_app_installation(
        private_key, app_id,
        github_app.app_installation_for_repository(organization_name,
                                                   repository_name).id)

    organization = github_installation.organization(organization_name)
    repository = github_installation.repository(organization.login,
                                                repository_name)
    pull_request = github_installation.pull_request(organization.login,
                                                    repository.name,
                                                    pull_request_id)

    # Get reviewers
    reviewers = set()
    try:
        owner_file_contents = repository.file_contents('CODEOWNERS')
        data = owner_file_contents.decoded.decode('utf-8')
        code_owners = CodeOwners(data)

        for f in pull_request.files():
            file_reviewers = code_owners.of(f.filename)
            if file_reviewers is None:
                continue

            for reviewer_type, reviewer in file_reviewers:
                if reviewer_type == 'USERNAME':
                    reviewers.add(reviewer.replace('@', ''))
                    continue
                raise SystemError("Unknown reviewer_type: %s" % reviewer_type)
    except:
        return 0

    # Get last commit date
    commit_dates = []
    for c in pull_request.commits():
        date = dateutil_parser.parse(c.commit.committer['date'])
        commit_dates.append(date)
    last_commit_date = max(commit_dates) if commit_dates else None

    # Parse comments
    approvals = set()
    for comment in pull_request.issue_comments():
        # Find the signoffs
        if comment.created_at > last_commit_date:
            for line in comment.body.split("\n"):
                if line.strip() in APPROVAL_ALIASES:
                    approvals.add(comment.user.login)

    if any([(r in approvals) for r in reviewers]):
        pull_request.create_review("Pull Request Approved.",
                                   list(pull_request.commits())[-1].sha,
                                   'APPROVE')
        return 0

    return 1