pdksync 0.3.0 → 0.4.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
- SHA1:
3
- metadata.gz: dcb6ea51b43a295e28ab7a3bb90ccf3d398ccdbd
4
- data.tar.gz: f214afd41acd5fc6bba7557e3ce79230a8e1dde8
2
+ SHA256:
3
+ metadata.gz: ab2ac9994044ffbddbbe2a6a18933d764477c2cdff17578abc2b203272c0bca0
4
+ data.tar.gz: da3644827bdad46868369dd0297ebae4dedfd15225ccf41def3aecdb5c0bfd73
5
5
  SHA512:
6
- metadata.gz: 69ee152722be2fa9a862727de092981c1c9855a44c36e5b1033b22a4883585a0ef8596fa666ca8d65443ae2fec3244c16b590e7d034a479ba83e30baf3773ee5
7
- data.tar.gz: 542e70e07027ad294e99d5d0933b36e586feed3bd55c3036edef2eb26832eea3cb8324d7ff50297be69eb01e78dd7dabd376679097e4a0686a83f45696c194d8
6
+ metadata.gz: 9d35e566ef6c5f29fdff5536721343d9c21aeedca3c3465afc4813183cc6b3ff6919687e43c63167649a6024fb711f420fbd9d604f402880eb99d32d0c1483f1
7
+ data.tar.gz: e5a4b656cc8a940d106a652b6a3818e3fc7106020b3581d192eb2d5706183a069edf59e1d6196c4aaf06c495f876bfe6c2591079abbb3e9b585196a863bf91ba
data/CHANGELOG.md CHANGED
@@ -2,9 +2,23 @@
2
2
 
3
3
  All 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).
4
4
 
5
- ## [0.3.0](https://github.com/puppetlabs/pdksync/tree/0.3.0) (2018-11-15)
5
+ ## [0.4.0](https://github.com/puppetlabs/pdksync/tree/0.4.0) (2019-02-04)
6
6
 
7
- [Full Changelog](https://github.com/puppetlabs/pdksync/compare/0.2.0...0.3.0)
7
+ [Full Changelog](https://github.com/puppetlabs/pdksync/compare/v0.3.0...0.4.0)
8
+
9
+ ### Added
10
+
11
+ - \(MODULES-8419\) Refactor to add support for GitLab [\#85](https://github.com/puppetlabs/pdksync/pull/85) ([antaflos](https://github.com/antaflos))
12
+ - \(MODULES-7233\) - Add configurable file option [\#81](https://github.com/puppetlabs/pdksync/pull/81) ([eimlav](https://github.com/eimlav))
13
+
14
+ ### Fixed
15
+
16
+ - \(MODULES-8283\) - Fix PR title overwritten in pdksync runs [\#84](https://github.com/puppetlabs/pdksync/pull/84) ([eimlav](https://github.com/eimlav))
17
+ - \(MODULES-8382\) - Fix API rate limit false positive [\#83](https://github.com/puppetlabs/pdksync/pull/83) ([eimlav](https://github.com/eimlav))
18
+
19
+ ## [v0.3.0](https://github.com/puppetlabs/pdksync/tree/v0.3.0) (2018-11-15)
20
+
21
+ [Full Changelog](https://github.com/puppetlabs/pdksync/compare/0.2.0...v0.3.0)
8
22
 
9
23
  ### Added
10
24
 
data/README.md CHANGED
@@ -6,7 +6,7 @@ Table of Contents
6
6
  1. [Overview](#overview)
7
7
  2. [Usage](#usage)
8
8
  3. [How it works](#how-it-works)
9
- 4. [Installing](#installing)
9
+ 4. [Configuration](#configuration)
10
10
  5. [Workflow](#workflow)
11
11
  6. [Migrating from modulesync to pdksync](#migrating-from-modulesync-to-pdksync)
12
12
  7. [Contributing](#contributing)
@@ -14,17 +14,26 @@ Table of Contents
14
14
  ### Overview
15
15
  --------
16
16
 
17
- Pdksync is an efficient way to run a `pdk update` command against the various repositories that we manage — keeping them up-to-date with the changes made to PDK. It is a solution for converted modules that no longer run with modulesync.
17
+ Pdksync is an efficient way to run a `pdk update` command against the various Puppet module repositories that you manage — keeping them up-to-date with the changes made to PDK. It is a solution for converted modules that no longer run with modulesync.
18
+
19
+ Pdksync by default expects that your Puppet module repositories live on GitHub and will behave accordingly. It also supports GitLab as an alternative Git hosting platform.
18
20
 
19
21
  ### Usage
20
22
  ----------
21
23
 
22
- > Note: This tool creates a 'live' pull request against the master branch of the module it is running against — defined in `managed_modules.yml`. Before running this tool, ensure this file reflects the modules you wish it to run against, and that `constants.rb` is up-to-date with the correct namespace your modules reside in.
24
+ > Note: This tool creates a 'live' pull (merge) request against the master branch of the module it is running against — defined in `managed_modules.yml`. Before running this tool, ensure this file reflects the modules you wish it to run against. Additionally make sure that the Pdksync configuration file `$HOME/.pdksync.yml` sets the correct namespace, Git platform and Git base URI for your modules. See section [Configuration](#configuration) for details.
23
25
 
24
26
  1. To use pdksync, clone the GitHub repo or install it as a gem. Set up the environment by exporting a GitHub token:
25
- ```
26
- export GITHUB_TOKEN=<access_token>
27
- ```
27
+
28
+ ```
29
+ export GITHUB_TOKEN=<access_token>
30
+ ```
31
+
32
+ If you use GitLab instead of GitHub export your GitLab access token:
33
+
34
+ ```
35
+ export GITLAB_TOKEN=<access_token>
36
+ ```
28
37
  2. Before the script will run, you need to install the gems:
29
38
  ```
30
39
  bundle install --path .bundle/gems/
@@ -41,9 +50,10 @@ Pdksync is a gem that works to clone, update, and push module repositories. It i
41
50
 
42
51
  The gem takes in a file, `managed_modules.yml`, stored within the gem that lists all the repositories that need to be updated. It then clones them, one after another, so that a local copy exists. The update command is ran against this local copy, with the subsequent changes being added into a commit on a unique branch. It is then pushed back to the remote master — where the local copy was originally cloned. The commit is merged to the master via a pull request, causing the gem to begin to clone the next repository.
43
52
 
44
- By default, pdksync will supply a label to a PR (default is 'maintenance'). This can be changed by opening `lib/pdksync/constants.rb` and modifying the `PDKSYNC_LABEL` constant. You must ensure that the label selected exists on the modules that you are applying pdksync to. Should you wish to disable this feature, simply change `PDKSYNC_LABEL` to an empty string i.e. ''. Similarly, when supplying a label using the `git:push_and_create_pr` rake task, the label must exist on each of the managed modules to run successfully.
53
+ By default, pdksync will supply a label to a PR (default is 'maintenance'). This can be changed by creating `$HOME/.pdksync.yml` and setting the `pdksync_label` key. You must ensure that the label selected exists on the modules that you are applying pdksync to. Should you wish to disable this feature, simply change `pdksync_label` to an empty string i.e. `''`. Similarly, when supplying a label using the `git:push_and_create_pr` rake task, the label must exist on each of the managed modules to run successfully.
45
54
 
46
55
  The following rake tasks are available with pdksync:
56
+ - `show_config` Display the current configuration of pdksync
47
57
  - `git:clone_managed_modules` Clone managed modules.
48
58
  - `git:create_commit[:branch_name, :commit_message]` Stage commits for modules, branchname and commit message eg rake 'git:create_commit[flippity, commit messagez]'.
49
59
  - `git:push_and_create_pr[:pr_title, :label]` Push commit, and create PR for modules. Label is optional eg rake 'git:push_and_create_pr[pr title goes here, optional label right here]'.
@@ -55,10 +65,80 @@ The following rake tasks are available with pdksync:
55
65
  - `rake 'pdksync[MODULES-8231]'` PR title outputs as `pdksync - MODULES-8231 - pdksync_heads/master-0-gabccfb1`
56
66
  - `run_a_command[:command]` Run a command against modules eg rake 'run_a_command[complex command here -f -gx]'
57
67
 
68
+ ### Configuration
69
+
70
+ By default pdksync will use hardcoded values for configuring itself. However, if you wish to override these values, simply create `$HOME/.pdksync.yml` and use the following format:
71
+ ```
72
+ ---
73
+ namespace: 'puppetlabs'
74
+ pdksync_dir: 'modules_pdksync'
75
+ push_file_destination: 'origin'
76
+ create_pr_against: 'master'
77
+ managed_modules: 'managed_modules.yml'
78
+ pdksync_label: 'maintenance'
79
+ git_platform: :github
80
+ git_base_uri: 'https://github.com'
81
+ # Only used when git_platform is set to :gitlab
82
+ gitlab_api_endpoint: 'https://gitlab.com/api/v4'
83
+ ```
84
+
85
+ You may override any property. Those that are not specified in your config file will use their corresponding default value from `lib/pdksync/constants.rb`.
86
+
87
+ #### Git platform support
88
+
89
+ By default pdksync assumes you are hosting your Puppet modules on GitHub, and GitHub is the only platform officially supported by Puppetlabs in pdksync.
90
+
91
+ Pdksync also supports the GitLab platform, but without official support by Puppetlabs.
92
+
93
+ ##### GitHub
94
+
95
+ To use GitHub you only need to export your GitHub access token as the
96
+ environment variable `GITHUB_TOKEN` and configure the namespace in which your
97
+ modules are hosted in `$HOME/.pdksync.yml` as described above.
98
+
99
+ ##### GitLab
100
+
101
+ To use GitLab at `https://gitlab.com` you need to set `git_platform: :gitlab`
102
+ and configure the namespace of your modules in `$HOME/.pdksync.yml`. You also
103
+ need to export your GitLab access token as the environment variable
104
+ `GITLAB_TOKEN`.
105
+
106
+ Your `$HOME/.pdksync.yml` then looks like this:
107
+
108
+ ```
109
+ # ~/pdksync.yml
110
+ ---
111
+ namespace: 'acme'
112
+ git_platform: :gitlab
113
+ ```
114
+
115
+ Export your GitLab access token:
116
+
117
+ ```
118
+ $ export GITLAB_TOKEN=<your GitLab access token here>
119
+ ```
120
+
121
+ If you are running your own GitLab instance on premise or use a GitLab instance
122
+ other than the official one at `https://gitlab.com` you also need to configure
123
+ `git_base_uri` and `gitlab_api_endpoint` in `$HOME/.pdksync.yml` so that
124
+ pdksync knows from where to clone your modules and where to access to GitLab
125
+ API to create the live merge requests:
126
+
127
+ ```
128
+ # ~/pdksync.yml
129
+ ---
130
+ namespace: 'puppetmodules'
131
+ git_platform: :gitlab
132
+ git_base_uri: 'https://gitlab.example.com'
133
+ # alternatively use SSH:
134
+ #git_base_uri: 'ssh://git@gitlab.example.com:2222'
135
+ gitlab_api_endpoint: 'https://gitlab.example.com/api/v4'
136
+ ```
137
+
58
138
  ### Workflow
59
139
  --------
60
140
 
61
- It currently runs without additional arguments. To alter how it runs, make alterations to either the `constants.rb` or `managed_modules.yml`.
141
+ It currently runs without additional arguments. To alter how it runs, make alterations to either `HOME/.pdksync.yml` or `managed_modules.yml`.
62
142
 
63
143
  ### Managed modules
64
144
  ----------
@@ -71,7 +151,8 @@ This module runs through a pre-set array of modules, with this array set within
71
151
  - puppetlabs-stdlib
72
152
  - puppetlabs-mysql
73
153
  ```
74
- To add a module, add it to the list. To remove a module, remove it from the list.
154
+
155
+ To add a module, add it to the list. To remove a module, remove it from the list. If you wish to specify a custom managed modules file, use the `managed_modules` property in your configuration file to specify the path to the file.
75
156
 
76
157
  ### Migrating from modulesync to pdksync
77
158
  --------
data/Rakefile CHANGED
@@ -1,6 +1,24 @@
1
1
  require_relative 'lib/pdksync'
2
+ require 'colorize'
2
3
  require 'github_changelog_generator/task'
3
4
 
5
+ desc 'Display the current configuration of pdksync'
6
+ task :show_config do
7
+ include PdkSync::Constants
8
+ puts 'PDKSync Configuration'.bold.yellow
9
+ puts '- Git hosting platform: '.bold + "#{PdkSync::Constants::GIT_PLATFORM}".cyan
10
+ puts '- Git base URI: '.bold + "#{PdkSync::Constants::GIT_BASE_URI}".cyan
11
+ if PdkSync::Constants::GIT_PLATFORM == :gitlab
12
+ puts '- Gitlab API endpoint: '.bold + "#{PdkSync::Constants::GITLAB_API_ENDPOINT}".cyan
13
+ end
14
+ puts '- Namespace: '.bold + "#{PdkSync::Constants::NAMESPACE}".cyan
15
+ puts '- PDKSync Dir: '.bold + "#{PdkSync::Constants::PDKSYNC_DIR}".cyan
16
+ puts '- Push File Destination: '.bold + "#{PdkSync::Constants::PUSH_FILE_DESTINATION}".cyan
17
+ puts '- Create PR Against: '.bold + "#{PdkSync::Constants::CREATE_PR_AGAINST}".cyan
18
+ puts '- Managed Modules: '.bold + "#{PdkSync::Constants::MANAGED_MODULES}".cyan
19
+ puts '- Default PDKSync Label: '.bold + "#{PdkSync::Constants::PDKSYNC_LABEL}".cyan
20
+ end
21
+
4
22
  desc 'Run full pdksync process, clone repository, pdk update, create pr. Additional title information can be added to the title, which will be appended before the reference section.'
5
23
  task :pdksync, [:additional_title] do |task, args|
6
24
  args = {:branch_name => "pdksync_{ref}",
@@ -10,7 +28,7 @@ task :pdksync, [:additional_title] do |task, args|
10
28
  PdkSync::main(steps: [:use_pdk_ref, :clone, :pdk_update, :create_commit, :push_and_create_pr], args: args)
11
29
  end
12
30
 
13
- namespace :pdk do
31
+ namespace :pdk do
14
32
  desc 'Runs PDK convert against modules'
15
33
  task :pdk_convert do
16
34
  PdkSync::main(steps: [:pdk_convert])
@@ -53,7 +71,7 @@ GitHubChangelogGenerator::RakeTask.new :changelog do |config|
53
71
  config.user = 'puppetlabs'
54
72
  config.project = 'pdksync'
55
73
  # config.since_tag = '1.1.1'
56
- config.future_release = '0.3.0'
74
+ config.future_release = '0.4.0'
57
75
  config.exclude_labels = ['maintenance']
58
76
  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)."
59
77
  config.add_pr_wo_labels = true
data/lib/pdksync.rb CHANGED
@@ -4,8 +4,8 @@ require 'open3'
4
4
  require 'fileutils'
5
5
  require 'rake'
6
6
  require 'pdk'
7
- require 'octokit'
8
7
  require 'pdksync/constants'
8
+ require 'pdksync/gitplatformclient'
9
9
  require 'json'
10
10
  require 'yaml'
11
11
  require 'colorize'
@@ -13,8 +13,6 @@ require 'bundler'
13
13
 
14
14
  # @summary
15
15
  # This module set's out and controls the pdksync process
16
- # @param [String] @access_token
17
- # The token used to access github, must be exported locally.
18
16
  # @param [String] @namspace
19
17
  # The namespace of the repositories we are updating.
20
18
  # @param [String] @pdksync_dir
@@ -25,22 +23,37 @@ require 'bundler'
25
23
  # The branch the the pull requests are to be made against.
26
24
  # @param [String] @managed_modules
27
25
  # The file that the array of managed modules is to be retrieved from.
26
+ # @param [Symbol] @git_platform
27
+ # The Git hosting platform to use for pull requests
28
+ # @param [String] @git_base_uri
29
+ # The base URI for Git repository access, for example 'https://github.com' or
30
+ # 'ssh://git@repo.example.com:2222'
31
+ # @param [Hash] @git_platform_access_settings
32
+ # Hash of access settings required to access the configured Git hosting
33
+ # platform API. Must always contain the key :access_token set to the exported
34
+ # GITHUB_TOKEN or GITLAB_TOKEN. In case of Gitlab it also must contain the
35
+ # key :gitlab_api_endpoint with an appropriate value.
28
36
  module PdkSync
29
37
  include Constants
30
- @access_token = Constants::ACCESS_TOKEN
31
38
  @namespace = Constants::NAMESPACE
32
39
  @pdksync_dir = Constants::PDKSYNC_DIR
33
40
  @push_file_destination = Constants::PUSH_FILE_DESTINATION
34
41
  @create_pr_against = Constants::CREATE_PR_AGAINST
35
42
  @managed_modules = Constants::MANAGED_MODULES
36
43
  @default_pdksync_label = Constants::PDKSYNC_LABEL
44
+ @git_platform = Constants::GIT_PLATFORM
45
+ @git_base_uri = Constants::GIT_BASE_URI
46
+ @git_platform_access_settings = {
47
+ access_token: Constants::ACCESS_TOKEN,
48
+ gitlab_api_endpoint: Constants::GITLAB_API_ENDPOINT
49
+ }
37
50
 
38
51
  def self.main(steps: [:clone], args: nil)
39
52
  create_filespace
40
53
  client = setup_client
41
54
  module_names = return_modules
42
55
  raise "No modules found in '#{@managed_modules}'" if module_names.nil?
43
- validate_modules_exist(module_names)
56
+ validate_modules_exist(client, module_names)
44
57
  pr_list = []
45
58
 
46
59
  # The current directory is saved for cleanup purposes
@@ -59,7 +72,7 @@ module PdkSync
59
72
  # validation push_and_create_pr
60
73
  if steps.include?(:push_and_create_pr)
61
74
  raise 'Needs a pr_title' if args.nil? || args[:pr_title].nil?
62
- puts "PR title =#{args[:pr_title]}"
75
+ puts "PR title =#{args[:additional_title]} #{args[:pr_title]}"
63
76
  end
64
77
  # validation clean_branches
65
78
  if steps.include?(:clean_branches)
@@ -69,6 +82,7 @@ module PdkSync
69
82
 
70
83
  abort "No modules listed in #{@managed_modules}" if module_names.nil?
71
84
  module_names.each do |module_name|
85
+ module_args = args.clone
72
86
  Dir.chdir(main_path) unless Dir.pwd == main_path
73
87
  print "#{module_name}, "
74
88
  repo_name = "#{@namespace}/#{module_name}"
@@ -98,7 +112,7 @@ module PdkSync
98
112
  if steps.include?(:run_a_command)
99
113
  Dir.chdir(main_path) unless Dir.pwd == main_path
100
114
  print 'run command, '
101
- exit_status = run_command(output_path, args)
115
+ exit_status = run_command(output_path, module_args)
102
116
  next unless exit_status.zero?
103
117
  end
104
118
  if steps.include?(:pdk_update)
@@ -106,18 +120,18 @@ module PdkSync
106
120
  next unless pdk_update(output_path).zero?
107
121
  if steps.include?(:use_pdk_ref)
108
122
  ref = return_template_ref
109
- pr_title = args[:additional_title] ? "#{args[:additional_title]} - pdksync_#{ref}" : "pdksync_#{ref}"
110
- args = { branch_name: "pdksync_#{ref}",
111
- commit_message: "pdksync_#{ref}",
112
- pr_title: pr_title,
113
- pdksync_label: @default_pdksync_label }
123
+ pr_title = module_args[:additional_title] ? "#{module_args[:additional_title]} - pdksync_#{ref}" : "pdksync_#{ref}"
124
+ module_args = module_args.merge(branch_name: "pdksync_#{ref}",
125
+ commit_message: pr_title,
126
+ pr_title: pr_title,
127
+ pdksync_label: @default_pdksync_label)
114
128
  end
115
129
  print 'pdk update, '
116
130
  end
117
131
  if steps.include?(:create_commit)
118
132
  Dir.chdir(main_path) unless Dir.pwd == main_path
119
133
  git_instance = Git.open(output_path)
120
- create_commit(git_instance, args[:branch_name], args[:commit_message])
134
+ create_commit(git_instance, module_args[:branch_name], module_args[:commit_message])
121
135
  print 'commit created, '
122
136
  end
123
137
  if steps.include?(:push_and_create_pr)
@@ -128,7 +142,7 @@ module PdkSync
128
142
  pdk_version = return_pdk_version("#{output_path}/metadata.json")
129
143
 
130
144
  # If a label is supplied, verify that it is available in the repo
131
- label = args[:pdksync_label] ? args[:pdksync_label] : args[:label]
145
+ label = module_args[:pdksync_label] ? module_args[:pdksync_label] : module_args[:label]
132
146
  label_valid = (label.is_a?(String) && !label.to_str.empty?) ? check_for_label(client, repo_name, label) : nil
133
147
 
134
148
  # Exit current iteration if an error occured retrieving a label
@@ -137,7 +151,7 @@ module PdkSync
137
151
  end
138
152
 
139
153
  # Create the PR and add link to pr list
140
- pr = create_pr(client, repo_name, git_instance.current_branch, pdk_version, args[:pr_title])
154
+ pr = create_pr(client, repo_name, git_instance.current_branch, pdk_version, module_args[:pr_title])
141
155
  if pr.nil?
142
156
  break
143
157
  end
@@ -153,7 +167,7 @@ module PdkSync
153
167
  end
154
168
  if steps.include?(:clean_branches)
155
169
  Dir.chdir(main_path) unless Dir.pwd == main_path
156
- delete_branch(client, repo_name, args[:branch_name])
170
+ delete_branch(client, repo_name, module_args[:branch_name])
157
171
  print 'branch deleted, '
158
172
  end
159
173
  puts 'done.'.green
@@ -173,14 +187,12 @@ module PdkSync
173
187
 
174
188
  # @summary
175
189
  # This method when called will create and return an octokit client with access to the upstream git repositories.
176
- # @return [Octokit::Client] client
177
- # The octokit client that has been created.
190
+ # @return [PdkSync::GitPlatformClient] client
191
+ # The Git platform client that has been created.
178
192
  def self.setup_client
179
- client = Octokit::Client.new(access_token: @access_token.to_s)
180
- client.user.login
181
- client
182
- rescue ArgumentError, Octokit::Unauthorized
183
- raise "Access Token not set up correctly - Use export 'GITHUB_TOKEN=<put your token here>' to set it."
193
+ PdkSync::GitPlatformClient.new(@git_platform, @git_platform_access_settings)
194
+ rescue StandardError => error
195
+ raise "Git platform access not set up correctly: #{error}"
184
196
  end
185
197
 
186
198
  # @summary
@@ -193,14 +205,19 @@ module PdkSync
193
205
  end
194
206
 
195
207
  # @summary
196
- # This method when called will parse an array of module names and verify whether they are valid GitHub repo names
208
+ # This method when called will parse an array of module names and verify
209
+ # whether they are valid repo or project names on the configured Git
210
+ # hosting platform.
211
+ # @param [PdkSync::GitPlatformClient] client
212
+ # The Git platform client used to get a repository.
197
213
  # @param [Array] module_names
198
- # String array of the names of GitHub repos
199
- def self.validate_modules_exist(module_names)
214
+ # String array of the names of Git platform repos
215
+ def self.validate_modules_exist(client, module_names)
200
216
  invalid_names = []
217
+ raise "Error reading in modules. Check syntax of '#{@managed_modules}'." unless !module_names.nil? && module_names.is_a?(Array)
201
218
  module_names.each do |module_name|
202
219
  # If module name is invalid, push it to invalid names array
203
- unless Octokit.repository?("#{@namespace}/#{module_name}")
220
+ unless client.repository?("#{@namespace}/#{module_name}")
204
221
  invalid_names.push(module_name)
205
222
  next
206
223
  end
@@ -250,7 +267,7 @@ module PdkSync
250
267
  # @return [Git::Base]
251
268
  # A git object representing the local repository.
252
269
  def self.clone_directory(namespace, module_name, output_path)
253
- Git.clone("https://github.com/#{namespace}/#{module_name}.git", output_path.to_s) # is returned
270
+ Git.clone("#{@git_base_uri}/#{namespace}/#{module_name}.git", output_path.to_s) # is returned
254
271
  rescue Git::GitExecuteError => error
255
272
  puts "(FAILURE) Cloning #{module_name} has failed. #{error}".red
256
273
  end
@@ -352,7 +369,7 @@ module PdkSync
352
369
  # @param [String] template_ref
353
370
  # The unique template_ref that is used as part of the commit name.
354
371
  # @param [String] commit_message
355
- # If sepecified it will be the message for the commit.
372
+ # If specified it will be the message for the commit.
356
373
  def self.commit_staged_files(git_repo, template_ref, commit_message = nil)
357
374
  message = if commit_message.nil?
358
375
  "pdksync_#{template_ref}"
@@ -378,8 +395,8 @@ module PdkSync
378
395
 
379
396
  # @summary
380
397
  # 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.
381
- # @param [Octokit::Client] client
382
- # The octokit client used to gain access to and manipulate the repository.
398
+ # @param [PdkSync::GitPlatformClient] client
399
+ # The Git platform client used to gain access to and manipulate the repository.
383
400
  # @param [String] repo_name
384
401
  # The name of the repository on which the commit is to be made.
385
402
  # @param [String] template_ref
@@ -407,8 +424,8 @@ module PdkSync
407
424
 
408
425
  # @summary
409
426
  # This method when called will check on the given repository for the existence of the supplied label
410
- # @param [Octokit::Client] client
411
- # The octokit client used to gain access to and manipulate the repository.
427
+ # @param [PdkSync::GitPlatformClient] client
428
+ # The Git platform client used to gain access to and manipulate the repository.
412
429
  # @param [String] repo_name
413
430
  # The name of the repository on which the commit is to be made.
414
431
  # @param [String] label
@@ -437,8 +454,8 @@ module PdkSync
437
454
 
438
455
  # @summary
439
456
  # This method when called will add a given label to a given repository
440
- # @param [Octokit::Client] client
441
- # The octokit client used to gain access to and manipulate the repository.
457
+ # @param [PdkSync::GitPlatformClient] client
458
+ # The Git Platform client used to gain access to and manipulate the repository.
442
459
  # @param [String] repo_name
443
460
  # The name of the repository on which the commit is to be made.
444
461
  # @param [Integer] issue_number
@@ -454,8 +471,8 @@ module PdkSync
454
471
 
455
472
  # @summary
456
473
  # This method when called will delete any preexisting branch on the given repository that matches the given name.
457
- # @param [Octokit::Client] client
458
- # The octokit client used to gain access to and manipulate the repository.
474
+ # @param [PdkSync::GitPlatformClient] client
475
+ # The Git platform client used to gain access to and manipulate the repository.
459
476
  # @param [String] repo_name
460
477
  # The name of the repository from which the branch is to be deleted.
461
478
  # @param [String] branch_name
@@ -1,14 +1,78 @@
1
+ require 'yaml'
2
+
1
3
  # @summary
2
4
  # A module used to contain a set of variables that are expected to remain constant across all iterations of the main pdksync module.
5
+ # @note
6
+ # Configuration is loaded from `$HOME/.pdksync.yml`. If $HOME is not set, the config_path will use the current directory.
7
+ # Set PDKSYNC_LABEL to '' to disable adding a label during pdksync runs.
3
8
  module PdkSync # rubocop:disable Style/ClassAndModuleChildren
9
+ # Constants contains the configuration for pdksync to use
4
10
  module Constants
5
- ACCESS_TOKEN = ENV['GITHUB_TOKEN'].freeze
6
- NAMESPACE = 'puppetlabs'.freeze
7
- PDKSYNC_DIR = 'modules_pdksync'.freeze
8
- PUSH_FILE_DESTINATION = 'origin'.freeze
9
- CREATE_PR_AGAINST = 'master'.freeze
10
- MANAGED_MODULES = 'managed_modules.yml'.freeze
11
- # Set PDKSYNC_LABEL to '' to disable adding a label during pdksync runs
12
- PDKSYNC_LABEL = 'maintenance'.freeze
11
+ default_config = {
12
+ namespace: 'puppetlabs',
13
+ pdksync_dir: 'modules_pdksync',
14
+ push_file_destination: 'origin',
15
+ create_pr_against: 'master',
16
+ managed_modules: 'managed_modules.yml',
17
+ pdksync_label: 'maintenance',
18
+ git_platform: :github,
19
+ git_base_uri: 'https://github.com',
20
+ gitlab_api_endpoint: 'https://gitlab.com/api/v4'
21
+ }
22
+
23
+ supported_git_platforms = [:github, :gitlab]
24
+
25
+ config = {}
26
+
27
+ config_path = "#{ENV['HOME']}/.pdksync.yml"
28
+
29
+ # pdksync config file must exist, not be empty and not be an empty YAML file
30
+ if File.exist?(config_path) && YAML.load_file(config_path) && !YAML.load_file(config_path).nil?
31
+ custom_config = YAML.load_file(config_path)
32
+ config[:namespace] = custom_config['namespace'] ||= default_config[:namespace]
33
+ config[:pdksync_dir] = custom_config['pdksync_dir'] ||= default_config[:pdksync_dir]
34
+ config[:push_file_destination] = custom_config['push_file_destination'] ||= default_config[:push_file_destination]
35
+ config[:create_pr_against] = custom_config['create_pr_against'] ||= default_config[:create_pr_against]
36
+ config[:managed_modules] = custom_config['managed_modules'] ||= default_config[:managed_modules]
37
+ config[:pdksync_label] = custom_config['pdksync_label'] ||= default_config[:pdksync_label]
38
+ config[:git_platform] = custom_config['git_platform'] ||= default_config[:git_platform]
39
+ config[:git_base_uri] = custom_config['git_base_uri'] ||= case config[:git_platform]
40
+ when :gitlab
41
+ 'https://gitlab.com'
42
+ else
43
+ default_config[:git_base_uri]
44
+ end
45
+ config[:gitlab_api_endpoint] = custom_config['gitlab_api_endpoint'] ||= default_config[:gitlab_api_endpoint]
46
+ else
47
+ config = default_config
48
+ end
49
+
50
+ NAMESPACE = config[:namespace].freeze
51
+ PDKSYNC_DIR = config[:pdksync_dir].freeze
52
+ PUSH_FILE_DESTINATION = config[:push_file_destination].freeze
53
+ CREATE_PR_AGAINST = config[:create_pr_against].freeze
54
+ MANAGED_MODULES = config[:managed_modules].freeze
55
+ PDKSYNC_LABEL = config[:pdksync_label].freeze
56
+ GIT_PLATFORM = config[:git_platform].downcase.to_sym.freeze
57
+ GIT_BASE_URI = config[:git_base_uri].freeze
58
+ GITLAB_API_ENDPOINT = config[:gitlab_api_endpoint].freeze
59
+ ACCESS_TOKEN = case GIT_PLATFORM
60
+ when :github
61
+ ENV['GITHUB_TOKEN'].freeze
62
+ when :gitlab
63
+ ENV['GITLAB_TOKEN'].freeze
64
+ end
65
+
66
+ # Sanity checks
67
+
68
+ unless supported_git_platforms.include?(GIT_PLATFORM)
69
+ raise "Unsupported Git hosting platform '#{GIT_PLATFORM}'."\
70
+ " Supported platforms are: #{supported_git_platforms.join(', ')}"
71
+ end
72
+
73
+ if ACCESS_TOKEN.nil?
74
+ raise "Git platform access token for #{GIT_PLATFORM.capitalize} not set"\
75
+ " - use 'export #{GIT_PLATFORM.upcase}_TOKEN=\"<your token>\"' to set"
76
+ end
13
77
  end
14
78
  end
@@ -0,0 +1,75 @@
1
+ require 'octokit'
2
+
3
+ # @summary
4
+ # This class wraps Octokit::Client and provides the method implementations
5
+ # required by pdksync main to access the Github API for creating pull
6
+ # requests, adding labels, and so forth.
7
+ class PdkSync::GithubClient
8
+ # @summary
9
+ # Creates a new Octokit::Client and logs in the user based on the
10
+ # supplied access token
11
+ # @param access_token
12
+ # The Github access token, required to access the Github API
13
+ def initialize(access_token)
14
+ @client = Octokit::Client.new(access_token: access_token.to_s)
15
+ @client.user.login
16
+ end
17
+
18
+ # @summary Checks if the supplied repository exists on the Git hosting platform
19
+ # @param [String] repository
20
+ # The full repository name, i.e. "namespace/repo_name"
21
+ # @return [Boolean] true if the repository exists, false otherwise
22
+ def repository?(repository)
23
+ @client.repository?(repository)
24
+ end
25
+
26
+ # @summary Creates a new pull request against the Git hosting platform
27
+ # @param [String] repo_name
28
+ # The full repository name, i.e. "namespace/repo_name" in which to create
29
+ # the pull request
30
+ # @param [String] create_pr_against
31
+ # The target branch against which to create the pull request
32
+ # @param [String] head
33
+ # The source branch from which to create the pull request
34
+ # @param [String] title
35
+ # The title/name of the pull request to create
36
+ # @param [String] message
37
+ # The pull request message/body
38
+ # @return An Octokit pull request object for the newly created pull request
39
+ def create_pull_request(repo_name, create_pr_against, head, title, message)
40
+ @client.create_pull_request(repo_name, create_pr_against, head, title, message)
41
+ end
42
+
43
+ # @summary Gets the labels available in the repository
44
+ # @param [String] repo_name
45
+ # The full repository name, i.e. "namespace/repo_name", from which to get
46
+ # the available labels
47
+ # @return [Array] List of available labels in the repository
48
+ def labels(repo_name)
49
+ @client.labels(repo_name)
50
+ end
51
+
52
+ # @summary Updates an existing issue/pull request in the repository
53
+ # @param [String] repo_name
54
+ # The full repository name, i.e. "namespace/repo_name" in which to update
55
+ # the issue
56
+ # @param [Integer] issue_number
57
+ # The id number of the issue/pull request to update
58
+ # @param [Hash] options
59
+ # A hash of options definint the changes to the issue
60
+ # @return An Octokit issue object of the updated issue
61
+ def update_issue(repo_name, issue_number, options)
62
+ @client.update_issue(repo_name, issue_number, options)
63
+ end
64
+
65
+ # @summary Deletes a branch in the repository
66
+ # @param [String] repo_name
67
+ # The full repository name, i.e. "namespace/repo_name" in which to delete
68
+ # the branch
69
+ # @param [String] branch_name
70
+ # The name of the branch to delete
71
+ # @return [Boolean] true on success, false on failure
72
+ def delete_branch(repo_name, branch_name)
73
+ @client.delete_branch(repo_name, branch_name)
74
+ end
75
+ end
@@ -0,0 +1,91 @@
1
+ require 'gitlab'
2
+
3
+ # @summary
4
+ # This class wraps Gitlab::Client and provides the method implementations
5
+ # required by pdksync main to access the Gitlab API for creating merge
6
+ # requests, adding labels, and so forth.
7
+ class PdkSync::GitlabClient
8
+ # @summary
9
+ # Creates a new Gitlab::Client and logs in the user based on the
10
+ # supplied access token and the Gitlab API endpoint URL
11
+ # @param [String] access_token
12
+ # The Gitlab private access token, required to access the Gitlab API
13
+ # @param [String] gitlab_api_endpoint
14
+ # URL to the Gitlab API endpoint against which to work
15
+ def initialize(access_token, gitlab_api_endpoint)
16
+ @client = Gitlab.client(endpoint: gitlab_api_endpoint, private_token: access_token)
17
+ end
18
+
19
+ # @summary Checks if the supplied project exists on the Git hosting platform
20
+ # @param [String] project
21
+ # The full repository name, i.e. "namespace/project"
22
+ # @return [Boolean] true if the project exists, false otherwise
23
+ def repository?(project)
24
+ @client.project(project)
25
+
26
+ true
27
+ rescue Gitlab::Error::NotFound
28
+ false
29
+ end
30
+
31
+ # @summary
32
+ # Creates a new merge request (i.e. pull request) against the Gitlab
33
+ # platform
34
+ # @param [String] project
35
+ # The full project name, i.e. "namespace/project" in which to create
36
+ # the merge request
37
+ # @param [String] target_branch
38
+ # The target branch against which to create the merge request
39
+ # @param [String] source_branch
40
+ # The source branch from which to create the merge request
41
+ # @param [String] title
42
+ # The title/name of the merge request to create
43
+ # @param [String] message
44
+ # The pull request message/body
45
+ # @return
46
+ # A Gitlab merge request object for the newly created merge request
47
+ def create_pull_request(project, target_branch, source_branch, title, message)
48
+ mr_options = {
49
+ source_branch: source_branch,
50
+ target_branch: target_branch,
51
+ description: message
52
+ }
53
+ @client.create_merge_request(project, title, mr_options)
54
+ end
55
+
56
+ # @summary Gets the labels available in the project
57
+ # @param [String] project
58
+ # The full project name, i.e. "namespace/project", from which to get
59
+ # the available labels
60
+ # @return [Array] List of available labels in the project
61
+ def labels(project)
62
+ @client.labels(project)
63
+ end
64
+
65
+ # @summary Updates an existing merge request in the repository
66
+ # @note This method is specifically used to set labels for a merge request
67
+ # @param [String] project
68
+ # The full project name, i.e. "namespace/project" in which to update
69
+ # the issue
70
+ # @param [Integer] id
71
+ # The id number of the merge request to update
72
+ # @param [Hash] options
73
+ # A hash of options defining the changes to the merge request
74
+ # @return A Gitlab merge request object of the updated merge request
75
+ def update_issue(project, id, options)
76
+ # Gitlab requires labels to be supplied as a comma-separated string
77
+ labels = options[:labels].join(',')
78
+ @client.update_merge_request(project, id, labels: labels)
79
+ end
80
+
81
+ # @summary Deletes a branch in the project
82
+ # @param [String] project
83
+ # The full project name, i.e. "namespace/project" in which to delete
84
+ # the branch
85
+ # @param [String] branch_name
86
+ # The name of the branch to delete
87
+ # @return [Boolean] true on success, false on failure
88
+ def delete_branch(project, branch_name)
89
+ @client.delete_branch(project, branch_name)
90
+ end
91
+ end
@@ -0,0 +1,109 @@
1
+ require 'pdksync/pullrequest'
2
+
3
+ # @summary
4
+ # The GitPlatformClient class creates a PdkSync::GithubClient or
5
+ # PdkSync::GitlabClient and provides methods wrapping the client's
6
+ # corresponding methods
7
+ class PdkSync::GitPlatformClient
8
+ # @summary
9
+ # Creates a PdkSync::GithubClient or PdkSync::GitlabClient based on the
10
+ # value of git_platform.
11
+ # @param [Symbol] git_platform
12
+ # The symbol designating the Git hosting platform to use and thus which
13
+ # client to create
14
+ # @param [Hash] git_platform_access_settings
15
+ # Hash of Git platform access settings, such as access_token or
16
+ # gitlab_api_endpoint. access_token is always required,
17
+ # gitlab_api_endpoint only for Gitlab.
18
+ def initialize(git_platform, git_platform_access_settings)
19
+ @git_platform = git_platform
20
+
21
+ # TODO: raise exceptions when git_platform_access_settings hash is not
22
+ # set up correctly? Or let PdkSync::GithubClient or PdkSync::GitlabClient
23
+ # raise errors later and let them propagate upwards?
24
+ access_token = git_platform_access_settings[:access_token]
25
+ @client = case git_platform
26
+ when :github
27
+ require 'pdksync/githubclient'
28
+
29
+ PdkSync::GithubClient.new(access_token)
30
+ when :gitlab
31
+ require 'pdksync/gitlabclient'
32
+
33
+ gitlab_api_endpoint = git_platform_access_settings[:gitlab_api_endpoint]
34
+ PdkSync::GitlabClient.new(access_token, gitlab_api_endpoint)
35
+ end
36
+ end
37
+
38
+ # @summary Checks if the supplied project exists on the Git hosting platform
39
+ # @param [String] project
40
+ # The full repository name, i.e. "namespace/project"
41
+ # @return [Boolean] true if the project exists, false otherwise
42
+ def repository?(project)
43
+ @client.repository?(project)
44
+ end
45
+
46
+ # @summary
47
+ # Creates a new pull/merge request against the Git hosting platform and
48
+ # wraps the Github or Gitlab result in a PdkSync::PullRequest object for
49
+ # consumption by pdksync main
50
+ # @param [String] project
51
+ # The full project name, i.e. "namespace/project" in which to create
52
+ # the pull/merge request
53
+ # @param [String] target_branch
54
+ # The target branch against which to create the pull/merge request
55
+ # @param [String] source_branch
56
+ # The source branch from which to create the pull/merge request
57
+ # @param [String] title
58
+ # The title/name of the pull/merge request to create
59
+ # @param [String] message
60
+ # The pull/merge request message/body
61
+ # @return [PdkSync::PullRequest]
62
+ # A pdksync pull request object for the newly created pull/merge request
63
+ # for consumption by pdksync main
64
+ def create_pull_request(project, target_branch, source_branch, title, message)
65
+ client_pr = @client.create_pull_request(project, target_branch, source_branch, title, message)
66
+ pr = case @git_platform
67
+ when :github
68
+ PdkSync::PullRequest.github(client_pr)
69
+ when :gitlab
70
+ PdkSync::PullRequest.gitlab(client_pr)
71
+ end
72
+ pr
73
+ end
74
+
75
+ # @summary Gets the labels available in the project
76
+ # @param [String] project
77
+ # The full project name, i.e. "namespace/project", from which to get
78
+ # the available labels
79
+ # @return [Array] List of available labels in the project
80
+ def labels(project)
81
+ @client.labels(project)
82
+ end
83
+
84
+ # @summary Updates an existing pull/merge request in the repository
85
+ # @note
86
+ # This method is specifically used to set labels for a pull/merge request
87
+ # @param [String] project
88
+ # The full project name, i.e. "namespace/project" in which to update
89
+ # the issue
90
+ # @param [Integer] id
91
+ # The id number of the pull/merge request to update
92
+ # @param [Hash] options
93
+ # A hash of options defining the changes to the pull/merge request
94
+ # @return A pull/merge request object of the updated pull/merge request
95
+ def update_issue(project, id, options)
96
+ @client.update_issue(project, id, options)
97
+ end
98
+
99
+ # @summary Deletes a branch in the project
100
+ # @param [String] project
101
+ # The full project name, i.e. "namespace/project" in which to delete
102
+ # the branch
103
+ # @param [String] branch_name
104
+ # The name of the branch to delete
105
+ # @return [Boolean] true on success, false on failure
106
+ def delete_branch(project, branch_name)
107
+ @client.delete_branch(project, branch_name)
108
+ end
109
+ end
@@ -0,0 +1,35 @@
1
+ # @summary A simple wrapper class around Github pull request and Gitlab merge
2
+ # request objects used to abstract the differences and provide a common
3
+ # interface to PR URL and number/id.
4
+ class PdkSync::PullRequest
5
+ class << self
6
+ def github(pr_object)
7
+ new(pr_object)
8
+ end
9
+
10
+ def gitlab(pr_object)
11
+ new(pr_object, :gitlab)
12
+ end
13
+
14
+ private :new
15
+ end
16
+
17
+ attr_reader :html_url, :number
18
+
19
+ # Create a new PR wrapper object setting html_url and number
20
+ # @param pr_object
21
+ # The pull request object to wrap as created by Octokit::Client or
22
+ # Gitlab::Client
23
+ # @param [Symbol] git_platform
24
+ # The Git hosting platform against which the pull request is made
25
+ def initialize(pr_object, git_platform = :github)
26
+ case git_platform
27
+ when :github
28
+ @html_url = pr_object.html_url
29
+ @number = pr_object.number
30
+ when :gitlab
31
+ @html_url = pr_object.web_url
32
+ @number = pr_object.iid
33
+ end
34
+ end
35
+ end
data/pdksync.gemspec CHANGED
@@ -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 = 'pdksync'
6
- spec.version = '0.3.0'
6
+ spec.version = '0.4.0'
7
7
  spec.authors = ['Puppet']
8
8
  spec.email = ['']
9
9
  spec.summary = 'Puppet Module PDK Synchronizer'
@@ -17,11 +17,12 @@ 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 'bundler'
20
+ spec.add_development_dependency 'bundler', '~> 1.15'
21
21
  spec.add_development_dependency 'rake'
22
22
  spec.add_development_dependency 'rspec'
23
23
  spec.add_development_dependency 'rubocop', '~> 0.50.0'
24
24
  spec.add_development_dependency 'octokit'
25
+ spec.add_development_dependency 'gitlab'
25
26
  spec.add_development_dependency 'pry'
26
27
 
27
28
  spec.add_runtime_dependency 'git', '~>1.3'
@@ -14,6 +14,7 @@ describe PdkSync do
14
14
 
15
15
  before(:each) do
16
16
  allow(PdkSync).to receive(:return_modules).and_return(@module_names)
17
+ allow(PdkSync).to receive(:validate_modules_exist).and_return(@module_names)
17
18
  Dir.chdir(@folder)
18
19
  end
19
20
 
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pdksync
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Puppet
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-15 00:00:00.000000000 Z
11
+ date: 2019-02-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '0'
19
+ version: '1.15'
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: '1.15'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -80,6 +80,20 @@ dependencies:
80
80
  - - ">="
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: gitlab
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: pry
85
99
  requirement: !ruby/object:Gem::Requirement
@@ -141,6 +155,10 @@ files:
141
155
  - Rakefile
142
156
  - lib/pdksync.rb
143
157
  - lib/pdksync/constants.rb
158
+ - lib/pdksync/githubclient.rb
159
+ - lib/pdksync/gitlabclient.rb
160
+ - lib/pdksync/gitplatformclient.rb
161
+ - lib/pdksync/pullrequest.rb
144
162
  - managed_modules.yml
145
163
  - pdksync.gemspec
146
164
  - spec/lib/pdksync_spec.rb
@@ -164,7 +182,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
164
182
  version: '0'
165
183
  requirements: []
166
184
  rubyforge_project:
167
- rubygems_version: 2.6.11
185
+ rubygems_version: 2.7.7
168
186
  signing_key:
169
187
  specification_version: 4
170
188
  summary: Puppet Module PDK Synchronizer