labclient 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/lib/labclient.rb +23 -4
  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 +48 -7
  7. data/lib/labclient/docs.rb +9 -5
  8. data/lib/labclient/epics/epic.rb +13 -0
  9. data/lib/labclient/error.rb +1 -0
  10. data/lib/labclient/files/create.rb +14 -8
  11. data/lib/labclient/generator/generator.rb +70 -0
  12. data/lib/labclient/generator/names.rb +68 -0
  13. data/lib/labclient/generator/template_helper.rb +81 -0
  14. data/lib/labclient/generator/templates/environments.rb +98 -0
  15. data/lib/labclient/generator/templates/pages.rb +67 -0
  16. data/lib/labclient/generator/templates/pipeline_trigger.rb +82 -0
  17. data/lib/labclient/generator/wizard.rb +142 -0
  18. data/lib/labclient/groups/group.rb +9 -1
  19. data/lib/labclient/http.rb +3 -2
  20. data/lib/labclient/issues/create.rb +2 -0
  21. data/lib/labclient/issues/issue.rb +31 -1
  22. data/lib/labclient/issues/update.rb +20 -2
  23. data/lib/labclient/jobs/delete.rb +1 -1
  24. data/lib/labclient/jobs/keep.rb +1 -1
  25. data/lib/labclient/jobs/play.rb +1 -1
  26. data/lib/labclient/jobs/trace.rb +2 -2
  27. data/lib/labclient/klass.rb +34 -4
  28. data/lib/labclient/lab_struct.rb +17 -0
  29. data/lib/labclient/license/list.rb +2 -2
  30. data/lib/labclient/members/member.rb +1 -0
  31. data/lib/labclient/merge_requests/accept.rb +15 -6
  32. data/lib/labclient/merge_requests/create.rb +12 -0
  33. data/lib/labclient/merge_requests/merge_request.rb +49 -4
  34. data/lib/labclient/notes/epics/create.rb +12 -4
  35. data/lib/labclient/notes/epics/delete.rb +3 -3
  36. data/lib/labclient/notes/epics/list.rb +21 -4
  37. data/lib/labclient/notes/epics/show.rb +4 -4
  38. data/lib/labclient/notes/epics/update.rb +4 -4
  39. data/lib/labclient/notes/issues/create.rb +11 -1
  40. data/lib/labclient/notes/issues/list.rb +18 -3
  41. data/lib/labclient/notes/issues/show.rb +1 -1
  42. data/lib/labclient/notes/merge_requests/create.rb +8 -0
  43. data/lib/labclient/notes/merge_requests/list.rb +20 -2
  44. data/lib/labclient/notes/snippets/create.rb +1 -1
  45. data/lib/labclient/notes/snippets/list.rb +20 -3
  46. data/lib/labclient/notes/snippets/show.rb +1 -1
  47. data/lib/labclient/notifications/update.rb +1 -1
  48. data/lib/labclient/overview.rb +110 -11
  49. data/lib/labclient/paginated_response.rb +8 -1
  50. data/lib/labclient/pipelines/pipeline.rb +41 -0
  51. data/lib/labclient/projects/methods.rb +71 -2
  52. data/lib/labclient/projects/reference.rb +14 -0
  53. data/lib/labclient/projects/snippets/project_snippet.rb +12 -0
  54. data/lib/labclient/protected_branches/protect.rb +6 -5
  55. data/lib/labclient/protected_environments/list.rb +29 -0
  56. data/lib/labclient/protected_environments/protect.rb +53 -0
  57. data/lib/labclient/protected_environments/protected_environment.rb +22 -0
  58. data/lib/labclient/protected_environments/show.rb +24 -0
  59. data/lib/labclient/protected_environments/unprotect.rb +31 -0
  60. data/lib/labclient/snippets/snippet.rb +2 -2
  61. data/lib/labclient/users/membership.rb +62 -0
  62. data/lib/labclient/users/memberships.rb +8 -3
  63. data/lib/labclient/users/user.rb +13 -1
  64. data/lib/labclient/version.rb +1 -1
  65. metadata +37 -9
  66. data/lib/labclient/open_struct.rb +0 -14
@@ -0,0 +1,142 @@
1
+ module LabClient
2
+ # Generator Namespace
3
+ module Generator
4
+ # Helper to Generate Data / Populate GitLab
5
+ class Wizard
6
+ include Generator::Names # Name Generator
7
+ attr_reader :client
8
+ attr_accessor :count, :random, :password, :templates, :domain, :skip_confirmation
9
+
10
+ def inspect
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
20
+ end
21
+
22
+ def initialize(client)
23
+ require 'faker' # Ensure Faker is Available
24
+
25
+ @client = client
26
+ self.random = true # Populate Random or use only Templates
27
+ self.count = default_count
28
+ self.password = SecureRandom.uuid
29
+ puts "Default Password: #{password}"
30
+
31
+ self.skip_confirmation = true
32
+ self.domain = URI.parse(client.settings[:url]).hostname
33
+
34
+ # Default Templates
35
+ self.templates ||= templates_default
36
+ end
37
+
38
+ def template(name, opts = {})
39
+ template_klass = templates_all.find { |x| x.template_name == name.to_sym }
40
+
41
+ raise "Invalid Template! Available Templates: #{templates_all.map(&:template_name).join(', ')}" unless template_klass
42
+
43
+ template_klass.new(client, opts)
44
+ end
45
+
46
+ # Random Counters
47
+ def default_count
48
+ {
49
+ users: 20,
50
+ projects: 5,
51
+ groups: 5,
52
+ issues: 2
53
+ }
54
+ end
55
+
56
+ def generate_users
57
+ puts 'Generating Users'
58
+ @users = @user_names.map do |name|
59
+ username = name.downcase.gsub(/[^0-9A-Za-z]/, '')
60
+ email = "#{username}@#{domain}"
61
+ puts "User -- Name: #{name}, UserName: #{username}, Email: #{email}"
62
+
63
+ client.users.create(
64
+ name: name,
65
+ email: email,
66
+ password: password,
67
+ username: username,
68
+ skip_confirmation: skip_confirmation
69
+ )
70
+ end
71
+ end
72
+
73
+ def generate_groups
74
+ puts 'Generating Groups'
75
+ @groups = @group_names.map do |name|
76
+ path = name.downcase.gsub(/[^0-9A-Za-z]/, '')
77
+ puts "Group -- #{name}/#{path}"
78
+ client.groups.create(name: name, path: path)
79
+ end
80
+ end
81
+
82
+ def generate_group_membership
83
+ puts 'Adding Group members'
84
+ ## Group Access Level
85
+ @groups.each do |group|
86
+ @users.sample(rand(1..@users.count)).each do |user|
87
+ level = group.valid_group_project_levels.sample
88
+ puts "Group Add: #{group.name}: #{user.name} - #{level}"
89
+ group.member_add(user, access_level: level)
90
+ # :nocov:
91
+ rescue StandardError => e
92
+ puts e.message
93
+ next
94
+ # :nocov:
95
+ end
96
+ end
97
+ end
98
+
99
+ def generate_projects(group)
100
+ puts 'Generating Projects'
101
+ # Collect Group Members
102
+ members = group.members
103
+
104
+ # Loop through project names, create project add issues
105
+ @project_names.uniq.map do |project_name|
106
+ puts "Project: #{project_name}"
107
+ project = group.project_create(name: project_name, description: gen_description)
108
+
109
+ rand(count[:issues]).times do
110
+ project.issue_create(generate_issue_data(members.sample))
111
+ end
112
+ end
113
+ end
114
+
115
+ def generate_issue_data(member)
116
+ {
117
+ assignee_id: member.id,
118
+ description: Faker::Hacker.say_something_smart,
119
+ title: Faker::Company.catch_phrase
120
+ }
121
+ end
122
+
123
+ # Execute Generation
124
+ def run!
125
+ # Collect Names
126
+ generate_names
127
+ generate_users
128
+ generate_groups
129
+ generate_group_membership
130
+
131
+ @groups.map do |group|
132
+ generate_projects(group)
133
+ end
134
+
135
+ # Run Templates
136
+ templates.each { |template_klass| template(template_klass).run! }
137
+
138
+ nil
139
+ end
140
+ end
141
+ end
142
+ 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)
@@ -246,6 +246,11 @@ module LabClient
246
246
  client.groups.milestones.list(id, query)
247
247
  end
248
248
 
249
+ # Reload Helper
250
+ def reload
251
+ update_self client.groups.show(id)
252
+ end
253
+
249
254
  # rubocop:disable Metrics/BlockLength
250
255
  help do
251
256
  subtitle 'Group'
@@ -319,6 +324,9 @@ module LabClient
319
324
 
320
325
  # Registry
321
326
  option 'registry_repositories', 'Get a list of registry repositories [Hash]'
327
+
328
+ # Reload Helper
329
+ option 'reload', 'Reload this object (New API Call)'
322
330
  end
323
331
  # rubocop:enable Metrics/BlockLength
324
332
  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
@@ -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
 
@@ -33,6 +33,8 @@ module LabClient
33
33
 
34
34
  def create(project_id, query = {})
35
35
  project_id = format_id(project_id)
36
+ format_query_id(:assignee_id, query)
37
+
36
38
  client.request(:post, "projects/#{project_id}/issues", Issue, query)
37
39
  end
38
40
  end
@@ -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
@@ -87,6 +101,18 @@ module LabClient
87
101
  client.resource_labels.issues.show(project_id, iid, resource_event_id)
88
102
  end
89
103
 
104
+ # Reload Helper
105
+ def reload
106
+ update_self client.issues.show(project_id, iid)
107
+ end
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
+
90
116
  help do
91
117
  subtitle 'Issue'
92
118
  option 'update', 'Update issue (accepts hash).'
@@ -95,7 +121,8 @@ module LabClient
95
121
  option 'subscribe', 'Subscribe to notifications'
96
122
  option 'unsubscribe', 'Unsubscribe to notifications'
97
123
  option 'participants', 'List participants in this issue.'
98
- option 'notes', 'List notes/comments.'
124
+ option 'notes', 'List notes/comments. [Hash]'
125
+ option 'note_create', 'Creates a new note for issue. [Hash]'
99
126
  option 'agent_detail', 'Get user agent details.'
100
127
  option 'related_merge_requests', 'Get all related Merge Requests.'
101
128
  option 'closed_by', 'Get all Merge Requests that will close this issue.'
@@ -109,6 +136,9 @@ module LabClient
109
136
  # Resource Labels
110
137
  option 'resource_labels', 'List of all label events'
111
138
  option 'resource_label', 'Show single label event [Resource Event ID]'
139
+
140
+ # Reload Helper
141
+ option 'reload', 'Reload this object (New API Call)'
112
142
  end
113
143
  end
114
144
  end
@@ -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,19 +1,21 @@
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
15
16
  # Assume no methods by default
16
- def help
17
+ # rubocop:disable Metrics/MethodLength, Metrics/AbcSize
18
+ def help(help_filter = nil)
17
19
  docs = LabClient::Docs.docs.dig(group_name, 'Reference')
18
20
  unless docs
19
21
  puts 'No Available Help'
@@ -25,7 +27,11 @@ module LabClient
25
27
  next unless doc[:options]
26
28
 
27
29
  doc[:options].each do |opt|
28
- puts ' ' + opt[:name]
30
+ if help_filter
31
+ next unless (opt[:name] + opt[:text]).include? help_filter.to_s
32
+ end
33
+
34
+ puts " #{opt[:name]}"
29
35
  puts " #{opt[:text]}\n"
30
36
  end
31
37
  end
@@ -33,6 +39,23 @@ module LabClient
33
39
  # Ignore Output
34
40
  nil
35
41
  end
42
+ # rubocop:enable Metrics/MethodLength, Metrics/AbcSize
43
+
44
+ # Documented API Methods
45
+ def api_methods
46
+ docs = LabClient::Docs.docs.dig(group_name, 'Reference')
47
+
48
+ unless docs
49
+ puts 'No Available Help'
50
+ return false
51
+ end
52
+
53
+ LabClient::Docs.docs.dig(group_name, 'Reference').map do |doc|
54
+ doc[:options].map do |opt|
55
+ opt[:name]
56
+ end
57
+ end.flatten.sort
58
+ end
36
59
 
37
60
  def valid_group_project_levels
38
61
  %i[guest reporter developer maintainer owner]
@@ -74,6 +97,7 @@ module LabClient
74
97
  self
75
98
  end
76
99
 
100
+ # rubocop:disable Lint/MissingSuper
77
101
  def initialize(hash = nil, response = nil, client = nil)
78
102
  @client = client
79
103
  @response = response
@@ -84,6 +108,12 @@ module LabClient
84
108
  @table[k] = v
85
109
  end
86
110
  end
111
+ # rubocop:enable Lint/MissingSuper
112
+
113
+ # Forward response success
114
+ def success?
115
+ @response.success?
116
+ end
87
117
 
88
118
  # Formatting Time Helper
89
119
  def format_time?(time)
@@ -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