async def test_dispatching(): router = routing.Router() event = sansio.Event({ "action": "new", "count": 42 }, event="nothing", delivery_id="1234") await router.dispatch(event) # Should raise no exceptions. shallow_registration = Callback() deep_registration_1 = Callback() deep_registration_2 = Callback() deep_registration_3 = Callback() never_called_1 = Callback() never_called_2 = Callback() never_called_3 = Callback() # Wrong event. router.add(never_called_1.meth, "something") # Wrong event and data detail. router.add(never_called_1.meth, "something", action="new") # Wrong data detail key. router.add(never_called_1.meth, "nothing", never=42) # Wrong data detail value. router.add(never_called_1.meth, "nothing", count=-13) await router.dispatch(event) assert not never_called_1.called router = routing.Router() router.add(shallow_registration.meth, "something") router.add(deep_registration_1.meth, "something", action="new") router.add(deep_registration_2.meth, "something", action="new") router.add(deep_registration_3.meth, "something", count=42) router.add(never_called_1.meth, "something else") router.add(never_called_2.meth, "something", never="called") router.add(never_called_3.meth, "something", count=-13) event = sansio.Event({ "action": "new", "count": 42, "ignored": True }, event="something", delivery_id="1234") await router.dispatch(event) assert shallow_registration.called assert deep_registration_1.called assert deep_registration_2.called assert deep_registration_3.called assert not never_called_1.called assert not never_called_2.called assert not never_called_3.called
async def test_router_copy(): router = routing.Router() deep_callback = Callback() shallow_callback = Callback() router.add(deep_callback.meth, "something", extra=42) router.add(shallow_callback.meth, "something") event = sansio.Event({"extra": 42}, event="something", delivery_id="1234") await router.dispatch(event) assert deep_callback.called assert shallow_callback.called deep_callback.called = shallow_callback.called = False other_router = routing.Router(router) await other_router.dispatch(event) assert deep_callback.called assert shallow_callback.called
async def test_shallow_callback(): router = routing.Router() callback = Callback() router.add(callback.meth, "pull_request") event = sansio.Event({}, event="pull_request", delivery_id="1234") await router.dispatch(event) assert callback.called assert callback.event == event
async def test_deep_callback(): router = routing.Router() callback = Callback() router.add(callback.meth, "pull_request", data=42) event = sansio.Event({"data": 42}, event="pull_request", delivery_id="1234") await router.dispatch(event) assert callback.called assert callback.event == event assert not callback.args assert not callback.kwargs
async def test_register(): router = routing.Router() called = False @router.register("pull_request", action="new") async def callback(event): nonlocal called called = True event = sansio.Event({"action": "new"}, event="pull_request", delivery_id="1234") await router.dispatch(event) assert called
async def test_shallow_callback(): router = routing.Router() callback = Callback() router.add(callback.meth, "pull_request") event = sansio.Event({}, event="pull_request", delivery_id="1234") await router.dispatch(event) assert callback.called assert callback.event == event assert not callback.args assert not callback.kwargs await router.dispatch(event, 42, hello="world") assert callback.args == (42, ) assert callback.kwargs == {"hello": "world"}
async def configure(self, config, router, session): logger.debug('Configuring github plugin') self._verification = os.environ.get('SIRBOT_GITHUB_SECRET') if not self._verification: raise GitHubSetupError('SIRBOT_GITHUB_SECRET NOT SET') path = os.path.join(os.path.dirname(os.path.abspath(__file__)), '..', 'config.yml') with open(path) as file: defaultconfig = yaml.load(file) self._config = merge_dict(config, defaultconfig[self.__name__]) self._session = session self._http_router = router self._github_router = routing.Router() logger.debug('Adding github endpoint: %s', self._config['endpoint']) self._http_router.add_route('POST', self._config['endpoint'], self._dispatch) self._started = True
import asyncio import datetime import os from typing import Any import aiohttp import cachetools from aiohttp import web from gidgethub import routing from gidgethub.sansio import Event from . import check_runs, installations, issues, pull_requests from .api import GitHubAPI from .log import CustomAccessLogger, logger router = routing.Router(check_runs.router, installations.router, issues.router, pull_requests.router) cache = cachetools.LRUCache(maxsize=500) # type: cachetools.LRUCache[Any, Any] async def main(request: web.Request) -> web.Response: try: body = await request.read() secret = os.environ.get("GITHUB_SECRET") event = Event.from_http(request.headers, body, secret=secret) if event.event == "ping": return web.Response(status=200) logger.info( "event=%(event)s delivery_id=%(delivery_id)s", { "event": f"{event.event}:{event.data['action']}",
import logging from typing import Any from gidgethub import routing from gidgethub.sansio import Event from algorithms_keeper import utils from algorithms_keeper.api import GitHubAPI from algorithms_keeper.constants import EMPTY_ISSUE_BODY_COMMENT, Label issues_router = routing.Router() logger = logging.getLogger(__package__) @issues_router.register("issues", action="opened") async def close_invalid_issue(event: Event, gh: GitHubAPI, *args: Any, **kwargs: Any) -> None: """Close an invalid issue. An issue is considered invalid if: - It doesn't contain any description. """ issue = event.data["issue"] if not issue["body"]: logger.info("Empty issue body: %s", issue["html_url"]) await utils.close_pr_or_issue( gh, comment=EMPTY_ISSUE_BODY_COMMENT.format( user_login=issue["user"]["login"]),
import asyncio import os import sys import traceback import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import black_out router = routing.Router(black_out.router) cache = cachetools.LRUCache(maxsize=500) async def main(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) print("GH delivery ID", event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH") async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI( session,
import logging from typing import Any from gidgethub import routing from gidgethub.sansio import Event from algorithms_keeper.api import GitHubAPI from algorithms_keeper.constants import GREETING_COMMENT installation_router = routing.Router() logger = logging.getLogger(__package__) @installation_router.register("installation", action="created") @installation_router.register("installation_repositories", action="added") async def repo_installation_added(event: Event, gh: GitHubAPI, *args: Any, **kwargs: Any) -> None: """Give the repository a heads up that the app has been installed. This callback will be triggered by two events: 1. When a new installation for this app is added 2. When a new repository is added in an existing installation """ try: repositories = event.data["repositories"] except KeyError: repositories = event.data["repositories_added"] for repository in repositories: repo_name = repository["full_name"]
import asyncio import importlib import os import sys import traceback import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import backport, bpo router = routing.Router(backport.router, bpo.router) cache = cachetools.LRUCache(maxsize=500) async def main(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) print('GH delivery ID', event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH") with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session, "python/bedevere",
import os import sys import traceback import cachetools from aiohttp import web from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import backport_pr from . import delete_branch from . import status_change router = routing.Router(backport_pr.router, delete_branch.router, status_change.router) cache = cachetools.LRUCache(maxsize=500) async def main(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) print('GH delivery ID', event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH") async with aiohttp.ClientSession() as session:
post = await request.post() sha = post['sha'].strip() async with dbpool.acquire() as conn: async with conn.cursor() as cursor: await cursor.execute('INSERT INTO authorized_shas (sha) VALUES (%s);', sha) log.info(f'authorized sha: {sha}') session = await aiohttp_session.get_session(request) set_message(session, f'SHA {sha} authorized.', 'info') raise web.HTTPFound('/') @routes.get('/healthcheck') async def healthcheck(request): # pylint: disable=unused-argument return web.Response(status=200) gh_router = gh_routing.Router() @gh_router.register('pull_request') async def pull_request_callback(event): gh_pr = event.data['pull_request'] number = gh_pr['number'] target_branch = FQBranch.from_gh_json(gh_pr['base']) for wb in watched_branches: if (wb.prs and number in wb.prs) or (wb.branch == target_branch): await wb.notify_github_changed(event.app) @gh_router.register('push') async def push_callback(event): data = event.data
from algorithms_keeper.constants import ( CHECKBOX_NOT_TICKED_COMMENT, EMPTY_PR_BODY_COMMENT, INVALID_EXTENSION_COMMENT, MAX_PR_REACHED_COMMENT, PR_REVIEW_COMMENT, Label, ) from algorithms_keeper.parser import PythonParser # To disable this check, set the constant to 0. MAX_PR_PER_USER = 3 STAGE_PREFIX = "awaiting" MAX_RETRIES = 5 pull_request_router = routing.Router() logger = logging.getLogger(__package__) async def update_stage_label( gh: GitHubAPI, *, pull_request: Dict[str, Any], next_label: Optional[str] = None ) -> None: """Update the stage label of the given pull request. This is a two steps process with one being optional: 1. Remove any of the stage labels, if present. 2. Add the next stage label given in the `next_label` argument. If `next_label` argument is not provided, then only the first step is performed.
def test_too_much_detail(): router = routing.Router() with pytest.raises(TypeError): router.add(None, "pull_request", data=42, too_much=6)
import asyncio import logging import os import aiohttp import azure.functions as func from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from ..ghutils import ping from ..ghutils import server from . import classify, closed router = routing.Router(classify.router, closed.router, ping.router) CLIENT_SESSION = None async def main(req: func.HttpRequest) -> func.HttpResponse: global CLIENT_SESSION try: if CLIENT_SESSION is None: CLIENT_SESSION = aiohttp.ClientSession() secret = os.environ.get("GH_SECRET") oauth_token = os.environ.get("GH_AUTH") body = req.get_body() gh = gh_aiohttp.GitHubAPI( CLIENT_SESSION, "Microsoft/pvscbot", oauth_token=oauth_token )
import asyncio import os import sys import traceback import aiohttp import cachetools from aiohttp import web from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing, sansio from . import check_runs, installations router = routing.Router(installations.router, check_runs.router) cache = cachetools.LRUCache(maxsize=500) # type: cachetools.LRUCache async def main(request: web.Request) -> web.Response: try: body = await request.read() secret = os.environ.get("GITHUB_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) if event.event == "ping": return web.Response(status=200) async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session, "algorithms-bot", cache=cache) # Give GitHub some time to reach internal consistency. await asyncio.sleep(1) await router.dispatch(event, gh) try:
import asyncio import os import sys import traceback import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import wip router = routing.Router(wip.router) cache = cachetools.LRUCache(maxsize=500) async def handler(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) print('GH delivery ID', event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH") async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session, "aio-libs/github-bot", oauth_token=oauth_token,
import os import aiohttp from gidgethub.aiohttp import GitHubAPI from aiohttp import web from gidgethub import routing, sansio from gidgethub import aiohttp as gh_aiohttp from utils.auth import get_jwt, get_installation, get_installation_access_token import event import json routes = web.RouteTableDef() router = routing.Router(event.router) @routes.post("/") async def main(request): body = await request.read() user = json.loads(body.decode('utf8'))['repository']['owner']['login'] repo = json.loads(body.decode('utf8'))['repository']['full_name'] secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) async with aiohttp.ClientSession() as session: app_id = os.getenv("GH_APP_ID") jwt = get_jwt(app_id) gh = gh_aiohttp.GitHubAPI(session, user) try: installation = await get_installation(gh, jwt, user) except ValueError as ve: print(ve) else: access_token = await get_installation_access_token(
import asyncio import importlib import os import sys import traceback import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import review router = routing.Router(review.router) cache = cachetools.LRUCache(maxsize=500) async def main(request): """The actual webserver instance to work with GH webhooks later on""" try: body = await request.read() secret = os.environ.get("GH_SECRET") bot_usr = os.environ.get("GH_USERNAME") event = sansio.Event.from_http(request.headers, body, secret=secret) print("GH delivery ID", event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH")
import asyncio import importlib import os import sys import traceback import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from . import backport, bpo, close_pr, follow_up, news, stage router = routing.Router(backport.router, bpo.router, close_pr.router, follow_up.router, news.router, stage.router) cache = cachetools.LRUCache(maxsize=500) async def main(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) print('GH delivery ID', event.delivery_id, file=sys.stderr) if event.event == "ping": return web.Response(status=200) oauth_token = os.environ.get("GH_AUTH") async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session, "python/bedevere",
import logging from typing import Any, List from gidgethub import routing from gidgethub.sansio import Event from algorithms_keeper import utils from algorithms_keeper.api import GitHubAPI from algorithms_keeper.constants import Label check_run_router = routing.Router() logger = logging.getLogger(__package__) @check_run_router.register("check_run", action="completed") async def check_ci_status_and_label(event: Event, gh: GitHubAPI, *args: Any, **kwargs: Any) -> None: """Add and remove label when any of the check runs fail. This event will be triggered on every check run when it is completed but we only want to know the final conclusion. So, the `if` statement makes sure we execute the block only when the last check run is completed. """ repository = event.data["repository"]["full_name"] try: commit_sha = event.data["check_run"]["head_sha"] pr_for_commit = await utils.get_pr_for_commit(gh, sha=commit_sha, repository=repository)
import os from aiohttp import web import aiohttp from gidgethub import routing, sansio from gidgethub import aiohttp as gh_aiohttp from . import pull_request from . import comments router = routing.Router(pull_request.router, comments.router) async def test(request): return web.Response(status=200, text="Hello world!") async def main(request): # read the GitHub webhook payload body = await request.read() # our authentication token and secret oauth_token = os.environ.get("GH_TOKEN") # a representation of GitHub webhook event event = sansio.Event.from_http(request.headers, body) # instead of mariatta, use your own username async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session,
``@algorithms-keeper review-all`` to trigger the checks for all the pull request files, including the modified files. As we cannot post review comments on lines not part of the diff, this command only modify the labels accordingly. """ import logging import re from typing import Any, Pattern from gidgethub import routing from gidgethub.sansio import Event from algorithms_keeper import utils from algorithms_keeper.api import GitHubAPI from algorithms_keeper.event.pull_request import check_pr_files commands_router = routing.Router() COMMAND_RE: Pattern[str] = re.compile(r"@algorithms-keeper\s+([a-z\-]+)", re.IGNORECASE) logger = logging.getLogger(__package__) @commands_router.register("issue_comment", action="created") async def main(event: Event, gh: GitHubAPI, *args: Any, **kwargs: Any) -> None: """Main function to parse the issue comment body and call the respective command function if it matches. Only the comments made by either the member or the owner of the organization will be considered. """
import importlib import logging import os import sys import traceback import aiohttp from aiohttp import web from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from .ghutils import server from .github import classify, closed, news router = routing.Router(classify.router, closed.router, news.router) async def hello(_): return web.Response(text="Hello, world") async def main(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") oauth_token = os.environ.get("GH_AUTH") async with aiohttp.ClientSession() as session: gh = gh_aiohttp.GitHubAPI(session, "Microsoft/pvscbot", oauth_token=oauth_token)
import aiohttp from aiohttp import web import cachetools from gidgethub import aiohttp as gh_aiohttp from gidgethub import routing from gidgethub import sansio from gidgethub import apps from webservice import issues, installation cache = cachetools.LRUCache(maxsize=500) routes = web.RouteTableDef() router = routing.Router(issues.router, installation.router) @routes.get("/", name="home") async def handle_get(request): return web.Response(text="Hello world") @routes.post("/webhook") async def webhook(request): try: body = await request.read() secret = os.environ.get("GH_SECRET") event = sansio.Event.from_http(request.headers, body, secret=secret) if event.event == "ping": return web.Response(status=200)
"""Check if a bugs.python.org issue number is specified in the pull request's title.""" import re from gidgethub import routing from . import util router = routing.Router() TAG_NAME = "issue-number" CLOSING_TAG = f"<!-- /{TAG_NAME} -->" BODY = f"""\ {{body}} <!-- {TAG_NAME}: bpo-{{issue_number}} --> https://bugs.python.org/issue{{issue_number}} {CLOSING_TAG} """ ISSUE_RE = re.compile(r"bpo-(?P<issue>\d+)") SKIP_ISSUE_LABEL = util.skip_label("issue") STATUS_CONTEXT = "bedevere/issue-number" # Try to keep descriptions at or below 50 characters, else GitHub's CSS will truncate it. _FAILURE_DESCRIPTION = 'No issue # in title or "skip issue" label found' _FAILURE_URL = "https://devguide.python.org/pullrequest/#submitting" FAILURE_STATUS = util.create_status(STATUS_CONTEXT, util.StatusState.FAILURE, description=_FAILURE_DESCRIPTION, target_url=_FAILURE_URL) del _FAILURE_DESCRIPTION del _FAILURE_URL SKIP_ISSUE_STATUS = util.create_status(STATUS_CONTEXT,
import sys import traceback import aiohttp from aiohttp import web from gidgethub import apps from gidgethub import routing from gidgethub import sansio from gidgethub.aiohttp import GitHubAPI from marvin import commands from marvin import constants from marvin import status from marvin import triage_runner router = routing.Router(commands.router, status.router) routes = web.RouteTableDef() def is_bot_comment(event: sansio.Event) -> bool: """Determine whether an event was triggered by our own comments.""" if "comment" not in event.data: return False comment = event.data["comment"] comment_author_login = comment["user"]["login"] return comment_author_login in [constants.BOT_NAME, constants.BOT_NAME + "[bot]"] def is_opted_in(event: sansio.Event) -> bool: """Perform a conservative opt-in check.