gitlab 3.0.0 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +2 -0
- data/.travis.yml +1 -0
- data/LICENSE.txt +1 -1
- data/README.md +28 -3
- data/bin/gitlab +7 -0
- data/gitlab.gemspec +3 -2
- data/lib/gitlab.rb +8 -0
- data/lib/gitlab/api.rb +1 -1
- data/lib/gitlab/cli.rb +57 -0
- data/lib/gitlab/cli_helpers.rb +141 -0
- data/lib/gitlab/client.rb +8 -6
- data/lib/gitlab/client/branches.rb +79 -0
- data/lib/gitlab/client/merge_requests.rb +15 -2
- data/lib/gitlab/client/projects.rb +25 -4
- data/lib/gitlab/client/repositories.rb +22 -23
- data/lib/gitlab/client/system_hooks.rb +58 -0
- data/lib/gitlab/client/users.rb +17 -0
- data/lib/gitlab/configuration.rb +3 -3
- data/lib/gitlab/objectified_hash.rb +8 -2
- data/lib/gitlab/request.rb +21 -5
- data/lib/gitlab/version.rb +1 -1
- data/spec/fixtures/branch.json +1 -0
- data/spec/fixtures/{project_branches.json → branches.json} +0 -0
- data/spec/fixtures/create_branch.json +1 -0
- data/spec/fixtures/merge_request_comments.json +1 -0
- data/spec/fixtures/project_commit.json +13 -0
- data/spec/fixtures/project_commit_diff.json +10 -0
- data/spec/fixtures/{project_branch.json → protect_branch.json} +1 -1
- data/spec/fixtures/system_hook.json +1 -0
- data/spec/fixtures/system_hook_test.json +1 -0
- data/spec/fixtures/system_hooks.json +1 -0
- data/spec/fixtures/unprotect_branch.json +1 -0
- data/spec/gitlab/cli_spec.rb +80 -0
- data/spec/gitlab/client/branches_spec.rb +103 -0
- data/spec/gitlab/client/groups_spec.rb +21 -21
- data/spec/gitlab/client/issues_spec.rb +26 -26
- data/spec/gitlab/client/merge_requests_spec.rb +45 -13
- data/spec/gitlab/client/milestones_spec.rb +11 -11
- data/spec/gitlab/client/notes_spec.rb +30 -30
- data/spec/gitlab/client/projects_spec.rb +93 -59
- data/spec/gitlab/client/repositories_spec.rb +28 -25
- data/spec/gitlab/client/snippets_spec.rb +16 -16
- data/spec/gitlab/client/system_hooks_spec.rb +69 -0
- data/spec/gitlab/client/users_spec.rb +60 -24
- data/spec/gitlab/objectified_hash_spec.rb +23 -0
- data/spec/gitlab/request_spec.rb +48 -0
- data/spec/gitlab_spec.rb +16 -7
- data/spec/spec_helper.rb +19 -8
- metadata +70 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 88679bf87230b7d3d6bb8f0e96fb779967936216
|
4
|
+
data.tar.gz: 6c41b6c43280434257bc160aa38963ef50a4cc72
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ae58eefafd56dba8d8b87029c89972d036c479d3a3d15b6a7196e08495d9325de841a1860cb29151dd879aa05bee8fef1f340118d6309b520532804615b464d9
|
7
|
+
data.tar.gz: a96ddd98eebc816f295856c6996b1b29462c9a236d4a1d67b5c6259dc00e7f1b7b08bbf395c7bc69d1b8983e7be990ca2cda9a143c218f33dab3d3df8134731f
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,10 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/NARKOZ/gitlab.png)](http://travis-ci.org/NARKOZ/gitlab)
|
4
4
|
|
5
|
-
|
5
|
+
[website](http://narkoz.github.io/gitlab) |
|
6
|
+
[documentation](http://rubydoc.info/gems/gitlab/frames)
|
7
|
+
|
8
|
+
Gitlab is a Ruby wrapper and CLI for the [GitLab API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api#gitlab-api).
|
6
9
|
|
7
10
|
## Installation
|
8
11
|
|
@@ -25,7 +28,7 @@ Configuration example:
|
|
25
28
|
|
26
29
|
```ruby
|
27
30
|
Gitlab.configure do |config|
|
28
|
-
config.endpoint = 'https://example.net/api/
|
31
|
+
config.endpoint = 'https://example.net/api/v3' # API endpoint URL (required)
|
29
32
|
config.private_token = 'qEsq1pt6HJPaNciie3MG' # user's private token (required)
|
30
33
|
config.user_agent = 'Custom User Agent' # user agent, default to 'Gitlab Ruby Gem [version]' (optional)
|
31
34
|
end
|
@@ -35,7 +38,7 @@ Usage examples:
|
|
35
38
|
|
36
39
|
```ruby
|
37
40
|
# set an API endpoint
|
38
|
-
Gitlab.endpoint = 'http://example.net/api/
|
41
|
+
Gitlab.endpoint = 'http://example.net/api/v3'
|
39
42
|
# => "http://example.net/api/v2"
|
40
43
|
|
41
44
|
# set a user private token
|
@@ -69,6 +72,28 @@ Gitlab.sudo = nil
|
|
69
72
|
|
70
73
|
For more information, refer to [documentation](http://rubydoc.info/gems/gitlab/frames).
|
71
74
|
|
75
|
+
## CLI
|
76
|
+
|
77
|
+
Usage examples:
|
78
|
+
|
79
|
+
```sh
|
80
|
+
# list users
|
81
|
+
gitlab users
|
82
|
+
|
83
|
+
# get current user
|
84
|
+
gitlab user
|
85
|
+
|
86
|
+
# get a user
|
87
|
+
gitlab user 2
|
88
|
+
|
89
|
+
# filter output
|
90
|
+
gitlab user --only=id,username
|
91
|
+
|
92
|
+
gitlab user --except=email,bio
|
93
|
+
```
|
94
|
+
|
95
|
+
For more information, refer to [website](http://narkoz.github.io/gitlab).
|
96
|
+
|
72
97
|
## License
|
73
98
|
|
74
99
|
Released under the BSD 2-clause license. See LICENSE.txt for details.
|
data/bin/gitlab
ADDED
data/gitlab.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |gem|
|
|
8
8
|
gem.version = Gitlab::VERSION
|
9
9
|
gem.authors = ["Nihad Abbasov"]
|
10
10
|
gem.email = ["mail@narkoz.me"]
|
11
|
-
gem.description = %q{Ruby client for GitLab API}
|
12
|
-
gem.summary = %q{A Ruby wrapper for the GitLab API}
|
11
|
+
gem.description = %q{Ruby client and CLI for GitLab API}
|
12
|
+
gem.summary = %q{A Ruby wrapper and CLI for the GitLab API}
|
13
13
|
gem.homepage = "https://github.com/narkoz/gitlab"
|
14
14
|
|
15
15
|
gem.files = `git ls-files`.split($/)
|
@@ -18,6 +18,7 @@ Gem::Specification.new do |gem|
|
|
18
18
|
gem.require_paths = ["lib"]
|
19
19
|
|
20
20
|
gem.add_runtime_dependency 'httparty'
|
21
|
+
gem.add_runtime_dependency 'terminal-table'
|
21
22
|
|
22
23
|
gem.add_development_dependency 'rake'
|
23
24
|
gem.add_development_dependency 'rspec'
|
data/lib/gitlab.rb
CHANGED
@@ -26,4 +26,12 @@ module Gitlab
|
|
26
26
|
def self.respond_to?(method)
|
27
27
|
return client.respond_to?(method) || super
|
28
28
|
end
|
29
|
+
|
30
|
+
# Returns an unsorted array of available client methods.
|
31
|
+
#
|
32
|
+
# @return [Array<Symbol>]
|
33
|
+
def self.actions
|
34
|
+
hidden = /endpoint|private_token|user_agent|sudo|get|post|put|\Adelete\z|validate|set_request_defaults/
|
35
|
+
(Gitlab::Client.instance_methods - Object.methods).reject {|e| e[hidden]}
|
36
|
+
end
|
29
37
|
end
|
data/lib/gitlab/api.rb
CHANGED
data/lib/gitlab/cli.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'gitlab'
|
2
|
+
require 'terminal-table/import'
|
3
|
+
require_relative 'cli_helpers'
|
4
|
+
|
5
|
+
class Gitlab::CLI
|
6
|
+
extend Helpers
|
7
|
+
|
8
|
+
def self.start(args)
|
9
|
+
command = args.shift.strip rescue 'help'
|
10
|
+
run(command, args)
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.run(cmd, args=[])
|
14
|
+
case cmd
|
15
|
+
when 'help'
|
16
|
+
puts actions_table
|
17
|
+
when 'info'
|
18
|
+
endpoint = Gitlab.endpoint ? Gitlab.endpoint : 'not set'
|
19
|
+
private_token = Gitlab.private_token ? Gitlab.private_token : 'not set'
|
20
|
+
puts "Gitlab endpoint is #{endpoint}"
|
21
|
+
puts "Gitlab private token is #{private_token}"
|
22
|
+
puts "Ruby Version is #{RUBY_VERSION}"
|
23
|
+
puts "Gitlab Ruby Gem #{Gitlab::VERSION}"
|
24
|
+
when '-v', '--version'
|
25
|
+
puts "Gitlab Ruby Gem #{Gitlab::VERSION}"
|
26
|
+
else
|
27
|
+
unless Gitlab.actions.include?(cmd.to_sym)
|
28
|
+
puts "Unknown command. Run `gitlab help` for a list of available commands."
|
29
|
+
exit(1)
|
30
|
+
end
|
31
|
+
|
32
|
+
if args.any? && (args.last.start_with?('--only=') || args.last.start_with?('--except='))
|
33
|
+
command_args = args[0..-2]
|
34
|
+
else
|
35
|
+
command_args = args
|
36
|
+
end
|
37
|
+
|
38
|
+
confirm_command(cmd)
|
39
|
+
|
40
|
+
begin
|
41
|
+
data = args.any? ? Gitlab.send(cmd, *command_args) : Gitlab.send(cmd)
|
42
|
+
rescue => e
|
43
|
+
puts e.message
|
44
|
+
exit(1)
|
45
|
+
end
|
46
|
+
|
47
|
+
case data
|
48
|
+
when Gitlab::ObjectifiedHash
|
49
|
+
puts single_record_table(data, cmd, args)
|
50
|
+
when Array
|
51
|
+
puts multiple_record_table(data, cmd, args)
|
52
|
+
else
|
53
|
+
puts data.inspect
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
class Gitlab::CLI
|
2
|
+
# Defines methods related to CLI output and formatting.
|
3
|
+
module Helpers
|
4
|
+
extend self
|
5
|
+
|
6
|
+
# Returns filtered required fields.
|
7
|
+
#
|
8
|
+
# @return [Array]
|
9
|
+
def required_fields(args)
|
10
|
+
if args.any? && args.last.start_with?('--only=')
|
11
|
+
args.last.gsub('--only=', '').split(',')
|
12
|
+
else
|
13
|
+
[]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns filtered excluded fields.
|
18
|
+
#
|
19
|
+
# @return [Array]
|
20
|
+
def excluded_fields(args)
|
21
|
+
if args.any? && args.last.start_with?('--except=')
|
22
|
+
args.last.gsub('--except=', '').split(',')
|
23
|
+
else
|
24
|
+
[]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Confirms command with a desctructive action.
|
29
|
+
#
|
30
|
+
# @return [String]
|
31
|
+
def confirm_command(cmd)
|
32
|
+
if cmd.start_with?('remove_') || cmd.start_with?('delete_')
|
33
|
+
puts "Are you sure? (y/n)"
|
34
|
+
if %w(y yes).include?($stdin.gets.to_s.strip.downcase)
|
35
|
+
puts 'Proceeding..'
|
36
|
+
else
|
37
|
+
puts 'Command aborted.'
|
38
|
+
exit(1)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Table with available commands.
|
44
|
+
#
|
45
|
+
# @return [String]
|
46
|
+
def actions_table
|
47
|
+
client = Gitlab::Client.new(endpoint: '')
|
48
|
+
actions = Gitlab.actions
|
49
|
+
methods = []
|
50
|
+
|
51
|
+
actions.each do |action|
|
52
|
+
methods << {
|
53
|
+
name: action,
|
54
|
+
owner: client.method(action).owner.to_s.gsub('Gitlab::Client::', '')
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
owners = methods.map {|m| m[:owner]}.uniq.sort
|
59
|
+
methods_c = methods.group_by {|m| m[:owner]}
|
60
|
+
methods_c = methods_c.map {|_, v| [_, v.sort_by {|hv| hv[:name]}] }
|
61
|
+
methods_c = Hash[methods_c.sort_by(&:first).map {|k, v| [k, v]}]
|
62
|
+
max_column_length = methods_c.values.max_by(&:size).size
|
63
|
+
|
64
|
+
rows = max_column_length.times.map do |i|
|
65
|
+
methods_c.keys.map do |key|
|
66
|
+
methods_c[key][i] ? methods_c[key][i][:name] : ''
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
table do |t|
|
71
|
+
t.title = "Available commands (#{actions.size} total)"
|
72
|
+
t.headings = owners
|
73
|
+
|
74
|
+
rows.each do |row|
|
75
|
+
t.add_row row
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Table for a single record.
|
81
|
+
#
|
82
|
+
# @return [String]
|
83
|
+
def single_record_table(data, cmd, args)
|
84
|
+
hash = data.to_h
|
85
|
+
keys = hash.keys.sort {|x, y| x.to_s <=> y.to_s }
|
86
|
+
keys = keys & required_fields(args) if required_fields(args).any?
|
87
|
+
keys = keys - excluded_fields(args)
|
88
|
+
|
89
|
+
table do |t|
|
90
|
+
t.title = "Gitlab.#{cmd} #{args.join(', ')}"
|
91
|
+
|
92
|
+
keys.each_with_index do |key, index|
|
93
|
+
case value = hash[key]
|
94
|
+
when Hash
|
95
|
+
value = 'Hash'
|
96
|
+
when nil
|
97
|
+
value = 'null'
|
98
|
+
end
|
99
|
+
|
100
|
+
t.add_row [key, value]
|
101
|
+
t.add_separator unless keys.size - 1 == index
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
# Table for multiple records.
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
def multiple_record_table(data, cmd, args)
|
110
|
+
return 'No data' if data.empty?
|
111
|
+
|
112
|
+
arr = data.map(&:to_h)
|
113
|
+
keys = arr.first.keys.sort {|x, y| x.to_s <=> y.to_s }
|
114
|
+
keys = keys & required_fields(args) if required_fields(args).any?
|
115
|
+
keys = keys - excluded_fields(args)
|
116
|
+
|
117
|
+
table do |t|
|
118
|
+
t.title = "Gitlab.#{cmd} #{args.join(', ')}"
|
119
|
+
t.headings = keys
|
120
|
+
|
121
|
+
arr.each_with_index do |hash, index|
|
122
|
+
values = []
|
123
|
+
|
124
|
+
keys.each do |key|
|
125
|
+
case value = hash[key]
|
126
|
+
when Hash
|
127
|
+
value = 'Hash'
|
128
|
+
when nil
|
129
|
+
value = 'null'
|
130
|
+
end
|
131
|
+
|
132
|
+
values << value
|
133
|
+
end
|
134
|
+
|
135
|
+
t.add_row values
|
136
|
+
t.add_separator unless arr.size - 1 == index
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
data/lib/gitlab/client.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
module Gitlab
|
2
2
|
# Wrapper for the Gitlab REST API.
|
3
3
|
class Client < API
|
4
|
-
Dir[File.expand_path('../client/*.rb', __FILE__)].each{|f| require f}
|
4
|
+
Dir[File.expand_path('../client/*.rb', __FILE__)].each {|f| require f}
|
5
5
|
|
6
|
-
include
|
6
|
+
include Branches
|
7
|
+
include Groups
|
7
8
|
include Issues
|
8
|
-
include
|
9
|
+
include MergeRequests
|
9
10
|
include Milestones
|
10
|
-
include
|
11
|
+
include Notes
|
11
12
|
include Projects
|
12
13
|
include Repositories
|
13
|
-
include
|
14
|
-
include
|
14
|
+
include Snippets
|
15
|
+
include SystemHooks
|
16
|
+
include Users
|
15
17
|
end
|
16
18
|
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
class Gitlab::Client
|
2
|
+
# Defines methods related to repositories.
|
3
|
+
module Branches
|
4
|
+
# Gets a list of project repositiory branches.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# Gitlab.branches(42)
|
8
|
+
#
|
9
|
+
# @param [Integer] project The ID of a project.
|
10
|
+
# @param [Hash] options A customizable set of options.
|
11
|
+
# @option options [Integer] :page The page number.
|
12
|
+
# @option options [Integer] :per_page The number of results per page.
|
13
|
+
# @return [Array<Gitlab::ObjectifiedHash>]
|
14
|
+
def branches(project, options={})
|
15
|
+
get("/projects/#{project}/repository/branches", :query => options)
|
16
|
+
end
|
17
|
+
alias_method :repo_branches, :branches
|
18
|
+
|
19
|
+
# Gets information about a repository branch.
|
20
|
+
#
|
21
|
+
# @example
|
22
|
+
# Gitlab.branch(3, 'api')
|
23
|
+
# Gitlab.repo_branch(5, 'master')
|
24
|
+
#
|
25
|
+
# @param [Integer] project The ID of a project.
|
26
|
+
# @param [String] branch The name of the branch.
|
27
|
+
# @return [Gitlab::ObjectifiedHash]
|
28
|
+
def branch(project, branch)
|
29
|
+
get("/projects/#{project}/repository/branches/#{branch}")
|
30
|
+
end
|
31
|
+
|
32
|
+
alias_method :repo_branch, :branch
|
33
|
+
|
34
|
+
# Protects a repository branch.
|
35
|
+
#
|
36
|
+
# @example
|
37
|
+
# Gitlab.protect_branch(3, 'api')
|
38
|
+
# Gitlab.repo_protect_branch(5, 'master')
|
39
|
+
#
|
40
|
+
# @param [Integer] project The ID of a project.
|
41
|
+
# @param [String] branch The name of the branch.
|
42
|
+
# @return [Gitlab::ObjectifiedHash]
|
43
|
+
def protect_branch(project, branch)
|
44
|
+
put("/projects/#{project}/repository/branches/#{branch}/protect")
|
45
|
+
end
|
46
|
+
alias_method :repo_protect_branch, :protect_branch
|
47
|
+
|
48
|
+
# Unprotects a repository branch.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# Gitlab.unprotect_branch(3, 'api')
|
52
|
+
# Gitlab.repo_unprotect_branch(5, 'master')
|
53
|
+
#
|
54
|
+
# @param [Integer] project The ID of a project.
|
55
|
+
# @param [String] branch The name of the branch.
|
56
|
+
# @return [Gitlab::ObjectifiedHash]
|
57
|
+
def unprotect_branch(project, branch)
|
58
|
+
put("/projects/#{project}/repository/branches/#{branch}/unprotect")
|
59
|
+
end
|
60
|
+
alias_method :repo_unprotect_branch, :unprotect_branch
|
61
|
+
|
62
|
+
# Creates a repository branch. Requires Gitlab >= 6.8.x
|
63
|
+
#
|
64
|
+
# @example
|
65
|
+
# Gitlab.create_branch(3, 'api')
|
66
|
+
# Gitlab.repo_create_branch(5, 'master')
|
67
|
+
#
|
68
|
+
# @param [Integer] project The ID of a project.
|
69
|
+
# @param [String] branch The name of the new branch.
|
70
|
+
# @param [String] ref Create branch from commit sha or existing branch
|
71
|
+
# @return [Gitlab::ObjectifiedHash]
|
72
|
+
def create_branch(project, branch, ref)
|
73
|
+
post("/projects/#{project}/repository/branches",:body => {:branch_name => branch, :ref => ref})
|
74
|
+
end
|
75
|
+
alias_method :repo_create_branch, :create_branch
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
@@ -62,6 +62,7 @@ class Gitlab::Client
|
|
62
62
|
# @option options [String] :source_branch The source branch name.
|
63
63
|
# @option options [String] :target_branch The target branch name.
|
64
64
|
# @option options [Integer] :assignee_id The ID of a user to assign merge request.
|
65
|
+
# @option options [String] :state_event New state (close|reopen|merge).
|
65
66
|
# @return [Gitlab::ObjectifiedHash] Information about updated merge request.
|
66
67
|
def update_merge_request(project, id, options={})
|
67
68
|
put("/projects/#{project}/merge_request/#{id}", :body => options)
|
@@ -70,8 +71,8 @@ class Gitlab::Client
|
|
70
71
|
# Adds a comment to a merge request.
|
71
72
|
#
|
72
73
|
# @example
|
73
|
-
# Gitlab.
|
74
|
-
# Gitlab.
|
74
|
+
# Gitlab.create_merge_request_comment(5, 1, "Awesome merge!")
|
75
|
+
# Gitlab.create_merge_request_comment('gitlab', 1, "Awesome merge!")
|
75
76
|
#
|
76
77
|
# @param [Integer] project The ID of a project.
|
77
78
|
# @param [Integer] id The ID of a merge request.
|
@@ -81,6 +82,18 @@ class Gitlab::Client
|
|
81
82
|
post("/projects/#{project}/merge_request/#{id}/comments", :body => {:note => note})
|
82
83
|
end
|
83
84
|
|
85
|
+
# Gets the comments on a merge request.
|
86
|
+
#
|
87
|
+
# @example
|
88
|
+
# Gitlab.merge_request_comments(5, 1)
|
89
|
+
#
|
90
|
+
# @param [Integer] project The ID of a project.
|
91
|
+
# @param [Integer] id The ID of a merge request.
|
92
|
+
# @return [Gitlab::ObjectifiedHash] The merge request's comments.
|
93
|
+
def merge_request_comments(project, id)
|
94
|
+
get("/projects/#{project}/merge_request/#{id}/comments")
|
95
|
+
end
|
96
|
+
|
84
97
|
private
|
85
98
|
|
86
99
|
def check_attributes!(options, attrs)
|