Skip to content

Instantly share code, notes, and snippets.

@jbarber
Last active December 2, 2020 16:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save jbarber/da838855099339bfc07116e49b78bfd9 to your computer and use it in GitHub Desktop.
Save jbarber/da838855099339bfc07116e49b78bfd9 to your computer and use it in GitHub Desktop.
Github GraphQL query for repos, their topics, and Gemfile
require 'httparty'
require 'json'
require 'byebug'
def get_data
query = File.open('repos.graphql', 'r').read
token = 'https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/'
cursor = nil
repos = []
org = 'evil_mega_corp'
loop do
response = HTTParty.post(
'https://api.github.com/graphql',
headers: {
'User-Agent' => 'https://gist.github.com/jbarber/da838855099339bfc07116e49b78bfd9',
'Authorization' => "bearer #{token}",
},
body: {
'query' => query,
'variables' => {
'org' => org,
'cursor' => cursor,
},
}.to_json,
timeout: 90,
)
unless response.success?
raise "Github returned #{response.code}: #{response.body}"
end
if response.parsed_response['errors']
raise "Github returned an error: #{response.parsed_response['errors']}"
end
root = response.parsed_response.dig('data', 'organization', 'repositories')
repos << root['nodes']
cursor = root.dig('pageInfo', 'endCursor')
break unless root.dig('pageInfo', 'hasNextPage')
end
return repos.flatten
end
def graphql2objects(repos)
repos.map do |repo|
{
name: repo['name'],
gemfile: repo.dig('object', 'text'),
archived: repo['isArchived'],
private: repo['isPrivate'],
topics: repo.dig('repositoryTopics', 'nodes').map(&:values).map(&:first).flat_map(&:values),
}
end
end
parsed_repos = graphql2objects(get_data)
puts parsed_repos.reject { |a| a[:topics].include?("dead") || a[:archived] }.to_json
query ($org: String!, $cursor: String) {
organization(login: $org) {
repositories(first: 100, after: $cursor) {
pageInfo {
endCursor
hasNextPage
}
nodes {
name
isArchived
isPrivate
repositoryTopics(first: 100) {
nodes {
topic {
name
}
}
}
object(expression: "master:Gemfile") {
... on Blob {
text
}
}
}
}
}
}
{
"org": "Evilcorp",
"cursor": "ASDASDASD=="
}
@jbarber
Copy link
Author

jbarber commented Apr 12, 2018

Give it a go at https://developer.github.com/v4/explorer/ - the org variable is compulsory, but you can remove cursor.

If you want to use it via HTTP from your favorite language, see https://developer.github.com/v4/guides/forming-calls/

@kruszczynski
Copy link

@jbarber it only uses first page of however many were fetched - I fixed it in this fork 🍴

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment