modulesync 2.0.1 → 2.2.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.
@@ -0,0 +1,57 @@
1
+ require 'modulesync'
2
+ require 'modulesync/repository'
3
+ require 'modulesync/util'
4
+
5
+ module ModuleSync
6
+ # Provide methods to retrieve source code attributes
7
+ class SourceCode
8
+ attr_reader :given_name
9
+ attr_reader :options
10
+
11
+ def initialize(given_name, options)
12
+ @options = Util.symbolize_keys(options || {})
13
+
14
+ @given_name = given_name
15
+
16
+ return unless given_name.include?('/')
17
+
18
+ @repository_name = given_name.split('/').last
19
+ @repository_namespace = given_name.split('/')[0...-1].join('/')
20
+ end
21
+
22
+ def repository
23
+ @repository ||= Repository.new directory: working_directory, remote: repository_remote
24
+ end
25
+
26
+ def repository_name
27
+ @repository_name ||= given_name
28
+ end
29
+
30
+ def repository_namespace
31
+ @repository_namespace ||= @options[:namespace] || ModuleSync.options[:namespace]
32
+ end
33
+
34
+ def repository_path
35
+ @repository_path ||= "#{repository_namespace}/#{repository_name}"
36
+ end
37
+
38
+ def repository_remote
39
+ @repository_remote ||= @options[:remote] || _repository_remote
40
+ end
41
+
42
+ def working_directory
43
+ @working_directory ||= File.join(ModuleSync.options[:project_root], repository_path)
44
+ end
45
+
46
+ def path(*parts)
47
+ File.join(working_directory, *parts)
48
+ end
49
+
50
+ private
51
+
52
+ def _repository_remote
53
+ git_base = ModuleSync.options[:git_base]
54
+ git_base.start_with?('file://') ? "#{git_base}#{repository_path}" : "#{git_base}#{repository_path}.git"
55
+ end
56
+ end
57
+ end
@@ -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,12 +3,12 @@ $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.2.0'
7
7
  spec.authors = ['Vox Pupuli']
8
8
  spec.email = ['voxpupuli@groups.io']
9
9
  spec.summary = 'Puppet Module Synchronizer'
10
10
  spec.description = 'Utility to synchronize common files across puppet modules in Github.'
11
- spec.homepage = 'http://github.com/voxpupuli/modulesync'
11
+ spec.homepage = 'https://github.com/voxpupuli/modulesync'
12
12
  spec.license = 'Apache-2.0'
13
13
  spec.required_ruby_version = '>= 2.5.0'
14
14
 
@@ -17,13 +17,14 @@ Gem::Specification.new do |spec|
17
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
18
  spec.require_paths = ['lib']
19
19
 
20
- spec.add_development_dependency 'aruba', '~> 0.14'
20
+ spec.add_development_dependency 'aruba', '>= 0.14', '< 2'
21
21
  spec.add_development_dependency 'bundler'
22
22
  spec.add_development_dependency 'rake'
23
23
  spec.add_development_dependency 'rspec'
24
24
  spec.add_development_dependency 'rubocop', '~> 0.50.0'
25
+ spec.add_development_dependency 'cucumber'
25
26
 
26
- spec.add_runtime_dependency 'git', '~>1.3'
27
+ spec.add_runtime_dependency 'git', '~>1.7'
27
28
  spec.add_runtime_dependency 'gitlab', '~>4.0'
28
29
  spec.add_runtime_dependency 'octokit', '~>4.0'
29
30
  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,146 @@
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 tags
103
+ FileUtils.chdir(bare_repo_dir) do
104
+ return run %w{git tag --list}
105
+ end
106
+ end
107
+
108
+ def remote_url
109
+ "file://#{bare_repo_dir}"
110
+ end
111
+
112
+ def self.git_base
113
+ "file://#{Faker.working_directory}/bare/"
114
+ end
115
+
116
+ private
117
+
118
+ def tmp_repo_dir
119
+ File.join Faker.working_directory, 'tmp', namespace, name
120
+ end
121
+
122
+ def bare_repo_dir
123
+ File.join Faker.working_directory, 'bare', namespace, "#{name}.git"
124
+ end
125
+
126
+ GIT_ENV = {
127
+ 'GIT_AUTHOR_NAME' => 'Faker',
128
+ 'GIT_AUTHOR_EMAIL' => 'faker@example.com',
129
+ 'GIT_COMMITTER_NAME' => 'Faker',
130
+ 'GIT_COMMITTER_EMAIL' => 'faker@example.com',
131
+ }.freeze
132
+
133
+ def run(command)
134
+ stdout, stderr, status = Open3.capture3(GIT_ENV, *command)
135
+ return stdout if status.success?
136
+
137
+ warn "Command '#{command}' failed: #{status}"
138
+ warn ' STDOUT:'
139
+ warn stdout
140
+ warn ' STDERR:'
141
+ warn stderr
142
+ raise CommandExecutionError, "Command '#{command}' failed: #{status}"
143
+ end
144
+ end
145
+ end
146
+ end
data/spec/spec_helper.rb CHANGED
@@ -1 +1,25 @@
1
+ begin
2
+ require 'simplecov'
3
+ require 'simplecov-console'
4
+ require 'codecov'
5
+ rescue LoadError
6
+ else
7
+ SimpleCov.start do
8
+ track_files 'lib/**/*.rb'
9
+
10
+ add_filter '/spec'
11
+
12
+ enable_coverage :branch
13
+
14
+ # do not track vendored files
15
+ add_filter '/vendor'
16
+ add_filter '/.vendor'
17
+ end
18
+
19
+ SimpleCov.formatters = [
20
+ SimpleCov::Formatter::Console,
21
+ SimpleCov::Formatter::Codecov,
22
+ ]
23
+ end
24
+
1
25
  require 'modulesync'
@@ -5,7 +5,7 @@ describe ModuleSync do
5
5
  it 'loads the managed modules from the specified :managed_modules_conf' do
6
6
  allow(ModuleSync).to receive(:find_template_files).and_return([])
7
7
  allow(ModuleSync::Util).to receive(:parse_config).with('./config_defaults.yml').and_return({})
8
- expect(ModuleSync).to receive(:managed_modules).with('./test_file.yml', nil, nil).and_return([])
8
+ expect(ModuleSync).to receive(:managed_modules).with(no_args).and_return([])
9
9
 
10
10
  options = { managed_modules_conf: 'test_file.yml' }
11
11
  ModuleSync.update(options)
@@ -14,8 +14,12 @@ describe ModuleSync do
14
14
 
15
15
  context '::pr' do
16
16
  describe "Raise Error" do
17
+ let(:puppet_module) do
18
+ ModuleSync::PuppetModule.new 'puppet-test', remote: 'dummy'
19
+ end
20
+
17
21
  it 'raises an error when neither GITHUB_TOKEN nor GITLAB_TOKEN are set for PRs' do
18
- expect { ModuleSync.pr({}) }.to raise_error(RuntimeError).and output(/No GitHub or GitLab token specified for --pr/).to_stderr
22
+ expect { ModuleSync.pr(puppet_module) }.to raise_error(RuntimeError).and output(/No GitHub or GitLab token specified for --pr/).to_stderr
19
23
  end
20
24
  end
21
25
  end
metadata CHANGED
@@ -1,29 +1,35 @@
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.2.0
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-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: aruba
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0.14'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '2'
20
23
  type: :development
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '0.14'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '2'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: bundler
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -80,20 +86,34 @@ dependencies:
80
86
  - - "~>"
81
87
  - !ruby/object:Gem::Version
82
88
  version: 0.50.0
89
+ - !ruby/object:Gem::Dependency
90
+ name: cucumber
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ version: '0'
96
+ type: :development
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
83
103
  - !ruby/object:Gem::Dependency
84
104
  name: git
85
105
  requirement: !ruby/object:Gem::Requirement
86
106
  requirements:
87
107
  - - "~>"
88
108
  - !ruby/object:Gem::Version
89
- version: '1.3'
109
+ version: '1.7'
90
110
  type: :runtime
91
111
  prerelease: false
92
112
  version_requirements: !ruby/object:Gem::Requirement
93
113
  requirements:
94
114
  - - "~>"
95
115
  - !ruby/object:Gem::Version
96
- version: '1.3'
116
+ version: '1.7'
97
117
  - !ruby/object:Gem::Dependency
98
118
  name: gitlab
99
119
  requirement: !ruby/object:Gem::Requirement
@@ -164,11 +184,13 @@ executables:
164
184
  extensions: []
165
185
  extra_rdoc_files: []
166
186
  files:
187
+ - ".config/cucumber.yml"
188
+ - ".github/workflows/ci.yml"
189
+ - ".github/workflows/release.yml"
167
190
  - ".gitignore"
168
191
  - ".rspec"
169
192
  - ".rubocop.yml"
170
193
  - ".rubocop_todo.yml"
171
- - ".travis.yml"
172
194
  - CHANGELOG.md
173
195
  - Gemfile
174
196
  - HISTORY.md
@@ -182,24 +204,31 @@ files:
182
204
  - features/step_definitions/git_steps.rb
183
205
  - features/support/env.rb
184
206
  - features/update.feature
207
+ - features/update/bad_context.feature
208
+ - features/update/bump_version.feature
185
209
  - lib/modulesync.rb
186
210
  - lib/modulesync/cli.rb
211
+ - lib/modulesync/cli/thor.rb
187
212
  - lib/modulesync/constants.rb
188
- - lib/modulesync/git.rb
189
213
  - lib/modulesync/hook.rb
190
214
  - lib/modulesync/pr/github.rb
191
215
  - lib/modulesync/pr/gitlab.rb
216
+ - lib/modulesync/puppet_module.rb
192
217
  - lib/modulesync/renderer.rb
218
+ - lib/modulesync/repository.rb
193
219
  - lib/modulesync/settings.rb
220
+ - lib/modulesync/source_code.rb
194
221
  - lib/modulesync/util.rb
195
222
  - lib/monkey_patches.rb
196
223
  - modulesync.gemspec
224
+ - spec/helpers/faker.rb
225
+ - spec/helpers/faker/puppet_module_remote_repo.rb
197
226
  - spec/spec_helper.rb
198
227
  - spec/unit/modulesync/pr/github_spec.rb
199
228
  - spec/unit/modulesync/pr/gitlab_spec.rb
200
229
  - spec/unit/modulesync/settings_spec.rb
201
230
  - spec/unit/modulesync_spec.rb
202
- homepage: http://github.com/voxpupuli/modulesync
231
+ homepage: https://github.com/voxpupuli/modulesync
203
232
  licenses:
204
233
  - Apache-2.0
205
234
  metadata: {}
@@ -218,7 +247,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
218
247
  - !ruby/object:Gem::Version
219
248
  version: '0'
220
249
  requirements: []
221
- rubygems_version: 3.1.2
250
+ rubygems_version: 3.2.22
222
251
  signing_key:
223
252
  specification_version: 4
224
253
  summary: Puppet Module Synchronizer
@@ -228,6 +257,10 @@ test_files:
228
257
  - features/step_definitions/git_steps.rb
229
258
  - features/support/env.rb
230
259
  - features/update.feature
260
+ - features/update/bad_context.feature
261
+ - features/update/bump_version.feature
262
+ - spec/helpers/faker.rb
263
+ - spec/helpers/faker/puppet_module_remote_repo.rb
231
264
  - spec/spec_helper.rb
232
265
  - spec/unit/modulesync/pr/github_spec.rb
233
266
  - spec/unit/modulesync/pr/gitlab_spec.rb