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 +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
|
+
[](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
|