pdksync 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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)