Skip to content

Commit b3d8bee

Browse files
committed
refactor into a class
1 parent 058924e commit b3d8bee

File tree

1 file changed

+178
-145
lines changed

1 file changed

+178
-145
lines changed

api/ruby/find-inactive-members/find_inactive_members.rb

Lines changed: 178 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,182 @@
33
require 'optparse'
44
require 'optparse/date'
55

6-
SCOPES=["read:org", "read:user", "repo", "user:email"]
7-
8-
def env_help
9-
output=<<-EOM
10-
Required Environment variables:
11-
OCTOKIT_ACCESS_TOKEN: A valid personal access token with Organzation admin priviliges
12-
OCTOKIT_API_ENDPOINT: A valid GitHub/GitHub Enterprise API endpoint URL (Defaults to https://api.github.com)
13-
EOM
14-
output
6+
7+
class InactiveMemberSearch
8+
attr_accessor :organization, :members, :repositories, :date
9+
10+
SCOPES=["read:org", "read:user", "repo", "user:email"]
11+
12+
def initialize(options={})
13+
@client = options[:client]
14+
if options[:check]
15+
check_app
16+
check_scopes
17+
exit 0
18+
end
19+
20+
raise(OptionParser::MissingArgument) if (
21+
options[:organization].nil? or
22+
options[:date].nil?
23+
)
24+
25+
@date = options[:date]
26+
@organization = options[:organization]
27+
28+
organization_members
29+
organization_repositories
30+
member_activity
31+
end
32+
33+
def check_app
34+
info "Application client/secret? #{@client.application_authenticated?}\n"
35+
info "Authentication Token? #{@client.token_authenticated?}\n"
36+
end
37+
38+
def check_scopes
39+
info "Scopes: #{@client.scopes.join ','}\n"
40+
end
41+
42+
def env_help
43+
output=<<-EOM
44+
Required Environment variables:
45+
OCTOKIT_ACCESS_TOKEN: A valid personal access token with Organzation admin priviliges
46+
OCTOKIT_API_ENDPOINT: A valid GitHub/GitHub Enterprise API endpoint URL (Defaults to https://api.github.com)
47+
EOM
48+
output
49+
end
50+
51+
# helper to get an auth token for the OAuth application and a user
52+
def get_auth_token(login, password, otp)
53+
temp_client = Octokit::Client.new(login: login, password: password)
54+
res = temp_client.create_authorization(
55+
{
56+
:idempotent => true,
57+
:scopes => SCOPES,
58+
:headers => {'X-GitHub-OTP' => otp}
59+
})
60+
res[:token]
61+
end
62+
private
63+
def debug(message)
64+
$stderr.print message
65+
end
66+
67+
def info(message)
68+
$stdout.print message
69+
end
70+
71+
def organization_members
72+
# get all organization members and place into an array of hashes
73+
@members = @client.organization_members(@organization).collect do |m|
74+
email = @client.user(m[:login])[:email]
75+
{
76+
login: m["login"],
77+
email: email,
78+
active: false
79+
}
80+
end
81+
info "#{@members.length} members found.\n"
82+
end
83+
84+
def organization_repositories
85+
# get all repos in the organizaton and place into a hash
86+
@repositories = @client.organization_repositories(@organization).collect do |repo|
87+
repo["full_name"]
88+
end
89+
info "#{@repositories.length} repositories found.\n"
90+
end
91+
92+
# method to switch member status to active
93+
def make_active(login)
94+
hsh = @members.find { |member| member[:login] == login }
95+
hsh[:active] = true
96+
end
97+
98+
def commit_activity(repository)
99+
# get all commits after specified date and iterate
100+
info "...commits"
101+
begin
102+
@client.commits_since(repo, @date).each do |commit|
103+
# if commmitter is a member of the org and not active, make active
104+
if t = @members.find {|member| member[:login] == commit["author"]["login"] && member[:active] == false }
105+
make_active(t[:login])
106+
end
107+
end
108+
rescue
109+
info "...skipping blank repo"
110+
end
111+
end
112+
113+
def issue_activity(repo, date=@date)
114+
# get all issues after specified date and iterate
115+
info "...issues"
116+
@client.list_issues(repo, { :since => date }).each do |issue|
117+
# if creator is a member of the org and not active, make active
118+
if t = @members.find {|member| member[:login] == issue["user"]["login"] && member[:active] == false }
119+
make_active(t[:login])
120+
end
121+
end
122+
end
123+
124+
def issue_comment_activity(repo, date=@date)
125+
# get all issue comments after specified date and iterate
126+
info "...issue comments"
127+
@client.issues_comments(repo, { :since => date}).each do |comment|
128+
# if commenter is a member of the org and not active, make active
129+
if t = @members.find {|member| member[:login] == comment["user"]["login"] && member[:active] == false }
130+
make_active(t[:login])
131+
end
132+
end
133+
end
134+
135+
def pr_activity(repo, date=@date)
136+
# get all pull request comments comments after specified date and iterate
137+
info "...pr comments"
138+
@client.pull_requests_comments(repo, { :since => date}).each do |comment|
139+
# if commenter is a member of the org and not active, make active
140+
if t = @members.find {|member| member[:login] == comment["user"]["login"] && member[:active] == false }
141+
make_active(t[:login])
142+
end
143+
end
144+
end
145+
146+
def member_activity
147+
@repos_completed = 0
148+
# print update to terminal
149+
info "Analyzing activity for #{@members.length} members and #{@repositories.length} repos for #{@organization}\n"
150+
151+
# for each repo
152+
@repositories.each do |repo|
153+
info "rate limit remaining: #{@client.rate_limit.remaining} "
154+
info "analyzing #{repo}"
155+
156+
commit_activity(repo)
157+
issue_activity(repo)
158+
issue_comment_activity(repo)
159+
pr_activity(repo)
160+
161+
# print update to terminal
162+
@repos_completed += 1
163+
info "...#{@repos_completed}/#{@repositories.length} repos completed\n"
164+
end
165+
166+
# open a new csv for output
167+
CSV.open("inactive_users.csv", "wb") do |csv|
168+
# iterate and print inactive members
169+
@members.each do |member|
170+
if member[:active] == false
171+
member_detail = "#{member[:login]} <#{member[:email] unless member[:email].nil?}>"
172+
info "#{member_detail} is inactive\n"
173+
csv << [member_detail]
174+
if false # ARGV[2] == "purge"
175+
info "removing #{member[:login]}\n"
176+
@client.remove_organization_member(ORGANIZATION, member[:login])
177+
end
178+
end
179+
end
180+
end
181+
end
15182
end
16183

17184
options = {}
@@ -58,140 +225,6 @@ def env_help
58225
kit.middleware = stack if @debug
59226
end
60227

61-
@client = Octokit::Client.new
62-
63-
def debug(message)
64-
$stderr.print message
65-
end
66-
67-
def info(message)
68-
$stdout.print message
69-
end
70-
71-
def check_scopes
72-
info "Scopes: #{@client.scopes.join ','}\n"
73-
end
74-
75-
def check_app
76-
info "Application client/secret? #{Octokit.client.application_authenticated?}\n"
77-
info "Authentication Token? #{Octokit.client.token_authenticated?}\n"
78-
end
79-
80-
# helper to get an auth token for the OAuth application and a user
81-
def get_auth_token(login, password, otp)
82-
temp_client = Octokit::Client.new(login: login, password: password)
83-
res = temp_client.create_authorization(
84-
{
85-
:idempotent => true,
86-
:scopes => SCOPES,
87-
:headers => {'X-GitHub-OTP' => otp}
88-
})
89-
res[:token]
90-
end
91-
92-
if options[:check]
93-
check_app
94-
check_scopes
95-
exit 0
96-
end
97-
98-
raise(OptionParser::MissingArgument) if (
99-
options[:organization].nil? or
100-
options[:date].nil?
101-
)
102-
103-
# get all organization members and place into an array of hashes
104-
@members = @client.organization_members(options[:organization]).collect do |m|
105-
email = @client.user(m[:login])[:email]
106-
{
107-
login: m["login"],
108-
email: email,
109-
active: false
110-
}
111-
end
112-
113-
info "#{@members.length} members found.\n"
114-
115-
# get all repos in the organizaton and place into a hash
116-
repos = @client.organization_repositories(options[:organization]).collect do |repo|
117-
repo["full_name"]
118-
end
119-
120-
info "#{repos.length} repositories found.\n"
228+
options[:client] = Octokit::Client.new
121229

122-
# method to switch member status to active
123-
def make_active(login)
124-
hsh = @members.find { |member| member[:login] == login }
125-
hsh[:active] = true
126-
end
127-
128-
# print update to terminal
129-
info "Analyzing activity for #{@members.length} members and #{repos.length} repos for #{options[:organization]}\n"
130-
131-
@repos_completed = 0
132-
133-
# for each repo
134-
repos.each do |repo|
135-
info "rate limit remaining: #{@client.rate_limit.remaining} "
136-
info "analyzing #{repo}"
137-
138-
# get all commits after specified date and iterate
139-
info "...commits"
140-
begin
141-
@client.commits_since(repo, options[:date]).each do |commit|
142-
# if commmitter is a member of the org and not active, make active
143-
if t = @members.find {|member| member[:login] == commit["author"]["login"] && member[:active] == false }
144-
make_active(t[:login])
145-
end
146-
end
147-
rescue
148-
info "...skipping blank repo"
149-
end
150-
151-
# get all issues after specified date and iterate
152-
info "...issues"
153-
@client.list_issues(repo, { :since => options[:date] }).each do |issue|
154-
# if creator is a member of the org and not active, make active
155-
if t = @members.find {|member| member[:login] == issue["user"]["login"] && member[:active] == false }
156-
make_active(t[:login])
157-
end
158-
end
159-
160-
# get all issue comments after specified date and iterate
161-
info "...comments"
162-
@client.issues_comments(repo, { :since => options[:date]}).each do |comment|
163-
# if commenter is a member of the org and not active, make active
164-
if t = @members.find {|member| member[:login] == comment["user"]["login"] && member[:active] == false }
165-
make_active(t[:login])
166-
end
167-
end
168-
169-
# get all pull request comments comments after specified date and iterate
170-
info "...pr comments"
171-
@client.pull_requests_comments(repo, { :since => options[:date]}).each do |comment|
172-
# if commenter is a member of the org and not active, make active
173-
if t = @members.find {|member| member[:login] == comment["user"]["login"] && member[:active] == false }
174-
make_active(t[:login])
175-
end
176-
end
177-
178-
# print update to terminal
179-
@repos_completed += 1
180-
info "...#{@repos_completed}/#{repos.length} repos completed\n"
181-
end
182-
183-
# open a new csv for output
184-
CSV.open("inactive_users.csv", "wb") do |csv|
185-
# iterate and print inactive members
186-
@members.each do |member|
187-
if member[:active] == false
188-
member_detail = "#{member[:login]} <#{member[:email] unless member[:email].nil?}>"
189-
info "#{member_detail} is inactive\n"
190-
csv << [member_detail]
191-
if false # ARGV[2] == "purge"
192-
info "removing #{member[:login]}\n"
193-
@client.remove_organization_member(ORGANIZATION, member[:login])
194-
end
195-
end
196-
end
197-
end
230+
InactiveMemberSearch.new(options)

0 commit comments

Comments
 (0)