Skip to content

Instantly share code, notes, and snippets.

@mriddle
Last active October 12, 2022 20:05
Show Gist options
  • Save mriddle/623bc0114aaa719f7d15f6c9f110091f to your computer and use it in GitHub Desktop.
Save mriddle/623bc0114aaa719f7d15f6c9f110091f to your computer and use it in GitHub Desktop.
List of all unarchived repositories within organization using the GitHub GraphQL API. Requires a PAT (Personal Access Token) that has the necessary privileges
#!/usr/bin/env ruby
# List of all unarchived repositories within organization
# - group by year last updated
# - exclude those updated in the last 12 months
#
# Requires a GitHub Personal Access Token with the `repo` scope
# and it will need be authorized with with SSO where applicable.
#
# Pass token in via the GITHUB_ACCESS_TOKEN environment variable
#
# Usage: ./repository_archiving_report.rb
#
# Example output:
#
# 3 not updated since 2016
# - https://github.com/org_or_user_name/repo_name
# ...
#
# 7 not updated since 2018
# - https://github.com/org_or_user_name/repo_name
# ...
require 'bundler/inline'
gemfile do
source 'https://rubygems.org'
gem "graphql-client"
gem "pry-byebug"
end
require "graphql/client"
require "graphql/client/http"
#####################
# GraphQL connection
#####################
module GitHubGraphAPI
# Configure GraphQL endpoint using the basic HTTP network adapter.
HTTPAdapter = GraphQL::Client::HTTP.new("https://api.github.com/graphql") do
def headers(_)
token = ENV.fetch("GITHUB_ACCESS_TOKEN")
{ "Authorization" => "Bearer #{token}" }
end
end
# An offline copy of the schema allows queries to be typed checked statically
# before even sending a request.
unless File.exists? "db/schema.json"
# Schema = GraphQL::Client.load_schema(HTTP)
Dir.mkdir("db") unless Dir.exists?("db")
GraphQL::Client.dump_schema(HTTPAdapter, "db/schema.json")
end
Schema = GraphQL::Client.load_schema("db/schema.json")
Client = GraphQL::Client.new(schema: Schema, execute: HTTPAdapter)
end
################
# GraphQL query
################
RepositoriesQuery = GitHubGraphAPI::Client.parse <<-'GRAPHQL'
query($first:Int=null,$after:String=null) {
viewer {
repositories(first: $first, after: $after, affiliations: [ORGANIZATION_MEMBER], ownerAffiliations: [ORGANIZATION_MEMBER]) {
totalCount
edges {
node {
name
url
owner {
login
}
isArchived
isFork
isPrivate
createdAt
updatedAt
pushedAt
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
}
GRAPHQL
########################
# Retrieve repositories
########################
all_repositories = []
cursor = nil
has_next_page = true
current_count = 0
while has_next_page
result = GitHubGraphAPI::Client.query(RepositoriesQuery, variables: {
first: 100, # 100 is the maximum number of records you can retrieve at a time
after: cursor
}
)
repositories = result.data.viewer.repositories.edges.map(&:node)
all_repositories.concat(repositories)
has_next_page = result.data.viewer.repositories.page_info.has_next_page # set this to false if you want to play around without fetching the entire dataset
cursor = result.data.viewer.repositories.page_info.end_cursor
total_count = result.data.viewer.repositories.total_count
current_count += repositories.size
puts "Fetching data (#{current_count} / #{total_count}) from repositories [next:#{cursor}]"
end
#####################################################################
# Report on unarchived repositories not touched in the last 12 months
#####################################################################
def within_last_12_months?(date_string)
return false if date_string.nil?
DateTime.parse(date_string) >= DateTime.now.prev_year
end
puts "-" * 47
puts "List of all unarchived repositories"
puts " - grouped by year last updated"
puts " - excludes those updated in the last 12 months"
puts "-" * 47
binding.pry
list_by_year = all_repositories
.reject { |repo| repo.is_archived || within_last_12_months?(repo.pushed_at) }
# .reject { |repo| repo.is_fork } # Optionally filter on forks
# .reject { |repo| repo.is_private } # Optionally filter on private/public repositories
# .select { |repo| repo.owner.login == "org_name" } # Optionally filter on repositories under github.com/org_name (ORGANIZATION_MEMBER will include all repositories the org has access to)
.group_by { |repo| DateTime.parse(repo.pushed_at).year }
list_by_year.keys.sort.each do |year|
group = list_by_year[year]
puts "#{group.count} not updated since #{year}"
group.each { |repo| puts " - " + repo.url }
puts ""
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment