modulesync 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 16cd854b2ba5a64f73b1051081fbf1e3bdbe39bbec2b7dacf5de3a3f37750625
4
- data.tar.gz: d45c398dd5e7fc20d4bbf257ca0303bda0faa91ea49d3b6804d34fdbb25e1175
3
+ metadata.gz: 139a0b0b011d17ff31b014560eb02ce6a57e62f2e45ffaa06c9acf778240b047
4
+ data.tar.gz: f1696a42bcf9cf44719ea8f7c5f5580481672e9c3dd920463f77f2f72d54a82a
5
5
  SHA512:
6
- metadata.gz: 38ae3613c9b28a0d679445350dcf6d625ad0db7156db8e26df7b4a4703a79713b471ce786d20d879a4bcdf8cd23830ac8277f259435f6fb191eede8a5a49ac9f
7
- data.tar.gz: 62cacbdc9b002371957bc732727774c79d3b5783280469e3a2a34379265b784a8b6c0a6bccf1ce47ceb4bccea27cdb0273933b86381a37d57fd39e011b382d49
6
+ metadata.gz: 22bf21a62e3c6e3c8df65bed7b1356af3dc656ba85ae885338b0f35b501c1217c5159918d2c21fcbe3c92c52d14ab2f561b876004eabec99ecaa81521c875c88
7
+ data.tar.gz: 751fdcd7d6ee62611f90659e21eb94a103ac6473c98b6907342441675232e1c946dc69ed925dff5e1f708dd4e5f8dca68e039b38600d7c73c9f919dc837a9aee
@@ -7,6 +7,7 @@ AllCops:
7
7
  - 'tmp/**/*'
8
8
  - 'pkg/**/*'
9
9
  - 'lib/monkey_patches.rb'
10
+ - 'spec/**/*'
10
11
 
11
12
  Style/HashSyntax:
12
13
  Enabled: false
@@ -6,10 +6,13 @@ dist: trusty
6
6
  script: 'bundle exec rake test'
7
7
  rvm:
8
8
  - 2.0
9
- - 2.1.9
10
- - 2.2.6
11
- - 2.3.3
12
- - 2.4.0
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.4.0
24
+ rvm: 2.7
22
25
  tags: true
23
26
  all_branches: true
24
27
  repo: voxpupuli/modulesync
@@ -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
@@ -3,4 +3,4 @@ source ENV['GEM_SOURCE'] || 'https://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  gem 'cucumber', '< 3.0' if RUBY_VERSION < '2.1'
6
- gem 'octokit', '~> 4.0'
6
+ gem 'octokit', '~> 4.9'
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
@@ -19,3 +19,4 @@ Cucumber::Rake::Task.new do |t|
19
19
  end
20
20
 
21
21
  task :test => %i[clean spec cucumber rubocop]
22
+ task :default => %i[test]
@@ -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
+ """
@@ -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, file)
36
- File.join(project_root, namespace, puppet_module, file)
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(module_file(options[:project_root], namespace, module_name, filename))
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 = Renderer.render(erb, configs)
99
- Renderer.sync(template, module_file(options[:project_root], namespace, module_name, filename))
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
- STDERR.puts "Error while rendering #{filename}"
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
- # We only do GitHub PR work if the GITHUB_TOKEN variable is set in the environment.
142
- repo_path = File.join(namespace, module_name)
143
- puts "Submitting PR '#{options[:pr_title]}' on GitHub to #{repo_path} - merges #{options[:branch]} into master"
144
- github = Octokit::Client.new(:access_token => GITHUB_TOKEN)
145
- pr = github.create_pull_request(repo_path, 'master', options[:branch], options[:pr_title], options[:message])
146
- puts "PR created at #{pr['html_url']}"
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
- # PR labels can either be a list in the YAML file or they can pass in a comma
149
- # separated list via the command line argument.
150
- pr_labels = Util.parse_list(options[:pr_labels])
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
- # We only assign labels to the PR if we've discovered a list > 1. The labels MUST
153
- # already exist. We DO NOT create missing labels.
154
- unless pr_labels.empty?
155
- puts "Attaching the following labels to PR #{pr['number']}: #{pr_labels.join(', ')}"
156
- github.add_labels_to_an_issue(repo_path, pr['number'], pr_labels)
157
- end
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
- STDERR.puts "Error while updating #{puppet_module}"
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]
@@ -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,
@@ -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)
@@ -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.0.0'
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.0.0
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: 2019-09-19 00:00:00.000000000 Z
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.0.6
196
+ rubygems_version: 3.1.2
197
197
  signing_key:
198
198
  specification_version: 4
199
199
  summary: Puppet Module Synchronizer