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 +4 -4
- data/.circleci/config.yml +25 -0
- data/.gitignore +1 -0
- data/CHANGELOG.md +37 -0
- data/Gemfile +8 -0
- data/README.md +15 -3
- data/lib/lapidarist.rb +7 -0
- data/lib/lapidarist/bundle_command.rb +2 -3
- data/lib/lapidarist/cli.rb +17 -20
- data/lib/lapidarist/configuration.rb +7 -1
- data/lib/lapidarist/gem.rb +43 -31
- data/lib/lapidarist/gems.rb +1 -1
- data/lib/lapidarist/git_command.rb +6 -7
- data/lib/lapidarist/group_constraint.rb +15 -0
- data/lib/lapidarist/level.rb +6 -5
- data/lib/lapidarist/level_constraint.rb +29 -0
- data/lib/lapidarist/options.rb +25 -1
- data/lib/lapidarist/outdated.rb +56 -9
- data/lib/lapidarist/sha.rb +2 -3
- data/lib/lapidarist/shell.rb +3 -9
- data/lib/lapidarist/summary.rb +10 -11
- data/lib/lapidarist/update.rb +8 -12
- data/lib/lapidarist/version.rb +1 -1
- data/lib/lapidarist/version_change.rb +39 -0
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b8c8ab46b2d54a0e859b530fc4a412dc89f483eed5244a12c9dd00c0adb1c2c8
|
4
|
+
data.tar.gz: 326f99a9496187492dead76dcc989ff4236aa40361d72391ae94faf1ba82c106
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
data/CHANGELOG.md
ADDED
@@ -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
data/README.md
CHANGED
@@ -1,8 +1,11 @@
|
|
1
1
|
# Lapidarist
|
2
2
|
|
3
|
-
|
3
|
+
[![CircleCI](https://circleci.com/gh/attack/lapidarist.svg?style=svg)](https://circleci.com/gh/attack/lapidarist)
|
4
4
|
|
5
|
-
|
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
|
-
|
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
|
|
data/lib/lapidarist.rb
CHANGED
@@ -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
|
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
|
data/lib/lapidarist/cli.rb
CHANGED
@@ -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
|
-
|
31
|
-
|
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
|
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
|
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
|
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
|
89
|
+
attr_reader :args, :git, :test, :outdated, :update, :sha
|
93
90
|
end
|
94
91
|
end
|
data/lib/lapidarist/gem.rb
CHANGED
@@ -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
|
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
|
-
|
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&.
|
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&.
|
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? &&
|
107
|
+
failed? && !version_change.next_level.nil?
|
90
108
|
end
|
91
109
|
|
92
110
|
def next_semver_level
|
93
|
-
|
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
|
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
|
data/lib/lapidarist/gems.rb
CHANGED
@@ -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
|
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
|
data/lib/lapidarist/level.rb
CHANGED
@@ -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
|
data/lib/lapidarist/options.rb
CHANGED
@@ -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)
|
data/lib/lapidarist/outdated.rb
CHANGED
@@ -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 =
|
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
|
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
|
data/lib/lapidarist/sha.rb
CHANGED
@@ -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
|
24
|
+
attr_reader :good_shas, :git
|
26
25
|
end
|
27
26
|
end
|
data/lib/lapidarist/shell.rb
CHANGED
@@ -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
|
data/lib/lapidarist/summary.rb
CHANGED
@@ -1,24 +1,23 @@
|
|
1
1
|
module Lapidarist
|
2
2
|
class Summary
|
3
|
-
def initialize(gems
|
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
|
14
|
+
case data.status
|
16
15
|
when :updated
|
17
|
-
logger.summary " + updated #{gem.name} from #{gem.installed_version} to #{data
|
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
|
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
|
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
|
28
|
+
attr_reader :gems
|
30
29
|
|
31
30
|
def object_count(objects_or_length, singlular, plural)
|
32
31
|
length =
|
data/lib/lapidarist/update.rb
CHANGED
@@ -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
|
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
|
-
|
38
|
-
|
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
|
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}")
|
data/lib/lapidarist/version.rb
CHANGED
@@ -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
|
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-
|
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
|