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.
@@ -0,0 +1,41 @@
1
+ # PUPPET VERSION PLATFORM COMPATIBILITY
2
+ #
3
+ # Define the Puppet version as a root key, then specify the OS platform(s) and versions(s) that this Puppet version is
4
+ # compatible with AND that you wish to test on. If you wish to exclude a platform from testing, simply omit it.
5
+ #
6
+ # OS names and versions must conform to the VMPooler nomenclature and conventions.
7
+ #
8
+ # Running 'bundle exec rake 'pdksync:generate_vmpooler_release_checks[7]' will generate an entry in the 'provision.yaml'
9
+ # for each managed module that contains a configuration that satisfies both:
10
+ # - The module's compatible platforms
11
+ # - The Puppet version's compatible platforms (in this example: '7')
12
+ #
13
+ # NOTE: arch will always be assumed to be 'x86_64'
14
+ ---
15
+ 5:
16
+ centos: ['5', '6', '7', '8']
17
+ debian: ['8', '9', '10']
18
+ oracle: ['5', '6', '7']
19
+ redhat: ['5', '6', '7', '8']
20
+ sles: ['12', '15']
21
+ scientific: ['6', '7']
22
+ ubuntu: ['14.04', '16.04', '18.04']
23
+ win: ['2008r2', '2012r2', '2016', '2019', '10-pro']
24
+ 6:
25
+ centos: ['5', '6', '7', '8']
26
+ debian: ['8', '9', '10']
27
+ oracle: ['5', '6', '7']
28
+ redhat: ['5', '6', '7', '8']
29
+ sles: ['12', '15']
30
+ scientific: ['6', '7']
31
+ ubuntu: ['14.04', '16.04', '18.04', '20.04']
32
+ win: ['2008r2', '2012r2', '2016', '2019', '10-pro']
33
+ 7:
34
+ centos: ['7', '8']
35
+ debian: ['9', '10']
36
+ oracle: ['7']
37
+ redhat: ['7', '8']
38
+ sles: ['12', '15']
39
+ scientific: ['7']
40
+ ubuntu: ['18.04', '20.04']
41
+ win: ['2012r2', '2016', '2019', '10-pro']
@@ -0,0 +1,155 @@
1
+ require 'yaml'
2
+ require 'pdk/version'
3
+ require 'ostruct'
4
+
5
+ # @summary
6
+ # A class used to contain a set of configuration variables
7
+ # @note
8
+ # Configuration is loaded from `$HOME/.pdksync.yml`. If $HOME is not set, the config_path will use the current directory.
9
+ # The configuration filename and path can be overridden with env variable PDK_CONFIG_PATH
10
+ # Set PDKSYNC_LABEL to '' to disable adding a label during pdksync runs.
11
+ module PdkSync
12
+ class Configuration < OpenStruct
13
+ SUPPORTED_SCM_PLATFORMS = [:github, :gitlab].freeze
14
+ PDKSYNC_FILE_NAME = 'pdksync.yml'.freeze
15
+
16
+ # Any key value added to the default config or custom config
17
+ # will automatically be a new configuration item and referenced
18
+ # via Configuration.new.<key_name> ie.
19
+ # c = Configuration.new
20
+ # c.api_endpoint
21
+ DEFAULT_CONFIG = {
22
+ namespace: 'puppetlabs',
23
+ pdksync_dir: 'modules_pdksync',
24
+ pdksync_gem_dir: 'gems_pdksync',
25
+ push_file_destination: 'origin',
26
+ create_pr_against: 'main',
27
+ managed_modules: 'managed_modules.yml',
28
+ pdksync_label: 'maintenance',
29
+ git_platform: :github,
30
+ git_base_uri: 'https://github.com',
31
+ gitlab_api_endpoint: 'https://gitlab.com/api/v4',
32
+ api_endpoint: nil,
33
+ pdk_templates_prefix: nil,
34
+ pdk_templates_ref: PDK::VERSION,
35
+ pdk_templates_url: 'https://github.com/puppetlabs/pdk-templates.git',
36
+ jenkins_platform: :jenkins,
37
+ jenkins_base_uri: 'https://jenkins.io',
38
+ jenkins_api_endpoint: '',
39
+ jenkins_server_url: '',
40
+ module_is_authoritive: true
41
+ }.freeze
42
+
43
+ # @param config_path [String] - the path to the pdk config file
44
+ def initialize(config_path = ENV['PDKSYNC_CONFIG_PATH'])
45
+ @config_path = locate_config_path(config_path)
46
+ @custom_config = DEFAULT_CONFIG.merge(custom_config(@config_path))
47
+ @custom_config[:pdk_templates_ref] = "#{@custom_config[:pdk_templates_prefix]}#{@custom_config[:pdk_templates_ref]}"
48
+ super(@custom_config)
49
+ valid_scm?(git_platform)
50
+ valid_access_token?
51
+ end
52
+
53
+ # @return [Hash] - returns the access settings for git scm
54
+ def git_platform_access_settings
55
+ @git_platform_access_settings ||= {
56
+ access_token: access_token,
57
+ gitlab_api_endpoint: gitlab_api_endpoint || api_endpoint,
58
+ api_endpoint: api_endpoint
59
+
60
+ }
61
+ end
62
+
63
+ def jenkins_platform_access_settings
64
+ @jenkins_platform_access_settings ||= {
65
+ jenkins_username: ENV['JENKINS_USERNAME'].freeze,
66
+ jenkins_password: ENV['JENKINS_PASSWORD'].freeze,
67
+ jenkins_api_endpoint: ''
68
+ }
69
+ end
70
+
71
+ # @return [Hash] - returns the access settings for gemfury account
72
+ def gemfury_access_settings
73
+ valid_access_token_gem_fury?
74
+ @gemfury_access_token = access_token_gem_fury
75
+ end
76
+
77
+ # @return [String] return a rendered string for pdk to use the templates
78
+ def templates
79
+ "--template-url=#{pdk_templates_url} --template-ref=#{pdk_templates_ref}"
80
+ end
81
+
82
+ # @param path [String] path to the pdksync config file in yaml format
83
+ # @return [Hash] the custom configuration as a hash
84
+ def custom_config(path = nil)
85
+ return {} unless path
86
+ return {} unless File.exist?(path)
87
+ c = (YAML.load_file(path) || {}).transform_keys_to_symbols
88
+ c[:git_base_uri] ||= 'https://gitlab.com' if c[:git_platform].eql?(:gitlab)
89
+ c
90
+ end
91
+
92
+ # @return [String] the path the pdksync config file, nil if not found
93
+ def locate_config_path(custom_file = nil)
94
+ files = [
95
+ custom_file,
96
+ PDKSYNC_FILE_NAME,
97
+ File.join(ENV['HOME'], PDKSYNC_FILE_NAME)
98
+ ]
99
+ files.find { |file| file && File.exist?(file) }
100
+ end
101
+
102
+ private
103
+
104
+ # @return [Boolean] true if the supported platforms were specified correctly
105
+ # @param scm [Symbol] - the scm type (:github or :gitlab)
106
+ def valid_scm?(scm)
107
+ unless SUPPORTED_SCM_PLATFORMS.include?(scm)
108
+ raise ArgumentError, "Unsupported Git hosting platform '#{scm}'."\
109
+ " Supported platforms are: #{SUPPORTED_SCM_PLATFORMS.join(', ')}"
110
+ end
111
+ true
112
+ end
113
+
114
+ # @return [Boolean] true if the access token for the scm platform was supplied
115
+ def valid_access_token?
116
+ if access_token.nil?
117
+ raise ArgumentError, "Git platform access token for #{git_platform.capitalize} not set"\
118
+ " - use 'export #{git_platform.upcase}_TOKEN=\"<your token>\"' to set"
119
+ end
120
+ true
121
+ end
122
+
123
+ # @return [Boolean] true if the access token for the gemfury was supplied
124
+ def valid_access_token_gem_fury?
125
+ if access_token_gem_fury.nil?
126
+ raise 'Gemfury access token not set'\
127
+ " - use 'export GEMFURY_TOKEN=\"<your token>\"' to set"
128
+ end
129
+ true
130
+ end
131
+
132
+ # @return [String] the platform specific access token
133
+ def access_token
134
+ case git_platform
135
+ when :github
136
+ ENV['GITHUB_TOKEN'].freeze
137
+ when :gitlab
138
+ ENV['GITLAB_TOKEN'].freeze
139
+ end
140
+ end
141
+
142
+ # @return [String] the gem_fury access token
143
+ def access_token_gem_fury
144
+ ENV['GEMFURY_TOKEN'].freeze
145
+ end
146
+ end
147
+ end
148
+
149
+ # monkey patch
150
+ class Hash
151
+ # take keys of hash and transform those to a symbols
152
+ def transform_keys_to_symbols
153
+ each_with_object({}) { |(k, v), memo| memo[k.to_sym] = v; }
154
+ end
155
+ end
@@ -10,7 +10,9 @@ class PdkSync::GithubClient
10
10
  # supplied access token
11
11
  # @param access_token
12
12
  # The Github access token, required to access the Github API
13
- def initialize(access_token)
13
+ def initialize(access_token, api_endpoint = nil)
14
+ # USE ENV['OCTOKIT_API_ENDPOINT'] or pass in the api_endpoint
15
+ Octokit.configure { |c| c.api_endpoint = api_endpoint } unless api_endpoint.nil?
14
16
  @client = Octokit::Client.new(access_token: access_token.to_s)
15
17
  @client.user.login
16
18
  end
@@ -26,11 +26,11 @@ class PdkSync::GitPlatformClient
26
26
  when :github
27
27
  require 'pdksync/githubclient'
28
28
 
29
- PdkSync::GithubClient.new(access_token)
29
+ PdkSync::GithubClient.new(access_token, git_platform_access_settings[:api_endpoint])
30
30
  when :gitlab
31
31
  require 'pdksync/gitlabclient'
32
32
 
33
- gitlab_api_endpoint = git_platform_access_settings[:gitlab_api_endpoint]
33
+ gitlab_api_endpoint = git_platform_access_settings[:gitlab_api_endpoint] || git_platform_access_settings[:api_endpoint]
34
34
  PdkSync::GitlabClient.new(access_token, gitlab_api_endpoint)
35
35
  end
36
36
  end
@@ -0,0 +1,50 @@
1
+ require 'jenkins_api_client'
2
+
3
+ # @summary
4
+ # This class wraps Gitlab::JenkinsCLient and provides the method implementations
5
+ # required by pdksync main to access the Jenkins API for creating jobs in jenkins
6
+ class PdkSync::JenkinsClient
7
+ # @summary
8
+ # Creates a new Jenkins::Client and logs in the user based on the
9
+ # supplied user credentials and the Jenkins API endpoint URL
10
+ # @param [String] jenkins_platform_access_settings
11
+ # The Jenkins credentials, required to access the Jenkins API
12
+
13
+ def initialize(jenkins_server_url, jenkins_platform_access_settings)
14
+ jenkins_username = jenkins_platform_access_settings[:jenkins_username]
15
+ jenkins_password = jenkins_platform_access_settings[:jenkins_password]
16
+ @client = JenkinsApi::Client.new('server_url' => jenkins_server_url,
17
+ 'username' => jenkins_username,
18
+ 'password' => jenkins_password)
19
+ end
20
+
21
+ # @summary
22
+ # Creates a new adhoc job against the jenkins
23
+ # platform
24
+ # @param [String] github_repo
25
+ # Repo or Module for which the adhoc job to be created
26
+ # @param [String] github_branch
27
+ # The target branch against which to create the adhoc job
28
+ # @return
29
+ # Build Id returned by the job
30
+ def create_adhoc_job(github_repo, github_branch, github_user, job_name)
31
+ # params to start the build
32
+ job_params = { 'GITHUB_USER' => github_user,
33
+ 'GITHUB_REPO' => github_repo,
34
+ 'GITHUB_REF' => github_branch }
35
+ # job name
36
+ # Wait for up to 30 seconds, attempt to cancel queued build
37
+ opts = { 'build_start_timeout' => 30,
38
+ 'cancel_on_build_start_timeout' => true,
39
+ 'completion_proc' => lambda { |build_number, cancelled| # rubocop:disable Style/Lambda
40
+ if build_number
41
+ PdkSync::Logger.info "Wait over: build #{build_number} started"
42
+ else
43
+ PdkSync::Logger.info "Wait over: build not started, build #{cancelled ? '' : 'NOT '} cancelled"
44
+ end
45
+ } }
46
+
47
+ build_id = @client.job.build(job_name, job_params || {}, opts)
48
+ build_id
49
+ end
50
+ end
@@ -0,0 +1,116 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
5
+ class String
6
+ def colorize(color_code)
7
+ "\e[#{color_code}m#{self}\e[0m"
8
+ end
9
+
10
+ def red
11
+ colorize(31)
12
+ end
13
+
14
+ def green
15
+ colorize(32)
16
+ end
17
+
18
+ def fatal
19
+ red
20
+ end
21
+
22
+ def yellow
23
+ colorize(33)
24
+ end
25
+
26
+ def light_blue
27
+ colorize(36)
28
+ end
29
+ end
30
+
31
+ module PdkSync
32
+ class Logger
33
+ def self.warn(message)
34
+ logger.warn(message)
35
+ end
36
+
37
+ def self.info(message)
38
+ logger.info(message)
39
+ end
40
+
41
+ def self.debug(message)
42
+ logger.debug(message)
43
+ end
44
+
45
+ def self.fatal(message)
46
+ logger.fatal(message)
47
+ end
48
+
49
+ def self.crit(message)
50
+ logger.error(message)
51
+ end
52
+
53
+ def self.log_file
54
+ if ENV['PDKSYNC_LOG_FILENAME'] && File.exist?(ENV['PDKSYNC_LOG_FILENAME'])
55
+ ENV['PDKSYNC_LOG_FILENAME']
56
+ else
57
+ STDOUT
58
+ end
59
+ end
60
+
61
+ def self.logger(file = PdkSync::Logger.log_file)
62
+ @logger ||= begin
63
+ log = ::Logger.new(file)
64
+ log.level = log_level
65
+ log.progname = 'PdkSync'
66
+ log.formatter = proc do |severity, datetime, progname, msg|
67
+ if PdkSync::Logger.log_file == STDOUT
68
+ "#{severity} - #{progname}: #{msg}\n".send(color(severity))
69
+ else
70
+ "#{datetime} #{severity} - #{progname}: #{msg}\n".send(color(severity))
71
+ end
72
+ end
73
+ log
74
+ end
75
+ end
76
+
77
+ def logger
78
+ @logger ||= PdkSync::Logger.logger
79
+ end
80
+
81
+ def self.color(severity)
82
+ case severity
83
+ when ::Logger::Severity::WARN, 'WARN'
84
+ :yellow
85
+ when ::Logger::Severity::INFO, 'INFO'
86
+ :green
87
+ when ::Logger::Severity::FATAL, 'FATAL'
88
+ :fatal
89
+ when ::Logger::Severity::ERROR, 'ERROR'
90
+ :fatal
91
+ when ::Logger::Severity::DEBUG, 'DEBUG'
92
+ :light_blue
93
+ else
94
+ :green
95
+ end
96
+ end
97
+
98
+ def self.log_level
99
+ level = ENV['LOG_LEVEL'].downcase if ENV['LOG_LEVEL']
100
+ case level
101
+ when 'warn'
102
+ ::Logger::Severity::WARN
103
+ when 'fatal'
104
+ ::Logger::Severity::FATAL
105
+ when 'debug'
106
+ ::Logger::Severity::DEBUG
107
+ when 'info'
108
+ ::Logger::Severity::INFO
109
+ when 'error'
110
+ ::Logger::Severity::ERROR
111
+ else
112
+ ::Logger::Severity::INFO
113
+ end
114
+ end
115
+ end
116
+ end
@@ -10,6 +10,23 @@ task :pdksync, [:additional_title] do |_task, args|
10
10
  PdkSync.main(steps: [:use_pdk_ref, :clone, :pdk_update, :create_commit, :push, :create_pr], args: args)
11
11
  end
12
12
 
13
+ desc 'Run full gem_testing process, clone repository, gemfile update, create pr. Additional title information can be added to the title, which will be appended before the reference section.'
14
+ task :gem_testing, [:additional_title, :gem_to_test, :gem_line, :gem_sha_finder, :gem_sha_replacer, :gem_version_finder, :gem_version_replacer, :gem_branch_finder, :gem_branch_replacer] do |_task, args| # rubocop:disable Metrics/LineLength
15
+ args = { branch_name: 'pdksync_gem_testing{ref}',
16
+ commit_message: 'pdksync_gem_testing{ref}',
17
+ pr_title: 'pdksync_gem_testing{ref}',
18
+ additional_title: args[:additional_title],
19
+ gem_to_test: args[:gem_to_test],
20
+ gem_line: args[:gem_line],
21
+ gem_sha_finder: args[:gem_sha_finder],
22
+ gem_sha_replacer: args[:gem_sha_replacer],
23
+ gem_version_finder: args[:gem_version_finder],
24
+ gem_version_replacer: args[:gem_version_replacer],
25
+ gem_branch_finder: args[:gem_branch_finder],
26
+ gem_branch_replacer: args[:gem_branch_replacer] }
27
+ PdkSync.main(steps: [:use_gem_ref, :clone, :gem_file_update, :create_commit, :push, :create_pr], args: args)
28
+ end
29
+
13
30
  namespace :pdksync do
14
31
  desc 'Runs PDK convert against modules'
15
32
  task :pdk_convert do
@@ -21,27 +38,89 @@ namespace :pdksync do
21
38
  PdkSync.main(steps: [:pdk_validate])
22
39
  end
23
40
 
24
- desc "Run a command against modules eg rake 'run_a_command[complex command here -f -gx]'"
25
- task :run_a_command, [:command] do |_task, args|
26
- PdkSync.main(steps: [:run_a_command], args: args[:command])
41
+ desc "Run a command against modules eg rake 'run_a_command[complex command here -f -gx, 'background']'"
42
+ task :run_a_command, [:command, :option] do |_task, args|
43
+ PdkSync.main(steps: [:run_a_command], args: args)
44
+ end
45
+
46
+ desc "Gem File Update'gem_file_update[gem_to_test, gem_line, gem_sha_finder, gem_sha_replacer, gem_version_finder, gem_version_replacer, gem_branch_finder, gem_branch_replacer]'"
47
+ task :gem_file_update, [:gem_to_test, :gem_line, :gem_sha_finder, :gem_sha_replacer, :gem_version_finder, :gem_version_replacer, :gem_branch_finder, :gem_branch_replacer] do |_task, args|
48
+ PdkSync.main(steps: [:gem_file_update], args: args)
49
+ end
50
+
51
+ desc "Run test against modules eg rake 'run_tests_locally[litmus, 'provision_type']'"
52
+ task :run_tests_locally, [:provision_type, :puppet_collection] do |_task, args|
53
+ PdkSync.main(steps: [:run_tests_locally], args: args)
54
+ end
55
+
56
+ desc "Fetch run results against modules eg rake 'fetch_test_results_locally[litmus]'"
57
+ task :fetch_test_results_locally do
58
+ PdkSync.main(steps: [:fetch_test_results_locally])
59
+ end
60
+
61
+ desc "Run test in jenkins for traditional modules eg rake 'run_tests_jenkins['jenkins_server_url', 'branchname']'"
62
+ task :run_tests_jenkins, [:jenkins_server_url, :github_branch, :test_framework, :github_user] do |_task, args|
63
+ PdkSync.main(steps: [:run_tests_jenkins], args: args)
64
+ end
65
+
66
+ desc 'Multi Gem Testing, multi_gem_testing[gem_name, version_file, build_gem, gem_path, gemfury_username]'
67
+ task :multi_gem_testing, [:gem_name, :version_file, :build_gem, :gem_path, :gemfury_username] do |_task, args|
68
+ PdkSync.main(steps: [:multi_gem_testing], args: args)
69
+ end
70
+
71
+ desc 'Multi Gem File Update, multigem_file_update[gem_name, gemfury_username]'
72
+ task :multigem_file_update, [:gem_name, :gemfury_username] do |_task, args|
73
+ PdkSync.main(steps: [:multigem_file_update], args: args)
27
74
  end
28
75
 
29
76
  desc 'Display the current configuration of pdksync'
30
77
  task :show_config do
31
- include PdkSync::Constants
78
+ config = PdkSync::Configuration.new
32
79
  puts 'Please note that you can override any of the configuration by using an additional file at `$HOME/.pdksync.yml`.'.bold.red
33
- puts 'PDKSync Configuration'.bold.yellow
34
- puts '- Git hosting platform: '.bold + PdkSync::Constants::GIT_PLATFORM.to_s.cyan
35
- puts '- Git base URI: '.bold + PdkSync::Constants::GIT_BASE_URI.to_s.cyan
36
- if PdkSync::Constants::GIT_PLATFORM == :gitlab
37
- puts '- Gitlab API endpoint: '.bold + PdkSync::Constants::GITLAB_API_ENDPOINT.to_s.cyan
80
+ puts "\nPDKSync Configuration".bold.yellow
81
+ config.to_h.each do |key, value|
82
+ puts "- #{key}: ".bold + value.to_s.cyan
38
83
  end
39
- puts '- Namespace: '.bold + PdkSync::Constants::NAMESPACE.to_s.cyan
40
- puts '- PDKSync Dir: '.bold + PdkSync::Constants::PDKSYNC_DIR.to_s.cyan
41
- puts '- Push File Destination: '.bold + PdkSync::Constants::PUSH_FILE_DESTINATION.to_s.cyan
42
- puts '- Create PR Against: '.bold + PdkSync::Constants::CREATE_PR_AGAINST.to_s.cyan
43
- puts '- Managed Modules: '.bold + PdkSync::Constants::MANAGED_MODULES.to_s.cyan
44
- puts '- Default PDKSync Label: '.bold + PdkSync::Constants::PDKSYNC_LABEL.to_s.cyan
84
+ end
85
+
86
+ desc "Fetch run results against traditional modules eg rake 'fetch_traditional_test_results'"
87
+ task :test_results_jenkins, [:jenkins_server_url] do |_task, args|
88
+ PdkSync.main(steps: [:test_results_jenkins], args: args)
89
+ end
90
+
91
+ desc 'Add a provision list key to provision.yaml'
92
+ task :add_provision_list, [:key, :provisioner, :images] do |_task, args|
93
+ PdkSync.main(steps: [:add_provision_list], args: args)
94
+ end
95
+
96
+ desc 'Generates release checks in provision.yaml based on module compatible platforms and puppet version'
97
+ task :generate_vmpooler_release_checks, [:puppet_version] do |_task, args|
98
+ PdkSync.main(steps: [:generate_vmpooler_release_checks], args: args)
99
+ end
100
+
101
+ desc 'Update the metadata.json OS supported list to that defined in conf/supported_os_list.yaml'
102
+ task :update_os_support do |_task, args|
103
+ PdkSync.main(steps: [:update_os_support], args: args)
104
+ end
105
+
106
+ desc 'Remove a platform version from the metadata.json'
107
+ task :remove_platform_from_metadata, [:os, :version] do |_task, args|
108
+ PdkSync.main(steps: [:remove_platform_from_metadata], args: args)
109
+ end
110
+
111
+ desc 'Add a platform version to the metadata.json'
112
+ task :add_platform_to_metadata, [:os, :version] do |_task, args|
113
+ PdkSync.main(steps: [:add_platform_to_metadata], args: args)
114
+ end
115
+
116
+ desc 'Add or update a requirement in the metadata.json'
117
+ task :update_requirements, [:name, :key, :value] do |_task, args|
118
+ PdkSync.main(steps: [:update_requirements], args: args)
119
+ end
120
+
121
+ desc 'Normalise the OS and OS versions in the metadata.json'
122
+ task :normalize_metadata_supported_platforms do |_task, args|
123
+ PdkSync.main(steps: [:normalize_metadata_supported_platforms], args: args)
45
124
  end
46
125
  end
47
126
 
@@ -51,6 +130,11 @@ namespace :git do
51
130
  PdkSync.main(steps: [:clone])
52
131
  end
53
132
 
133
+ desc 'Clone managed gem'
134
+ task :clone_gem, [:gem_name] do |_task, args|
135
+ PdkSync.main(steps: [:clone_gem], args: args)
136
+ end
137
+
54
138
  desc "Stage commits for modules, branchname and commit message eg rake 'git:create_commit[flippity, commit messagez]'"
55
139
  task :create_commit, [:branch_name, :commit_message] do |_task, args|
56
140
  PdkSync.main(steps: [:create_commit], args: args)