gitlab 3.0.0 → 3.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.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.travis.yml +1 -0
  4. data/LICENSE.txt +1 -1
  5. data/README.md +28 -3
  6. data/bin/gitlab +7 -0
  7. data/gitlab.gemspec +3 -2
  8. data/lib/gitlab.rb +8 -0
  9. data/lib/gitlab/api.rb +1 -1
  10. data/lib/gitlab/cli.rb +57 -0
  11. data/lib/gitlab/cli_helpers.rb +141 -0
  12. data/lib/gitlab/client.rb +8 -6
  13. data/lib/gitlab/client/branches.rb +79 -0
  14. data/lib/gitlab/client/merge_requests.rb +15 -2
  15. data/lib/gitlab/client/projects.rb +25 -4
  16. data/lib/gitlab/client/repositories.rb +22 -23
  17. data/lib/gitlab/client/system_hooks.rb +58 -0
  18. data/lib/gitlab/client/users.rb +17 -0
  19. data/lib/gitlab/configuration.rb +3 -3
  20. data/lib/gitlab/objectified_hash.rb +8 -2
  21. data/lib/gitlab/request.rb +21 -5
  22. data/lib/gitlab/version.rb +1 -1
  23. data/spec/fixtures/branch.json +1 -0
  24. data/spec/fixtures/{project_branches.json → branches.json} +0 -0
  25. data/spec/fixtures/create_branch.json +1 -0
  26. data/spec/fixtures/merge_request_comments.json +1 -0
  27. data/spec/fixtures/project_commit.json +13 -0
  28. data/spec/fixtures/project_commit_diff.json +10 -0
  29. data/spec/fixtures/{project_branch.json → protect_branch.json} +1 -1
  30. data/spec/fixtures/system_hook.json +1 -0
  31. data/spec/fixtures/system_hook_test.json +1 -0
  32. data/spec/fixtures/system_hooks.json +1 -0
  33. data/spec/fixtures/unprotect_branch.json +1 -0
  34. data/spec/gitlab/cli_spec.rb +80 -0
  35. data/spec/gitlab/client/branches_spec.rb +103 -0
  36. data/spec/gitlab/client/groups_spec.rb +21 -21
  37. data/spec/gitlab/client/issues_spec.rb +26 -26
  38. data/spec/gitlab/client/merge_requests_spec.rb +45 -13
  39. data/spec/gitlab/client/milestones_spec.rb +11 -11
  40. data/spec/gitlab/client/notes_spec.rb +30 -30
  41. data/spec/gitlab/client/projects_spec.rb +93 -59
  42. data/spec/gitlab/client/repositories_spec.rb +28 -25
  43. data/spec/gitlab/client/snippets_spec.rb +16 -16
  44. data/spec/gitlab/client/system_hooks_spec.rb +69 -0
  45. data/spec/gitlab/client/users_spec.rb +60 -24
  46. data/spec/gitlab/objectified_hash_spec.rb +23 -0
  47. data/spec/gitlab/request_spec.rb +48 -0
  48. data/spec/gitlab_spec.rb +16 -7
  49. data/spec/spec_helper.rb +19 -8
  50. metadata +70 -22
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e73d6232b1c15dcf05f0b58e12e4d93ca076d210
4
- data.tar.gz: b8e227455c58f3195448c2712b0ea6f1e3d56ade
3
+ metadata.gz: 88679bf87230b7d3d6bb8f0e96fb779967936216
4
+ data.tar.gz: 6c41b6c43280434257bc160aa38963ef50a4cc72
5
5
  SHA512:
6
- metadata.gz: e624e3813e30c96657d5810788dc56bcf032b8f132a8a36a88ad3a7a13aa9a42f2c7bf3f61a47c9c21c5013dc09327e79d305db7a67f985530a6998c5e94da95
7
- data.tar.gz: d118ef1b86f69311740d79e0f74390c8041e2c8a5b96345ed0edb52bbbc5bfa243fd380b8e8106eeaf71d28114968aeac879938ec5a76aa399d4adb2c075b47d
6
+ metadata.gz: ae58eefafd56dba8d8b87029c89972d036c479d3a3d15b6a7196e08495d9325de841a1860cb29151dd879aa05bee8fef1f340118d6309b520532804615b464d9
7
+ data.tar.gz: a96ddd98eebc816f295856c6996b1b29462c9a236d4a1d67b5c6259dc00e7f1b7b08bbf395c7bc69d1b8983e7be990ca2cda9a143c218f33dab3d3df8134731f
data/.gitignore CHANGED
@@ -16,3 +16,5 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  .idea
19
+ .ruby-version
20
+ .ruby-gemset
@@ -2,3 +2,4 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ - 2.1
@@ -1,4 +1,4 @@
1
- Copyright (c) 2012-2013 Nihad Abbasov <mail@narkoz.me>
1
+ Copyright (c) 2012-2014 Nihad Abbasov <mail@narkoz.me>
2
2
  All rights reserved.
3
3
 
4
4
  Redistribution and use in source and binary forms, with or without
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
- Gitlab is a Ruby wrapper for the [GitLab API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api#gitlab-api).
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/v2' # API endpoint URL (required)
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/v2'
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.
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift File.expand_path('../../lib', __FILE__)
4
+
5
+ require 'gitlab/cli'
6
+
7
+ Gitlab::CLI.start(ARGV)
@@ -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'
@@ -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
@@ -2,7 +2,7 @@ module Gitlab
2
2
  # @private
3
3
  class API < Request
4
4
  # @private
5
- attr_accessor *Configuration::VALID_OPTIONS_KEYS
5
+ attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
6
6
 
7
7
  # Creates a new API.
8
8
  # @raise [Error:MissingCredentials]
@@ -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
@@ -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 Users
6
+ include Branches
7
+ include Groups
7
8
  include Issues
8
- include Notes
9
+ include MergeRequests
9
10
  include Milestones
10
- include Snippets
11
+ include Notes
11
12
  include Projects
12
13
  include Repositories
13
- include MergeRequests
14
- include Groups
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.comment_merge_request(5, 1, "Awesome merge!")
74
- # Gitlab.comment_merge_request('gitlab', 1, "Awesome merge!")
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)