labclient 0.1.2 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labclient.rb +16 -6
  3. data/lib/labclient/access_levels.rb +24 -30
  4. data/lib/labclient/branches/branch.rb +25 -0
  5. data/lib/labclient/branches/create.rb +33 -0
  6. data/lib/labclient/client.rb +47 -7
  7. data/lib/labclient/commits/project_helpers.rb +4 -0
  8. data/lib/labclient/commits/show.rb +11 -2
  9. data/lib/labclient/docs.rb +9 -5
  10. data/lib/labclient/epics/epic.rb +13 -0
  11. data/lib/labclient/error.rb +1 -0
  12. data/lib/labclient/files/create.rb +14 -8
  13. data/lib/labclient/files/update.rb +1 -1
  14. data/lib/labclient/generator/generator.rb +9 -21
  15. data/lib/labclient/generator/names.rb +17 -3
  16. data/lib/labclient/generator/template_helper.rb +81 -0
  17. data/lib/labclient/generator/templates/environments.rb +98 -0
  18. data/lib/labclient/generator/templates/pages.rb +24 -30
  19. data/lib/labclient/generator/templates/pipeline_trigger.rb +82 -0
  20. data/lib/labclient/generator/wizard.rb +29 -9
  21. data/lib/labclient/groups/group.rb +1 -1
  22. data/lib/labclient/http.rb +3 -2
  23. data/lib/labclient/issues/issue.rb +23 -1
  24. data/lib/labclient/issues/update.rb +20 -2
  25. data/lib/labclient/jobs/delete.rb +1 -1
  26. data/lib/labclient/jobs/keep.rb +1 -1
  27. data/lib/labclient/jobs/play.rb +1 -1
  28. data/lib/labclient/jobs/trace.rb +2 -2
  29. data/lib/labclient/klass.rb +6 -3
  30. data/lib/labclient/lab_struct.rb +21 -0
  31. data/lib/labclient/license/list.rb +2 -2
  32. data/lib/labclient/members/member.rb +1 -0
  33. data/lib/labclient/merge_requests/accept.rb +15 -6
  34. data/lib/labclient/merge_requests/create.rb +12 -0
  35. data/lib/labclient/merge_requests/merge_request.rb +49 -4
  36. data/lib/labclient/notes/epics/create.rb +12 -4
  37. data/lib/labclient/notes/epics/delete.rb +3 -3
  38. data/lib/labclient/notes/epics/list.rb +21 -4
  39. data/lib/labclient/notes/epics/show.rb +4 -4
  40. data/lib/labclient/notes/epics/update.rb +4 -4
  41. data/lib/labclient/notes/issues/create.rb +11 -1
  42. data/lib/labclient/notes/issues/list.rb +18 -3
  43. data/lib/labclient/notes/issues/show.rb +1 -1
  44. data/lib/labclient/notes/merge_requests/create.rb +8 -0
  45. data/lib/labclient/notes/merge_requests/list.rb +20 -2
  46. data/lib/labclient/notes/snippets/create.rb +1 -1
  47. data/lib/labclient/notes/snippets/list.rb +20 -3
  48. data/lib/labclient/notes/snippets/show.rb +1 -1
  49. data/lib/labclient/notifications/update.rb +1 -1
  50. data/lib/labclient/overview.rb +79 -11
  51. data/lib/labclient/paginated_response.rb +3 -1
  52. data/lib/labclient/pipelines/pipeline.rb +41 -0
  53. data/lib/labclient/projects/environments/project_environment.rb +10 -0
  54. data/lib/labclient/projects/methods.rb +49 -2
  55. data/lib/labclient/projects/reference.rb +12 -0
  56. data/lib/labclient/projects/snippets/project_snippet.rb +12 -0
  57. data/lib/labclient/protected_branches/protect.rb +6 -5
  58. data/lib/labclient/protected_environments/list.rb +29 -0
  59. data/lib/labclient/protected_environments/protect.rb +53 -0
  60. data/lib/labclient/protected_environments/protected_environment.rb +22 -0
  61. data/lib/labclient/protected_environments/show.rb +24 -0
  62. data/lib/labclient/protected_environments/unprotect.rb +31 -0
  63. data/lib/labclient/snippets/snippet.rb +2 -2
  64. data/lib/labclient/users/membership.rb +62 -0
  65. data/lib/labclient/users/memberships.rb +8 -3
  66. data/lib/labclient/users/user.rb +7 -1
  67. data/lib/labclient/version.rb +1 -1
  68. metadata +16 -7
  69. data/lib/labclient/generator/templates/template.rb +0 -23
  70. data/lib/labclient/open_struct.rb +0 -14
@@ -5,10 +5,18 @@ module LabClient
5
5
  class Wizard
6
6
  include Generator::Names # Name Generator
7
7
  attr_reader :client
8
- attr_accessor :count, :random, :password, :templates, :domain
8
+ attr_accessor :count, :random, :password, :templates, :domain, :skip_confirmation
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)
@@ -18,17 +26,21 @@ module LabClient
18
26
  self.random = true # Populate Random or use only Templates
19
27
  self.count = default_count
20
28
  self.password = SecureRandom.uuid
29
+ puts "Default Password: #{password}"
30
+
31
+ self.skip_confirmation = true
21
32
  self.domain = URI.parse(client.settings[:url]).hostname
33
+
34
+ # Default Templates
35
+ self.templates ||= templates_default
22
36
  end
23
37
 
24
38
  def template(name, opts = {})
25
- case name
26
- when :pages then Pages.new(client, opts)
27
- end
28
- end
39
+ template_klass = templates_all.find { |x| x.template_name == name.to_sym }
29
40
 
30
- def pages(opts = {})
31
- Pages.new(client, opts)
41
+ raise "Invalid Template! Available Templates: #{templates_all.map(&:template_name).join(', ')}" unless template_klass
42
+
43
+ template_klass.new(client, opts)
32
44
  end
33
45
 
34
46
  # Random Counters
@@ -42,6 +54,7 @@ module LabClient
42
54
  end
43
55
 
44
56
  def generate_users
57
+ puts 'Generating Users'
45
58
  @users = @user_names.map do |name|
46
59
  username = name.downcase.gsub(/[^0-9A-Za-z]/, '')
47
60
  email = "#{username}@#{domain}"
@@ -51,12 +64,14 @@ module LabClient
51
64
  name: name,
52
65
  email: email,
53
66
  password: password,
54
- username: username
67
+ username: username,
68
+ skip_confirmation: skip_confirmation
55
69
  )
56
70
  end
57
71
  end
58
72
 
59
73
  def generate_groups
74
+ puts 'Generating Groups'
60
75
  @groups = @group_names.map do |name|
61
76
  path = name.downcase.gsub(/[^0-9A-Za-z]/, '')
62
77
  puts "Group -- #{name}/#{path}"
@@ -65,6 +80,7 @@ module LabClient
65
80
  end
66
81
 
67
82
  def generate_group_membership
83
+ puts 'Adding Group members'
68
84
  ## Group Access Level
69
85
  @groups.each do |group|
70
86
  @users.sample(rand(1..@users.count)).each do |user|
@@ -81,6 +97,7 @@ module LabClient
81
97
  end
82
98
 
83
99
  def generate_projects(group)
100
+ puts 'Generating Projects'
84
101
  # Collect Group Members
85
102
  members = group.members
86
103
 
@@ -115,6 +132,9 @@ module LabClient
115
132
  generate_projects(group)
116
133
  end
117
134
 
135
+ # Run Templates
136
+ templates.each { |template_klass| template(template_klass).run! }
137
+
118
138
  nil
119
139
  end
120
140
  end
@@ -42,7 +42,7 @@ module LabClient
42
42
 
43
43
  def projects(query = {})
44
44
  # Details Query Includes Projects
45
- if query.empty? && !@table.dig(:projects).blank?
45
+ if query.empty? && !@table[:projects].blank?
46
46
  @table[:projects].map { |project| LabClient::Project.new(project, response, client) }
47
47
  else
48
48
  client.groups.projects(id, query)
@@ -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
@@ -72,10 +73,10 @@ module Typhoeus
72
73
  def process_body
73
74
  if body.empty?
74
75
  nil
75
- elsif headers['content-type'] == 'text/plain'
76
+ elsif headers['content-type']&.include? '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
 
@@ -14,6 +14,16 @@ module LabClient
14
14
  # User Fields
15
15
  user_attrs %i[closed_by author assignee]
16
16
 
17
+ # Via State Events
18
+ def close
19
+ client.issues.update(project_id, iid, state_event: :close)
20
+ end
21
+
22
+ # Via State Events
23
+ def reopen
24
+ client.issues.update(project_id, iid, state_event: :reopen)
25
+ end
26
+
17
27
  def update(query)
18
28
  client.issues.update(project_id, iid, query)
19
29
  end
@@ -66,6 +76,10 @@ module LabClient
66
76
  client.notes.issues.list(project_id, iid)
67
77
  end
68
78
 
79
+ def note_create(query)
80
+ client.notes.issues.create(project_id, iid, query)
81
+ end
82
+
69
83
  def agent_detail
70
84
  client.issues.agent_detail(project_id, iid)
71
85
  end
@@ -92,6 +106,13 @@ module LabClient
92
106
  update_self client.issues.show(project_id, iid)
93
107
  end
94
108
 
109
+ def project
110
+ # If from List Project ID isn't stored
111
+ project_id = collect_project_id if project_id.nil?
112
+
113
+ client.projects.show(project_id)
114
+ end
115
+
95
116
  help do
96
117
  subtitle 'Issue'
97
118
  option 'update', 'Update issue (accepts hash).'
@@ -100,7 +121,8 @@ module LabClient
100
121
  option 'subscribe', 'Subscribe to notifications'
101
122
  option 'unsubscribe', 'Unsubscribe to notifications'
102
123
  option 'participants', 'List participants in this issue.'
103
- option 'notes', 'List notes/comments.'
124
+ option 'notes', 'List notes/comments. [Hash]'
125
+ option 'note_create', 'Creates a new note for issue. [Hash]'
104
126
  option 'agent_detail', 'Get user agent details.'
105
127
  option 'related_merge_requests', 'Get all related Merge Requests.'
106
128
  option 'closed_by', 'Get all Merge Requests that will close this issue.'
@@ -18,19 +18,37 @@ module LabClient
18
18
  |-------------------------------------------|----------------|----------|--------------|
19
19
  | title | string | no | The title of an issue |
20
20
  | description | string | no | The description of an issue. Limited to 1,048,576 characters. |
21
+
22
+
21
23
  DOC
22
24
  end
23
25
 
24
26
  doc 'Update' do
25
- desc 'Close Ticket'
27
+ title 'Close / Reopen'
28
+ markdown <<~DOC
29
+ Closing/Reopening of issues is handled via state_events. Either :close, or :reopen. The issue objects themselves also have helpers `reopen` `close`.
30
+ DOC
31
+
26
32
  example 'client.issues.update(5, 1, state_event: :close)'
27
33
  end
28
34
 
35
+ doc 'Update' do
36
+ example 'client.issues.update(5, 1, state_event: :reopen)'
37
+ end
38
+
39
+ doc 'Update' do
40
+ desc 'Through Issue Object'
41
+ example <<~DOC
42
+ issue = client.issues.show(5,1)
43
+ issue.close
44
+ DOC
45
+ end
46
+
29
47
  doc 'Update' do
30
48
  desc 'Through Issue Object'
31
49
  example <<~DOC
32
50
  issue = client.issues.show(5,1)
33
- issue.update(title: "Dew it!")
51
+ issue.reopen
34
52
  DOC
35
53
  end
36
54
 
@@ -3,7 +3,7 @@ module LabClient
3
3
  # Specifics
4
4
  class Jobs < Common
5
5
  doc 'Update' do
6
- title 'Retry'
6
+ title 'Delete'
7
7
  desc 'Delete artifacts of a job. [Project ID, Job ID]'
8
8
  example 'client.jobs.delete(264, 14)'
9
9
  end
@@ -3,7 +3,7 @@ module LabClient
3
3
  # Specifics
4
4
  class Jobs < Common
5
5
  doc 'Update' do
6
- title 'Retry'
6
+ title 'Keep'
7
7
  desc 'Prevents artifacts from being deleted when expiration is set. [Project ID, Job ID]'
8
8
  example 'client.jobs.keep(264, 14)'
9
9
  end
@@ -3,7 +3,7 @@ module LabClient
3
3
  # Specifics
4
4
  class Jobs < Common
5
5
  doc 'Update' do
6
- title 'Retry'
6
+ title 'Play'
7
7
  desc 'Triggers a manual action to start a job. [Project ID, Job ID]'
8
8
  example 'client.jobs.play(264, 14)'
9
9
  end
@@ -20,14 +20,14 @@ module LabClient
20
20
  desc 'via Job'
21
21
  example <<~DOC
22
22
  job = client.jobs.show(264,1)
23
- job.trace
23
+ job.trace #=> String
24
24
  DOC
25
25
  end
26
26
 
27
27
  def trace(project_id, job_id)
28
28
  job_id = format_id(job_id)
29
29
  project_id = format_id(project_id)
30
- puts client.request(:get, "projects/#{project_id}/jobs/#{job_id}/trace")
30
+ client.request(:get, "projects/#{project_id}/jobs/#{job_id}/trace")
31
31
  end
32
32
  end
33
33
  end
@@ -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
@@ -30,7 +31,7 @@ module LabClient
30
31
  next unless (opt[:name] + opt[:text]).include? help_filter.to_s
31
32
  end
32
33
 
33
- puts ' ' + opt[:name]
34
+ puts " #{opt[:name]}"
34
35
  puts " #{opt[:text]}\n"
35
36
  end
36
37
  end
@@ -96,6 +97,7 @@ module LabClient
96
97
  self
97
98
  end
98
99
 
100
+ # rubocop:disable Lint/MissingSuper
99
101
  def initialize(hash = nil, response = nil, client = nil)
100
102
  @client = client
101
103
  @response = response
@@ -106,6 +108,7 @@ module LabClient
106
108
  @table[k] = v
107
109
  end
108
110
  end
111
+ # rubocop:enable Lint/MissingSuper
109
112
 
110
113
  # Forward response success
111
114
  def success?
@@ -0,0 +1,21 @@
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
+
17
+ def slice(*opts)
18
+ to_h.slice(*opts)
19
+ end
20
+ end
21
+ 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,
@@ -51,6 +51,7 @@ module LabClient
51
51
  option 'level', 'Humanized symbol of access level. e.g. :developer'
52
52
  option 'user', 'Collect user object.'
53
53
  option '<permission>?', 'True/False evaluation each guest?, developer? etc'
54
+ option 'greater_than', 'True/False if user has greater than [Permission Name]'
54
55
  end
55
56
  end
56
57
  end
@@ -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