-
Notifications
You must be signed in to change notification settings - Fork 39
/
github_issues.check
executable file
·145 lines (117 loc) · 3.2 KB
/
github_issues.check
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env ruby
require "rubygems"
require "time"
require "json"
require "open-uri"
require "net/https"
class GithubIssue
def initialize(hash)
@hash = hash
end
def pull_request?
@hash["pull_request"] && @hash["pull_request"]["html_url"]
end
def comments_count
@hash["comments"]
end
def updated_at
@updated_at ||=
Time.parse(@hash["updated_at"])
end
def formatted_updated_at
time_ago(updated_at)
end
def formatted_title
"#{formatted_updated_at} [#{comments_count}] #{"[PR]" if pull_request?}"
end
def formatted_description
@hash["title"].gsub(/[\r\n\t]/, " ")[0..100] + "..."
end
private
# https://gist.github.com/3808180
def time_ago(time)
case delta = (Time.now.to_i - time.to_i)
when 0..119 then "-1 min"
when 120..3599 then "-#{delta / 60} mins"
when 3600..86399 then "-#{(delta / 3600).round} hours"
else "-#{(delta / 86400).round} days"
end
end
end
class GithubIssuesStatus
def initialize(issues_url, json)
@issues_url = issues_url
@issues =
Array(JSON.parse(json)) \
.map { |e| GithubIssue.new(e) }
rescue JSON::ParserError
raise RuntimeError, "invalid json: '#{json}'"
end
def any_issues_with_0_comments?
@issues.any? { |i| i.comments_count.zero? }
end
def as_json(*)
{
:result => @issues.empty?,
:changing => any_issues_with_0_comments?,
:url => @issues_url,
:info => info
}
end
def to_json(*)
JSON.dump(as_json)
end
private
def info
@issues.inject([]) do |result, issue|
result.concat(issue_details(issue))
result
end[0..-2]
end
def issue_details(issue)
[ [issue.formatted_title, issue.formatted_description],
["-", ""] ]
end
end
class GithubIssues
def initialize(repo_owner, repo_name)
raise ArgumentError "repo_owner must not be nil" \
unless @repo_owner = repo_owner
raise ArgumentError "repo_name must not be nil" \
unless @repo_name = repo_name
end
def latest_status
GithubIssuesStatus.new(issues_url, force_utf8(http_get))
end
private
def http_get
# Github rate limits unauthenticated requests to the api by ip.
# To obtains client_id/client_secret just create new application on
# `https://github.com/settings/applications`.
if ENV.keys.grep(/GITHUB_ISSUES_CHECK/)
auth = "client_id=#{ENV["GITHUB_ISSUES_CHECK_CLIENT_ID"]}"
auth += "&client_secret=#{ENV["GITHUB_ISSUES_CHECK_CLIENT_SECRET"]}"
end
http_opts = {
"User-Agent" => "CheckmanGithubIssues (Hostname: #{`printf "%s" "$HOSTNAME"`})"
}
open("#{api_url}?#{auth}", http_opts).read
end
def api_url
"https://api.github.com/repos/#{@repo_owner}/#{@repo_name}/issues"
end
def issues_url
"https://github.com/#{@repo_owner}/#{@repo_name}/issues"
end
def force_utf8(string)
if string.respond_to?(:encode)
# Use 'binary' as source encoding since conversion
# to the same encoding is a no-op even if there are
# invalid bytes.
string.encode(string.encoding, "binary", :invalid => :replace, :undef => :replace)
else
string
end
end
end
puts GithubIssues.new(*ARGV).latest_status.to_json if __FILE__ == $0