pdksync 0.5.0 → 0.6.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.
data/Rakefile CHANGED
@@ -1,17 +1,23 @@
1
- require 'pdksync/rake_tasks'
2
- require 'github_changelog_generator/task'
3
- require 'rubocop/rake_task'
1
+ require "pdksync/rake_tasks"
2
+ require "github_changelog_generator/task"
3
+ require "rubocop/rake_task"
4
+ require "rspec/core/rake_task"
5
+ require "bundler/gem_tasks"
4
6
 
5
7
  RuboCop::RakeTask.new(:rubocop) do |t|
6
- t.options = ['--display-cop-names']
8
+ t.options = ["--display-cop-names"]
7
9
  end
8
10
 
11
+ RSpec::Core::RakeTask.new(:spec)
12
+
13
+ task :default => :spec
14
+
9
15
  GitHubChangelogGenerator::RakeTask.new :changelog do |config|
10
- config.user = 'puppetlabs'
11
- config.project = 'pdksync'
16
+ config.user = "puppetlabs"
17
+ config.project = "pdksync"
12
18
  # config.since_tag = '1.1.1'
13
- config.future_release = '0.5.0'
14
- config.exclude_labels = ['maintenance']
19
+ config.future_release = "0.6.0"
20
+ config.exclude_labels = ["maintenance"]
15
21
  config.header = "# Change log\n\nAll notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](http://semver.org)."
16
22
  config.add_pr_wo_labels = true
17
23
  config.issues = false
data/lib/pdksync.rb CHANGED
@@ -4,59 +4,45 @@ require 'open3'
4
4
  require 'fileutils'
5
5
  require 'rake'
6
6
  require 'pdk'
7
- require 'pdksync/constants'
7
+ require 'pdksync/configuration'
8
8
  require 'pdksync/gitplatformclient'
9
+
9
10
  require 'json'
10
11
  require 'yaml'
11
12
  require 'colorize'
12
13
  require 'bundler'
13
14
  require 'octokit'
15
+ require 'pdk/util/template_uri'
16
+ require 'pdksync/logger'
17
+ require 'pdksync/utils'
18
+ require 'terminal-table'
14
19
 
15
20
  # @summary
16
21
  # This module set's out and controls the pdksync process
17
- # @param [String] @namspace
18
- # The namespace of the repositories we are updating.
19
- # @param [String] @pdksync_dir
20
- # The local directory the repositories are to be copied to.
21
- # @param [String] @push_file_destination
22
- # The remote that the pull requests are to be made against.
23
- # @param [String] @create_pr_against
24
- # The branch the the pull requests are to be made against.
25
- # @param [String] @managed_modules
26
- # The file that the array of managed modules is to be retrieved from.
27
- # @param [Symbol] @git_platform
28
- # The Git hosting platform to use for pull requests
29
- # @param [String] @git_base_uri
30
- # The base URI for Git repository access, for example 'https://github.com' or
31
- # 'ssh://git@repo.example.com:2222'
32
- # @param [Hash] @git_platform_access_settings
33
- # Hash of access settings required to access the configured Git hosting
34
- # platform API. Must always contain the key :access_token set to the exported
35
- # GITHUB_TOKEN or GITLAB_TOKEN. In case of Gitlab it also must contain the
36
- # key :gitlab_api_endpoint with an appropriate value.
37
22
  module PdkSync
38
- include Constants
39
- @namespace = Constants::NAMESPACE
40
- @pdksync_dir = Constants::PDKSYNC_DIR
41
- @push_file_destination = Constants::PUSH_FILE_DESTINATION
42
- @create_pr_against = Constants::CREATE_PR_AGAINST
43
- @managed_modules = Constants::MANAGED_MODULES
44
- @default_pdksync_label = Constants::PDKSYNC_LABEL
45
- @git_platform = Constants::GIT_PLATFORM
46
- @git_base_uri = Constants::GIT_BASE_URI
47
- @git_platform_access_settings = {
48
- access_token: Constants::ACCESS_TOKEN,
49
- gitlab_api_endpoint: Constants::GITLAB_API_ENDPOINT
50
- }
23
+ def self.configuration
24
+ @configuration ||= PdkSync::Configuration.new
25
+ end
26
+
27
+ @main_path = Dir.pwd
28
+
29
+ def self.client
30
+ @client ||= Utils.setup_client
31
+ end
51
32
 
52
33
  def self.main(steps: [:clone], args: nil)
53
- check_pdk_version
54
- create_filespace
55
- client = setup_client
56
- module_names = return_modules
57
- raise "No modules found in '#{@managed_modules}'" if module_names.nil?
58
- validate_modules_exist(client, module_names)
34
+ Utils.check_pdk_version if ENV['PDKSYNC_VERSION_CHECK'].eql?('true')
35
+ Utils.create_filespace
36
+ Utils.create_filespace_gem
37
+ module_names = Utils.return_modules
38
+
39
+ unless steps.include?(:clone_gem) || steps.include?(:multi_gem_testing)
40
+ raise "No modules found in '#{Utils.configuration.managed_modules}'" if module_names.nil?
41
+ end
42
+
59
43
  pr_list = []
44
+ report_rows = []
45
+ table = Terminal::Table.new
60
46
 
61
47
  # The current directory is saved for cleanup purposes
62
48
  main_path = Dir.pwd
@@ -64,455 +50,330 @@ module PdkSync
64
50
  # validation run_a_command
65
51
  if steps.include?(:run_a_command)
66
52
  raise '"run_a_command" requires an argument to run.' if args.nil?
67
- puts "Command '#{args}'"
53
+ PdkSync::Logger.info "Command '#{args}'"
68
54
  end
69
55
  # validation create_commit
70
56
  if steps.include?(:create_commit)
71
57
  raise 'Needs a branch_name and commit_message' if args.nil? || args[:commit_message].nil? || args[:branch_name].nil?
72
- puts "Commit branch_name=#{args[:branch_name]} commit_message=#{args[:commit_message]}"
58
+ PdkSync::Logger.info "Commit branch_name=#{args[:branch_name]} commit_message=#{args[:commit_message]}"
73
59
  end
74
60
  # validation create_pr
75
61
  if steps.include?(:create_pr)
76
62
  raise 'Needs a pr_title' if args.nil? || args[:pr_title].nil?
77
- puts "PR title =#{args[:additional_title]} #{args[:pr_title]}"
63
+ PdkSync::Logger.info "PR title =#{args[:additional_title]} #{args[:pr_title]}"
78
64
  end
79
65
  # validation clean_branches
80
66
  if steps.include?(:clean_branches)
81
67
  raise 'Needs a branch_name, and the branch name contains the string pdksync' if args.nil? || args[:branch_name].nil? || !args[:branch_name].include?('pdksync')
82
- puts "Removing branch_name =#{args[:branch_name]}"
68
+ PdkSync::Logger.info "Removing branch_name =#{args[:branch_name]}"
69
+ end
70
+ # validation clone_gem
71
+ if steps.include?(:clone_gem)
72
+ raise 'Needs a gem_name' if args.nil? || args[:gem_name].nil?
73
+ PdkSync::Logger.info "Command '#{args}'"
74
+ end
75
+ # validation multi_gem_testing
76
+ if steps.include?(:multi_gem_testing)
77
+ raise '"multi_gem_testing" requires arguments to run version_file and build_gem.' if args.nil? || args[:version_file].nil? || args[:build_gem].nil?
78
+ puts "Command '#{args}'"
79
+ end
80
+ # validation multi_gem_file_update
81
+ if steps.include?(:multigem_file_update)
82
+ raise 'multigem_file_update requires arguments gem_to_test, gemfury_username to run.' if args[:gem_name].nil? || args[:gemfury_username].nil?
83
+ puts "Command '#{args}'"
84
+ end
85
+ # validation gem_file_update
86
+ if steps.include?(:gem_file_update)
87
+ raise '"gem_file_update" requires arguments (gem_to_test) to run.' if args[:gem_to_test].nil?
88
+ puts "Command '#{args}'"
89
+ end
90
+ # validation run_tests_locally
91
+ if steps.include?(:run_tests_locally)
92
+ puts "Command '#{args}'"
93
+ end
94
+ # validation fetch_test_results_locally
95
+ if steps.include?(:fetch_test_results_locally)
96
+ puts "Command '#{args}'"
97
+ end
98
+ # validation run_tests_jenkins
99
+ if steps.include?(:run_tests_jenkins)
100
+ raise 'run_tests_jenkins requires arguments (jenkins_server_url, github_branch) to run.' if args[:github_branch].nil? || args[:jenkins_server_url].nil?
101
+ puts "Command '#{args}'"
102
+ end
103
+ # validation test_results_jenkins
104
+ if steps.include?(:test_results_jenkins)
105
+ raise 'test_results_jenkins requires argument jenkins_server_url to run.' if args[:jenkins_server_url].nil?
106
+ puts "Command '#{args}'"
83
107
  end
84
108
 
85
- abort "No modules listed in #{@managed_modules}" if module_names.nil?
86
- module_names.each do |module_name|
87
- module_args = args.clone
109
+ unless steps.include?(:clone_gem) || steps.include?(:multi_gem_testing)
110
+ abort "No modules listed in #{Utils.configuration.managed_modules}" if module_names.nil?
111
+ end
112
+
113
+ if steps.include?(:clone_gem) || steps.include?(:multi_gem_testing)
114
+ gem_args = args.clone
88
115
  Dir.chdir(main_path) unless Dir.pwd == main_path
89
- print "#{module_name}, "
90
- repo_name = "#{@namespace}/#{module_name}"
91
- output_path = "#{@pdksync_dir}/#{module_name}"
92
- if steps.include?(:clone)
93
- clean_env(output_path) if Dir.exist?(output_path)
94
- print 'delete module directory, '
95
- @git_repo = clone_directory(@namespace, module_name, output_path)
96
- print 'cloned, '
97
- puts "(WARNING) Unable to clone repo for #{module_name}".red if @git_repo.nil?
116
+ PdkSync::Logger.info "#{gem_args[:gem_name]}, "
117
+ output_path = File.join(Utils.configuration.pdksync_gem_dir, gem_args[:gem_name])
118
+ if steps.include?(:clone_gem)
119
+ Utils.clean_env(output_path) if Dir.exist?(output_path)
120
+ PdkSync::Logger.info 'delete gem directory, '
121
+ @git_repo = Utils.clone_directory(Utils.configuration.namespace, gem_args[:gem_name], output_path)
122
+ PdkSync::Logger.info 'cloned'
123
+ PdkSync::Logger.error "Unable to clone repo for #{gem_args[:gem_name]}".red if @git_repo.nil?
98
124
  Dir.chdir(main_path) unless Dir.pwd == main_path
99
- next if @git_repo.nil?
100
125
  end
101
- puts '(WARNING) @output_path does not exist, skipping module'.red unless File.directory?(output_path)
102
- next unless File.directory?(output_path)
103
- if steps.include?(:pdk_convert)
104
- exit_status = run_command(output_path, "#{return_pdk_path} convert --force --template-url https://github.com/puppetlabs/pdk-templates")
105
- print 'converted, '
106
- next unless exit_status.zero?
107
- end
108
- if steps.include?(:pdk_validate)
126
+ puts '(WARNING) @output_path does not exist, gem'.red unless File.directory?(output_path)
127
+ if steps.include?(:multi_gem_testing)
109
128
  Dir.chdir(main_path) unless Dir.pwd == main_path
110
- exit_status = run_command(output_path, "#{return_pdk_path} validate -a")
111
- print 'validated, '
112
- next unless exit_status.zero?
113
- end
114
- if steps.include?(:run_a_command)
129
+ PdkSync::Logger.info 'Multi Gem Testing, '
130
+ current_gem_version = Utils.check_gem_latest_version(gem_args[:gem_name])
131
+ PdkSync::Logger.info current_gem_version
132
+ new_gem_version = Utils.update_gem_latest_version_by_one(current_gem_version)
133
+ PdkSync::Logger.info new_gem_version
115
134
  Dir.chdir(main_path) unless Dir.pwd == main_path
116
- print 'run command, '
117
- exit_status = run_command(output_path, module_args)
118
- next unless exit_status.zero?
119
- end
120
- if steps.include?(:pdk_update)
135
+ exit_status = Utils.run_command(output_path, "sed s/#{current_gem_version}/#{new_gem_version}/g #{gem_args[:version_file]} >> test.yml", nil)
136
+ PdkSync::Logger.info 'Updated the version'
121
137
  Dir.chdir(main_path) unless Dir.pwd == main_path
122
- next unless pdk_update(output_path).zero?
123
- if steps.include?(:use_pdk_ref)
124
- ref = return_template_ref
125
- pr_title = module_args[:additional_title] ? "#{module_args[:additional_title]} - pdksync_#{ref}" : "pdksync_#{ref}"
126
- module_args = module_args.merge(branch_name: "pdksync_#{ref}",
127
- commit_message: pr_title,
128
- pr_title: pr_title,
129
- pdksync_label: @default_pdksync_label)
130
- end
131
- print 'pdk update, '
132
- end
133
- if steps.include?(:create_commit)
138
+ exit_status = Utils.run_command(output_path, "cp test.yml #{gem_args[:version_file]}", nil)
134
139
  Dir.chdir(main_path) unless Dir.pwd == main_path
135
- git_instance = Git.open(output_path)
136
- create_commit(git_instance, module_args[:branch_name], module_args[:commit_message])
137
- print 'commit created, '
138
- end
139
- if steps.include?(:push)
140
+ exit_status = Utils.run_command(output_path, 'rm -rf test.yml', nil)
141
+ PdkSync::Logger.info 'bundle install'
142
+ Dir.chdir(main_path) unless Dir.pwd == main_path
143
+ exit_status = Utils.run_command(output_path, 'bundle install', nil)
144
+ PdkSync::Logger.info 'building gem'
145
+ Dir.chdir(main_path) unless Dir.pwd == main_path
146
+ exit_status = Utils.run_command(output_path, "bundle exec #{gem_args[:build_gem]}", nil)
147
+ PdkSync::Logger.info 'uploading packages'
140
148
  Dir.chdir(main_path) unless Dir.pwd == main_path
141
- git_instance = Git.open(output_path)
142
- if git_instance.diff(git_instance.current_branch, "#{@push_file_destination}/#{@create_pr_against}").size != 0 # Git::Diff doesn't have empty? # rubocop:disable Style/ZeroLengthPredicate
143
- push_staged_files(git_instance, git_instance.current_branch, repo_name)
144
- print 'push, '
145
- else
146
- print 'skipped push, '
149
+ Dir.chdir("#{output_path}/#{gem_args[:gem_path]}") unless Dir.pwd == output_path
150
+ gemfury_token = Utils.configuration.gemfury_access_settings
151
+ Dir.glob('*.gem') do |filename|
152
+ PdkSync::Logger.info filename
153
+ Dir.chdir(main_path) unless Dir.pwd == main_path
154
+ exit_status = Utils.run_command("#{output_path}/#{gem_args[:gem_path]}", "curl -F package=@#{filename} https://" + gemfury_token + "@push.fury.io/#{gem_args[:gemfury_username]}/", nil)
147
155
  end
148
156
  end
149
- if steps.include?(:create_pr)
157
+ else
158
+ module_names.each do |module_name|
159
+ module_args = args.clone
150
160
  Dir.chdir(main_path) unless Dir.pwd == main_path
151
- git_instance = Git.open(output_path)
152
- if git_instance.diff(git_instance.current_branch, "#{@push_file_destination}/#{@create_pr_against}").size != 0 # Git::Diff doesn't have empty? # rubocop:disable Style/ZeroLengthPredicate
153
- pdk_version = return_pdk_version("#{output_path}/metadata.json")
154
-
155
- # If a label is supplied, verify that it is available in the repo
156
- label = module_args[:pdksync_label] ? module_args[:pdksync_label] : module_args[:label]
157
- label_valid = (label.is_a?(String) && !label.to_str.empty?) ? check_for_label(client, repo_name, label) : nil
158
-
159
- # Exit current iteration if an error occured retrieving a label
160
- if label_valid == false
161
- raise 'Ensure label is valid'
161
+ PdkSync::Logger.info "#{module_name}, "
162
+ repo_name = File.join(Utils.configuration.namespace, module_name)
163
+ output_path = File.join(Utils.configuration.pdksync_dir, module_name)
164
+ if steps.include?(:clone)
165
+ Utils.validate_modules_exist(client, module_names)
166
+ Utils.clean_env(output_path) if Dir.exist?(output_path)
167
+ PdkSync::Logger.info 'delete module directory'
168
+ @git_repo = Utils.clone_directory(Utils.configuration.namespace, module_name, output_path)
169
+ PdkSync::Logger.info 'cloned'
170
+ PdkSync::Logger.error "Unable to clone repo for #{module_name}" if @git_repo.nil?
171
+ Dir.chdir(main_path) unless Dir.pwd == main_path
172
+ next if @git_repo.nil?
173
+ end
174
+ PdkSync::Logger.warn "#{output_path} does not exist, skipping module" unless File.directory?(output_path)
175
+ next unless File.directory?(output_path)
176
+ if steps.include?(:pdk_convert)
177
+ exit_status = Utils.run_command(output_path, "#{Utils.return_pdk_path} convert --force #{configuration.templates}", nil)
178
+ PdkSync::Logger.info 'converted'
179
+ next unless exit_status.zero?
180
+ end
181
+ if steps.include?(:pdk_validate)
182
+ Dir.chdir(main_path) unless Dir.pwd == main_path
183
+ exit_status = Utils.run_command(output_path, "#{Utils.return_pdk_path} validate -a", nil)
184
+ PdkSync::Logger.info 'validated' if exit_status.zero?
185
+ next unless exit_status.zero?
186
+ end
187
+ if steps.include?(:run_a_command)
188
+ Dir.chdir(main_path) unless Dir.pwd == main_path
189
+ PdkSync::Logger.info 'run command'
190
+ if module_args[:option].nil?
191
+ pid = Utils.run_command(output_path, module_args[:command], module_args[:option])
192
+ next unless pid != 0 # rubocop:disable Metrics/BlockNesting
193
+ else
194
+ exit_status = Utils.run_command(output_path, module_args[:command], nil)
195
+ next unless exit_status.zero? # rubocop:disable Metrics/BlockNesting
162
196
  end
163
-
164
- # Create the PR and add link to pr list
165
- pr = create_pr(client, repo_name, git_instance.current_branch, pdk_version, module_args[:pr_title])
166
- if pr.nil?
167
- break
197
+ end
198
+ if steps.include?(:gem_file_update)
199
+ Dir.chdir(main_path) unless Dir.pwd == main_path
200
+ print 'gem file update, '
201
+ Utils.gem_file_update(output_path, module_args[:gem_to_test], module_args[:gem_line], module_args[:gem_sha_finder], module_args[:gem_sha_replacer], module_args[:gem_version_finder], module_args[:gem_version_replacer], module_args[:gem_branch_finder], module_args[:gem_branch_replacer], main_path) # rubocop:disable Metrics/LineLength
202
+ print 'gem file updated, '
203
+ end
204
+ if steps.include?(:run_tests_locally)
205
+ Dir.chdir(main_path) unless Dir.pwd == main_path
206
+ PdkSync::Logger.info 'Run tests '
207
+ module_type = Utils.module_type(output_path, module_name)
208
+ Utils.run_tests_locally(output_path, module_type, module_args[:provision_type], module_name, module_args[:puppet_collection])
209
+ end
210
+ if steps.include?(:fetch_test_results_locally)
211
+ Dir.chdir(main_path) unless Dir.pwd == main_path
212
+ PdkSync::Logger.info 'Fetch test results for local run '
213
+ module_type = Utils.module_type(output_path, module_name)
214
+ table = Utils.fetch_test_results_locally(output_path, module_type, module_name, report_rows)
215
+ end
216
+ if steps.include?(:pdk_update)
217
+ Dir.chdir(main_path) unless Dir.pwd == main_path
218
+ next unless Utils.pdk_update(output_path).zero?
219
+ if steps.include?(:use_pdk_ref)
220
+ ref = Utils.return_template_ref(File.join(output_path, 'metadata.json'))
221
+ pr_title = module_args[:additional_title] ? "#{module_args[:additional_title]} - pdksync_#{ref}" : "pdksync_#{ref}" # rubocop:disable Metrics/BlockNesting
222
+ module_args = module_args.merge(branch_name: "pdksync_#{ref}",
223
+ commit_message: pr_title,
224
+ pr_title: pr_title,
225
+ pdksync_label: Utils.configuration.default_pdksync_label)
168
226
  end
169
-
170
- pr_list.push(pr.html_url)
171
- print 'created pr, '
172
-
173
- # If a valid label is supplied, add this to the PR
174
- if label_valid == true
175
- add_label(client, repo_name, pr.number, label)
176
- print "added label '#{label}' "
227
+ PdkSync::Logger.info 'pdk update'
228
+ end
229
+ if steps.include?(:use_gem_ref)
230
+ pr_title = module_args[:additional_title] ? "#{module_args[:additional_title]} - pdksync_gem_testing" : 'pdksync_gem_testing'
231
+ module_args = module_args.merge(branch_name: "gem_testing_#{module_args[:gem_to_test]}",
232
+ commit_message: pr_title,
233
+ pr_title: pr_title,
234
+ pdksync_label: Utils.configuration.default_pdksync_label)
235
+ end
236
+ if steps.include?(:create_commit)
237
+ Dir.chdir(main_path) unless Dir.pwd == main_path
238
+ git_instance = Git.open(output_path)
239
+ Utils.create_commit(git_instance, module_args[:branch_name], module_args[:commit_message])
240
+ PdkSync::Logger.info 'commit created'
241
+ end
242
+ if steps.include?(:push)
243
+ Dir.chdir(main_path) unless Dir.pwd == main_path
244
+ git_instance = Git.open(output_path)
245
+ if git_instance.diff(git_instance.current_branch, "#{Utils.configuration.push_file_destination}/#{Utils.configuration.create_pr_against}").size != 0 # Git::Diff doesn't have empty? # rubocop:disable Style/ZeroLengthPredicate
246
+ PdkSync::Logger.info 'push'
247
+ Utils.push_staged_files(git_instance, git_instance.current_branch, repo_name)
248
+ else
249
+ PdkSync::Logger.info 'skipped push'
177
250
  end
178
- else
179
- print 'skipped pr, '
180
251
  end
181
- end
182
- if steps.include?(:clean_branches)
183
- Dir.chdir(main_path) unless Dir.pwd == main_path
184
- delete_branch(client, repo_name, module_args[:branch_name])
185
- print 'branch deleted, '
186
- end
187
- puts 'done.'.green
188
- end
189
- return if pr_list.size.zero?
190
- puts "\nPRs created:\n".blue
191
- pr_list.each do |pr|
192
- puts pr
193
- end
194
- end
195
-
196
- # @summary
197
- # Check the local pdk version against the most recent tagged release on GitHub
198
- def self.check_pdk_version
199
- stdout, _stderr, status = Open3.capture3("#{return_pdk_path} --version")
200
- raise "(FAILURE) Unable to find pdk at '#{return_pdk_path}'.".red unless status.exitstatus
201
-
202
- local_version = stdout.strip
203
- remote_version = Octokit.tags('puppetlabs/pdk').first[:name][1..-1]
204
-
205
- unless Gem::Version.new(remote_version) <= Gem::Version.new(local_version)
206
- puts "(WARNING) The current version of pdk is #{remote_version} however you are using #{local_version}".red
207
- end
208
- rescue StandardError => error
209
- puts "(WARNING) Unable to check latest pdk version. #{error}".red
210
- end
211
-
212
- # @summary
213
- # This method when called will create a directory identified by the set global variable '@pdksync_dir', on the condition that it does not already exist.
214
- def self.create_filespace
215
- FileUtils.mkdir @pdksync_dir unless Dir.exist?(@pdksync_dir)
216
- end
217
-
218
- # @summary
219
- # This method when called will create and return an octokit client with access to the upstream git repositories.
220
- # @return [PdkSync::GitPlatformClient] client
221
- # The Git platform client that has been created.
222
- def self.setup_client
223
- PdkSync::GitPlatformClient.new(@git_platform, @git_platform_access_settings)
224
- rescue StandardError => error
225
- raise "Git platform access not set up correctly: #{error}"
226
- end
227
-
228
- # @summary
229
- # This method when called will access a file set by the global variable '@managed_modules' and retrieve the information within as an array.
230
- # @return [Array]
231
- # An array of different module names.
232
- def self.return_modules
233
- raise "File '#{@managed_modules}' is empty/does not exist" if File.size?(@managed_modules).nil?
234
- YAML.safe_load(File.open(@managed_modules))
235
- end
236
-
237
- # @summary
238
- # This method when called will parse an array of module names and verify
239
- # whether they are valid repo or project names on the configured Git
240
- # hosting platform.
241
- # @param [PdkSync::GitPlatformClient] client
242
- # The Git platform client used to get a repository.
243
- # @param [Array] module_names
244
- # String array of the names of Git platform repos
245
- def self.validate_modules_exist(client, module_names)
246
- invalid_names = []
247
- raise "Error reading in modules. Check syntax of '#{@managed_modules}'." unless !module_names.nil? && module_names.is_a?(Array)
248
- module_names.each do |module_name|
249
- # If module name is invalid, push it to invalid names array
250
- unless client.repository?("#{@namespace}/#{module_name}")
251
- invalid_names.push(module_name)
252
- next
253
- end
254
- end
255
- # Raise error if any invalid matches were found
256
- raise "Could not find the following repositories: #{invalid_names}" unless invalid_names.empty?
257
- end
258
-
259
- # @summary
260
- # Try to use a fully installed pdk, otherwise fall back to the bundled pdk gem.
261
- # @return String
262
- # Path to the pdk executable
263
- def self.return_pdk_path
264
- full_path = '/opt/puppetlabs/pdk/bin/pdk'
265
- path = if File.executable?(full_path)
266
- full_path
267
- else
268
- puts "(WARNING) Using pdk on PATH not '#{full_path}'".red
269
- 'pdk'
270
- end
271
- path
272
- end
273
-
274
- def self.create_commit(git_repo, branch_name, commit_message)
275
- checkout_branch(git_repo, branch_name)
276
- if add_staged_files(git_repo) # ignore rubocop for clarity on side effect ordering # rubocop:disable Style/GuardClause
277
- commit_staged_files(git_repo, branch_name, commit_message)
278
- end
279
- end
280
-
281
- # @summary
282
- # This method when called will call the delete function against the given repository if it exists.
283
- # @param [String] output_path
284
- # The repository that is to be deleted.
285
- def self.clean_env(output_path)
286
- # If a local copy already exists it is removed
287
- FileUtils.rm_rf(output_path)
288
- end
289
-
290
- # @summary
291
- # This method when called will clone a given repository into a local location that has also been set.
292
- # @param [String] namespace
293
- # The namespace the repository is located in.
294
- # @param [String] module_name
295
- # The name of the repository.
296
- # @param [String] output_path
297
- # The location the repository is to be cloned to.
298
- # @return [Git::Base]
299
- # A git object representing the local repository.
300
- def self.clone_directory(namespace, module_name, output_path)
301
- Git.clone("#{@git_base_uri}/#{namespace}/#{module_name}.git", output_path.to_s) # is returned
302
- rescue Git::GitExecuteError => error
303
- puts "(FAILURE) Cloning #{module_name} has failed. #{error}".red
304
- end
305
-
306
- # @summary
307
- # This method when called will run a command command at the given location, with an error message being thrown if it is not successful.
308
- # @param [String] output_path
309
- # The location that the command is to be run from.
310
- # @param [String] command
311
- # The command to be run.
312
- # @return [Integer]
313
- # The status code of the command run.
314
- def self.run_command(output_path, command)
315
- stdout = ''
316
- stderr = ''
317
- status = Process::Status
318
-
319
- Dir.chdir(output_path) unless Dir.pwd == output_path
320
-
321
- # Environment cleanup required due to Ruby subshells using current Bundler environment
322
- if command =~ %r{^bundle}
323
- Bundler.with_clean_env do
324
- stdout, stderr, status = Open3.capture3(command)
325
- end
326
- else
327
- stdout, stderr, status = Open3.capture3(command)
328
- end
329
-
330
- puts "\n#{stdout}\n".yellow
331
- puts "(FAILURE) Unable to run command '#{command}': #{stderr}".red unless status.exitstatus.zero?
332
- status.exitstatus
333
- end
252
+ if steps.include?(:create_pr)
253
+ Dir.chdir(main_path) unless Dir.pwd == main_path
254
+ git_instance = Git.open(output_path)
255
+ if git_instance.diff(git_instance.current_branch, "#{Utils.configuration.push_file_destination}/#{Utils.configuration.create_pr_against}").size != 0 # Git::Diff doesn't have empty? # rubocop:disable Style/ZeroLengthPredicate
256
+ pdk_version = Utils.return_pdk_version("#{output_path}/metadata.json")
257
+
258
+ # If a label is supplied, verify that it is available in the repo
259
+ label = module_args[:pdksync_label] ? module_args[:pdksync_label] : module_args[:label] # rubocop:disable Metrics/BlockNesting
260
+ label_valid = (label.is_a?(String) && !label.to_str.empty?) ? Utils.check_for_label(client, repo_name, label) : nil # rubocop:disable Metrics/BlockNesting
261
+
262
+ # Exit current iteration if an error occured retrieving a label
263
+ if label_valid == false # rubocop:disable Metrics/BlockNesting
264
+ raise 'Ensure label is valid'
265
+ end
266
+
267
+ # Create the PR and add link to pr list
268
+ pr = Utils.create_pr(client, repo_name, git_instance.current_branch, pdk_version, module_args[:pr_title])
269
+ break if pr.nil? # rubocop:disable Metrics/BlockNesting
270
+
271
+ pr_list.push(pr.html_url)
272
+ PdkSync::Logger.info 'created pr'
273
+
274
+ # If a valid label is supplied, add this to the PR
275
+ if label_valid == true # rubocop:disable Metrics/BlockNesting
276
+ Utils.add_label(client, repo_name, pr.number, label)
277
+ PdkSync::Logger.info "added label '#{label}' "
278
+ end
279
+ else
280
+ PdkSync::Logger.info 'skipped pr'
281
+ end
282
+ end
283
+ if steps.include?(:clean_branches)
284
+ Dir.chdir(main_path) unless Dir.pwd == main_path
285
+ Utils.delete_branch(client, repo_name, module_args[:branch_name])
286
+ PdkSync::Logger.info 'branch deleted'
287
+ end
288
+ if steps.include?(:run_tests_jenkins)
289
+ jenkins_client = Utils.setup_jenkins_client(module_args[:jenkins_server_url])
290
+ Dir.chdir(main_path) unless Dir.pwd == main_path
291
+ PdkSync::Logger.info 'Run tests in jenkins '
292
+ module_type = Utils.module_type(output_path, module_name)
293
+ if module_type == 'traditional'
294
+ github_user = 'puppetlabs' if module_args[:test_framework].nil? # rubocop:disable Metrics/BlockNesting
295
+ github_user = module_args[:github_user] unless module_args[:github_user].nil? # rubocop:disable Metrics/BlockNesting
296
+ if module_args[:test_framework] == 'jenkins' || module_args[:test_framework].nil? # rubocop:disable Metrics/BlockNesting
297
+ module_name = "puppetlabs-#{module_name}" if %w[cisco_ios device_manager].include?(module_name) # rubocop:disable Metrics/BlockNesting
298
+ job_name = "forge-module_#{module_name}_init-manual-parameters_adhoc"
299
+ job_name = "forge-windows_#{module_name}_init-manual-parameters_adhoc" if ['puppetlabs-reboot', 'puppetlabs-iis', 'puppetlabs-powershell', 'sqlserver'].include?(module_name) # rubocop:disable Metrics/BlockNesting, Metrics/LineLength
300
+ build_id = Utils.run_tests_jenkins(jenkins_client, module_name, module_args[:github_branch], github_user, job_name)
301
+ next if build_id.nil? # rubocop:disable Metrics/BlockNesting
302
+ PdkSync::Logger.info "New adhoc TEST EXECUTION has started. \nYou can check progress here: #{configuration['jenkins_server_url']}/job/#{job_name}/#{build_id}"
303
+ Utils.test_results_jenkins(module_args[:jenkins_server_url], build_id, job_name, module_name)
304
+ end
305
+ end
306
+ if module_type == 'litmus'
307
+ PdkSync::Logger.info '(Error) Module Type is Litmus please use the rake task run_tests_locally to run'.red
308
+ end
309
+ end
310
+ if steps.include?(:test_results_jenkins)
311
+ Dir.chdir(main_path) unless Dir.pwd == main_path
312
+ PdkSync::Logger.info 'Fetch test results from jenkins, '
313
+ module_type = Utils.module_type(output_path, module_name)
314
+ if module_type == 'litmus'
315
+ PdkSync::Logger.info '(Error) Module Type is Litmus please use the rake task run_tests_locally to run'.red
316
+ next
317
+ end
334
318
 
335
- # @summary
336
- # This method when called will run the 'pdk update --force' command at the given location, with an error message being thrown if it is not successful.
337
- # @param [String] output_path
338
- # The location that the command is to be run from.
339
- # @return [Integer]
340
- # The status code of the pdk update run.
341
- def self.pdk_update(output_path)
342
- # Runs the pdk update command
343
- Dir.chdir(output_path) unless Dir.pwd == output_path
344
- _stdout, stderr, status = Open3.capture3("#{return_pdk_path} update --force")
345
- puts "(FAILURE) Unable to run `pdk update`: #{stderr}".red unless status.exitstatus.zero?
346
- status.exitstatus
347
- end
319
+ module_name = "puppetlabs-#{module_name}" if %w[cisco_ios device_manager].include?(module_name)
320
+ File.open("results_#{module_name}.out", 'r') do |f|
321
+ f.each_line do |line|
322
+ if line.include?('BUILD_ID')
323
+ build_id = line.split('=')[1].strip
324
+ elsif line.include?('MODULE_NAME')
325
+ module_name = line.split('=')[1].strip
326
+ end
327
+ end
348
328
 
349
- # @summary
350
- # This method when called will retrieve the template ref of the current module, i.e. the one that was navigated into in the 'pdk_update' method.
351
- # @param [String] metadata_file
352
- # An optional input that can be used to set the location of the metadata file.
353
- # @return [String]
354
- # A string value that represents the current pdk template.
355
- def self.return_template_ref(metadata_file = 'metadata.json')
356
- file = File.read(metadata_file)
357
- data_hash = JSON.parse(file)
358
- data_hash['template-ref']
359
- end
329
+ job_name = "forge-module_#{module_name}_init-manual-parameters_adhoc" if module_args[:job_name].nil?
330
+ job_name = "forge-windows_#{module_name}_init-manual-parameters_adhoc" if ['puppetlabs-reboot', 'puppetlabs-iis', 'puppetlabs-powershell', 'sqlserver'].include?(module_name)
331
+ Utils.test_results_jenkins(module_args[:jenkins_server_url], build_id, job_name, module_name)
332
+ end
333
+ end
334
+ if steps.include?(:multigem_file_update)
335
+ Dir.chdir(main_path) unless Dir.pwd == main_path
336
+ gemfury_readonly_token = Utils.configuration.gemfury_access_settings
337
+ Utils.update_gemfile_multigem(output_path, module_args[:gem_name], gemfury_readonly_token, module_args[:gemfury_username])
338
+ PdkSync::Logger.info 'Updated with multigem, '
339
+ end
360
340
 
361
- # @summary
362
- # This method when called will checkout a new local branch of the given repository.
363
- # @param [Git::Base] git_repo
364
- # A git object representing the local repository to be branched.
365
- # @param [String] branch_suffix
366
- # The string that is appended on the branch name. eg template_ref or a friendly name
367
- def self.checkout_branch(git_repo, branch_suffix)
368
- git_repo.branch("pdksync_#{branch_suffix}").checkout
369
- end
341
+ if steps.include?(:add_provision_list)
342
+ result = Utils.add_provision_list(output_path, module_args[:key], module_args[:provisioner], [module_args[:images], module_args.extras].flatten)
343
+ raise "#{output_path}/provision.yaml does not exist" unless result
344
+ end
370
345
 
371
- # @summary
372
- # This method when called will retrieve the pdk_version of the current module, i.e. the one that was navigated into in the 'pdk_update' method.
373
- # @param [String] metadata_file
374
- # An optional input that can be used to set the location of the metadata file.
375
- # @return [String]
376
- # A string value that represents the current pdk version.
377
- def self.return_pdk_version(metadata_file = 'metadata.json')
378
- file = File.read(metadata_file)
379
- data_hash = JSON.parse(file)
380
- data_hash['pdk-version']
381
- end
346
+ if steps.include?(:generate_vmpooler_release_checks)
347
+ Utils.generate_vmpooler_release_checks(output_path, module_args[:puppet_version].to_i)
348
+ end
382
349
 
383
- # @summary
384
- # This method when called will stage all changed files within the given repository, conditional on them being managed via the pdk.
385
- # @param [Git::Base] git_repo
386
- # A git object representing the local repository to be staged.
387
- def self.add_staged_files(git_repo)
388
- if git_repo.status.changed != {}
389
- git_repo.add(all: true)
390
- puts 'All files have been staged.'
391
- true
392
- else
393
- puts 'Nothing to commit.'
394
- false
395
- end
396
- end
350
+ if steps.include?(:update_os_support)
351
+ Utils.update_os_support(output_path)
352
+ end
397
353
 
398
- # @summary
399
- # This method when called will create a commit containing all currently staged files, with the name of the commit containing the template ref as a unique identifier.
400
- # @param [Git::Base] git_repo
401
- # A git object representing the local repository against which the commit is to be made.
402
- # @param [String] template_ref
403
- # The unique template_ref that is used as part of the commit name.
404
- # @param [String] commit_message
405
- # If specified it will be the message for the commit.
406
- def self.commit_staged_files(git_repo, template_ref, commit_message = nil)
407
- message = if commit_message.nil?
408
- "pdksync_#{template_ref}"
409
- else
410
- commit_message
411
- end
412
- git_repo.commit(message)
413
- end
354
+ if steps.include?(:remove_platform_from_metadata)
355
+ Utils.remove_platform_from_metadata(output_path, module_args[:os], module_args[:version])
356
+ end
414
357
 
415
- # @summary
416
- # This method when called will push the given local commit to local repository's origin.
417
- # @param [Git::Base] git_repo
418
- # A git object representing the local repository againt which the push is to be made.
419
- # @param [String] template_ref
420
- # The unique reference that that represents the template the update has ran against.
421
- # @param [String] repo_name
422
- # The name of the repository on which the commit is to be made.
423
- def self.push_staged_files(git_repo, current_branch, repo_name)
424
- git_repo.push(@push_file_destination, current_branch)
425
- rescue StandardError => error
426
- puts "(FAILURE) Pushing to #{@push_file_destination} for #{repo_name} has failed. #{error}".red
427
- end
358
+ if steps.include?(:add_platform_to_metadata)
359
+ Utils.add_platform_to_metadata(output_path, module_args[:os], module_args[:version])
360
+ end
428
361
 
429
- # @summary
430
- # This method when called will create a pr on the given repository that will create a pr to merge the given commit into the master with the pdk version as an identifier.
431
- # @param [PdkSync::GitPlatformClient] client
432
- # The Git platform client used to gain access to and manipulate the repository.
433
- # @param [String] repo_name
434
- # The name of the repository on which the commit is to be made.
435
- # @param [String] template_ref
436
- # The unique reference that that represents the template the update has ran against.
437
- # @param [String] pdk_version
438
- # The current version of the pdk on which the update is run.
439
- def self.create_pr(client, repo_name, template_ref, pdk_version, pr_title = nil)
440
- if pr_title.nil?
441
- title = "pdksync - Update using #{pdk_version}"
442
- message = "pdk version: `#{pdk_version}` \n pdk template ref: `#{template_ref}`"
443
- head = "pdksync_#{template_ref}"
444
- else
445
- title = "pdksync - #{pr_title}"
446
- message = "#{pr_title}\npdk version: `#{pdk_version}` \n"
447
- head = template_ref
448
- end
449
- pr = client.create_pull_request(repo_name, @create_pr_against,
450
- head,
451
- title,
452
- message)
453
- pr
454
- rescue StandardError => error
455
- puts "(FAILURE) PR creation for #{repo_name} has failed. #{error}".red
456
- end
362
+ if steps.include?(:update_requirements)
363
+ Utils.update_requirements(output_path, module_args[:name], module_args[:key], module_args[:value])
364
+ end
457
365
 
458
- # @summary
459
- # This method when called will check on the given repository for the existence of the supplied label
460
- # @param [PdkSync::GitPlatformClient] client
461
- # The Git platform client used to gain access to and manipulate the repository.
462
- # @param [String] repo_name
463
- # The name of the repository on which the commit is to be made.
464
- # @param [String] label
465
- # The label to check for.
466
- # @return [Boolean]
467
- # A boolean stating whether the label was found.
468
- def self.check_for_label(client, repo_name, label)
469
- # Get labels from repository
470
- repo_labels = client.labels(repo_name)
366
+ if steps.include?(:normalize_metadata_supported_platforms)
367
+ Utils.normalize_metadata_supported_platforms(output_path)
368
+ end
471
369
 
472
- # Look for label in the repository's labels
473
- match = false
474
- repo_labels.each do |repo_label|
475
- if repo_label.name == label
476
- match = true
477
- break
370
+ PdkSync::Logger.info 'done'
478
371
  end
372
+ table = Terminal::Table.new title: 'Module Test Results', headings: %w[Module Status Result From], rows: report_rows
373
+ puts table if steps.include?(:fetch_test_results_locally)
374
+ return if pr_list.size.zero?
375
+ PdkSync::Logger.info "\nPRs created:\n"
376
+ puts pr_list.join("\n")
479
377
  end
480
-
481
- # Raise error if a match was not found else return true
482
- (match == false) ? (raise StandardError, "Label '#{label}' not found in #{repo_name}") : (return true)
483
- rescue StandardError => error
484
- puts "(FAILURE) Retrieving labels for #{repo_name} has failed. #{error}".red
485
- return false
486
- end
487
-
488
- # @summary
489
- # This method when called will add a given label to a given repository
490
- # @param [PdkSync::GitPlatformClient] client
491
- # The Git Platform client used to gain access to and manipulate the repository.
492
- # @param [String] repo_name
493
- # The name of the repository on which the commit is to be made.
494
- # @param [Integer] issue_number
495
- # The id of the issue (i.e. pull request) to add the label to.
496
- # @param [String] label
497
- # The label to add.
498
- def self.add_label(client, repo_name, issue_number, label)
499
- client.update_issue(repo_name, issue_number, labels: [label])
500
- rescue StandardError => error
501
- puts "(FAILURE) Adding label to #{repo_name} issue #{issue_number} has failed. #{error}".red
502
- return false
503
- end
504
-
505
- # @summary
506
- # This method when called will delete any preexisting branch on the given repository that matches the given name.
507
- # @param [PdkSync::GitPlatformClient] client
508
- # The Git platform client used to gain access to and manipulate the repository.
509
- # @param [String] repo_name
510
- # The name of the repository from which the branch is to be deleted.
511
- # @param [String] branch_name
512
- # The name of the branch that is to be deleted.
513
- def self.delete_branch(client, repo_name, branch_name)
514
- client.delete_branch(repo_name, branch_name)
515
- rescue StandardError => error
516
- puts "(FAILURE) Deleting #{branch_name} in #{repo_name} failed. #{error}".red
517
378
  end
518
379
  end