Skip to content

Instantly share code, notes, and snippets.

@keithpitt
Created May 10, 2017 23:49
Show Gist options
  • Select an option

  • Save keithpitt/6f13b3b2058c6ae62c7154308032fc90 to your computer and use it in GitHub Desktop.

Select an option

Save keithpitt/6f13b3b2058c6ae62c7154308032fc90 to your computer and use it in GitHub Desktop.

Revisions

  1. keithpitt created this gist May 10, 2017.
    86 changes: 86 additions & 0 deletions graphql-pagination-example.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,86 @@
    require 'uri'
    require 'net/http'
    require 'net/https'
    require 'json'

    GRAPHQL_API_KEY = ENV.fetch("GRAPHQL_API_KEY")

    def perform_graphql_query(query, variables)
    # This is our Buildkite GraphQL Endpoint.
    uri = URI.parse("https://graphql.buildkite.com/v1")

    # Create an instance of the HTTP class so we can make a HTTP request.
    https = Net::HTTP.new(uri.host, uri.port)
    https.use_ssl = true

    # Setup our actual request. Authentication is done via a Buildkite API key with
    # the GraphQL scope enabled.
    req = Net::HTTP::Post.new(uri.path, { 'Content-Type' => 'application/json', 'Authorization' => "Bearer #{GRAPHQL_API_KEY}" })
    req.body = JSON.generate(query: query, variables: variables)

    # Perform the request and return the response.
    https.request(req)
    end

    query = <<~GRAPHQL
    query GetPipelines($organizationSlug: ID!, $after: String, $pageSize: Int) {
    organization(slug: $organizationSlug) {
    pipelines(first: $pageSize, after: $after) {
    pageInfo {
    hasNextPage
    }
    edges {
    cursor
    node {
    name
    builds(first: 1, branch:"%default") {
    edges {
    node {
    state
    }
    }
    }
    }
    }
    }
    }
    }
    GRAPHQL

    # Get the organization slug from an environment variable
    org_slug = ENV.fetch("ORGANIZATION_SLUG")

    # Setup the first set of variables we'll send to GraphQL
    variables = { organizationSlug: org_slug, pageSize: 5 }

    # `has_next_page` will stay true as long as the `pageInfo.hasNextPage` variable is
    # true in the GraphQL response
    has_next_page = true

    while has_next_page
    response = perform_graphql_query(query, variables)

    # Make sure the GraphQL response is all good
    if response.code.to_i != 200
    raise "GraphQL query failed: #{response.code} #{response.message} #{response.body}"
    end

    # Parse the JSON from the GraphQL query
    json = JSON.parse(response.body)

    # Figure out if there's another page of info. If this is false, the
    # `has_next_page` will become false and the loop will stop
    has_next_page = json["data"]["organization"]["pipelines"]["pageInfo"]["hasNextPage"]

    # If there's still another page, grab the last cursor in the list, and add it
    # to the variables that we'll send in the next iteration
    if has_next_page
    variables[:after] = json["data"]["organization"]["pipelines"]["edges"].last["cursor"]
    end

    # Just show the output
    puts response.body
    puts "-------------------------"
    end

    puts "\nAll done! No more pipelines to paginate through!"