modulesync 1.0.0 → 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 +4 -4
- data/.rubocop.yml +1 -0
- data/.travis.yml +8 -5
- data/CHANGELOG.md +8 -0
- data/Gemfile +1 -1
- data/README.md +17 -0
- data/Rakefile +1 -0
- data/features/update.feature +33 -0
- data/lib/modulesync.rb +49 -32
- data/lib/modulesync/cli.rb +1 -0
- data/lib/modulesync/renderer.rb +4 -3
- data/modulesync.gemspec +2 -2
- data/spec/unit/modulesync_spec.rb +55 -0
- metadata +7 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 139a0b0b011d17ff31b014560eb02ce6a57e62f2e45ffaa06c9acf778240b047
|
4
|
+
data.tar.gz: f1696a42bcf9cf44719ea8f7c5f5580481672e9c3dd920463f77f2f72d54a82a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 22bf21a62e3c6e3c8df65bed7b1356af3dc656ba85ae885338b0f35b501c1217c5159918d2c21fcbe3c92c52d14ab2f561b876004eabec99ecaa81521c875c88
|
7
|
+
data.tar.gz: 751fdcd7d6ee62611f90659e21eb94a103ac6473c98b6907342441675232e1c946dc69ed925dff5e1f708dd4e5f8dca68e039b38600d7c73c9f919dc837a9aee
|
data/.rubocop.yml
CHANGED
data/.travis.yml
CHANGED
@@ -6,10 +6,13 @@ dist: trusty
|
|
6
6
|
script: 'bundle exec rake test'
|
7
7
|
rvm:
|
8
8
|
- 2.0
|
9
|
-
- 2.1
|
10
|
-
- 2.2
|
11
|
-
- 2.3
|
12
|
-
- 2.4
|
9
|
+
- 2.1
|
10
|
+
- 2.2
|
11
|
+
- 2.3
|
12
|
+
- 2.4
|
13
|
+
- 2.5
|
14
|
+
- 2.6
|
15
|
+
- 2.7
|
13
16
|
notifications:
|
14
17
|
email: false
|
15
18
|
deploy:
|
@@ -18,7 +21,7 @@ deploy:
|
|
18
21
|
secure: "Tbf1EbLEobIIox+fftJZADZsfQQ6kl0urcMNetK7NJzFo/negD/WyJIUj3kro/B7buyYADEjTui/JR4o8EPbugfM3ie5vYOd5k3AesSzbdr4BSwGe/cGbGOB7/PZuGfFLkb94/FiCU2mIwibkbh1rHWGlBoPj7ntL0+5ZtdvsM4="
|
19
22
|
gem: modulesync
|
20
23
|
on:
|
21
|
-
rvm: 2.
|
24
|
+
rvm: 2.7
|
22
25
|
tags: true
|
23
26
|
all_branches: true
|
24
27
|
repo: voxpupuli/modulesync
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## 2020-05-01 - 1.1.0
|
4
|
+
|
5
|
+
This release provides metadata in the ERB template scope which makes it easy to read files from inside the module. A possible application is reading metadata.json and generating CI configs based on that.
|
6
|
+
|
7
|
+
* Add metadata to ERB template scope - [#168](https://github.com/voxpupuli/modulesync/pull/168)
|
8
|
+
* Skip issuing a PR if one already exists for -b option - [#171](https://github.com/voxpupuli/modulesync/pull/171)
|
9
|
+
* Correct the type on the pr-labels option to prevent a deprecation warning - [#173](https://github.com/voxpupuli/modulesync/pull/173)
|
10
|
+
|
3
11
|
## 2019-09-19 - 1.0.0
|
4
12
|
|
5
13
|
This is the first stable release! 🎉
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -389,6 +389,23 @@ As mentioned, files in the moduleroot directory must be ERB templates (they must
|
|
389
389
|
<%= @configs[:puppet_module] %>
|
390
390
|
```
|
391
391
|
|
392
|
+
Alternatively some meta data is passed to the template. This will allow you to add custom Ruby extensions inside the
|
393
|
+
template, reading other files from the module, to make the template system more adaptive.
|
394
|
+
|
395
|
+
```erb
|
396
|
+
module: <%= @metadata[:module_name] %>
|
397
|
+
target: <%= @metadata[:target_file] %>
|
398
|
+
workdir: <%= @metadata[:workdir] %>
|
399
|
+
```
|
400
|
+
|
401
|
+
Will result in something like:
|
402
|
+
|
403
|
+
```
|
404
|
+
module: puppet-test
|
405
|
+
target: modules/github-org/puppet-test/test
|
406
|
+
workdir: modules/github-org/puppet-test
|
407
|
+
```
|
408
|
+
|
392
409
|
The Templates
|
393
410
|
-------------
|
394
411
|
|
data/Rakefile
CHANGED
data/features/update.feature
CHANGED
@@ -922,3 +922,36 @@ Feature: update
|
|
922
922
|
When I run `msync update -m "Update Gemfile"`
|
923
923
|
Then the exit status should be 0
|
924
924
|
Then the output should contain "Using repository's default branch: develop"
|
925
|
+
|
926
|
+
Scenario: Adding a new file from a template using meta data
|
927
|
+
And a file named "config_defaults.yml" with:
|
928
|
+
"""
|
929
|
+
---
|
930
|
+
"""
|
931
|
+
Given a file named "managed_modules.yml" with:
|
932
|
+
"""
|
933
|
+
---
|
934
|
+
- puppet-test
|
935
|
+
"""
|
936
|
+
And a file named "modulesync.yml" with:
|
937
|
+
"""
|
938
|
+
---
|
939
|
+
namespace: maestrodev
|
940
|
+
git_base: https://github.com/
|
941
|
+
"""
|
942
|
+
And a directory named "moduleroot"
|
943
|
+
And a file named "moduleroot/test.erb" with:
|
944
|
+
"""
|
945
|
+
module: <%= @metadata[:module_name] %>
|
946
|
+
target: <%= @metadata[:target_file] %>
|
947
|
+
workdir: <%= @metadata[:workdir] %>
|
948
|
+
"""
|
949
|
+
When I run `msync update --noop`
|
950
|
+
Then the exit status should be 0
|
951
|
+
Given I run `cat modules/maestrodev/puppet-test/test`
|
952
|
+
Then the output should contain:
|
953
|
+
"""
|
954
|
+
module: puppet-test
|
955
|
+
target: modules/maestrodev/puppet-test/test
|
956
|
+
workdir: modules/maestrodev/puppet-test
|
957
|
+
"""
|
data/lib/modulesync.rb
CHANGED
@@ -16,7 +16,7 @@ Octokit.configure do |c|
|
|
16
16
|
c.api_endpoint = ENV.fetch('GITHUB_BASE_URL', 'https://api.github.com')
|
17
17
|
end
|
18
18
|
|
19
|
-
module ModuleSync
|
19
|
+
module ModuleSync # rubocop:disable Metrics/ModuleLength
|
20
20
|
include Constants
|
21
21
|
|
22
22
|
def self.config_defaults
|
@@ -32,8 +32,8 @@ module ModuleSync
|
|
32
32
|
File.join(config_path, MODULE_FILES_DIR, file)
|
33
33
|
end
|
34
34
|
|
35
|
-
def self.module_file(project_root, namespace, puppet_module,
|
36
|
-
File.join(project_root, namespace, puppet_module,
|
35
|
+
def self.module_file(project_root, namespace, puppet_module, *parts)
|
36
|
+
File.join(project_root, namespace, puppet_module, *parts)
|
37
37
|
end
|
38
38
|
|
39
39
|
# List all template files.
|
@@ -46,7 +46,7 @@ module ModuleSync
|
|
46
46
|
.collect { |p| p.chomp('.erb') }
|
47
47
|
.to_a
|
48
48
|
else
|
49
|
-
puts "#{local_template_dir} does not exist." \
|
49
|
+
$stdout.puts "#{local_template_dir} does not exist." \
|
50
50
|
' Check that you are working in your module configs directory or' \
|
51
51
|
' that you have passed in the correct directory with -c.'
|
52
52
|
exit
|
@@ -60,7 +60,7 @@ module ModuleSync
|
|
60
60
|
def self.managed_modules(config_file, filter, negative_filter)
|
61
61
|
managed_modules = Util.parse_config(config_file)
|
62
62
|
if managed_modules.empty?
|
63
|
-
puts "No modules found in #{config_file}." \
|
63
|
+
$stdout.puts "No modules found in #{config_file}." \
|
64
64
|
' Check that you specified the right :configs directory and :managed_modules_conf file.'
|
65
65
|
exit
|
66
66
|
end
|
@@ -89,27 +89,29 @@ module ModuleSync
|
|
89
89
|
namespace = settings.additional_settings[:namespace]
|
90
90
|
module_name = settings.additional_settings[:puppet_module]
|
91
91
|
configs = settings.build_file_configs(filename)
|
92
|
+
target_file = module_file(options[:project_root], namespace, module_name, filename)
|
92
93
|
if configs['delete']
|
93
|
-
Renderer.remove(
|
94
|
+
Renderer.remove(target_file)
|
94
95
|
else
|
95
96
|
templatename = local_file(options[:configs], filename)
|
96
97
|
begin
|
97
98
|
erb = Renderer.build(templatename)
|
98
|
-
template
|
99
|
-
|
99
|
+
# Meta data passed to the template as @metadata[:name]
|
100
|
+
metadata = {
|
101
|
+
:module_name => module_name,
|
102
|
+
:workdir => module_file(options[:project_root], namespace, module_name),
|
103
|
+
:target_file => target_file,
|
104
|
+
}
|
105
|
+
template = Renderer.render(erb, configs, metadata)
|
106
|
+
Renderer.sync(template, target_file)
|
100
107
|
rescue # rubocop:disable Lint/RescueWithoutErrorClass
|
101
|
-
|
108
|
+
$stderr.puts "Error while rendering #{filename}"
|
102
109
|
raise
|
103
110
|
end
|
104
111
|
end
|
105
112
|
end
|
106
113
|
|
107
114
|
def self.manage_module(puppet_module, module_files, module_options, defaults, options)
|
108
|
-
if options[:pr] && !GITHUB_TOKEN
|
109
|
-
STDERR.puts 'Environment variable GITHUB_TOKEN must be set to use --pr!'
|
110
|
-
raise unless options[:skip_broken]
|
111
|
-
end
|
112
|
-
|
113
115
|
namespace, module_name = module_name(puppet_module, options[:namespace])
|
114
116
|
git_repo = File.join(namespace, module_name)
|
115
117
|
unless options[:offline]
|
@@ -125,7 +127,7 @@ module ModuleSync
|
|
125
127
|
:git_base => options[:git_base],
|
126
128
|
:namespace => namespace)
|
127
129
|
settings.unmanaged_files(module_files).each do |filename|
|
128
|
-
puts "Not managing #{filename} in #{module_name}"
|
130
|
+
$stdout.puts "Not managing #{filename} in #{module_name}"
|
129
131
|
end
|
130
132
|
|
131
133
|
files_to_manage = settings.managed_files(module_files)
|
@@ -138,24 +140,39 @@ module ModuleSync
|
|
138
140
|
pushed = Git.update(git_repo, files_to_manage, options)
|
139
141
|
return nil unless pushed && options[:pr]
|
140
142
|
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
143
|
+
manage_pr(namespace, module_name, options)
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def self.manage_pr(namespace, module_name, options)
|
148
|
+
if options[:pr] && GITHUB_TOKEN.empty?
|
149
|
+
$stderr.puts 'Environment variable GITHUB_TOKEN must be set to use --pr!'
|
150
|
+
raise unless options[:skip_broken]
|
151
|
+
end
|
147
152
|
|
148
|
-
|
149
|
-
|
150
|
-
|
153
|
+
# We only do GitHub PR work if the GITHUB_TOKEN variable is set in the environment.
|
154
|
+
repo_path = File.join(namespace, module_name)
|
155
|
+
github = Octokit::Client.new(:access_token => GITHUB_TOKEN)
|
151
156
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
157
|
+
# Skip creating the PR if it exists already.
|
158
|
+
head = "#{namespace}:#{options[:branch]}"
|
159
|
+
pull_requests = github.pull_requests(repo_path, :state => 'open', :base => 'master', :head => head)
|
160
|
+
if pull_requests.empty?
|
161
|
+
pr = github.create_pull_request(repo_path, 'master', options[:branch], options[:pr_title], options[:message])
|
162
|
+
$stdout.puts "Submitted PR '#{options[:pr_title]}' to #{repo_path} - merges #{options[:branch]} into master"
|
163
|
+
else
|
164
|
+
$stdout.puts "Skipped! #{pull_requests.length} PRs found for branch #{options[:branch]}"
|
158
165
|
end
|
166
|
+
|
167
|
+
# PR labels can either be a list in the YAML file or they can pass in a comma
|
168
|
+
# separated list via the command line argument.
|
169
|
+
pr_labels = Util.parse_list(options[:pr_labels])
|
170
|
+
|
171
|
+
# We only assign labels to the PR if we've discovered a list > 1. The labels MUST
|
172
|
+
# already exist. We DO NOT create missing labels.
|
173
|
+
return if pr_labels.empty?
|
174
|
+
$stdout.puts "Attaching the following labels to PR #{pr['number']}: #{pr_labels.join(', ')}"
|
175
|
+
github.add_labels_to_an_issue(repo_path, pr['number'], pr_labels)
|
159
176
|
end
|
160
177
|
|
161
178
|
def self.update(options)
|
@@ -176,10 +193,10 @@ module ModuleSync
|
|
176
193
|
begin
|
177
194
|
manage_module(puppet_module, module_files, module_options, defaults, options)
|
178
195
|
rescue # rubocop:disable Lint/RescueWithoutErrorClass
|
179
|
-
|
196
|
+
$stderr.puts "Error while updating #{puppet_module}"
|
180
197
|
raise unless options[:skip_broken]
|
181
198
|
errors = true
|
182
|
-
puts "Skipping #{puppet_module} as update process failed"
|
199
|
+
$stdout.puts "Skipping #{puppet_module} as update process failed"
|
183
200
|
end
|
184
201
|
end
|
185
202
|
exit 1 if errors && options[:fail_on_warnings]
|
data/lib/modulesync/cli.rb
CHANGED
@@ -96,6 +96,7 @@ module ModuleSync
|
|
96
96
|
:desc => 'Title of GitHub PR',
|
97
97
|
:default => CLI.defaults[:pr_title] || 'Update to module template files'
|
98
98
|
option :pr_labels,
|
99
|
+
:type => :array,
|
99
100
|
:desc => 'Labels to add to the GitHub PR',
|
100
101
|
:default => CLI.defaults[:pr_labels] || []
|
101
102
|
option :offline,
|
data/lib/modulesync/renderer.rb
CHANGED
@@ -4,8 +4,9 @@ require 'find'
|
|
4
4
|
module ModuleSync
|
5
5
|
module Renderer
|
6
6
|
class ForgeModuleFile
|
7
|
-
def initialize(configs = {})
|
7
|
+
def initialize(configs = {}, metadata = {})
|
8
8
|
@configs = configs
|
9
|
+
@metadata = metadata
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
@@ -26,8 +27,8 @@ module ModuleSync
|
|
26
27
|
File.delete(file) if File.exist?(file)
|
27
28
|
end
|
28
29
|
|
29
|
-
def self.render(_template, configs = {})
|
30
|
-
ForgeModuleFile.new(configs).render
|
30
|
+
def self.render(_template, configs = {}, metadata = {})
|
31
|
+
ForgeModuleFile.new(configs, metadata).render
|
31
32
|
end
|
32
33
|
|
33
34
|
def self.sync(template, target_name)
|
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 = '1.
|
6
|
+
spec.version = '1.1.0'
|
7
7
|
spec.authors = ['Vox Pupuli']
|
8
8
|
spec.email = ['voxpupuli@groups.io']
|
9
9
|
spec.summary = 'Puppet Module Synchronizer'
|
@@ -17,7 +17,7 @@ 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'
|
20
|
+
spec.add_development_dependency 'aruba', '~> 0.14'
|
21
21
|
spec.add_development_dependency 'bundler'
|
22
22
|
spec.add_development_dependency 'rake'
|
23
23
|
spec.add_development_dependency 'rspec'
|
@@ -11,4 +11,59 @@ describe ModuleSync do
|
|
11
11
|
ModuleSync.update(options)
|
12
12
|
end
|
13
13
|
end
|
14
|
+
|
15
|
+
context '::manage_pr' do
|
16
|
+
before(:each) do
|
17
|
+
stub_const('GITHUB_TOKEN', 'test')
|
18
|
+
@git_repo = 'test/modulesync'
|
19
|
+
@namespace, @repo_name = @git_repo.split('/')
|
20
|
+
@options = {
|
21
|
+
:pr => true,
|
22
|
+
:pr_title => 'Test PR is submitted',
|
23
|
+
:branch => 'test',
|
24
|
+
:message => 'Hello world',
|
25
|
+
:pr_auto_merge => false,
|
26
|
+
}
|
27
|
+
|
28
|
+
@client = double()
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'rasies an error when GITHUB_TOKEN not set for PRs' do
|
32
|
+
stub_const('GITHUB_TOKEN', '')
|
33
|
+
options = {:pr => true, :skip_broken => false}
|
34
|
+
|
35
|
+
expect { ModuleSync.manage_pr(@namespace, @repo_name, options) }.to raise_error(RuntimeError).and output(/GITHUB_TOKEN/).to_stderr
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'submits PR when --pr is set' do
|
39
|
+
allow(Octokit::Client).to receive(:new).and_return(@client)
|
40
|
+
allow(@client).to receive(:pull_requests).with(@git_repo, :state => 'open', :base => 'master', :head => "#{@namespace}:#{@options[:branch]}").and_return([])
|
41
|
+
expect(@client).to receive(:create_pull_request).with(@git_repo, 'master', @options[:branch], @options[:pr_title], @options[:message]).and_return({"html_url" => "http://example.com/pulls/22"})
|
42
|
+
expect { ModuleSync.manage_pr(@namespace, @repo_name, @options) }.to output(/Submitted PR/).to_stdout
|
43
|
+
end
|
44
|
+
|
45
|
+
it 'skips submitting PR if one has already been issued' do
|
46
|
+
allow(Octokit::Client).to receive(:new).and_return(@client)
|
47
|
+
|
48
|
+
pr = {
|
49
|
+
"title" => "Test title",
|
50
|
+
"html_url" => "https://example.com/pulls/44",
|
51
|
+
"number" => "44"
|
52
|
+
}
|
53
|
+
|
54
|
+
expect(@client).to receive(:pull_requests).with(@git_repo, :state => 'open', :base => 'master', :head => "#{@namespace}:#{@options[:branch]}").and_return([pr])
|
55
|
+
expect { ModuleSync.manage_pr(@namespace, @repo_name, @options) }.to output(/Skipped! 1 PRs found for branch test/).to_stdout
|
56
|
+
end
|
57
|
+
|
58
|
+
it 'adds labels to PR when --pr-labels is set' do
|
59
|
+
@options[:pr_labels] = "HELLO,WORLD"
|
60
|
+
|
61
|
+
allow(Octokit::Client).to receive(:new).and_return(@client)
|
62
|
+
allow(@client).to receive(:create_pull_request).and_return({"html_url" => "http://example.com/pulls/22", "number" => "44"})
|
63
|
+
allow(@client).to receive(:pull_requests).with(@git_repo, :state => 'open', :base => 'master', :head => "#{@namespace}:#{@options[:branch]}").and_return([])
|
64
|
+
|
65
|
+
expect(@client).to receive(:add_labels_to_an_issue).with(@git_repo, "44", ["HELLO", "WORLD"])
|
66
|
+
expect { ModuleSync.manage_pr(@namespace, @repo_name, @options) }.to output(/Attaching the following labels to PR 44: HELLO, WORLD/).to_stdout
|
67
|
+
end
|
68
|
+
end
|
14
69
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: modulesync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.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:
|
11
|
+
date: 2020-05-04 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
|
-
version: '0'
|
19
|
+
version: '0.14'
|
20
20
|
type: :development
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '0'
|
26
|
+
version: '0.14'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -193,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
193
193
|
- !ruby/object:Gem::Version
|
194
194
|
version: '0'
|
195
195
|
requirements: []
|
196
|
-
rubygems_version: 3.
|
196
|
+
rubygems_version: 3.1.2
|
197
197
|
signing_key:
|
198
198
|
specification_version: 4
|
199
199
|
summary: Puppet Module Synchronizer
|