Пример #1
0
async def handle_add_blurb_get(request):
    """Render a page with a textbox and submit button."""
    token = request.rel_url.query.get("code")
    request_session = await get_session(request)
    context = {"csrf": util.get_csrf_token(session=request_session)}

    if await util.has_session(request):
        context.update(await util.get_session_context(request, context))
        async with aiohttp.ClientSession() as session:

            gh = GitHubAPI(session, context["username"])

            jwt = get_jwt(
                app_id=os.getenv("GH_APP_ID"), private_key=os.getenv("GH_PRIVATE_KEY")
            )
            try:
                await util.get_installation(gh, jwt, context["username"])
            except error.InstallationNotFound:
                return web.HTTPFound(location=request.app.router["install"].url_for())

    elif token is not None:

        async with aiohttp.ClientSession() as session:
            payload = {
                "client_id": os.environ.get("GH_CLIENT_ID"),
                "client_secret": os.environ.get("GH_CLIENT_SECRET"),
                "code": token,
            }
            async with session.post(
                "https://github.com/login/oauth/access_token", data=payload
            ) as response:
                response_text = await response.text()
                access_token = get_access_token(response_text)
                gh = GitHubAPI(session, "blurb-it", oauth_token=access_token)
                response = await gh.getitem("/user")
                login_name = response["login"]
                request_session["username"] = login_name
                request_session["token"] = access_token
                context["username"] = request_session["username"]

                gh = GitHubAPI(session, context["username"])

                jwt = get_jwt(
                    app_id=os.getenv("GH_APP_ID"),
                    private_key=os.getenv("GH_PRIVATE_KEY"),
                )
                try:
                    await util.get_installation(gh, jwt, context["username"])
                except error.InstallationNotFound:
                    return web.HTTPFound(
                        location=request.app.router["install"].url_for()
                    )

    else:
        return web.HTTPFound(location=request.app.router["home"].url_for())

    response = aiohttp_jinja2.render_template(
        "add_blurb.html", request, context=context
    )
    return response
Пример #2
0
async def main():
    async with aiohttp.ClientSession() as session:
        app_id = os.getenv("GH_APP_ID")

        jwt = get_jwt(app_id)
        gh = GitHubAPI(session, "Mariatta")

        try:
            installation = await get_installation(gh, jwt, "Mariatta")

        except ValueError as ve:
            # Raised if Mariatta did not installed the GitHub App
            print(ve)
        else:
            access_token = await get_installation_access_token(
                gh, jwt=jwt, installation_id=installation["id"])

            # treat access_token as if a personal access token

            # Example, creating a GitHub issue as a GitHub App
            gh_app = GitHubAPI(session,
                               "black_out",
                               oauth_token=access_token["token"])
            await gh_app.post(
                "/repos/mariatta/strange-relationship/issues",
                data={
                    "title": "We got a problem 🤖",
                    "body": "Use more emoji! (I'm a GitHub App!) ",
                },
            )
Пример #3
0
async def get_issues(user, repo):
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "octaflop", oauth_token=os.getenv("GH_AUTH"))
        url = f'/repos/{user}/{repo}/issues'
        print(url)
        issues = gh.getiter(url)
        return [i async for i in issues]
Пример #4
0
 def __init__(self, server: ni_abc.ServerHost, client: aiohttp.ClientSession,
              event: PullRequestEvent,
              request: JSONDict) -> None:
     """Represent a contribution."""
     self.server = server
     self.event = event
     self.request = request
     self._gh = GitHubAPI(client, "the-knights-who-say-ni",
                          oauth_token=server.contrib_auth_token())
Пример #5
0
 def __init__(self, path: Path, config: Configuration,
              session: ClientSession) -> None:
     self._config = config
     self._github = GitHubAPI(
         session,
         config.github_user,
         oauth_token=config.github_token.get_secret_value(),
     )
     self._repo = Repo(str(path))
Пример #6
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "syin", oauth_token=os.getenv("GH_AUTH"))

        issue = await gh.post('/repos/syin/gitbot/issues',
                              data={
                                  'title': 'test',
                                  'body': 'test',
                              })

        issue_id = issue["number"]
        comment = await gh.post(
            '/repos/syin/gitbot/issues/{id}/comments'.format(id=issue_id),
            data={
                'body': 'test comment',
            })

        close_issue = await gh.patch(
            '/repos/syin/gitbot/issues/{id}'.format(id=issue_id),
            data={'state': 'closed'},
        )

        reaction = await gh.post(
            '/repos/syin/gitbot/issues/{id}/reactions'.format(id=issue_id),
            accept="application/vnd.github.squirrel-girl-preview+json",
            data={'content': 'hooray'},
        )
Пример #7
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "geokai", oauth_token=os.getenv("GH_AUTH"))
        issue_list = await gh.getitem(
            '/repos/mariatta/strange-relationship/issues?creator=geokai')
        issue_number = issue_list[0]['number']
        print(issue_number)
Пример #8
0
async def comment_on_issue(user, repo, issue_id):
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "octaflop", oauth_token=os.getenv("GH_AUTH"))
        await gh.post(f'/repos/{user}/{repo}/issues/{issue_id}/comments',
                      data={
                          'body': 'Moi, aussie!',
                      })
Пример #9
0
async def main():
    """
    - Get Python core team
    - Get Python core's public repos
    - Create Python triage team, assign the repos
    :return:
    """
    async with aiohttp.ClientSession() as session:
        # must have repo, and admin:org permissions
        gh = GitHubAPI(session,
                       "python",
                       oauth_token=os.getenv("GH_AUTH"),
                       cache=cache)
        core_team = await get_team(gh, "python-core")
        repo_names = [
            repo async for repo in get_core_repos(gh, core_team["id"])
        ]
        await gh.post(
            "/orgs/python/teams",
            data={
                "name": "Python triage",
                "description": "Triagers for core Python",
                "maintainers": ["mariatta", "zware", "vstinner"],
                "privacy": "closed",
                "repo_names": repo_names,
            },
        )
Пример #10
0
async def react_to_issue():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, 'dawran6', oauth_token=os.getenv('GH_AUTH'))
        await gh.post(
            '/repos/mariatta/strange-relationship/issues/83/reactions',
            data={'content': 'hooray'},
            accept='application/vnd.github.squirrel-girl-preview+json')
Пример #11
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "mariatta", oauth_token=os.getenv("GH_AUTH"))
        await gh.patch(
            '/repos/mariatta/strange-relationship/issues/159',
            data={'state': 'closed'},
        )
Пример #12
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "mohantyk", oauth_token=os.getenv("GH_AUTH"))
        await gh.patch('/repos/mohantyk/test_bot/issues/1',
                       data={
                           'state': 'closed',
                       })
Пример #13
0
async def get_total_open_prs(
    gh: GitHubAPI,
    installation_id: int,
    *,
    repository: str,
    user_login: Optional[str] = None,
    count: Optional[bool] = True,
) -> Any:
    """Return the total number of open pull requests in the repository.

    If the `user_login` parameter is given, then return the total number of open
    pull request by that user in the repository.

    If the `count` parameter is `False`, it returns the list of pull request
    numbers instead.

    For GitHub's REST API v3, issues and pull requests are the same so
    `repository["open_issues_count"]` returns the total number of open
    issues and pull requests. As we only want the pull request count,
    we can make a search API call for open pull requests.
    """
    installation_access_token = await get_access_token(gh, installation_id)
    search_url = f"/search/issues?q=type:pr+state:open+repo:{repository}"
    if user_login is not None:
        search_url += f"+author:{user_login}"
    if count is False:
        pr_numbers = []
        async for pull in gh.getiter(search_url,
                                     oauth_token=installation_access_token):
            pr_numbers.append(pull["number"])
        return pr_numbers
    data = await gh.getitem(search_url, oauth_token=installation_access_token)
    return data["total_count"]
Пример #14
0
async def close_issue(user, repo, issue_id):
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "octaflop", oauth_token=os.getenv("GH_AUTH"))
        await gh.patch(f'/repos/{user}/{repo}/issues/{issue_id}',
                       data={
                           'state': 'closed',
                       })
Пример #15
0
Файл: gh.py Проект: ahelm/wusa
async def async_post_gh_api(
    api: str,
    token: str,
    data: Dict[str, Union[str, int]],
) -> Dict[str, Any]:
    """Coroutine which sends a POST request to GitHub API.

    Parameters
    ----------
    api
        API endpoint to which a POST requests is send.

    token
        Auth token for GitHub to access API endpoint.

    data
        Dictionary with additional data to attach to POST request

    Returns
    -------
        Dictionary containing respond to request.
    """
    async with ClientSession() as session:
        gh_api = GitHubAPI(session, "wusa", oauth_token=token)
        return await gh_api.post(api, data=data)
Пример #16
0
async def add_issue(user, repo):
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "octaflop", oauth_token=os.getenv("GH_AUTH"))
        await gh.post(f'/repos/{user}/{repo}/issues',
                      data={
                          'title': 'We got a problem ',
                          'body': 'Use more emoji!',
                      })
Пример #17
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "joker_bot", oauth_token=os.getenv("joker"))
        await gh.post("/repos/sohanjokerinfini/mayadata/pulls",
                      data={
                          "title": "hello github bot  ",
                          "body": "Thanks!"
                      })
Пример #18
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "geokai", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/mariatta/strange-relationship/issues/128/comments',
              data={
                  'title': 'My next comment',
                  'body': text_object,
              })
Пример #19
0
async def create_issue():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, 'dawran6', oauth_token=os.getenv('GH_AUTH'))
        await gh.post('/repos/mariatta/strange-relationship/issues',
                      data={
                          'title': 'Mayday! Too many problems!',
                          'body': 'Mayday!',
                      })
Пример #20
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "msandfor", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/msandfor/snickers/issues',
                      data={
                          'title': "Not sure if this is working",
                          'body': "Might have to restart the whole tutorial",
                      })
Пример #21
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "geokai", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/mariatta/strange-relationship/issues',
              data={
                  'title': 'A new issue to test',
                  'body': 'geokai says, I\'m almost a bot',
              })
Пример #22
0
async def main() -> None:
    async with ClientSession() as session:
        await execute("rate",
                      dependency=GitHubAPI(
                          session=session,
                          requester=os.environ["GITHUB_USER"],
                          oauth_token=os.environ["GITHUB_TOKEN"],
                      ))
Пример #23
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "r-ash", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/r-ash/ws-install/issues',
                      data={
                          'title': 'Test issue creation',
                          'body': 'Testing :)',
                      })
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "mariatta", oauth_token=os.getenv("GH_AUTH"))
        await gh.post(
            '/repos/mariatta/strange-relationship/issues/159/comments',
            data={
                'body': "This is a known issue",
            })
Пример #25
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "kevin", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/mariatta/strange-relationship/issues',
                      data={
                          'title': 'We got a problem',
                          'body': 'More cowbell!',
                      })
async def main():
   async with aiohttp.ClientSession() as session:
       gh = GitHubAPI(session, "manaswinidas", oauth_token=os.getenv("GH_AUTH"))
       await gh.post('/repos/manaswinidas/github-ci/issues',
             data={
                 'title': 'We got a problem',
                 'body': 'Use more emoji!',
             })
Пример #27
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "WillMcLV", oauth_token=os.getenv("GH_AUTH"))
        await gh.post("/repos/WillMcLV/BotTest/issues",
                      data={
                          "title": "Hello",
                          "body": "Goodbye."
                      })
Пример #28
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "mohantyk", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/mohantyk/test_bot/issues',
                      data={
                          'title': 'We got a problem',
                          'body': 'Use more emoji!',
                      })
Пример #29
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "pietro909", oauth_token=os.getenv("GH_AUTH"))
        await gh.post('/repos/pietro909/algorithms-coursera/issues',
                      data={
                          'title': 'We got a problem',
                          'body': 'Use more emoji!',
                      })
Пример #30
0
async def main():
    async with aiohttp.ClientSession() as session:
        gh = GitHubAPI(session, "mariatta", oauth_token=os.getenv("GH_AUTH"))
        response = await gh.post(
            '/repos/mariatta/strange-relationship/issues/276/comments',
            data={
                'body': 'Use more emoji!',
            })
        print(f"Commented on the issue!")
Пример #31
0
class Host(ni_abc.ContribHost):

    """Implement a webhook for GitHub pull requests."""

    route = 'POST', '/github'

    _useful_actions =  {PullRequestEvent.opened.value,
                        PullRequestEvent.unlabeled.value,
                        PullRequestEvent.synchronize.value}

    def __init__(self, server: ni_abc.ServerHost, client: aiohttp.ClientSession,
                 event: PullRequestEvent,
                 request: JSONDict) -> None:
        """Represent a contribution."""
        self.server = server
        self.event = event
        self.request = request
        self._gh = GitHubAPI(client, "the-knights-who-say-ni",
                             oauth_token=server.contrib_auth_token())

    @classmethod
    async def process(cls, server: ni_abc.ServerHost,
                      request: web.Request, client: aiohttp.ClientSession) -> "Host":
        """Process the pull request."""
        event = sansio.Event.from_http(request.headers,
                                       await request.read(),
                                       secret=server.contrib_secret())
        if event.event == "ping":
            # A ping event; nothing to do.
            # https://developer.github.com/webhooks/#ping-event
            raise ni_abc.ResponseExit(status=http.HTTPStatus.OK)
        elif event.event != "pull_request":
            # Only happens if GitHub is misconfigured to send the wrong events.
            raise TypeError(f"don't know how to handle a {event.event!r} event")
        elif event.data['action'] not in cls._useful_actions:
            raise ni_abc.ResponseExit(status=http.HTTPStatus.NO_CONTENT)
        elif event.data['action'] in {PullRequestEvent.opened.value, PullRequestEvent.synchronize.value}:
            if event.data['action'] == PullRequestEvent.opened.value:
                # GitHub is eventually consistent, so add a delay to wait for
                # the API to digest the new pull request.
                await asyncio.sleep(1)
            return cls(server, client, PullRequestEvent(event.data['action']),
                       event.data)
        elif event.data['action'] == PullRequestEvent.unlabeled.value:
            label = event.data['label']['name']
            if not label.startswith(LABEL_PREFIX):
                raise ni_abc.ResponseExit(status=http.HTTPStatus.NO_CONTENT)
            return cls(server, client, PullRequestEvent.unlabeled, event.data)
        else:  # pragma: no cover
            # Should never happen.
            raise TypeError(f"don't know how to handle a {event.data['action']!r} action")

    async def usernames(self) -> AbstractSet[str]:
        """Return an iterable with all of the contributors' usernames."""
        pull_request = self.request['pull_request']
        # Start with the author of the pull request.
        logins = {pull_request['user']['login']}
        # For each commit, get the author and committer.
        async for commit in self._gh.getiter(pull_request['commits_url']):
            author = commit['author']
            # When the author is missing there seems to typically be a
            # matching commit that **does** specify the author. (issue #56)
            if author:
                author_login = author.get('login')
                if commit['commit']['author']['email'].lower() == GITHUB_EMAIL:
                    self.server.log("Ignoring GitHub-managed username: "******"Ignoring GitHub-managed username: "******"""Construct the URL to the label."""
        if not hasattr(self, '_labels_url'):
            issue_url = self.request['pull_request']['issue_url']
            issue_data = await self._gh.getitem(issue_url)
            self._labels_url = uritemplate.URITemplate(issue_data['labels_url'])
        return self._labels_url.expand(name=label)

    async def current_label(self) -> Optional[str]:
        """Return the current CLA-related label."""
        labels_url = await self.labels_url()
        all_labels = []
        async for label in self._gh.getiter(labels_url):
            all_labels.append(label['name'])
        cla_labels = [x for x in all_labels if x.startswith(LABEL_PREFIX)]
        cla_labels.sort()
        return cla_labels[0] if len(cla_labels) > 0 else None

    async def set_label(self, status: ni_abc.Status) -> str:
        """Set the label on the pull request based on the status of the CLA."""
        labels_url = await self.labels_url()
        if status == ni_abc.Status.signed:
            await self._gh.post(labels_url, data=[CLA_OK])
            return CLA_OK
        else:
            await self._gh.post(labels_url, data=[NO_CLA])
            return NO_CLA

    async def remove_label(self) -> Optional[str]:
        """Remove any CLA-related labels from the pull request."""
        cla_label = await self.current_label()
        if cla_label is None:
            return None
        deletion_url = await self.labels_url(cla_label)
        await self._gh.delete(deletion_url)
        return cla_label

    async def comment(self, status: ni_abc.Status) -> Optional[str]:
        """Add an appropriate comment relating to the CLA status."""
        comments_url = self.request['pull_request']['comments_url']
        if status == ni_abc.Status.signed:
            return None
        elif status == ni_abc.Status.not_signed:
            if random.random() < EASTEREGG_PROBABILITY:  # pragma: no cover
                message = NO_CLA_TEMPLATE.format(body=NO_CLA_BODY_EASTEREGG)
            else:
                message = NO_CLA_TEMPLATE.format(body=NO_CLA_BODY)
        elif status == ni_abc.Status.username_not_found:
            message = NO_CLA_TEMPLATE.format(body=NO_USERNAME_BODY)
        else:  # pragma: no cover
            # Should never be reached.
            raise TypeError("don't know how to handle {}".format(status))
        await self._gh.post(comments_url, data={'body': message})
        return message

    async def update(self, status: ni_abc.Status) -> None:
        if self.event == PullRequestEvent.opened:
            await self.set_label(status)
            await self.comment(status)
        elif self.event == PullRequestEvent.unlabeled:
            # The assumption is that a PR will almost always go from no CLA to
            # being cleared, so don't bug the user with what will probably
            # amount to a repeated message about lacking a CLA.
            await self.set_label(status)
        elif self.event == PullRequestEvent.synchronize:
            current_label = await self.current_label()
            if status == ni_abc.Status.signed:
                if current_label != CLA_OK:
                    await self.remove_label()
            elif current_label != NO_CLA:
                    await self.remove_label()
                    # Since there is a chance a new person was added to a PR
                    # which caused the change in status, a comment on how to
                    # resolve the CLA issue is probably called for.
                    await self.comment(status)
        else:  # pragma: no cover
            # Should never be reached.
            msg = 'do not know how to update a PR for {}'.format(self.event)
            raise RuntimeError(msg)