lapidarist 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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