gitlab 4.19.0 → 5.1.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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +0 -267
- data/LICENSE.txt +1 -1
- data/README.md +1 -1
- data/lib/gitlab/cli_helpers.rb +1 -1
- data/lib/gitlab/client/groups.rb +149 -0
- data/lib/gitlab/client/issues.rb +11 -0
- data/lib/gitlab/client/merge_requests.rb +28 -2
- data/lib/gitlab/client/merge_trains.rb +55 -0
- data/lib/gitlab/client/pipeline_schedules.rb +12 -0
- data/lib/gitlab/client/pipelines.rb +25 -0
- data/lib/gitlab/client/project_exports.rb +54 -0
- data/lib/gitlab/client/project_releases.rb +11 -0
- data/lib/gitlab/client/projects.rb +81 -1
- data/lib/gitlab/client/runners.rb +67 -0
- data/lib/gitlab/client/users.rb +125 -1
- data/lib/gitlab/client.rb +10 -1
- data/lib/gitlab/configuration.rb +2 -1
- data/lib/gitlab/headers/page_links.rb +37 -0
- data/lib/gitlab/headers/total.rb +29 -0
- data/lib/gitlab/paginated_response.rb +6 -1
- data/lib/gitlab/request.rb +13 -4
- data/lib/gitlab/version.rb +1 -1
- data/lib/gitlab.rb +5 -2
- metadata +22 -5
- data/lib/gitlab/page_links.rb +0 -35
@@ -43,6 +43,18 @@ class Gitlab::Client
|
|
43
43
|
get("/projects/#{url_encode project}/pipelines/#{id}/test_report")
|
44
44
|
end
|
45
45
|
|
46
|
+
# Gets a single pipeline's variables.
|
47
|
+
#
|
48
|
+
# @example
|
49
|
+
# Gitlab.pipeline_variables(5, 36)
|
50
|
+
#
|
51
|
+
# @param [Integer, String] project The ID or name of a project.
|
52
|
+
# @param [Integer] id The ID of a pipeline.
|
53
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
54
|
+
def pipeline_variables(project, id)
|
55
|
+
get("/projects/#{url_encode project}/pipelines/#{id}/variables")
|
56
|
+
end
|
57
|
+
|
46
58
|
# Create a pipeline.
|
47
59
|
#
|
48
60
|
# @example
|
@@ -101,5 +113,18 @@ class Gitlab::Client
|
|
101
113
|
def delete_pipeline(project, id)
|
102
114
|
delete("/projects/#{url_encode project}/pipelines/#{id}")
|
103
115
|
end
|
116
|
+
|
117
|
+
# Update a pipeline metadata
|
118
|
+
#
|
119
|
+
# @example
|
120
|
+
# Gitlab.update_pipeline_metadata(5, 1, name: 'new name')
|
121
|
+
#
|
122
|
+
# @param [Integer, String] project The ID or name of a project.
|
123
|
+
# @param [Integer] id The ID of a pipeline.
|
124
|
+
# @option options [String] :name The new name of the pipeline.
|
125
|
+
# @return [Gitlab::ObjectifiedHash]
|
126
|
+
def update_pipeline_metadata(project, id, options = {})
|
127
|
+
put("/projects/#{url_encode project}/pipelines/#{id}/metadata", body: options)
|
128
|
+
end
|
104
129
|
end
|
105
130
|
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Gitlab::Client
|
4
|
+
# Defines methods related to project exports.
|
5
|
+
# @see https://docs.gitlab.com/ce/api/project_import_export.html
|
6
|
+
module ProjectExports
|
7
|
+
# Start a new export
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# Gitlab.export_project(2)
|
11
|
+
#
|
12
|
+
# @param [Integer, String] id The ID or path of a project.
|
13
|
+
# @param [Hash] options A customizable set of options.
|
14
|
+
# @option options [String] description(optional) Overrides the project description
|
15
|
+
# @option options [hash] upload(optional) Hash that contains the information to upload the exported project to a web server
|
16
|
+
# @option options [String] upload[url] TThe URL to upload the project
|
17
|
+
# @option options [String] upload[http_method](optional) The HTTP method to upload the exported project. Only PUT and POST methods allowed. Default is PUT
|
18
|
+
# @return [Gitlab::ObjectifiedHash]
|
19
|
+
def export_project(id, options = {})
|
20
|
+
post("/projects/#{url_encode id}/export", body: options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Get the status of export
|
24
|
+
#
|
25
|
+
# @example
|
26
|
+
# Gitlab.export_project_status(2)
|
27
|
+
#
|
28
|
+
# @param [Integer, String] id The ID or path of a project.
|
29
|
+
# @return [Gitlab::ObjectifiedHash]
|
30
|
+
def export_project_status(id)
|
31
|
+
get("/projects/#{url_encode id}/export")
|
32
|
+
end
|
33
|
+
|
34
|
+
# Download the finished export
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# Gitlab.exported_project_download(2)
|
38
|
+
#
|
39
|
+
# @param [Integer, String] id The ID or path of a project.
|
40
|
+
# @return [Gitlab::FileResponse]
|
41
|
+
def exported_project_download(id)
|
42
|
+
get("/projects/#{url_encode id}/export/download",
|
43
|
+
format: nil,
|
44
|
+
headers: { Accept: 'application/octet-stream' },
|
45
|
+
parser: proc { |body, _|
|
46
|
+
if body.encoding == Encoding::ASCII_8BIT # binary response
|
47
|
+
::Gitlab::FileResponse.new StringIO.new(body, 'rb+')
|
48
|
+
else # error with json response
|
49
|
+
::Gitlab::Request.parse(body)
|
50
|
+
end
|
51
|
+
})
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -75,5 +75,16 @@ class Gitlab::Client
|
|
75
75
|
def delete_project_release(project, tag_name)
|
76
76
|
delete("/projects/#{url_encode project}/releases/#{tag_name}")
|
77
77
|
end
|
78
|
+
|
79
|
+
# Gets Latest Release
|
80
|
+
#
|
81
|
+
# @example
|
82
|
+
# Gitlab.project_latest_release(5)
|
83
|
+
#
|
84
|
+
# @param [Integer, String] project The ID or name of a project
|
85
|
+
# @return [Gitlab::ObjectifiedHash] Information about the release
|
86
|
+
def project_latest_release(project)
|
87
|
+
get("/projects/#{url_encode project}/releases/permalink/latest")
|
88
|
+
end
|
78
89
|
end
|
79
90
|
end
|
@@ -3,7 +3,7 @@
|
|
3
3
|
class Gitlab::Client
|
4
4
|
# Defines methods related to projects.
|
5
5
|
# @see https://docs.gitlab.com/ce/api/projects.html
|
6
|
-
module Projects
|
6
|
+
module Projects # rubocop:disable Metrics/ModuleLength
|
7
7
|
# Gets a list of projects owned by the authenticated user.
|
8
8
|
#
|
9
9
|
# @example
|
@@ -704,5 +704,85 @@ class Gitlab::Client
|
|
704
704
|
def project_deploy_tokens(project, options = {})
|
705
705
|
get("/projects/#{url_encode project}/deploy_tokens", query: options)
|
706
706
|
end
|
707
|
+
|
708
|
+
# Get languages used with percentage value
|
709
|
+
#
|
710
|
+
# @example
|
711
|
+
# Gitlab.project_languages(42)
|
712
|
+
#
|
713
|
+
# @param [Integer, String] id The ID or path of a project.
|
714
|
+
# @return [Gitlab::ObjectifiedHash]
|
715
|
+
def project_languages(project)
|
716
|
+
get("/projects/#{url_encode project}/languages")
|
717
|
+
end
|
718
|
+
|
719
|
+
# List all project access tokens.
|
720
|
+
#
|
721
|
+
# @example
|
722
|
+
# Gitlab.project_access_tokens(42)
|
723
|
+
#
|
724
|
+
# @param [Integer, String] project The ID or path of a project.
|
725
|
+
# @option options [String] :state Limit by active/inactive state. Optional.
|
726
|
+
#
|
727
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
728
|
+
def project_access_tokens(project, options = {})
|
729
|
+
get("/projects/#{url_encode project}/access_tokens", query: options)
|
730
|
+
end
|
731
|
+
|
732
|
+
# Get a specific project access token.
|
733
|
+
#
|
734
|
+
# @example
|
735
|
+
# Gitlab.project_access_token(42, 1234)
|
736
|
+
#
|
737
|
+
# @param [Integer, String] project The ID or path of a project.
|
738
|
+
# @param [Integer] token_id The ID of the project access token.
|
739
|
+
#
|
740
|
+
# @return [Gitlab::ObjectifiedHash] Information about the specified project access token.
|
741
|
+
def project_access_token(project, token_id)
|
742
|
+
get("/projects/#{url_encode project}/access_tokens/#{token_id}")
|
743
|
+
end
|
744
|
+
|
745
|
+
# Creates a new project access token.
|
746
|
+
#
|
747
|
+
# @example
|
748
|
+
# Gitlab.create_project_access_token(42, 'My Token', ['api'], '2024-12-12', access_level: 40)
|
749
|
+
#
|
750
|
+
# @param [Integer, String] project The ID or path of a project.
|
751
|
+
# @param [String] name The name of the project access token.
|
752
|
+
# @param [Array] scopes List of scopes of the project access token.
|
753
|
+
# @param [String] expires_at A date string in the format YYYY-MM-DD.
|
754
|
+
# @option options [Integer] :access_level Access level. Optional. Defaults to 40.
|
755
|
+
#
|
756
|
+
# @return [Gitlab::ObjectifiedHash] Information about the created project access token.
|
757
|
+
def create_project_access_token(project, name, scopes, expires_at, options = {})
|
758
|
+
post("/projects/#{url_encode project}/access_tokens", body: { name: name, scopes: scopes, expires_at: expires_at }.merge(options))
|
759
|
+
end
|
760
|
+
|
761
|
+
# Rotate a project access token.
|
762
|
+
#
|
763
|
+
# @example
|
764
|
+
# Gitlab.rotate_project_access_token(42, 1234)
|
765
|
+
#
|
766
|
+
# @param [Integer, String] project The ID or path of a project.
|
767
|
+
# @param [Integer] token_id The ID of the project access token.
|
768
|
+
# @option options [String] :expires_at A date string in the format YEAR-MONTH-DAY.
|
769
|
+
#
|
770
|
+
# @return [Gitlab::ObjectifiedHash] Information about the specified project access token.
|
771
|
+
def rotate_project_access_token(project, token_id, options = {})
|
772
|
+
post("/projects/#{url_encode project}/access_tokens/#{token_id}/rotate", query: options)
|
773
|
+
end
|
774
|
+
|
775
|
+
# Revoke a project access token.
|
776
|
+
#
|
777
|
+
# @example
|
778
|
+
# Gitlab.revoke_project_access_token(42, 1234)
|
779
|
+
#
|
780
|
+
# @param [Integer, String] project The ID or path of a project.
|
781
|
+
# @param [Integer] token_id The ID of the project access token.
|
782
|
+
#
|
783
|
+
# @return [Gitlab::ObjectifiedHash]
|
784
|
+
def revoke_project_access_token(project, token_id)
|
785
|
+
delete("/projects/#{url_encode project}/access_tokens/#{token_id}")
|
786
|
+
end
|
707
787
|
end
|
708
788
|
end
|
@@ -207,5 +207,72 @@ class Gitlab::Client
|
|
207
207
|
body = { token: token }
|
208
208
|
post('/runners/verify', body: body)
|
209
209
|
end
|
210
|
+
|
211
|
+
# Creates a new group runner with the new Gitlab approach (v16.0+) and returns the id/token information
|
212
|
+
# https://docs.gitlab.com/ee/api/users.html#create-a-runner
|
213
|
+
# You must use an access token with the create_runner scope
|
214
|
+
#
|
215
|
+
# @example
|
216
|
+
# Gitlab.create_group_runner(9, tag_list: ['one', 'two'])
|
217
|
+
# Gitlab.create_group_runner(9, paused: false, description: 'A note', run_untagged: true)
|
218
|
+
#
|
219
|
+
# @param [String] group(required) Group ID.
|
220
|
+
# @param [Hash] options A customizable set of options.
|
221
|
+
# @return <Gitlab::ObjectifiedHash> Response against runner registration
|
222
|
+
def create_group_runner(group, options = {})
|
223
|
+
create_runner({ runner_type: 'group_type', group_id: group }.merge(options))
|
224
|
+
end
|
225
|
+
|
226
|
+
# Creates a new project runner with the new Gitlab approach (v16.0+) and returns the id/token information
|
227
|
+
# https://docs.gitlab.com/ee/api/users.html#create-a-runner
|
228
|
+
# You must use an access token with the create_runner scope
|
229
|
+
#
|
230
|
+
# @example
|
231
|
+
# Gitlab.create_project_runner(12, tag_list: ['one', 'two'])
|
232
|
+
# Gitlab.create_project_runner(12, paused: false, description: 'A note', run_untagged: true)
|
233
|
+
#
|
234
|
+
# @param [String] project(required) Project ID.
|
235
|
+
# @param [Hash] options A customizable set of options.
|
236
|
+
# @return <Gitlab::ObjectifiedHash> Response against runner registration
|
237
|
+
def create_project_runner(project, options = {})
|
238
|
+
create_runner({ runner_type: 'project_type', project_id: project }.merge(options))
|
239
|
+
end
|
240
|
+
|
241
|
+
# Creates a new instance runner with the new Gitlab approach (v16.0+) and returns the id/token information
|
242
|
+
# You must be an administrator of the GitLab instance
|
243
|
+
# You must use an access token with the create_runner scope
|
244
|
+
# https://docs.gitlab.com/ee/api/users.html#create-a-runner
|
245
|
+
#
|
246
|
+
# @example
|
247
|
+
# Gitlab.create_instance_runner(tag_list: ['one', 'two'])
|
248
|
+
# Gitlab.create_instance_runner(paused: false, description: 'A note', run_untagged: true)
|
249
|
+
#
|
250
|
+
# @param [String] group(required) Project ID.
|
251
|
+
# @param [Hash] options A customizable set of options.
|
252
|
+
# @return <Gitlab::ObjectifiedHash> Response against runner registration
|
253
|
+
def create_instance_runner(options = {})
|
254
|
+
create_runner({ runner_type: 'instance_type' }.merge(options))
|
255
|
+
end
|
256
|
+
|
257
|
+
private
|
258
|
+
|
259
|
+
# Creates a runner linked to the current user.
|
260
|
+
# You must use an access token with the create_runner scope
|
261
|
+
# https://docs.gitlab.com/ee/api/users.html#create-a-runner
|
262
|
+
#
|
263
|
+
# @param [Hash] options(required) A customizable set of options.
|
264
|
+
# @option options [String] :description(optional) Runner description.
|
265
|
+
# @option options [Hash] :info(optional) Runner metadata.
|
266
|
+
# @option options [Boolean] :paused(optional) Whether the Runner ignores new jobs.
|
267
|
+
# @option options [Boolean] :locked(optional) Whether the Runner should be locked for current project.
|
268
|
+
# @option options [Boolean] :run_untagged(optional) Whether the Runner should handle untagged jobs.
|
269
|
+
# @option options [Array<String>] :tag_list(optional) List of Runner tags.
|
270
|
+
# @option options [String] :access_level(optional) Access level of the runner; not_protected or ref_protected.
|
271
|
+
# @option options [Integer] :maximum_timeout(optional) Maximum timeout set when this Runner will handle the job.
|
272
|
+
# @option options [String] :maintenance_note(optional) Free-form maintenance notes for the runner (1024 characters).
|
273
|
+
# @return <Gitlab::ObjectifiedHash> Response against runner registration {"id": 1, "token": foo "token_expires_at": null}
|
274
|
+
def create_runner(options)
|
275
|
+
post('/user/runners', body: options)
|
276
|
+
end
|
210
277
|
end
|
211
278
|
end
|
data/lib/gitlab/client/users.rb
CHANGED
@@ -58,6 +58,22 @@ class Gitlab::Client
|
|
58
58
|
post('/users', body: body)
|
59
59
|
end
|
60
60
|
|
61
|
+
# Creates a service account.
|
62
|
+
# Requires authentication from an admin account.
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# Gitlab.create_service_account('service_account_6018816a18e515214e0c34c2b33523fc', 'Service account user')
|
66
|
+
#
|
67
|
+
# @param [String] name (required) The email of the service account.
|
68
|
+
# @param [String] username (required) The username of the service account.
|
69
|
+
# @return [Gitlab::ObjectifiedHash] Information about created service account.
|
70
|
+
def create_service_account(*args)
|
71
|
+
raise ArgumentError, 'Missing required parameters' unless args[1]
|
72
|
+
|
73
|
+
body = { name: args[0], username: args[1] }
|
74
|
+
post('/service_accounts', body: body)
|
75
|
+
end
|
76
|
+
|
61
77
|
# Updates a user.
|
62
78
|
#
|
63
79
|
# @example
|
@@ -110,6 +126,28 @@ class Gitlab::Client
|
|
110
126
|
post("/users/#{user_id}/unblock")
|
111
127
|
end
|
112
128
|
|
129
|
+
# Deactivates the specified user. Available only for admin.
|
130
|
+
#
|
131
|
+
# @example
|
132
|
+
# Gitlab.deactivate_user(15)
|
133
|
+
#
|
134
|
+
# @param [Integer] user_id The Id of user
|
135
|
+
# @return [Boolean] success or not
|
136
|
+
def deactivate_user(user_id)
|
137
|
+
post("/users/#{user_id}/deactivate")
|
138
|
+
end
|
139
|
+
|
140
|
+
# Activate the specified user. Available only for admin.
|
141
|
+
#
|
142
|
+
# @example
|
143
|
+
# Gitlab.activate_user(15)
|
144
|
+
#
|
145
|
+
# @param [Integer] user_id The Id of user
|
146
|
+
# @return [Boolean] success or not
|
147
|
+
def activate_user(user_id)
|
148
|
+
post("/users/#{user_id}/activate")
|
149
|
+
end
|
150
|
+
|
113
151
|
# Approves the specified user. Available only for admin.
|
114
152
|
#
|
115
153
|
# @example
|
@@ -276,7 +314,7 @@ class Gitlab::Client
|
|
276
314
|
delete(url)
|
277
315
|
end
|
278
316
|
|
279
|
-
# Search for
|
317
|
+
# Search for users by name
|
280
318
|
#
|
281
319
|
# @example
|
282
320
|
# Gitlab.user_search('gitlab')
|
@@ -291,6 +329,19 @@ class Gitlab::Client
|
|
291
329
|
get('/users', query: options)
|
292
330
|
end
|
293
331
|
|
332
|
+
# Get user by username
|
333
|
+
#
|
334
|
+
# @example
|
335
|
+
# Gitlab.user_by_username('gitlab')
|
336
|
+
#
|
337
|
+
# @param [String] username A username to get.
|
338
|
+
# @param [Hash] options A customizable set of options.
|
339
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
340
|
+
def user_by_username(username, options = {})
|
341
|
+
options[:username] = username
|
342
|
+
get('/users', query: options)
|
343
|
+
end
|
344
|
+
|
294
345
|
# Gets user custom_attributes.
|
295
346
|
#
|
296
347
|
# @example
|
@@ -382,6 +433,47 @@ class Gitlab::Client
|
|
382
433
|
post("/users/#{user_id}/impersonation_tokens", body: body)
|
383
434
|
end
|
384
435
|
|
436
|
+
# Get all personal access tokens for a user
|
437
|
+
#
|
438
|
+
# @example
|
439
|
+
# Gitlab.user_personal_access_tokens(1)
|
440
|
+
#
|
441
|
+
# @param [Integer] user_id The ID of the user.
|
442
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
443
|
+
def user_personal_access_tokens(user_id)
|
444
|
+
get("/personal_access_tokens?user_id=#{user_id}")
|
445
|
+
end
|
446
|
+
|
447
|
+
# Create personal access token
|
448
|
+
#
|
449
|
+
# @example
|
450
|
+
# Gitlab.create_personal_access_token(2, "token", ["api", "read_user"])
|
451
|
+
# Gitlab.create_personal_access_token(2, "token", ["api", "read_user"], "1970-01-01")
|
452
|
+
#
|
453
|
+
# @param [Integer] user_id The ID of the user.
|
454
|
+
# @param [String] name Name of the personal access token.
|
455
|
+
# @param [Array<String>] scopes Array of scopes for the impersonation token
|
456
|
+
# @param [String] expires_at Date for impersonation token expiration in ISO format.
|
457
|
+
# @return [Gitlab::ObjectifiedHash]
|
458
|
+
def create_personal_access_token(user_id, name, scopes, expires_at = nil)
|
459
|
+
body = { name: name, scopes: scopes }
|
460
|
+
body[:expires_at] = expires_at if expires_at
|
461
|
+
post("/users/#{user_id}/personal_access_tokens", body: body)
|
462
|
+
end
|
463
|
+
|
464
|
+
# Rotate a personal access token
|
465
|
+
#
|
466
|
+
# @example
|
467
|
+
# Gitlab.rotate_personal_access_token(1)
|
468
|
+
#
|
469
|
+
# @param [Integer] personal_access_token_id ID of the personal access token.
|
470
|
+
# @return [Gitlab::ObjectifiedHash]
|
471
|
+
def rotate_personal_access_token(personal_access_token_id, expires_at = nil)
|
472
|
+
body = {}
|
473
|
+
body[:expires_at] = expires_at if expires_at
|
474
|
+
post("/personal_access_tokens/#{personal_access_token_id}/rotate", body: body)
|
475
|
+
end
|
476
|
+
|
385
477
|
# Revoke an impersonation token
|
386
478
|
#
|
387
479
|
# @example
|
@@ -393,5 +485,37 @@ class Gitlab::Client
|
|
393
485
|
def revoke_user_impersonation_token(user_id, impersonation_token_id)
|
394
486
|
delete("/users/#{user_id}/impersonation_tokens/#{impersonation_token_id}")
|
395
487
|
end
|
488
|
+
|
489
|
+
# Lists all projects and groups a user is a member of
|
490
|
+
#
|
491
|
+
# @example
|
492
|
+
# Gitlab.memberships(2)
|
493
|
+
#
|
494
|
+
# @param [Integer] user_id The ID of the user.
|
495
|
+
def memberships(user_id)
|
496
|
+
get("/users/#{user_id}/memberships")
|
497
|
+
end
|
498
|
+
|
499
|
+
# Revoke a personal access token
|
500
|
+
#
|
501
|
+
# @example
|
502
|
+
# Gitlab.revoke_personal_access_token(1)
|
503
|
+
#
|
504
|
+
# @param [Integer] personal_access_token_id ID of the personal access token.
|
505
|
+
# @return [Gitlab::ObjectifiedHash]
|
506
|
+
def revoke_personal_access_token(personal_access_token_id)
|
507
|
+
delete("/personal_access_tokens/#{personal_access_token_id}")
|
508
|
+
end
|
509
|
+
|
510
|
+
# Disables two factor authentication (2FA) for the specified user.
|
511
|
+
#
|
512
|
+
# @example
|
513
|
+
# Gitlab.disable_two_factor(1)
|
514
|
+
#
|
515
|
+
# @param [Integer] id The ID of a user.
|
516
|
+
# @return [Gitlab::ObjectifiedHash]
|
517
|
+
def disable_two_factor(user_id)
|
518
|
+
patch("/users/#{user_id}/disable_two_factor")
|
519
|
+
end
|
396
520
|
end
|
397
521
|
end
|
data/lib/gitlab/client.rb
CHANGED
@@ -37,6 +37,7 @@ module Gitlab
|
|
37
37
|
include Markdown
|
38
38
|
include MergeRequestApprovals
|
39
39
|
include MergeRequests
|
40
|
+
include MergeTrains
|
40
41
|
include Milestones
|
41
42
|
include Namespaces
|
42
43
|
include Notes
|
@@ -46,6 +47,7 @@ module Gitlab
|
|
46
47
|
include Pipelines
|
47
48
|
include ProjectBadges
|
48
49
|
include ProjectClusters
|
50
|
+
include ProjectExports
|
49
51
|
include ProjectReleaseLinks
|
50
52
|
include ProjectReleases
|
51
53
|
include Projects
|
@@ -75,7 +77,7 @@ module Gitlab
|
|
75
77
|
# @return [String]
|
76
78
|
def inspect
|
77
79
|
inspected = super
|
78
|
-
inspected
|
80
|
+
inspected = redact_private_token(inspected, @private_token) if @private_token
|
79
81
|
inspected
|
80
82
|
end
|
81
83
|
|
@@ -89,7 +91,14 @@ module Gitlab
|
|
89
91
|
|
90
92
|
private
|
91
93
|
|
94
|
+
def redact_private_token(inspected, private_token)
|
95
|
+
redacted = only_show_last_four_chars(private_token)
|
96
|
+
inspected.sub %(@private_token="#{private_token}"), %(@private_token="#{redacted}")
|
97
|
+
end
|
98
|
+
|
92
99
|
def only_show_last_four_chars(token)
|
100
|
+
return '****' if token.size <= 4
|
101
|
+
|
93
102
|
"#{'*' * (token.size - 4)}#{token[-4..]}"
|
94
103
|
end
|
95
104
|
end
|
data/lib/gitlab/configuration.rb
CHANGED
@@ -5,7 +5,7 @@ module Gitlab
|
|
5
5
|
# Defines constants and methods related to configuration.
|
6
6
|
module Configuration
|
7
7
|
# An array of valid keys in the options hash when configuring a Gitlab::API.
|
8
|
-
VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httparty].freeze
|
8
|
+
VALID_OPTIONS_KEYS = %i[endpoint private_token user_agent sudo httparty pat_prefix].freeze
|
9
9
|
|
10
10
|
# The user agent that will be sent to the API endpoint if none is set.
|
11
11
|
DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}"
|
@@ -37,6 +37,7 @@ module Gitlab
|
|
37
37
|
def reset
|
38
38
|
self.endpoint = ENV['GITLAB_API_ENDPOINT'] || ENV['CI_API_V4_URL']
|
39
39
|
self.private_token = ENV['GITLAB_API_PRIVATE_TOKEN'] || ENV['GITLAB_API_AUTH_TOKEN']
|
40
|
+
self.pat_prefix = nil
|
40
41
|
self.httparty = get_httparty_config(ENV['GITLAB_API_HTTPARTY_OPTIONS'])
|
41
42
|
self.sudo = nil
|
42
43
|
self.user_agent = DEFAULT_USER_AGENT
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module Headers
|
5
|
+
# Parses link header.
|
6
|
+
#
|
7
|
+
# @private
|
8
|
+
class PageLinks
|
9
|
+
HEADER_LINK = 'Link'
|
10
|
+
DELIM_LINKS = ','
|
11
|
+
LINK_REGEX = /<([^>]+)>; rel="([^"]+)"/
|
12
|
+
METAS = %w[last next first prev].freeze
|
13
|
+
|
14
|
+
attr_accessor(*METAS)
|
15
|
+
|
16
|
+
def initialize(headers)
|
17
|
+
link_header = headers[HEADER_LINK]
|
18
|
+
|
19
|
+
extract_links(link_header) if link_header && link_header =~ /(next|first|last|prev)/
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def extract_links(header)
|
25
|
+
header.split(DELIM_LINKS).each do |link|
|
26
|
+
LINK_REGEX.match(link.strip) do |match|
|
27
|
+
url = match[1]
|
28
|
+
meta = match[2]
|
29
|
+
next if !url || !meta || METAS.index(meta).nil?
|
30
|
+
|
31
|
+
send("#{meta}=", url)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gitlab
|
4
|
+
module Headers
|
5
|
+
# Parses total header.
|
6
|
+
#
|
7
|
+
# @private
|
8
|
+
class Total
|
9
|
+
HEADER_TOTAL = 'x-total'
|
10
|
+
TOTAL_REGEX = /^\d+$/
|
11
|
+
|
12
|
+
attr_accessor :total
|
13
|
+
|
14
|
+
def initialize(headers)
|
15
|
+
header_total = headers[HEADER_TOTAL]
|
16
|
+
|
17
|
+
extract_total(header_total) if header_total
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def extract_total(header_total)
|
23
|
+
TOTAL_REGEX.match(header_total.strip) do |match|
|
24
|
+
@total = match[0]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -30,7 +30,8 @@ module Gitlab
|
|
30
30
|
end
|
31
31
|
|
32
32
|
def parse_headers!(headers)
|
33
|
-
@links = PageLinks.new headers
|
33
|
+
@links = Headers::PageLinks.new headers
|
34
|
+
@total = Headers::Total.new headers
|
34
35
|
end
|
35
36
|
|
36
37
|
def each_page
|
@@ -58,6 +59,10 @@ module Gitlab
|
|
58
59
|
lazy_paginate.take(limit).each(&block)
|
59
60
|
end
|
60
61
|
|
62
|
+
def total
|
63
|
+
@total.total
|
64
|
+
end
|
65
|
+
|
61
66
|
def last_page?
|
62
67
|
!(@links.nil? || @links.last.nil?)
|
63
68
|
end
|
data/lib/gitlab/request.rb
CHANGED
@@ -12,7 +12,7 @@ module Gitlab
|
|
12
12
|
headers 'Accept' => 'application/json', 'Content-Type' => 'application/x-www-form-urlencoded'
|
13
13
|
parser(proc { |body, _| parse(body) })
|
14
14
|
|
15
|
-
attr_accessor :private_token, :endpoint
|
15
|
+
attr_accessor :private_token, :endpoint, :pat_prefix
|
16
16
|
|
17
17
|
# Converts the response body to an ObjectifiedHash.
|
18
18
|
def self.parse(body)
|
@@ -38,7 +38,7 @@ module Gitlab
|
|
38
38
|
raise Error::Parsing, 'The response is not a valid JSON'
|
39
39
|
end
|
40
40
|
|
41
|
-
%w[get post put delete].each do |method|
|
41
|
+
%w[get post put patch delete].each do |method|
|
42
42
|
define_method method do |path, options = {}|
|
43
43
|
params = options.dup
|
44
44
|
|
@@ -93,10 +93,19 @@ module Gitlab
|
|
93
93
|
def authorization_header
|
94
94
|
raise Error::MissingCredentials, 'Please provide a private_token or auth_token for user' unless private_token
|
95
95
|
|
96
|
-
|
96
|
+
# The Personal Access Token prefix can be at most 20 characters, and the
|
97
|
+
# generated part is of length 20 characters. Personal Access Tokens, thus
|
98
|
+
# can have a maximum size of 40 characters. GitLab uses
|
99
|
+
# `Doorkeeper::OAuth::Helpers::UniqueToken.generate` for generating
|
100
|
+
# OAuth2 tokens, and specified `hex` as token generator method. Thus, the
|
101
|
+
# OAuth2 tokens are of length more than 64. If the token length is below
|
102
|
+
# that, it is probably a Personal Access Token or CI_JOB_TOKEN.
|
103
|
+
if private_token.size >= 64
|
104
|
+
{ 'Authorization' => "Bearer #{private_token}" }
|
105
|
+
elsif private_token.start_with?(pat_prefix.to_s)
|
97
106
|
{ 'PRIVATE-TOKEN' => private_token }
|
98
107
|
else
|
99
|
-
{ '
|
108
|
+
{ 'JOB-TOKEN' => private_token }
|
100
109
|
end
|
101
110
|
end
|
102
111
|
|
data/lib/gitlab/version.rb
CHANGED
data/lib/gitlab.rb
CHANGED
@@ -4,7 +4,8 @@ require 'gitlab/version'
|
|
4
4
|
require 'gitlab/objectified_hash'
|
5
5
|
require 'gitlab/configuration'
|
6
6
|
require 'gitlab/error'
|
7
|
-
require 'gitlab/page_links'
|
7
|
+
require 'gitlab/headers/page_links'
|
8
|
+
require 'gitlab/headers/total'
|
8
9
|
require 'gitlab/paginated_response'
|
9
10
|
require 'gitlab/file_response'
|
10
11
|
require 'gitlab/request'
|
@@ -49,8 +50,10 @@ module Gitlab
|
|
49
50
|
#
|
50
51
|
# @return [Array<Symbol>]
|
51
52
|
def self.actions
|
53
|
+
# rubocop:disable Layout/LineLength
|
52
54
|
hidden =
|
53
|
-
/endpoint|private_token|auth_token|user_agent|sudo|get|post|put|\Adelete\z|validate\z|request_defaults|httparty/
|
55
|
+
/endpoint|private_token|auth_token|user_agent|sudo|get|post|put|patch|\Adelete\z|validate\z|request_defaults|httparty/
|
56
|
+
# rubocop:enable Layout/LineLength
|
54
57
|
(Gitlab::Client.instance_methods - Object.methods).reject { |e| e[hidden] }
|
55
58
|
end
|
56
59
|
end
|