gouteur 1.0.2 → 1.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/CHANGELOG.md +9 -0
- data/Gemfile.lock +27 -27
- data/README.md +6 -1
- data/lib/gouteur/checker.rb +8 -36
- data/lib/gouteur/cli.rb +47 -5
- data/lib/gouteur/gemfile.rb +66 -0
- data/lib/gouteur/message.rb +3 -1
- data/lib/gouteur/repo.rb +28 -3
- data/lib/gouteur/version.rb +1 -1
- data/lib/gouteur.rb +1 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 56cca423043e101ebc4014b3b5bb4bc8edf1dd27ce25493b6ec918fe6da669c8
|
4
|
+
data.tar.gz: a92f38d08ce56549acae5b6696e2519f0cbef9820750bb29cef419f867448ccc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 56dfc4cb69657e92322d1e7105bb8d2df73de9b230673758eb98842ec39b5033e56d7d7c6ba39a41a8149734c0db6898157844b7f3b31427febd9b5711cbef2b
|
7
|
+
data.tar.gz: 9b5ceb4857337045681e84448301cafb8985f441816c8f9188706f70b5e95f736b62d739bc90d0abe9f46a4888ff6b59702d3c511e79b193d65ec8beaa337318
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
## [Unreleased]
|
2
2
|
|
3
|
+
## [1.1.0] - 2023-02-21
|
4
|
+
|
5
|
+
### Added
|
6
|
+
|
7
|
+
- Added force flag to force testing, irrespective of version constraints
|
8
|
+
- Support passing dotfile repo names to CLI
|
9
|
+
- Support setting custom names for repos in dotfile
|
10
|
+
- Support git SSH/SCP addresses
|
11
|
+
|
3
12
|
## [1.0.2] - 2022-09-24
|
4
13
|
|
5
14
|
### Fixed
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
gouteur (1.0
|
4
|
+
gouteur (1.1.0)
|
5
5
|
|
6
6
|
PATH
|
7
7
|
remote: spec/gouteur/example_repo
|
@@ -12,51 +12,51 @@ GEM
|
|
12
12
|
remote: https://rubygems.org/
|
13
13
|
specs:
|
14
14
|
ast (2.4.2)
|
15
|
-
debug (1.
|
16
|
-
irb (>= 1.
|
15
|
+
debug (1.7.1)
|
16
|
+
irb (>= 1.5.0)
|
17
17
|
reline (>= 0.3.1)
|
18
18
|
diff-lcs (1.5.0)
|
19
|
-
io-console (0.
|
20
|
-
irb (1.
|
19
|
+
io-console (0.6.0)
|
20
|
+
irb (1.6.2)
|
21
21
|
reline (>= 0.3.0)
|
22
|
-
json (2.6.
|
22
|
+
json (2.6.3)
|
23
23
|
parallel (1.22.1)
|
24
|
-
parser (3.
|
24
|
+
parser (3.2.1.0)
|
25
25
|
ast (~> 2.4.1)
|
26
26
|
rainbow (3.1.1)
|
27
27
|
rake (13.0.6)
|
28
|
-
regexp_parser (2.
|
28
|
+
regexp_parser (2.7.0)
|
29
29
|
relaxed-rubocop (2.5)
|
30
|
-
reline (0.3.
|
30
|
+
reline (0.3.2)
|
31
31
|
io-console (~> 0.5)
|
32
32
|
rexml (3.2.5)
|
33
|
-
rspec (3.
|
34
|
-
rspec-core (~> 3.
|
35
|
-
rspec-expectations (~> 3.
|
36
|
-
rspec-mocks (~> 3.
|
37
|
-
rspec-core (3.
|
38
|
-
rspec-support (~> 3.
|
39
|
-
rspec-expectations (3.
|
33
|
+
rspec (3.12.0)
|
34
|
+
rspec-core (~> 3.12.0)
|
35
|
+
rspec-expectations (~> 3.12.0)
|
36
|
+
rspec-mocks (~> 3.12.0)
|
37
|
+
rspec-core (3.12.1)
|
38
|
+
rspec-support (~> 3.12.0)
|
39
|
+
rspec-expectations (3.12.2)
|
40
40
|
diff-lcs (>= 1.2.0, < 2.0)
|
41
|
-
rspec-support (~> 3.
|
42
|
-
rspec-mocks (3.
|
41
|
+
rspec-support (~> 3.12.0)
|
42
|
+
rspec-mocks (3.12.3)
|
43
43
|
diff-lcs (>= 1.2.0, < 2.0)
|
44
|
-
rspec-support (~> 3.
|
45
|
-
rspec-support (3.
|
46
|
-
rubocop (1.
|
44
|
+
rspec-support (~> 3.12.0)
|
45
|
+
rspec-support (3.12.0)
|
46
|
+
rubocop (1.45.1)
|
47
47
|
json (~> 2.3)
|
48
48
|
parallel (~> 1.10)
|
49
|
-
parser (>= 3.
|
49
|
+
parser (>= 3.2.0.0)
|
50
50
|
rainbow (>= 2.2.2, < 4.0)
|
51
51
|
regexp_parser (>= 1.8, < 3.0)
|
52
52
|
rexml (>= 3.2.5, < 4.0)
|
53
|
-
rubocop-ast (>= 1.
|
53
|
+
rubocop-ast (>= 1.24.1, < 2.0)
|
54
54
|
ruby-progressbar (~> 1.7)
|
55
|
-
unicode-display_width (>=
|
56
|
-
rubocop-ast (1.
|
57
|
-
parser (>= 3.
|
55
|
+
unicode-display_width (>= 2.4.0, < 3.0)
|
56
|
+
rubocop-ast (1.26.0)
|
57
|
+
parser (>= 3.2.1.0)
|
58
58
|
ruby-progressbar (1.11.0)
|
59
|
-
unicode-display_width (2.
|
59
|
+
unicode-display_width (2.4.2)
|
60
60
|
|
61
61
|
PLATFORMS
|
62
62
|
ruby
|
data/README.md
CHANGED
@@ -37,7 +37,9 @@ repos:
|
|
37
37
|
ref: some_specific_branch # optional, default is the default branch
|
38
38
|
before: setup_special_dependency # optional, bundle is always installed
|
39
39
|
tasks: ['rspec', 'rake foo'] # optional, default is `rake`
|
40
|
+
name: cool_gem # optional, defaults to repo name from uri, e.g. `some_gem`
|
40
41
|
locked: true # optional, prevents setting an incompatible VERSION
|
42
|
+
force: true # optional, forces test even if VERSION is incompatible
|
41
43
|
```
|
42
44
|
|
43
45
|
Then simply `bundle exec gouteur` or add the rake task to your Rakefile:
|
@@ -64,7 +66,11 @@ tasks: 'rspec --pattern "**/{,*}{keyword1,keyword2}{,*,*/**/*}_spec.rb"'`
|
|
64
66
|
From the shell:
|
65
67
|
|
66
68
|
```shell
|
69
|
+
# example: check one dependent repo
|
67
70
|
gouteur 'https://github.com/foo/bar'
|
71
|
+
|
72
|
+
# see other usage options:
|
73
|
+
gouteur --help
|
68
74
|
```
|
69
75
|
|
70
76
|
From Ruby:
|
@@ -86,7 +92,6 @@ Possible future improvements:
|
|
86
92
|
- support more sources of code, e.g. latest release, private GitHub repositories
|
87
93
|
- improve performance by tracing & rerunning only specs/tests that use the gem
|
88
94
|
- save time in MiniTest by forcing it to run in fail-fast mode like RSpec
|
89
|
-
- add help output and more options to the CLI executable
|
90
95
|
- other ideas? open an issue!
|
91
96
|
|
92
97
|
## License
|
data/lib/gouteur/checker.rb
CHANGED
@@ -3,15 +3,16 @@ require 'yaml'
|
|
3
3
|
module Gouteur
|
4
4
|
# main process class
|
5
5
|
class Checker
|
6
|
-
attr_reader :repo
|
6
|
+
attr_reader :repo, :force
|
7
7
|
|
8
|
-
def self.call(repo, silent: false)
|
9
|
-
new(repo, silent: silent).call
|
8
|
+
def self.call(repo, silent: false, force: repo&.force?)
|
9
|
+
new(repo, silent: silent, force: force).call
|
10
10
|
end
|
11
11
|
|
12
|
-
def initialize(repo, silent: false)
|
12
|
+
def initialize(repo, silent: false, force: repo&.force?)
|
13
13
|
@repo = repo
|
14
14
|
@silent = silent
|
15
|
+
@force = force
|
15
16
|
end
|
16
17
|
|
17
18
|
def call
|
@@ -21,7 +22,8 @@ module Gouteur
|
|
21
22
|
|
22
23
|
run_tasks(adapted: false)
|
23
24
|
|
24
|
-
|
25
|
+
repo.gemfile.create_adapted(drop_version_constraint: force)
|
26
|
+
repo.remove_host_from_gemspecs if force
|
25
27
|
install_adapted_bundle or return handle_incompatible_semver
|
26
28
|
|
27
29
|
run_tasks(adapted: true)
|
@@ -58,36 +60,6 @@ module Gouteur
|
|
58
60
|
)
|
59
61
|
end
|
60
62
|
|
61
|
-
def create_adapted_gemfile
|
62
|
-
content = File.exist?(gemfile_path) ? File.read(gemfile_path) : ''
|
63
|
-
adapted_content = adapt_gemfile_content(content)
|
64
|
-
File.open(adapted_gemfile_path, 'w') { |f| f.puts(adapted_content) }
|
65
|
-
end
|
66
|
-
|
67
|
-
def adapt_gemfile_content(content)
|
68
|
-
new_entry = "gem '#{Host.name}', path: '#{Host.root}' # set by gouteur "
|
69
|
-
|
70
|
-
existing_ref_pattern =
|
71
|
-
/^ *gem +(?<q>'|")#{Host.name}\k<q>(?<v> *,\s*(?<q2>'|")[^'"]+\k<q2>*)?/
|
72
|
-
|
73
|
-
if content =~ existing_ref_pattern
|
74
|
-
content.gsub(existing_ref_pattern) do
|
75
|
-
# keep version specification if there was one
|
76
|
-
new_entry.sub(/(?=, path:)/, Regexp.last_match[:v].to_s)
|
77
|
-
end
|
78
|
-
else
|
79
|
-
"#{content}\n#{new_entry}\n"
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
def gemfile_path
|
84
|
-
repo.bundle.gemfile_path
|
85
|
-
end
|
86
|
-
|
87
|
-
def adapted_gemfile_path
|
88
|
-
"#{repo.bundle.gemfile_path}.gouteur"
|
89
|
-
end
|
90
|
-
|
91
63
|
def install_adapted_bundle
|
92
64
|
result = repo.bundle.install(env: adaptation_env)
|
93
65
|
if result.success?
|
@@ -116,7 +88,7 @@ module Gouteur
|
|
116
88
|
|
117
89
|
def adaptation_env
|
118
90
|
{
|
119
|
-
'BUNDLE_GEMFILE' =>
|
91
|
+
'BUNDLE_GEMFILE' => repo.gemfile.adapted_path,
|
120
92
|
'SPEC_OPTS' => '--fail-fast', # saves time with rspec tasks
|
121
93
|
}
|
122
94
|
end
|
data/lib/gouteur/cli.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
1
3
|
module Gouteur
|
2
4
|
# command line interface - prints to stdout and returns true or false
|
3
5
|
module CLI
|
4
6
|
module_function
|
5
7
|
|
6
|
-
def call(
|
8
|
+
def call(argv = ARGV)
|
9
|
+
args = option_parser.parse!(argv)
|
10
|
+
|
7
11
|
repos = pick_repos(args)
|
8
12
|
if repos.empty?
|
9
13
|
puts '', Message.no_repos, ''
|
@@ -11,16 +15,54 @@ module Gouteur
|
|
11
15
|
end
|
12
16
|
|
13
17
|
repos.all? do |repo|
|
14
|
-
success, message = Gouteur::Checker.call(repo)
|
18
|
+
success, message = Gouteur::Checker.call(repo, force: !!@force)
|
15
19
|
puts '', message, ''
|
16
20
|
success
|
17
21
|
end
|
18
22
|
end
|
19
23
|
|
24
|
+
def option_parser
|
25
|
+
@force = false
|
26
|
+
|
27
|
+
OptionParser.new do |opts|
|
28
|
+
opts.banner = <<~SH
|
29
|
+
Usage: gouteur [repos] [options]
|
30
|
+
|
31
|
+
Examples:
|
32
|
+
gouteur https://github.com/me/my_repo
|
33
|
+
gouteur my_repo # my_repo must be listed in .gouteur.yml
|
34
|
+
|
35
|
+
SH
|
36
|
+
|
37
|
+
opts.separator 'Options:'
|
38
|
+
|
39
|
+
opts.on("-f", "--force", "Force tests, override version constraints") do
|
40
|
+
@force = true
|
41
|
+
end
|
42
|
+
|
43
|
+
opts.on("-v", "--version", "Show gouteur version") do
|
44
|
+
puts "gouteur #{Gouteur::VERSION}"
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on("-h", "--help", "Show this help") do
|
49
|
+
puts opts
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
20
55
|
def pick_repos(args)
|
21
|
-
|
22
|
-
|
23
|
-
|
56
|
+
dotfile_repos = Dotfile.repos
|
57
|
+
return dotfile_repos if args.empty?
|
58
|
+
|
59
|
+
args.map do |arg|
|
60
|
+
if dotfile_repo = dotfile_repos.find { |r| r.name == arg }
|
61
|
+
dotfile_repo
|
62
|
+
else
|
63
|
+
Gouteur::Repo.new(uri: arg)
|
64
|
+
end
|
65
|
+
end
|
24
66
|
end
|
25
67
|
end
|
26
68
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Gouteur
|
2
|
+
# Gemfile of a repository that depends on the library under test
|
3
|
+
class Gemfile
|
4
|
+
attr_reader :original_path
|
5
|
+
|
6
|
+
def initialize(original_path)
|
7
|
+
@original_path = original_path
|
8
|
+
end
|
9
|
+
|
10
|
+
def adapted_path
|
11
|
+
"#{original_path}.gouteur"
|
12
|
+
end
|
13
|
+
|
14
|
+
def content
|
15
|
+
File.exist?(original_path) ? File.read(original_path) : ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_adapted(drop_version_constraint: false)
|
19
|
+
adapted_content = self.class.adapt(
|
20
|
+
content,
|
21
|
+
drop_version_constraint: drop_version_constraint,
|
22
|
+
)
|
23
|
+
File.open(adapted_path, 'w') { |f| f.puts(adapted_content) }
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.adapt(content, drop_version_constraint: false)
|
27
|
+
new_entry = "gem '#{Host.name}', path: '#{Host.root}' # set by gouteur "
|
28
|
+
|
29
|
+
existing_ref_pattern =
|
30
|
+
/
|
31
|
+
^\s*gem\W+#{Host.name}\W
|
32
|
+
(?<version>
|
33
|
+
\s*,\s*
|
34
|
+
(?:
|
35
|
+
#{VERSION_NUMBER_PATTERN}
|
36
|
+
|
|
37
|
+
\[(?:\s*#{VERSION_NUMBER_PATTERN}\s*,?\s*)+\]
|
38
|
+
)
|
39
|
+
)?
|
40
|
+
/x
|
41
|
+
|
42
|
+
return "#{content}\n#{new_entry}\n" unless content =~ existing_ref_pattern
|
43
|
+
|
44
|
+
content.gsub(existing_ref_pattern) do
|
45
|
+
if drop_version_constraint
|
46
|
+
new_entry
|
47
|
+
else
|
48
|
+
# keep version specification if there was one
|
49
|
+
new_entry.sub(/(?=, path:)/, Regexp.last_match[:version].to_s)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
VERSION_NUMBER_PATTERN =
|
55
|
+
/
|
56
|
+
\d+\.\d+ # float
|
57
|
+
|
|
58
|
+
\d+ # int
|
59
|
+
|
|
60
|
+
(?:%[qQ]?)?
|
61
|
+
(?:
|
62
|
+
'[^']+'|"[^"]+"|\[[^\]]+\]|\{[^}]+\}|\([^)]+\)|<[^>]+>
|
63
|
+
) # string literal
|
64
|
+
/x.freeze
|
65
|
+
end
|
66
|
+
end
|
data/lib/gouteur/message.rb
CHANGED
@@ -75,6 +75,8 @@ module Gouteur
|
|
75
75
|
The new version number of `#{Host.name}` is incompatible with the version requirements specified by `#{repo}`.
|
76
76
|
|
77
77
|
Releasing incompatible versions is considered OK by default, so tasks will be SKIPPED in this case. If you want gouteur to FAIL in this case, set the `locked` flag.
|
78
|
+
|
79
|
+
Use the `force` flag to override this version constraint and run the tests anyway.
|
78
80
|
MSG
|
79
81
|
end
|
80
82
|
|
@@ -84,7 +86,7 @@ module Gouteur
|
|
84
86
|
|
85
87
|
The new version number of `#{Host.name}` is incompatible with the version requirements specified by `#{repo}`.
|
86
88
|
|
87
|
-
Incompatible version numbers can be allowed by removing the `locked` flag. This will make gouteur SKIP the tasks in this case.
|
89
|
+
Incompatible version numbers can be allowed by removing the `locked` flag. This will make gouteur SKIP the tasks in this case unless the `force` flag is set.
|
88
90
|
MSG
|
89
91
|
end
|
90
92
|
|
data/lib/gouteur/repo.rb
CHANGED
@@ -6,13 +6,22 @@ module Gouteur
|
|
6
6
|
attr_reader :uri, :name, :ref, :tasks
|
7
7
|
alias to_s name
|
8
8
|
|
9
|
-
def initialize(
|
10
|
-
|
11
|
-
|
9
|
+
def initialize(
|
10
|
+
uri:,
|
11
|
+
name: nil,
|
12
|
+
ref: nil,
|
13
|
+
before: [],
|
14
|
+
tasks: 'rake',
|
15
|
+
locked: false,
|
16
|
+
force: false
|
17
|
+
)
|
18
|
+
@uri = uri
|
19
|
+
@name = name || extract_name_from_uri(uri)
|
12
20
|
@ref = ref
|
13
21
|
@before = Array(before)
|
14
22
|
@tasks = Array(tasks)
|
15
23
|
@locked = !!locked
|
24
|
+
@force = !!force
|
16
25
|
end
|
17
26
|
|
18
27
|
def fetch
|
@@ -35,10 +44,26 @@ module Gouteur
|
|
35
44
|
@bundle ||= Gouteur::Bundle.new(clone_path)
|
36
45
|
end
|
37
46
|
|
47
|
+
def gemfile
|
48
|
+
@gemfile ||= Gouteur::Gemfile.new(bundle.gemfile_path)
|
49
|
+
end
|
50
|
+
|
38
51
|
def locked?
|
39
52
|
@locked
|
40
53
|
end
|
41
54
|
|
55
|
+
def force?
|
56
|
+
@force
|
57
|
+
end
|
58
|
+
|
59
|
+
def remove_host_from_gemspecs
|
60
|
+
Dir[File.join(clone_path, '*.gemspec')].each do |gemspec_path|
|
61
|
+
content = File.read(gemspec_path)
|
62
|
+
new_content = content.gsub(/^.+_dependency.+\b#{Host.name}\b.+$/, '')
|
63
|
+
File.write(gemspec_path, new_content)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
42
67
|
private
|
43
68
|
|
44
69
|
def extract_name_from_uri(uri)
|
data/lib/gouteur/version.rb
CHANGED
data/lib/gouteur.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gouteur
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Janosch Müller
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-02-21 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: Run tests of dependent gems against your changes.
|
14
14
|
email:
|
@@ -39,6 +39,7 @@ files:
|
|
39
39
|
- lib/gouteur/checker.rb
|
40
40
|
- lib/gouteur/cli.rb
|
41
41
|
- lib/gouteur/dotfile.rb
|
42
|
+
- lib/gouteur/gemfile.rb
|
42
43
|
- lib/gouteur/host.rb
|
43
44
|
- lib/gouteur/message.rb
|
44
45
|
- lib/gouteur/rake_task.rb
|
@@ -67,7 +68,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
67
68
|
- !ruby/object:Gem::Version
|
68
69
|
version: '0'
|
69
70
|
requirements: []
|
70
|
-
rubygems_version: 3.4.
|
71
|
+
rubygems_version: 3.4.1
|
71
72
|
signing_key:
|
72
73
|
specification_version: 4
|
73
74
|
summary: See if your lib is still digestible.
|