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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9cced511802f382d5ebaf4035fd7b06e98f0eca07e72e29c08ddae2b8de01d2f
4
- data.tar.gz: 2854883c107ac874febb0e1aeb1c939d5c621bffed23feb38f22a63e1aaa0d0d
3
+ metadata.gz: 56cca423043e101ebc4014b3b5bb4bc8edf1dd27ce25493b6ec918fe6da669c8
4
+ data.tar.gz: a92f38d08ce56549acae5b6696e2519f0cbef9820750bb29cef419f867448ccc
5
5
  SHA512:
6
- metadata.gz: 34a5301cfb9d2c421079334b0426763c70aeeffcd9e1f270385979403e0506d7753d7e1eba9db1a3741b636154861fb0833c3945a6c1fe60c0bf0ecf3d5410c6
7
- data.tar.gz: 066d049552256df89bede60548f584e5806cfbe4f6d0a470f23ed40d5fb8c0c1554c7f9ef6cf75c6360e7c77d21adc2ac2d4c22e15df71c94d82cb9a8811ce95
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.2)
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.6.2)
16
- irb (>= 1.3.6)
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.5.11)
20
- irb (1.4.1)
19
+ io-console (0.6.0)
20
+ irb (1.6.2)
21
21
  reline (>= 0.3.0)
22
- json (2.6.2)
22
+ json (2.6.3)
23
23
  parallel (1.22.1)
24
- parser (3.1.2.1)
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.5.0)
28
+ regexp_parser (2.7.0)
29
29
  relaxed-rubocop (2.5)
30
- reline (0.3.1)
30
+ reline (0.3.2)
31
31
  io-console (~> 0.5)
32
32
  rexml (3.2.5)
33
- rspec (3.11.0)
34
- rspec-core (~> 3.11.0)
35
- rspec-expectations (~> 3.11.0)
36
- rspec-mocks (~> 3.11.0)
37
- rspec-core (3.11.0)
38
- rspec-support (~> 3.11.0)
39
- rspec-expectations (3.11.1)
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.11.0)
42
- rspec-mocks (3.11.1)
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.11.0)
45
- rspec-support (3.11.1)
46
- rubocop (1.36.0)
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.1.2.1)
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.20.1, < 2.0)
53
+ rubocop-ast (>= 1.24.1, < 2.0)
54
54
  ruby-progressbar (~> 1.7)
55
- unicode-display_width (>= 1.4.0, < 3.0)
56
- rubocop-ast (1.21.0)
57
- parser (>= 3.1.1.0)
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.3.0)
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
@@ -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
- create_adapted_gemfile
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' => adapted_gemfile_path,
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(args = ARGV)
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
- repos = args.map { |arg| Gouteur::Repo.new(uri: arg) }
22
- repos = Dotfile.repos if repos.empty?
23
- repos
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
@@ -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(uri:, ref: nil, before: [], tasks: 'rake', locked: false)
10
- @uri = URI.parse(uri)
11
- @name = extract_name_from_uri(uri)
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)
@@ -1,3 +1,3 @@
1
1
  module Gouteur
2
- VERSION = '1.0.2'.freeze
2
+ VERSION = '1.1.0'.freeze
3
3
  end
data/lib/gouteur.rb CHANGED
@@ -4,6 +4,7 @@ require 'gouteur/bundle'
4
4
  require 'gouteur/checker'
5
5
  require 'gouteur/cli'
6
6
  require 'gouteur/dotfile'
7
+ require 'gouteur/gemfile'
7
8
  require 'gouteur/host'
8
9
  require 'gouteur/message'
9
10
  require 'gouteur/repo'
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.2
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: 2022-09-24 00:00:00.000000000 Z
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.0.dev
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.