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

Building GitHub Integrations with Webhooks and ...

Building GitHub Integrations with Webhooks and REST

Webhooks are valuable tools for powering real-time integrations and workflows in your project’s existing tools. This session will walk through an approach of building a webhook-powered application that acts on events as they take place on GitHub. You will also learn how to use the GitHub REST API through the Octokit SDK to call for additional resources after receiving an event.

Brooks Swinnerton

May 07, 2020
Tweet

More Decks by Brooks Swinnerton

Other Decks in Technology

Transcript

  1. Brooks Swinnerton Engineering Manager, Ecosystem Events Jane Sternbach Senior Software

    Engineer, Ecosystem Events John Tzikas Senior Software Engineer, Ecosystem Events
  2. Today’s agenda 1. Introduction to REST APIs
 2. Introduction to

    Webhooks
 3. Webhooks best practices
 4. Workshop: Building an integration
  3. Today’s agenda 1. Introduction to REST APIs
 2. Introduction to

    Webhooks
 3. Webhooks best practices
 4. Workshop: Building an integration
  4. Today’s agenda 1. Introduction to REST APIs
 2. Introduction to

    Webhooks
 3. Webhooks best practices
 4. Workshop: Building an integration
  5. Today’s agenda 1. Introduction to REST APIs
 2. Introduction to

    Webhooks
 3. Webhooks best practices
 4. Workshop: Building an integration
  6. Today’s agenda 1. Introduction to REST APIs
 2. Introduction to

    Webhooks
 3. Webhooks best practices
 4. Workshop: Building an integration
  7. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /user │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │◀───────────────────────────────────│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "login": "bswinnerton", │ │ │ │ │ ... │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  8. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /user │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │◀───────────────────────────────────│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "login": "bswinnerton", │ │ │ │ │ ... │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  9. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /user │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │◀───────────────────────────────────│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "login": "bswinnerton", │ │ │ │ │ ... │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  10. { "login": "bswinnerton", "id": 934497, "name": "Brooks Swinnerton", "company": "GitHub",

    "blog": "https://brooks.sh", "location": "Brooklyn, NY", "bio": "Ecosystem Engineering Manager", "public_repos": 41, "public_gists": 56, "followers": 620, "following": 68, "created_at": "2011-07-23T17:44:47Z", "updated_at": "2020-04-25T00:15:50Z" } > JSON
  11. const { Octokit } = require("@octokit/rest"); const octokit = new

    Octokit(); octokit.users.getAuthenticated();
  12. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  13. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  14. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  15. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ You │ GET /pull_requests/:id │ GitHub │ │ │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  16. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ You │ GET /pull_requests/:id │ GitHub │ │ │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  17. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ You │ GET /pull_requests/:id │ GitHub │ │ │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ │ GET /pull_requests/:id │ │ │ │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  18. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /pull_requests/:id │ │ │e │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ You │ GET /pull_requests/:id │ GitHub │ │ │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 304 Not Modified │ │ │ │ │ │ │ │ │ │ GET /pull_requests/:id │ │ │ │ │───────────────────────────────────▶│ │ │ │ │◀───────────────────────────────────│ │ │ │ │ HTTP 200 OK {...} │ │ │ └─────┘ └────────┘ ▼ > REST API
  19. ┌─────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ GET /user │ │ │e │ │───────────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ You │ │ GitHub │ │ │ │◀───────────────────────────────────│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "login": "bswinnerton", │ │ │ │ │ ... │ │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ └─────┘ └────────┘ ▼ > REST API
  20. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ GitHub │ ... │ You │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  21. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ GitHub │ ... │ You │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  22. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ GitHub │ ... │ You │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  23. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom” ... }, "sender": { "login": “bswinnerton", ... } ... }
  24. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom” ... }, "sender": { "login": “bswinnerton", ... } ... }
  25. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom” ... }, "sender": { "login": “bswinnerton", ... } ... }
  26. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom” ... }, "sender": { "login": “bswinnerton", ... } ... }
  27. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom" ... }, "sender": { "login": "bswinnerton", ... } ... }
  28. check_run check_suite commit_comment content_reference create delete deploy_key deployment deployment_status fork

    github_app_authorization gollum installation installation_repositories issue_comment issues label marketplace_purchase member membership meta milestone organization org_block page_build project_card project_column project public pull_request pull_request_review pull_request_review_comment push package release repository repository_import repository_vulnerability_alert security_advisory sponsorship star status team team_add watch * > developer.github.com/webhooks/
  29. check_run check_suite commit_comment content_reference create delete deploy_key deployment deployment_status fork

    github_app_authorization gollum installation installation_repositories issue_comment issues label marketplace_purchase member membership meta milestone organization org_block page_build project_card project_column project public pull_request pull_request_review pull_request_review_comment push package release repository repository_import repository_vulnerability_alert security_advisory sponsorship star status team team_add watch * > developer.github.com/webhooks/
  30. check_run check_suite commit_comment content_reference create delete deploy_key deployment deployment_status fork

    github_app_authorization gollum installation installation_repositories issue_comment issues label marketplace_purchase member membership meta milestone organization org_block page_build project_card project_column project public pull_request pull_request_review pull_request_review_comment push package release repository repository_import repository_vulnerability_alert security_advisory sponsorship star status team team_add watch * > developer.github.com/webhooks/
  31. check_run check_suite commit_comment content_reference create delete deploy_key deployment deployment_status fork

    github_app_authorization gollum installation installation_repositories issue_comment issues label marketplace_purchase member membership meta milestone organization org_block page_build project_card project_column project public pull_request pull_request_review pull_request_review_comment push package release repository repository_import repository_vulnerability_alert security_advisory sponsorship star status team team_add watch * > developer.github.com/webhooks/
  32. ┌────────┐ ┌─────┐ ┌─────┐ │T │ │ │ │ │ │

    │i │ │ │ │ │ │ │m │ │ POST / │ │ POST / │ │ │e │ │────────────▶│ │────────────▶│ │ │ │ │ { ... } │ │ { ... } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ngrok│ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀────────────│ │◀────────────│ │ │ │ │ HTTP 200 OK │ │ HTTP 200 OK │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ └─────┘ ▼ > ngrok
  33. > ngrok ┌────────┐ ┌─────┐ ┌─────┐ │T │ │ │ │

    │ │ │i │ │ │ │ │ │ │m │ │ POST / │ │ POST / │ │ │e │ │────────────▶│ │────────────▶│ │ │ │ │ { ... } │ │ { ... } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ngrok│ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀────────────│ │◀────────────│ │ │ │ │ HTTP 200 OK │ │ HTTP 200 OK │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ └─────┘ ▼
  34. > ngrok ┌────────┐ ┌─────┐ ┌─────┐ │T │ │ │ │

    │ │ │i │ │ │ │ │ │ │m │ │ POST / │ │ POST / │ │ │e │ │────────────▶│ │────────────▶│ │ │ │ │ { ... } │ │ { ... } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ngrok│ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀────────────│ │◀────────────│ │ │ │ │ HTTP 200 OK │ │ HTTP 200 OK │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ └─────┘ ▼
  35. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  36. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  37. ┌────────┐ ┌─────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │────────────────────────────▶ │ │ │ │ │─────────────────────────▶ │ │ │ │ │ │ │ │ │ GitHub │ │ You │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ └────────┘ └─────┘ ▼ > webhooks
  38. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ GitHub │ ... │ You │ │ │ │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > webhooks
  39. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ Evil │ ... │ You │ │ │ Person │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > malicious webhooks
  40. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ { │ │ │ │ │ "action": "edited", │ │ │ │ Evil │ ... │ You │ │ │ Person │ } │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > malicious webhooks
  41. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ GitHub │ │ You │ │ │ │ │ │ │ │(secret)│ │(secret)│ │ │(abcdef)│ │(abcdef)│ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > shared secret
  42. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ x-hub-signature: f0ad5b │ │ │ │ │ │ │ │ │ │ { │ │ │ │ GitHub │ "action": "edited", │ You │ │ │ │ ... │ │ │ │(secret)│ } │(secret)│ │ │(abcdef)│ │(abcdef)│ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > HMAC signatures
  43. ┌────────┐ ┌────────┐ │T │ │ │ │ │i │ │

    │ │ │m │ │ POST / │ │ │e │ │───────────────────────────────▶│ │ │ │ │ x-hub-signature: f0ad5b ✔ │ │ │ │ │ │ │ │ │ │ { │ │ │ │ GitHub │ "action": "edited", ✔ │ You │ │ │ │ ... │ │ │ │(secret)│ } │(secret)│ │ │(abcdef)│ │(abcdef)│ │ │ │ │ │ │ │ │ │ │ │ │ │◀───────────────────────────────│ │ │ │ │ HTTP 200 OK │ │ │ │ │ │ │ │ └────────┘ └────────┘ ▼ > HMAC signatures
  44. HTTP/1.1 User-Agent: GitHub-Hookshot/ef5a70a X-Github-Delivery: d6552d80-8a73-11ea-83d4-d009fa985176 X-Github-Event: issue_comment { "action": "created",

    "comment": { "id": 621527989, "body": "Hi Mom” ... }, "sender": { "login": “bswinnerton", ... } ... }
  45. • How to develop & test hooks • How to

    make REST API calls via Octokit • Best practices with webhooks What to expect
  46. • Terminal • Editor • Docker • Browser • Your

    repository • GitHub pages site • Webhook deliveries page Preparation