modulesync 1.3.0 → 2.1.1
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/.config/cucumber.yml +1 -0
- data/.github/workflows/ci.yml +29 -0
- data/.github/workflows/release.yml +31 -0
- data/.gitignore +1 -0
- data/.rubocop.yml +8 -1
- data/.rubocop_todo.yml +16 -35
- data/CHANGELOG.md +79 -1
- data/Gemfile +5 -1
- data/HISTORY.md +227 -0
- data/README.md +10 -10
- data/Rakefile +24 -0
- data/features/cli.feature +14 -6
- data/features/hook.feature +3 -5
- data/features/step_definitions/git_steps.rb +73 -35
- data/features/support/env.rb +4 -0
- data/features/update.feature +163 -341
- data/features/update/bad_context.feature +26 -0
- data/features/update/bump_version.feature +87 -0
- data/lib/modulesync.rb +60 -51
- data/lib/modulesync/cli.rb +5 -4
- data/lib/modulesync/cli/thor.rb +24 -0
- data/lib/modulesync/pr/github.rb +23 -13
- data/lib/modulesync/pr/gitlab.rb +26 -14
- data/lib/modulesync/puppet_module.rb +37 -0
- data/lib/modulesync/repository.rb +158 -0
- data/lib/modulesync/source_code.rb +57 -0
- data/lib/modulesync/util.rb +4 -1
- data/lib/monkey_patches.rb +9 -48
- data/modulesync.gemspec +4 -4
- data/spec/helpers/faker.rb +14 -0
- data/spec/helpers/faker/puppet_module_remote_repo.rb +146 -0
- data/spec/unit/modulesync_spec.rb +6 -2
- metadata +30 -10
- data/.travis.yml +0 -27
- data/lib/modulesync/git.rb +0 -194
@@ -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
|
+
"""
|
@@ -0,0 +1,87 @@
|
|
1
|
+
Feature: Bump a new version after an update
|
2
|
+
Scenario: Bump the module version, update changelog and tag it after an update that produces changes
|
3
|
+
Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
|
4
|
+
And the puppet module "puppet-test" from "fakenamespace" has a file named "CHANGELOG.md" with:
|
5
|
+
"""
|
6
|
+
## 1965-04-14 - Release 0.4.2
|
7
|
+
"""
|
8
|
+
And a file named "config_defaults.yml" with:
|
9
|
+
"""
|
10
|
+
---
|
11
|
+
new-file:
|
12
|
+
content: aruba
|
13
|
+
"""
|
14
|
+
And a directory named "moduleroot"
|
15
|
+
And a file named "moduleroot/new-file.erb" with:
|
16
|
+
"""
|
17
|
+
<%= @configs['content'] %>
|
18
|
+
"""
|
19
|
+
When I run `msync update --message "Add new-file" --bump --changelog --tag`
|
20
|
+
Then the exit status should be 0
|
21
|
+
And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba"
|
22
|
+
And the stdout should contain:
|
23
|
+
"""
|
24
|
+
Bumped to version 0.4.3
|
25
|
+
"""
|
26
|
+
And the stdout should contain:
|
27
|
+
"""
|
28
|
+
Tagging with 0.4.3
|
29
|
+
"""
|
30
|
+
And the file named "modules/fakenamespace/puppet-test/CHANGELOG.md" should contain "0.4.3"
|
31
|
+
And the puppet module "puppet-test" from "fakenamespace" should have 2 commits made by "Aruba"
|
32
|
+
And the puppet module "puppet-test" from "fakenamespace" should have a tag named "0.4.3"
|
33
|
+
|
34
|
+
Scenario: Bump the module version after an update that produces changes
|
35
|
+
Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
|
36
|
+
And a file named "config_defaults.yml" with:
|
37
|
+
"""
|
38
|
+
---
|
39
|
+
new-file:
|
40
|
+
content: aruba
|
41
|
+
"""
|
42
|
+
And a directory named "moduleroot"
|
43
|
+
And a file named "moduleroot/new-file.erb" with:
|
44
|
+
"""
|
45
|
+
<%= @configs['content'] %>
|
46
|
+
"""
|
47
|
+
When I run `msync update --message "Add new-file" --bump`
|
48
|
+
Then the exit status should be 0
|
49
|
+
And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba"
|
50
|
+
And the stdout should contain:
|
51
|
+
"""
|
52
|
+
Bumped to version 0.4.3
|
53
|
+
"""
|
54
|
+
And the puppet module "puppet-test" from "fakenamespace" should have 2 commits made by "Aruba"
|
55
|
+
And the puppet module "puppet-test" from "fakenamespace" should not have a tag named "0.4.3"
|
56
|
+
|
57
|
+
Scenario: Bump the module version with changelog update when no CHANGELOG.md is available
|
58
|
+
Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
|
59
|
+
And a file named "config_defaults.yml" with:
|
60
|
+
"""
|
61
|
+
---
|
62
|
+
new-file:
|
63
|
+
content: aruba
|
64
|
+
"""
|
65
|
+
And a directory named "moduleroot"
|
66
|
+
And a file named "moduleroot/new-file.erb" with:
|
67
|
+
"""
|
68
|
+
<%= @configs['content'] %>
|
69
|
+
"""
|
70
|
+
When I run `msync update --message "Add new-file" --bump --changelog`
|
71
|
+
Then the exit status should be 0
|
72
|
+
And the file named "modules/fakenamespace/puppet-test/new-file" should contain "aruba"
|
73
|
+
And the stdout should contain:
|
74
|
+
"""
|
75
|
+
Bumped to version 0.4.3
|
76
|
+
No CHANGELOG.md file found, not updating.
|
77
|
+
"""
|
78
|
+
And the file named "modules/fakenamespace/puppet-test/CHANGELOG.md" should not exist
|
79
|
+
And the puppet module "puppet-test" from "fakenamespace" should have 2 commits made by "Aruba"
|
80
|
+
|
81
|
+
Scenario: Dont bump the module version after an update that produces no changes
|
82
|
+
Given a basic setup with a puppet module "puppet-test" from "fakenamespace"
|
83
|
+
And a directory named "moduleroot"
|
84
|
+
When I run `msync update --message "Add new-file" --bump --tag`
|
85
|
+
Then the exit status should be 0
|
86
|
+
And the puppet module "puppet-test" from "fakenamespace" should have no commits made by "Aruba"
|
87
|
+
And the puppet module "puppet-test" from "fakenamespace" should not have a tag named "0.4.3"
|
data/lib/modulesync.rb
CHANGED
@@ -1,15 +1,19 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
require 'pathname'
|
3
|
+
|
3
4
|
require 'modulesync/cli'
|
4
5
|
require 'modulesync/constants'
|
5
|
-
require 'modulesync/git'
|
6
6
|
require 'modulesync/hook'
|
7
|
+
require 'modulesync/puppet_module'
|
7
8
|
require 'modulesync/renderer'
|
8
9
|
require 'modulesync/settings'
|
9
10
|
require 'modulesync/util'
|
11
|
+
|
10
12
|
require 'monkey_patches'
|
11
13
|
|
12
14
|
module ModuleSync # rubocop:disable Metrics/ModuleLength
|
15
|
+
class Error < StandardError; end
|
16
|
+
|
13
17
|
include Constants
|
14
18
|
|
15
19
|
def self.config_defaults
|
@@ -21,12 +25,12 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
21
25
|
}
|
22
26
|
end
|
23
27
|
|
24
|
-
def self.
|
25
|
-
|
28
|
+
def self.options
|
29
|
+
@options
|
26
30
|
end
|
27
31
|
|
28
|
-
def self.
|
29
|
-
File.join(
|
32
|
+
def self.local_file(config_path, file)
|
33
|
+
File.join(config_path, MODULE_FILES_DIR, file)
|
30
34
|
end
|
31
35
|
|
32
36
|
# List all template files.
|
@@ -39,10 +43,10 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
39
43
|
.collect { |p| p.chomp('.erb') }
|
40
44
|
.to_a
|
41
45
|
else
|
42
|
-
$
|
46
|
+
$stderr.puts "#{local_template_dir} does not exist." \
|
43
47
|
' Check that you are working in your module configs directory or' \
|
44
48
|
' that you have passed in the correct directory with -c.'
|
45
|
-
exit
|
49
|
+
exit 1
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
@@ -50,21 +54,20 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
50
54
|
file_list.map { |file| file.sub(/#{path}/, '') }
|
51
55
|
end
|
52
56
|
|
53
|
-
def self.managed_modules
|
57
|
+
def self.managed_modules
|
58
|
+
config_file = config_path(options[:managed_modules_conf], options)
|
59
|
+
filter = options[:filter]
|
60
|
+
negative_filter = options[:negative_filter]
|
61
|
+
|
54
62
|
managed_modules = Util.parse_config(config_file)
|
55
63
|
if managed_modules.empty?
|
56
|
-
$
|
64
|
+
$stderr.puts "No modules found in #{config_file}." \
|
57
65
|
' Check that you specified the right :configs directory and :managed_modules_conf file.'
|
58
|
-
exit
|
66
|
+
exit 1
|
59
67
|
end
|
60
68
|
managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
|
61
69
|
managed_modules.reject! { |m| m =~ Regexp.new(negative_filter) } unless negative_filter.nil?
|
62
|
-
managed_modules
|
63
|
-
end
|
64
|
-
|
65
|
-
def self.module_name(module_name, default_namespace)
|
66
|
-
return [default_namespace, module_name] unless module_name.include?('/')
|
67
|
-
ns, mod = module_name.split('/')
|
70
|
+
managed_modules.map { |given_name, options| PuppetModule.new(given_name, options) }
|
68
71
|
end
|
69
72
|
|
70
73
|
def self.hook(options)
|
@@ -78,11 +81,11 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
78
81
|
end
|
79
82
|
end
|
80
83
|
|
81
|
-
def self.manage_file(filename, settings, options)
|
84
|
+
def self.manage_file(puppet_module, filename, settings, options)
|
82
85
|
namespace = settings.additional_settings[:namespace]
|
83
86
|
module_name = settings.additional_settings[:puppet_module]
|
84
87
|
configs = settings.build_file_configs(filename)
|
85
|
-
target_file =
|
88
|
+
target_file = puppet_module.path(filename)
|
86
89
|
if configs['delete']
|
87
90
|
Renderer.remove(target_file)
|
88
91
|
else
|
@@ -92,49 +95,52 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
92
95
|
# Meta data passed to the template as @metadata[:name]
|
93
96
|
metadata = {
|
94
97
|
:module_name => module_name,
|
95
|
-
:workdir =>
|
98
|
+
:workdir => puppet_module.working_directory,
|
96
99
|
:target_file => target_file,
|
97
100
|
}
|
98
101
|
template = Renderer.render(erb, configs, metadata)
|
99
102
|
Renderer.sync(template, target_file)
|
100
|
-
rescue
|
101
|
-
$stderr.puts "Error while rendering #{filename}"
|
103
|
+
rescue StandardError => e
|
104
|
+
$stderr.puts "#{puppet_module.given_name}: Error while rendering file: '#{filename}'"
|
102
105
|
raise
|
103
106
|
end
|
104
107
|
end
|
105
108
|
end
|
106
109
|
|
107
|
-
def self.manage_module(puppet_module, module_files,
|
108
|
-
|
109
|
-
|
110
|
-
default_namespace = module_options[:namespace]
|
111
|
-
end
|
112
|
-
namespace, module_name = module_name(puppet_module, default_namespace)
|
113
|
-
git_repo = File.join(namespace, module_name)
|
114
|
-
unless options[:offline]
|
115
|
-
Git.pull(options[:git_base], git_repo, options[:branch], options[:project_root], module_options || {})
|
116
|
-
end
|
110
|
+
def self.manage_module(puppet_module, module_files, defaults)
|
111
|
+
puts "Syncing '#{puppet_module.given_name}'"
|
112
|
+
puppet_module.repository.prepare_workspace(options[:branch]) unless options[:offline]
|
117
113
|
|
118
|
-
module_configs = Util.parse_config(
|
114
|
+
module_configs = Util.parse_config puppet_module.path(MODULE_CONF_FILE)
|
119
115
|
settings = Settings.new(defaults[GLOBAL_DEFAULTS_KEY] || {},
|
120
116
|
defaults,
|
121
117
|
module_configs[GLOBAL_DEFAULTS_KEY] || {},
|
122
118
|
module_configs,
|
123
|
-
:puppet_module =>
|
119
|
+
:puppet_module => puppet_module.repository_name,
|
124
120
|
:git_base => options[:git_base],
|
125
|
-
:namespace =>
|
121
|
+
:namespace => puppet_module.repository_namespace)
|
122
|
+
|
126
123
|
settings.unmanaged_files(module_files).each do |filename|
|
127
|
-
$stdout.puts "Not managing #{filename} in #{
|
124
|
+
$stdout.puts "Not managing '#{filename}' in '#{puppet_module.given_name}'"
|
128
125
|
end
|
129
126
|
|
130
127
|
files_to_manage = settings.managed_files(module_files)
|
131
|
-
files_to_manage.each { |filename| manage_file(filename, settings, options) }
|
128
|
+
files_to_manage.each { |filename| manage_file(puppet_module, filename, settings, options) }
|
132
129
|
|
133
130
|
if options[:noop]
|
134
|
-
|
131
|
+
puts "Using no-op. Files in '#{puppet_module.given_name}' may be changed but will not be committed."
|
132
|
+
puppet_module.repository.show_changes(options)
|
133
|
+
options[:pr] && \
|
134
|
+
pr(puppet_module).manage(puppet_module.repository_namespace, puppet_module.repository_name, options)
|
135
135
|
elsif !options[:offline]
|
136
|
-
pushed =
|
137
|
-
|
136
|
+
pushed = puppet_module.repository.submit_changes(files_to_manage, options)
|
137
|
+
# Only bump/tag if pushing didn't fail (i.e. there were changes)
|
138
|
+
if pushed && options[:bump]
|
139
|
+
new = puppet_module.bump(options[:message], options[:changelog])
|
140
|
+
puppet_module.repository.tag(new, options[:tag_pattern]) if options[:tag]
|
141
|
+
end
|
142
|
+
pushed && options[:pr] && \
|
143
|
+
pr(puppet_module).manage(puppet_module.repository_namespace, puppet_module.repository_name, options)
|
138
144
|
end
|
139
145
|
end
|
140
146
|
|
@@ -147,9 +153,10 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
147
153
|
self.class.config_path(file, options)
|
148
154
|
end
|
149
155
|
|
150
|
-
def self.update(
|
151
|
-
options = config_defaults.merge(
|
156
|
+
def self.update(cli_options)
|
157
|
+
@options = config_defaults.merge(cli_options)
|
152
158
|
defaults = Util.parse_config(config_path(CONF_FILE, options))
|
159
|
+
|
153
160
|
if options[:pr]
|
154
161
|
unless options[:branch]
|
155
162
|
$stderr.puts 'A branch must be specified with --branch to use --pr!'
|
@@ -163,26 +170,28 @@ module ModuleSync # rubocop:disable Metrics/ModuleLength
|
|
163
170
|
local_files = find_template_files(local_template_dir)
|
164
171
|
module_files = relative_names(local_files, local_template_dir)
|
165
172
|
|
166
|
-
managed_modules = self.managed_modules(config_path(options[:managed_modules_conf], options),
|
167
|
-
options[:filter],
|
168
|
-
options[:negative_filter])
|
169
|
-
|
170
173
|
errors = false
|
171
174
|
# managed_modules is either an array or a hash
|
172
|
-
managed_modules.each do |puppet_module
|
175
|
+
managed_modules.each do |puppet_module|
|
173
176
|
begin
|
174
|
-
manage_module(puppet_module, module_files,
|
175
|
-
rescue
|
176
|
-
|
177
|
+
manage_module(puppet_module, module_files, defaults)
|
178
|
+
rescue ModuleSync::Error, Git::GitExecuteError => e
|
179
|
+
message = e.message || "Error during '#{options[:command]}'"
|
180
|
+
$stderr.puts "#{puppet_module.given_name}: #{message}"
|
181
|
+
exit 1 unless options[:skip_broken]
|
182
|
+
errors = true
|
183
|
+
$stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
|
184
|
+
rescue StandardError => e
|
177
185
|
raise unless options[:skip_broken]
|
178
186
|
errors = true
|
179
|
-
$stdout.puts "Skipping #{puppet_module} as update process failed"
|
187
|
+
$stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
|
180
188
|
end
|
181
189
|
end
|
182
190
|
exit 1 if errors && options[:fail_on_warnings]
|
183
191
|
end
|
184
192
|
|
185
|
-
def self.pr(
|
193
|
+
def self.pr(puppet_module)
|
194
|
+
module_options = puppet_module.options
|
186
195
|
github_conf = module_options[:github]
|
187
196
|
gitlab_conf = module_options[:gitlab]
|
188
197
|
|
data/lib/modulesync/cli.rb
CHANGED
@@ -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
|
-
|
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.
|
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
|
data/lib/modulesync/pr/github.rb
CHANGED
@@ -15,26 +15,36 @@ module ModuleSync
|
|
15
15
|
|
16
16
|
def manage(namespace, module_name, options)
|
17
17
|
repo_path = File.join(namespace, module_name)
|
18
|
-
|
18
|
+
branch = options[:remote_branch] || options[:branch]
|
19
|
+
head = "#{namespace}:#{branch}"
|
19
20
|
target_branch = options[:pr_target_branch] || 'master'
|
20
21
|
|
21
|
-
|
22
|
-
if pull_requests.empty?
|
23
|
-
pr = @api.create_pull_request(repo_path,
|
24
|
-
target_branch,
|
25
|
-
options[:branch],
|
26
|
-
options[:pr_title],
|
27
|
-
options[:message])
|
22
|
+
if options[:noop]
|
28
23
|
$stdout.puts \
|
29
|
-
"
|
30
|
-
|
24
|
+
"Using no-op. Would submit PR '#{options[:pr_title]}' to #{repo_path} " \
|
25
|
+
"- merges #{branch} into #{target_branch}"
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
29
|
+
pull_requests = @api.pull_requests(repo_path,
|
30
|
+
:state => 'open',
|
31
|
+
:base => target_branch,
|
32
|
+
:head => head)
|
33
|
+
unless pull_requests.empty?
|
31
34
|
# Skip creating the PR if it exists already.
|
32
|
-
$stdout.puts "Skipped! #{pull_requests.length} PRs found for branch #{
|
35
|
+
$stdout.puts "Skipped! #{pull_requests.length} PRs found for branch #{branch}"
|
36
|
+
return
|
33
37
|
end
|
34
38
|
|
35
|
-
# PR labels can either be a list in the YAML file or they can pass in a comma
|
36
|
-
# separated list via the command line argument.
|
37
39
|
pr_labels = ModuleSync::Util.parse_list(options[:pr_labels])
|
40
|
+
pr = @api.create_pull_request(repo_path,
|
41
|
+
target_branch,
|
42
|
+
branch,
|
43
|
+
options[:pr_title],
|
44
|
+
options[:message])
|
45
|
+
$stdout.puts \
|
46
|
+
"Submitted PR '#{options[:pr_title]}' to #{repo_path} " \
|
47
|
+
"- merges #{branch} into #{target_branch}"
|
38
48
|
|
39
49
|
# We only assign labels to the PR if we've discovered a list > 1. The labels MUST
|
40
50
|
# already exist. We DO NOT create missing labels.
|
data/lib/modulesync/pr/gitlab.rb
CHANGED
@@ -15,27 +15,39 @@ module ModuleSync
|
|
15
15
|
|
16
16
|
def manage(namespace, module_name, options)
|
17
17
|
repo_path = File.join(namespace, module_name)
|
18
|
-
|
19
|
-
head = "#{namespace}:#{
|
18
|
+
branch = options[:remote_branch] || options[:branch]
|
19
|
+
head = "#{namespace}:#{branch}"
|
20
20
|
target_branch = options[:pr_target_branch] || 'master'
|
21
|
+
|
22
|
+
if options[:noop]
|
23
|
+
$stdout.puts \
|
24
|
+
"Using no-op. Would submit MR '#{options[:pr_title]}' to #{repo_path} " \
|
25
|
+
"- merges #{branch} into #{target_branch}"
|
26
|
+
return
|
27
|
+
end
|
28
|
+
|
21
29
|
merge_requests = @api.merge_requests(repo_path,
|
22
30
|
:state => 'opened',
|
23
31
|
:source_branch => head,
|
24
32
|
:target_branch => target_branch)
|
25
|
-
|
26
|
-
mr_labels = ModuleSync::Util.parse_list(options[:pr_labels])
|
27
|
-
mr = @api.create_merge_request(repo_path, options[:pr_title],
|
28
|
-
:source_branch => options[:branch],
|
29
|
-
:target_branch => target_branch,
|
30
|
-
:labels => mr_labels)
|
31
|
-
$stdout.puts \
|
32
|
-
"Submitted MR '#{options[:pr_title]}' to #{repo_path} - merges #{options[:branch]} into #{target_branch}"
|
33
|
-
return if mr_labels.empty?
|
34
|
-
$stdout.puts "Attached the following labels to MR #{mr.iid}: #{mr_labels.join(', ')}"
|
35
|
-
else
|
33
|
+
unless merge_requests.empty?
|
36
34
|
# Skip creating the MR if it exists already.
|
37
|
-
$stdout.puts "Skipped! #{merge_requests.length} MRs found for branch #{
|
35
|
+
$stdout.puts "Skipped! #{merge_requests.length} MRs found for branch #{branch}"
|
36
|
+
return
|
38
37
|
end
|
38
|
+
|
39
|
+
mr_labels = ModuleSync::Util.parse_list(options[:pr_labels])
|
40
|
+
mr = @api.create_merge_request(repo_path,
|
41
|
+
options[:pr_title],
|
42
|
+
:source_branch => branch,
|
43
|
+
:target_branch => target_branch,
|
44
|
+
:labels => mr_labels)
|
45
|
+
$stdout.puts \
|
46
|
+
"Submitted MR '#{options[:pr_title]}' to #{repo_path} " \
|
47
|
+
"- merges #{branch} into #{target_branch}"
|
48
|
+
|
49
|
+
return if mr_labels.empty?
|
50
|
+
$stdout.puts "Attached the following labels to MR #{mr.iid}: #{mr_labels.join(', ')}"
|
39
51
|
end
|
40
52
|
end
|
41
53
|
end
|