modulesync 2.6.0 → 2.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +2 -4
- data/.github/workflows/release.yml +1 -1
- data/.rubocop.yml +3 -48
- data/.rubocop_todo.yml +124 -19
- data/CHANGELOG.md +13 -0
- data/Gemfile +6 -5
- data/Rakefile +4 -11
- data/lib/modulesync/cli.rb +107 -107
- data/lib/modulesync/git_service/base.rb +2 -2
- data/lib/modulesync/git_service/github.rb +5 -5
- data/lib/modulesync/git_service/gitlab.rb +9 -9
- data/lib/modulesync/renderer.rb +1 -1
- data/lib/modulesync/repository.rb +2 -2
- data/lib/modulesync.rb +21 -21
- data/modulesync.gemspec +5 -9
- data/spec/helpers/faker/puppet_module_remote_repo.rb +4 -4
- data/spec/helpers/faker.rb +1 -0
- data/spec/unit/modulesync/git_service/factory_spec.rb +8 -2
- data/spec/unit/modulesync/git_service/github_spec.rb +23 -25
- data/spec/unit/modulesync/git_service/gitlab_spec.rb +26 -29
- data/spec/unit/modulesync/git_service_spec.rb +48 -47
- data/spec/unit/modulesync/settings_spec.rb +1 -1
- data/spec/unit/modulesync/source_code_spec.rb +5 -7
- metadata +21 -71
@@ -13,12 +13,12 @@ module ModuleSync
|
|
13
13
|
Octokit.configure do |c|
|
14
14
|
c.api_endpoint = endpoint
|
15
15
|
end
|
16
|
-
@api = Octokit::Client.new(:
|
16
|
+
@api = Octokit::Client.new(access_token: token)
|
17
17
|
end
|
18
18
|
|
19
19
|
private
|
20
20
|
|
21
|
-
def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:)
|
21
|
+
def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:)
|
22
22
|
head = "#{namespace}:#{source_branch}"
|
23
23
|
|
24
24
|
if noop
|
@@ -28,9 +28,9 @@ module ModuleSync
|
|
28
28
|
end
|
29
29
|
|
30
30
|
pull_requests = @api.pull_requests(repo_path,
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
31
|
+
state: 'open',
|
32
|
+
base: target_branch,
|
33
|
+
head: head)
|
34
34
|
unless pull_requests.empty?
|
35
35
|
# Skip creating the PR if it exists already.
|
36
36
|
$stdout.puts "Skipped! #{pull_requests.length} PRs found for branch '#{source_branch}'"
|
@@ -11,8 +11,8 @@ module ModuleSync
|
|
11
11
|
super()
|
12
12
|
|
13
13
|
@api = Gitlab::Client.new(
|
14
|
-
:
|
15
|
-
:
|
14
|
+
endpoint: endpoint,
|
15
|
+
private_token: token,
|
16
16
|
)
|
17
17
|
end
|
18
18
|
|
@@ -26,7 +26,7 @@ module ModuleSync
|
|
26
26
|
|
27
27
|
private
|
28
28
|
|
29
|
-
def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:) # rubocop:disable
|
29
|
+
def _open_pull_request(repo_path:, namespace:, title:, message:, source_branch:, target_branch:, labels:, noop:) # rubocop:disable Lint/UnusedMethodArgument
|
30
30
|
if noop
|
31
31
|
$stdout.puts "Using no-op. Would submit MR '#{title}' to '#{repo_path}' " \
|
32
32
|
"- merges #{source_branch} into #{target_branch}"
|
@@ -34,9 +34,9 @@ module ModuleSync
|
|
34
34
|
end
|
35
35
|
|
36
36
|
merge_requests = @api.merge_requests(repo_path,
|
37
|
-
:
|
38
|
-
:
|
39
|
-
:
|
37
|
+
state: 'opened',
|
38
|
+
source_branch: source_branch,
|
39
|
+
target_branch: target_branch)
|
40
40
|
unless merge_requests.empty?
|
41
41
|
# Skip creating the MR if it exists already.
|
42
42
|
$stdout.puts "Skipped! #{merge_requests.length} MRs found for branch '#{source_branch}'"
|
@@ -45,9 +45,9 @@ module ModuleSync
|
|
45
45
|
|
46
46
|
mr = @api.create_merge_request(repo_path,
|
47
47
|
title,
|
48
|
-
:
|
49
|
-
:
|
50
|
-
:
|
48
|
+
source_branch: source_branch,
|
49
|
+
target_branch: target_branch,
|
50
|
+
labels: labels)
|
51
51
|
$stdout.puts \
|
52
52
|
"Submitted MR '#{title}' to '#{repo_path}' " \
|
53
53
|
"- merges '#{source_branch}' into '#{target_branch}'"
|
data/lib/modulesync/renderer.rb
CHANGED
@@ -15,7 +15,7 @@ module ModuleSync
|
|
15
15
|
erb_obj = if RUBY_VERSION >= '2.7'
|
16
16
|
ERB.new(template, trim_mode: '-')
|
17
17
|
else
|
18
|
-
ERB.new(template,
|
18
|
+
ERB.new(template, trim_mode: '-')
|
19
19
|
end
|
20
20
|
erb_obj.filename = template_file
|
21
21
|
erb_obj.def_method(ForgeModuleFile, 'render()', template_file)
|
@@ -140,8 +140,8 @@ module ModuleSync
|
|
140
140
|
begin
|
141
141
|
opts_commit = {}
|
142
142
|
opts_push = {}
|
143
|
-
opts_commit = { :
|
144
|
-
opts_push = { :
|
143
|
+
opts_commit = { amend: true } if options[:amend]
|
144
|
+
opts_push = { force: true } if options[:force]
|
145
145
|
if options[:pre_commit_script]
|
146
146
|
script = "#{File.dirname(File.dirname(__FILE__))}/../contrib/#{options[:pre_commit_script]}"
|
147
147
|
`#{script} #{@directory}`
|
data/lib/modulesync.rb
CHANGED
@@ -12,17 +12,17 @@ require 'modulesync/util'
|
|
12
12
|
|
13
13
|
require 'monkey_patches'
|
14
14
|
|
15
|
-
module ModuleSync
|
15
|
+
module ModuleSync
|
16
16
|
class Error < StandardError; end
|
17
17
|
|
18
18
|
include Constants
|
19
19
|
|
20
20
|
def self.config_defaults
|
21
21
|
{
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
25
|
-
:
|
22
|
+
project_root: 'modules/',
|
23
|
+
managed_modules_conf: 'managed_modules.yml',
|
24
|
+
configs: '.',
|
25
|
+
tag_pattern: '%s',
|
26
26
|
}
|
27
27
|
end
|
28
28
|
|
@@ -33,7 +33,7 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
33
33
|
def self.local_file(config_path, file)
|
34
34
|
path = File.join(config_path, MODULE_FILES_DIR, file)
|
35
35
|
if !File.exist?("#{path}.erb") && File.exist?(path)
|
36
|
-
|
36
|
+
warn "Warning: using '#{path}' as template without '.erb' suffix"
|
37
37
|
path
|
38
38
|
else
|
39
39
|
"#{path}.erb"
|
@@ -50,9 +50,9 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
50
50
|
.collect { |p| p.chomp('.erb') }
|
51
51
|
.to_a
|
52
52
|
else
|
53
|
-
|
54
|
-
|
55
|
-
|
53
|
+
warn "#{local_template_dir} does not exist. " \
|
54
|
+
'Check that you are working in your module configs directory or ' \
|
55
|
+
'that you have passed in the correct directory with -c.'
|
56
56
|
exit 1
|
57
57
|
end
|
58
58
|
end
|
@@ -68,8 +68,8 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
68
68
|
|
69
69
|
managed_modules = Util.parse_config(config_file)
|
70
70
|
if managed_modules.empty?
|
71
|
-
|
72
|
-
|
71
|
+
warn "No modules found in #{config_file}. " \
|
72
|
+
'Check that you specified the right :configs directory and :managed_modules_conf file.'
|
73
73
|
exit 1
|
74
74
|
end
|
75
75
|
managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
|
@@ -99,16 +99,16 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
99
99
|
erb = Renderer.build(template_file)
|
100
100
|
# Meta data passed to the template as @metadata[:name]
|
101
101
|
metadata = {
|
102
|
-
:
|
103
|
-
:
|
104
|
-
:
|
105
|
-
:
|
102
|
+
module_name: settings.additional_settings[:puppet_module],
|
103
|
+
namespace: settings.additional_settings[:namespace],
|
104
|
+
workdir: puppet_module.working_directory,
|
105
|
+
target_file: target_file,
|
106
106
|
}
|
107
107
|
template = Renderer.render(erb, configs, metadata)
|
108
108
|
mode = File.stat(template_file).mode
|
109
109
|
Renderer.sync(template, target_file, mode)
|
110
110
|
rescue StandardError
|
111
|
-
|
111
|
+
warn "#{puppet_module.given_name}: Error while rendering file: '#{filename}'"
|
112
112
|
raise
|
113
113
|
end
|
114
114
|
end
|
@@ -128,9 +128,9 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
128
128
|
defaults,
|
129
129
|
module_configs[GLOBAL_DEFAULTS_KEY] || {},
|
130
130
|
module_configs,
|
131
|
-
:
|
132
|
-
:
|
133
|
-
:
|
131
|
+
puppet_module: puppet_module.repository_name,
|
132
|
+
git_base: options[:git_base],
|
133
|
+
namespace: puppet_module.repository_namespace)
|
134
134
|
|
135
135
|
settings.unmanaged_files(module_files).each do |filename|
|
136
136
|
$stdout.puts "Not managing '#{filename}' in '#{puppet_module.given_name}'"
|
@@ -178,7 +178,7 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
178
178
|
manage_module(puppet_module, module_files, defaults)
|
179
179
|
rescue ModuleSync::Error, Git::GitExecuteError => e
|
180
180
|
message = e.message || 'Error during `update`'
|
181
|
-
|
181
|
+
warn "#{puppet_module.given_name}: #{message}"
|
182
182
|
exit 1 unless options[:skip_broken]
|
183
183
|
errors = true
|
184
184
|
$stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
|
@@ -222,7 +222,7 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
222
222
|
raise Thor::Error, message if @options[:fail_fast]
|
223
223
|
|
224
224
|
errors[puppet_module.given_name] = message
|
225
|
-
|
225
|
+
warn message
|
226
226
|
end
|
227
227
|
|
228
228
|
$stdout.puts ''
|
data/modulesync.gemspec
CHANGED
@@ -3,33 +3,29 @@ $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.
|
6
|
+
spec.version = '2.7.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
11
|
spec.homepage = 'https://github.com/voxpupuli/modulesync'
|
12
12
|
spec.license = 'Apache-2.0'
|
13
|
-
spec.required_ruby_version = '>= 2.
|
13
|
+
spec.required_ruby_version = '>= 2.7.0'
|
14
14
|
|
15
15
|
spec.files = `git ls-files -z`.split("\x0")
|
16
16
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
17
17
|
spec.require_paths = ['lib']
|
18
18
|
|
19
19
|
spec.add_development_dependency 'aruba', '~>2.0'
|
20
|
-
spec.add_development_dependency 'bundler'
|
21
20
|
spec.add_development_dependency 'cucumber'
|
22
21
|
spec.add_development_dependency 'rake'
|
23
22
|
spec.add_development_dependency 'rspec'
|
24
|
-
spec.add_development_dependency 'rubocop', '~> 1.28.2'
|
25
|
-
spec.add_development_dependency 'rubocop-performance'
|
26
|
-
spec.add_development_dependency 'rubocop-rake'
|
27
|
-
spec.add_development_dependency 'rubocop-rspec'
|
28
23
|
spec.add_development_dependency 'simplecov'
|
24
|
+
spec.add_development_dependency 'voxpupuli-rubocop', '~> 1.3'
|
29
25
|
|
30
26
|
spec.add_runtime_dependency 'git', '~>1.7'
|
31
27
|
spec.add_runtime_dependency 'gitlab', '~>4.0'
|
32
|
-
spec.add_runtime_dependency 'octokit', '
|
33
|
-
spec.add_runtime_dependency 'puppet-blacksmith', '>= 3.0', '<
|
28
|
+
spec.add_runtime_dependency 'octokit', '>=4', '<7'
|
29
|
+
spec.add_runtime_dependency 'puppet-blacksmith', '>= 3.0', '< 8'
|
34
30
|
spec.add_runtime_dependency 'thor'
|
35
31
|
end
|
@@ -102,21 +102,21 @@ module ModuleSync
|
|
102
102
|
|
103
103
|
def tags
|
104
104
|
FileUtils.chdir(bare_repo_dir) do
|
105
|
-
return run %w
|
105
|
+
return run %w[git tag --list]
|
106
106
|
end
|
107
107
|
end
|
108
108
|
|
109
109
|
def delete_branch(branch)
|
110
110
|
FileUtils.chdir(bare_repo_dir) do
|
111
|
-
run %W
|
111
|
+
run %W[git branch -D #{branch}]
|
112
112
|
end
|
113
113
|
end
|
114
114
|
|
115
115
|
def create_branch(branch, from = nil)
|
116
116
|
from ||= default_branch
|
117
117
|
FileUtils.chdir(tmp_repo_dir) do
|
118
|
-
run %W
|
119
|
-
run %W
|
118
|
+
run %W[git branch -c #{from} #{branch}]
|
119
|
+
run %W[git push --set-upstream origin #{branch}]
|
120
120
|
end
|
121
121
|
end
|
122
122
|
|
data/spec/helpers/faker.rb
CHANGED
@@ -4,13 +4,19 @@ require 'modulesync/git_service/factory'
|
|
4
4
|
describe ModuleSync::GitService::Factory do
|
5
5
|
context 'when instantiate a GitHub service without credentials' do
|
6
6
|
it 'raises an error' do
|
7
|
-
expect
|
7
|
+
expect do
|
8
|
+
ModuleSync::GitService::Factory.instantiate(type: :github, endpoint: nil,
|
9
|
+
token: nil)
|
10
|
+
end.to raise_error(ModuleSync::GitService::MissingCredentialsError)
|
8
11
|
end
|
9
12
|
end
|
10
13
|
|
11
14
|
context 'when instantiate a GitLab service without credentials' do
|
12
15
|
it 'raises an error' do
|
13
|
-
expect
|
16
|
+
expect do
|
17
|
+
ModuleSync::GitService::Factory.instantiate(type: :gitlab, endpoint: nil,
|
18
|
+
token: nil)
|
19
|
+
end.to raise_error(ModuleSync::GitService::MissingCredentialsError)
|
14
20
|
end
|
15
21
|
end
|
16
22
|
end
|
@@ -4,8 +4,8 @@ require 'modulesync/git_service/github'
|
|
4
4
|
|
5
5
|
describe ModuleSync::GitService::GitHub do
|
6
6
|
context '::open_pull_request' do
|
7
|
-
before
|
8
|
-
@client = double
|
7
|
+
before do
|
8
|
+
@client = double
|
9
9
|
allow(Octokit::Client).to receive(:new).and_return(@client)
|
10
10
|
@it = ModuleSync::GitService::GitHub.new('test', 'https://api.github.com')
|
11
11
|
end
|
@@ -28,53 +28,51 @@ describe ModuleSync::GitService::GitHub do
|
|
28
28
|
it 'submits PR when --pr is set' do
|
29
29
|
allow(@client).to receive(:pull_requests)
|
30
30
|
.with(args[:repo_path],
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
).and_return([])
|
31
|
+
state: 'open',
|
32
|
+
base: 'master',
|
33
|
+
head: "#{args[:namespace]}:#{args[:source_branch]}").and_return([])
|
35
34
|
expect(@client).to receive(:create_pull_request)
|
36
35
|
.with(args[:repo_path],
|
37
36
|
'master',
|
38
37
|
args[:source_branch],
|
39
38
|
args[:title],
|
40
|
-
args[:message]
|
41
|
-
).and_return({"html_url" => "http://example.com/pulls/22"})
|
39
|
+
args[:message]).and_return({ 'html_url' => 'http://example.com/pulls/22' })
|
42
40
|
expect { @it.open_pull_request(**args) }.to output(/Submitted PR/).to_stdout
|
43
41
|
end
|
44
42
|
|
45
43
|
it 'skips submitting PR if one has already been issued' do
|
46
44
|
pr = {
|
47
|
-
|
48
|
-
|
49
|
-
|
45
|
+
'title' => 'Test title',
|
46
|
+
'html_url' => 'https://example.com/pulls/44',
|
47
|
+
'number' => '44',
|
50
48
|
}
|
51
49
|
|
52
50
|
expect(@client).to receive(:pull_requests)
|
53
51
|
.with(args[:repo_path],
|
54
|
-
:
|
55
|
-
:
|
56
|
-
:
|
57
|
-
).and_return([pr])
|
52
|
+
state: 'open',
|
53
|
+
base: 'master',
|
54
|
+
head: "#{args[:namespace]}:#{args[:source_branch]}").and_return([pr])
|
58
55
|
expect { @it.open_pull_request(**args) }.to output("Skipped! 1 PRs found for branch 'test'\n").to_stdout
|
59
56
|
end
|
60
57
|
|
61
58
|
context 'when labels are set' do
|
62
|
-
let(:labels) { %w
|
59
|
+
let(:labels) { %w[HELLO WORLD] }
|
63
60
|
|
64
61
|
it 'adds labels to PR' do
|
65
|
-
allow(@client).to receive(:create_pull_request).and_return({
|
62
|
+
allow(@client).to receive(:create_pull_request).and_return({ 'html_url' => 'http://example.com/pulls/22',
|
63
|
+
'number' => '44', })
|
66
64
|
allow(@client).to receive(:pull_requests)
|
67
65
|
.with(args[:repo_path],
|
68
|
-
:
|
69
|
-
:
|
70
|
-
:
|
71
|
-
).and_return([])
|
66
|
+
state: 'open',
|
67
|
+
base: 'master',
|
68
|
+
head: "#{args[:namespace]}:#{args[:source_branch]}").and_return([])
|
72
69
|
expect(@client).to receive(:add_labels_to_an_issue)
|
73
70
|
.with(args[:repo_path],
|
74
|
-
|
75
|
-
[
|
76
|
-
|
77
|
-
|
71
|
+
'44',
|
72
|
+
%w[HELLO WORLD])
|
73
|
+
expect do
|
74
|
+
@it.open_pull_request(**args)
|
75
|
+
end.to output(/Attaching the following labels to PR 44: HELLO, WORLD/).to_stdout
|
78
76
|
end
|
79
77
|
end
|
80
78
|
end
|
@@ -4,8 +4,8 @@ require 'modulesync/git_service/gitlab'
|
|
4
4
|
|
5
5
|
describe ModuleSync::GitService::GitLab do
|
6
6
|
context '::open_pull_request' do
|
7
|
-
before
|
8
|
-
@client = double
|
7
|
+
before do
|
8
|
+
@client = double
|
9
9
|
allow(Gitlab::Client).to receive(:new).and_return(@client)
|
10
10
|
@it = ModuleSync::GitService::GitLab.new('test', 'https://gitlab.com/api/v4')
|
11
11
|
end
|
@@ -28,62 +28,59 @@ describe ModuleSync::GitService::GitLab do
|
|
28
28
|
it 'submits MR when --pr is set' do
|
29
29
|
allow(@client).to receive(:merge_requests)
|
30
30
|
.with(args[:repo_path],
|
31
|
-
:
|
32
|
-
:
|
33
|
-
:
|
34
|
-
).and_return([])
|
31
|
+
state: 'opened',
|
32
|
+
source_branch: args[:source_branch],
|
33
|
+
target_branch: 'master').and_return([])
|
35
34
|
|
36
35
|
expect(@client).to receive(:create_merge_request)
|
37
36
|
.with(args[:repo_path],
|
38
37
|
args[:title],
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
).and_return({"html_url" => "http://example.com/pulls/22"})
|
38
|
+
labels: [],
|
39
|
+
source_branch: args[:source_branch],
|
40
|
+
target_branch: 'master').and_return({ 'html_url' => 'http://example.com/pulls/22' })
|
43
41
|
|
44
42
|
expect { @it.open_pull_request(**args) }.to output(/Submitted MR/).to_stdout
|
45
43
|
end
|
46
44
|
|
47
45
|
it 'skips submitting MR if one has already been issued' do
|
48
46
|
mr = {
|
49
|
-
|
50
|
-
|
51
|
-
|
47
|
+
'title' => 'Test title',
|
48
|
+
'html_url' => 'https://example.com/pulls/44',
|
49
|
+
'iid' => '44',
|
52
50
|
}
|
53
51
|
|
54
52
|
expect(@client).to receive(:merge_requests)
|
55
53
|
.with(args[:repo_path],
|
56
|
-
:
|
57
|
-
:
|
58
|
-
:
|
59
|
-
).and_return([mr])
|
54
|
+
state: 'opened',
|
55
|
+
source_branch: args[:source_branch],
|
56
|
+
target_branch: 'master').and_return([mr])
|
60
57
|
|
61
58
|
expect { @it.open_pull_request(**args) }.to output("Skipped! 1 MRs found for branch 'test'\n").to_stdout
|
62
59
|
end
|
63
60
|
|
64
61
|
context 'when labels are set' do
|
65
|
-
let(:labels) { %w
|
62
|
+
let(:labels) { %w[HELLO WORLD] }
|
66
63
|
|
67
64
|
it 'adds labels to MR' do
|
68
|
-
mr = double
|
69
|
-
allow(mr).to receive(:iid).and_return(
|
65
|
+
mr = double
|
66
|
+
allow(mr).to receive(:iid).and_return('42')
|
70
67
|
|
71
68
|
expect(@client).to receive(:create_merge_request)
|
72
69
|
.with(args[:repo_path],
|
73
70
|
args[:title],
|
74
|
-
:
|
75
|
-
:
|
76
|
-
:
|
77
|
-
).and_return(mr)
|
71
|
+
labels: %w[HELLO WORLD],
|
72
|
+
source_branch: args[:source_branch],
|
73
|
+
target_branch: 'master').and_return(mr)
|
78
74
|
|
79
75
|
allow(@client).to receive(:merge_requests)
|
80
76
|
.with(args[:repo_path],
|
81
|
-
:
|
82
|
-
:
|
83
|
-
:
|
84
|
-
).and_return([])
|
77
|
+
state: 'opened',
|
78
|
+
source_branch: args[:source_branch],
|
79
|
+
target_branch: 'master').and_return([])
|
85
80
|
|
86
|
-
expect
|
81
|
+
expect do
|
82
|
+
@it.open_pull_request(**args)
|
83
|
+
end.to output(/Attached the following labels to MR 42: HELLO, WORLD/).to_stdout
|
87
84
|
end
|
88
85
|
end
|
89
86
|
end
|