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

Launching GitHub's GraphQL API

Sponsored · Ship Features Fearlessly Turn features on and off without deploys. Used by thousands of Ruby developers.

Launching GitHub's GraphQL API

Avatar for Brooks Swinnerton

Brooks Swinnerton

October 11, 2017
Tweet

More Decks by Brooks Swinnerton

Other Decks in Technology

Transcript

  1. { "login": "bswinnerton", "id": 934497, "avatar_url": "https://avatars1.githubusercontent.com/u/934497?v=4", "url": "https://api.github.com/users/bswinnerton", "html_url":

    "https://github.com/bswinnerton", "site_admin": true, "name": "Brooks Swinnerton", "location": "Brooklyn, NY", "email": "[email protected]", "bio": ":octocat:", "public_repos": 32, "public_gists": 55, "followers": 231, "following": 60, "created_at": "2011-07-23T17:44:47Z", "updated_at": "2017-10-02T17:38:48Z", "private_gists": 172, "total_private_repos": 9, "owned_private_repos": 8, "disk_usage": 87918, "collaborators": 7, "plan": { "name": "developer", "space": 976562499, "collaborators": 0, "private_repos": 9999 } } https://api.github.com/user GET
  2. { "login": "bswinnerton", "id": 934497, "avatar_url": "https://avatars1.githubusercontent.com/u/934497?v=4", "url": "https://api.github.com/users/bswinnerton", "html_url":

    "https://github.com/bswinnerton", "site_admin": true, "name": "Brooks Swinnerton", "location": "Brooklyn, NY", "email": "[email protected]", "bio": ":octocat:", "public_repos": 32, "public_gists": 55, "followers": 231, "following": 60, "created_at": "2011-07-23T17:44:47Z", "updated_at": "2017-10-02T17:38:48Z", "private_gists": 172, "total_private_repos": 9, "owned_private_repos": 8, "disk_usage": 87918, "collaborators": 7, "plan": { "name": "developer", "space": 976562499, "collaborators": 0, "private_repos": 9999 } } https://api.github.com/user GET
  3. { "login": "bswinnerton", "id": 934497, "name": "Brooks Swinnerton", "location": "Brooklyn,

    NY", "email": "[email protected]", "bio": ":octocat:", ... } https://api.github.com/user GET
  4. https://api.github.com/user GET { "login": "bswinnerton", "id": 934497, "name": "Brooks Swinnerton",

    "location": "Brooklyn, NY", "email": "[email protected]", "bio": ":octocat:", "public_repos": 32, "public_gists": 55, "private_gists": 172, "owned_private_repos": 8, ... }
  5. https://api.github.com/user GET { "login": "bswinnerton", "id": 934497, "name": "Brooks Swinnerton",

    "location": "Brooklyn, NY", "email": "[email protected]", "bio": ":octocat:", "public_repos": 32, "public_gists": 55, "private_gists": 172, "owned_private_repos": 8, "url": "https://api.github.com/users/bswinnerton", "gists_url": "https://api.github.com/users/bswinnerton/gists{/ gist_id}", "repos_url": "https://api.github.com/users/bswinnerton/repos", ... }
  6. https://api.github.com/user GET { "login": "bswinnerton", "id": 934497, "name": "Brooks Swinnerton",

    "location": "Brooklyn, NY", "email": "[email protected]", "bio": ":octocat:", "public_repos": 32, "public_gists": 55, "private_gists": 172, "owned_private_repos": 8, "url": "https://api.github.com/users/bswinnerton", "gists_url": "https://api.github.com/users/bswinnerton/gists{/ gist_id}", "repos_url": "https://api.github.com/users/bswinnerton/repos", ... }
  7. https://api.github.com/users/bswinnerton/repos GET [ { "id": 82398282, "name": "launchbar-github", "private": false,

    "description": "A LaunchBar action for GitHub", "language": "JavaScript", "homepage": "http://launchbar-github.com", "owner": { "login": "bswinnerton", "id": 934497, "url": "https://api.github.com/users/bswinnerton", ... }, "url": "https://api.github.com/repos/bswinnerton/launchbar-github", "issues_url": "https://api.github.com/repos/bswinnerton/launchbar-github/ issues{/number}" }, ... ]
  8. https://api.github.com/users/bswinnerton/repos GET [ { "id": 82398282, "name": "launchbar-github", "private": false,

    "description": "A LaunchBar action for GitHub", "language": "JavaScript", "homepage": "http://launchbar-github.com", "owner": { "login": "bswinnerton", "id": 934497, "url": "https://api.github.com/users/bswinnerton", ... }, "url": "https://api.github.com/repos/bswinnerton/launchbar-github", "issues_url": "https://api.github.com/repos/bswinnerton/launchbar-github/ issues{/number}" }, ... ]
  9. https://api.github.com/repos/bswinnerton/launchbar-github/issues GET [ { "id": 246489445, "number": 83, "title": "Error

    when viewing Gists of another user", "state": "open", "body": "I can't reproduce this in every case...", "user": { "login": "bswinnerton", "id": 934497, "url": "https://api.github.com/users/bswinnerton", ... }, "url": "https://api.github.com/repos/bswinnerton/launchbar-github/issues/ 83", "repository_url": "https://api.github.com/repos/bswinnerton/launchbar- github", ... }, ... ]
  10. { viewer { name email } } { "data": {

    "viewer": { "name": "Brooks Swinnerton", "email": "[email protected]" } } }
  11. https://api.github.com/graphql POST { user(login:"defunkt") { name bio } } {

    "data": { "user": { "name": "Chris Wanstrath", "bio": """ } } }
  12. { viewer { name email } } type RootQuery {

    viewer: User } type User { name: String email: String }
  13. { viewer { name email } } type RootQuery {

    viewer: User } type User { name: String email: String }
  14. { viewer { name email } } type RootQuery {

    viewer: User } type User { name: String email: String }
  15. type RootQuery { user(login: String): User } type User {

    name: String bio: String } { user(login:"defunkt") { name bio } }
  16. { user(login:"defunkt") { name bio } } type RootQuery {

    user(login: String): User } type User { name: String bio: String }
  17. type RootQuery { user(login: String): User } type User {

    name: String bio: String } { user(login:"defunkt") { name bio } }
  18. type RootQuery { user(login: String): User } type User {

    name: String bio: String } { user(login:"defunkt") { name bio } }
  19. { licenses { name nickname url } } type RootQuery

    { licenses: [License]! } type License { name: String! nickname: String url: URL! }
  20. { licenses { name nickname url } } type RootQuery

    { licenses: [License]! } type License { name: String! nickname: String url: URL! }
  21. { licenses { name nickname url } } type RootQuery

    { licenses: [License]! } type License { name: String! nickname: String url: URL! }
  22. { user(login: "defunkt") { name bio } user(login: "bswinnerton") {

    name bio } } { "data": { "user": { "name": "Chris Wanstrath", "bio": """ }, "user": { "name": "Brooks Swinnerton", "bio": "#$" } } }
  23. { user(login: "defunkt") { name bio } user(login: "bswinnerton") {

    name bio } } { "data": { "user": { "name": "Chris Wanstrath", "bio": """ }, "user": { "name": "Brooks Swinnerton", "bio": "#$" } } }
  24. { "data": { "chris": { "name": "Chris Wanstrath", "bio": """

    }, "brooks": { "name": "Brooks Swinnerton", "bio": "#$" } } }
  25. { "data": { "chris": { "name": "Chris Wanstrath", "bio": """

    }, "brooks": { "name": "Brooks Swinnerton", "bio": "#$" } } }
  26. { chris: user(login: "defunkt") { ...UserInfo } brooks: user(login: "bswinnerton")

    { ...UserInfo } } fragment UserInfo on User { name bio }
  27. { "data": { "user": { "name": "Chris Wanstrath", "bio": """

    } } } { "login": "defunkt" } query($login:String!) { user(login:$login) { name bio } }
  28. { viewer { repositories { totalCount } } } {

    "data": { "viewer": { "repositories": { "totalCount": 65 } } } }
  29. { viewer { repositories(first:2) { edges { node { name

    } } } } } { "data": { "viewer": { "repositories": { "edges": [ { "node": { "name": "nyc-restaurant-grades" } }, { "node": { "name": "launchbar-github" } } ] } } } }
  30. { viewer { repositories(first:2) { edges { cursor node {

    name } } } } } { "data": { "viewer": { "repositories": { "edges": [ { "cursor": "Y3Vyc29yOnYyOpHOA5rd9g==", "node": { "name": "nyc-restaurant-grades" } }, { "cursor": "Y3Vyc29yOnYyOpHOBOlMSg==", "node": { "name": "launchbar-github" } } ] } } } }
  31. { viewer { repositories(first:2) { edges { cursor node {

    name } } } } } { "data": { "viewer": { "repositories": { "edges": [ { "cursor": "Y3Vyc29yOnYyOpHOA5rd9g==", "node": { "name": "nyc-restaurant-grades" } }, { "cursor": "Y3Vyc29yOnYyOpHOBOlMSg==", "node": { "name": "launchbar-github" } } ] } } } }
  32. { viewer { repositories(first:2) { edges { cursor node {

    name } } } } } { "data": { "viewer": { "repositories": { "edges": [ { "cursor": "Y3Vyc29yOnYyOpHOA5rd9g==", "node": { "name": "nyc-restaurant-grades" } }, { "cursor": "Y3Vyc29yOnYyOpHOBOlMSg==", "node": { "name": "launchbar-github" } } ] } } } }
  33. { "data": { "viewer": { "repositories": { "edges": [ {

    "cursor": "Y3Vyc29yOnYyOpHOAIibww==", "node": { "name": "bswinnerton.github.io" } }, { "cursor": "Y3Vyc29yOnYyOpHOArDTpw==", "node": { "name": "dotfiles" } } ] } } } }
  34. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4
  35. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4
  36. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4
  37. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4
  38. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4
  39. March 20, 2016: Proposal submitted April 6, 2016: Proof of

    concept April 12, 2016: New team created September 4th, 2016: Early access May 22, 2017: API v4 Today: 200 million queries/day
  40. { viewer { repositories(last:100) { edges { node { name

    issues(last:50) { edges { node { title } } } } } } } rateLimit(dryRun:true) { nodeCount } }
  41. { viewer { repositories(last:100) { edges { node { name

    issues(last:50) { edges { node { title } } } } } } } rateLimit(dryRun:true) { nodeCount } }
  42. { viewer { repositories(last:100) { edges { node { name

    issues(last:50) { edges { node { title } } } } } } } rateLimit(dryRun:true) { nodeCount } } { "data": { "rateLimit": { "nodeCount": 5100 } } }
  43. { viewer { repositories(last:100) { edges { node { name

    issues(last:50) { edges { node { title } } } } } } } rateLimit(dryRun:true) { cost } } { "data": { "rateLimit": { "cost": 1 } } }
  44. @result = GraphQL::Client.query(ProjectsQuery) <% @result.data.projects.each do |project| %> <h1><%= project.name

    %></h1> <% project.columns.each do |column| %> <p><%= column.name %></p> <p><%= column.cards.total_count %></p> <% column.cards.each do |card| %> <% card.title %> <p>Opened by <%= card.owner.login %></p> <% end %> <% end %> <% end %> Controller View