labclient 0.1.2 → 0.1.3

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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labclient.rb +7 -4
  3. data/lib/labclient/branches/branch.rb +25 -0
  4. data/lib/labclient/branches/create.rb +33 -0
  5. data/lib/labclient/client.rb +2 -2
  6. data/lib/labclient/epics/epic.rb +13 -0
  7. data/lib/labclient/error.rb +1 -0
  8. data/lib/labclient/files/create.rb +14 -8
  9. data/lib/labclient/generator/generator.rb +2 -14
  10. data/lib/labclient/generator/names.rb +17 -3
  11. data/lib/labclient/generator/template_helper.rb +82 -0
  12. data/lib/labclient/generator/templates/environments.rb +98 -0
  13. data/lib/labclient/generator/templates/pages.rb +24 -30
  14. data/lib/labclient/generator/templates/pipeline_trigger.rb +82 -0
  15. data/lib/labclient/generator/wizard.rb +23 -7
  16. data/lib/labclient/http.rb +2 -1
  17. data/lib/labclient/issues/issue.rb +6 -1
  18. data/lib/labclient/klass.rb +3 -2
  19. data/lib/labclient/lab_struct.rb +17 -0
  20. data/lib/labclient/license/list.rb +2 -2
  21. data/lib/labclient/merge_requests/accept.rb +15 -6
  22. data/lib/labclient/merge_requests/create.rb +12 -0
  23. data/lib/labclient/merge_requests/merge_request.rb +49 -4
  24. data/lib/labclient/notes/epics/create.rb +4 -4
  25. data/lib/labclient/notes/epics/delete.rb +3 -3
  26. data/lib/labclient/notes/epics/list.rb +21 -4
  27. data/lib/labclient/notes/epics/show.rb +4 -4
  28. data/lib/labclient/notes/epics/update.rb +4 -4
  29. data/lib/labclient/notes/issues/create.rb +3 -1
  30. data/lib/labclient/notes/issues/list.rb +18 -3
  31. data/lib/labclient/notes/issues/show.rb +1 -1
  32. data/lib/labclient/notes/merge_requests/list.rb +20 -2
  33. data/lib/labclient/notes/snippets/create.rb +1 -1
  34. data/lib/labclient/notes/snippets/list.rb +20 -3
  35. data/lib/labclient/notes/snippets/show.rb +1 -1
  36. data/lib/labclient/notifications/update.rb +1 -1
  37. data/lib/labclient/paginated_response.rb +1 -1
  38. data/lib/labclient/pipelines/pipeline.rb +41 -0
  39. data/lib/labclient/projects/methods.rb +30 -2
  40. data/lib/labclient/projects/reference.rb +5 -0
  41. data/lib/labclient/projects/snippets/project_snippet.rb +12 -0
  42. data/lib/labclient/snippets/snippet.rb +2 -2
  43. data/lib/labclient/users/user.rb +6 -0
  44. data/lib/labclient/version.rb +1 -1
  45. metadata +10 -7
  46. data/lib/labclient/generator/templates/template.rb +0 -23
  47. data/lib/labclient/open_struct.rb +0 -14
@@ -1,9 +1,24 @@
1
1
  module LabClient
2
2
  module Generator
3
+ # Docs for the wizard
4
+ class GeneratorDocs
5
+ doc 'Templates' do
6
+ title 'Pages'
7
+ markdown <<~DOC
8
+ Create GitLab Pages group and test projects. Projects imported from Gitlab's [demo pages projects](https://gitlab.com/pages)
9
+
10
+ | Setting | Default | Type | Description |
11
+ | ---------- | --------- | ------- | -------------------------------------- |
12
+ | group_name | Generated | String | Parent Group name for pages projects |
13
+ | group_path | Generated | String | Parent Group path |
14
+ | count | 5 | Integer | Number of projects to import (max: 28) |
15
+ DOC
16
+ end
17
+ end
18
+
3
19
  # Page Import Creation
4
- class Pages < TemplateHelper
5
- include Names
6
- attr_accessor :group_name, :group_path, :count
20
+ class Pages < GroupTemplateHelper
21
+ attr_accessor :count
7
22
 
8
23
  # All Available Pages Projects
9
24
  def list
@@ -17,23 +32,10 @@ module LabClient
17
32
  end
18
33
 
19
34
  def setup
20
- self.group_name = opts[:group_name] || "#{gen_groups.sample} Pages"
21
- self.group_path = opts[:group_path] || group_name.downcase.gsub(' ', '-')
35
+ super
22
36
  self.count = opts[:count] || 5
23
37
  end
24
38
 
25
- def generate_group
26
- @group = client.groups.create(name: group_name, path: group_path)
27
- puts "#{@group.name} - #{@group.web_url}"
28
- raise 'Unable to Create Group' unless @group.success?
29
- end
30
-
31
- def generate_projects
32
- @projects = list.sample(count).map do |name|
33
- generate_project(name)
34
- end
35
- end
36
-
37
39
  def generate_project(name)
38
40
  @group.project_create(
39
41
  name: name,
@@ -52,21 +54,13 @@ module LabClient
52
54
  @projects.each(&:wait_for_import)
53
55
  end
54
56
 
55
- # Execute Template
56
- def run!
57
- generate_group
58
- generate_projects
59
- wait_for_import
60
- generate_pipelines
61
-
62
- @projects.each do |project|
63
- puts "#{project.name} - #{project.web_url}"
57
+ def setup_projects
58
+ @projects = list.sample(count).map do |name|
59
+ generate_project(name)
64
60
  end
65
61
 
66
- {
67
- group: @group,
68
- projects: @projects
69
- }
62
+ wait_for_import
63
+ generate_pipelines
70
64
  end
71
65
  end
72
66
  end
@@ -0,0 +1,82 @@
1
+ module LabClient
2
+ module Generator
3
+ # Docs for the wizard
4
+ class GeneratorDocs
5
+ doc 'Templates' do
6
+ title 'Pipeline Triggers'
7
+ markdown <<~DOC
8
+ Create GitLab Pipeline Triggers group and test projects.
9
+
10
+ - Child Pipeline: Parent pipeline with artifact, that is then executed as a child pipeline
11
+
12
+ | Setting | Default | Type | Description |
13
+ | ---------- | --------- | ------- | -------------------------------------- |
14
+ | group_name | Generated | String | Parent Group name for pages projects |
15
+ | group_path | Generated | String | Parent Group path |
16
+ DOC
17
+ end
18
+ end
19
+
20
+ # Child and other Trigger Examples
21
+ # https://docs.gitlab.com/ee/ci/yaml/#trigger
22
+ class PipelineTrigger < GroupTemplateHelper
23
+ def setup_projects
24
+ create_child_pipeline
25
+ end
26
+
27
+ def trigger_child_pipeline_yaml
28
+ <<~YAML
29
+ image: busybox:latest
30
+
31
+ build_child:
32
+ stage: build
33
+ script:
34
+ - cp child_pipeline.yml artifact.yml
35
+ artifacts:
36
+ paths:
37
+ - artifact.yml
38
+
39
+ trigger_child:
40
+ stage: deploy
41
+ trigger:
42
+ include:
43
+ - artifact: artifact.yml
44
+ job: build_child
45
+
46
+ YAML
47
+ end
48
+
49
+ def child_pipeline_yaml
50
+ <<~YAML
51
+ image: busybox:latest
52
+
53
+ child:
54
+ script:
55
+ - echo "Do your build here"
56
+ YAML
57
+ end
58
+
59
+ def create_child_pipeline
60
+ project = @group.project_create(
61
+ name: 'Child Pipeline',
62
+ description: 'Child Pipeline',
63
+ auto_devops_enabled: false
64
+ )
65
+
66
+ # Create Child
67
+ project.file_create(
68
+ 'child_pipeline.yml',
69
+ create_file(child_pipeline_yaml)
70
+ )
71
+
72
+ # Create Parent
73
+ project.file_create(
74
+ '.gitlab-ci.yml',
75
+ create_file(trigger_child_pipeline_yaml)
76
+ )
77
+
78
+ @projects.push project
79
+ end
80
+ end
81
+ end
82
+ end
@@ -8,7 +8,15 @@ module LabClient
8
8
  attr_accessor :count, :random, :password, :templates, :domain
9
9
 
10
10
  def inspect
11
- "#<Wizard count=#{count}, random=#{random}, domain=#{domain}>"
11
+ "#<Wizard count=#{count}, random=#{random}, domain=#{domain}> templates=#{templates}"
12
+ end
13
+
14
+ def templates_default
15
+ %i[pages pipeline_trigger environments]
16
+ end
17
+
18
+ def templates_all
19
+ LabClient::Generator::TemplateHelper.descendants
12
20
  end
13
21
 
14
22
  def initialize(client)
@@ -19,16 +27,17 @@ module LabClient
19
27
  self.count = default_count
20
28
  self.password = SecureRandom.uuid
21
29
  self.domain = URI.parse(client.settings[:url]).hostname
30
+
31
+ # Default Templates
32
+ self.templates ||= templates_default
22
33
  end
23
34
 
24
35
  def template(name, opts = {})
25
- case name
26
- when :pages then Pages.new(client, opts)
27
- end
28
- end
36
+ template_klass = templates_all.find { |x| x.template_name == name.to_sym }
29
37
 
30
- def pages(opts = {})
31
- Pages.new(client, opts)
38
+ raise "Invalid Template! Available Templates: #{templates_all.map(&:template_name).join(', ')}" unless template_klass
39
+
40
+ template_klass.new(client, opts)
32
41
  end
33
42
 
34
43
  # Random Counters
@@ -42,6 +51,7 @@ module LabClient
42
51
  end
43
52
 
44
53
  def generate_users
54
+ puts 'Generating Users'
45
55
  @users = @user_names.map do |name|
46
56
  username = name.downcase.gsub(/[^0-9A-Za-z]/, '')
47
57
  email = "#{username}@#{domain}"
@@ -57,6 +67,7 @@ module LabClient
57
67
  end
58
68
 
59
69
  def generate_groups
70
+ puts 'Generating Groups'
60
71
  @groups = @group_names.map do |name|
61
72
  path = name.downcase.gsub(/[^0-9A-Za-z]/, '')
62
73
  puts "Group -- #{name}/#{path}"
@@ -65,6 +76,7 @@ module LabClient
65
76
  end
66
77
 
67
78
  def generate_group_membership
79
+ puts 'Adding Group members'
68
80
  ## Group Access Level
69
81
  @groups.each do |group|
70
82
  @users.sample(rand(1..@users.count)).each do |user|
@@ -81,6 +93,7 @@ module LabClient
81
93
  end
82
94
 
83
95
  def generate_projects(group)
96
+ puts 'Generating Projects'
84
97
  # Collect Group Members
85
98
  members = group.members
86
99
 
@@ -115,6 +128,9 @@ module LabClient
115
128
  generate_projects(group)
116
129
  end
117
130
 
131
+ # Run Templates
132
+ templates.each { |template_klass| template(template_klass).run! }
133
+
118
134
  nil
119
135
  end
120
136
  end
@@ -3,6 +3,7 @@ module LabClient
3
3
  # Request Helper
4
4
  class HTTP
5
5
  attr_accessor :settings
6
+
6
7
  def initialize(settings)
7
8
  self.settings = settings
8
9
  end
@@ -75,7 +76,7 @@ module Typhoeus
75
76
  elsif headers['content-type'] == 'text/plain'
76
77
  body
77
78
  else
78
- Oj.load(body, mode: :compat, object_class: OpenStruct)
79
+ Oj.load(body, mode: :compat, object_class: LabClient::LabStruct)
79
80
  end
80
81
  end
81
82
 
@@ -66,6 +66,10 @@ module LabClient
66
66
  client.notes.issues.list(project_id, iid)
67
67
  end
68
68
 
69
+ def note_create(query)
70
+ client.notes.issues.create(project_id, iid, query)
71
+ end
72
+
69
73
  def agent_detail
70
74
  client.issues.agent_detail(project_id, iid)
71
75
  end
@@ -100,7 +104,8 @@ module LabClient
100
104
  option 'subscribe', 'Subscribe to notifications'
101
105
  option 'unsubscribe', 'Unsubscribe to notifications'
102
106
  option 'participants', 'List participants in this issue.'
103
- option 'notes', 'List notes/comments.'
107
+ option 'notes', 'List notes/comments. [Hash]'
108
+ option 'note_create', 'Creates a new note for issue. [Hash]'
104
109
  option 'agent_detail', 'Get user agent details.'
105
110
  option 'related_merge_requests', 'Get all related Merge Requests.'
106
111
  option 'closed_by', 'Get all Merge Requests that will close this issue.'
@@ -1,14 +1,15 @@
1
1
  # Top Namesapce
2
2
  module LabClient
3
3
  # Common Configuration for all Class Helpers
4
- class Klass < OpenStruct
4
+ class Klass < LabStruct
5
5
  include CurlHelper
6
6
 
7
7
  attr_reader :client, :response
8
+
8
9
  extend Docs
9
10
 
10
11
  def verbose
11
- ap self
12
+ ap self, ruby19_syntax: true
12
13
  end
13
14
 
14
15
  # API Methods here have to be explicitly documented / custom helpers
@@ -0,0 +1,17 @@
1
+ # Extensions for OpenStruct specific to LabClient
2
+ module LabClient
3
+ # Unique inherited class to not override top level openstruct
4
+ class LabStruct < OpenStruct
5
+ def keys
6
+ to_h.keys.sort
7
+ end
8
+
9
+ def inspect
10
+ to_h.inspect
11
+ end
12
+
13
+ def as_json(*args)
14
+ super.as_json['table']
15
+ end
16
+ end
17
+ end
@@ -32,12 +32,12 @@ module LabClient
32
32
  :expires_at => "2050-11-14",
33
33
  :historical_max => 0,
34
34
  :maximum_user_count => 48,
35
- :licensee => OpenStruct {
35
+ :licensee => LabStruct {
36
36
  :Name => "GitLab Henley",
37
37
  :Email => "test_user@gitlab.com",
38
38
  :Company => "GitLab, Inc."
39
39
  },
40
- :add_ons => OpenStruct {},
40
+ :add_ons => LabStruct {},
41
41
  :expired => false,
42
42
  :overage => 0,
43
43
  :user_limit => 100,
@@ -7,10 +7,19 @@ module LabClient
7
7
  desc 'Merge changes submitted with MR. [Project ID, merge request iid]'
8
8
 
9
9
  markdown <<~DOC
10
- - <small>if merge request is unable to be accepted (ie: Work in Progress, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you'll get a `405` and the error message 'Method Not Allowed'</small>
11
- - <small>If it has some conflicts and can not be merged - you'll get a `406` and the error message 'Branch cannot be merged'</small>
12
- - <small>If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a `409` and the error message 'SHA </small>does not match HEAD of source branch'
13
- - <small>If you don't have permissions to accept this merge request - you'll get a `401`</small>
10
+ - <small>if merge request is unable to be accepted (ie: Work in Progress, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you'll get a `405` and the error message 'Method Not Allowed'</small>
11
+ - <small>If it has some conflicts and can not be merged - you'll get a `406` and the error message 'Branch cannot be merged'</small>
12
+ - <small>If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a `409` and the error message 'SHA </small>does not match HEAD of source branch'
13
+ - <small>If you don't have permissions to accept this merge request - you'll get a `401`</small>
14
+
15
+ | **Attribute** | **Attribute** |
16
+ | ---------------------------- | ------------------------------------------------------------------------------------------------- |
17
+ | merge_commit_message | Custom merge commit message |
18
+ | squash_commit_message | Custom squash commit message |
19
+ | squash | if true the commits will be squashed into a single commit on merge |
20
+ | should_remove_source_branch | if true removes the source branch |
21
+ | merge_when_pipeline_succeeds | if true the MR is merged when the pipeline succeeds |
22
+ | sha | if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail |
14
23
  DOC
15
24
 
16
25
  example 'client.merge_requests.accept(343, 3)'
@@ -29,11 +38,11 @@ module LabClient
29
38
  end
30
39
 
31
40
  # Accept
32
- def accept(project_id, merge_request_id)
41
+ def accept(project_id, merge_request_id, query = {})
33
42
  project_id = format_id(project_id)
34
43
  merge_request_id = format_id(merge_request_id)
35
44
 
36
- client.request(:put, "projects/#{project_id}/merge_requests/#{merge_request_id}/merge", MergeRequest)
45
+ client.request(:put, "projects/#{project_id}/merge_requests/#{merge_request_id}/merge", MergeRequest, query)
37
46
  end
38
47
  end
39
48
  end
@@ -41,6 +41,18 @@ module LabClient
41
41
  DOC
42
42
  end
43
43
 
44
+ doc 'Create' do
45
+ desc 'via Project'
46
+ example <<~DOC
47
+ project = client.projects.show(264)
48
+ project.merge_request_create(
49
+ title: 'New MR!',
50
+ source_branch: 'sweet-release',
51
+ target_branch: :master
52
+ )
53
+ DOC
54
+ end
55
+
44
56
  # Create
45
57
  def create(project_id, query)
46
58
  project_id = format_id(project_id)
@@ -51,8 +51,8 @@ module LabClient
51
51
  client.merge_requests.delete(project_id, iid)
52
52
  end
53
53
 
54
- def accept
55
- client.merge_requests.accept(project_id, iid)
54
+ def accept(query = {})
55
+ client.merge_requests.accept(project_id, iid, query)
56
56
  end
57
57
 
58
58
  def merge_ref
@@ -99,6 +99,10 @@ module LabClient
99
99
  client.notes.merge_requests.list(project_id, iid)
100
100
  end
101
101
 
102
+ def note_create(query)
103
+ client.notes.merge_requests.create(project_id, iid, query)
104
+ end
105
+
102
106
  def todo
103
107
  client.merge_requests.todo(project_id, iid)
104
108
  end
@@ -166,9 +170,42 @@ module LabClient
166
170
  client.resource_labels.merge_requests.show(project_id, iid, resource_event_id)
167
171
  end
168
172
 
173
+ # Reload
174
+ def reload
175
+ update_self client.merge_requests.show(project_id, iid)
176
+ end
177
+
178
+ # Wait for Import / Set a Hard Limit
179
+ def wait_for_merge_status(total_time = 300, sleep_time = 15)
180
+ # :unchecked
181
+ # :cannot_be_merged_recheck
182
+ # :checking
183
+ # :cannot_be_merged_rechecking
184
+ # :can_be_merged
185
+ # :cannot_be_merged
186
+
187
+ # Success
188
+ # [unchecked, can_be_merged]
189
+
190
+ # Fail
191
+ # [cannot_be_merged cannot_be_merged_recheck]
192
+
193
+ Timeout.timeout(total_time) do
194
+ loop do
195
+ reload
196
+ puts "Waiting for Merge Status: #{merge_status}"
197
+ break if %w[can_be_merged unchecked].include? merge_status
198
+ raise "Cannot be merged! #{import_error}" if %w[cannot_be_merged cannot_be_merged_recheck].include? merge_status
199
+
200
+ sleep sleep_time
201
+ end
202
+ end
203
+ end
204
+
205
+ # rubocop:disable Metrics/BlockLength
169
206
  help do
170
207
  subtitle 'MergeRequest'
171
- option 'accept', 'Merge changes submitted'
208
+ option 'accept', 'Merge changes submitted [Hash]'
172
209
  option 'add_time_spent', 'Adds spent time. Accepts Duration or Human Format. (1.hour or "1h")'
173
210
  option 'changes', 'Show merge request changes'
174
211
  option 'closes_issues', 'Show issues that this merge request will close'
@@ -176,7 +213,13 @@ module LabClient
176
213
  option 'create_pipeline', 'Create new pipeline for this merge request.'
177
214
  option 'delete', 'Delete this merge request.'
178
215
  option 'merge_ref', 'Show Merge Ref'
179
- option 'notes', 'List notes/comments.'
216
+ option 'reload', 'Reload this merge request object (New API Call)'
217
+ option 'wait_for_merge_status', 'Looping, wait for merge request status [Timeout, Interval]'
218
+
219
+ # Notes
220
+ option 'notes', 'List notes/comments. [Hash]'
221
+ option 'note_create', 'Creates a new note. [Hash]'
222
+
180
223
  option 'participants', 'List participants in this merge request.'
181
224
  option 'pipelines', 'List pipelines in this merge request.'
182
225
  option 'reset_spent_time', 'Resets the spent time'
@@ -206,6 +249,8 @@ module LabClient
206
249
  option 'resource_labels', 'List of all label events'
207
250
  option 'resource_label', 'Show single label event [Resource Event ID]'
208
251
  end
252
+
253
+ # rubocop:enable Metrics/BlockLength
209
254
  end
210
255
  # rubocop:enable Metrics/ClassLength
211
256
  end