lib/modulesync.rb in modulesync-2.2.0 vs lib/modulesync.rb in modulesync-2.3.0
- old
+ new
@@ -1,5 +1,6 @@
+require 'English'
require 'fileutils'
require 'pathname'
require 'modulesync/cli'
require 'modulesync/constants'
@@ -16,14 +17,14 @@
include Constants
def self.config_defaults
{
- :project_root => 'modules/',
+ :project_root => 'modules/',
:managed_modules_conf => 'managed_modules.yml',
- :configs => '.',
- :tag_pattern => '%s'
+ :configs => '.',
+ :tag_pattern => '%s',
}
end
def self.options
@options
@@ -42,12 +43,12 @@
Find.find(local_template_dir).find_all { |p| p =~ /.erb$/ && !File.directory?(p) }
.collect { |p| p.chomp('.erb') }
.to_a
else
$stderr.puts "#{local_template_dir} does not exist." \
- ' Check that you are working in your module configs directory or' \
- ' that you have passed in the correct directory with -c.'
+ ' Check that you are working in your module configs directory or' \
+ ' that you have passed in the correct directory with -c.'
exit 1
end
end
def self.relative_names(file_list, path)
@@ -60,11 +61,11 @@
negative_filter = options[:negative_filter]
managed_modules = Util.parse_config(config_file)
if managed_modules.empty?
$stderr.puts "No modules found in #{config_file}." \
- ' Check that you specified the right :configs directory and :managed_modules_conf file.'
+ ' Check that you specified the right :configs directory and :managed_modules_conf file.'
exit 1
end
managed_modules.select! { |m| m =~ Regexp.new(filter) } unless filter.nil?
managed_modules.reject! { |m| m =~ Regexp.new(negative_filter) } unless negative_filter.nil?
managed_modules.map { |given_name, options| PuppetModule.new(given_name, options) }
@@ -80,11 +81,10 @@
hook.deactivate
end
end
def self.manage_file(puppet_module, filename, settings, options)
- namespace = settings.additional_settings[:namespace]
module_name = settings.additional_settings[:puppet_module]
configs = settings.build_file_configs(filename)
target_file = puppet_module.path(filename)
if configs['delete']
Renderer.remove(target_file)
@@ -93,25 +93,30 @@
begin
erb = Renderer.build(templatename)
# Meta data passed to the template as @metadata[:name]
metadata = {
:module_name => module_name,
- :workdir => puppet_module.working_directory,
+ :workdir => puppet_module.working_directory,
:target_file => target_file,
}
template = Renderer.render(erb, configs, metadata)
Renderer.sync(template, target_file)
- rescue StandardError => e
+ rescue StandardError
$stderr.puts "#{puppet_module.given_name}: Error while rendering file: '#{filename}'"
raise
end
end
end
def self.manage_module(puppet_module, module_files, defaults)
puts "Syncing '#{puppet_module.given_name}'"
- puppet_module.repository.prepare_workspace(options[:branch]) unless options[:offline]
+ # NOTE: #prepare_workspace now supports to execute only offline operations
+ # but we totally skip the workspace preparation to keep the current behavior
+ unless options[:offline]
+ puppet_module.repository.prepare_workspace(branch: options[:branch],
+ operate_offline: false)
+ end
module_configs = Util.parse_config puppet_module.path(MODULE_CONF_FILE)
settings = Settings.new(defaults[GLOBAL_DEFAULTS_KEY] || {},
defaults,
module_configs[GLOBAL_DEFAULTS_KEY] || {},
@@ -127,27 +132,26 @@
files_to_manage = settings.managed_files(module_files)
files_to_manage.each { |filename| manage_file(puppet_module, filename, settings, options) }
if options[:noop]
puts "Using no-op. Files in '#{puppet_module.given_name}' may be changed but will not be committed."
- puppet_module.repository.show_changes(options)
- options[:pr] && \
- pr(puppet_module).manage(puppet_module.repository_namespace, puppet_module.repository_name, options)
+ changed = puppet_module.repository.show_changes(options)
+ changed && options[:pr] && puppet_module.open_pull_request
elsif !options[:offline]
pushed = puppet_module.repository.submit_changes(files_to_manage, options)
# Only bump/tag if pushing didn't fail (i.e. there were changes)
if pushed && options[:bump]
new = puppet_module.bump(options[:message], options[:changelog])
puppet_module.repository.tag(new, options[:tag_pattern]) if options[:tag]
end
- pushed && options[:pr] && \
- pr(puppet_module).manage(puppet_module.repository_namespace, puppet_module.repository_name, options)
+ pushed && options[:pr] && puppet_module.open_pull_request
end
end
def self.config_path(file, options)
return file if Pathname.new(file).absolute?
+
File.join(options[:configs], file)
end
def config_path(file, options)
self.class.config_path(file, options)
@@ -155,74 +159,108 @@
def self.update(cli_options)
@options = config_defaults.merge(cli_options)
defaults = Util.parse_config(config_path(CONF_FILE, options))
- if options[:pr]
- unless options[:branch]
- $stderr.puts 'A branch must be specified with --branch to use --pr!'
- raise
- end
-
- @pr = create_pr_manager if options[:pr]
- end
-
local_template_dir = config_path(MODULE_FILES_DIR, options)
local_files = find_template_files(local_template_dir)
module_files = relative_names(local_files, local_template_dir)
errors = false
# managed_modules is either an array or a hash
managed_modules.each do |puppet_module|
- begin
- manage_module(puppet_module, module_files, defaults)
- rescue ModuleSync::Error, Git::GitExecuteError => e
- message = e.message || "Error during '#{options[:command]}'"
- $stderr.puts "#{puppet_module.given_name}: #{message}"
- exit 1 unless options[:skip_broken]
- errors = true
- $stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
- rescue StandardError => e
- raise unless options[:skip_broken]
- errors = true
- $stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
- end
+ manage_module(puppet_module, module_files, defaults)
+ rescue ModuleSync::Error, Git::GitExecuteError => e
+ message = e.message || 'Error during `update`'
+ $stderr.puts "#{puppet_module.given_name}: #{message}"
+ exit 1 unless options[:skip_broken]
+ errors = true
+ $stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
+ rescue StandardError
+ raise unless options[:skip_broken]
+
+ errors = true
+ $stdout.puts "Skipping '#{puppet_module.given_name}' as update process failed"
end
exit 1 if errors && options[:fail_on_warnings]
end
- def self.pr(puppet_module)
- module_options = puppet_module.options
- github_conf = module_options[:github]
- gitlab_conf = module_options[:gitlab]
+ def self.clone(cli_options)
+ @options = config_defaults.merge(cli_options)
- if !github_conf.nil?
- base_url = github_conf[:base_url] || ENV.fetch('GITHUB_BASE_URL', 'https://api.github.com')
- require 'modulesync/pr/github'
- ModuleSync::PR::GitHub.new(github_conf[:token], base_url)
- elsif !gitlab_conf.nil?
- base_url = gitlab_conf[:base_url] || ENV.fetch('GITLAB_BASE_URL', 'https://gitlab.com/api/v4')
- require 'modulesync/pr/gitlab'
- ModuleSync::PR::GitLab.new(gitlab_conf[:token], base_url)
- elsif @pr.nil?
- $stderr.puts 'No GitHub or GitLab token specified for --pr!'
- raise
- else
- @pr
+ managed_modules.each do |puppet_module|
+ puppet_module.repository.clone unless puppet_module.repository.cloned?
end
end
- def self.create_pr_manager
- github_token = ENV.fetch('GITHUB_TOKEN', '')
- gitlab_token = ENV.fetch('GITLAB_TOKEN', '')
+ def self.execute(cli_options)
+ @options = config_defaults.merge(cli_options)
- if !github_token.empty?
- require 'modulesync/pr/github'
- ModuleSync::PR::GitHub.new(github_token, ENV.fetch('GITHUB_BASE_URL', 'https://api.github.com'))
- elsif !gitlab_token.empty?
- require 'modulesync/pr/gitlab'
- ModuleSync::PR::GitLab.new(gitlab_token, ENV.fetch('GITLAB_BASE_URL', 'https://gitlab.com/api/v4'))
- else
- warn '--pr specified without environment variables GITHUB_TOKEN or GITLAB_TOKEN'
+ errors = {}
+ managed_modules.each do |puppet_module|
+ $stdout.puts "#{puppet_module.given_name}:"
+
+ puppet_module.repository.clone unless puppet_module.repository.cloned?
+ puppet_module.repository.switch branch: @options[:branch]
+
+ command_args = cli_options[:command_args]
+ local_script = File.expand_path command_args[0]
+ command_args[0] = local_script if File.exist?(local_script)
+
+ # Remove bundler-related env vars to allow the subprocess to run `bundle`
+ command_env = ENV.reject { |k, _v| k.match?(/(^BUNDLE|^SOURCE_DATE_EPOCH$|^GEM_|RUBY)/) }
+
+ result = system command_env, *command_args, unsetenv_others: true, chdir: puppet_module.working_directory
+ unless result
+ message = "Command execution failed ('#{@options[:command_args].join ' '}': #{$CHILD_STATUS})"
+ raise Thor::Error, message if @options[:fail_fast]
+
+ errors.merge!(
+ puppet_module.given_name => message,
+ )
+ $stderr.puts message
+ end
+
+ $stdout.puts ''
+ end
+
+ unless errors.empty?
+ raise Thor::Error, <<~MSG
+ Error(s) during `execute` command:
+ #{errors.map { |name, message| " * #{name}: #{message}" }.join "\n"}
+ MSG
+ end
+
+ exit 1 unless errors.empty?
+ end
+
+ def self.reset(cli_options)
+ @options = config_defaults.merge(cli_options)
+ if @options[:branch].nil?
+ raise Thor::Error,
+ "Error: 'branch' option is missing, please set it in configuration or in command line."
+ end
+
+ managed_modules.each do |puppet_module|
+ puppet_module.repository.reset_workspace(
+ branch: @options[:branch],
+ source_branch: @options[:source_branch],
+ operate_offline: @options[:offline],
+ )
+ end
+ end
+
+ def self.push(cli_options)
+ @options = config_defaults.merge(cli_options)
+
+ if @options[:branch].nil?
+ raise Thor::Error,
+ "Error: 'branch' option is missing, please set it in configuration or in command line."
+ end
+
+ managed_modules.each do |puppet_module|
+ puppet_module.repository.push branch: @options[:branch], remote_branch: @options[:remote_branch]
+ rescue ModuleSync::Error => e
+ raise Thor::Error, "#{puppet_module.given_name}: #{e.message}"
end
end
end