Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Create GitHub bots with PHP & Symfony

Create GitHub bots with PHP & Symfony

Bots are a great way to link tools together and enhance the developers/users experiences across companies and projects.

As engineers, we use GitHub every day and this tool take a huge part in our workflow, and someday we probably need to be able to automatically perform actions when something happens on GitHub.

In this talk, we're gonna learn how to make our own bots to interact with GitHub, by using both GitHub web hooks and GitHub API in PHP, and we'll see how some packages/bundles could help us in Symfony.

Demo bot source code: http://bit.ly/oss-enthusiast-bot

Sylvain Mauduit

November 22, 2016
Tweet

More Decks by Sylvain Mauduit

Other Decks in Programming

Transcript

  1. GitHub bot | Definition A GitHub bot is a web

    app which is going to react to events happening on GitHub by performing some action on its side and/or will trigger other behaviours on GitHub
  2. GitHub bot | Workflow Event Something happens on GitHub GITHUB

    Triggers a Web Hook call GitHub will call your server GITHUB Web hook request handling Process the event CUSTOM APP (BOT) Use GitHub API as an output CUSTOM APP (BOT)
  3. GitHub bot | Today’s menu 1. Connect GitHub to our

    app via GitHub web hooks 2. Communicate with GitHub via the GitHub API
  4. Each GitHub activity will trigger an event. Comment on commit

    on deployment on fork comment on issue/PR labelling an issue when open a PR on push … You can request a web hook call on all/some events GitHub | Events
  5. Web hook payload | Example POST /webhook HTTP/1.1 Host: my_awesome_bot.com

    User-Agent: GitHub-Hookshot/044aadd Content-Type: application/json X-GitHub-Event: issues X-Github-Delivery: 72d3162e-cc78-11e3-81ab-4c9367dc0958 X-Hub-Signature: sha1=5b97ee25c90585f5b809e87d5be7bd942e3c7a28
  6. Web hook payload | Example { "action": "opened", "issue": {

    "url": "https://api.github.com/repos/octocat/Hello-World/issues/1347", "number": 1347, ... }, "repository" : { "id": 1296269, "full_name": "octocat/Hello-World", ... }, "sender": { "login": "octocat", "id": 1, ... } }
  7. Web hook | Security Recreate the signature and compare it

    Using the same secret CUSTOM APP Sign the web hook call Using the secret GITHUB REQUEST X-Hub-Signature sha1=5b97ee25c9… Secret
 my_secret https://developer.github.com/webhooks/securing/
  8. Web hook | Security <?php $signature = $request->headers->get('X-Hub-Signature'); $explodeResult =

    explode('=', $signature, 2); if (2 !== count($explodeResult)) { return false; // Invalid signature header } list($algorithm, $hash) = $explodeResult; $payload = $request->getContent(); $payloadHash = hash_hmac($algorithm, $payload, 'my_secret'); if ($hash !== $payloadHash) { return false; // Invalid signature (wrong secret or altered payload) }
  9. Several choice to auth to GitHub API Personal tokens JWT

    OAuth2 app … Easy way to start (and test the bot): Personal access token https://github.com/settings/tokens/new GitHub API | Authentication
  10. GitHub API | Authentication <?php $token = '23c6834b1d353eabf976e524ed489c812ff86a7d'; $cacheDir =

    sprintf( '%s/github-api-cache', $this->container->getParameter('kernel.cache_dir') ); $client = new Client( new CachedHttpClient( ['cache_dir' => $cacheDir] ) ); $client->authenticate($token, null, Client::AUTH_HTTP_TOKEN);
  11. GitHub API | Call the API <?php $client ->issue() ->comments()

    ->create( 'Octocat', 'Hello-World', 1337, ['body' => 'Hello!'] );
  12. Tips | Development Ngrok
 https://ngrok.com/
 Expose you dev env to

    the world KnpLabs/php-github-api
 https://github.com/KnpLabs/php-github-api
 GitHub API client for PHP
  13. Tips | Development Swop/github-webhook
 https://github.com/Swop/github-webhook
 GitHub web hook signature validator

    & payload deserializer Swop/github-webhook-bundle
 https://github.com/Swop/github-webhook-bundle
 Symfony bundle around the above lib + web hook declaration on controllers with annotations
  14. Tips | Want to try middleware approach? Swop/github-webhook-middleware
 https://github.com/Swop/github-webhook-middleware
 PSR-15

    & PSR-7 middleware Swop/github-webhook-stackphp
 https://github.com/Swop/github-webhook-stackphp
 StackPHP middleware
  15. Middleware | With Zend Stratigility use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; use

    Swop\GitHubWebHook\Security\SignatureValidator; use Swop\GitHubWebHookMiddleware\GithubWebHook; $app = (new \Zend\Stratigility\MiddlewarePipe()) ->pipe(new GithubWebHook(new SignatureValidator(), 'my_secret')) ->pipe('/webhook', function (RequestInterface $request, ResponseInterface $response) { // The security has been check. // Do some stuff with the web hook... return new \Zend\Diactoros\Response\JsonResponse(['message' => 'OK']); }); $request = \Zend\Diactoros\ServerRequestFactory::fromGlobals(); \Zend\Diactoros\Server::createServerFromRequest($app, $request) ->listen(new \Zend\Stratigility\NoopFinalHandler());
  16. Bot | Notificator Main controller Wildcard GitHub event types GitHub

    Web hook REQUEST github. {event_type} DISPATCH (Eventually) Performs actions or get more info on GitHub (using the API) Check review label Internal hook Check review status on merge Internal hook … Internal hook github. {event_type} Notification Notification Notification Attach resulting notifications to the initial event
  17. Bot | Notificator Main controller Wildcard GitHub event types GitHub

    Web hook REQUEST github. {event_type} DISPATCH Notification Notification Notification SlackOutput Post Slack message MailOutput Send a mail MonologOutput Log the notification GitHubOutput Comment on PR/commit StatsDOutput Increment a metric
 on Graphite Output chain LOOP OVER NOTIFICATIONS
  18. Going further | Here’s some ideas… Create a GitHub “Integration”


    https://developer.github.com/early-access/integrations/
 • Uses JWT instead of personal tokens • Act on its own instead of behalf a user • Web hooks / permissions are built-in
  19. Going further | Here’s some ideas… Register your web hooks

    from… your bot web page
 Travis CI-like
 • Create a web interface on your app • Use GitHub API to auto-register itself as web hook on the user-selected repos.
  20. You like these toys? Join us! Senior full-stack eng. Senior

    backend eng. iOS eng. Contact me: [email protected] Image source: pexels.com