obituary 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/obituary/archive_checker.rb +56 -7
- data/lib/obituary/repository_finder.rb +18 -2
- data/lib/obituary/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: bdf0d0d04ff7d5747998cdf8e2cd5f09795dfc209cd3fb57695d29a5ebca266a
|
|
4
|
+
data.tar.gz: 400a554517085b8e4ab28e1e22d4d05197f0c72678af732a07f460d8b4ed4bed
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a6e96a0ee5518b3957e82d68293893161b828b68900cfb83433931ea2a1ef982dc96a5fdf70a4be711253bac9f276a3b6cad05878a9620f92e95a826ace35bff
|
|
7
|
+
data.tar.gz: fe2236c892f0ab526c6fc228b8a96ebdeb72f702c69f265b2c4ed069b95d6fb23902e765280092911da1cf0528b7861784586cc19944cf7e6f9f7e31942475cc
|
data/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Obituary
|
|
1
|
+
# Obituary [](https://badge.fury.io/rb/obituary) [](https://github.com/ydah/obituary/actions/workflows/main.yml)
|
|
2
2
|
|
|
3
3
|
Obituary detects archived GitHub repositories for your RubyGem dependencies. It can be used as a CLI command in CI or as an RSpec matcher to keep dependency health visible.
|
|
4
4
|
|
|
@@ -8,6 +8,7 @@ module Obituary
|
|
|
8
8
|
class ArchiveChecker
|
|
9
9
|
API_ENDPOINT = 'https://api.github.com/repos'
|
|
10
10
|
WARNING_THRESHOLD = 100
|
|
11
|
+
MAX_REDIRECTS = 5
|
|
11
12
|
|
|
12
13
|
def initialize(github_token:)
|
|
13
14
|
@github_token = github_token
|
|
@@ -15,19 +16,14 @@ module Obituary
|
|
|
15
16
|
|
|
16
17
|
def archived?(owner_repo)
|
|
17
18
|
url = URI.join("#{API_ENDPOINT}/", owner_repo)
|
|
18
|
-
|
|
19
|
-
request['Authorization'] = "Bearer #{@github_token}"
|
|
20
|
-
request['Accept'] = 'application/vnd.github.v3+json'
|
|
21
|
-
|
|
22
|
-
response = Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
|
|
23
|
-
http.request(request)
|
|
24
|
-
end
|
|
19
|
+
response, moved_to = fetch_response_following_redirects(url)
|
|
25
20
|
|
|
26
21
|
warn_if_rate_limit_low(response)
|
|
27
22
|
|
|
28
23
|
case response
|
|
29
24
|
when Net::HTTPSuccess
|
|
30
25
|
data = JSON.parse(response.body)
|
|
26
|
+
warn_if_repository_moved(owner_repo, data, moved_to)
|
|
31
27
|
data.fetch('archived', nil)
|
|
32
28
|
when Net::HTTPNotFound
|
|
33
29
|
warn("Repository not found for #{owner_repo}")
|
|
@@ -36,6 +32,13 @@ module Obituary
|
|
|
36
32
|
raise Obituary::Error, 'GitHub token unauthorized'
|
|
37
33
|
when Net::HTTPForbidden
|
|
38
34
|
raise Obituary::Error, 'GitHub API rate limit exceeded'
|
|
35
|
+
when Net::HTTPRedirection
|
|
36
|
+
if moved_to
|
|
37
|
+
warn("Repository moved for #{owner_repo} -> #{moved_to}")
|
|
38
|
+
else
|
|
39
|
+
warn("GitHub API error for #{owner_repo}: #{response.code}")
|
|
40
|
+
end
|
|
41
|
+
nil
|
|
39
42
|
else
|
|
40
43
|
warn("GitHub API error for #{owner_repo}: #{response.code}")
|
|
41
44
|
nil
|
|
@@ -47,6 +50,52 @@ module Obituary
|
|
|
47
50
|
|
|
48
51
|
private
|
|
49
52
|
|
|
53
|
+
def fetch_response_following_redirects(initial_url)
|
|
54
|
+
url = initial_url
|
|
55
|
+
moved_to = nil
|
|
56
|
+
response = nil
|
|
57
|
+
|
|
58
|
+
MAX_REDIRECTS.times do
|
|
59
|
+
response = request(url)
|
|
60
|
+
return [response, moved_to] unless response.is_a?(Net::HTTPRedirection)
|
|
61
|
+
|
|
62
|
+
location = response['Location']
|
|
63
|
+
return [response, moved_to] if location.nil? || location.empty?
|
|
64
|
+
|
|
65
|
+
moved_to ||= extract_owner_repo_from_location(location)
|
|
66
|
+
url = URI.join(url.to_s, location)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
[response, moved_to]
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def request(url)
|
|
73
|
+
request = Net::HTTP::Get.new(url)
|
|
74
|
+
request['Authorization'] = "Bearer #{@github_token}"
|
|
75
|
+
request['Accept'] = 'application/vnd.github.v3+json'
|
|
76
|
+
|
|
77
|
+
Net::HTTP.start(url.hostname, url.port, use_ssl: true) do |http|
|
|
78
|
+
http.request(request)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def warn_if_repository_moved(original_owner_repo, data, moved_to)
|
|
83
|
+
resolved_owner_repo = data['full_name'] || moved_to
|
|
84
|
+
return if resolved_owner_repo.nil? || resolved_owner_repo == original_owner_repo
|
|
85
|
+
|
|
86
|
+
warn("Repository moved for #{original_owner_repo} -> #{resolved_owner_repo}")
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def extract_owner_repo_from_location(location)
|
|
90
|
+
uri = URI.parse(location)
|
|
91
|
+
match = uri.path.match(%r{\A/repos/([^/]+)/([^/]+)\z})
|
|
92
|
+
return nil unless match
|
|
93
|
+
|
|
94
|
+
"#{match[1]}/#{match[2]}"
|
|
95
|
+
rescue URI::InvalidURIError
|
|
96
|
+
nil
|
|
97
|
+
end
|
|
98
|
+
|
|
50
99
|
def warn_if_rate_limit_low(response)
|
|
51
100
|
remaining = response['X-RateLimit-Remaining']
|
|
52
101
|
return unless remaining
|
|
@@ -8,6 +8,14 @@ module Obituary
|
|
|
8
8
|
class RepositoryFinder
|
|
9
9
|
RUBYGEMS_API = 'https://rubygems.org/api/v1/gems'
|
|
10
10
|
GITHUB_REGEX = %r{github\.com[/:]([^/]+)/([^/.]+)}
|
|
11
|
+
REPOSITORY_URL_KEYS = %w[
|
|
12
|
+
source_code_uri
|
|
13
|
+
homepage_uri
|
|
14
|
+
bug_tracker_uri
|
|
15
|
+
changelog_uri
|
|
16
|
+
documentation_uri
|
|
17
|
+
wiki_uri
|
|
18
|
+
].freeze
|
|
11
19
|
|
|
12
20
|
def initialize(config: Obituary.configuration)
|
|
13
21
|
@config = config
|
|
@@ -25,8 +33,7 @@ module Obituary
|
|
|
25
33
|
|
|
26
34
|
data = fetch_rubygems(gem_name)
|
|
27
35
|
if data
|
|
28
|
-
repo =
|
|
29
|
-
parse_github_repo(data['homepage_uri'])
|
|
36
|
+
repo = find_repo_from_rubygems_data(data)
|
|
30
37
|
return @cache[gem_name] = repo
|
|
31
38
|
end
|
|
32
39
|
|
|
@@ -68,6 +75,15 @@ module Obituary
|
|
|
68
75
|
nil
|
|
69
76
|
end
|
|
70
77
|
|
|
78
|
+
def find_repo_from_rubygems_data(data)
|
|
79
|
+
REPOSITORY_URL_KEYS.each do |key|
|
|
80
|
+
repo = parse_github_repo(data[key])
|
|
81
|
+
return repo if repo
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
nil
|
|
85
|
+
end
|
|
86
|
+
|
|
71
87
|
def parse_github_repo(url)
|
|
72
88
|
return nil if url.nil? || url.strip.empty?
|
|
73
89
|
|
data/lib/obituary/version.rb
CHANGED