Skip to content

Instantly share code, notes, and snippets.

@alzabo
Created August 7, 2018 14:33
Show Gist options
  • Save alzabo/499930d8fbde44fb61c1c7ff9483f511 to your computer and use it in GitHub Desktop.
Save alzabo/499930d8fbde44fb61c1c7ff9483f511 to your computer and use it in GitHub Desktop.
# frozen_string_literal: true
require 'octokit'
require 'faraday'
ORG_FILTER = ARGV[0] || /GSI.*/
HOOK_URL = ENV['JIRA_WEBHOOK_URL']
ACCESS_TOKEN = ENV['GITHUB_ACCESS_TOKEN']
TEAM_NAME = 'AUTO: Service Account Read Access'
TEAM_MEMBERS = ['github-ls-jira-svc'].freeze
TEAM_DESCRIPTION = <<~DESC
Provides read access to all org repos for service accounts.
Integrations include: the service account for the JIRA
to GHE integration.
Membership managed by automation. Unmanaged members will be
removed
DESC
if ACCESS_TOKEN.nil?
puts <<~ERRMSG.tr("\n", ' ')
Cannot authenticate to GitHub unless `GITHUB_ACCESS_TOKEN` environment
variable is set
ERRMSG
exit 1
end
# For whatever reason, API calls to ghe.eng.fireeye.com occasionally
# fail. The Faraday retry middleware should salve this. The following
# stolen from http://snags88.github.io/implementing-faraday-retry-in-rails
Octokit.configure do |c|
c.auto_paginate = true
c.middleware = Faraday::RackBuilder.new do |builder|
builder.use Faraday::Request::Retry
# add the default Octokit middlewares
builder.use Octokit::Middleware::FollowRedirects
builder.use Octokit::Response::RaiseError
builder.use Octokit::Response::FeedParser
builder.adapter Faraday.default_adapter
end
end
client = Octokit::Client.new(
auto_traversal: true,
access_token: ACCESS_TOKEN,
api_endpoint: 'https://ghe.eng.fireeye.com/api/v3/'
)
puts "Running #{$PROGRAM_NAME} with org filter: #{ORG_FILTER.inspect}"
orgs = client.all_orgs.select { |org| org.login.match(Regexp.new(ORG_FILTER)) }
orgs.each do |org|
org = client.org(org.login)
if !client.org_member?(org.login, client.user.login)
puts <<~NONMEMBER.tr("\n", ' ')
[#{org.login}] Skipping #{org.login}: API user #{client.user.login} is not a member
of this org. The API user must be an admin to configure orgs. Add the user at
#{org.html_url}/people/
NONMEMBER
next
elsif client.org_membership(org.login, user: client.user.login).role != 'admin'
puts <<~NONADMIN.tr("\n", ' ')
[#{org.login}] Skipping #{org.login}: API user #{client.user.login} is
not an admin of #{org.login}. Change roles at
#{org.html_url}/people/#{client.user.login}
NONADMIN
next
end
# Get the existing team by name or create it
team = client.org_teams(org.login).detect { |t| t.name == TEAM_NAME }
# If the team needs to be created, batch creation is faster than iterating
# through each repo (the only option when the team already exists)
team ||= begin
all_repos = client.org_repos(org.login).collect(&:full_name)
new_team = client.create_team(org.login,
name: TEAM_NAME,
description: TEAM_DESCRIPTION,
repo_names: all_repos)
puts <<~ADDTEAM.tr("\n", ' ')
[#{org.login}] Created team "#{org.login}/#{TEAM_NAME}" and
added #{all_repos.length} repos
ADDTEAM
new_team
end
# Add members, if they don't already exist
TEAM_MEMBERS.each do |member|
next if client.team_member?(team.id, member)
client.add_team_membership(team.id, member, role: 'member')
end
# Remove any members that aren't listed in `TEAM_MEMBERS`
current_members = client.team_members(team.id).collect(&:login)
(current_members - TEAM_MEMBERS).each do |member|
client.remove_team_membership(team.id, member)
puts "[#{org.login}] Removed #{member} from #{org.login}/#{TEAM_NAME}"
end
# Add repos
all_org_repos = client.org_repos(org.login).collect(&:full_name)
current_team_repos = client.team_repos(team.id).collect(&:full_name)
(all_org_repos - current_team_repos).each do |repo_name|
client.add_team_repository(team.id, repo_name, permission: 'pull')
puts "[#{org.login}] Added #{repo_name} to #{org.login}/#{TEAM_NAME}"
end
# Add the webhook URL, if provided and it isn't already configured
unless HOOK_URL.nil? || client.org_hooks(org.login)
.collect { |h| h.config.url }
.member?(HOOK_URL)
client.create_org_hook(org.login,
{ url: HOOK_URL, content_type: 'form' },
events: ['push'],
active: true)
end
puts "[#{org.login}] Finished configuring #{org.login}"
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment