History

Create command to check for updates

Jasper van Merle committed 7 years ago

Commit d0300dd1 parent dae48e22 files · +107 −0Browse files

Showing the changes to lib (2 of 2 files). Show all

Unified · Split

2 files
  1. lib/docs/core/scraper.rb +29 −0
  2. lib/tasks/updates.thor +78 −0
lib/docs/core/scraper.rb+29−0
@@ -132,6 +132,35 @@ module Docs · 131 unmodified lines
132 end132 end
133 end133 end
134 134
135 def get_latest_version
136 raise NotImplementedError
137 end
138
139 # Returns whether or not this scraper is outdated.
140 #
141 # The default implementation assumes the documentation uses a semver(-like) approach when it comes to versions.
142 # Patch updates are ignored because there are usually little to no documentation changes in bug-fix-only releases.
143 #
144 # Scrapers of documentations that do not use this versioning approach should override this method.
145 #
146 # Examples of the default implementation:
147 # 1 -> 2 = outdated
148 # 1.1 -> 1.2 = outdated
149 # 1.1.1 -> 1.1.2 = not outdated
150 def is_outdated(current_version, latest_version)
151 current_parts = current_version.split(/\./).map(&:to_i)
152 latest_parts = latest_version.split(/\./).map(&:to_i)
153
154 # Only check the first two parts, the third part is for patch updates
155 [0, 1].each do |i|
156 break if i >= current_parts.length or i >= latest_parts.length
157 return true if latest_parts[i] > current_parts[i]
158 return false if latest_parts[i] < current_parts[i]
159 end
160
161 false
162 end
163
135 private164 private
136 165
137 def request_one(url)166 def request_one(url)
lib/tasks/updates.thor+78−0
@@ -0,0 +1,78 @@
1class UpdatesCLI < Thor
2 def self.to_s
3 'Updates'
4 end
5
6 def initialize(*args)
7 require 'docs'
8 require 'progress_bar'
9 super
10 end
11
12 desc 'check [doc]...', 'Check for outdated documentations'
13 def check(*names)
14 # Convert names to a list of Scraper instances
15 # Versions are omitted, if v10 is outdated than v8 is aswell
16 docs = names.map {|name| Docs.find(name.split(/@|~/)[0], false)}.uniq
17
18 # Check all documentations for updates when no arguments are given
19 docs = Docs.all if docs.empty?
20
21 progress_bar = ::ProgressBar.new docs.length
22 progress_bar.write
23
24 results = docs.map do |doc|
25 result = check_doc(doc)
26 progress_bar.increment!
27 result
28 end
29
30 outdated = results.select {|result| result.is_a?(Hash) && result[:is_outdated]}
31 return if outdated.empty?
32
33 logger.info("Outdated documentations (#{outdated.length}):")
34 outdated.each do |result|
35 logger.info("#{result[:name]}: #{result[:current_version]} -> #{result[:latest_version]}")
36 end
37 rescue Docs::DocNotFound => error
38 logger.error(error)
39 logger.info('Run "thor docs:list" to see the list of docs.')
40 end
41
42 private
43
44 def check_doc(doc)
45 # Scraper versions are always sorted from new to old
46 # Therefore, the first item's release value is the latest current scraper version
47 #
48 # For example, a scraper could scrape 3 versions: 10, 11 and 12
49 # doc.versions.first would be the scraper for version 12 if the scraper is written like all the other scrapers are
50 instance = doc.versions.first.new
51
52 current_version = instance.options[:release]
53 return nil if current_version.nil?
54
55 latest_version = instance.get_latest_version
56 return nil if latest_version.nil?
57
58 {
59 name: doc.name,
60 current_version: current_version,
61 latest_version: latest_version,
62 is_outdated: instance.is_outdated(current_version, latest_version)
63 }
64 rescue NotImplementedError
65 logger.warn("Can't check #{doc.name}, get_latest_version is not implemented")
66 rescue => error
67 logger.error("Error while checking #{doc.name}: #{error}")
68 end
69
70 def logger
71 @logger ||= Logger.new($stdout).tap do |logger|
72 logger.formatter = proc do |severity, datetime, progname, msg|
73 prefix = severity != "INFO" ? "[#{severity}] " : ""
74 "#{prefix}#{msg}\n"
75 end
76 end
77 end
78end