init project

This commit is contained in:
Jasder
2020-03-09 00:40:16 +08:00
commit 2937b2a94d
6549 changed files with 7215173 additions and 0 deletions

0
lib/assets/.keep Normal file
View File

11
lib/educoder.rb Normal file
View File

@@ -0,0 +1,11 @@
#coding=utf-8
#
#
module Educoder
# 调用时才加载
autoload :TipException, "educoder/tip_exception"
autoload :Utils, "educoder/units"
autoload :Sms, "educoder/sms"
autoload :I18n, "educoder/i18n"
autoload :Ufile, "educoder/ufile"
end

167
lib/educoder/i18n.rb Normal file
View File

@@ -0,0 +1,167 @@
module Educoder
module I18n
def self.included(base)
base.extend Educoder::I18n
end
def l(*args)
case args.size
when 1
::I18n.t(*args)
when 2
if args.last.is_a?(Hash)
::I18n.t(*args)
elsif args.last.is_a?(String)
::I18n.t(args.first, :value => args.last)
else
::I18n.t(args.first, :count => args.last)
end
else
raise "Translation string with multiple values: #{args.first}"
end
end
def l_or_humanize(s, options={})
k = "#{options[:prefix]}#{s}".to_sym
::I18n.t(k, :default => s.to_s.humanize)
end
def l_hours(hours)
hours = hours.to_f
l((hours < 2.0 ? :label_f_hour : :label_f_hour_plural), :value => ("%.2f" % hours.to_f))
end
def ll(lang, str, value=nil)
::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
end
def format_date(date)
return nil unless date
options = {}
options[:format] = Setting.date_format unless Setting.date_format.blank?
options[:locale] = User.current.language unless User.current.language.blank?
::I18n.l(date.to_date, options)
end
def format_time(time, include_date = true)
return nil unless time
options = {}
options[:format] = (Setting.time_format.blank? ? :time : Setting.time_format)
options[:locale] = User.current.language unless User.current.language.blank?
time = time.to_time if time.is_a?(String)
zone = User.current.time_zone
local = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)
(include_date ? "#{format_date(local)} " : "") + ::I18n.l(local, options)
end
def day_name(day)
::I18n.t('date.day_names')[day % 7]
end
def day_letter(day)
::I18n.t('date.abbr_day_names')[day % 7].first
end
def month_name(month)
::I18n.t('date.month_names')[month]
end
def valid_languages
::I18n.available_locales
end
# Returns an array of languages names and code sorted by names, example:
# [["Deutsch", "de"], ["English", "en"] ...]
#
# The result is cached to prevent from loading all translations files.
def languages_options
ActionController::Base.cache_store.fetch "i18n/languages_options" do
valid_languages.map {|lang| [ll(lang.to_s, :general_lang_name), lang.to_s]}.sort {|x,y| x.first <=> y.first }
end
end
def find_language(lang)
@@languages_lookup = valid_languages.inject({}) {|k, v| k[v.to_s.downcase] = v; k }
@@languages_lookup[lang.to_s.downcase]
end
def set_language_if_valid(lang)
if l = find_language(lang)
::I18n.locale = l
end
end
def current_language
::I18n.locale
end
# Custom backend based on I18n::Backend::Simple with the following changes:
# * lazy loading of translation files
# * available_locales are determined by looking at translation file names
class Backend
(class << self; self; end).class_eval { public :include }
module Implementation
include ::I18n::Backend::Base
# Stores translations for the given locale in memory.
# This uses a deep merge for the translations hash, so existing
# translations will be overwritten by new ones only at the deepest
# level of the hash.
def store_translations(locale, data, options = {})
locale = locale.to_sym
translations[locale] ||= {}
data = data.deep_symbolize_keys
translations[locale].deep_merge!(data)
end
# Get available locales from the translations filenames
def available_locales
@available_locales ||= ::I18n.load_path.map {|path| File.basename(path, '.*')}.uniq.sort.map(&:to_sym)
end
# Clean up translations
def reload!
@translations = nil
@available_locales = nil
super
end
protected
def init_translations(locale)
locale = locale.to_s
paths = ::I18n.load_path.select {|path| File.basename(path, '.*') == locale}
load_translations(paths)
translations[locale] ||= {}
end
def translations
@translations ||= {}
end
# Looks up a translation from the translations hash. Returns nil if
# eiher key is nil, or locale, scope or key do not exist as a key in the
# nested translations hash. Splits keys or scopes containing dots
# into multiple keys, i.e. <tt>currency.format</tt> is regarded the same as
# <tt>%w(currency format)</tt>.
def lookup(locale, key, scope = [], options = {})
init_translations(locale) unless translations.key?(locale)
keys = ::I18n.normalize_keys(locale, key, scope, options[:separator])
keys.inject(translations) do |result, _key|
_key = _key.to_sym
return nil unless result.is_a?(Hash) && result.has_key?(_key)
result = result[_key]
result = resolve(locale, _key, result, options.merge(:scope => nil)) if result.is_a?(Symbol)
result
end
end
end
include Implementation
# Adds fallback to default locale for untranslated strings
include ::I18n::Backend::Fallbacks
end
end
end

75
lib/educoder/sms.rb Normal file
View File

@@ -0,0 +1,75 @@
#coding=utf-8
require 'net/https'
require 'uri'
module Educoder
module Sms
def self.send(opt={})
Rails.logger.info "#{opt[:mobile]} - #{opt[:code]}"
begin
o = sendYunpian(opt[:mobile], opt[:code], opt[:send_type], opt[:name], opt[:user_name], opt[:result])
if o["code"] != 0
Rails.logger.error "发送短信出错: #{o['code']}--#{o['msg']}"
end
return o["code"]
rescue => e
Rails.logger.error "发送短信出错: #{e}"
return false
end
end
def self.notify_admin(opt)
opt[:name] = '管理员'
opt[:mobile] = ENV['NOTIFY_ADMIN_PHONE'] || EduSetting.get('notify_admin_phone') || '18711085785'
send(opt)
end
def self.sendYunpian(mobile, code, send_type, name, user_name, result)
#修改为您的apikey.可在官网http://www.yunpian.com)登录后用户中心首页看到
apikey = EduSetting.get('sms_apikey')
#指定模板发送接口HTTP地址
send_tpl_sms_uri = URI.parse('https://sms.yunpian.com/v2/sms/single_send.json')
params = {}
params['apikey'] = apikey
params['mobile'] = mobile
params['text'] = ""
if send_type.nil?
params['text'] = "【Edu实训】" + code + "手机验证码有效期为10分钟。如非本人操作请忽略。"
elsif send_type == 'competition_start'
params['text'] = "【Edu实训】亲爱的#{user_name},你参与的#{name}将于#{result}开始,请及时参赛"
elsif send_type == "teacher_register"
params['mobile'] = EduSetting.get('teacher_register_phone') || '17680641960'
params['text'] = "【Edu实训】亲爱的#{user_name},有新的老师#{name}注册啦,请尽快处理"
elsif send_type == 'subject_authorization' || send_type == 'shixun_authorization'
params['text'] = "【Edu实训】亲爱的#{user_name},您提交的#{name}#{send_type=='subject_authorization'?'实训路径':'实训'}发布申请#{result},请登录平台查看详情"
elsif send_type == 'authentication_pro' || send_type == 'authentication'|| send_type == 'trial_authorization' || send_type == 'project_info'
params['text'] = "【Edu实训】亲爱的#{user_name},您提交的#{send_type == 'authentication_pro'?'职业认证':(send_type == 'authentication'? '实名认证' : (send_type == 'project_info'?'加入申请':'试用申请' ))}#{result},请登录平台查看详情"
elsif send_type == "apply_pro_certification" || send_type == "apply_auth"
params['text'] = "【Edu实训】亲爱的#{name},有新的#{send_type == 'apply_pro_certification'?'职业':'实名'}认证申请,请尽快处理"
elsif send_type == "publish_subject" ||send_type == "publish_shixun"|| send_type == "user_apply_auth" || send_type == "discuss"
params['mobile'] = EduSetting.get('subject_shixun_notify_phone') || '18711011226' if send_type == "publish_subject" || send_type == "publish_shixun"
params['text'] = "【Edu实训】亲爱的#{name},有新的#{send_type == 'publish_subject'?'实训路径':(send_type == 'publish_shixun' ? '实训' : (send_type == 'discuss' ? '实训评论':'试用'))}申请发布,请尽快处理"
elsif send_type == 'join_course_multi_role'
params['text'] = "【Edu实训】亲爱的#{user_name},您的课堂#{name}有助教或者教师申请加入,请尽快审核"
elsif send_type == 'applied_project_info'
params['text'] = "【Edu实训】亲爱的#{user_name},您的项目#{name}有成员申请加入,请尽快审核"
end
http = Net::HTTP.new(send_tpl_sms_uri.host, send_tpl_sms_uri.port)
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.use_ssl = true
begin
request = Net::HTTP::Post.new(send_tpl_sms_uri.request_uri)
request.set_form_data(params)
request['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8'
response = http.start { |http| http.request(request) }
ActiveSupport::JSON.decode(response.body)
rescue =>err
Rails.logger.error("#############sendYunpian_error: #{err.message}")
return nil
end
end
end
end

View File

@@ -0,0 +1,24 @@
module Educoder
class TipException < StandardError
attr_reader :status, :message
def initialize(status=-1, message)
case status
when 403
message = "您没有权限进行该操作"
when 404
message = "您访问的页面不存在或已被删除"
end
@status = status
@message = message
Rails.logger.error("############# #{@status}, #{@message}")
end
def tip_json
{status: self.status, message: self.message}
end
end
end

130
lib/educoder/ufile.rb Normal file
View File

@@ -0,0 +1,130 @@
#coding=utf-8
#
# ucloud 文件上传
#
require 'base64'
require 'openssl'
require 'faraday'
module Educoder
class Ufile
PATH_PREFIX = %r{^/}
def initialize(uploader={})
@ucloud_public_key = uploader[:ucloud_public_key]
@ucloud_private_key = uploader[:ucloud_private_key]
@ucloud_public_read = uploader[:ucloud_public_read]
@ucloud_bucket = @ucloud_public_read ? uploader[:ucloud_public_bucket] : uploader[:ucloud_private_bucket]
@ucloud_bucket_host = @ucloud_public_read ? uploader[:ucloud_public_bucket_host] : uploader[:ucloud_private_bucket_host]
@ucloud_cdn_host = @ucloud_public_read ? uploader[:ucloud_public_cdn_host] : uploader[:ucloud_private_cdn_host]
@ucloud_private_expire_seconds = uploader[:ucloud_private_expire_seconds] || 300
unless @ucloud_cdn_host.include?('//')
raise "config.ucloud_cdn_host requirement include // http:// or https://, but you give: #{@ucloud_cdn_host}"
end
end
# 上传文件
def put(path, file, headers = {})
path.sub!(PATH_PREFIX, '')
response = conn.put(path, file.read) do |req|
req.headers = headers
token = authorization(req.method, headers['Content-Type'], path)
req.headers['Authorization'] = token
end
if response.success?
true
else
raise 'Ucloud上传失败'
end
end
# 读取文件
def get(path)
path.sub!(PATH_PREFIX, '')
response = conn.get(url(path))
if response.success?
return response
else
raise 'Ucloud Get File Fail'
end
end
# 删除文件
def delete(path)
path.sub!(PATH_PREFIX, '')
response = conn.delete(url(path)) do |req|
req.headers['Authorization'] = authorization(req.method, nil, path)
end
if response.success?
true
else
raise 'Ucloud Get File Fail'
end
end
def url(path)
if @ucloud_public_read
public_get_url(path)
else
private_get_url(path)
end
end
# 公开的访问地址
def public_get_url(path)
path.sub!(PATH_PREFIX, '')
[@ucloud_cdn_host, path].join('/')
end
# 私有空间访问地址
def private_get_url(path)
public_get_url(path) + privite_get_url_auth(path)
end
private
def conn
@conn ||= begin
Faraday.new(url: @ucloud_bucket_host) do |req|
req.request :url_encoded
req.adapter Faraday.default_adapter
end
end
end
# 私密查看url的认证信息
def privite_get_url_auth(path)
expired_ts = private_expire_ts
signed_str = signature(string_to_sign('GET', nil, path, expired_ts))
"?UCloudPublicKey=#{@ucloud_public_key}&Expires=#{expired_ts}&Signature=#{signed_str}"
end
def private_expire_ts
@ucloud_private_expire_seconds + Time.now.to_i
end
def authorization(http_method, content_type, path)
signed_str = signature(string_to_sign(http_method, content_type, path))
"UCloud " + @ucloud_public_key + ":" + signed_str
end
def signature(str)
Base64.strict_encode64(OpenSSL::HMAC.digest('sha1', @ucloud_private_key, str))
end
def string_to_sign(http_method, ori_content_type, path, expired_ts = nil)
http_verb = "#{http_method.upcase}\n"
content_md5 = "\n"
content_type = "#{ori_content_type}\n"
timestamp = "#{expired_ts}\n"
full_path = "/#{@ucloud_bucket}/#{path}"
http_verb + content_md5 + content_type + timestamp + full_path
end
end
end

144
lib/educoder/units.rb Normal file
View File

@@ -0,0 +1,144 @@
require 'fileutils'
module Educoder
module Utils
class << self
# Returns the relative root url of the application
def relative_url_root
ActionController::Base.respond_to?('relative_url_root') ?
ActionController::Base.relative_url_root.to_s :
ActionController::Base.config.relative_url_root.to_s
end
# Sets the relative root url of the application
def relative_url_root=(arg)
if ActionController::Base.respond_to?('relative_url_root=')
ActionController::Base.relative_url_root=arg
else
ActionController::Base.config.relative_url_root = arg
end
end
# Generates a n bytes random hex string
# Example:
# random_hex(4) # => "89b8c729"
def random_hex(n)
SecureRandom.hex(n)
end
def save_upload(upload, path)
directory = File.dirname(path)
unless File.exists?(directory)
FileUtils.mkdir_p directory
end
File.open(path, "wb") do |f|
if upload.respond_to?(:read)
buffer = ""
while (buffer = upload.read(8192))
f.write(buffer)
yield buffer if block_given?
end
else
f.write(upload)
yield upload if block_given?
end
end
end
def digest(diskfile)
md5 = Digest::MD5.new
File.open(diskfile, "rb") do |f|
buffer = ""
while (buffer = f.read(8192))
md5.update(buffer)
end
end
md5.hexdigest
end
end
module Shell
module_function
def shell_quote(str)
if Redmine::Platform.mswin?
'"' + str.gsub(/"/, '\\"') + '"'
else
"'" + str.gsub(/'/, "'\"'\"'") + "'"
end
end
def shell_quote_command(command)
if Redmine::Platform.mswin? && RUBY_PLATFORM == 'java'
command
else
shell_quote(command)
end
end
end
module DateCalculation
# Returns the number of working days between from and to
def working_days(from, to)
days = (to - from).to_i
if days > 0
weeks = days / 7
result = weeks * (7 - non_working_week_days.size)
days_left = days - weeks * 7
start_cwday = from.cwday
days_left.times do |i|
unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)
result += 1
end
end
result
else
0
end
end
# Adds working days to the given date
def add_working_days(date, working_days)
if working_days > 0
weeks = working_days / (7 - non_working_week_days.size)
result = weeks * 7
days_left = working_days - weeks * (7 - non_working_week_days.size)
cwday = date.cwday
while days_left > 0
cwday += 1
unless non_working_week_days.include?(((cwday - 1) % 7) + 1)
days_left -= 1
end
result += 1
end
next_working_date(date + result)
else
date
end
end
# Returns the date of the first day on or after the given date that is a working day
def next_working_date(date)
cwday = date.cwday
days = 0
while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)
days += 1
end
date + days
end
# Returns the index of non working week days (1=monday, 7=sunday)
def non_working_week_days
@non_working_week_days ||= begin
days = Setting.non_working_week_days
if days.is_a?(Array) && days.size < 7
days.map(&:to_i)
else
[]
end
end
end
end
end
end

View File

View File

View File

@@ -0,0 +1,51 @@
# 新版Git测试说明
统一:
参考实训http://47.96.87.25:48080/shixuns/ca9fvobr/repository
请求方式POST
参数{repo_path: "educoder/ca9fvobr.git"}
公共方法:
['add_repository', 'fork_repository', 'delete_repository', 'file_tree', 'update_file',
'file_content', 'commits']
1、仓库目录接口
测试方法模拟1000个用户同时去访问接口访问方式
http://121.199.19.206:9000/api/file_tree
参数:
{repo_path: "educoder/ca9fvobr.git", path: ''} // 如:{path: 'step1'}
2、创建版本库
访问地址http://121.199.19.206:9000/api/add_repository
参数:
{repo_path: 比如:"Hjqreturn/aaass1.git"}
3、fork版本库
http://121.199.19.206:9000/api/fork_repository
参数:
{repo_path: 'Hjqreturn/aaass1.git', fork_repository_path: 'educoder/ca9fvobr.git'}
说明fork_repository_path是新项目的repo_path, repo_path是源项目的
4、更新文件
测试方法:
1、更新同一个文件并发量可以不用很大可以用同一个用户并发10-100
2、更新不同的文件可以依据创建的版本库去更新
访问地址http://121.199.19.206:9000/api/update_file
参数:
{repo_path: "educoder/ca9fvobr.git",
file_path: 'step1/main.py',
message: 'commit by test',
content: 'afdjadsjfj1111',
author_name: 'guange',
author_email: '8863824@gmil.com'}
5、获取文件内容
访问地址http://121.199.19.206:9000/api/file_content
参数:
{repo_path: "educoder/ca9fvobr.git", path: 'step1/main.py',}
6、获取提交记录
访问地址http://121.199.19.206:9000/api/commits
参数:
{repo_path: 比如:"educoder/ca9fvobr.git"}

View File

@@ -0,0 +1,72 @@
mbtclufr
9op3hs4j
96ctv7yr
rtmzxfke
ofqxthrf
czu9w4gj
9fpzj6et
pwhc865b
maozpx4l
y5wh2ofx
b5rzhpf3
bs243nrl
47fn2yfb
kwotfxey
w5468sbp
fyekprio
q6ze5fih
b5hjq9zm
ky8pbqux
53phc7nq
b9j2yuix
9t3uphwk
iokm8ah2
qlsy6xb4
345bqhfi
v728fqia
4euftvf2
f23sef5m
nhqis8m9
qp72tb5x
gt3anszw
tng6heyf
nb9keawo
elgnbkp9
4neslomg
lh35s6ma
xmc4rpay
qrpaxi6b
9fla2zry
efuibzrm
fzp3iu4w
pligsyn8
glbksr29
kfm7ghyc
p6hk3svf
p539gjhm
am5o73er
4x3qwrbe
fqosyl8g
of5z3fci
tb7hw62n
ie6zxg7r
4q2bmy9h
fpm3u5yb
nikx3ojt
vt82s9bq
ma59fefo
lxa39tfq
4gnockxf
nxwg84ey
fmie8nzb
w5nsr24v
4hn3efwc
h9ljfbq7
nuv54t8b
2te9fmfq
vihnsayz
qhlyn82s
vw74kmfr
vcta36bz
henz425l
g529v38z

4
lib/gitlab-cli/Gemfile Normal file
View File

@@ -0,0 +1,4 @@
source 'http://gems.ruby-china.org/'
# Specify your gem's dependencies in gitlab.gemspec
gemspec

View File

@@ -0,0 +1,24 @@
Copyright (c) 2012-2014 Nihad Abbasov <mail@narkoz.me>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

121
lib/gitlab-cli/README.md Normal file
View File

@@ -0,0 +1,121 @@
# Gitlab
[![Build Status](https://travis-ci.org/NARKOZ/gitlab.png)](http://travis-ci.org/NARKOZ/gitlab)
[website](http://narkoz.github.io/gitlab) |
[documentation](http://rubydoc.info/gems/gitlab/frames)
Gitlab is a Ruby wrapper and CLI for the [GitLab API](https://github.com/gitlabhq/gitlabhq/tree/master/doc/api#gitlab-api).
## Installation
Install it from rubygems:
```sh
gem install gitlab
```
Or add to a Gemfile:
```ruby
gem 'gitlab'
# gem 'gitlab', :git => 'git://github.com/NARKOZ/gitlab.git'
```
## Usage
Configuration example:
```ruby
Gitlab.configure do |config|
config.endpoint = 'https://example.net/api/v3' # API endpoint URL, default: ENV['GITLAB_API_ENDPOINT']
config.private_token = 'qEsq1pt6HJPaNciie3MG' # user's private token, default: ENV['GITLAB_API_PRIVATE_TOKEN']
# Optional
# config.user_agent = 'Custom User Agent' # user agent, default: 'Gitlab Ruby Gem [version]'
# config.sudo = 'user' # username for sudo mode, default: nil
end
```
(Note: If you are using Gitlab.com's hosted service, your endpoint will be `https://gitlab.com/api/v3`)
Usage examples:
```ruby
# set an API endpoint
Gitlab.endpoint = 'http://example.net/api/v3'
# => "http://example.net/api/v3"
# set a user private token
Gitlab.private_token = 'qEsq1pt6HJPaNciie3MG'
# => "qEsq1pt6HJPaNciie3MG"
# list projects
Gitlab.projects(:per_page => 5)
# => [#<Gitlab::ObjectifiedHash:0x000000023326e0 @data={"id"=>1, "code"=>"brute", "name"=>"Brute", "description"=>nil, "path"=>"brute", "default_branch"=>nil, "owner"=>#<Gitlab::ObjectifiedHash:0x00000002331600 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:56Z"}>, #<Gitlab::ObjectifiedHash:0x000000023450d8 @data={"id"=>2, "code"=>"mozart", "name"=>"Mozart", "description"=>nil, "path"=>"mozart", "default_branch"=>nil, "owner"=>#<Gitlab::ObjectifiedHash:0x00000002344ca0 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:57Z"}>, #<Gitlab::ObjectifiedHash:0x00000002344958 @data={"id"=>3, "code"=>"gitlab", "name"=>"Gitlab", "description"=>nil, "path"=>"gitlab", "default_branch"=>nil, "owner"=>#<Gitlab::ObjectifiedHash:0x000000023447a0 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>, "private"=>true, "issues_enabled"=>true, "merge_requests_enabled"=>true, "wall_enabled"=>true, "wiki_enabled"=>true, "created_at"=>"2012-09-17T09:41:58Z"}>]
# initialize a new client
g = Gitlab.client(:endpoint => 'https://api.example.com', :private_token => 'qEsq1pt6HJPaNciie3MG')
# => #<Gitlab::Client:0x00000001e62408 @endpoint="https://api.example.com", @private_token="qEsq1pt6HJPaNciie3MG", @user_agent="Gitlab Ruby Gem 2.0.0">
# get a user
user = g.user
# => #<Gitlab::ObjectifiedHash:0x00000002217990 @data={"id"=>1, "email"=>"john@example.com", "name"=>"John Smith", "bio"=>nil, "skype"=>"", "linkedin"=>"", "twitter"=>"john", "dark_scheme"=>false, "theme_id"=>1, "blocked"=>false, "created_at"=>"2012-09-17T09:41:56Z"}>
# get a user's email
user.email
# => "john@example.com"
# set a sudo mode to perform API calls as another user
Gitlab.sudo = 'other_user'
# => "other_user"
# disable a sudo mode
Gitlab.sudo = nil
# => nil
```
For more information, refer to [documentation](http://rubydoc.info/gems/gitlab/frames).
## CLI
Usage examples:
```sh
# list users
gitlab users
# get current user
gitlab user
# get a user
gitlab user 2
# filter output
gitlab user --only=id,username
gitlab user --except=email,bio
```
## CLI Shell
Usage examples:
```sh
# start shell session
gitlab shell
# list available commands
gitlab> help
# list groups
gitlab> groups
# protect a branch
gitlab> protect_branch 1 master
```
For more information, refer to [website](http://narkoz.github.io/gitlab).
## License
Released under the BSD 2-clause license. See LICENSE.txt for details.

9
lib/gitlab-cli/Rakefile Normal file
View File

@@ -0,0 +1,9 @@
require "bundler/gem_tasks"
require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
spec.pattern = FileList['spec/**/*_spec.rb']
spec.rspec_opts = ['--color', '--format d']
end
task :default => :spec

7
lib/gitlab-cli/bin/gitlab Executable file
View File

@@ -0,0 +1,7 @@
#!/usr/bin/env ruby
$:.unshift File.expand_path('../../lib', __FILE__)
require 'gitlab/cli'
Gitlab::CLI.start(ARGV)

View File

@@ -0,0 +1,26 @@
# -*- encoding: utf-8 -*-
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'gitlab/version'
Gem::Specification.new do |gem|
gem.name = "gitlab"
gem.version = Gitlab::VERSION
gem.authors = ["Nihad Abbasov"]
gem.email = ["mail@narkoz.me"]
gem.description = %q{Ruby client and CLI for GitLab API}
gem.summary = %q{A Ruby wrapper and CLI for the GitLab API}
gem.homepage = "https://github.com/narkoz/gitlab"
gem.files = `git ls-files`.split($/)
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
gem.require_paths = ["lib"]
gem.add_runtime_dependency 'httparty'
gem.add_runtime_dependency 'terminal-table'
gem.add_development_dependency 'rake'
gem.add_development_dependency 'rspec'
gem.add_development_dependency 'webmock'
end

View File

@@ -0,0 +1,37 @@
require 'gitlab/version'
require 'gitlab/objectified_hash'
require 'gitlab/configuration'
require 'gitlab/error'
require 'gitlab/request'
require 'gitlab/api'
require 'gitlab/client'
module Gitlab
extend Configuration
# Alias for Gitlab::Client.new
#
# @return [Gitlab::Client]
def self.client(options={})
Gitlab::Client.new(options)
end
# Delegate to Gitlab::Client
def self.method_missing(method, *args, &block)
return super unless client.respond_to?(method)
client.send(method, *args, &block)
end
# Delegate to Gitlab::Client
def self.respond_to?(method)
return client.respond_to?(method) || super
end
# Returns an unsorted array of available client methods.
#
# @return [Array<Symbol>]
def self.actions
hidden = /endpoint|private_token|user_agent|sudo|get|post|put|\Adelete\z|validate|set_request_defaults/
(Gitlab::Client.instance_methods - Object.methods).reject {|e| e[hidden]}
end
end

View File

@@ -0,0 +1,17 @@
module Gitlab
# @private
class API < Request
# @private
attr_accessor(*Configuration::VALID_OPTIONS_KEYS)
# Creates a new API.
# @raise [Error:MissingCredentials]
def initialize(options={})
options = Gitlab.options.merge(options)
Configuration::VALID_OPTIONS_KEYS.each do |key|
send("#{key}=", options[key])
end
set_request_defaults @endpoint, @private_token, @sudo
end
end
end

View File

@@ -0,0 +1,47 @@
require 'gitlab'
require 'terminal-table/import'
require_relative 'cli_helpers'
require_relative 'shell'
class Gitlab::CLI
extend Helpers
def self.start(args)
command = args.shift.strip rescue 'help'
run(command, args)
end
def self.run(cmd, args=[])
case cmd
when 'help'
puts actions_table
when 'info'
endpoint = Gitlab.endpoint ? Gitlab.endpoint : 'not set'
private_token = Gitlab.private_token ? Gitlab.private_token : 'not set'
puts "Gitlab endpoint is #{endpoint}"
puts "Gitlab private token is #{private_token}"
puts "Ruby Version is #{RUBY_VERSION}"
puts "Gitlab Ruby Gem #{Gitlab::VERSION}"
when '-v', '--version'
puts "Gitlab Ruby Gem #{Gitlab::VERSION}"
when 'shell'
Gitlab::Shell.start
else
unless valid_command?(cmd)
puts "Unknown command. Run `gitlab help` for a list of available commands."
exit(1)
end
if args.any? && (args.last.start_with?('--only=') || args.last.start_with?('--except='))
command_args = args[0..-2]
else
command_args = args
end
confirm_command(cmd)
data = gitlab_helper(cmd, command_args) { exit(1) }
output_table(cmd, args, data)
end
end
end

View File

@@ -0,0 +1,175 @@
class Gitlab::CLI
# Defines methods related to CLI output and formatting.
module Helpers
extend self
# Returns filtered required fields.
#
# @return [Array]
def required_fields(args)
if args.any? && args.last.start_with?('--only=')
args.last.gsub('--only=', '').split(',')
else
[]
end
end
# Returns filtered excluded fields.
#
# @return [Array]
def excluded_fields(args)
if args.any? && args.last.start_with?('--except=')
args.last.gsub('--except=', '').split(',')
else
[]
end
end
# Confirms command is valid.
#
# @return [Boolean]
def valid_command?(cmd)
command = cmd.is_a?(Symbol) ? cmd : cmd.to_sym
Gitlab.actions.include?(command)
end
# Confirms command with a desctructive action.
#
# @return [String]
def confirm_command(cmd)
if cmd.start_with?('remove_') || cmd.start_with?('delete_')
puts "Are you sure? (y/n)"
if %w(y yes).include?($stdin.gets.to_s.strip.downcase)
puts 'Proceeding..'
else
puts 'Command aborted.'
exit(1)
end
end
end
# Table with available commands.
#
# @return [String]
def actions_table
client = Gitlab::Client.new(endpoint: '')
actions = Gitlab.actions
methods = []
actions.each do |action|
methods << {
name: action,
owner: client.method(action).owner.to_s.gsub('Gitlab::Client::', '')
}
end
owners = methods.map {|m| m[:owner]}.uniq.sort
methods_c = methods.group_by {|m| m[:owner]}
methods_c = methods_c.map {|_, v| [_, v.sort_by {|hv| hv[:name]}] }
methods_c = Hash[methods_c.sort_by(&:first).map {|k, v| [k, v]}]
max_column_length = methods_c.values.max_by(&:size).size
rows = max_column_length.times.map do |i|
methods_c.keys.map do |key|
methods_c[key][i] ? methods_c[key][i][:name] : ''
end
end
table do |t|
t.title = "Available commands (#{actions.size} total)"
t.headings = owners
rows.each do |row|
t.add_row row
end
end
end
# Decides which table to use.
#
# @return [String]
def output_table(cmd, args, data)
case data
when Gitlab::ObjectifiedHash
puts single_record_table(data, cmd, args)
when Array
puts multiple_record_table(data, cmd, args)
else
puts data.inspect
end
end
# Table for a single record.
#
# @return [String]
def single_record_table(data, cmd, args)
hash = data.to_h
keys = hash.keys.sort {|x, y| x.to_s <=> y.to_s }
keys = keys & required_fields(args) if required_fields(args).any?
keys = keys - excluded_fields(args)
table do |t|
t.title = "Gitlab.#{cmd} #{args.join(', ')}"
keys.each_with_index do |key, index|
case value = hash[key]
when Hash
value = 'Hash'
when nil
value = 'null'
end
t.add_row [key, value]
t.add_separator unless keys.size - 1 == index
end
end
end
# Table for multiple records.
#
# @return [String]
def multiple_record_table(data, cmd, args)
return 'No data' if data.empty?
arr = data.map(&:to_h)
keys = arr.first.keys.sort {|x, y| x.to_s <=> y.to_s }
keys = keys & required_fields(args) if required_fields(args).any?
keys = keys - excluded_fields(args)
table do |t|
t.title = "Gitlab.#{cmd} #{args.join(', ')}"
t.headings = keys
arr.each_with_index do |hash, index|
values = []
keys.each do |key|
case value = hash[key]
when Hash
value = 'Hash'
when nil
value = 'null'
end
values << value
end
t.add_row values
t.add_separator unless arr.size - 1 == index
end
end
end
# Helper function to call Gitlab commands with args.
def gitlab_helper(cmd, args=[])
begin
data = args.any? ? Gitlab.send(cmd, *args) : Gitlab.send(cmd)
rescue => e
puts e.message
yield if block_given?
end
data
end
end
end

View File

@@ -0,0 +1,18 @@
module Gitlab
# Wrapper for the Gitlab REST API.
class Client < API
Dir[File.expand_path('../client/*.rb', __FILE__)].each {|f| require f}
include Branches
include Groups
include Issues
include MergeRequests
include Milestones
include Notes
include Projects
include Repositories
include Snippets
include SystemHooks
include Users
end
end

View File

@@ -0,0 +1,79 @@
class Gitlab::Client
# Defines methods related to repositories.
module Branches
# Gets a list of project repositiory branches.
#
# @example
# Gitlab.branches(42)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def branches(project, options={})
get("/projects/#{project}/repository/branches", :query => options)
end
alias_method :repo_branches, :branches
# Gets information about a repository branch.
#
# @example
# Gitlab.branch(3, 'api')
# Gitlab.repo_branch(5, 'master')
#
# @param [Integer] project The ID of a project.
# @param [String] branch The name of the branch.
# @return [Gitlab::ObjectifiedHash]
def branch(project, branch)
get("/projects/#{project}/repository/branches/#{branch}")
end
alias_method :repo_branch, :branch
# Protects a repository branch.
#
# @example
# Gitlab.protect_branch(3, 'api')
# Gitlab.repo_protect_branch(5, 'master')
#
# @param [Integer] project The ID of a project.
# @param [String] branch The name of the branch.
# @return [Gitlab::ObjectifiedHash]
def protect_branch(project, branch)
put("/projects/#{project}/repository/branches/#{branch}/protect")
end
alias_method :repo_protect_branch, :protect_branch
# Unprotects a repository branch.
#
# @example
# Gitlab.unprotect_branch(3, 'api')
# Gitlab.repo_unprotect_branch(5, 'master')
#
# @param [Integer] project The ID of a project.
# @param [String] branch The name of the branch.
# @return [Gitlab::ObjectifiedHash]
def unprotect_branch(project, branch)
put("/projects/#{project}/repository/branches/#{branch}/unprotect")
end
alias_method :repo_unprotect_branch, :unprotect_branch
# Creates a repository branch. Requires Gitlab >= 6.8.x
#
# @example
# Gitlab.create_branch(3, 'api')
# Gitlab.repo_create_branch(5, 'master')
#
# @param [Integer] project The ID of a project.
# @param [String] branch The name of the new branch.
# @param [String] ref Create branch from commit sha or existing branch
# @return [Gitlab::ObjectifiedHash]
def create_branch(project, branch, ref)
post("/projects/#{project}/repository/branches",:body => {:branch_name => branch, :ref => ref})
end
alias_method :repo_create_branch, :create_branch
end
end

View File

@@ -0,0 +1,88 @@
class Gitlab::Client
# Defines methods related to groups.
module Groups
# Gets a list of groups.
#
# @example
# Gitlab.groups
# Gitlab.groups(:per_page => 40)
#
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def groups(options={})
get("/groups", :query => options)
end
# Gets a single group.
#
# @example
# Gitlab.group(42)
#
# @param [Integer] id The ID of a group.
# @return [Gitlab::ObjectifiedHash]
def group(id)
get("/groups/#{id}")
end
# Creates a new group.
#
# @param [String] name The name of a group.
# @param [String] path The path of a group.
# @return [Gitlab::ObjectifiedHash] Information about created group.
def create_group(name, path)
body = {:name => name, :path => path}
post("/groups", :body => body)
end
# Get a list of group members.
#
# @example
# Gitlab.group_members(1)
# Gitlab.group_members(1, :per_page => 40)
#
# @param [Integer] id The ID of a group.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def group_members(id, options={})
get("/groups/#{id}/members", :query => options)
end
# Adds a user to group.
#
# @example
# Gitlab.add_group_member(1, 2, 40)
#
# @param [Integer] team_id The group id to add a member to.
# @param [Integer] user_id The user id of the user to add to the team.
# @param [Integer] access_level Project access level.
# @return [Gitlab::ObjectifiedHash] Information about added team member.
def add_group_member(team_id, user_id, access_level)
post("/groups/#{team_id}/members", :body => {:user_id => user_id, :access_level => access_level})
end
# Removes user from user group.
#
# @example
# Gitlab.remove_group_member(1, 2)
#
# @param [Integer] team_id The group ID.
# @param [Integer] user_id The ID of a user.
# @return [Gitlab::ObjectifiedHash] Information about removed team member.
def remove_group_member(team_id, user_id)
delete("/groups/#{team_id}/members/#{user_id}")
end
# Transfers a project to a group
#
# @param [Integer] id The ID of a group.
# @param [Integer] project_id The ID of a project.
def transfer_project_to_group(id, project_id)
body = {:id => id, :project_id => project_id}
post("/groups/#{id}/projects/#{project_id}", :body => body)
end
end
end

View File

@@ -0,0 +1,92 @@
class Gitlab::Client
# Defines methods related to issues.
module Issues
# Gets a list of user's issues.
# Will return a list of project's issues if project ID passed.
#
# @example
# Gitlab.issues
# Gitlab.issues(5)
# Gitlab.issues(:per_page => 40)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def issues(project=nil, options={})
if project.to_i.zero?
get("/issues", :query => options)
else
get("/projects/#{project}/issues", :query => options)
end
end
# Gets a single issue.
#
# @example
# Gitlab.issue(5, 42)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of an issue.
# @return [Gitlab::ObjectifiedHash]
def issue(project, id)
get("/projects/#{project}/issues/#{id}")
end
# Creates a new issue.
#
# @param [Integer] project The ID of a project.
# @param [String] title The title of an issue.
# @param [Hash] options A customizable set of options.
# @option options [String] :description The description of an issue.
# @option options [Integer] :assignee_id The ID of a user to assign issue.
# @option options [Integer] :milestone_id The ID of a milestone to assign issue.
# @option options [String] :labels Comma-separated label names for an issue.
# @return [Gitlab::ObjectifiedHash] Information about created issue.
def create_issue(project, title, options={})
body = {:title => title}.merge(options)
post("/projects/#{project}/issues", :body => body)
end
# Updates an issue.
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of an issue.
# @param [Hash] options A customizable set of options.
# @option options [String] :title The title of an issue.
# @option options [String] :description The description of an issue.
# @option options [Integer] :assignee_id The ID of a user to assign issue.
# @option options [Integer] :milestone_id The ID of a milestone to assign issue.
# @option options [String] :labels Comma-separated label names for an issue.
# @option options [String] :state_event The state event of an issue ('close' or 'reopen').
# @return [Gitlab::ObjectifiedHash] Information about updated issue.
def edit_issue(project, id, options={})
put("/projects/#{project}/issues/#{id}", :body => options)
end
# Closes an issue.
#
# @example
# Gitlab.close_issue(3, 42)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of an issue.
# @return [Gitlab::ObjectifiedHash] Information about closed issue.
def close_issue(project, id)
put("/projects/#{project}/issues/#{id}", :body => {:state_event => 'close'})
end
# Reopens an issue.
#
# @example
# Gitlab.reopen_issue(3, 42)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of an issue.
# @return [Gitlab::ObjectifiedHash] Information about reopened issue.
def reopen_issue(project, id)
put("/projects/#{project}/issues/#{id}", :body => {:state_event => 'reopen'})
end
end
end

View File

@@ -0,0 +1,135 @@
class Gitlab::Client
# Defines methods related to merge requests.
module MergeRequests
# Gets a list of project merge requests.
#
# @example
# Gitlab.merge_requests(5)
# Gitlab.merge_requests(:per_page => 40)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def merge_requests(project, options={})
get("/projects/#{project}/merge_requests", :query => options)
end
# Gets a single merge request.
#
# @example
# Gitlab.merge_request(5, 36)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a merge request.
# @return <Gitlab::ObjectifiedHash]
def merge_request(project, id)
get("/projects/#{project}/merge_request/#{id}")
end
# Creates a merge request.
#
# @example
# Gitlab.create_merge_request(5, 'New merge request',
# :source_branch => 'source_branch', :target_branch => 'target_branch')
# Gitlab.create_merge_request(5, 'New merge request',
# :source_branch => 'source_branch', :target_branch => 'target_branch', :assignee_id => 42)
#
# @param [Integer] project The ID of a project.
# @param [String] title The title of a merge request.
# @param [Hash] options A customizable set of options.
# @option options [String] :source_branch (required) The source branch name.
# @option options [String] :target_branch (required) The target branch name.
# @option options [Integer] :assignee_id (optional) The ID of a user to assign merge request.
# @return [Gitlab::ObjectifiedHash] Information about created merge request.
def create_merge_request(project, title, gid, options={})
check_attributes!(options, [:source_branch, :target_branch])
body = {:title => title}.merge(options)
post("/projects/#{project}/merge_requests?user_id=#{gid}", :body => body)
end
# Updates a merge request.
#
# @example
# Gitlab.update_merge_request(5, 42, :title => 'New title')
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a merge request.
# @param [Hash] options A customizable set of options.
# @option options [String] :title The title of a merge request.
# @option options [String] :source_branch The source branch name.
# @option options [String] :target_branch The target branch name.
# @option options [Integer] :assignee_id The ID of a user to assign merge request.
# @option options [String] :state_event New state (close|reopen|merge).
# @return [Gitlab::ObjectifiedHash] Information about updated merge request.
def update_merge_request(project, id, gid, options={})
put("/projects/#{project}/merge_request/#{id}?user_id=#{gid}", :body => options)
end
# Adds a comment to a merge request.
#
# @example
# Gitlab.create_merge_request_comment(5, 1, "Awesome merge!")
# Gitlab.create_merge_request_comment('gitlab', 1, "Awesome merge!")
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a merge request.
# @param [String] note The content of a comment.
# @return [Gitlab::ObjectifiedHash] Information about created merge request comment.
def create_merge_request_comment(project, id, note, gid)
post("/projects/#{project}/merge_request/#{id}/comments?user_id=#{gid}", :body => {:note => note})
end
# Get a list of merge request commits.
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
def merge_request_commits(project, id)
get("/projects/#{project}/merge_request/#{id}/commits")
end
# Shows information about the merge request including its files and changes. With GitLab 8.2 the return fields upvotes and downvotes are deprecated and always return 0.
# Parameters:
# id (required) - The ID of a project
# merge_request_id (required) - The ID of MR
def merge_request_changes(project, id)
get("/projects/#{project}/merge_request/#{id}/changes")
end
# Gets the comments on a merge request.
#
# @example
# Gitlab.merge_request_comments(5, 1)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a merge request.
# @return [Gitlab::ObjectifiedHash] The merge request's comments.
def merge_request_comments(project, id)
get("/projects/#{project}/merge_request/#{id}/comments")
end
# Accept a merge request.
#
# @example
# Gitlab.accept_pull_rquest(5, 1)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a merge request.
# @return [Gitlab::ObjectifiedHash]
def accept_merge_rquest(project, id, gid)
put("/projects/#{project}/merge_request/#{id}/merge?user_id=#{gid}")
end
private
def check_attributes!(options, attrs)
attrs.each do |attr|
unless options.has_key?(attr) || options.has_key?(attr.to_s)
raise Gitlab::Error::MissingAttributes.new("Missing '#{attr}' parameter")
end
end
end
end
end

View File

@@ -0,0 +1,57 @@
class Gitlab::Client
# Defines methods related to milestones.
module Milestones
# Gets a list of project's milestones.
#
# @example
# Gitlab.milestones(5)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def milestones(project, options={})
get("/projects/#{project}/milestones", :query => options)
end
# Gets a single milestone.
#
# @example
# Gitlab.milestone(5, 36)
#
# @param [Integer, String] project The ID of a project.
# @param [Integer] id The ID of a milestone.
# @return [Gitlab::ObjectifiedHash]
def milestone(project, id)
get("/projects/#{project}/milestones/#{id}")
end
# Creates a new milestone.
#
# @param [Integer] project The ID of a project.
# @param [String] title The title of a milestone.
# @param [Hash] options A customizable set of options.
# @option options [String] :description The description of a milestone.
# @option options [String] :due_date The due date of a milestone.
# @return [Gitlab::ObjectifiedHash] Information about created milestone.
def create_milestone(project, title, options={})
body = {:title => title}.merge(options)
post("/projects/#{project}/milestones", :body => body)
end
# Updates a milestone.
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a milestone.
# @param [Hash] options A customizable set of options.
# @option options [String] :title The title of a milestone.
# @option options [String] :description The description of a milestone.
# @option options [String] :due_date The due date of a milestone.
# @option options [String] :state_event The state of a milestone ('close' or 'activate').
# @return [Gitlab::ObjectifiedHash] Information about updated milestone.
def edit_milestone(project, id, options={})
put("/projects/#{project}/milestones/#{id}", :body => options)
end
end
end

View File

@@ -0,0 +1,106 @@
class Gitlab::Client
# Defines methods related to notes.
module Notes
# Gets a list of projects notes.
#
# @example
# Gitlab.notes(5)
#
# @param [Integer] project The ID of a project.
# @return [Array<Gitlab::ObjectifiedHash>]
def notes(project)
get("/projects/#{project}/notes")
end
# Gets a list of notes for a issue.
#
# @example
# Gitlab.issue_notes(5, 10)
#
# @param [Integer] project The ID of a project.
# @param [Integer] issue The ID of an issue.
# @return [Array<Gitlab::ObjectifiedHash>]
def issue_notes(project, issue)
get("/projects/#{project}/issues/#{issue}/notes")
end
# Gets a list of notes for a snippet.
#
# @example
# Gitlab.snippet_notes(5, 1)
#
# @param [Integer] project The ID of a project.
# @param [Integer] snippet The ID of a snippet.
# @return [Array<Gitlab::ObjectifiedHash>]
def snippet_notes(project, snippet)
get("/projects/#{project}/snippets/#{snippet}/notes")
end
# Gets a single wall note.
#
# @example
# Gitlab.note(5, 15)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a note.
# @return [Gitlab::ObjectifiedHash]
def note(project, id)
get("/projects/#{project}/notes/#{id}")
end
# Gets a single issue note.
#
# @example
# Gitlab.issue_note(5, 10, 1)
#
# @param [Integer] project The ID of a project.
# @param [Integer] issue The ID of an issue.
# @param [Integer] id The ID of a note.
# @return [Gitlab::ObjectifiedHash]
def issue_note(project, issue, id)
get("/projects/#{project}/issues/#{issue}/notes/#{id}")
end
# Gets a single snippet note.
#
# @example
# Gitlab.snippet_note(5, 11, 3)
#
# @param [Integer] project The ID of a project.
# @param [Integer] snippet The ID of a snippet.
# @param [Integer] id The ID of an note.
# @return [Gitlab::ObjectifiedHash]
def snippet_note(project, snippet, id)
get("/projects/#{project}/snippets/#{snippet}/notes/#{id}")
end
# Creates a new wall note.
#
# @param [Integer] project The ID of a project.
# @param [String] body The body of a note.
# @return [Gitlab::ObjectifiedHash] Information about created note.
def create_note(project, body)
post("/projects/#{project}/notes", :body => {:body => body})
end
# Creates a new issue note.
#
# @param [Integer] project The ID of a project.
# @param [Integer] issue The ID of an issue.
# @param [String] body The body of a note.
# @return [Gitlab::ObjectifiedHash] Information about created note.
def create_issue_note(project, issue, body)
post("/projects/#{project}/issues/#{issue}/notes", :body => {:body => body})
end
# Creates a new snippet note.
#
# @param [Integer] project The ID of a project.
# @param [Integer] snippet The ID of a snippet.
# @param [String] body The body of a note.
# @return [Gitlab::ObjectifiedHash] Information about created note.
def create_snippet_note(project, snippet, body)
post("/projects/#{project}/snippets/#{snippet}/notes", :body => {:body => body})
end
end
end

View File

@@ -0,0 +1,328 @@
class Gitlab::Client
# Defines methods related to projects.
module Projects
# Gets a list of projects owned by the authenticated user.
#
# @example
# Gitlab.projects
#
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @option options [String] :scope Scope of projects. 'owned' for list of projects owned by the authenticated user, 'all' to get all projects (admin only)
# @return [Array<Gitlab::ObjectifiedHash>]
def projects(options={})
if (options[:scope])
get("/projects/#{options[:scope]}", :query => options)
else
get("/projects", :query => options)
end
end
def current_user_project(user_id, project_name)
get("/projects/current_user_projects?user_id=#{user_id}&project_name=#{project_name}")
end
# Gets information about a project.
#
# @example
# Gitlab.project(3)
# Gitlab.project('gitlab')
#
# @param [Integer, String] id The ID or name of a project.
# @return [Gitlab::ObjectifiedHash]
def project(id)
get("/projects/#{id}")
end
# Gets a list of project events.
#
# @example
# Gitlab.project_events(42)
# Gitlab.project_events('gitlab')
#
# @param [Integer, String] project The ID or name of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def project_events(project, options={})
get("/projects/#{project}/events", :query => options)
end
# Creates a new project.
#
# @example
# Gitlab.create_project('gitlab')
# Gitlab.create_project('viking', :description => 'Awesome project')
# Gitlab.create_project('Red', :wall_enabled => false)
#
# @param [String] name The name of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :description The description of a project.
# @option options [String] :default_branch The default branch of a project.
# @option options [String] :group_id The group in which to create a project.
# @option options [String] :namespace_id The namespace in which to create a project.
# @option options [Boolean] :wiki_enabled The wiki integration for a project (0 = false, 1 = true).
# @option options [Boolean] :wall_enabled The wall functionality for a project (0 = false, 1 = true).
# @option options [Boolean] :issues_enabled The issues integration for a project (0 = false, 1 = true).
# @option options [Boolean] :snippets_enabled The snippets integration for a project (0 = false, 1 = true).
# @option options [Boolean] :merge_requests_enabled The merge requests functionality for a project (0 = false, 1 = true).
# @option options [Boolean] :public The setting for making a project public (0 = false, 1 = true).
# @option options [Integer] :user_id The user/owner id of a project.
# @return [Gitlab::ObjectifiedHash] Information about created project.
def create_project(name, options={})
url = options[:user_id] ? "/projects/user/#{options[:user_id]}" : "/projects"
post(url, :body => {:name => name}.merge(options))
end
# Updates a project team member to a specified access level.
# id (required) - The ID of a project
# name (optional) - project name
# path (optional) - repository name for project
# description (optional) - short project description
# default_branch (optional)
# issues_enabled (optional)
# merge_requests_enabled (optional)
# wiki_enabled (optional)
# snippets_enabled (optional)
# public (optional) - if true same as setting visibility_level = 20
# visibility_level (optional)
def edit_project(id, name, path)
put("/projects/#{id}", :body => {:name => name, :path => path})
end
# Deletes a project.
#
# @example
# Gitlab.delete_project(4)
#
# @param [Integer, String] id The ID or name of a project.
# @return [Gitlab::ObjectifiedHash] Information about deleted project.
def delete_project(id)
delete("/projects/#{id}")
end
# Gets a list of project team members.
#
# @example
# Gitlab.team_members(42)
# Gitlab.team_members('gitlab')
#
# @param [Integer, String] project The ID or name of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :query The search query.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def team_members(project, options={})
get("/projects/#{project}/members", :query => options)
end
# Gets a project team member.
#
# @example
# Gitlab.team_member('gitlab', 2)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of a project team member.
# @return [Gitlab::ObjectifiedHash]
def team_member(project, id)
get("/projects/#{project}/members/#{id}")
end
# Adds a user to project team.
#
# @example
# Gitlab.add_team_member('gitlab', 2, 40)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of a user.
# @param [Integer] access_level The access level to project.
# @param [Hash] options A customizable set of options.
# @return [Gitlab::ObjectifiedHash] Information about added team member.
def add_team_member(project, id, access_level)
post("/projects/#{project}/members", :body => {:user_id => id, :access_level => access_level})
end
# Updates a team member's project access level.
#
# @example
# Gitlab.edit_team_member('gitlab', 3, 20)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of a user.
# @param [Integer] access_level The access level to project.
# @param [Hash] options A customizable set of options.
# @return [Array<Gitlab::ObjectifiedHash>] Information about updated team member.
def edit_team_member(project, id, access_level)
put("/projects/#{project}/members/#{id}", :body => {:access_level => access_level})
end
# Removes a user from project team.
#
# @example
# Gitlab.remove_team_member('gitlab', 2)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of a user.
# @param [Hash] options A customizable set of options.
# @return [Gitlab::ObjectifiedHash] Information about removed team member.
def remove_team_member(project, id)
delete("/projects/#{project}/members/#{id}")
end
# Gets a list of project hooks.
#
# @example
# Gitlab.project_hooks(42)
# Gitlab.project_hooks('gitlab')
#
# @param [Integer, String] project The ID or name of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def project_hooks(project, options={})
get("/projects/#{project}/hooks", :query => options)
end
# Gets a project hook.
#
# @example
# Gitlab.project_hook(42, 5)
# Gitlab.project_hook('gitlab', 5)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of a hook.
# @return [Gitlab::ObjectifiedHash]
def project_hook(project, id)
get("/projects/#{project}/hooks/#{id}")
end
# Adds a new hook to the project.
#
# @example
# Gitlab.add_project_hook(42, 'https://api.example.net/v1/webhooks/ci')
#
# @param [Integer, String] project The ID or name of a project.
# @param [String] url The hook URL.
# @param [Hash] options Events list (`{push_events: true, merge_requests_events: false}`).
# @return [Gitlab::ObjectifiedHash] Information about added hook.
def add_project_hook(project, url, options = {})
available_events = [:push_events, :merge_requests_events, :issues_events]
passed_events = available_events.select { |event| options[event] }
events = Hash[passed_events.map { |event| [event, options[event]] }]
post("/projects/#{project}/hooks", :body => {:url => url}.merge(events))
end
# Updates a project hook URL.
#
# @example
# Gitlab.edit_project_hook(42, 1, 'https://api.example.net/v1/webhooks/ci')
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of the hook.
# @param [String] url The hook URL.
# @return [Gitlab::ObjectifiedHash] Information about updated hook.
def edit_project_hook(project, id, url)
put("/projects/#{project}/hooks/#{id}", :body => {:url => url})
end
# Deletes a hook from project.
#
# @example
# Gitlab.delete_project_hook('gitlab', 4)
#
# @param [Integer, String] project The ID or name of a project.
# @param [String] id The ID of the hook.
# @return [Gitlab::ObjectifiedHash] Information about deleted hook.
def delete_project_hook(project, id)
delete("/projects/#{project}/hooks/#{id}")
end
# Forks a project into the user namespace of the authenticated user.
# @param [Integer] - The ID of the project to be forked
def fork(gpid, gid)
post ("/projects/fork/#{gpid}?user_id=#{gid}")
# post("/projects/fork/#{id}")
end
# Mark this project as forked from the other
#
# @example
# Gitlab.make_forked(42, 24)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] id The ID of the project it is forked from.
# @return [Gitlab::ObjectifiedHash] Information about the forked project.
def make_forked_from(project, id)
post("/projects/#{project}/fork/#{id}")
end
# Remove a forked_from relationship for a project.
#
# @example
# Gitlab.remove_forked(42)
#
# @param [Integer, String] project The ID or name of a project.
# @param [Integer] project The ID of the project it is forked from
# @return [Gitlab::ObjectifiedHash] Information about the forked project.
def remove_forked(project)
delete("/projects/#{project}/fork")
end
# Gets a project deploy keys.
#
# @example
# Gitlab.deploy_keys(42)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def deploy_keys(project, options={})
get("/projects/#{project}/keys", :query => options)
end
# Gets a single project deploy key.
#
# @example
# Gitlab.deploy_key(42, 1)
#
# @param [Integer, String] project The ID of a project.
# @param [Integer] id The ID of a deploy key.
# @return [Gitlab::ObjectifiedHash]
def deploy_key(project, id)
get("/projects/#{project}/keys/#{id}")
end
# Creates a new deploy key.
#
# @example
# Gitlab.create_deploy_key(42, 'My Key', 'Key contents')
#
# @param [Integer] project The ID of a project.
# @param [String] title The title of a deploy key.
# @param [String] key The content of a deploy key.
# @return [Gitlab::ObjectifiedHash] Information about created deploy key.
def create_deploy_key(project, title, key)
post("/projects/#{project}/keys", body: {title: title, key: key})
end
# Deletes a deploy key from project.
#
# @example
# Gitlab.delete_deploy_key(42, 1)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a deploy key.
# @return [Gitlab::ObjectifiedHash] Information about deleted deploy key.
def delete_deploy_key(project, id)
delete("/projects/#{project}/keys/#{id}")
end
end
end

View File

@@ -0,0 +1,213 @@
class Gitlab::Client
# Defines methods related to repositories.
module Repositories
def trees(project, options={})
get "/projects/#{project}/repository/tree", query: options
end
alias_method :repo_trees, :trees
def files(project, file_path, ref)
get "/projects/#{project}/repository/files", query: {file_path: file_path, ref: ref}
end
alias_method :repo_files, :files
def file_blob(project, options={})
get("/projects/#{project}/repository/blobs", query: options)
end
# Gets a list of project repository tags.
#
# @example
# Gitlab.tags(42)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def tags(project, options={})
get("/projects/#{project}/repository/tags", :query => options)
end
alias_method :repo_tags, :tags
# Creates a new project repository tag.
#
# @example
# Gitlab.create_tag(42,'new_tag','master')
#
# @param [Integer] project The ID of a project.
# @param [String] tag_name The name of the new tag.
# @param [String] ref The ref (commit sha, branch name, or another tag) the tag will point to.
# @return [Gitlab::ObjectifiedHash]
def create_tag(project, tag_name, ref)
post("/projects/#{project}/repository/tags", body: {tag_name: tag_name, ref: ref})
end
alias_method :repo_create_tag, :create_tag
# Gets a list of project commits.
#
# @example
# Gitlab.commits('viking')
# Gitlab.repo_commits('gitlab', :ref_name => 'api')
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :ref_name The branch or tag name of a project repository.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @option options [String] :search The obj of results's search value.
# @return [Array<Gitlab::ObjectifiedHash>]
def commits(project, options={})
get("/projects/#{project}/repository/commits", :query => options)
end
alias_method :repo_commits, :commits
# Gets a list of project commits.
#
# @example
# Gitlab.commits('viking')
# Gitlab.repo_commits('gitlab', :ref_name => 'api')
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :ref_name The branch or tag name of a project repository.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def commits_total_count(project, options={})
get("/projects/#{project}/repository/commits_total_count", :query => options)
end
alias_method :repo_commits, :commits_total_count
# Gets total project commits.
#
# @example
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :rev The branch or tag name of a project repository.
# @return [Hash<Gitlab::ObjectifiedHash>]
def user_static(project, options={})
get("/projects/#{project}/repository/user_static", :query => options)
end
def get_branch_commit_id(project, git_tree, ref_name)
get("/projects/#{project}/repository/get_branch_commit_id?git_tree=#{git_tree}&ref_name=#{ref_name}")
end
# Gets a specific commit identified by the commit hash or name of a branch or tag.
#
# @example
# Gitlab.commit(42, '6104942438c14ec7bd21c6cd5bd995272b3faff6')
# Gitlab.repo_commit(3, 'ed899a2f4b50b4370feeea94676502b42383c746')
#
# @param [Integer] project The ID of a project.
# @param [String] sha The commit hash or name of a repository branch or tag
# @return [Gitlab::ObjectifiedHash]
def commit(project, sha)
get("/projects/#{project}/repository/commits/#{sha}")
end
alias_method :repo_commit, :commit
# Gets a statics of project repository.
#
# @example
# Gitlab.commits('viking')
# Gitlab.repo_commits('gitlab', :ref_name => 'api')
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :ref_name The branch or tag name of a project repository.
# @option options [String] :creator The user name of a project repository.
# @option options [Integer] :period Statistics over time. 1:total 2one month 3one week
# @return [Array<Gitlab::ObjectifiedHash>]
def rep_stats(project, options={})
get("/projects/#{project}/repository/rep_stats", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
def rep_stats_week(project, options={})
get("/projects/#{project}/repository/rep_stats_week", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
def rep_stats_month(project, options={})
get("/projects/#{project}/repository/rep_stats_month", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
def rep_user_stats(project, options={})
get("/projects/#{project}/repository/rep_user_stats", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
# static all users
def admin_rep_stats_week(project, options={})
get("/projects/#{project}/repository/admin_rep_stats_week", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
def admin_rep_stats_month(project, options={})
get("/projects/#{project}/repository/admin_rep_stats_month", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
def admin_rep_stats_all(project, options={})
get("/projects/#{project}/repository/admin_rep_stats_all", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
# Gets a tree activities of project repository.
#
# @example
# Gitlab.commits('viking')
# Gitlab.repo_commits('gitlab', :ref_name => 'api')
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :ref_name The branch or tag name of a project repository.
# @option options [String] :creator The user name of a project repository.
# @option options [Integer] :period Statistics over time. 1:total 2one month 3one week
# @return [Array<Gitlab::ObjectifiedHash>]
def rep_last_changes(project, options={})
get("/projects/#{project}/repository/rep_last_changes", :query => options)
end
alias_method :repo_rep_stats, :rep_stats
# Get the diff of a commit in a project.
#
# @example
# Gitlab.commit_diff(42, '6104942438c14ec7bd21c6cd5bd995272b3faff6')
# Gitlab.repo_commit_diff(3, 'ed899a2f4b50b4370feeea94676502b42383c746')
#
# @param [Integer] project The ID of a project.
# @param [String] sha The name of a repository branch or tag or if not given the default branch.
# @return [Gitlab::ObjectifiedHash]
def commit_diff(project, sha)
get("/projects/#{project}/repository/commits/#{sha}/diff")
end
alias_method :repo_commit_diff, :commit_diff
# Get the commits count of each contributor in a project
# @param [Integer] project the ID fo a project.
# @return [Gitlab::ObjectifiedHash]
def contributors(project)
get("/projects/#{project}/repository/contributors")
end
# Get an archive of the repository
# @param [Integer] project the ID fo a project.
# sha (optional) - The commit SHA to download defaults to the tip of the default branch
# @return [Gitlab::ObjectifiedHash]
def project_archive(project, sha)
get("/projects/#{project}/repository/archive?sha=#{sha}")
end
# update file
def edit_file(project, username, options={})
put("/projects/#{project}/repository/files?username=#{username}", :body => options)
end
alias_method :repo_project_archive, :project_archive
end
end

View File

@@ -0,0 +1,86 @@
class Gitlab::Client
# Defines methods related to snippets.
module Snippets
# Gets a list of project's snippets.
#
# @example
# Gitlab.snippets(42)
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Gitlab::ObjectifiedHash]
def snippets(project, options={})
get("/projects/#{project}/snippets", :query => options)
end
# Gets information about a snippet.
#
# @example
# Gitlab.snippet(2, 14)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a snippet.
# @return [Gitlab::ObjectifiedHash]
def snippet(project, id)
get("/projects/#{project}/snippets/#{id}")
end
# Creates a new snippet.
#
# @example
# Gitlab.create_snippet(42, {:title => 'REST', :file_name => 'api.rb', :code => 'some code'})
#
# @param [Integer] project The ID of a project.
# @param [Hash] options A customizable set of options.
# @option options [String] :title (required) The title of a snippet.
# @option options [String] :file_name (required) The name of a snippet file.
# @option options [String] :code (required) The content of a snippet.
# @option options [String] :lifetime (optional) The expiration date of a snippet.
# @return [Gitlab::ObjectifiedHash] Information about created snippet.
def create_snippet(project, options={})
check_attributes!(options, [:title, :file_name, :code])
post("/projects/#{project}/snippets", :body => options)
end
# Updates a snippet.
#
# @example
# Gitlab.edit_snippet(42, 34, :file_name => 'README.txt')
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a snippet.
# @param [Hash] options A customizable set of options.
# @option options [String] :title The title of a snippet.
# @option options [String] :file_name The name of a snippet file.
# @option options [String] :code The content of a snippet.
# @option options [String] :lifetime The expiration date of a snippet.
# @return [Gitlab::ObjectifiedHash] Information about updated snippet.
def edit_snippet(project, id, options={})
put("/projects/#{project}/snippets/#{id}", :body => options)
end
# Deletes a snippet.
#
# @example
# Gitlab.delete_snippet(2, 14)
#
# @param [Integer] project The ID of a project.
# @param [Integer] id The ID of a snippet.
# @return [Gitlab::ObjectifiedHash] Information about deleted snippet.
def delete_snippet(project, id)
delete("/projects/#{project}/snippets/#{id}")
end
private
def check_attributes!(options, attrs)
attrs.each do |attr|
unless options.has_key?(attr) || options.has_key?(attr.to_s)
raise Gitlab::Error::MissingAttributes.new("Missing '#{attr}' parameter")
end
end
end
end
end

View File

@@ -0,0 +1,58 @@
class Gitlab::Client
# Defines methods related to system hooks.
module SystemHooks
# Gets a list of system hooks.
#
# @example
# Gitlab.hooks
# Gitlab.system_hooks
#
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def hooks(options={})
get("/hooks", query: options)
end
alias_method :system_hooks, :hooks
# Adds a new system hook.
#
# @example
# Gitlab.add_hook('http://example.com/hook')
# Gitlab.add_system_hook('https://api.example.net/v1/hook')
#
# @param [String] url The hook URL.
# @return [Gitlab::ObjectifiedHash]
def add_hook(url)
post("/hooks", :body => {:url => url})
end
alias_method :add_system_hook, :add_hook
# Tests a system hook.
#
# @example
# Gitlab.hook(3)
# Gitlab.system_hook(12)
#
# @param [Integer] id The ID of a system hook.
# @return [Array<Gitlab::ObjectifiedHash>]
def hook(id)
get("/hooks/#{id}")
end
alias_method :system_hook, :hook
# Deletes a new system hook.
#
# @example
# Gitlab.delete_hook(3)
# Gitlab.delete_system_hook(12)
#
# @param [Integer] id The ID of a system hook.
# @return [Gitlab::ObjectifiedHash]
def delete_hook(id)
delete("/hooks/#{id}")
end
alias_method :delete_system_hook, :delete_hook
end
end

View File

@@ -0,0 +1,131 @@
class Gitlab::Client
# Defines methods related to users.
module Users
# Gets a list of users.
#
# @example
# Gitlab.users
#
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def users(options={})
get("/users", :query => options)
end
# Gets information about a user.
# Will return information about an authorized user if no ID passed.
#
# @example
# Gitlab.user
# Gitlab.user(2)
#
# @param [Integer] id The ID of a user.
# @return [Gitlab::ObjectifiedHash]
def user(id=nil)
id.to_i.zero? ? get("/user") : get("/users/#{id}")
end
# Creates a new user.
# Requires authentication from an admin account.
#
# @param [String] email The email of a user.
# @param [String] password The password of a user.
# @param [Hash] options A customizable set of options.
# @option options [String] :name The name of a user. Defaults to email.
# @option options [String] :skype The skype of a user.
# @option options [String] :linkedin The linkedin of a user.
# @option options [String] :twitter The twitter of a user.
# @option options [Integer] :projects_limit The limit of projects for a user.
# @return [Gitlab::ObjectifiedHash] Information about created user.
def create_user(email, password, options={})
body = {:email => email, :password => password, :name => email}.merge(options)
post("/users", :body => body)
end
# Updates a user.
#
# @param [Integer] id The ID of a user.
# @param [Hash] options A customizable set of options.
# @option options [String] email The email of a user.
# @option options [String] password The password of a user.
# @option options [String] :name The name of a user. Defaults to email.
# @option options [String] :skype The skype of a user.
# @option options [String] :linkedin The linkedin of a user.
# @option options [String] :twitter The twitter of a user.
# @option options [Integer] :projects_limit The limit of projects for a user.
# @return [Gitlab::ObjectifiedHash] Information about created user.
def edit_user(user_id, options={})
put("/users/#{user_id}", :body => options)
end
def edit_user_email(user_id, options={})
put("/users/#{user_id}/email", :body => options)
end
def delete_user(user_id)
delete("/users/#{user_id}")
end
# Creates a new user session.
#
# @example
# Gitlab.session('jack@example.com', 'secret12345')
#
# @param [String] email The email of a user.
# @param [String] password The password of a user.
# @return [Gitlab::ObjectifiedHash]
# @note This method doesn't require private_token to be set.
def session(email, password)
post("/session", :body => {:email => email, :password => password})
end
# Gets a list of user's SSH keys.
#
# @example
# Gitlab.ssh_keys
#
# @param [Hash] options A customizable set of options.
# @option options [Integer] :page The page number.
# @option options [Integer] :per_page The number of results per page.
# @return [Array<Gitlab::ObjectifiedHash>]
def ssh_keys(options={})
get("/user/keys", :query => options)
end
# Gets information about SSH key.
#
# @example
# Gitlab.ssh_key(1)
#
# @param [Integer] id The ID of a user's SSH key.
# @return [Gitlab::ObjectifiedHash]
def ssh_key(id)
get("/user/keys/#{id}")
end
# Creates a new SSH key.
#
# @example
# Gitlab.create_ssh_key('key title', 'key body')
#
# @param [String] title The title of an SSH key.
# @param [String] key The SSH key body.
# @return [Gitlab::ObjectifiedHash] Information about created SSH key.
def create_ssh_key(title, key)
post("/user/keys", :body => {:title => title, :key => key})
end
# Deletes an SSH key.
#
# @example
# Gitlab.delete_ssh_key(1)
#
# @param [Integer] id The ID of a user's SSH key.
# @return [Gitlab::ObjectifiedHash] Information about deleted SSH key.
def delete_ssh_key(id)
delete("/user/keys/#{id}")
end
end
end

View File

@@ -0,0 +1,39 @@
module Gitlab
# Defines constants and methods related to configuration.
module Configuration
# An array of valid keys in the options hash when configuring a Gitlab::API.
VALID_OPTIONS_KEYS = [:endpoint, :private_token, :user_agent, :sudo, :httparty].freeze
# The user agent that will be sent to the API endpoint if none is set.
DEFAULT_USER_AGENT = "Gitlab Ruby Gem #{Gitlab::VERSION}".freeze
# @private
attr_accessor(*VALID_OPTIONS_KEYS)
# Sets all configuration options to their default values
# when this module is extended.
def self.extended(base)
base.reset
end
# Convenience method to allow configuration options to be set in a block.
def configure
yield self
end
# Creates a hash of options and their values.
def options
VALID_OPTIONS_KEYS.inject({}) do |option, key|
option.merge!(key => send(key))
end
end
# Resets all configuration options to the defaults.
def reset
self.endpoint = ENV['GITLAB_API_ENDPOINT']
self.private_token = ENV['GITLAB_API_PRIVATE_TOKEN']
self.sudo = nil
self.user_agent = DEFAULT_USER_AGENT
end
end
end

View File

@@ -0,0 +1,45 @@
module Gitlab
module Error
# Custom error class for rescuing from all Gitlab errors.
class Error < StandardError; end
# Raise when attributes are missing.
class MissingAttributes < Error; end
# Raised when API endpoint credentials not configured.
class MissingCredentials < Error; end
# Raised when impossible to parse response body.
class Parsing < Error; end
# Raised when API endpoint returns the HTTP status code 400.
class BadRequest < Error; end
# Raised when API endpoint returns the HTTP status code 401.
class Unauthorized < Error; end
# Raised when API endpoint returns the HTTP status code 403.
class Forbidden < Error; end
# Raised when API endpoint returns the HTTP status code 404.
class NotFound < Error; end
# Raised when API endpoint returns the HTTP status code 405.
class MethodNotAllowed < Error; end
# Raised when API endpoint returns the HTTP status code 406.
class DataNotAccepted < Error; end
# Raised when API endpoint returns the HTTP status code 409.
class Conflict < Error; end
# Raised when API endpoint returns the HTTP status code 500.
class InternalServerError < Error; end
# Raised when API endpoint returns the HTTP status code 502.
class BadGateway < Error; end
# Raised when API endpoint returns the HTTP status code 503.
class ServiceUnavailable < Error; end
end
end

View File

@@ -0,0 +1,44 @@
require 'gitlab'
require 'gitlab/cli_helpers'
module Gitlab::Help
extend Gitlab::CLI::Helpers
def self.get_help(methods,cmd=nil)
help = ''
if cmd.nil? || cmd == 'help'
help = actions_table
else
ri_cmd = `which ri`.chomp
if $? == 0
namespace = methods.select {|m| m[:name] === cmd }.map {|m| m[:owner]+'.'+m[:name] }.shift
if namespace
begin
ri_output = `#{ri_cmd} -T #{namespace} 2>&1`.chomp
if $? == 0
ri_output.gsub!(/#{cmd}\((.*?)\)/, cmd+' \1')
ri_output.gsub!(/Gitlab\./, 'gitlab> ')
ri_output.gsub!(/Gitlab\..+$/, '')
ri_output.gsub!(/\,\s?/, ' ')
help = ri_output
else
help = "Ri docs not found for #{namespace}, please install the docs to use 'help'"
end
rescue => e
puts e.message
end
else
help = "Unknown command: #{cmd}"
end
else
help = "'ri' tool not found in your PATH, please install it to use the help."
end
end
puts help
end
end

View File

@@ -0,0 +1,24 @@
module Gitlab
# Converts hashes to the objects.
class ObjectifiedHash
# Creates a new ObjectifiedHash object.
def initialize(hash)
@hash = hash
@data = hash.inject({}) do |data, (key,value)|
value = ObjectifiedHash.new(value) if value.is_a? Hash
data[key.to_s] = value
data
end
end
def to_hash
@hash
end
alias_method :to_h, :to_hash
# Delegate to ObjectifiedHash.
def method_missing(key)
@data.key?(key.to_s) ? @data[key.to_s] : nil
end
end
end

View File

@@ -0,0 +1,116 @@
require 'httparty'
require 'json'
module Gitlab
# @private
class Request
include HTTParty
format :json
headers 'Accept' => 'application/json'
parser Proc.new { |body, _| parse(body) }
attr_accessor :private_token
# Converts the response body to an ObjectifiedHash.
def self.parse(body)
body = decode(body)
if body.is_a? Hash
ObjectifiedHash.new body
elsif body.is_a? Array
body.collect! { |e| ObjectifiedHash.new(e) }
elsif body == true
body
else
raise Error::Parsing.new "Couldn't parse a response body"
end
end
# Decodes a JSON response into Ruby object.
def self.decode(response)
begin
JSON.load response
rescue JSON::ParserError
raise Error::Parsing.new "The response is not a valid JSON"
end
end
def get(path, options={})
set_httparty_config(options)
set_private_token_header(options)
validate self.class.get(path, options)
end
def post(path, options={})
set_httparty_config(options)
set_private_token_header(options, path)
validate self.class.post(path, options)
end
def put(path, options={})
set_httparty_config(options)
set_private_token_header(options)
validate self.class.put(path, options)
end
def delete(path, options={})
set_httparty_config(options)
set_private_token_header(options)
validate self.class.delete(path, options)
end
# Checks the response code for common errors.
# Returns parsed response for successful requests.
def validate(response)
# case response.code
# when 400; raise Error::BadRequest.new error_message(response)
# when 401; raise Error::Unauthorized.new error_message(response)
# when 403; raise Error::Forbidden.new error_message(response)
# when 404; raise Error::NotFound.new error_message(response)
# when 405; raise Error::MethodNotAllowed.new error_message(response)
# when 406; raise Error::DataNotAccepted.new error_message(response)
# when 409; raise Error::Conflict.new error_message(response)
# when 500; raise Error::InternalServerError.new error_message(response)
# when 502; raise Error::BadGateway.new error_message(response)
# when 503; raise Error::ServiceUnavailable.new error_message(response)
# end
response.parsed_response
end
# Sets a base_uri and default_params for requests.
# @raise [Error::MissingCredentials] if endpoint not set.
def set_request_defaults(endpoint, private_token, sudo=nil)
raise Error::MissingCredentials.new("Please set an endpoint to API") unless endpoint
@private_token = private_token
self.class.base_uri endpoint
self.class.default_params :sudo => sudo
self.class.default_params.delete(:sudo) if sudo.nil?
end
private
# Sets a PRIVATE-TOKEN header for requests.
# @raise [Error::MissingCredentials] if private_token not set.
def set_private_token_header(options, path=nil)
unless path == '/session'
raise Error::MissingCredentials.new("Please set a private_token for user") unless @private_token
options[:headers] = {'PRIVATE-TOKEN' => @private_token}
end
end
# Set HTTParty configuration
# @see https://github.com/jnunemaker/httparty
def set_httparty_config(options)
if self.httparty
options.merge!(self.httparty)
end
end
def error_message(response)
"Server responded with code #{response.code}, message: #{response.parsed_response.message}. " \
"Request URI: #{response.request.base_uri}#{response.request.path}"
end
end
end

View File

@@ -0,0 +1,51 @@
require 'gitlab'
require 'gitlab/help'
require 'gitlab/cli_helpers'
require 'readline'
class Gitlab::Shell
extend Gitlab::CLI::Helpers
def self.start
actions = Gitlab.actions
comp = proc { |s| actions.map(&:to_s).grep(/^#{Regexp.escape(s)}/) }
Readline.completion_proc = comp
Readline.completion_append_character = ' '
client = Gitlab::Client.new(endpoint: '')
while buf = Readline.readline('gitlab> ', true)
next if buf.nil? || buf.empty?
break if buf == 'exit'
buf = buf.scan(/["][^"]+["]|\S+/).map { |word| word.gsub(/^['"]|['"]$/,'') }
cmd = buf.shift
args = buf.count > 0 ? buf : []
if cmd == 'help'
methods = []
actions.each do |action|
methods << {
name: action.to_s,
owner: client.method(action).owner.to_s
}
end
args[0].nil? ? Gitlab::Help.get_help(methods) : Gitlab::Help.get_help(methods, args[0])
next
end
data = if actions.include?(cmd.to_sym)
confirm_command(cmd)
gitlab_helper(cmd, args)
else
"'#{cmd}' is not a valid command. See the 'help' for a list of valid commands."
end
output_table(cmd, args, data)
end
end
end

View File

@@ -0,0 +1,3 @@
module Gitlab
VERSION = "3.2.0"
end

View File

@@ -0,0 +1 @@
{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected": true}

View File

@@ -0,0 +1 @@
[{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"}},{"name":"dashboard-feed","commit":{"id":"f8f6ff065eccc6ede4d35ed87a09bb962b84ca25","parents":[{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e"}],"tree":"e17f2157143d550891d4669c10b7446e4739bc6d","message":"add projects atom feed","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-31T23:42:02-07:00","committed_date":"2012-05-31T23:42:02-07:00"}},{"name":"master","commit":{"id":"2cf8010792c3075824ee27d0f037aeb178cbbf7e","parents":[{"id":"af226ae9c9af406c8a0e0bbdf364563495c2f432"},{"id":"e851cb07762aa464aae10e8b4b28de87c1a6f925"}],"tree":"6c6845838039f01723d91f395a1d2fa1dcc82522","message":"Merge pull request #868 from SaitoWu/bugfix/encoding\n\nBugfix/encoding","author":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"committer":{"name":"Dmitriy Zaporozhets","email":"dmitriy.zaporozhets@gmail.com"},"authored_date":"2012-05-30T00:24:43-07:00","committed_date":"2012-05-30T00:24:43-07:00"}},{"name":"preview_notes","commit":{"id":"3749e0d99ac6bfbc65889b1b7a5310e14e7fe89a","parents":[{"id":"2483181f2c3d4ea7d2c68147b19bc07fc3937b0c"}],"tree":"f8c56161b0d6561568f088df9961362eb1ece88b","message":"pass project_id to notes preview path","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-08-09T23:46:27-07:00","committed_date":"2012-08-09T23:46:27-07:00"}},{"name":"refactoring","commit":{"id":"7c7761099cae83f59fe5780340e100be890847b2","parents":[{"id":"058d80b3363dd4fc4417ca4f60f76119188a2470"}],"tree":"d7d4a94c700dc0e84ee943019213d2358a49c413","message":"fix deprecation warnings","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-05-29T07:16:28-07:00","committed_date":"2012-05-29T07:16:28-07:00"}}]

View File

@@ -0,0 +1 @@
{"note":"Cool Merge Request!","author":{"id":1,"username":"jsmith","email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-07-11T01:32:18Z"}}

View File

@@ -0,0 +1 @@
{"name":"api","commit":{ "id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","message":"API: expose issues project id","parent_ids":["949b1df930bedace1dbd755aaa4a82e8c451a616"],"authored_date":"2012-07-25T04:22:21-07:00","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","committed_date":"2012-07-25T04:22:21-07:00","committer_name":"Nihad Abbasov","committer_email":"narkoz.2008@gmail.com"},"protected": false}

View File

@@ -0,0 +1 @@
{"id":2,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}}

View File

@@ -0,0 +1 @@
{"message": "409 Already exists"}

60
lib/gitlab-cli/spec/fixtures/group.json vendored Normal file
View File

@@ -0,0 +1,60 @@
{"id": 10, "name": "GitLab-Group", "path": "gitlab-group", "owner_id": 6, "projects": [
{
"id": 9,
"name": "mojito",
"description": null,
"default_branch": "master",
"owner": {
"id": 6,
"username": "jose",
"email": "jose@abc.com",
"name": "Jose Jose",
"blocked": false,
"created_at": "2013-02-06T06:54:06Z"
},
"path": "mojito",
"path_with_namespace": "gitlab-group/mojito",
"issues_enabled": true,
"merge_requests_enabled": true,
"wall_enabled": true,
"wiki_enabled": true,
"created_at": "2013-02-06T16:59:15Z",
"namespace": {
"created_at": "2013-02-06T16:58:22Z",
"id": 10,
"name": "GitLab-Group",
"owner_id": 6,
"path": "gitlab-group",
"updated_at": "2013-02-06T16:58:22Z"
}
},
{
"id": 10,
"name": "gitlabhq",
"description": null,
"default_branch": null,
"owner": {
"id": 6,
"username": "randx",
"email": "randx@github.com",
"name": "Dmitry Z",
"blocked": false,
"created_at": "2013-02-06T06:54:06Z"
},
"path": "gitlabhq",
"path_with_namespace": "gitlab-group/gitlabhq",
"issues_enabled": true,
"merge_requests_enabled": true,
"wall_enabled": true,
"wiki_enabled": true,
"created_at": "2013-02-06T17:02:31Z",
"namespace": {
"created_at": "2013-02-06T16:58:22Z",
"id": 10,
"name": "GitLab-Group",
"owner_id": 6,
"path": "gitlab-group",
"updated_at": "2013-02-06T16:58:22Z"
}
}
]}

View File

@@ -0,0 +1 @@
{"id":3,"name":"Gitlab-Group","path":"gitlab-group","owner_id":1}

View File

@@ -0,0 +1 @@
{"id":2,"username":"jsmith","email":"jsmith@local.host","name":"John Smith","state":"active","created_at":"2013-09-04T18:15:30Z","access_level":10}

View File

@@ -0,0 +1 @@
{"created_at":"2013-09-04T18:18:15Z","group_access":10,"group_id":3,"id":2,"notification_level":3,"updated_at":"2013-09-04T18:18:15Z","user_id":2}

View File

@@ -0,0 +1 @@
[{"id":1,"username":"eraymond","email":"eraymond@local.host","name":"Edward Raymond","state":"active","created_at":"2013-08-30T16:16:22Z","access_level":50},{"id":1,"username":"jsmith","email":"jsmith@local.host","name":"John Smith","state":"active","created_at":"2013-08-30T16:16:22Z","access_level":50}]

View File

@@ -0,0 +1,2 @@
[{"id": 3,"name": "ThreeGroup","path": "threegroup","owner_id": 1},{"id": 5,"name": "Five-Group","path": "five-group","owner_id": 2},{"id": 8,"name": "Eight Group","path": "eight-group","owner_id": 6}
]

View File

@@ -0,0 +1 @@
{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}

View File

@@ -0,0 +1 @@
[{"id":1,"project_id":1,"title":"Culpa eius recusandae suscipit autem distinctio dolorum.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":6,"project_id":2,"title":"Ut in dolorum omnis sed sit aliquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":21,"project_id":1,"title":"Vitae ea aliquam et quo eligendi sapiente voluptatum labore hic nihil culpa.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":26,"project_id":2,"title":"Quo enim est nihil atque placeat voluptas neque eos voluptas.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}]

1
lib/gitlab-cli/spec/fixtures/key.json vendored Normal file
View File

@@ -0,0 +1 @@
{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"}

View File

@@ -0,0 +1 @@
[{"id":1,"title":"narkoz@helium","key":"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCkUsh42Nh1yefGd1jbSELn5XsY8p5Oxmau0/1HqHnjuYOaj5X+kHccFDwtmtg9Ox8ua/+WptNsiE8IUwsD3zKgEjajgwq3gMeeFdxfXwM+tEvHOOMV9meRrgRWGYCToPbT6sR7/YMAYa7cPqWSpx/oZhYfz4XtoMv3ZZT1fZMmx3MY3HwXwW8j+obJyN2K4LN0TFi9RPgWWYn0DCyb9OccmABimt3i74WoJ/OT8r6/7swce8+OSe0Q2wBhyTtvxg2vtUcoek8Af+EZaUMBwSEzEsocOCzwQvjF5XUk5o7dJ8nP8W3RE60JWX57t16eQm7lBmumLYfszpn2isd6W7a1 narkoz@helium"}]

View File

@@ -0,0 +1 @@
{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}}

View File

@@ -0,0 +1 @@
[{"note":"this is the 1st comment on the 2merge merge request","author":{"id":11,"username":"admin","email":"admin@example.com","name":"A User","state":"active","created_at":"2014-03-06T08:17:35.000Z"}},{"note":"another discussion point on the 2merge request","author":{"id":12,"username":"admin","email":"admin@example.com","name":"A User","state":"active","created_at":"2014-03-06T08:17:35.000Z"}}]

View File

@@ -0,0 +1 @@
[{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"New feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}}]

View File

@@ -0,0 +1 @@
{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"}

View File

@@ -0,0 +1 @@
[{"id":1,"project_id":3,"title":"3.0","description":"","due_date":"2012-10-22","closed":false,"updated_at":"2012-09-17T10:15:31Z","created_at":"2012-09-17T10:15:31Z"}]

View File

@@ -0,0 +1 @@
{"id":1201,"body":"The solution is rather tricky","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"created_at":"2012-11-27T19:16:44Z"}

View File

@@ -0,0 +1 @@
[{"id":1201,"body":"The solution is rather tricky","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"created_at":"2012-11-27T19:16:44Z"},{"id":1207,"body":"I know, right?","author":{"id":1,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"created_at":"2012-11-27T19:58:21Z"}]

View File

@@ -0,0 +1 @@
{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"public":false,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"}

View File

@@ -0,0 +1,13 @@
{
"id": "6104942438c14ec7bd21c6cd5bd995272b3faff6",
"short_id": "6104942438c",
"title": "Sanitize for network graph",
"author_name": "randx",
"author_email": "dmitriy.zaporozhets@gmail.com",
"created_at": "2012-09-20T09:06:12+03:00",
"committed_date": "2012-09-20T09:06:12+03:00",
"authored_date": "2012-09-20T09:06:12+03:00",
"parent_ids": [
"ae1d9fb46aa2b07ee9836d49862ec4e2c46fbbba"
]
}

View File

@@ -0,0 +1,10 @@
{
"diff": "--- a/doc/update/5.4-to-6.0.md\n+++ b/doc/update/5.4-to-6.0.md\n@@ -71,6 +71,8 @@\n sudo -u git -H bundle exec rake migrate_keys RAILS_ENV=production\n sudo -u git -H bundle exec rake migrate_inline_notes RAILS_ENV=production\n \n+sudo -u git -H bundle exec rake assets:precompile RAILS_ENV=production\n+\n ```\n \n ### 6. Update config files",
"new_path": "doc/update/5.4-to-6.0.md",
"old_path": "doc/update/5.4-to-6.0.md",
"a_mode": null,
"b_mode": "100644",
"new_file": false,
"renamed_file": false,
"deleted_file": false
}

View File

@@ -0,0 +1 @@
[{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","short_id":"f7dd067490f","title":"API: expose issues project id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T04:22:21-07:00"},{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616","short_id":"949b1df930b","title":"API: update docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:35:41-07:00"},{"id":"1b95c8bff351f6718ec31ac1de1e48c57bc95d44","short_id":"1b95c8bff35","title":"API: ability to get project by id","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-25T02:18:30-07:00"},{"id":"92d98f5a0c28bffd7b070cda190b07ab72667d58","short_id":"92d98f5a0c2","title":"Merge pull request #1118 from patthoyts/pt/ldap-missing-password","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:51:06-07:00"},{"id":"60d3e94874964a626f105d3598e1c122addcf43e","short_id":"60d3e948749","title":"Merge pull request #1122 from patthoyts/pt/missing-log","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:50:34-07:00"},{"id":"b683a71aa1230f17f9df47661c77dfeae27027de","short_id":"b683a71aa12","title":"Merge pull request #1135 from NARKOZ/api","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-25T01:48:00-07:00"},{"id":"fbb41100db35cf2def2c8b4d896b7015d56bd15b","short_id":"fbb41100db3","title":"update help section with issues API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:52:43-07:00"},{"id":"eca823c1c7cef45cc18c6ab36d2327650c85bfc3","short_id":"eca823c1c7c","title":"Merge branch 'master' into api","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:46:36-07:00"},{"id":"024e0348904179a8dea81c01e27a5f014cf57499","short_id":"024e0348904","title":"update API docs","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:25:01-07:00"},{"id":"7b33d8cbcab3b0ee5789ec607455ab62130db69f","short_id":"7b33d8cbcab","title":"add issues API","author_name":"Nihad Abbasov","author_email":"narkoz.2008@gmail.com","created_at":"2012-07-24T05:19:51-07:00"},{"id":"6035ad7e1fe519d0c6a42731790183889e3ba31d","short_id":"6035ad7e1fe","title":"Create the githost.log file if necessary.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T07:32:04-07:00"},{"id":"a2d244ec062f3348f6cd1c5218c6097402c5f562","short_id":"a2d244ec062","title":"Handle LDAP missing credentials error with a flash message.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-21T01:04:05-07:00"},{"id":"8b7e404b5b6944e9c92cc270b2e5d0005781d49d","short_id":"8b7e404b5b6","title":"Up to 2.7.0","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:53:55-07:00"},{"id":"11721b0dbe82c35789be3e4fa8e14663934b2ff5","short_id":"11721b0dbe8","title":"Help section for system hooks completed","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:47:57-07:00"},{"id":"9c8a1e651716212cf50a623d98e03b8dbdb2c64a","short_id":"9c8a1e65171","title":"Fix system hook example","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:32:42-07:00"},{"id":"4261acda90ff4c61326d80cba026ae76e8551f8f","short_id":"4261acda90f","title":"move SSH keys tab closer to begining","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:27:09-07:00"},{"id":"a69fc5dd23bd502fd36892a80eec21a4c53891f8","short_id":"a69fc5dd23b","title":"Endless event loading for dsahboard","author_name":"randx","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-21T00:23:05-07:00"},{"id":"860fa1163a5fbdfec2bb01ff2d584351554dee29","short_id":"860fa1163a5","title":"Merge pull request #1117 from patthoyts/pt/user-form","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T14:23:49-07:00"},{"id":"787e5e94acf5e20280416c9fda105ef5b77576b3","short_id":"787e5e94acf","title":"Fix english on the edit user form.","author_name":"Pat Thoyts","author_email":"patthoyts@users.sourceforge.net","created_at":"2012-07-20T14:18:42-07:00"},{"id":"9267cb04b0b3fdf127899c4b7e636dc27fac06d3","short_id":"9267cb04b0b","title":"Merge branch 'refactoring_controllers' of dev.gitlabhq.com:gitlabhq","author_name":"Dmitriy Zaporozhets","author_email":"dmitriy.zaporozhets@gmail.com","created_at":"2012-07-20T07:24:56-07:00"}]

View File

@@ -0,0 +1,8 @@
{
"created_at": "2013-10-05T15:05:26Z",
"fingerprint": "5c:b5:e6:b0:f5:31:65:3f:a6:b5:59:86:32:cc:15:e1",
"id": 2,
"key": "ssh-rsa ...",
"updated_at": "2013-10-05T15:05:26Z",
"user_id": null
}

View File

@@ -0,0 +1 @@
[{"title":null,"project_id":2,"action_name":"opened","target_id":null,"target_type":null,"author_id":1,"data":{"before":"ac0c1aa3898d6dea54d7868ea6f9c45fd5e30c59","after":"66350dbb62a221bc619b665aef3e1e7d3b306747","ref":"refs/heads/master","user_id":1,"user_name":"Administrator","project_id":2,"repository":{"name":"gitlab-ci","url":"git@demo.gitlab.com:gitlab/gitlab-ci.git","description":"Continuous integration server for gitlabhq | Coordinator","homepage":"http://demo.gitlab.com/gitlab/gitlab-ci"},"commits":[{"id":"8cf469b039931bab37bbf025e6b69287ea3cfb0e","message":"Modify screenshot\n\nSigned-off-by: Dmitriy Zaporozhets \u003Cdummy@gmail.com\u003E","timestamp":"2014-05-20T10:34:27+00:00","url":"http://demo.gitlab.com/gitlab/gitlab-ci/commit/8cf469b039931bab37bbf025e6b69287ea3cfb0e","author":{"name":"Dummy","email":"dummy@gmail.com"}},{"id":"66350dbb62a221bc619b665aef3e1e7d3b306747","message":"Edit some code\n\nSigned-off-by: Dmitriy Zaporozhets \u003Cdummy@gmail.com\u003E","timestamp":"2014-05-20T10:35:15+00:00","url":"http://demo.gitlab.com/gitlab/gitlab-ci/commit/66350dbb62a221bc619b665aef3e1e7d3b306747","author":{"name":"Dummy","email":"dummy@gmail.com"}}],"total_commits_count":2},"target_title":null,"created_at":"2014-05-20T10:35:26.240Z"},{"title":null,"project_id":2,"action_name":"opened","target_id":2,"target_type":"MergeRequest","author_id":1,"data":null,"target_title":" Morbi et cursus leo. Sed eget vestibulum sapien","created_at":"2014-05-20T10:24:11.917Z"}]

View File

@@ -0,0 +1 @@
{"id":1,"code":"brute","name":"Brute","description":null,"path":"brute","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Owner","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:56Z"}

View File

@@ -0,0 +1 @@
{"created_at":"2013-07-03T13:51:48Z","forked_from_project_id":24,"forked_to_project_id":42,"id":1,"updated_at":"2013-07-03T13:51:48Z"}

View File

@@ -0,0 +1 @@
{"id":1,"url":"https://api.example.net/v1/webhooks/ci"}

View File

@@ -0,0 +1 @@
[{"id":1,"url":"https://api.example.net/v1/webhooks/ci"}]

View File

@@ -0,0 +1 @@
[{"id":36,"project_id":3,"title":"Eos ut modi et laudantium quasi porro voluptas sed.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":35,"project_id":3,"title":"Ducimus illo in iure voluptatem dolores labore.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":34,"project_id":3,"title":"Rem tempora voluptatum atque eum sit nihil neque.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":33,"project_id":3,"title":"Beatae possimus nostrum nihil reiciendis laboriosam nihil delectus alias accusantium dolor unde.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":32,"project_id":3,"title":"Deserunt tenetur impedit est beatae voluptas voluptas quaerat quisquam.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":16,"project_id":3,"title":"Numquam earum aut laudantium reprehenderit voluptatem aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":15,"project_id":3,"title":"Qui veritatis voluptas fuga voluptate voluptas cupiditate.","description":null,"labels":[],"milestone":null,"assignee":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":14,"project_id":3,"title":"In assumenda et ipsa qui debitis voluptatem incidunt.","description":null,"labels":[],"milestone":null,"assignee":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":13,"project_id":3,"title":"Illo eveniet consequatur enim iste provident facilis rerum voluptatem et architecto aut.","description":null,"labels":[],"milestone":null,"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"author":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"},{"id":12,"project_id":3,"title":"Veniam et tempore quidem eum reprehenderit cupiditate non aut velit eaque.","description":null,"labels":[],"milestone":null,"assignee":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"closed":false,"updated_at":"2012-09-17T09:42:20Z","created_at":"2012-09-17T09:42:20Z"}]

View File

@@ -0,0 +1,6 @@
{
"id": 2,
"title": "Key Title",
"key": "ssh-rsa ...",
"created_at": "2013-09-22T18:34:32Z"
}

View File

@@ -0,0 +1,6 @@
[{
"id": 2,
"title": "Key Title",
"key": "ssh-rsa ...",
"created_at": "2013-09-22T18:34:32Z"
}]

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1 @@
[{"id":1,"code":"brute","name":"Brute","description":null,"path":"brute","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"code":"mozart","name":"Mozart","description":null,"path":"mozart","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:57Z"},{"id":3,"code":"gitlab","name":"Gitlab","description":null,"path":"gitlab","default_branch":null,"owner":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"private":true,"issues_enabled":true,"merge_requests_enabled":true,"wall_enabled":true,"wiki_enabled":true,"created_at":"2012-09-17T09:41:58Z"}]

View File

@@ -0,0 +1 @@
{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected":true}

View File

@@ -0,0 +1 @@
{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","private_token":"qEsq1pt6HJPaNciie3MG"}

View File

@@ -0,0 +1 @@
{"id":1,"title":"Rails Console ActionMailer","file_name":"mailer_test.rb","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"expires_at":"2012-09-24T00:00:00Z","updated_at":"2012-09-17T09:51:42Z","created_at":"2012-09-17T09:51:42Z"}

View File

@@ -0,0 +1 @@
[{"id":1,"title":"Rails Console ActionMailer","file_name":"mailer_test.rb","author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z"},"expires_at":"2012-09-24T00:00:00Z","updated_at":"2012-09-17T09:51:42Z","created_at":"2012-09-17T09:51:42Z"}]

View File

@@ -0,0 +1 @@
{"id": 3, "url": "http://example.com/hook", "created_at": "2013-10-02T10:15:31Z"}

View File

@@ -0,0 +1 @@
{ "event_name": "project_create", "name": "Ruby", "path": "ruby", "project_id": 1, "owner_name": "Someone", "owner_email": "example@gitlabhq.com" }

View File

@@ -0,0 +1 @@
[{"id": 3, "url": "http://example.com/hook", "created_at": "2013-10-02T10:15:31Z"}]

1
lib/gitlab-cli/spec/fixtures/tag.json vendored Normal file
View File

@@ -0,0 +1 @@
{"name": "v1.0.0","commit": {"id": "2695effb5807a22ff3d138d593fd856244e155e7","parents": [],"message": "Initial commit","authored_date": "2012-05-28T04:42:42-07:00","author_name": "John Smith","author email": "john@example.com","committer_name": "Jack Smith","committed_date": "2012-05-28T04:42:42-07:00","committer_email": "jack@example.com"},"protected": false}

View File

@@ -0,0 +1 @@
{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40}

View File

@@ -0,0 +1 @@
[{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-09-17T09:41:56Z","access_level":40},{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":40},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","blocked":false,"created_at":"2012-09-17T09:42:03Z","access_level":20}]

View File

@@ -0,0 +1 @@
{"name":"api","commit":{"id":"f7dd067490fe57505f7226c3b54d3127d2f7fd46","parents":[{"id":"949b1df930bedace1dbd755aaa4a82e8c451a616"}],"tree":"f8c4b21c036339f92fcc5482aa28a41250553b27","message":"API: expose issues project id","author":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"committer":{"name":"Nihad Abbasov","email":"narkoz.2008@gmail.com"},"authored_date":"2012-07-25T04:22:21-07:00","committed_date":"2012-07-25T04:22:21-07:00"},"protected":false}

View File

@@ -0,0 +1 @@
{"id":1,"target_branch":"master","source_branch":"api","project_id":3,"title":"A different new feature","closed":false,"merged":false,"author":{"id":1,"email":"john@example.com","name":"John Smith","blocked":false,"created_at":"2012-10-19T05:56:05Z"},"assignee":{"id":2,"email":"jack@example.com","name":"Jack Smith","blocked":false,"created_at":"2012-10-19T05:56:14Z"}}

View File

@@ -0,0 +1 @@
{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"}

View File

@@ -0,0 +1 @@
[{"id":1,"email":"john@example.com","name":"John Smith","bio":null,"skype":"","linkedin":"","twitter":"john","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:41:56Z"},{"id":2,"email":"jack@example.com","name":"Jack Smith","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":3,"email":"wilma@mayerblanda.ca","name":"Beatrice Jewess","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":4,"email":"nicole@mertz.com","name":"Felipe Davis","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":5,"email":"aliza_stark@schmeler.info","name":"Michale Von","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":6,"email":"faye.watsica@rohanwalter.com","name":"Ambrose Hansen","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"},{"id":7,"email":"maida@walshtorp.name","name":"Alana Hahn","bio":null,"skype":"","linkedin":"","twitter":"","dark_scheme":false,"theme_id":1,"blocked":false,"created_at":"2012-09-17T09:42:03Z"}]

View File

@@ -0,0 +1,80 @@
require 'spec_helper'
describe Gitlab::CLI do
describe ".run" do
context "when command is version" do
it "should show gem version" do
output = capture_output { Gitlab::CLI.run('-v') }
expect(output).to eq("Gitlab Ruby Gem #{Gitlab::VERSION}\n")
end
end
context "when command is info" do
it "should show environment info" do
output = capture_output { Gitlab::CLI.run('info') }
expect(output).to include("Gitlab endpoint is")
expect(output).to include("Gitlab private token is")
expect(output).to include("Ruby Version is")
expect(output).to include("Gitlab Ruby Gem")
end
end
context "when command is help" do
it "should show available actions" do
output = capture_output { Gitlab::CLI.run('help') }
expect(output).to include('Available commands')
expect(output).to include('MergeRequests')
expect(output).to include('team_members')
end
end
context "when command is user" do
before do
stub_get("/user", "user")
@output = capture_output { Gitlab::CLI.run('user') }
end
it "should show executed command" do
expect(@output).to include('Gitlab.user')
end
it "should show user data" do
expect(@output).to include('name')
expect(@output).to include('John Smith')
end
end
end
describe ".start" do
context "when command with excluded fields" do
before do
stub_get("/user", "user")
args = ['user', '--except=id,email,name']
@output = capture_output { Gitlab::CLI.start(args) }
end
it "should show user data with excluded fields" do
expect(@output).to_not include('John Smith')
expect(@output).to include('bio')
expect(@output).to include('created_at')
end
end
context "when command with required fields" do
before do
stub_get("/user", "user")
args = ['user', '--only=id,email,name']
@output = capture_output { Gitlab::CLI.start(args) }
end
it "should show user data with required fields" do
expect(@output).to include('id')
expect(@output).to include('name')
expect(@output).to include('email')
expect(@output).to include('John Smith')
expect(@output).to_not include('bio')
expect(@output).to_not include('created_at')
end
end
end
end

View File

@@ -0,0 +1,103 @@
require 'spec_helper'
describe Gitlab::Client do
it { should respond_to :repo_branches }
it { should respond_to :repo_branch }
it { should respond_to :repo_protect_branch }
it { should respond_to :repo_unprotect_branch }
describe ".branches" do
before do
stub_get("/projects/3/repository/branches", "branches")
@branches = Gitlab.branches(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/repository/branches")).to have_been_made
end
it "should return an array of repository branches" do
expect(@branches).to be_an Array
expect(@branches.first.name).to eq("api")
end
end
describe ".branch" do
before do
stub_get("/projects/3/repository/branches/api", "branch")
@branch = Gitlab.branch(3, "api")
end
it "should get the correct resource" do
expect(a_get("/projects/3/repository/branches/api")).to have_been_made
end
it "should return information about a repository branch" do
expect(@branch.name).to eq("api")
end
end
describe ".protect_branch" do
before do
stub_put("/projects/3/repository/branches/api/protect", "protect_branch")
@branch = Gitlab.protect_branch(3, "api")
end
it "should get the correct resource" do
expect(a_put("/projects/3/repository/branches/api/protect")).to have_been_made
end
it "should return information about a protected repository branch" do
expect(@branch.name).to eq("api")
expect(@branch.protected).to eq(true)
end
end
describe ".unprotect_branch" do
before do
stub_put("/projects/3/repository/branches/api/unprotect", "unprotect_branch")
@branch = Gitlab.unprotect_branch(3, "api")
end
it "should get the correct resource" do
expect(a_put("/projects/3/repository/branches/api/unprotect")).to have_been_made
end
it "should return information about an unprotected repository branch" do
expect(@branch.name).to eq("api")
expect(@branch.protected).to eq(false)
end
end
describe ".create_branch" do
context "with branch name" do
before do
stub_post("/projects/3/repository/branches", "create_branch")
@branch = Gitlab.create_branch(3, "api","master")
end
it "should get the correct resource" do
expect(a_post("/projects/3/repository/branches")).to have_been_made
end
it "should return information about a new repository branch" do
expect(@branch.name).to eq("api")
end
end
context "with commit hash" do
before do
stub_post("/projects/3/repository/branches", "create_branch")
@branch = Gitlab.create_branch(3, "api","949b1df930bedace1dbd755aaa4a82e8c451a616")
end
it "should get the correct resource" do
expect(a_post("/projects/3/repository/branches")).to have_been_made
end
it "should return information about a new repository branch" do
expect(@branch.name).to eq("api")
end
end
end
end

View File

@@ -0,0 +1,111 @@
require 'spec_helper'
describe Gitlab::Client do
describe ".groups" do
before do
stub_get("/groups", "groups")
stub_get("/groups/3", "group")
@group = Gitlab.group(3)
@groups = Gitlab.groups
end
it "should get the correct resource" do
expect(a_get("/groups")).to have_been_made
expect(a_get("/groups/3")).to have_been_made
end
it "should return an array of Groups" do
expect(@groups).to be_an Array
expect(@groups.first.path).to eq("threegroup")
end
end
describe ".create_group" do
before do
stub_post("/groups", "group_create")
@group = Gitlab.create_group('GitLab-Group', 'gitlab-path')
end
it "should get the correct resource" do
expect(a_post("/groups").
with(:body => {:path => 'gitlab-path', :name => 'GitLab-Group'})).to have_been_made
end
it "should return information about a created group" do
expect(@group.name).to eq("Gitlab-Group")
expect(@group.path).to eq("gitlab-group")
end
end
describe ".transfer_project_to_group" do
before do
stub_post("/projects", "project")
@project = Gitlab.create_project('Gitlab')
stub_post("/groups", "group_create")
@group = Gitlab.create_group('GitLab-Group', 'gitlab-path')
stub_post("/groups/#{@group.id}/projects/#{@project.id}", "group_create")
@group_transfer = Gitlab.transfer_project_to_group(@group.id,@project.id)
end
it "should post to the correct resource" do
expect(a_post("/groups/#{@group.id}/projects/#{@project.id}").with(:body => {:id => @group.id.to_s, :project_id => @project.id.to_s})).to have_been_made
end
it "should return information about the group" do
expect(@group_transfer.name).to eq(@group.name)
expect(@group_transfer.path).to eq(@group.path)
expect(@group_transfer.id).to eq(@group.id)
end
end
describe ".group_members" do
before do
stub_get("/groups/3/members", "group_members")
@members = Gitlab.group_members(3)
end
it "should get the correct resource" do
expect(a_get("/groups/3/members")).to have_been_made
end
it "should return information about a group members" do
expect(@members).to be_an Array
expect(@members.size).to eq(2)
expect(@members[1].name).to eq("John Smith")
end
end
describe ".add_group_member" do
before do
stub_post("/groups/3/members", "group_member")
@member = Gitlab.add_group_member(3, 1, 40)
end
it "should get the correct resource" do
expect(a_post("/groups/3/members").
with(:body => {:user_id => '1', :access_level => '40'})).to have_been_made
end
it "should return information about an added member" do
expect(@member.name).to eq("John Smith")
end
end
describe ".remove_group_member" do
before do
stub_delete("/groups/3/members/1", "group_member_delete")
@group = Gitlab.remove_group_member(3, 1)
end
it "should get the correct resource" do
expect(a_delete("/groups/3/members/1")).to have_been_made
end
it "should return information about the group the member was removed from" do
expect(@group.group_id).to eq(3)
end
end
end

View File

@@ -0,0 +1,122 @@
require 'spec_helper'
describe Gitlab::Client do
describe ".issues" do
context "with project ID passed" do
before do
stub_get("/projects/3/issues", "project_issues")
@issues = Gitlab.issues(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/issues")).to have_been_made
end
it "should return an array of project's issues" do
expect(@issues).to be_an Array
expect(@issues.first.project_id).to eq(3)
end
end
context "without project ID passed" do
before do
stub_get("/issues", "issues")
@issues = Gitlab.issues
end
it "should get the correct resource" do
expect(a_get("/issues")).to have_been_made
end
it "should return an array of user's issues" do
expect(@issues).to be_an Array
expect(@issues.first.closed).to be_falsey
expect(@issues.first.author.name).to eq("John Smith")
end
end
end
describe ".issue" do
before do
stub_get("/projects/3/issues/33", "issue")
@issue = Gitlab.issue(3, 33)
end
it "should get the correct resource" do
expect(a_get("/projects/3/issues/33")).to have_been_made
end
it "should return information about an issue" do
expect(@issue.project_id).to eq(3)
expect(@issue.assignee.name).to eq("Jack Smith")
end
end
describe ".create_issue" do
before do
stub_post("/projects/3/issues", "issue")
@issue = Gitlab.create_issue(3, 'title')
end
it "should get the correct resource" do
expect(a_post("/projects/3/issues").
with(:body => {:title => 'title'})).to have_been_made
end
it "should return information about a created issue" do
expect(@issue.project_id).to eq(3)
expect(@issue.assignee.name).to eq("Jack Smith")
end
end
describe ".edit_issue" do
before do
stub_put("/projects/3/issues/33", "issue")
@issue = Gitlab.edit_issue(3, 33, :title => 'title')
end
it "should get the correct resource" do
expect(a_put("/projects/3/issues/33").
with(:body => {:title => 'title'})).to have_been_made
end
it "should return information about an edited issue" do
expect(@issue.project_id).to eq(3)
expect(@issue.assignee.name).to eq("Jack Smith")
end
end
describe ".close_issue" do
before do
stub_put("/projects/3/issues/33", "issue")
@issue = Gitlab.close_issue(3, 33)
end
it "should get the correct resource" do
expect(a_put("/projects/3/issues/33").
with(:body => {:state_event => 'close'})).to have_been_made
end
it "should return information about an closed issue" do
expect(@issue.project_id).to eq(3)
expect(@issue.assignee.name).to eq("Jack Smith")
end
end
describe ".reopen_issue" do
before do
stub_put("/projects/3/issues/33", "issue")
@issue = Gitlab.reopen_issue(3, 33)
end
it "should get the correct resource" do
expect(a_put("/projects/3/issues/33").
with(:body => {:state_event => 'reopen'})).to have_been_made
end
it "should return information about an reopened issue" do
expect(@issue.project_id).to eq(3)
expect(@issue.assignee.name).to eq("Jack Smith")
end
end
end

View File

@@ -0,0 +1,124 @@
require 'spec_helper'
describe Gitlab::Client do
describe ".merge_requests" do
before do
stub_get("/projects/3/merge_requests", "merge_requests")
@merge_requests = Gitlab.merge_requests(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/merge_requests")).to have_been_made
end
it "should return an array of project's merge requests" do
expect(@merge_requests).to be_an Array
expect(@merge_requests.first.project_id).to eq(3)
end
end
describe ".merge_request" do
before do
stub_get("/projects/3/merge_request/1", "merge_request")
@merge_request = Gitlab.merge_request(3, 1)
end
it "should get the correct resource" do
expect(a_get("/projects/3/merge_request/1")).to have_been_made
end
it "should return information about a merge request" do
expect(@merge_request.project_id).to eq(3)
expect(@merge_request.assignee.name).to eq("Jack Smith")
end
end
describe ".create_merge_request" do
before do
stub_post("/projects/3/merge_requests", "create_merge_request")
end
it "should fail if it doesn't have a source_branch" do
expect {
Gitlab.create_merge_request(3, 'New merge request', :target_branch => 'master')
}.to raise_error Gitlab::Error::MissingAttributes
end
it "should fail if it doesn't have a target_branch" do
expect {
Gitlab.create_merge_request(3, 'New merge request', :source_branch => 'dev')
}.to raise_error Gitlab::Error::MissingAttributes
end
it "should return information about a merge request" do
@merge_request = Gitlab.create_merge_request(3, 'New feature',
:source_branch => 'api',
:target_branch => 'master'
)
expect(@merge_request.project_id).to eq(3)
expect(@merge_request.assignee.name).to eq("Jack Smith")
expect(@merge_request.title).to eq('New feature')
end
end
describe ".update_merge_request" do
before do
stub_put("/projects/3/merge_request/2", "update_merge_request")
@merge_request = Gitlab.update_merge_request(3, 2,
:assignee_id => '1',
:target_branch => 'master',
:title => 'A different new feature'
)
end
it "should return information about a merge request" do
expect(@merge_request.project_id).to eq(3)
expect(@merge_request.assignee.name).to eq("Jack Smith")
expect(@merge_request.title).to eq('A different new feature')
end
end
describe ".merge_request_comments" do
before do
stub_get("/projects/3/merge_request/2/comments", "merge_request_comments")
@merge_request = Gitlab.merge_request_comments(3, 2)
end
it "should return merge request's comments" do
expect(@merge_request).to be_an Array
expect(@merge_request.length).to eq(2)
expect(@merge_request[0].note).to eq("this is the 1st comment on the 2merge merge request")
expect(@merge_request[0].author.id).to eq(11)
expect(@merge_request[1].note).to eq("another discussion point on the 2merge request")
expect(@merge_request[1].author.id).to eq(12)
end
end
describe ".merge_request_comments" do
before do
stub_get("/projects/3/merge_request/2/comments", "merge_request_comments")
@merge_request = Gitlab.merge_request_comments(3, 2)
end
it "should return merge request's comments" do
expect(@merge_request).to be_an Array
expect(@merge_request.length).to eq(2)
expect(@merge_request[0].note).to eq("this is the 1st comment on the 2merge merge request")
expect(@merge_request[0].author.id).to eq(11)
expect(@merge_request[1].note).to eq("another discussion point on the 2merge request")
expect(@merge_request[1].author.id).to eq(12)
end
end
describe ".create_merge_request_comment" do
before do
stub_post("/projects/3/merge_request/2/comments", "comment_merge_request")
end
it "should return information about a merge request" do
@merge_request = Gitlab.create_merge_request_comment(3, 2, 'Cool Merge Request!')
expect(@merge_request.note).to eq('Cool Merge Request!')
@merge_request.author.id == 1
end
end
end

View File

@@ -0,0 +1,66 @@
require 'spec_helper'
describe Gitlab::Client do
describe ".milestones" do
before do
stub_get("/projects/3/milestones", "milestones")
@milestones = Gitlab.milestones(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/milestones")).to have_been_made
end
it "should return an array of project's milestones" do
expect(@milestones).to be_an Array
expect(@milestones.first.project_id).to eq(3)
end
end
describe ".milestone" do
before do
stub_get("/projects/3/milestones/1", "milestone")
@milestone = Gitlab.milestone(3, 1)
end
it "should get the correct resource" do
expect(a_get("/projects/3/milestones/1")).to have_been_made
end
it "should return information about a milestone" do
expect(@milestone.project_id).to eq(3)
end
end
describe ".create_milestone" do
before do
stub_post("/projects/3/milestones", "milestone")
@milestone = Gitlab.create_milestone(3, 'title')
end
it "should get the correct resource" do
expect(a_post("/projects/3/milestones").
with(:body => {:title => 'title'})).to have_been_made
end
it "should return information about a created milestone" do
expect(@milestone.project_id).to eq(3)
end
end
describe ".edit_milestone" do
before do
stub_put("/projects/3/milestones/33", "milestone")
@milestone = Gitlab.edit_milestone(3, 33, :title => 'title')
end
it "should get the correct resource" do
expect(a_put("/projects/3/milestones/33").
with(:body => {:title => 'title'})).to have_been_made
end
it "should return information about an edited milestone" do
expect(@milestone.project_id).to eq(3)
end
end
end

View File

@@ -0,0 +1,156 @@
require 'spec_helper'
describe Gitlab::Client do
describe "notes" do
context "when wall notes" do
before do
stub_get("/projects/3/notes", "notes")
@notes = Gitlab.notes(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/notes")).to have_been_made
end
it "should return an array of notes" do
expect(@notes).to be_an Array
expect(@notes.first.author.name).to eq("John Smith")
end
end
context "when issue notes" do
before do
stub_get("/projects/3/issues/7/notes", "notes")
@notes = Gitlab.issue_notes(3, 7)
end
it "should get the correct resource" do
expect(a_get("/projects/3/issues/7/notes")).to have_been_made
end
it "should return an array of notes" do
expect(@notes).to be_an Array
expect(@notes.first.author.name).to eq("John Smith")
end
end
context "when snippet notes" do
before do
stub_get("/projects/3/snippets/7/notes", "notes")
@notes = Gitlab.snippet_notes(3, 7)
end
it "should get the correct resource" do
expect(a_get("/projects/3/snippets/7/notes")).to have_been_made
end
it "should return an array of notes" do
expect(@notes).to be_an Array
expect(@notes.first.author.name).to eq("John Smith")
end
end
end
describe "note" do
context "when wall note" do
before do
stub_get("/projects/3/notes/1201", "note")
@note = Gitlab.note(3, 1201)
end
it "should get the correct resource" do
expect(a_get("/projects/3/notes/1201")).to have_been_made
end
it "should return information about a note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
context "when issue note" do
before do
stub_get("/projects/3/issues/7/notes/1201", "note")
@note = Gitlab.issue_note(3, 7, 1201)
end
it "should get the correct resource" do
expect(a_get("/projects/3/issues/7/notes/1201")).to have_been_made
end
it "should return information about a note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
context "when snippet note" do
before do
stub_get("/projects/3/snippets/7/notes/1201", "note")
@note = Gitlab.snippet_note(3, 7, 1201)
end
it "should get the correct resource" do
expect(a_get("/projects/3/snippets/7/notes/1201")).to have_been_made
end
it "should return information about a note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
end
describe "create note" do
context "when wall note" do
before do
stub_post("/projects/3/notes", "note")
@note = Gitlab.create_note(3, "The solution is rather tricky")
end
it "should get the correct resource" do
expect(a_post("/projects/3/notes").
with(:body => {:body => 'The solution is rather tricky'})).to have_been_made
end
it "should return information about a created note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
context "when issue note" do
before do
stub_post("/projects/3/issues/7/notes", "note")
@note = Gitlab.create_issue_note(3, 7, "The solution is rather tricky")
end
it "should get the correct resource" do
expect(a_post("/projects/3/issues/7/notes").
with(:body => {:body => 'The solution is rather tricky'})).to have_been_made
end
it "should return information about a created note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
context "when snippet note" do
before do
stub_post("/projects/3/snippets/7/notes", "note")
@note = Gitlab.create_snippet_note(3, 7, "The solution is rather tricky")
end
it "should get the correct resource" do
expect(a_post("/projects/3/snippets/7/notes").
with(:body => {:body => 'The solution is rather tricky'})).to have_been_made
end
it "should return information about a created note" do
expect(@note.body).to eq("The solution is rather tricky")
expect(@note.author.name).to eq("John Smith")
end
end
end
end

View File

@@ -0,0 +1,357 @@
require 'spec_helper'
describe Gitlab::Client do
describe ".projects" do
before do
stub_get("/projects", "projects")
@projects = Gitlab.projects
end
it "should get the correct resource" do
expect(a_get("/projects")).to have_been_made
end
it "should return an array of projects" do
expect(@projects).to be_an Array
expect(@projects.first.name).to eq("Brute")
expect(@projects.first.owner.name).to eq("John Smith")
end
end
describe ".project" do
before do
stub_get("/projects/3", "project")
@project = Gitlab.project(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3")).to have_been_made
end
it "should return information about a project" do
expect(@project.name).to eq("Gitlab")
expect(@project.owner.name).to eq("John Smith")
end
end
describe ".project_events" do
before do
stub_get("/projects/2/events", "project_events")
@events = Gitlab.project_events(2)
end
it "should get the correct resource" do
expect(a_get("/projects/2/events")).to have_been_made
end
it "should return an array of events" do
expect(@events).to be_an Array
expect(@events.size).to eq(2)
end
it "should return the action name of the event" do
expect(@events.first.action_name).to eq("opened")
end
end
describe ".create_project" do
before do
stub_post("/projects", "project")
@project = Gitlab.create_project('Gitlab')
end
it "should get the correct resource" do
expect(a_post("/projects")).to have_been_made
end
it "should return information about a created project" do
expect(@project.name).to eq("Gitlab")
expect(@project.owner.name).to eq("John Smith")
end
end
describe ".create_project for user" do
before do
stub_post("/users", "user")
@owner = Gitlab.create_user("john@example.com", "pass", {name: 'John Owner'})
stub_post("/projects/user/#{@owner.id}", "project_for_user")
@project = Gitlab.create_project('Brute', {:user_id => @owner.id})
end
it "should return information about a created project" do
expect(@project.name).to eq("Brute")
expect(@project.owner.name).to eq("John Owner")
end
end
describe ".delete_project" do
before do
stub_delete("/projects/Gitlab", "project")
@project = Gitlab.delete_project('Gitlab')
end
it "should get the correct resource" do
expect(a_delete("/projects/Gitlab")).to have_been_made
end
it "should return information about a deleted project" do
expect(@project.name).to eq("Gitlab")
expect(@project.owner.name).to eq("John Smith")
end
end
describe ".team_members" do
before do
stub_get("/projects/3/members", "team_members")
@team_members = Gitlab.team_members(3)
end
it "should get the correct resource" do
expect(a_get("/projects/3/members")).to have_been_made
end
it "should return an array of team members" do
expect(@team_members).to be_an Array
expect(@team_members.first.name).to eq("John Smith")
end
end
describe ".team_member" do
before do
stub_get("/projects/3/members/1", "team_member")
@team_member = Gitlab.team_member(3, 1)
end
it "should get the correct resource" do
expect(a_get("/projects/3/members/1")).to have_been_made
end
it "should return information about a team member" do
expect(@team_member.name).to eq("John Smith")
end
end
describe ".add_team_member" do
before do
stub_post("/projects/3/members", "team_member")
@team_member = Gitlab.add_team_member(3, 1, 40)
end
it "should get the correct resource" do
expect(a_post("/projects/3/members").
with(:body => {:user_id => '1', :access_level => '40'})).to have_been_made
end
it "should return information about an added team member" do
expect(@team_member.name).to eq("John Smith")
end
end
describe ".edit_team_member" do
before do
stub_put("/projects/3/members/1", "team_member")
@team_member = Gitlab.edit_team_member(3, 1, 40)
end
it "should get the correct resource" do
expect(a_put("/projects/3/members/1").
with(:body => {:access_level => '40'})).to have_been_made
end
it "should return information about an edited team member" do
expect(@team_member.name).to eq("John Smith")
end
end
describe ".remove_team_member" do
before do
stub_delete("/projects/3/members/1", "team_member")
@team_member = Gitlab.remove_team_member(3, 1)
end
it "should get the correct resource" do
expect(a_delete("/projects/3/members/1")).to have_been_made
end
it "should return information about a removed team member" do
expect(@team_member.name).to eq("John Smith")
end
end
describe ".project_hooks" do
before do
stub_get("/projects/1/hooks", "project_hooks")
@hooks = Gitlab.project_hooks(1)
end
it "should get the correct resource" do
expect(a_get("/projects/1/hooks")).to have_been_made
end
it "should return an array of hooks" do
expect(@hooks).to be_an Array
expect(@hooks.first.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
describe ".project_hook" do
before do
stub_get("/projects/1/hooks/1", "project_hook")
@hook = Gitlab.project_hook(1, 1)
end
it "should get the correct resource" do
expect(a_get("/projects/1/hooks/1")).to have_been_made
end
it "should return information about a hook" do
expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
describe ".add_project_hook" do
context "without specified events" do
before do
stub_post("/projects/1/hooks", "project_hook")
@hook = Gitlab.add_project_hook(1, "https://api.example.net/v1/webhooks/ci")
end
it "should get the correct resource" do
body = {:url => "https://api.example.net/v1/webhooks/ci"}
expect(a_post("/projects/1/hooks").with(:body => body)).to have_been_made
end
it "should return information about an added hook" do
expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
context "with specified events" do
before do
stub_post("/projects/1/hooks", "project_hook")
@hook = Gitlab.add_project_hook(1, "https://api.example.net/v1/webhooks/ci", push_events: true, merge_requests_events: true)
end
it "should get the correct resource" do
body = {:url => "https://api.example.net/v1/webhooks/ci", push_events: "true", merge_requests_events: "true"}
expect(a_post("/projects/1/hooks").with(:body => body)).to have_been_made
end
it "should return information about an added hook" do
expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
end
describe ".edit_project_hook" do
before do
stub_put("/projects/1/hooks/1", "project_hook")
@hook = Gitlab.edit_project_hook(1, 1, "https://api.example.net/v1/webhooks/ci")
end
it "should get the correct resource" do
body = {:url => "https://api.example.net/v1/webhooks/ci"}
expect(a_put("/projects/1/hooks/1").with(:body => body)).to have_been_made
end
it "should return information about an edited hook" do
expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
describe ".delete_project_hook" do
before do
stub_delete("/projects/1/hooks/1", "project_hook")
@hook = Gitlab.delete_project_hook(1, 1)
end
it "should get the correct resource" do
expect(a_delete("/projects/1/hooks/1")).to have_been_made
end
it "should return information about a deleted hook" do
expect(@hook.url).to eq("https://api.example.net/v1/webhooks/ci")
end
end
describe ".make_forked_from" do
before do
stub_post("/projects/42/fork/24", "project_fork_link")
@forked_project_link = Gitlab.make_forked_from(42, 24)
end
it "should get the correct resource" do
expect(a_post("/projects/42/fork/24")).to have_been_made
end
it "should return information about a forked project" do
expect(@forked_project_link.forked_from_project_id).to eq(24)
expect(@forked_project_link.forked_to_project_id).to eq(42)
end
end
describe ".remove_forked" do
before do
stub_delete("/projects/42/fork", "project_fork_link")
@forked_project_link = Gitlab.remove_forked(42)
end
it "should be sent to correct resource" do
expect(a_delete("/projects/42/fork")).to have_been_made
end
it "should return information about an unforked project" do
expect(@forked_project_link.forked_to_project_id).to eq(42)
end
end
describe ".deploy_keys" do
before do
stub_get("/projects/42/keys", "project_keys")
@deploy_keys = Gitlab.deploy_keys(42)
end
it "should get the correct resource" do
expect(a_get("/projects/42/keys")).to have_been_made
end
it "should return project deploy keys" do
expect(@deploy_keys).to be_an Array
expect(@deploy_keys.first.id).to eq 2
expect(@deploy_keys.first.title).to eq "Key Title"
expect(@deploy_keys.first.key).to match(/ssh-rsa/)
end
end
describe ".deploy_key" do
before do
stub_get("/projects/42/keys/2", "project_key")
@deploy_key = Gitlab.deploy_key(42, 2)
end
it "should get the correct resource" do
expect(a_get("/projects/42/keys/2")).to have_been_made
end
it "should return project deploy key" do
expect(@deploy_key.id).to eq 2
expect(@deploy_key.title).to eq "Key Title"
expect(@deploy_key.key).to match(/ssh-rsa/)
end
end
describe ".delete_deploy_key" do
before do
stub_delete("/projects/42/keys/2", "project_delete_key")
@deploy_key = Gitlab.delete_deploy_key(42, 2)
end
it "should get the correct resource" do
expect(a_delete("/projects/42/keys/2")).to have_been_made
end
it "should return information about a deleted key" do
expect(@deploy_key.id).to eq(2)
end
end
end

Some files were not shown because too many files have changed in this diff Show More