gems_bond 1.0.4

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: bc62800e859ce8dcf0015580a685bfaf8b5410c69843acae6d49e24fae011c4e
4
+ data.tar.gz: 6ee8416eade996316171af619d7e7fd6f14d3c82817f299c92c793902b5b6076
5
+ SHA512:
6
+ metadata.gz: d82f72f550a6be300e0d5ca5483b10ef8a7070e10912c89e2900675bdafd712ba6c4014728a5641f7789666d84da8ec126ea2c2b4e0d8a155b7134f68261f952
7
+ data.tar.gz: ae59181cbfbf9cff164a4c7c5776ccea3ef5c14a773a18d8ae5706be553fc61eff0b9d2a64b54bd11adeb7da8516152cbca5a1cc78daa04f292fdf43391618bb
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GemsBond
4
+ # Manages gem configuration
5
+ class Configuration
6
+ attr_accessor :github_token
7
+
8
+ def initialize
9
+ @github_token = nil
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GemsBond
4
+ # Examines gem sanity
5
+ module ExaminationHelper
6
+ SCORES = YAML.safe_load(File.read(File.join(File.dirname(__FILE__), "scores.yml")))
7
+ BOUNDARIES = SCORES["boundaries"]
8
+ RESULTS = SCORES["results"]
9
+
10
+ def version_gap
11
+ memoize(:version_gap) { calculate_version_gap }
12
+ end
13
+
14
+ RESULTS.each do |result, values|
15
+ define_method("#{result}_score") do
16
+ memoize("#{result}_score") do
17
+ weighted_average(
18
+ values.map do |key, weighting|
19
+ [__send__("#{key}_score"), weighting]
20
+ end
21
+ )
22
+ end
23
+ end
24
+ end
25
+
26
+ private
27
+
28
+ # Scores getters and calculation
29
+
30
+ BOUNDARIES.each_key do |key|
31
+ # create a _score getter for each key
32
+ define_method("#{key}_score") do
33
+ instance_variable_get("@#{key}_score") if instance_variable_defined?("@#{key}_score")
34
+
35
+ instance_variable_set("@#{key}_score", __send__("calculate_#{key}_score"))
36
+ end
37
+
38
+ # create a calculation method for each key
39
+ define_method("calculate_#{key}_score") do
40
+ value = public_send(key)
41
+ return unless value
42
+
43
+ min = BOUNDARIES[key]["min"]
44
+ max = BOUNDARIES[key]["max"]
45
+
46
+ # when lower the better (last commit at...)
47
+ if min
48
+ threshold = Float(BOUNDARIES[key]["threshold"] || 0)
49
+ return Float(1) if value <= threshold
50
+ return Float(0) if value >= min
51
+
52
+ soften(min - Float(value) + threshold, min + threshold)
53
+
54
+ # when higher the better (downloads count...)
55
+ else
56
+ return Float(1) if value >= max
57
+ return Float(0) if value <= 1
58
+
59
+ soften(Float(value), max)
60
+ end
61
+ end
62
+ end
63
+
64
+ def soften(value, comparison)
65
+ # returns a shaped curve
66
+ sigmoid = ->(x) { 1 / (1 + Math.exp(-x * 10)) }
67
+ # simoid boundaries are [0.5, 1]
68
+ # so remove 0.5 and multiply by 2 to have boundaries [0, 1]
69
+ (sigmoid.call(value / comparison) - 0.5) * 2
70
+ end
71
+
72
+ # --- COMPUTE
73
+
74
+ def weighted_average(scores)
75
+ acc = 0
76
+ weight = 0
77
+ scores.each do |score|
78
+ value, weighting = score
79
+ next unless value
80
+
81
+ acc += value * weighting
82
+ weight += weighting
83
+ end.compact
84
+ return if weight.zero?
85
+
86
+ acc / weight
87
+ end
88
+
89
+ # --- VERSION STATUS
90
+
91
+ def calculate_version_gap
92
+ return unless version && versions
93
+
94
+ index = versions.index { |v| v[:number] == version }
95
+ return unless index
96
+
97
+ gap = versions[0..index].count { |v| !v[:prerelease] } - 1
98
+ gap.positive? ? gap : 0
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems_bond/fetcher/ruby_gems"
4
+ require "gems_bond/fetcher/github"
5
+
6
+ module GemsBond
7
+ # Handles gem data
8
+ module FetchHelper
9
+ RUBY_GEM_KEYS = %i[
10
+ last_version_date
11
+ downloads_count
12
+ source_code_uri
13
+ versions
14
+ last_version
15
+ last_version_date
16
+ days_since_last_version
17
+ ].freeze
18
+
19
+ GITHUB_KEYS = %i[
20
+ contributors_count
21
+ stars_count
22
+ forks_count
23
+ last_commit_date
24
+ open_issues_count
25
+ days_since_last_commit
26
+ ].freeze
27
+
28
+ KEYS = RUBY_GEM_KEYS + GITHUB_KEYS
29
+
30
+ RUBY_GEM_KEYS.each do |key|
31
+ define_method(key) do
32
+ memoize(key) do
33
+ fetch(ruby_gems_fetcher, key)
34
+ end
35
+ end
36
+ end
37
+
38
+ GITHUB_KEYS.each do |key|
39
+ define_method(key) do
40
+ memoize(key) do
41
+ fetch(github_fetcher, key)
42
+ end
43
+ end
44
+ end
45
+
46
+ def fetch_all(verbose: false)
47
+ KEYS.each do |key|
48
+ __send__(key)
49
+ end
50
+ verbose && puts(name)
51
+ end
52
+
53
+ private
54
+
55
+ def fetch(fetcher, key)
56
+ fetcher&.public_send(key)
57
+ end
58
+
59
+ def ruby_gems_fetcher
60
+ return @ruby_gems_fetcher if defined?(@ruby_gems_fetcher)
61
+
62
+ @ruby_gems_fetcher = GemsBond::Fetcher::RubyGems.new(name).start
63
+ end
64
+
65
+ def github_fetcher
66
+ return @github_fetcher if defined?(@github_fetcher)
67
+
68
+ @github_fetcher = github_url && GemsBond::Fetcher::Github.new(github_url).start
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,121 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "octokit"
4
+
5
+ module GemsBond
6
+ module Fetcher
7
+ # Fetches data from GitHub
8
+ class Github
9
+ REPOSITORY_REGEX = %r{https?://github.com/(?<repository>.*/.*)}.freeze
10
+
11
+ class << self
12
+ def valid_url?(url)
13
+ url&.match?(REPOSITORY_REGEX)
14
+ end
15
+ end
16
+
17
+ def initialize(url)
18
+ @url = url
19
+ end
20
+
21
+ def source
22
+ "github"
23
+ end
24
+
25
+ def start
26
+ parse_url
27
+ login
28
+ set_repository
29
+ self
30
+ rescue Octokit::Unauthorized, Octokit::InvalidRepository, Octokit::NotFound
31
+ nil
32
+ end
33
+
34
+ def forks_count
35
+ @repository["forks"]
36
+ end
37
+
38
+ def stars_count
39
+ @repository["watchers"]
40
+ end
41
+
42
+ def contributors_count
43
+ client = Octokit::Client.new(access_token: token, per_page: 1)
44
+ client.contributors(@repository_path)
45
+ response = client.last_response
46
+ links = response.headers[:link]
47
+ return 0 unless links
48
+
49
+ Integer(links.match(/.*page=(?<last>\d+)>; rel="last"/)[:last], 10)
50
+ end
51
+
52
+ def open_issues_count
53
+ @repository["open_issues"]
54
+ end
55
+
56
+ def last_commit_date
57
+ date = client.commits(@repository_path).first[:commit][:committer][:date]
58
+ return unless date
59
+
60
+ Date.parse(date.to_s)
61
+ end
62
+
63
+ def days_since_last_commit
64
+ return unless last_commit_date
65
+
66
+ Date.today - last_commit_date
67
+ end
68
+
69
+ def lib_size
70
+ contents_size = dir_size("lib")
71
+ return unless contents_size
72
+
73
+ lines_count_estimation = contents_size / 25
74
+ return lines_count_estimation if lines_count_estimation < 100
75
+
76
+ lines_count_estimation - lines_count_estimation % 100
77
+ end
78
+
79
+ private
80
+
81
+ def parse_url
82
+ matches = @url.match(REPOSITORY_REGEX)
83
+ raise Octokit::InvalidRepository unless matches
84
+
85
+ path = matches[:repository].split("/")
86
+ @repository_path = "#{path[0]}/#{path[1]}"
87
+ end
88
+
89
+ def login
90
+ @login ||= client.user.login
91
+ end
92
+
93
+ def client
94
+ Octokit::Client.new(access_token: token)
95
+ end
96
+
97
+ def token
98
+ GemsBond.configuration&.github_token
99
+ end
100
+
101
+ def set_repository
102
+ @repository = client.repo(@repository_path)
103
+ end
104
+
105
+ def dir_size(dir_path)
106
+ contents = client.contents(@repository_path, path: dir_path)
107
+ acc =
108
+ contents
109
+ .select { |content| content[:type] == "file" }
110
+ .sum { |content| content[:size] }
111
+ acc +=
112
+ contents
113
+ .select { |content| content[:type] == "dir" }
114
+ .sum { |sub_dir| dir_size("#{dir_path}/#{sub_dir[:name]}") }
115
+ acc
116
+ rescue Octokit::NotFound
117
+ nil
118
+ end
119
+ end
120
+ end
121
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems"
4
+ require "rubygems"
5
+
6
+ module GemsBond
7
+ module Fetcher
8
+ # Fetches data from RubyGems
9
+ class RubyGems
10
+ def initialize(name)
11
+ @name = name
12
+ end
13
+
14
+ def source
15
+ "ruby gems"
16
+ end
17
+
18
+ def start
19
+ @info = Gems.info(@name)
20
+ self
21
+ rescue Gems::NotFound
22
+ nil
23
+ end
24
+
25
+ def downloads_count
26
+ Gems.total_downloads(@name)[:total_downloads]
27
+ end
28
+
29
+ def source_code_uri
30
+ @info["metadata"]["source_code_uri"]
31
+ end
32
+
33
+ def versions
34
+ Gems.versions(@name).map do |version|
35
+ {
36
+ number: version["number"],
37
+ created_at: Date.parse(version["created_at"]),
38
+ prerelease: version["prerelease"]
39
+ }
40
+ end
41
+ end
42
+
43
+ def last_version
44
+ versions&.first&.dig(:number)
45
+ end
46
+
47
+ def last_version_date
48
+ versions&.first&.dig(:created_at)
49
+ end
50
+
51
+ def days_since_last_version
52
+ return unless last_version_date
53
+
54
+ Date.today - last_version_date
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems_bond/fetch_helper"
4
+ require "gems_bond/examination_helper"
5
+
6
+ module GemsBond
7
+ # Handles gem data
8
+ class Gem
9
+ include FetchHelper
10
+ include ExaminationHelper
11
+
12
+ def initialize(dependency)
13
+ @dependency = dependency
14
+ end
15
+
16
+ def name
17
+ memoize(__method__) { @dependency.name }
18
+ end
19
+
20
+ def description
21
+ memoize(__method__) { @dependency.description }
22
+ end
23
+
24
+ def version
25
+ memoize(__method__) { @dependency.to_spec.version.to_s }
26
+ end
27
+
28
+ def homepage
29
+ memoize(__method__) { @dependency.to_spec.homepage }
30
+ end
31
+
32
+ def url
33
+ homepage || source_code_uri
34
+ end
35
+
36
+ def github_url
37
+ return homepage if GemsBond::Fetcher::Github.valid_url?(homepage)
38
+
39
+ source_code_uri if GemsBond::Fetcher::Github.valid_url?(source_code_uri)
40
+ end
41
+
42
+ private
43
+
44
+ def memoize(key)
45
+ return instance_variable_get("@#{key}") if instance_variable_defined?("@#{key}")
46
+
47
+ instance_variable_set("@#{key}", yield)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "erb"
4
+ require "fileutils"
5
+
6
+ module GemsBond
7
+ # Prints gems table
8
+ class Printer
9
+ MISSING = "-"
10
+
11
+ def initialize(gems)
12
+ @gems = gems
13
+ end
14
+
15
+ def call
16
+ puts "\nPreparing data for printing results..."
17
+ create_directory
18
+ File.open("gems_bond/spy.html", "w") do |file|
19
+ file.puts content
20
+ end
21
+ puts "Open file gems_bond/spy.html to display the results."
22
+ end
23
+
24
+ private
25
+
26
+ def create_directory
27
+ return if File.directory?("gems_bond")
28
+
29
+ FileUtils.mkdir_p("gems_bond")
30
+ end
31
+
32
+ def template
33
+ File.read(File.join(File.dirname(__FILE__), "../../views/", "diagnosis.erb"))
34
+ end
35
+
36
+ def content
37
+ ERB.new(template).result(binding)
38
+ end
39
+
40
+ def sorted_gems
41
+ # sort with putting gems without average_score at the end
42
+ @gems.sort do |a, b|
43
+ if a.average_score && b.average_score
44
+ a.average_score <=> b.average_score
45
+ else
46
+ a.average_score ? -1 : 1
47
+ end
48
+ end
49
+ end
50
+
51
+ def version_color(gap)
52
+ return "secondary" if gap.nil?
53
+ return "success" if gap.zero?
54
+
55
+ gap < 3 ? "warning" : "danger"
56
+ end
57
+
58
+ def color(score)
59
+ return "secondary" if score.nil?
60
+
61
+ if score < 0.33
62
+ "danger"
63
+ elsif score < 0.66
64
+ "warning"
65
+ else
66
+ "success"
67
+ end
68
+ end
69
+
70
+ def human_date(date)
71
+ return MISSING if date.nil?
72
+
73
+ date.strftime("%F")
74
+ end
75
+
76
+ def human_number(number)
77
+ return MISSING if number.nil?
78
+
79
+ number.to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1 ")
80
+ end
81
+
82
+ def human_score(score)
83
+ return MISSING if score.nil?
84
+
85
+ (score * 100).round
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GemsBond
4
+ # Makes Rails aware of the tasks
5
+ class Railtie < Rails::Railtie
6
+ rake_tasks do
7
+ load "tasks/gems_bond/spy.rake"
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ boundaries:
3
+ days_since_last_version:
4
+ min: 730
5
+ threshold: 90
6
+ days_since_last_commit:
7
+ min: 365
8
+ threshold: 2
9
+ open_issues_count:
10
+ max: 300
11
+ downloads_count:
12
+ max: 200_000_000
13
+ contributors_count:
14
+ max: 350
15
+ forks_count:
16
+ max: 15_000
17
+ stars_count:
18
+ max: 30_000
19
+ results:
20
+ activity:
21
+ days_since_last_version: 3
22
+ days_since_last_commit: 5
23
+ contributors_count: 2
24
+ open_issues_count: 1
25
+ popularity:
26
+ downloads_count: 2
27
+ contributors_count: 3
28
+ forks_count: 1
29
+ stars_count: 1
30
+ average:
31
+ activity: 1
32
+ popularity: 2
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems_bond/gem"
4
+ require "gems_bond/printer"
5
+
6
+ module GemsBond
7
+ # Inspects gems and outputs the result
8
+ class Spy
9
+ RETRIES = 2
10
+
11
+ def call
12
+ chrono do
13
+ fetch_gems
14
+ GemsBond::Printer.new(gems).call
15
+ end
16
+ end
17
+
18
+ def gems_count
19
+ @gems_count ||= gems.count
20
+ end
21
+
22
+ private
23
+
24
+ def chrono
25
+ start_at = Time.now
26
+ yield
27
+ seconds = Time.now - start_at
28
+ time_per_gem_text = "#{(seconds / Float(gems_count)).round(2)} second(s) per gem"
29
+ puts "\nIt took #{seconds} second(s) to spy #{gems_count} gem(s) (#{time_per_gem_text})."
30
+ end
31
+
32
+ def gems
33
+ @gems ||=
34
+ Bundler.load.current_dependencies.map do |dependency|
35
+ GemsBond::Gem.new(dependency)
36
+ end
37
+ end
38
+
39
+ def fetch_gems
40
+ puts "Fetching data for..."
41
+ gems.each_slice(100) do |batch|
42
+ threads = []
43
+ batch.each do |gem|
44
+ threads << gem_thread(gem)
45
+ end
46
+ threads.each(&:join)
47
+ end
48
+ end
49
+
50
+ def gem_thread(gem)
51
+ Thread.new do
52
+ begin
53
+ retries ||= 0
54
+ gem.fetch_all(verbose: true)
55
+ # rescue SocketError, Faraday::ConnectionFailed...
56
+ rescue StandardError
57
+ (retries += 1) <= RETRIES ? retry : nil
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module GemsBond
4
+ VERSION = "1.0.4"
5
+ end
data/lib/gems_bond.rb ADDED
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems_bond/configuration"
4
+ require "gems_bond/railtie" if defined?(Rails)
5
+
6
+ # Gem module
7
+ module GemsBond
8
+ class Error < StandardError; end
9
+
10
+ class << self
11
+ attr_accessor :configuration
12
+
13
+ def configure
14
+ self.configuration ||= Configuration.new
15
+ yield(configuration)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "gems_bond/spy"
4
+
5
+ begin
6
+ require "#{Rails.root}/config/initializers/gems_bond" if defined?(Rails)
7
+ rescue LoadError
8
+ nil
9
+ end
10
+
11
+ namespace :gems_bond do
12
+ desc "Investigates gems"
13
+ task :spy do
14
+ puts "Welcome, my name is Bond, Gems Bond."\
15
+ " I will do some spying on your gems for you..."
16
+
17
+ GemsBond.configure do |config|
18
+ # set github_token from ENV if given
19
+ config.github_token = ENV["GITHUB_TOKEN"] if ENV["GITHUB_TOKEN"]
20
+ end
21
+
22
+ unless GemsBond.configuration.github_token
23
+ puts "It seems that you didn't provide any GitHub token."\
24
+ " This is necessary to fetch more data from GitHub,"\
25
+ " like the last commit date, the forks count, the sise of the repository..."
26
+
27
+ puts "Please provide a GitHub token by adding it in the configuration"\
28
+ " or passing GITHUB_TOKEN=<token> when running the task."
29
+ exit
30
+ end
31
+
32
+ GemsBond::Spy.new.call
33
+ end
34
+ end
@@ -0,0 +1,116 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Gems Bond Diagnosis</title>
6
+ <link
7
+ href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
8
+ rel="stylesheet"
9
+ integrity="sha384-giJF6kkoqNQ00vy+HMDP7azOuL0xtbfIcaT9wjKHr8RbDVddVHyTfAAsrekwKmP1"
10
+ crossorigin="anonymous"
11
+ >
12
+ <script
13
+ src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/js/bootstrap.bundle.min.js"
14
+ integrity="sha384-ygbV9kiqUc6oa4msXn9868pTtWMgiQaeYH7/t7LECLbyPA2x65Kgf80OJFdroafW"
15
+ crossorigin="anonymous"
16
+ ></script>
17
+ </head>
18
+ <body style="margin: 40px;">
19
+ <div class="container">
20
+ <div class="row justify-content-center">
21
+ <div class="list-group">
22
+ <table class="table table-hover small text-nowrap">
23
+ <thead>
24
+ <tr>
25
+ <th scope="col">#</th>
26
+ <th scope="col">Name</th>
27
+ <th scope="col">Version</th>
28
+ <th scope="col">Activity</th>
29
+ <th scope="col">Popularity</th>
30
+ <th scope="col">Diagnosis</th>
31
+ </tr>
32
+ </thead>
33
+ <tbody>
34
+ <% sorted_gems.each_with_index do |gem, i| %>
35
+ <tr>
36
+ <th scope="row"><%= i %></th>
37
+ <td>
38
+ <% if gem.url %>
39
+ <a href="<%= gem.url %>" target="_blank" class="text-decoration-none"><%= gem.name %></a>
40
+ <% else %>
41
+ <%= gem.name %>
42
+ <% end %>
43
+ </td>
44
+ <td class="text-wrap">
45
+ <div>
46
+ <p class="mb-1"><%= gem.version || "-" %></p>
47
+ <% if gem.version_gap&.zero? %>
48
+ <p class="badge bg-<%= version_color(gem.version_gap) %>">
49
+ up-to-date
50
+ </p>
51
+ <% elsif gem.version_gap %>
52
+ <p class="badge bg-<%= version_color(gem.version_gap) %>">
53
+ <%= gem.version_gap %> behind <%= gem.last_version %>
54
+ </p>
55
+ <% end %>
56
+ </div>
57
+ </td>
58
+ <td>
59
+ <div class="mb-1">
60
+ <p class="small m-0 fw-bold">Last version</p>
61
+ <p class="small m-0"><%= human_date(gem.last_version_date) %></p>
62
+ </div>
63
+ <div class="mb-1">
64
+ <p class="small m-0 fw-bold">Last commit</p>
65
+ <p class="small m-0"><%= human_date(gem.last_commit_date) %></p>
66
+ </div>
67
+ <div class="mb-1">
68
+ <p class="small m-0 fw-bold">Contributors</p>
69
+ <p class="small m-0"><%= human_number(gem.contributors_count) %></p>
70
+ </div>
71
+ </td>
72
+ <td>
73
+ <div class="mb-1">
74
+ <p class="small m-0 fw-bold">Downloads</p>
75
+ <p class="small m-0"><%= human_number(gem.downloads_count) %></p>
76
+ </div>
77
+ <div class="mb-1">
78
+ <p class="small m-0 fw-bold">Forks</p>
79
+ <p class="small m-0"><%= human_number(gem.forks_count) %></p>
80
+ </div>
81
+ <div class="mb-1">
82
+ <p class="small m-0 fw-bold">Stars</p>
83
+ <p class="small m-0"><%= gem.stars_count || "-" %></p>
84
+ </div>
85
+ </td>
86
+ <td>
87
+ <div class="row align-items-end">
88
+ <div class="col-6">
89
+ <div class="alert alert-<%= color(gem.average_score) %> text-wrap text-center" role="alert">
90
+ <p class="mb-0">SCORE</p>
91
+ <p class="mb-0" style="font-size: 40px; font-weight: 600"><%= human_score(gem.average_score) %></p>
92
+ </div>
93
+ </div>
94
+ <div class="col-3">
95
+ <div class="alert alert-<%= color(gem.activity_score) %> text-wrap text-center" role="alert">
96
+ <p class="mb-0">ACTIVITY</p>
97
+ <p class="mb-0" style="font-size: 30px;"><%= human_score(gem.activity_score) %></p>
98
+ </div>
99
+ </div>
100
+ <div class="col-3">
101
+ <div class="alert alert-<%= color(gem.popularity_score) %> text-wrap text-center" role="alert">
102
+ <p class="mb-0">POPULARITY</p>
103
+ <p class="font-weight-bold mb-0" style="font-size: 30px;"><%= human_score(gem.popularity_score) %></p>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </td>
108
+ </tr>
109
+ <% end %>
110
+ </tbody>
111
+ </table>
112
+ </div>
113
+ </div>
114
+ </div>
115
+ </body>
116
+ </html>
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: gems_bond
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Edouard Piron
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: gems
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: octokit
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '4.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '4.0'
41
+ description: Inspect gems relying on data from RubyGems and GitHub
42
+ email:
43
+ - edouard.piron@gmail.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/gems_bond.rb
49
+ - lib/gems_bond/configuration.rb
50
+ - lib/gems_bond/examination_helper.rb
51
+ - lib/gems_bond/fetch_helper.rb
52
+ - lib/gems_bond/fetcher/github.rb
53
+ - lib/gems_bond/fetcher/ruby_gems.rb
54
+ - lib/gems_bond/gem.rb
55
+ - lib/gems_bond/printer.rb
56
+ - lib/gems_bond/railtie.rb
57
+ - lib/gems_bond/scores.yml
58
+ - lib/gems_bond/spy.rb
59
+ - lib/gems_bond/version.rb
60
+ - lib/tasks/gems_bond/spy.rake
61
+ - views/diagnosis.erb
62
+ homepage: https://github.com/BigBigDoudou/gems_bond
63
+ licenses:
64
+ - MIT
65
+ metadata:
66
+ homepage_uri: https://github.com/BigBigDoudou/gems_bond
67
+ source_code_uri: https://github.com/BigBigDoudou/gems_bond
68
+ post_install_message:
69
+ rdoc_options: []
70
+ require_paths:
71
+ - lib
72
+ required_ruby_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '2.4'
77
+ required_rubygems_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ requirements: []
83
+ rubygems_version: 3.0.3
84
+ signing_key:
85
+ specification_version: 4
86
+ summary: Inspect gems
87
+ test_files: []