Slide 1

Slide 1 text

Improving your workflow With GitHub’s API keavy

Slide 2

Slide 2 text

533 endpoints

Slide 3

Slide 3 text

Hello world.

Slide 4

Slide 4 text

Unauthenticated requests curl https://api.github.com/zen Practicality beats purity.

Slide 5

Slide 5 text

Unauthenticated requests curl -i https://api.github.com/users/keavy

Slide 6

Slide 6 text

Unauthenticated requests

Slide 7

Slide 7 text

Authenticated requests curl -i -u keavy:passw0rd https://api.github.com/keavy

Slide 8

Slide 8 text

GraphQL API https://developer.github.com/v4/

Slide 9

Slide 9 text

REST API https://developer.github.com/v3/

Slide 10

Slide 10 text

Then what?

Slide 11

Slide 11 text

Options for authentication • Personal Access Token • OAuth Application • GitHub Application

Slide 12

Slide 12 text

Personal Access Token • It’s a String (“f3e4b0c62a15dc2e5c…”) • Like a password • Functions like an OAuth token - broad permissions.

Slide 13

Slide 13 text

Personal Access Token: Good Ideas! • Acting just as yourself • Authenticating over the API as yourself • One off cURL commands • Personal scripts

Slide 14

Slide 14 text

Personal Access Token: Bad Ideas! • Setting up something for your whole team/company to use • Pretending to be a bot

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

OAuth Application • It’s an application. • It needs to be hosted somewhere. • You grant it broad permissions, e.g. to your repositories.

Slide 17

Slide 17 text

OAuth Application: Good Ideas! • Act as a GitHub user, across all of GitHub • Just identity - “login with GitHub”

Slide 18

Slide 18 text

OAuth Application: Bad Ideas! • Doing stuff on a specific repository (but not the rest!) • Doing stuff that should be acting as the Application itself

Slide 19

Slide 19 text

No content

Slide 20

Slide 20 text

GitHub App • It’s an application. • It needs to be hosted somewhere. • You install it on specific repositories. • You grant it narrow permissions, e.g. to write issues

Slide 21

Slide 21 text

GitHub App: Good Ideas! • The app needs to take actions, independently of a user • You only want to do stuff on specific repos • You want a direct connection to an Organization • You don't need to know and do everything the user can

Slide 22

Slide 22 text

GitHub App: Bad Ideas! • Identity provider: "login with GitHub” • Only want to act as the GitHub user, in everything they can do.

Slide 23

Slide 23 text

No content

Slide 24

Slide 24 text

Which is right? For you.

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

For you

Slide 27

Slide 27 text

API calls export GITHUB_TOKEN=47244ff0d0464521969 curl -u keavy:$GITHUB_TOKEN https://api.github.com/user/issues

Slide 28

Slide 28 text

Script to fetch your contributions : ${GITHUB_TOKEN:=`git config github.token`} : ${GH_LOGIN:=`git config github.user`} # e.g. for PRs I opened that were merged query = "author:$GH_LOGIN+is:merged+is:pr" url="https://api.github.com/search/issues? access_token=$GITHUB_TOKEN&q=$query"

Slide 29

Slide 29 text

For your team

Slide 30

Slide 30 text

Script GitHub App

Slide 31

Slide 31 text

GitHub App Slack App Email In-house App Another API GitHub

Slide 32

Slide 32 text

Improving your workflow With GitHub’s API keavy

Slide 33

Slide 33 text

Some examples

Slide 34

Slide 34 text

Contributions for

Slide 35

Slide 35 text

PRs labeled with

Slide 36

Slide 36 text

PRs awaiting your team’s response

Slide 37

Slide 37 text

Create an issue for your Team’s activity

Slide 38

Slide 38 text

Create an issue for your Team’s activity

Slide 39

Slide 39 text

How to build them

Slide 40

Slide 40 text

1. Register a GitHub App 2. Configure your app 3. Host it somewhere 4. Install it on the desired repos on GitHub 5. Steps to building a GitHub App

Slide 41

Slide 41 text

Step 1: Register a GitHub App

Slide 42

Slide 42 text

Step 1: Register a GitHub App

Slide 43

Slide 43 text

Step 1: Register a GitHub App

Slide 44

Slide 44 text

Step 1: Register a GitHub App

Slide 45

Slide 45 text

Step 1: Register a GitHub App https://developer.github.com/webhooks/securing/

Slide 46

Slide 46 text

Protip

Slide 47

Slide 47 text

Protip

Slide 48

Slide 48 text

Step 1: Register a GitHub App https://developer.github.com/v3/apps/permissions/

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

Step 2: Configure your GitHub App

Slide 51

Slide 51 text

No content

Slide 52

Slide 52 text

What installations do I have? Who am I? What installations can I show this user? Give me a token for this installation.

Slide 53

Slide 53 text

What installations do I have? Who am I? What installations can I show this user? Give me a token for this installation. Authenticate as the App

Slide 54

Slide 54 text

def self.private_key pem = ENV["GITHUB_APP_PRIVATE_KEY"] @private_key ||= OpenSSL::PKey::RSA.new(pem) end Configure your GitHub App App credentials

Slide 55

Slide 55 text

payload = { iat: Time.now, exp: 10.minute.from_now, iss: ENV["GITHUB_APP_IDENTIFIER"] } JWT.encode payload, Config.private_key, "RS256" Configure your GitHub App App credentials

Slide 56

Slide 56 text

@app_client = Octokit::Client.new( bearer_token: Demo::Config.jwt_assertion) Configure your GitHub App To make high-level API requests as the App

Slide 57

Slide 57 text

@app_client.get "/app" Configure your GitHub App To make high-level API requests as the App https://developer.github.com/v3/apps/

Slide 58

Slide 58 text

What repositories can I work with? What repositories can I show this user? What are the latest PRs in this repo? What members are in this team? What issues have mentioned this team lately?

Slide 59

Slide 59 text

What repositories can I work with? What repositories can I show this user? What are the latest PRs in this repo? What members are in this team? What issues have mentioned this team lately? Authenticate as the installation

Slide 60

Slide 60 text

client.create_integration_installation_access_token( installation_github_identifier ) Configure your GitHub App To make API requests for a specific installation

Slide 61

Slide 61 text

@installation_client = Octokit::Client.new( :access_token => @installation.current_token ) Configure your GitHub App To make API requests for a specific installation

Slide 62

Slide 62 text

@installation_client.get "/installation/repositories" Configure your GitHub App To make API requests for a specific installation https://developer.github.com/v3/apps/installations/

Slide 63

Slide 63 text

Watch out for

Slide 64

Slide 64 text

401 But whyyyyy?

Slide 65

Slide 65 text

401 But I’m doing everything right. Right?!

Slide 66

Slide 66 text

401 Clearly the API just hates me.

Slide 67

Slide 67 text

401 &&& Oh. It was that.

Slide 68

Slide 68 text

It’s good to talk. ''' https://platform.github.community/

Slide 69

Slide 69 text

Step 3: Host it somewhere

Slide 70

Slide 70 text

No content

Slide 71

Slide 71 text

Step 4: Install it

Slide 72

Slide 72 text

No content

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

post "/webhook" do case request.env['HTTP_X_GITHUB_EVENT'] when "installation" Demo::Installation.create_from_webhook( parsed_post_params["installation"] ) end halt 200 end Configure your GitHub App https://developer.github.com/v3/activity/events/types/#installationevent

Slide 75

Slide 75 text

Step 5: Use it!

Slide 76

Slide 76 text

GitHub App Slack App Email In-house App Another API GitHub

Slide 77

Slide 77 text

Connect it to a Slack App

Slide 78

Slide 78 text

Create or change content on GitHub

Slide 79

Slide 79 text

Send an email

Slide 80

Slide 80 text

API details

Slide 81

Slide 81 text

Contributions for

Slide 82

Slide 82 text

Process the request POST http://my-app.com/contributions text=keavy

Slide 83

Slide 83 text

Process the request POST http://my-app.com/contributions text=keavy login

Slide 84

Slide 84 text

# PRs the user opened @installation.client.search_issues( “created:>#{started_at_string} @#{@account} author:#{login} type:pr state:open") Search for the data

Slide 85

Slide 85 text

# PRs the user opened @installation.client.search_issues( “created:>#{started_at_string} @#{@account} author:#{login} type:pr state:open") Search for the data

Slide 86

Slide 86 text

# PRs the user opened @installation.client.search_issues( “created:>#{started_at_string} @#{@account} author:#{login} type:pr state:open") Search for the data

Slide 87

Slide 87 text

# PRs the user opened @installation.client.search_issues( “created:>#{started_at_string} @#{@account} author:#{login} type:pr state:open") Search for the data

Slide 88

Slide 88 text

# PRs the user commented on @installation.client.search_issues( “created:>#{started_at_string} @#{@account} commenter:#{login} type:pr state:open") Search for the data

Slide 89

Slide 89 text

https://developer.github.com/v3/libraries/ client.search_issues

Slide 90

Slide 90 text

No content

Slide 91

Slide 91 text

# PRs the user opened @installation.client.search_issues( “created:>#{started_at_string} @#{@account} author:#{login} type:pr state:open") Search for the data

Slide 92

Slide 92 text

https://developer.github.com/v3/search/#search-issues { "total_count": 280, "incomplete_results": false, "items": [ { "html_url": "https://github.com/batterseapower/pinyin-toolkit/issues/132", "number": 132, "title": "Line Number Indexes Beyond 20 Not Displayed", "user": { "login": "Nick3C", }, "labels": [ { "url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/labels/bug", "name": "bug", "color": "ff0000" } ], "state": "open" } ] }

Slide 93

Slide 93 text

https://developer.github.com/v3/search/#search-issues { "total_count": 280, "incomplete_results": false, "items": [ { "html_url": "https://github.com/batterseapower/pinyin-toolkit/issues/132", "number": 132, "title": "Line Number Indexes Beyond 20 Not Displayed", "user": { "login": "Nick3C", }, "labels": [ { "url": "https://api.github.com/repos/batterseapower/pinyin-toolkit/labels/bug", "name": "bug", "color": "ff0000" } ], "state": "open" } ] }

Slide 94

Slide 94 text

def formatted_results(category, items) "\n### #{category} (#{items.count})\n" + # format each item end def formatted_result(item) # get the repo name for that item " * [x] [#{repo}##{item.number}](#{item.html_url}) #{item.title}" end Format the results

Slide 95

Slide 95 text

def deliver!(content) status = 200 content_type :json { :response_type => 'in_channel', :text => content }.to_json end Send the results to a Slack App

Slide 96

Slide 96 text

Contributions for

Slide 97

Slide 97 text

PRs labeled with

Slide 98

Slide 98 text

Process the request POST http://my-app.com/labeled text=reviewable,bug

Slide 99

Slide 99 text

Process the request POST http://my-app.com/labeled text=reviewable,bug labels

Slide 100

Slide 100 text

is:open is:pr repo:org/repo_a repo:org/repo_b label:reviewable label:bug -label:blocked Build up a query

Slide 101

Slide 101 text

https://github.com/search/advanced Protip

Slide 102

Slide 102 text

# Search issues via the API @installation.client.search_issues(query.join(" ")).items Request the data from the API

Slide 103

Slide 103 text

PRs labeled with

Slide 104

Slide 104 text

PRs awaiting your team’s response

Slide 105

Slide 105 text

Build the query is:open is:pr org:api-playground team:api-playground/test-team -commenter:keavy -commenter:tarebyte updated:>2017-09-13

Slide 106

Slide 106 text

@installation.client.search_issues(query.join(" ")).items Request the data from the API

Slide 107

Slide 107 text

No content

Slide 108

Slide 108 text

PRs awaiting your team’s response

Slide 109

Slide 109 text

Create an issue for your Team’s activity

Slide 110

Slide 110 text

Process the request POST http://my-app.com/radar text=@api-playground/test-team api-sandbox

Slide 111

Slide 111 text

Process the request POST http://my-app.com/radar text=@api-playground/test-team api-sandbox team_name repo_name

Slide 112

Slide 112 text

Prepare the content # Check for data from other tools, e.g. who’s on call via PagerDuty # Check for checkbox items from the previous week’s radar # Prepare the text bits: @title ||= "Radar: Week of #{Date.today}” @body << "What's up, #{team_name}? What happened? " + "What's about to happen? What's going on in your head? "

Slide 113

Slide 113 text

Deliver output @installation.client.create_issue(@repo_name, @title, @body)

Slide 114

Slide 114 text

Deliver output @installation.client.create_issue(@repo_name, @title, @body)

Slide 115

Slide 115 text

Create an issue for your Team’s activity

Slide 116

Slide 116 text

Possibilities

Slide 117

Slide 117 text

Onboard new team member https://developer.github.com/v3/orgs/teams/ https://developer.github.com/v3/repos/collaborators/ • Add someone as a collaborator to certain repositories • Add them to certain teams (and/or the organization itself)

Slide 118

Slide 118 text

PR approval process https://developer.github.com/v3/orgs/teams/ • At least 2 people have reviewed a PR • The PR has been reviewed by someone who didn’t write the code • Separate approval for the code AND deployment • A manager has approved it, on the 2nd Wednesday of the month

Slide 119

Slide 119 text

PR approval process https://developer.github.com/v3/orgs/teams/ • At least 2 people have reviewed a PR • The PR has been reviewed by someone who didn’t write the code • Separate approval for the code AND deployment • A manager has approved it, on the 2nd Wednesday of the month

Slide 120

Slide 120 text

We’re hiring

Slide 121

Slide 121 text

PR approval process https://developer.github.com/v3/orgs/teams/ • At least 2 people have reviewed a PR • The PR has been reviewed by someone who didn’t write the code • Separate approval for the code AND deployment • A manager has approved it, on the 2nd Wednesday of the month

Slide 122

Slide 122 text

List commits on a PR https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request

Slide 123

Slide 123 text

List commits on a PR https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request [ { "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", "commit": { "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5", "message": "Fix all the bugs", }, "author": { "login": "octocat", "id": 1 } } ]

Slide 124

Slide 124 text

List commits on a PR https://developer.github.com/v3/pulls/#list-commits-on-a-pull-request [ { "sha": "6dcb09b5b57875f334f61aebed695e2e4193db5e", "commit": { "url": "https://api.github.com/repos/octocat/Hello-World/git/commits/6dcb09b5", "message": "Fix all the bugs", }, "author": { "login": "octocat", "id": 1 } } ]

Slide 125

Slide 125 text

List reviews on a PR https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request

Slide 126

Slide 126 text

List reviews on a PR https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request [ { "id": 80, "user": { "login": "octocat", "id": 1 }, "body": "Here is the body for the review." } ]

Slide 127

Slide 127 text

List reviews on a PR https://developer.github.com/v3/pulls/reviews/#list-reviews-on-a-pull-request [ { "id": 80, "user": { "login": "octocat", "id": 1 }, "body": "Here is the body for the review." } ]

Slide 128

Slide 128 text

Slide 129

Slide 129 text

Create a status https://developer.github.com/v3/repos/statuses/#create-a-status POST /repos/:owner/:repo/statuses/:sha { "state": "success", "description": "Approved by the wider crew", "context": "Review Process" }

Slide 130

Slide 130 text

Create a status https://developer.github.com/v3/repos/statuses/#create-a-status

Slide 131

Slide 131 text

Improving your workflow With GitHub’s API keavy

Slide 132

Slide 132 text

Work back from the problem • I want an ‘at a glance’ view of current bugs. • I want to check what PRs my team should look into. • I want to know what my team is up to.

Slide 133

Slide 133 text

Then from what you want to get

Slide 134

Slide 134 text

Then from what you want to get

Slide 135

Slide 135 text

Then from what you want to get

Slide 136

Slide 136 text

Reference

Slide 137

Slide 137 text

It’s good to talk. ''' https://platform.github.community/

Slide 138

Slide 138 text

401 Clearly the API just hates me.

Slide 139

Slide 139 text

200 I made that.

Slide 140

Slide 140 text

Thank you. keavy