-
Notifications
You must be signed in to change notification settings - Fork 3
/
repository.rb
120 lines (96 loc) · 2.94 KB
/
repository.rb
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
module EndOfLife
class Repository
class << self
include Dry::Monads[:result, :maybe]
def fetch(options)
github_client.bind do |github|
github.auto_paginate = true
options[:user] ||= github.user.login
query = search_query_for(options)
items = github.search_repositories(query, {sort: :updated}).items
Success(
items.filter_map do |repo|
next if repo.archived && options[:skip_archived]
Repository.new(
full_name: repo.full_name,
url: repo.html_url,
github_client: github
)
end
)
rescue => e
Failure("Unexpected error: #{e}")
end
end
def github_client
Maybe(ENV["GITHUB_TOKEN"])
.fmap { |token| Octokit::Client.new(access_token: token) }
.or { Failure("Please set GITHUB_TOKEN environment variable") }
end
def search_query_for(options)
query = "language:ruby"
query += if options[:repository]
" repo:#{options[:repository]}"
elsif options[:organizations]
options[:organizations].map { |org| " org:#{org}" }.join
else
" user:#{options[:user]}"
end
if options[:visibility]
query += " is:#{options[:visibility]}"
end
if options[:excludes]
words_to_exclude = options[:excludes].map { |word| "NOT #{word} " }.join
query += " #{words_to_exclude} in:name"
end
query
end
end
attr :full_name, :url
def initialize(full_name:, url:, github_client:)
@full_name = full_name
@url = url
@github_client = github_client
end
def eol_ruby?(at: Date.today)
ruby_version&.eol?(at: at)
end
def ruby_version
return @ruby_version if defined?(@ruby_version)
@ruby_version = ruby_versions.min
end
private
def ruby_versions
return @ruby_versions if defined?(@ruby_versions)
@ruby_versions = fetch_ruby_version_files.filter_map { |file|
parse_version_file(file)
}
end
POSSIBLE_RUBY_VERSION_FILES = [
".ruby-version",
"Gemfile.lock",
"Gemfile",
".tool-versions"
]
def fetch_ruby_version_files
Sync do
POSSIBLE_RUBY_VERSION_FILES
.map { |file_path| Async { fetch_file(file_path) } }
.filter_map(&:wait)
end
end
def fetch_file(file_path)
@github_client.contents(full_name, path: file_path)
rescue Octokit::NotFound
nil
end
def parse_version_file(file)
RubyVersion.from_file(file_name: file.name, content: decode_file(file))
end
def decode_file(file)
return file.content if file.encoding.nil?
return Base64.decode64(file.content) if file.encoding == "base64"
raise ArgumentError, "Unsupported encoding: #{file.encoding.inspect}"
end
end
end