コード例 #1
0
async def get_token_for_install(*, session: http.AsyncClient,
                                installation_id: str) -> str:
    """
    https://developer.github.com/apps/building-github-apps/authenticating-with-github-apps/#authenticating-as-an-installation
    """
    token = installation_cache.get(installation_id)
    if token is not None and not token.expired:
        return token.token
    app_token = generate_jwt(private_key=conf.PRIVATE_KEY,
                             app_identifier=conf.GITHUB_APP_ID)
    throttler = get_thottler_for_installation(
        # this isn't a real installation ID, but it provides rate limiting
        # for our GithubApp instead of the installations we typically act as
        installation_id=APPLICATION_ID)
    async with throttler:
        res = await session.post(
            conf.v3_url(f"/app/installations/{installation_id}/access_tokens"),
            headers=dict(
                Accept="application/vnd.github.machine-man-preview+json",
                Authorization=f"Bearer {app_token}",
            ),
        )
    if res.status_code > 300:
        raise Exception(f"Failed to get token, github response: {res.text}")
    token_response = TokenResponse(**res.json())
    installation_cache[installation_id] = token_response
    return token_response.token
コード例 #2
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def get_open_pull_requests(
     self, base: Optional[str] = None, head: Optional[str] = None
 ) -> Optional[List[GetOpenPullRequestsResponseSchema]]:
     """
     https://developer.github.com/v3/pulls/#list-pull-requests
     """
     log = self.log.bind(base=base, head=head)
     headers = await get_headers(installation_id=self.installation_id)
     params = dict(state="open", sort="updated")
     if base is not None:
         params["base"] = base
     if head is not None:
         params["head"] = head
     async with self.throttler:
         res = await self.session.get(
             conf.v3_url(f"/repos/{self.owner}/{self.repo}/pulls"),
             params=params,
             headers=headers,
         )
     try:
         res.raise_for_status()
     except http.HTTPError:
         log.warning("problem finding prs", res=res, exc_info=True)
         return None
     return [GetOpenPullRequestsResponseSchema.parse_obj(pr) for pr in res.json()]
コード例 #3
0
ファイル: cli.py プロジェクト: yowainwright/kodiak
def list_installs() -> None:
    app_token = generate_jwt(
        private_key=conf.PRIVATE_KEY, app_identifier=conf.GITHUB_APP_ID
    )
    results: List[Dict[str, Any]] = []
    headers = dict(
        Accept="application/vnd.github.machine-man-preview+json",
        Authorization=f"Bearer {app_token}",
    )
    url = conf.v3_url("/app/installations")
    while True:
        res = requests.get(url, headers=headers)
        res.raise_for_status()
        results += res.json()
        try:
            url = res.links["next"]["url"]
        except (KeyError, IndexError):
            break

    for r in results:
        try:
            install_url = r["account"]["html_url"]
            install_id = r["id"]
            click.echo(f"install:{install_id} for {install_url}")
        except (KeyError, IndexError):
            pass
コード例 #4
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def update_ref(self, *, ref: str, sha: str) -> http.Response:
     """
     https://docs.github.com/en/rest/reference/git#update-a-reference
     """
     headers = await get_headers(installation_id=self.installation_id)
     url = conf.v3_url(f"/repos/{self.owner}/{self.repo}/git/refs/heads/{ref}")
     async with self.throttler:
         return await self.session.patch(url, headers=headers, json=dict(sha=sha))
コード例 #5
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def update_branch(self, *, pull_number: int) -> http.Response:
     headers = await get_headers(installation_id=self.installation_id)
     async with self.throttler:
         return await self.session.put(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/pulls/{pull_number}/update-branch"
             ),
             headers=headers,
         )
コード例 #6
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def create_comment(self, body: str, pull_number: int) -> http.Response:
     headers = await get_headers(installation_id=self.installation_id)
     async with self.throttler:
         return await self.session.post(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/issues/{pull_number}/comments"
             ),
             json=dict(body=body),
             headers=headers,
         )
コード例 #7
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def delete_label(self, label: str, pull_number: int) -> http.Response:
     headers = await get_headers(installation_id=self.installation_id)
     escaped_label = urllib.parse.quote(label)
     async with self.throttler:
         return await self.session.delete(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/issues/{pull_number}/labels/{escaped_label}"
             ),
             headers=headers,
         )
コード例 #8
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def add_label(self, label: str, pull_number: int) -> http.Response:
     headers = await get_headers(installation_id=self.installation_id)
     async with self.throttler:
         return await self.session.post(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/issues/{pull_number}/labels"
             ),
             json=dict(labels=[label]),
             headers=headers,
         )
コード例 #9
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def delete_branch(self, branch: str) -> http.Response:
     """
     delete a branch by name
     """
     headers = await get_headers(installation_id=self.installation_id)
     ref = urllib.parse.quote(f"heads/{branch}")
     async with self.throttler:
         return await self.session.delete(
             conf.v3_url(f"/repos/{self.owner}/{self.repo}/git/refs/{ref}"),
             headers=headers,
         )
コード例 #10
0
async def get_login_for_install(*, installation_id: str) -> str:
    app_token = generate_jwt(private_key=conf.PRIVATE_KEY,
                             app_identifier=conf.GITHUB_APP_ID)
    res = await http.get(
        conf.v3_url(f"/app/installations/{installation_id}"),
        headers=dict(
            Accept="application/vnd.github.machine-man-preview+json",
            Authorization=f"Bearer {app_token}",
        ),
    )
    res.raise_for_status()
    return cast(str, res.json()["account"]["login"])
コード例 #11
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def approve_pull_request(self, *, pull_number: int) -> http.Response:
     """
     https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review
     """
     headers = await get_headers(installation_id=self.installation_id)
     body = dict(event="APPROVE")
     async with self.throttler:
         return await self.session.post(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/pulls/{pull_number}/reviews"
             ),
             headers=headers,
             json=body,
         )
コード例 #12
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def get_permissions_for_username(self, username: str) -> Permission:
     headers = await get_headers(installation_id=self.installation_id)
     async with self.throttler:
         res = await self.session.get(
             conf.v3_url(
                 f"/repos/{self.owner}/{self.repo}/collaborators/{username}/permission"
             ),
             headers=headers,
         )
     try:
         res.raise_for_status()
         return Permission(res.json()["permission"])
     except (http.HTTPError, IndexError, TypeError, ValueError):
         logger.exception("couldn't fetch permissions for username %r", username)
         return Permission.NONE
コード例 #13
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def create_notification(
     self, head_sha: str, message: str, summary: Optional[str] = None
 ) -> http.Response:
     headers = await get_headers(installation_id=self.installation_id)
     url = conf.v3_url(f"/repos/{self.owner}/{self.repo}/check-runs")
     body = dict(
         name=CHECK_RUN_NAME,
         head_sha=head_sha,
         status="completed",
         completed_at=datetime.now(timezone.utc).isoformat(),
         conclusion="neutral",
         output=dict(title=message, summary=summary or ""),
     )
     async with self.throttler:
         return await self.session.post(url, headers=headers, json=body)
コード例 #14
0
    async def get_open_pull_requests(
        self,
        base: Optional[str] = None,
        head: Optional[str] = None
    ) -> Optional[List[GetOpenPullRequestsResponseSchema]]:
        """
        https://developer.github.com/v3/pulls/#list-pull-requests
        """
        log = self.log.bind(base=base, head=head)
        headers = await get_headers(session=self.session,
                                    installation_id=self.installation_id)
        params = dict(state="open", sort="updated", per_page="100")
        if base is not None:
            params["base"] = base
        if head is not None:
            params["head"] = head

        open_prs = []

        page = None
        current_page = 0
        while page != []:
            current_page += 1
            if current_page > 20:
                log.info("hit pagination limit")
                break

            params["page"] = str(current_page)
            async with self.throttler:
                res = await self.session.get(
                    conf.v3_url(f"/repos/{self.owner}/{self.repo}/pulls"),
                    params=params,
                    headers=headers,
                )
            try:
                res.raise_for_status()
            except http.HTTPError:
                log.warning("problem finding prs", res=res, exc_info=True)
                return None

            page = res.json()
            open_prs += [
                GetOpenPullRequestsResponseSchema.parse_obj(pr) for pr in page
            ]

        return open_prs
コード例 #15
0
ファイル: __init__.py プロジェクト: TrendingTechnology/kodiak
 async def merge_pull_request(
     self,
     number: int,
     merge_method: str,
     commit_title: Optional[str],
     commit_message: Optional[str],
 ) -> http.Response:
     body = dict(merge_method=merge_method)
     # we must not pass the keys for commit_title or commit_message when they
     # are null because GitHub will error saying the title/message cannot be
     # null. When the keys are not passed, GitHub creates a title and
     # message.
     if commit_title is not None:
         body["commit_title"] = commit_title
     if commit_message is not None:
         body["commit_message"] = commit_message
     headers = await get_headers(installation_id=self.installation_id)
     url = conf.v3_url(f"/repos/{self.owner}/{self.repo}/pulls/{number}/merge")
     async with self.throttler:
         return await self.session.put(url, headers=headers, json=body)
コード例 #16
0
 async def get_pull_request(self, number: int) -> http.Response:
     headers = await get_headers(session=self.session,
                                 installation_id=self.installation_id)
     url = conf.v3_url(f"/repos/{self.owner}/{self.repo}/pulls/{number}")
     async with self.throttler:
         return await self.session.get(url, headers=headers)