ドキュメントには頻繁に更新が加えられ、その都度公開されています。本ページの翻訳はまだ未完成な部分があることをご了承ください。最新の情報については、英語のドキュメンテーションをご参照ください。本ページの翻訳に問題がある場合はこちらまでご連絡ください。

このバージョンの GitHub Enterprise はこの日付をもって終了となりました: 2021-03-02. 重大なセキュリティの問題に対してであっても、パッチリリースは作成されません。 パフォーマンスの向上、セキュリティの改善、新機能のためには、最新バージョンのGitHub Enterpriseにアップグレードしてください。 アップグレードに関する支援については、GitHub Enterprise supportに連絡してください。

RESTからGraphQLへの移行

GitHubのREST APIからGitHubのGraphQL APIへの移行に関するベストプラクティスと考慮点について学んでください。

ここには以下の内容があります:

APIのロジックに関する差異

RESTからGraphQLへの移行は、APIロジックの大きな変化を示します。 スタイルとしてのRESTと仕様としてのGraphQLとの違いのために、REST APIの呼び出しをGraphQL APIのクエリに1対1で置き換えることは難しく、しばしば望ましくないことになります。 移行の具体的な例を以下に示しました。

コードを REST API から GraphQL API に移行するには、以下を行います。

GraphQLによる重要な利点には以下があります。

以下にそれぞれの例を示します。

例:必要なデータだけを取得

1つのREST API呼び出しで、Organizationのメンバーのリストを取得します。

curl -v http(s)://[hostname]/api/v3/orgs/:org/members

目的がメンバー名とアバターへのリンクの取得だけなのであれば、このRESTのペイロードには過剰なデータが含まれています。 しかし、GraphQLのクエリでは指定した内容だけが返されます。

query {
    organization(login:"github") {
    membersWithRole(first: 100) {
      edges {
        node {
          name
          avatarUrl
        }
      }
    }
  }
}

別の例を考えてみましょう。プルリクエストのリストを取得して、それぞれがマージ可能かをチェックします。 REST APIの呼び出しは、プルリクエストとそのサマリ表現のリストを取得します。

curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/pulls

プルリクエストがマージ可能かを判断するためには、個別にそれぞれのプルリクエストの詳細な表現(大きなペイロード)を取得し、そのmergeable属性がtrueかfalse下をチェックしなければなりません。

curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/pulls/:number

GraphQLでは、それぞれのプルリクエストについてnumbermergeable属性だけを取得できます。

query {
    repository(owner:"octocat", name:"Hello-World") {
    pullRequests(last: 10) {
      edges {
        node {
          number
          mergeable
        }
      }
    }
  }
}

例:入れ子

入れ子になったフィールドにクエリを行うことで、複数のRESTの呼び出しを少数のGraphQLクエリに置き換えられます。 たとえば、プルリクエストをコミット、非レビューコメント、レビューをREST APIを使って取得するには、4つの別々の呼び出しが必要になります。

curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/pulls/:number
curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/pulls/:number/commits
curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/issues/:number/comments
curl -v http(s)://[hostname]/api/v3/repos/:owner/:repo/pulls/:number/reviews

GraphQL APIを使えば、入れ子のフィールドを利用して単一のクエリでこのデータを取得できます。

{
  repository(owner: "octocat", name: "Hello-World") {
    pullRequest(number: 1) {
      commits(first: 10) {
        edges {
          node {
            commit {
              oid
              message
            }
          }
        }
      }
      comments(first: 10) {
        edges {
          node {
            body
            author {
              login
            }
          }
        }
      }
      reviews(first: 10) {
        edges {
          node {
            state
          }
        }
      }
    }
  }
}

プルリクエストの番号で変数を置き換えることで、このクエリの力を拡張することもできます。

例:強力な型付け

GraphQLスキーマは強く型付けされており、データの扱いが安全になっています。

IssueもしくはプルリクエストにGraphQLのミューテーションを使ってコメントを追加する例で、間違ってclientMutationIdの値に文字列ではなく整数値を指定してしまったとしましょう。

mutation {
  addComment(input:{clientMutationId: 1234, subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}

このクエリを実行すると、この操作に期待される型を指定したエラーが返されます。

{
  "data": null,
  "errors": [
    {
      "message": "Argument 'input' on Field 'addComment' has an invalid value. Expected type 'AddCommentInput!'.",
      "locations": [
        {
          "line": 3,
          "column": 3
        }
      ]
    },
    {
      "message": "Argument 'clientMutationId' on InputObject 'AddCommentInput' has an invalid value. Expected type 'String'.",
      "locations": [
        {
          "line": 3,
          "column": 20
        }
      ]
    }
  ]
}

1234をクオートでラップすれば、この値を整数値から期待されている型である文字列に変換できます。

mutation {
  addComment(input:{clientMutationId: "1234", subjectId: "MDA6SXNzdWUyMjcyMDA2MTT=", body: "Looks good to me!"}) {
    clientMutationId
    commentEdge {
      node {
        body
        repository {
          id
          name
          nameWithOwner
        }
        issue {
          number
        }
      }
    }
  }
}