lapidarist 0.0.1 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52a3f4f375bdf8923d629d74fbe00ebfb7e7dd84738ff6c8e3977d1be2dbcba0
4
- data.tar.gz: f6b6ff542df51de84e710725b8a8d9bc53b9e39d529fb1c4e61cbf6eb4d1c40f
3
+ metadata.gz: b8c8ab46b2d54a0e859b530fc4a412dc89f483eed5244a12c9dd00c0adb1c2c8
4
+ data.tar.gz: 326f99a9496187492dead76dcc989ff4236aa40361d72391ae94faf1ba82c106
5
5
  SHA512:
6
- metadata.gz: 3ba56292233a696e78c23d274d8ab85d8ec04c5345d2991e2cbbae7f6b52b3dd08090c90af08eed8f63916676061f87415271dfeb6b2e6da020985cf07890f49
7
- data.tar.gz: e09937e6620630a277868e27941fca69d893b3fb2513fa0ca24cbfdb06975c5ed238f33604297e6628d73edeaf3b185faed32ba83f55fef7043f0d255c2d25d3
6
+ metadata.gz: 0fb14d325fde03f4162d14b87e73c3cddc0793a9f861066a9e0ea7c4d59d753a2d400b5e57ace22878620b1581197f4904358d2c1670303f442da458afb2bae9
7
+ data.tar.gz: ca2dd4fe4a9e5ed49f6082abe51ec6f1e1ed54b3025b58a347fce6bacd9b3978d01a62f18bffddc4b90cc36ab74d2a042048cb37f3882b773a15b38df2f40509
@@ -0,0 +1,25 @@
1
+ version: 2
2
+ jobs:
3
+ build:
4
+ docker:
5
+ - image: circleci/ruby:2.5.1
6
+ steps:
7
+ - checkout
8
+ - run:
9
+ name: Which bundler?
10
+ command: bundle -v
11
+
12
+ - run:
13
+ name: Bundle Install
14
+ command: bundle check || bundle install
15
+
16
+ - run:
17
+ name: Run rspec
18
+ command: |
19
+ bundle exec rspec --format RspecJunitFormatter \
20
+ --out test_results/rspec.xml \
21
+ --format progress \
22
+ spec
23
+
24
+ - store_test_results:
25
+ path: test_results
data/.gitignore CHANGED
@@ -11,3 +11,4 @@
11
11
  .rspec_status
12
12
 
13
13
  Gemfile.lock
14
+ *.gem
@@ -0,0 +1,37 @@
1
+ # Change log
2
+
3
+ ## master (unreleased)
4
+
5
+ ### New features
6
+
7
+ ## 0.1.0 (2018-08-07)
8
+
9
+ ### New features
10
+
11
+ * by default, outdated gems are updated in random order.
12
+ * allow random seed to be provided.
13
+ * use CircleCi to run specs.
14
+ * allow groups to have different semver level restrictions.
15
+ * add ability to promote gems in the order of being updated
16
+ * add ability to demote gems in the order of being updated
17
+ * add ability to only update specific gems
18
+ * add ability to update everything but specific excluded gems
19
+
20
+ ## 0.0.1 (2018-08-01)
21
+
22
+ ### New features
23
+
24
+ * update each outdated gem listed in the Gemfile as a separate git commit.
25
+ * allow all gems to be updated, not just those listed in the Gemfile.
26
+ * allow git commit command to have additional flags.
27
+ * add quiet mode for logging.
28
+ * limit the number of gems to be updated.
29
+ * do not attempt to update gems if there are uncommitted git changes.
30
+ * display summary after all attempts have finished.
31
+ * allow the restriction of updates to specific groups.
32
+ * restrict updates to a threshold semver level.
33
+ * recursively update a gem using each applicable semver level.
34
+
35
+ ### Bug fixes
36
+
37
+ * go to next update attempt when nothing was updated.
data/Gemfile CHANGED
@@ -4,3 +4,11 @@ git_source(:github) { |repo_name| "https://github.com/#{repo_name}" }
4
4
 
5
5
  # Specify your gem's dependencies in lapidarist.gemspec
6
6
  gemspec
7
+
8
+ group :development do
9
+ gem 'bump'
10
+ end
11
+
12
+ group :test do
13
+ gem 'rspec_junit_formatter'
14
+ end
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
1
  # Lapidarist
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/lapidarist`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ [![CircleCI](https://circleci.com/gh/attack/lapidarist.svg?style=svg)](https://circleci.com/gh/attack/lapidarist)
4
4
 
5
- TODO: Delete this and the text above, and describe your gem
5
+ Take the manual work out of updaeting your ruby gems, and let Lapidarist do the work.
6
+
7
+ You can run it from the command line yourself to update the gems of your project, or
8
+ automate it to run and update for you.
6
9
 
7
10
  ## Installation
8
11
 
@@ -20,9 +23,18 @@ Or install it yourself as:
20
23
 
21
24
  $ gem install lapidarist
22
25
 
26
+ Lapidarist depends on `bundler` and `git`.
27
+
23
28
  ## Usage
24
29
 
25
- TODO: Write usage instructions here
30
+ ```sh
31
+ lapidarist -d . -t 'rspec spec' --all
32
+ ```
33
+
34
+ To see all the options available
35
+ ```sh
36
+ lapidarist -h
37
+ ```
26
38
 
27
39
  ## Development
28
40
 
@@ -2,8 +2,11 @@ require 'lapidarist/version'
2
2
  require 'open3'
3
3
 
4
4
  require_relative 'lapidarist/configuration'
5
+ require_relative 'lapidarist/group_constraint'
6
+ require_relative 'lapidarist/level_constraint'
5
7
  require_relative 'lapidarist/options'
6
8
  require_relative 'lapidarist/level'
9
+ require_relative 'lapidarist/version_change'
7
10
  require_relative 'lapidarist/gem'
8
11
  require_relative 'lapidarist/gems'
9
12
 
@@ -25,5 +28,9 @@ module Lapidarist
25
28
  def config
26
29
  @config ||= Lapidarist::Configuration.new
27
30
  end
31
+
32
+ def logger
33
+ @logger ||= Lapidarist::Logger.new.tap { |l| l.setup }
34
+ end
28
35
  end
29
36
  end
@@ -2,7 +2,6 @@ module Lapidarist
2
2
  class BundleCommand
3
3
  def initialize
4
4
  @shell = Shell.new
5
- @logger = Logger.new
6
5
  end
7
6
 
8
7
  def outdated
@@ -11,7 +10,7 @@ module Lapidarist
11
10
  Enumerator.new do |y|
12
11
  shell.run('bundle outdated --strict') do |std_out_err|
13
12
  while line = std_out_err.gets
14
- logger.std_out_err(line, 'bundle outdated')
13
+ Lapidarist.logger.std_out_err(line, 'bundle outdated')
15
14
  gem = parse_gem_from(line)
16
15
  y.yield(gem) if gem
17
16
  end
@@ -31,7 +30,7 @@ module Lapidarist
31
30
 
32
31
  private
33
32
 
34
- attr_reader :shell, :logger
33
+ attr_reader :shell
35
34
 
36
35
  def parse_gem_from(line)
37
36
  regex = / \* (.*) \(newest (\d[\d\.]*\d)[,\s] installed (\d[\d\.]*\d)[\),\s](.*groups \"(.*)\")?/.match line
@@ -7,19 +7,16 @@ module Lapidarist
7
7
  @outdated = Outdated.new
8
8
  @update = Update.new
9
9
  @sha = Sha.new
10
-
11
- @logger = Logger.new
12
- @logger.setup
13
10
  end
14
11
 
15
12
  def run
16
13
  Options.new(args).parse
17
- logger.header('Starting lapidarist')
18
- logger.debug("directory: #{Lapidarist.config.directory}", :options)
19
- logger.debug("test_script: #{Lapidarist.config.test_script}", :options)
14
+ Lapidarist.logger.header('Starting lapidarist')
15
+ Lapidarist.logger.debug("directory: #{Lapidarist.config.directory}", :options)
16
+ Lapidarist.logger.debug("test_script: #{Lapidarist.config.test_script}", :options)
20
17
 
21
18
  unless git.clean?
22
- logger.footer('stopping, there are uncommitted changes')
19
+ Lapidarist.logger.footer('stopping, there are uncommitted changes')
23
20
  return 1
24
21
  end
25
22
 
@@ -27,11 +24,13 @@ module Lapidarist
27
24
  gems = outdated.run
28
25
 
29
26
  status = nil
30
- 1.step do |attempt|
31
- logger.header("Attempt ##{attempt}")
27
+ attempt = 0
28
+ loop do
29
+ attempt += 1
30
+ Lapidarist.logger.header("Attempt ##{attempt}")
32
31
 
33
32
  if gems.outdated.none?
34
- logger.footer('stopping, there are no applicable outdated gems')
33
+ Lapidarist.logger.footer('stopping, there are no applicable outdated gems')
35
34
  status = Status.new(gems, attempt)
36
35
  break
37
36
  end
@@ -39,19 +38,19 @@ module Lapidarist
39
38
  updated_gems = update.run(gems, attempt)
40
39
 
41
40
  if sha.new_commit_count.zero?
42
- logger.footer('nothing updated, trying again')
41
+ Lapidarist.logger.footer('nothing updated, trying again')
43
42
  gems = gems.merge(updated_gems)
44
43
  next
45
44
  end
46
45
 
47
- logger.header("Testing gem updates")
46
+ Lapidarist.logger.header("Testing gem updates")
48
47
  if test.success?
49
- logger.footer('test passed, nothing left to do')
48
+ Lapidarist.logger.footer('test passed, nothing left to do')
50
49
  gems = gems.merge(updated_gems)
51
50
  status = Status.new(gems, attempt)
52
51
  break
53
52
  else
54
- logger.footer('test failed, investigating failure')
53
+ Lapidarist.logger.footer('test failed, investigating failure')
55
54
  end
56
55
 
57
56
  failed_gem =
@@ -63,8 +62,7 @@ module Lapidarist
63
62
  updated_but_failed_gem,
64
63
  attempt: attempt,
65
64
  status: :failed,
66
- updated_version: updated_but_failed_gem.latest_attempt[:version],
67
- level: updated_but_failed_gem.latest_attempt[:level]
65
+ updated_version: updated_but_failed_gem.latest_attempt.version
68
66
  )
69
67
  else
70
68
  failed_gem_name = git.bisect(sha.last_good, test)
@@ -76,19 +74,18 @@ module Lapidarist
76
74
  updated_but_failed_gem,
77
75
  attempt: attempt,
78
76
  status: :failed,
79
- updated_version: updated_but_failed_gem.latest_attempt[:version],
80
- level: updated_but_failed_gem.latest_attempt[:level]
77
+ updated_version: updated_but_failed_gem.latest_attempt.version
81
78
  )
82
79
  end
83
80
  gems = gems.merge(failed_gem)
84
81
  end
85
82
 
86
- Summary.new(gems, logger).display
83
+ Summary.new(gems).display
87
84
  return status.to_i
88
85
  end
89
86
 
90
87
  private
91
88
 
92
- attr_reader :args, :git, :test, :outdated, :update, :sha, :logger
89
+ attr_reader :args, :git, :test, :outdated, :update, :sha
93
90
  end
94
91
  end
@@ -15,7 +15,13 @@ module Lapidarist
15
15
  update_limit: nil,
16
16
  groups: [],
17
17
  version: MAJOR,
18
- recursive: false
18
+ recursive: false,
19
+ random: true,
20
+ seed: nil,
21
+ promoted: [],
22
+ demoted: [],
23
+ only: [],
24
+ except: []
19
25
  )
20
26
  end
21
27
  end
@@ -1,31 +1,53 @@
1
1
  module Lapidarist
2
+ class NullAttempt
3
+ def status; nil; end
4
+ def reason; nil; end
5
+ def version; nil; end
6
+ def updated?; false; end
7
+ end
8
+
9
+ class Attempt
10
+ attr_reader :status, :reason, :version
11
+
12
+ def initialize(status:, reason:, version:)
13
+ @status = status
14
+ @reason = reason
15
+ @version = version
16
+ end
17
+
18
+ def updated?
19
+ status == :updated
20
+ end
21
+ end
22
+
2
23
  class Gem
3
- attr_reader :name, :newest_version, :installed_version, :attempts
24
+ attr_reader :name, :position, :newest_version, :installed_version, :attempts
4
25
 
5
- def initialize(name:, newest_version:, installed_version:, groups: [], attempts: {})
26
+ def initialize(name:, position: nil, newest_version:, installed_version:, groups: [], attempts: {})
6
27
  @name = name
28
+ @position = position
7
29
  @newest_version = newest_version
8
30
  @installed_version = installed_version
9
31
  @groups = groups
10
32
  @attempts = attempts
11
33
  end
12
34
 
13
- def self.from(gem, attempt: 0, status: nil, reason: nil, updated_version: nil, level: nil)
35
+ def self.from(gem, position: nil, attempt: 0, status: nil, reason: nil, updated_version: nil)
14
36
  attempts = gem.attempts
15
37
 
16
38
  if status
17
39
  attempts = attempts.merge(
18
- attempt => {
40
+ attempt => Attempt.new(
19
41
  status: status,
20
42
  reason: reason,
21
- version: updated_version,
22
- level: level
23
- }
43
+ version: updated_version
44
+ )
24
45
  )
25
46
  end
26
47
 
27
48
  new(
28
49
  name: gem.name,
50
+ position: position || gem.position,
29
51
  newest_version: gem.newest_version,
30
52
  installed_version: gem.installed_version,
31
53
  groups: gem.groups,
@@ -50,11 +72,7 @@ module Lapidarist
50
72
  end
51
73
 
52
74
  def current_status
53
- latest_attempt&.fetch(:status, nil)
54
- end
55
-
56
- def current_level
57
- latest_attempt&.fetch(:level, nil)
75
+ latest_attempt&.status
58
76
  end
59
77
 
60
78
  def outdated?(recursive: false)
@@ -74,7 +92,7 @@ module Lapidarist
74
92
  end
75
93
 
76
94
  def updated_version
77
- updated_attempt&.fetch(:version, nil)
95
+ updated_attempt&.version
78
96
  end
79
97
 
80
98
  def what_changed
@@ -86,15 +104,11 @@ module Lapidarist
86
104
  end
87
105
 
88
106
  def available_update_levels?
89
- failed? && current_level > PATCH
107
+ failed? && !version_change.next_level.nil?
90
108
  end
91
109
 
92
110
  def next_semver_level
93
- if current_level
94
- LEVELS.detect { |level| level < current_level }
95
- else
96
- MAJOR
97
- end
111
+ version_change.next_level
98
112
  end
99
113
 
100
114
  def log_s
@@ -106,32 +120,30 @@ module Lapidarist
106
120
  ].join(', ')
107
121
  end
108
122
 
109
- def to_h
110
- {
111
- name: name,
112
- newest_version: newest_version,
113
- installed_version: installed_version,
114
- groups: groups,
115
- attempts: attempts.to_h
116
- }
117
- end
118
-
119
123
  def latest_attempt_number
120
124
  @latest_attempt_number ||= attempts.keys.last
121
125
  end
122
126
 
123
127
  def latest_attempt
124
- @latest_attempt ||= attempts[latest_attempt_number] || {}
128
+ @latest_attempt ||= attempts[latest_attempt_number] || NullAttempt.new
125
129
  end
126
130
 
127
131
  private
128
132
 
129
133
  def version_changed?
134
+ # use VersionChange
130
135
  updated_version && installed_version != updated_version
131
136
  end
132
137
 
133
138
  def updated_attempt
134
- @updated_attempt ||= attempts.values.detect { |a| a[:status] == :updated }
139
+ @updated_attempt ||= attempts.values.detect(&:updated?)
140
+ end
141
+
142
+ def version_change
143
+ @version_change ||= Lapidarist::VersionChange.new(
144
+ installed: installed_version,
145
+ updated: latest_attempt&.version
146
+ )
135
147
  end
136
148
  end
137
149
  end
@@ -7,7 +7,7 @@ module Lapidarist
7
7
  end
8
8
 
9
9
  def each(&block)
10
- gems.sort_by(&:name).each(&block)
10
+ gems.sort_by(&:position).each(&block)
11
11
  end
12
12
 
13
13
  def outdated
@@ -2,7 +2,6 @@ module Lapidarist
2
2
  class GitCommand
3
3
  def initialize
4
4
  @shell = Shell.new
5
- @logger = Logger.new
6
5
  end
7
6
 
8
7
  def head
@@ -18,7 +17,7 @@ module Lapidarist
18
17
  end
19
18
 
20
19
  def bisect(start_sha, test)
21
- logger.header('Starting bisect')
20
+ Lapidarist.logger.header('Starting bisect')
22
21
  bisect_start(start_sha)
23
22
  bisect_run(start_sha, test)
24
23
  end
@@ -32,7 +31,7 @@ module Lapidarist
32
31
  end
33
32
 
34
33
  def clean?
35
- shell.run('[ -z "$(git status --porcelain)" ]')[1] == 0
34
+ shell.run('[ -z "$(git status --porcelain=v1 -uno)" ]')[1] == 0
36
35
  end
37
36
 
38
37
  def count_commits(start_sha, end_sha)
@@ -41,7 +40,7 @@ module Lapidarist
41
40
 
42
41
  private
43
42
 
44
- attr_reader :shell, :logger
43
+ attr_reader :shell
45
44
 
46
45
  def bisect_start(sha)
47
46
  shell.run('git bisect start')
@@ -59,7 +58,7 @@ module Lapidarist
59
58
  if bisect_step.failure?
60
59
  failing_sha = bisect_step.failing_sha
61
60
  failing_gem_name = bisect_step.failing_gem(failing_sha)
62
- logger.info("... found failing gem update: #{failing_gem_name}")
61
+ Lapidarist.logger.info("... found failing gem update: #{failing_gem_name}")
63
62
  end
64
63
 
65
64
  if bisect_step.success?
@@ -69,10 +68,10 @@ module Lapidarist
69
68
  end
70
69
 
71
70
  unless failing_gem_name
72
- logger.info("... last commit was failing commit")
71
+ Lapidarist.logger.info("... last commit was failing commit")
73
72
  end
74
73
 
75
- logger.footer("bisect done")
74
+ Lapidarist.logger.footer("bisect done")
76
75
  end
77
76
 
78
77
  if failing_gem_name && Lapidarist.config.debug
@@ -0,0 +1,15 @@
1
+ module Lapidarist
2
+ class GroupConstraint
3
+ attr_reader :name
4
+
5
+ def initialize(input)
6
+ parts = input.split(':')
7
+ @name = parts[0]
8
+ @level = Lapidarist::Level.from(parts[1])
9
+ end
10
+
11
+ def level
12
+ @level || Lapidarist.config.version
13
+ end
14
+ end
15
+ end
@@ -2,13 +2,18 @@ module Lapidarist
2
2
  class Level
3
3
  include Comparable
4
4
 
5
- attr_reader :index
5
+ attr_reader :name, :index
6
6
 
7
7
  def initialize(name:, index:)
8
8
  @name = name
9
9
  @index = index
10
10
  end
11
11
 
12
+ def self.from(name)
13
+ return unless name
14
+ Lapidarist::LEVELS.detect { |l| l.name == name.to_sym }
15
+ end
16
+
12
17
  def to_s
13
18
  name.to_s
14
19
  end
@@ -18,10 +23,6 @@ module Lapidarist
18
23
  return 0 if index == other.index
19
24
  return -1 if index > other.index
20
25
  end
21
-
22
- private
23
-
24
- attr_reader :name
25
26
  end
26
27
 
27
28
  MAJOR = Level.new(name: :major, index: 1)
@@ -0,0 +1,29 @@
1
+ module Lapidarist
2
+ class LevelConstraint
3
+ def initialize(gem)
4
+ @gem = gem
5
+ end
6
+
7
+ def maximum
8
+ available_semver_levels.compact.min
9
+ end
10
+
11
+ private
12
+
13
+ attr_reader :gem
14
+
15
+ def available_semver_levels
16
+ available_semver_levels = [default_constraint]
17
+ available_semver_levels << gem.next_semver_level if Lapidarist.config.recursive
18
+ available_semver_levels
19
+ end
20
+
21
+ def default_constraint
22
+ if Lapidarist.config.groups.any?
23
+ Lapidarist.config.groups.select { |g| gem.groups.include?(g.name) }.min_by(&:level).level
24
+ else
25
+ Lapidarist.config.version
26
+ end
27
+ end
28
+ end
29
+ end
@@ -49,7 +49,7 @@ module Lapidarist
49
49
  end
50
50
 
51
51
  opts.on("-g GROUP_NAME", "--group GROUP_NAME", "Limit gems to be updated to a specified group(s).") do |g|
52
- Lapidarist.config.groups << g
52
+ Lapidarist.config.groups << Lapidarist::GroupConstraint.new(g)
53
53
  end
54
54
 
55
55
  opts.on("--major", "Limit updates to major, minor and patch versions (essentially everything).") do |p|
@@ -67,6 +67,30 @@ module Lapidarist
67
67
  opts.on("-r", "--recursive", "Try updating a the major version, minor version then patch version.") do |t|
68
68
  Lapidarist.config.recursive = true
69
69
  end
70
+
71
+ opts.on("-o", "--ordered", "Do not randomize outdated list and keep alphabetical ordering.") do |t|
72
+ Lapidarist.config.random = false
73
+ end
74
+
75
+ opts.on("--seed SEED", "When randomizing the outdated order, use the provided seed.") do |s|
76
+ Lapidarist.config.seed = s.to_i
77
+ end
78
+
79
+ opts.on("--promote GEMS", "Promoted gems are updated first, in order as they are promoted.") do |gem_names|
80
+ Lapidarist.config.promoted += gem_names.split(',').map(&:strip)
81
+ end
82
+
83
+ opts.on("--demote GEMS", "Demoted gems are updated last, in reverse order as they are demoted.") do |gem_names|
84
+ Lapidarist.config.demoted += gem_names.split(',').map(&:strip).reverse
85
+ end
86
+
87
+ opts.on("--only GEMS", "Only update gems that are included in this list.") do |gem_names|
88
+ Lapidarist.config.only += gem_names.split(',').map(&:strip)
89
+ end
90
+
91
+ opts.on("--except GEMS", "Only update gems that are not included in this list.") do |gem_names|
92
+ Lapidarist.config.except += gem_names.split(',').map(&:strip)
93
+ end
70
94
  end
71
95
 
72
96
  opt_parser.parse!(args)
@@ -2,34 +2,81 @@ module Lapidarist
2
2
  class Outdated
3
3
  def initialize
4
4
  @bundle = BundleCommand.new
5
- @logger = Logger.new
6
5
  end
7
6
 
8
7
  def run
9
- logger.header('Detecting outdated gems')
8
+ Lapidarist.logger.header('Detecting outdated gems')
10
9
 
11
- gems = bundle.outdated.each_with_object([]) do |gem, results|
10
+ gems = outdated_gems.each_with_object([]) do |gem, results|
12
11
  reason = reason_to_skip(gem)
13
12
  if reason.nil?
14
- logger.info(" + #{gem.log_s}")
15
- results.push Gem.from(gem)
13
+ Lapidarist.logger.info(" + #{gem.log_s}")
14
+ results.push Gem.from(gem, position: results.length)
16
15
  else
17
- logger.info(" - (#{reason}) #{gem.log_s}")
18
- results.push Gem.from(gem, status: :skipped, reason: reason)
16
+ Lapidarist.logger.info(" - (#{reason}) #{gem.log_s}")
17
+ results.push Gem.from(gem, position: results.length, status: :skipped, reason: reason)
19
18
  end
20
19
  end
21
20
 
21
+ Lapidarist.logger.debug(gems.map(&:name), :order)
22
+
22
23
  Gems.new(gems)
23
24
  end
24
25
 
25
26
  private
26
27
 
27
- attr_reader :bundle, :logger
28
+ attr_reader :bundle
29
+
30
+ def all_outdated_gems
31
+ @all_outdated_gems ||= bundle.outdated.to_a.
32
+ select { |gem| Lapidarist.config.only.empty? || Lapidarist.config.only.include?(gem.name) }.
33
+ reject { |gem| Lapidarist.config.except.any? && Lapidarist.config.except.include?(gem.name) }
34
+ end
35
+
36
+ def promoted_gems
37
+ (Lapidarist.config.promoted - Lapidarist.config.demoted).map do |gem_name|
38
+ all_outdated_gems.detect { |g| g.name == gem_name }
39
+ end
40
+ end
41
+
42
+ def demoted_gems
43
+ Lapidarist.config.demoted.map do |gem_name|
44
+ all_outdated_gems.detect { |g| g.name == gem_name }
45
+ end
46
+ end
47
+
48
+ def remaining_outdated_gems
49
+ all_outdated_gems.reject do |gem|
50
+ Lapidarist.config.promoted.include?(gem.name) ||
51
+ Lapidarist.config.demoted.include?(gem.name)
52
+ end
53
+ end
54
+
55
+ def outdated_gems
56
+ sorted_remaining_outdated_gems =
57
+ if Lapidarist.config.random
58
+ remaining_outdated_gems.shuffle(random: random)
59
+ else
60
+ remaining_outdated_gems
61
+ end
62
+
63
+ promoted_gems + sorted_remaining_outdated_gems + demoted_gems
64
+ end
65
+
66
+ def random
67
+ Random.new(seed)
68
+ end
69
+
70
+ def seed
71
+ seed = Lapidarist.config.seed || rand(100_000)
72
+ Lapidarist.logger.info("seed: #{seed}", 1)
73
+ seed
74
+ end
28
75
 
29
76
  def reason_to_skip(gem)
30
77
  if !Lapidarist.config.all && !gem.dependency?
31
78
  :sub_dependency
32
- elsif Lapidarist.config.groups.any? && (Lapidarist.config.groups & gem.groups).none?
79
+ elsif Lapidarist.config.groups.any? && (Lapidarist.config.groups.map(&:name) & gem.groups).none?
33
80
  :unmatched_group
34
81
  end
35
82
  end
@@ -3,12 +3,11 @@ module Lapidarist
3
3
  def initialize
4
4
  @good_shas = []
5
5
  @git = GitCommand.new
6
- @logger = Logger.new
7
6
  end
8
7
 
9
8
  def record_good
10
9
  good_sha = git.head
11
- logger.debug("good sha: #{good_sha}")
10
+ Lapidarist.logger.debug("good sha: #{good_sha}")
12
11
  @good_shas << good_sha
13
12
  end
14
13
 
@@ -22,6 +21,6 @@ module Lapidarist
22
21
 
23
22
  private
24
23
 
25
- attr_reader :good_shas, :git, :logger
24
+ attr_reader :good_shas, :git
26
25
  end
27
26
  end
@@ -1,9 +1,5 @@
1
1
  module Lapidarist
2
2
  class Shell
3
- def initialize
4
- @logger = Logger.new
5
- end
6
-
7
3
  def run(*commands, label: nil, &block)
8
4
  if commands.one?
9
5
  run_single_command(commands.first, label, &block)
@@ -14,10 +10,8 @@ module Lapidarist
14
10
 
15
11
  private
16
12
 
17
- attr_reader :logger
18
-
19
13
  def run_single_command(command, label)
20
- logger.info "COMMAND > `#{command}`", 1
14
+ Lapidarist.logger.info "COMMAND > `#{command}`", 1
21
15
 
22
16
  if block_given?
23
17
  Open3.popen2e(command, chdir: Lapidarist.config.directory) do |_std_in, std_out_err|
@@ -28,13 +22,13 @@ module Lapidarist
28
22
 
29
23
  status = Open3.popen2e(command, chdir: Lapidarist.config.directory) do |_std_in, std_out_err, wait_thr|
30
24
  while line = std_out_err.gets
31
- logger.std_out_err(line, label || command)
25
+ Lapidarist.logger.std_out_err(line, label || command)
32
26
  out_err << line
33
27
  end
34
28
  wait_thr.value
35
29
  end
36
30
 
37
- logger.info "STATUS > #{status}", 2
31
+ Lapidarist.logger.info "STATUS > #{status}", 2
38
32
 
39
33
  [out_err.join("\n"), status]
40
34
  end
@@ -1,24 +1,23 @@
1
1
  module Lapidarist
2
2
  class Summary
3
- def initialize(gems, logger)
3
+ def initialize(gems)
4
4
  @gems = gems
5
- @logger = logger
6
5
  end
7
6
 
8
7
  def display
9
- logger.summary ''
10
- logger.summary 'Summary'
11
- logger.summary '-'*50
12
- logger.summary "#{object_count(gems.updated, 'gem', 'gems')} updated, #{object_count(gems.failed, 'gem', 'gems')} failed and #{object_count(gems.skipped, 'gem', 'gems')} skipped in #{object_count(gems.attempts, 'attempt', 'attempts')}"
8
+ Lapidarist.logger.summary ''
9
+ Lapidarist.logger.summary 'Summary'
10
+ Lapidarist.logger.summary '-'*50
11
+ Lapidarist.logger.summary "#{object_count(gems.updated, 'gem', 'gems')} updated, #{object_count(gems.failed, 'gem', 'gems')} failed and #{object_count(gems.skipped, 'gem', 'gems')} skipped in #{object_count(gems.attempts, 'attempt', 'attempts')}"
13
12
  gems.each do |gem|
14
13
  gem.attempts.each do |i, data|
15
- case data[:status]
14
+ case data.status
16
15
  when :updated
17
- logger.summary " + updated #{gem.name} from #{gem.installed_version} to #{data[:version]}"
16
+ Lapidarist.logger.summary " + updated #{gem.name} from #{gem.installed_version} to #{data.version}"
18
17
  when :failed
19
- logger.summary " x failed #{gem.name} from #{gem.installed_version} to #{data[:version]}"
18
+ Lapidarist.logger.summary " x failed #{gem.name} from #{gem.installed_version} to #{data.version}"
20
19
  when :skipped
21
- logger.summary " - skipped #{gem.name} (#{data[:reason]})"
20
+ Lapidarist.logger.summary " - skipped #{gem.name} (#{data.reason})"
22
21
  end
23
22
  end
24
23
  end
@@ -26,7 +25,7 @@ module Lapidarist
26
25
 
27
26
  private
28
27
 
29
- attr_reader :gems, :logger
28
+ attr_reader :gems
30
29
 
31
30
  def object_count(objects_or_length, singlular, plural)
32
31
  length =
@@ -3,13 +3,12 @@ module Lapidarist
3
3
  def initialize
4
4
  @bundle = BundleCommand.new
5
5
  @git = GitCommand.new
6
- @logger = Logger.new
7
6
  end
8
7
 
9
8
  def run(gems, attempt)
10
9
  before_sha = git.head if Lapidarist.config.debug
11
10
 
12
- logger.header('Updating outdated gems')
11
+ Lapidarist.logger.header('Updating outdated gems')
13
12
 
14
13
  limit =
15
14
  if Lapidarist.config.update_limit
@@ -29,26 +28,23 @@ module Lapidarist
29
28
 
30
29
  private
31
30
 
32
- attr_reader :outdated_gems, :bundle, :git, :logger
31
+ attr_reader :outdated_gems, :bundle, :git
33
32
 
34
33
  def update_gem(outdated_gem, attempt)
35
- logger.smart_header "Updating #{outdated_gem.name} from #{outdated_gem.installed_version}"
34
+ Lapidarist.logger.smart_header "Updating #{outdated_gem.name} from #{outdated_gem.installed_version}"
36
35
 
37
- available_semver_levels = [Lapidarist.config.version]
38
- available_semver_levels << outdated_gem.next_semver_level if Lapidarist.config.recursive
39
- semver_level_restriction = available_semver_levels.compact.min
40
-
41
- bundle.update(outdated_gem, level: semver_level_restriction)
36
+ level_constraint = Lapidarist::LevelConstraint.new(outdated_gem)
37
+ bundle.update(outdated_gem, level: level_constraint.maximum)
42
38
  updated_version = bundle.version(outdated_gem)
43
39
 
44
40
  if git.clean?
45
41
  skipped_gem = Gem.from(outdated_gem, attempt: attempt, status: :skipped, reason: :nothing_to_update)
46
- logger.footer "nothing to update for #{skipped_gem.name}"
42
+ Lapidarist.logger.footer "nothing to update for #{skipped_gem.name}"
47
43
 
48
44
  skipped_gem
49
45
  else
50
- updated_gem = Gem.from(outdated_gem, attempt: attempt, status: :updated, updated_version: updated_version, level: semver_level_restriction)
51
- logger.footer "updated #{updated_gem.name} to #{updated_gem.updated_version}"
46
+ updated_gem = Gem.from(outdated_gem, attempt: attempt, status: :updated, updated_version: updated_version)
47
+ Lapidarist.logger.footer "updated #{updated_gem.name} to #{updated_gem.updated_version}"
52
48
 
53
49
  git.add('Gemfile', 'Gemfile.lock')
54
50
  git.commit("Update #{updated_gem.what_changed}")
@@ -1,3 +1,3 @@
1
1
  module Lapidarist
2
- VERSION = "0.0.1"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,39 @@
1
+ module Lapidarist
2
+ class VersionChange
3
+ def initialize(installed:, updated:)
4
+ @installed = installed
5
+ @updated = updated
6
+ end
7
+
8
+ def next_level
9
+ if level
10
+ LEVELS.detect { |l| l < level }
11
+ else
12
+ Lapidarist::MAJOR
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ attr_reader :installed, :updated
19
+
20
+ def installed_segments
21
+ @installed_segments ||= installed.split('.')
22
+ end
23
+
24
+ def updated_segments
25
+ @updated_segments ||= updated&.split('.')
26
+ end
27
+
28
+ def level
29
+ @level ||=
30
+ if updated_segments && updated_segments[0] > installed_segments[0]
31
+ Lapidarist::MAJOR
32
+ elsif updated_segments && updated_segments[0] == installed_segments[0] && updated_segments[1] > installed_segments[1]
33
+ Lapidarist::MINOR
34
+ elsif updated_segments && updated_segments[0] == installed_segments[0] && updated_segments[1] == installed_segments[1] && updated_segments[2] > installed_segments[2]
35
+ Lapidarist::PATCH
36
+ end
37
+ end
38
+ end
39
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lapidarist
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Gangl
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-08-01 00:00:00.000000000 Z
11
+ date: 2018-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -61,9 +61,11 @@ executables:
61
61
  extensions: []
62
62
  extra_rdoc_files: []
63
63
  files:
64
+ - ".circleci/config.yml"
64
65
  - ".gitignore"
65
66
  - ".rspec"
66
67
  - ".travis.yml"
68
+ - CHANGELOG.md
67
69
  - Gemfile
68
70
  - LICENSE.txt
69
71
  - README.md
@@ -79,7 +81,9 @@ files:
79
81
  - lib/lapidarist/gem.rb
80
82
  - lib/lapidarist/gems.rb
81
83
  - lib/lapidarist/git_command.rb
84
+ - lib/lapidarist/group_constraint.rb
82
85
  - lib/lapidarist/level.rb
86
+ - lib/lapidarist/level_constraint.rb
83
87
  - lib/lapidarist/logger.rb
84
88
  - lib/lapidarist/options.rb
85
89
  - lib/lapidarist/outdated.rb
@@ -90,6 +94,7 @@ files:
90
94
  - lib/lapidarist/test_command.rb
91
95
  - lib/lapidarist/update.rb
92
96
  - lib/lapidarist/version.rb
97
+ - lib/lapidarist/version_change.rb
93
98
  homepage: https://github.com/attack/lapidarist
94
99
  licenses:
95
100
  - MIT