modulesync 2.0.1 → 2.0.2

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.
@@ -0,0 +1,26 @@
1
+ Feature: Run `msync update` without a good context
2
+
3
+ Scenario: Run `msync update` without any module
4
+ Given a directory named "moduleroot"
5
+ When I run `msync update --message "In a bad context"`
6
+ Then the exit status should be 1
7
+ And the stderr should contain:
8
+ """
9
+ No modules found
10
+ """
11
+
12
+ Scenario: Run `msync update` without the "moduleroot" directory
13
+ Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
14
+ When I run `msync update --message "In a bad context"`
15
+ Then the exit status should be 1
16
+ And the stderr should contain "moduleroot"
17
+
18
+ Scenario: Run `msync update` without commit message
19
+ Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
20
+ And a directory named "moduleroot"
21
+ When I run `msync update`
22
+ Then the exit status should be 1
23
+ And the stderr should contain:
24
+ """
25
+ No value provided for required option "--message"
26
+ """
data/lib/modulesync.rb CHANGED
@@ -39,10 +39,10 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
39
39
  .collect { |p| p.chomp('.erb') }
40
40
  .to_a
41
41
  else
42
- $stdout.puts "#{local_template_dir} does not exist." \
42
+ $stderr.puts "#{local_template_dir} does not exist." \
43
43
  ' Check that you are working in your module configs directory or' \
44
44
  ' that you have passed in the correct directory with -c.'
45
- exit
45
+ exit 1
46
46
  end
47
47
  end
48
48
 
@@ -53,9 +53,9 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
53
53
  def self.managed_modules(config_file, filter, negative_filter)
54
54
  managed_modules = Util.parse_config(config_file)
55
55
  if managed_modules.empty?
56
- $stdout.puts "No modules found in #{config_file}." \
56
+ $stderr.puts "No modules found in #{config_file}." \
57
57
  ' Check that you specified the right :configs directory and :managed_modules_conf file.'
58
- exit
58
+ exit 1
59
59
  end
60
60
  managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
61
61
  managed_modules.reject! { |m| m =~ Regexp.new(negative_filter) } unless negative_filter.nil?
@@ -1,10 +1,12 @@
1
1
  require 'thor'
2
+
2
3
  require 'modulesync'
4
+ require 'modulesync/cli/thor'
3
5
  require 'modulesync/constants'
4
6
  require 'modulesync/util'
5
7
 
6
8
  module ModuleSync
7
- class CLI
9
+ module CLI
8
10
  def self.defaults
9
11
  @defaults ||= Util.symbolize_keys(Util.parse_config(Constants::MODULESYNC_CONF_FILE))
10
12
  end
@@ -36,15 +38,14 @@ module ModuleSync
36
38
  class Base < Thor
37
39
  class_option :project_root,
38
40
  :aliases => '-c',
39
- :desc => 'Path used by git to clone modules into. Defaults to "modules"',
41
+ :desc => 'Path used by git to clone modules into.',
40
42
  :default => CLI.defaults[:project_root] || 'modules'
41
43
  class_option :git_base,
42
44
  :desc => 'Specify the base part of a git URL to pull from',
43
45
  :default => CLI.defaults[:git_base] || 'git@github.com:'
44
46
  class_option :namespace,
45
47
  :aliases => '-n',
46
- :desc => 'Remote github namespace (user or organization) to clone from and push to.' \
47
- ' Defaults to puppetlabs',
48
+ :desc => 'Remote github namespace (user or organization) to clone from and push to.',
48
49
  :default => CLI.defaults[:namespace] || 'puppetlabs'
49
50
  class_option :filter,
50
51
  :aliases => '-f',
@@ -0,0 +1,24 @@
1
+ require 'thor'
2
+ require 'modulesync/cli'
3
+
4
+ module ModuleSync
5
+ module CLI
6
+ # Workaround some, still unfixed, Thor behaviors
7
+ #
8
+ # This class extends ::Thor class to
9
+ # - exit with status code sets to `1` on Thor failure (e.g. missing required option)
10
+ # - exit with status code sets to `1` when user calls `msync` (or a subcommand) without required arguments
11
+ class Thor < ::Thor
12
+ desc '_invalid_command_call', 'Invalid command', hide: true
13
+ def _invalid_command_call
14
+ self.class.new.help
15
+ exit 1
16
+ end
17
+ default_task :_invalid_command_call
18
+
19
+ def self.exit_on_failure?
20
+ true
21
+ end
22
+ end
23
+ end
24
+ end
@@ -150,7 +150,7 @@ module ModuleSync
150
150
  tag(repo, new, options[:tag_pattern]) if options[:tag]
151
151
  end
152
152
  rescue ::Git::GitExecuteError => git_error
153
- if git_error.message =~ /working (directory|tree) clean/
153
+ if git_error.message.match?(/working (directory|tree) clean/)
154
154
  puts "There were no files to update in #{name}. Not committing."
155
155
  return false
156
156
  else
@@ -1,55 +1,16 @@
1
1
  module Git
2
- class Diff
3
- # Monkey patch process_full_diff until https://github.com/schacon/ruby-git/issues/326 is resolved
4
- def process_full_diff
5
- defaults = {
6
- :mode => '',
7
- :src => '',
8
- :dst => '',
9
- :type => 'modified'
10
- }
11
- final = {}
12
- current_file = nil
13
- full_diff_utf8_encoded = @full_diff.encode("UTF-8", "binary", {
14
- :invalid => :replace,
15
- :undef => :replace
16
- })
17
- full_diff_utf8_encoded.split("\n").each do |line|
18
- if m = /^diff --git a\/(.*?) b\/(.*?)/.match(line)
19
- current_file = m[1]
20
- final[current_file] = defaults.merge({:patch => line, :path => current_file})
21
- elsif !current_file.nil?
22
- if m = /^index (.......)\.\.(.......)( ......)*/.match(line)
23
- final[current_file][:src] = m[1]
24
- final[current_file][:dst] = m[2]
25
- final[current_file][:mode] = m[3].strip if m[3]
26
- end
27
- if m = /^([[:alpha:]]*?) file mode (......)/.match(line)
28
- final[current_file][:type] = m[1]
29
- final[current_file][:mode] = m[2]
30
- end
31
- if m = /^Binary files /.match(line)
32
- final[current_file][:binary] = true
33
- end
34
- final[current_file][:patch] << "\n" + line
35
- end
36
- end
37
- final.map { |e| [e[0], DiffFile.new(@base, e[1])] }
2
+ module LibMonkeyPatch
3
+ # Monkey patch set_custom_git_env_variables due to our ::Git::GitExecuteError handling.
4
+ #
5
+ # We rescue on the GitExecuteError and proceed differently based on the output of git.
6
+ # This way makes code language-dependent, so here we ensure that Git gem throw git commands with the "C" language
7
+ def set_custom_git_env_variables
8
+ super
9
+ ENV['LANG'] = 'C.UTF-8'
38
10
  end
39
11
  end
40
12
 
41
13
  class Lib
42
- # Monkey patch ls_files until https://github.com/ruby-git/ruby-git/pull/320 is resolved
43
- def ls_files(location=nil)
44
- location ||= '.'
45
- hsh = {}
46
- command_lines('ls-files', ['--stage', location]).each do |line|
47
- (info, file) = line.split("\t")
48
- (mode, sha, stage) = info.split
49
- file = eval(file) if file =~ /^\".*\"$/ # This takes care of quoted strings returned from git
50
- hsh[file] = {:path => file, :mode_index => mode, :sha_index => sha, :stage => stage}
51
- end
52
- hsh
53
- end
14
+ prepend LibMonkeyPatch
54
15
  end
55
16
  end
data/modulesync.gemspec CHANGED
@@ -3,7 +3,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |spec|
5
5
  spec.name = 'modulesync'
6
- spec.version = '2.0.1'
6
+ spec.version = '2.0.2'
7
7
  spec.authors = ['Vox Pupuli']
8
8
  spec.email = ['voxpupuli@groups.io']
9
9
  spec.summary = 'Puppet Module Synchronizer'
@@ -23,7 +23,7 @@ Gem::Specification.new do |spec|
23
23
  spec.add_development_dependency 'rspec'
24
24
  spec.add_development_dependency 'rubocop', '~> 0.50.0'
25
25
 
26
- spec.add_runtime_dependency 'git', '~>1.3'
26
+ spec.add_runtime_dependency 'git', '~>1.7'
27
27
  spec.add_runtime_dependency 'gitlab', '~>4.0'
28
28
  spec.add_runtime_dependency 'octokit', '~>4.0'
29
29
  spec.add_runtime_dependency 'puppet-blacksmith', '>= 3.0', '< 7'
@@ -0,0 +1,14 @@
1
+ module ModuleSync
2
+ # Faker is a top-level module to keep global faker config
3
+ module Faker
4
+ def self.working_directory=(path)
5
+ @working_directory = path
6
+ end
7
+
8
+ def self.working_directory
9
+ raise 'Working directory must be set' if @working_directory.nil?
10
+ FileUtils.mkdir_p @working_directory
11
+ @working_directory
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,140 @@
1
+ require 'open3'
2
+
3
+ require_relative '../faker'
4
+
5
+ module ModuleSync
6
+ # Fake a remote git repository that holds a puppet module
7
+ #
8
+ # This module allows to fake a remote repositiory using:
9
+ # - a bare repo
10
+ # - a temporary cloned repo to operate on the remote before exposing to modulesync
11
+ #
12
+ # Note: This module needs to have working_directory sets before using it
13
+ module Faker
14
+ class PuppetModuleRemoteRepo
15
+ class CommandExecutionError < StandardError; end
16
+
17
+ attr_reader :name, :namespace
18
+
19
+ def initialize(name, namespace)
20
+ @name = name
21
+ @namespace = namespace
22
+ end
23
+
24
+ def populate
25
+ FileUtils.chdir(Faker.working_directory) do
26
+ run %W[git init --bare #{bare_repo_dir}]
27
+ run %W[git clone #{bare_repo_dir} #{tmp_repo_dir}]
28
+
29
+ module_short_name = name.split('-').last
30
+
31
+ FileUtils.chdir(tmp_repo_dir) do
32
+ metadata = {
33
+ name: "modulesync-#{module_short_name}",
34
+ version: '0.4.2',
35
+ author: 'ModuleSync team',
36
+ }
37
+
38
+ File.write 'metadata.json', metadata.to_json
39
+ run %w[git add metadata.json]
40
+ run %w[git commit --message] << 'Initial commit'
41
+ run %w[git push]
42
+ end
43
+ end
44
+ end
45
+
46
+ def read_only=(value)
47
+ mode = value ? '0444' : '0644'
48
+ FileUtils.chdir(bare_repo_dir) do
49
+ run %W[git config core.sharedRepository #{mode}]
50
+ end
51
+ end
52
+
53
+ def default_branch
54
+ FileUtils.chdir(bare_repo_dir) do
55
+ stdout = run %w[git symbolic-ref --short HEAD]
56
+ return stdout.chomp
57
+ end
58
+ end
59
+
60
+ def default_branch=(value)
61
+ FileUtils.chdir(bare_repo_dir) do
62
+ run %W[git branch -M #{default_branch} #{value}]
63
+ run %W[git symbolic-ref HEAD refs/heads/#{value}]
64
+ end
65
+ end
66
+
67
+ def read_file(filename, branch = nil)
68
+ branch ||= default_branch
69
+ FileUtils.chdir(bare_repo_dir) do
70
+ return run %W[git show #{branch}:#{filename}]
71
+ rescue CommandExecutionError
72
+ return nil
73
+ end
74
+ end
75
+
76
+ def add_file(filename, content, branch = nil)
77
+ branch ||= default_branch
78
+ FileUtils.chdir(tmp_repo_dir) do
79
+ run %W[git checkout #{branch}]
80
+ File.write filename, content
81
+ run %W[git add #{filename}]
82
+ run %w[git commit --message] << "Add file: '#{filename}'"
83
+ run %w[git push]
84
+ end
85
+ end
86
+
87
+ def commit_count_between(commit1, commit2)
88
+ FileUtils.chdir(bare_repo_dir) do
89
+ stdout = run %W[git rev-list --count #{commit1}..#{commit2}]
90
+ return Integer(stdout)
91
+ end
92
+ end
93
+
94
+ def commit_count_by(author, commit = nil)
95
+ FileUtils.chdir(bare_repo_dir) do
96
+ commit ||= '--all'
97
+ stdout = run %W[git rev-list #{commit} --author #{author} --count]
98
+ return Integer(stdout)
99
+ end
100
+ end
101
+
102
+ def remote_url
103
+ "file://#{bare_repo_dir}"
104
+ end
105
+
106
+ def self.git_base
107
+ "file://#{Faker.working_directory}/bare/"
108
+ end
109
+
110
+ private
111
+
112
+ def tmp_repo_dir
113
+ File.join Faker.working_directory, 'tmp', namespace, name
114
+ end
115
+
116
+ def bare_repo_dir
117
+ File.join Faker.working_directory, 'bare', namespace, "#{name}.git"
118
+ end
119
+
120
+ GIT_ENV = {
121
+ 'GIT_AUTHOR_NAME' => 'Faker',
122
+ 'GIT_AUTHOR_EMAIL' => 'faker@example.com',
123
+ 'GIT_COMMITTER_NAME' => 'Faker',
124
+ 'GIT_COMMITTER_EMAIL' => 'faker@example.com',
125
+ }.freeze
126
+
127
+ def run(command)
128
+ stdout, stderr, status = Open3.capture3(GIT_ENV, *command)
129
+ return stdout if status.success?
130
+
131
+ warn "Command '#{command}' failed: #{status}"
132
+ warn ' STDOUT:'
133
+ warn stdout
134
+ warn ' STDERR:'
135
+ warn stderr
136
+ raise CommandExecutionError, "Command '#{command}' failed: #{status}"
137
+ end
138
+ end
139
+ end
140
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: modulesync
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.1
4
+ version: 2.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vox Pupuli
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-06 00:00:00.000000000 Z
11
+ date: 2021-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aruba
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '1.3'
89
+ version: '1.7'
90
90
  type: :runtime
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '1.3'
96
+ version: '1.7'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: gitlab
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -164,6 +164,7 @@ executables:
164
164
  extensions: []
165
165
  extra_rdoc_files: []
166
166
  files:
167
+ - ".config/cucumber.yml"
167
168
  - ".gitignore"
168
169
  - ".rspec"
169
170
  - ".rubocop.yml"
@@ -182,8 +183,10 @@ files:
182
183
  - features/step_definitions/git_steps.rb
183
184
  - features/support/env.rb
184
185
  - features/update.feature
186
+ - features/update/bad_context.feature
185
187
  - lib/modulesync.rb
186
188
  - lib/modulesync/cli.rb
189
+ - lib/modulesync/cli/thor.rb
187
190
  - lib/modulesync/constants.rb
188
191
  - lib/modulesync/git.rb
189
192
  - lib/modulesync/hook.rb
@@ -194,6 +197,8 @@ files:
194
197
  - lib/modulesync/util.rb
195
198
  - lib/monkey_patches.rb
196
199
  - modulesync.gemspec
200
+ - spec/helpers/faker.rb
201
+ - spec/helpers/faker/puppet_module_remote_repo.rb
197
202
  - spec/spec_helper.rb
198
203
  - spec/unit/modulesync/pr/github_spec.rb
199
204
  - spec/unit/modulesync/pr/gitlab_spec.rb
@@ -228,6 +233,9 @@ test_files:
228
233
  - features/step_definitions/git_steps.rb
229
234
  - features/support/env.rb
230
235
  - features/update.feature
236
+ - features/update/bad_context.feature
237
+ - spec/helpers/faker.rb
238
+ - spec/helpers/faker/puppet_module_remote_repo.rb
231
239
  - spec/spec_helper.rb
232
240
  - spec/unit/modulesync/pr/github_spec.rb
233
241
  - spec/unit/modulesync/pr/gitlab_spec.rb