Permalink
Switch branches/tags
Nothing to show
Find file Copy path
710fe88 Oct 1, 2018
1 contributor

Users who have contributed to this file

executable file 167 lines (149 sloc) 4.61 KB
#!/usr/bin/env ruby
# frozen_string_literal: true
require "fileutils"
require "graphql/client"
require "graphql/client/http"
require_relative "./utils"
CACHE_DIR = ".cache"
SCHEMA_PATH = File.join(CACHE_DIR, "github-schema.json")
REPO_JSON_PATH = "_data/repos.json"
JEKYLL_CONFIG = load_yaml("_config.yml")
CONFIG = JEKYLL_CONFIG["github_repos_metadata"] || {}
CONFIG.update load_yaml(CONFIG["inherit_from"]) if CONFIG["inherit_from"]
REPO_OVERRIDES = CONFIG["repos"] || {}
HTTP = GraphQL::Client::HTTP.new("https://api.github.com/graphql") do
def headers(_context)
if (token = ENV["JEKYLL_GITHUB_TOKEN"])
{ Authorization: "Bearer #{token}" }
else
STDERR.puts <<~MSG
Missing GitHub access token. Rate-limiting may cause errors.
To fix this, set JEKYLL_GITHUB_TOKEN to an access token created at
https://help.github.com/articles/creating-a-personal-access-token-for-the-command-line/
MSG
{}
end
end
end
unless File.exist?(SCHEMA_PATH)
FileUtils.mkdir_p File.dirname(SCHEMA_PATH)
puts "Saving #{SCHEMA_PATH}"
GraphQL::Client.dump_schema(HTTP, SCHEMA_PATH)
end
Client = GraphQL::Client.new(schema: SCHEMA_PATH, execute: HTTP)
IndexQuery = Client.parse <<-'GRAPHQL'
query($count: Int, $cursor: String) {
viewer {
login
repositories(first: $count, after: $cursor) {
pageInfo {
hasNextPage
endCursor
}
edges {
node {
name
nameWithOwner
owner {
login
}
createdAt
pushedAt
description
url
homepageUrl
isArchived
isFork
isPrivate
primaryLanguage {
name
}
languages(first: 100) {
edges {
node {
name
}
}
}
repositoryTopics(first:10) {
edges {
node {
topic {
name
}
}
}
}
}
}
}
}
}
GRAPHQL
# collect repos into `repos`
repos = []
repo_count = 0
cursor = nil
viewer = nil
loop do
result = Client.query(IndexQuery, variables: { count: 100, cursor: cursor })
viewer = result.data.viewer
repo_count += viewer.repositories.edges.length
repos +=
viewer
.repositories.edges
.map(&:node)
page_info = viewer.repositories.page_info
break unless page_info.has_next_page
cursor = page_info.end_cursor
end
# Filter according to config
# rubocop:disable Metrics/CyclomaticComplexity
# rubocop:disable Metrics/PerceivedComplexity
# rubocop:disable Layout/EmptyLineAfterGuardClause
def include_repo?(repo, includes, excludes, viewer)
return true if includes.any? { |s| File.fnmatch(s, repo.name_with_owner) }
return false if excludes.any? { |s| File.fnmatch(s, repo.name_with_owner) }
return false if repo.is_fork && !CONFIG["include_forks"]
return false if repo.is_private && !CONFIG["include_private"]
return false if repo.owner.login != viewer.login
return true
end
# rubocop:enable Metrics/CyclomaticComplexity
# rubocop:enable Metrics/PerceivedComplexity
# rubocop:enable Layout/EmptyLineAfterGuardClause
includes = (CONFIG["include"] || []).map { |s| s.include?("/") ? s : "*/#{s}" }
excludes = (CONFIG["exclude"] || []).map { |s| s.include?("/") ? s : "*/#{s}" }
repos = repos.select { |r| include_repo?(r, includes, excludes, viewer) }
# Convert to hashes
repo_hashes = repos.map do |repo|
h = repo.to_h.dup
h["languages"] = repo.languages.edges.map { |edge| edge.node.name }
h["primaryLanguage"] = repo.primary_language.name if repo.primary_language
h["topics"] = repo.repository_topics.edges.map { |edge| edge.node.topic.name }
h.delete "homepageUrl" if h["homepageUrl"]&.empty?
h.delete "isFork"
h.delete "isPrivate"
h.delete "repositoryTopics"
h["owner"] = h["owner"].dup
h["owner"].delete "__typename"
h
end
# Apply overrides
repo_hashes.each do |repo|
nwo = repo["nameWithOwner"]
REPO_OVERRIDES.each do |pattern, fields|
next unless File.fnmatch(pattern, nwo)
repo["topics"] = [fields["topics"]].flatten if fields&.key? "topics"
end
end
repo_description = ([
CONFIG["include_private"] && "public",
CONFIG["include_forks"] && "source",
repo_hashes.length == 1 ? "repo" : "repos"
] - [nil, false]).join(" ")
puts "Writing #{repo_hashes.length} #{repo_description} out of #{repo_count}"
FileUtils.mkdir_p File.dirname(REPO_JSON_PATH)
File.open(REPO_JSON_PATH, "w") do |f|
f << JSON.generate(repo_hashes, **JSON_OPTIONS)
end