Merge branch 'master' into fixes/api, code clean up and tests fixed
Conflicts: doc/api/projects.md spec/requests/api/projects_spec.rb
This commit is contained in:
commit
3374027e3a
4
Capfile.example
Normal file
4
Capfile.example
Normal file
|
@ -0,0 +1,4 @@
|
|||
load 'deploy'
|
||||
load 'deploy/assets'
|
||||
require 'bundler/capistrano'
|
||||
load 'config/deploy'
|
5
Gemfile
5
Gemfile
|
@ -1,4 +1,4 @@
|
|||
source "http://rubygems.org"
|
||||
source "https://rubygems.org"
|
||||
|
||||
def darwin_only(require_as)
|
||||
RUBY_PLATFORM.include?('darwin') && require_as
|
||||
|
@ -103,6 +103,9 @@ gem 'settingslogic'
|
|||
gem "foreman"
|
||||
gem "git"
|
||||
|
||||
# Cache
|
||||
gem "redis-rails"
|
||||
|
||||
group :assets do
|
||||
gem "sass-rails", "~> 3.2.5"
|
||||
gem "coffee-rails", "~> 3.2.2"
|
||||
|
|
19
Gemfile.lock
19
Gemfile.lock
|
@ -13,7 +13,7 @@ GIT
|
|||
raphael-rails (2.1.0)
|
||||
|
||||
GEM
|
||||
remote: http://rubygems.org/
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
actionmailer (3.2.12)
|
||||
actionpack (= 3.2.12)
|
||||
|
@ -329,8 +329,24 @@ GEM
|
|||
json (~> 1.4)
|
||||
redcarpet (2.2.2)
|
||||
redis (3.0.2)
|
||||
redis-actionpack (3.2.3)
|
||||
actionpack (~> 3.2.3)
|
||||
redis-rack (~> 1.4.0)
|
||||
redis-store (~> 1.1.0)
|
||||
redis-activesupport (3.2.3)
|
||||
activesupport (~> 3.2.3)
|
||||
redis-store (~> 1.1.0)
|
||||
redis-namespace (1.2.1)
|
||||
redis (~> 3.0.0)
|
||||
redis-rack (1.4.2)
|
||||
rack (~> 1.4.1)
|
||||
redis-store (~> 1.1.0)
|
||||
redis-rails (3.2.3)
|
||||
redis-actionpack (~> 3.2.3)
|
||||
redis-activesupport (~> 3.2.3)
|
||||
redis-store (~> 1.1.0)
|
||||
redis-store (1.1.3)
|
||||
redis (>= 2.2.0)
|
||||
request_store (1.0.5)
|
||||
rspec (2.12.0)
|
||||
rspec-core (~> 2.12.0)
|
||||
|
@ -504,6 +520,7 @@ DEPENDENCIES
|
|||
rb-fsevent
|
||||
rb-inotify
|
||||
redcarpet (~> 2.2.2)
|
||||
redis-rails
|
||||
rspec-rails (= 2.12.2)
|
||||
sass-rails (~> 3.2.5)
|
||||
sdoc
|
||||
|
|
31
README.md
31
README.md
|
@ -5,14 +5,14 @@
|
|||
### GitLab allows you to
|
||||
* keep your code secure on your own server
|
||||
* manage repositories, users and access permissions
|
||||
* communicate though issues, line-comments and wiki's
|
||||
* perform code reviews with merge requests
|
||||
* communicate through issues, line-comments and wiki pages
|
||||
* perform code review with merge requests
|
||||
|
||||
### GitLab is
|
||||
|
||||
* powered by Ruby on Rails
|
||||
* completely free and open source (MIT license)
|
||||
* used by 10.000 organization to keep their code secure
|
||||
* used by 10.000 organizations to keep their code secure
|
||||
|
||||
### Code status
|
||||
|
||||
|
@ -34,28 +34,35 @@
|
|||
|
||||
### Requirements
|
||||
|
||||
* Ubuntu/Debian*
|
||||
* Ubuntu/Debian**
|
||||
* ruby 1.9.3+
|
||||
* MySQL
|
||||
* git
|
||||
* gitlab-shell
|
||||
* redis
|
||||
|
||||
* More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
|
||||
** More details are in the [requirements doc](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/requirements.md)
|
||||
|
||||
### Installation
|
||||
|
||||
You can either follow the "ordinary" Installation guide to install it on a machine or use the Vagrant virtual machine. The Installation guide is recommended to set up a production server. The Vargrant virtual machine is recommended for development since it makes it much easier to set up all the dependencies for integration testing.
|
||||
#### For production
|
||||
|
||||
* [Installation guide for latest stable release](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md)
|
||||
Follow the installation guide for production server.
|
||||
|
||||
* [Installation guide for the current master branch](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
|
||||
* [Installation guide for latest stable release (4.2)](https://github.com/gitlabhq/gitlabhq/blob/4-2-stable/doc/install/installation.md) - **Recommended**
|
||||
|
||||
* [Installation guide for the current master branch (5.0)](https://github.com/gitlabhq/gitlabhq/blob/master/doc/install/installation.md)
|
||||
|
||||
|
||||
#### For development
|
||||
|
||||
If you want to contribute, please first read our [Contributing Guidelines](https://github.com/gitlabhq/gitlabhq/blob/master/CONTRIBUTING.md) and then we suggest you to use the Vagrant virtual machine project to get an environment working sandboxed and with all dependencies.
|
||||
|
||||
* [Vagrant virtual machine](https://github.com/gitlabhq/gitlab-vagrant-vm)
|
||||
|
||||
### Starting
|
||||
|
||||
1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab with:
|
||||
1. The Installation guide contains instructions to download an init script and run that on boot. With the init script you can also start GitLab
|
||||
|
||||
sudo service gitlab start
|
||||
|
||||
|
@ -63,18 +70,18 @@ You can either follow the "ordinary" Installation guide to install it on a machi
|
|||
|
||||
sudo /etc/init.d/gitlab restart
|
||||
|
||||
2. Start it with [Foreman](https://github.com/ddollar/foreman) in development model
|
||||
2. Start it with [Foreman](https://github.com/ddollar/foreman) in development mode
|
||||
|
||||
bundle exec foreman start -p 3000
|
||||
|
||||
3. Start it manually in development mode
|
||||
or start it manually
|
||||
|
||||
bundle exec rails s
|
||||
bundle exec rake sidekiq:start
|
||||
|
||||
### Running the tests
|
||||
|
||||
* Seed the database with
|
||||
* Seed the database
|
||||
|
||||
bundle exec rake db:setup RAILS_ENV=test
|
||||
bundle exec rake db:seed_fu RAILS_ENV=test
|
||||
|
|
|
@ -11,12 +11,7 @@ $ ->
|
|||
# Make the entire tree-item row clickable, but not if clicking another link (like a commit message)
|
||||
$("#tree-slider .tree-item").live 'click', (e) ->
|
||||
$('.tree-item-file-name a', this).trigger('click') if (e.target.nodeName != "A")
|
||||
|
||||
# Show/Hide the loading spinner
|
||||
$('#tree-slider .tree-item-file-name a, .breadcrumb a, .project-refs-form').live
|
||||
"ajax:beforeSend": -> $('.tree_progress').addClass("loading")
|
||||
"ajax:complete": -> $('.tree_progress').removeClass("loading")
|
||||
|
||||
|
||||
# Maintain forward/back history while browsing the file tree
|
||||
((window) ->
|
||||
History = window.History
|
||||
|
@ -33,7 +28,12 @@ $ ->
|
|||
|
||||
History.Adapter.bind window, 'statechange', ->
|
||||
state = History.getState()
|
||||
window.ajaxGet(state.url)
|
||||
$.ajax({
|
||||
url: state.url,
|
||||
dataType: 'script',
|
||||
beforeSend: -> $('.tree_progress').addClass("loading"),
|
||||
complete: -> $('.tree_progress').removeClass("loading")
|
||||
})
|
||||
)(window)
|
||||
|
||||
# See if there are lines selected
|
||||
|
|
|
@ -34,13 +34,6 @@
|
|||
padding: 15px;
|
||||
word-wrap: break-word;
|
||||
|
||||
pre {
|
||||
background: none !important;
|
||||
margin: 0;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.clearfix {
|
||||
margin: 0;
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
.cgray { color:gray }
|
||||
.cred { color:#D12F19 }
|
||||
.cgreen { color:#4a2 }
|
||||
.cblue { color:#29A }
|
||||
.cblack { color:#111 }
|
||||
.cdark { color:#444 }
|
||||
.cwhite { color:#fff!important }
|
||||
|
|
|
@ -120,3 +120,16 @@ ul.nav.nav-projects-tabs {
|
|||
.team_member_row form {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
.public-projects {
|
||||
li {
|
||||
margin-top: 8px;
|
||||
margin-bottom: 5px;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.description {
|
||||
margin-left: 22px;
|
||||
color: #aaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ class MergeRequest < ActiveRecord::Base
|
|||
|
||||
def validate_branches
|
||||
if target_branch == source_branch
|
||||
errors.add :base, "You can not use same branch for source and target branches"
|
||||
errors.add :branch_conflict, "You can not use same branch for source and target branches"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
class Repository
|
||||
include Gitlab::Popen
|
||||
|
||||
# Repository directory name with namespace direcotry
|
||||
# Examples:
|
||||
# gitlab/gitolite
|
||||
|
@ -147,4 +149,21 @@ class Repository
|
|||
|
||||
file_path
|
||||
end
|
||||
|
||||
# Return repo size in megabytes
|
||||
# Cached in redis
|
||||
def size
|
||||
Rails.cache.fetch(cache_key(:size)) do
|
||||
size = popen('du -s', path_to_repo).first.strip.to_i
|
||||
(size.to_f / 1024).round(2)
|
||||
end
|
||||
end
|
||||
|
||||
def expire_cache
|
||||
Rails.cache.delete(cache_key(:size))
|
||||
end
|
||||
|
||||
def cache_key(type)
|
||||
"#{type}:#{path_with_namespace}"
|
||||
end
|
||||
end
|
||||
|
|
|
@ -23,6 +23,7 @@ class GitPushService
|
|||
|
||||
project.ensure_satellite_exists
|
||||
project.discover_default_branch
|
||||
project.repository.expire_cache
|
||||
|
||||
if push_to_branch?(ref, oldrev)
|
||||
project.update_merge_requests(oldrev, newrev, ref, @user)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
= form_tag(user_omniauth_callback_path(:ldap), :class => "login-box", :id => 'new_ldap_user' ) do
|
||||
= image_tag "login-logo.png", :width => "304", :height => "66", :class => "login-logo", :alt => "Login Logo"
|
||||
= text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login"}
|
||||
= text_field_tag :username, nil, {:class => "text top", :placeholder => "LDAP Login", :autofocus => "autofocus"}
|
||||
= password_field_tag :password, nil, {:class => "text bottom", :placeholder => "Password"}
|
||||
%br/
|
||||
= submit_tag "LDAP Sign in", :class => "btn-primary btn"
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
- if event.proper?
|
||||
%div.event-item
|
||||
%span.cgray.pull-right
|
||||
#{time_ago_in_words(event.created_at)} ago.
|
||||
= cache event do
|
||||
%div.event-item
|
||||
%span.cgray.pull-right
|
||||
#{time_ago_in_words(event.created_at)} ago.
|
||||
|
||||
= image_tag gravatar_icon(event.author_email), class: "avatar s24"
|
||||
= image_tag gravatar_icon(event.author_email), class: "avatar s24"
|
||||
|
||||
- if event.push?
|
||||
= render "events/event/push", event: event
|
||||
.clearfix
|
||||
- elsif event.note?
|
||||
= render "events/event/note", event: event
|
||||
- else
|
||||
= render "events/event/common", event: event
|
||||
- if event.push?
|
||||
= render "events/event/push", event: event
|
||||
.clearfix
|
||||
- elsif event.note?
|
||||
= render "events/event/note", event: event
|
||||
- else
|
||||
= render "events/event/common", event: event
|
||||
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
= link_to "Milestones", "#milestones", 'data-toggle' => 'tab'
|
||||
%li
|
||||
= link_to "Notes", "#notes", 'data-toggle' => 'tab'
|
||||
%li
|
||||
= link_to "System Hooks", "#system_hooks", 'data-toggle' => 'tab'
|
||||
|
||||
.tab-content
|
||||
.tab-pane.active#README
|
||||
|
@ -103,3 +105,12 @@
|
|||
.file_content.wiki
|
||||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "notes.md"))
|
||||
|
||||
.tab-pane#system_hooks
|
||||
.file_holder
|
||||
.file_title
|
||||
%i.icon-file
|
||||
System Hooks
|
||||
.file_content.wiki
|
||||
= preserve do
|
||||
= markdown File.read(Rails.root.join("doc", "api", "system_hooks.md"))
|
||||
|
|
|
@ -22,7 +22,7 @@
|
|||
= mail_to Gitlab.config.gitlab.support_email, "support contact"
|
||||
%li
|
||||
Use the
|
||||
= link_to "search bar", '#', onclick: "$("#search").focus();"
|
||||
= link_to "search bar", '#', onclick: "$('#search').focus();"
|
||||
on the top of this page
|
||||
%li
|
||||
Ask in our
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
= link_to root_path, class: "home" do
|
||||
%h1 GITLAB
|
||||
%span.separator
|
||||
%h1.project_name Public Projects
|
||||
%h1.project_name Public Projects
|
||||
.container
|
||||
.content
|
||||
.prepend-top-20
|
||||
|
|
|
@ -9,11 +9,19 @@
|
|||
Project name is
|
||||
.input
|
||||
= f.text_field :name, placeholder: "Example Project", class: "xxlarge"
|
||||
|
||||
|
||||
- unless @repository.heads.empty?
|
||||
.clearfix
|
||||
= f.label :default_branch, "Default Branch"
|
||||
.input= f.select(:default_branch, @repository.heads.map(&:name), {}, style: "width:210px;")
|
||||
|
||||
.clearfix
|
||||
= f.label :description do
|
||||
Project description
|
||||
%span.light (optional)
|
||||
.input
|
||||
= f.text_area :description, placeholder: "awesome project", class: "xxlarge", rows: 3, maxlength: 250
|
||||
|
||||
%fieldset.features
|
||||
%legend Features:
|
||||
|
|
|
@ -1,8 +1,33 @@
|
|||
= render "project_head"
|
||||
= render 'clone_panel'
|
||||
= render "events/event_last_push", event: @last_push
|
||||
.content_list= render @events
|
||||
.loading.hide
|
||||
|
||||
.row
|
||||
.span9
|
||||
.content_list= render @events
|
||||
.loading.hide
|
||||
.span3
|
||||
.ui-box.white
|
||||
.padded
|
||||
%h3.page_title
|
||||
= @project.name
|
||||
- if @project.description.present?
|
||||
%p.light= @project.description
|
||||
|
||||
%hr
|
||||
%p
|
||||
Access level:
|
||||
- if @project.public
|
||||
%span.cblue
|
||||
%i.icon-share
|
||||
Public
|
||||
- else
|
||||
%span.cgreen
|
||||
%i.icon-lock
|
||||
Private
|
||||
|
||||
%p Repo Size: #{@project.repository.size} MB
|
||||
%p Created at: #{@project.created_at.stamp('Aug 22, 2013')}
|
||||
%p Owner: #{link_to @project.owner_name, @project.owner}
|
||||
:javascript
|
||||
$(function(){ Pager.init(20); });
|
||||
|
|
|
@ -1,18 +1,20 @@
|
|||
%h3.page_title
|
||||
Projects
|
||||
Projects (#{@projects.total_count})
|
||||
%small with read-only access
|
||||
%hr
|
||||
|
||||
%ul.unstyled
|
||||
- @projects.each do |project|
|
||||
%li.clearfix
|
||||
%h5
|
||||
%i.icon-share
|
||||
= project.name_with_namespace
|
||||
.pull-right
|
||||
%pre.dark.tiny git clone #{project.http_url_to_repo}
|
||||
.public-projects
|
||||
%ul.unstyled
|
||||
- @projects.each do |project|
|
||||
%li.clearfix
|
||||
%h5
|
||||
%i.icon-share
|
||||
= project.name_with_namespace
|
||||
.pull-right
|
||||
%pre.dark.tiny git clone #{project.http_url_to_repo}
|
||||
%p.description
|
||||
= project.description
|
||||
- unless @projects.present?
|
||||
%h3.nothing_here_message No public projects
|
||||
|
||||
- unless @projects.present?
|
||||
%h3.nothing_here_message No public projects
|
||||
|
||||
= paginate @projects, theme: "admin"
|
||||
= paginate @projects, theme: "admin"
|
||||
|
|
|
@ -11,9 +11,6 @@
|
|||
- else
|
||||
= link_to title, '#'
|
||||
|
||||
.clear
|
||||
%div.tree_progress
|
||||
|
||||
%div#tree-content-holder.tree-content-holder
|
||||
- if tree.is_blob?
|
||||
= render "tree/blob", blob: tree
|
||||
|
@ -40,6 +37,8 @@
|
|||
- if tree.readme
|
||||
= render "tree/readme", readme: tree.readme
|
||||
|
||||
%div.tree_progress
|
||||
|
||||
- unless tree.is_blob?
|
||||
:javascript
|
||||
// Load last commit log for each file in tree
|
||||
|
|
72
config/deploy.rb.example
Normal file
72
config/deploy.rb.example
Normal file
|
@ -0,0 +1,72 @@
|
|||
set :domain, 'set application domain here'
|
||||
set :db_adapter, 'mysql' # or postgres
|
||||
set :mount_point, '/'
|
||||
set :application, 'gitlabhq'
|
||||
set :user, 'git'
|
||||
set :rails_env, 'production'
|
||||
set :deploy_to, "/home/#{user}/apps/#{application}"
|
||||
set :bundle_without, %w[development test] + (%w[mysql postgres] - [db_adapter])
|
||||
set :asset_env, "RAILS_GROUPS=assets RAILS_RELATIVE_URL_ROOT=#{mount_point.sub /\/+\Z/, ''}"
|
||||
|
||||
set :use_sudo, false
|
||||
default_run_options[:pty] = true
|
||||
|
||||
# Or: `accurev`, `bzr`, `cvs`, `darcs`, `git`, `mercurial`, `perforce`, `subversion` or `none`
|
||||
set :scm, :git
|
||||
set :repository, "git@#{domain}:#{application}.git"
|
||||
set :deploy_via, :remote_cache
|
||||
|
||||
# Alternatively, you can deploy via copy, if you don't have gitlab in git
|
||||
#set :scm, :none
|
||||
#set :repository, '.'
|
||||
#set :deploy_via, :copy
|
||||
|
||||
server domain, :app, :web, :db, primary: true
|
||||
|
||||
namespace :foreman do
|
||||
desc 'Export the Procfile to Ubuntu upstart scripts'
|
||||
task :export, roles: :app do
|
||||
foreman_export = "foreman export upstart /etc/init -f Procfile -a #{application} -u #{user} -l #{shared_path}/log/foreman"
|
||||
run "cd #{release_path} && #{sudo} #{fetch :bundle_cmd, 'bundle'} exec #{foreman_export}"
|
||||
end
|
||||
|
||||
desc 'Start the application services'
|
||||
task :start, roles: :app do
|
||||
run "#{sudo} service #{application} start"
|
||||
end
|
||||
|
||||
desc 'Stop the application services'
|
||||
task :stop, roles: :app do
|
||||
run "#{sudo} service #{application} stop"
|
||||
end
|
||||
|
||||
desc 'Restart the application services'
|
||||
task :restart, roles: :app do
|
||||
run "#{sudo} service #{application} restart"
|
||||
end
|
||||
end
|
||||
|
||||
namespace :deploy do
|
||||
desc 'Start the application services'
|
||||
task :start, roles: :app do
|
||||
foreman.start
|
||||
end
|
||||
|
||||
desc 'Stop the application services'
|
||||
task :stop, roles: :app do
|
||||
foreman.stop
|
||||
end
|
||||
|
||||
desc 'Restart the application services'
|
||||
task :restart, roles: :app do
|
||||
foreman.restart
|
||||
end
|
||||
end
|
||||
|
||||
after 'deploy:cold' do
|
||||
run "cd #{release_path} && #{rake} gitlab:setup force=yes RAILS_ENV=#{rails_env}"
|
||||
deploy.restart
|
||||
end
|
||||
|
||||
after 'deploy:update', 'foreman:export' # Export foreman scripts
|
||||
#after 'deploy:update', 'foreman:restart' # Restart application scripts
|
|
@ -40,7 +40,7 @@ Gitlab::Application.configure do
|
|||
# config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
|
||||
|
||||
# Use a different cache store in production
|
||||
config.cache_store = :memory_store
|
||||
config.cache_store = :redis_store
|
||||
|
||||
# Enable serving of images, stylesheets, and JavaScripts from an asset server
|
||||
# config.action_controller.asset_host = "http://assets.example.com"
|
||||
|
|
|
@ -4,19 +4,19 @@ config_file = Rails.root.join('config', 'resque.yml')
|
|||
resque_url = if File.exists?(config_file)
|
||||
YAML.load_file(config_file)[Rails.env]
|
||||
else
|
||||
"localhost:6379"
|
||||
"redis://localhost:6379"
|
||||
end
|
||||
|
||||
Sidekiq.configure_server do |config|
|
||||
config.redis = {
|
||||
url: "redis://#{resque_url}",
|
||||
url: resque_url,
|
||||
namespace: 'resque:gitlab'
|
||||
}
|
||||
end
|
||||
|
||||
Sidekiq.configure_client do |config|
|
||||
config.redis = {
|
||||
url: "redis://#{resque_url}",
|
||||
url: resque_url,
|
||||
namespace: 'resque:gitlab'
|
||||
}
|
||||
end
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
development: localhost:6379
|
||||
test: localhost:6379
|
||||
production: redis.example.com:6379
|
||||
development: redis://localhost:6379
|
||||
test: redis://localhost:6379
|
||||
production: redis://redis.example.com:6379
|
||||
|
|
|
@ -166,7 +166,7 @@ Gitlab::Application.routes.draw do
|
|||
#
|
||||
# Project Area
|
||||
#
|
||||
resources :projects, constraints: { id: /[a-zA-Z.0-9_\-\/]+/ }, except: [:new, :create, :index], path: "/" do
|
||||
resources :projects, constraints: { id: /(?:[a-zA-Z.0-9_\-]+\/)?[a-zA-Z.0-9_\-]+/ }, except: [:new, :create, :index], path: "/" do
|
||||
member do
|
||||
get "wall"
|
||||
get "files"
|
||||
|
@ -175,10 +175,10 @@ Gitlab::Application.routes.draw do
|
|||
resources :blob, only: [:show], constraints: {id: /.+/}
|
||||
resources :tree, only: [:show, :edit, :update], constraints: {id: /.+/}
|
||||
resources :commit, only: [:show], constraints: {id: /[[:alnum:]]{6,40}/}
|
||||
resources :commits, only: [:show], constraints: {id: /.+/}
|
||||
resources :commits, only: [:show], constraints: {id: /(?:[^.]|\.(?!atom$))+/, format: /atom/}
|
||||
resources :compare, only: [:index, :create]
|
||||
resources :blame, only: [:show], constraints: {id: /.+/}
|
||||
resources :graph, only: [:show], constraints: {id: /.+/}
|
||||
resources :graph, only: [:show], constraints: {id: /(?:[^.]|\.(?!json$))+/, format: /json/}
|
||||
match "/compare/:from...:to" => "compare#show", as: "compare",
|
||||
:via => [:get, :post], constraints: {from: /.+/, to: /.+/}
|
||||
|
||||
|
|
|
@ -31,13 +31,10 @@ The API uses JSON to serialize data. You don't need to specify `.json` at the en
|
|||
|
||||
## Status codes
|
||||
|
||||
API requests return different status codes according to
|
||||
|
||||
The API is designed to provide status codes according to the context and how the request
|
||||
is handled. For example if a `GET` request is successful a status code `200 Ok`
|
||||
is returned. The API is designed to be RESTful.
|
||||
|
||||
The following list gives an overview of how the API functions are designed.
|
||||
The API is designed to return different status codes according to context and action. In this way
|
||||
if a request results in an error the caller is able to get insight into what went wrong, e.g.
|
||||
status code `400 Bad Request` is returned if a required attribute is missing from the request.
|
||||
The following list gives an overview of how the API functions generally behave.
|
||||
|
||||
API request types:
|
||||
|
||||
|
@ -58,7 +55,7 @@ Return values:
|
|||
* `403 Forbidden` - The request is not allowed, e.g. the user is not allowed to delete a project
|
||||
* `404 Not Found` - A resource could not be accessed, e.g. an ID for a resource could not be found
|
||||
* `405 Method Not Allowed` - The request is not supported
|
||||
* `409 Conflict` - A conflicting resource already exists, a project with same name already exists
|
||||
* `409 Conflict` - A conflicting resource already exists, e.g. creating a project with a name that already exists
|
||||
* `500 Server Error` - While handling the request something went wrong on the server side
|
||||
|
||||
|
||||
|
|
|
@ -44,3 +44,14 @@ Parameters:
|
|||
+ `name` (required) - The name of the group
|
||||
+ `path` (required) - The path of the group
|
||||
|
||||
## Transfer project to group
|
||||
|
||||
Transfer a project to the Group namespace. Available only for admin
|
||||
|
||||
```
|
||||
POST /groups/:id/projects/:project_id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
+ `id` (required) - The ID of a group
|
||||
+ `project_id (required) - The ID of a project
|
||||
|
|
|
@ -115,11 +115,9 @@ Parameters:
|
|||
+ `merge_requests_enabled` (optional) - enabled by default
|
||||
+ `wiki_enabled` (optional) - enabled by default
|
||||
|
||||
**Project access levels**
|
||||
|
||||
## Project access levels
|
||||
|
||||
The project access levels are defined in the `user_project` class. Currently, 4
|
||||
levels are recoginized:
|
||||
The project access levels are defined in the `user_project.rb` class. Currently, these levels are recoginized:
|
||||
|
||||
```
|
||||
GUEST = 10
|
||||
|
@ -129,7 +127,30 @@ levels are recoginized:
|
|||
```
|
||||
|
||||
|
||||
## List project team members
|
||||
### Create project for user
|
||||
|
||||
Creates a new project owned by user. Available only for admins.
|
||||
|
||||
```
|
||||
POST /projects/user/:user_id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `user_id` (required) - user_id of owner
|
||||
+ `name` (required) - new project name
|
||||
+ `description` (optional) - short project description
|
||||
+ `default_branch` (optional) - 'master' by default
|
||||
+ `issues_enabled` (optional) - enabled by default
|
||||
+ `wall_enabled` (optional) - enabled by default
|
||||
+ `merge_requests_enabled` (optional) - enabled by default
|
||||
+ `wiki_enabled` (optional) - enabled by default
|
||||
|
||||
|
||||
|
||||
## Team members
|
||||
|
||||
### List project team members
|
||||
|
||||
Get a list of project team members.
|
||||
|
||||
|
@ -140,14 +161,12 @@ GET /projects/:id/members
|
|||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID or NAME of a project
|
||||
+ `query` - Query string
|
||||
+ `query` (optional) - Query string to search for members
|
||||
|
||||
|
||||
## Team members
|
||||
|
||||
### Get project team member
|
||||
|
||||
Get a project team member.
|
||||
Gets a project team member.
|
||||
|
||||
```
|
||||
GET /projects/:id/members/:user_id
|
||||
|
@ -175,7 +194,7 @@ Parameters:
|
|||
|
||||
Adds a user to a project team. This is an idempotent method and can be called multiple times
|
||||
with the same parameters. Adding team membership to a user that is already a member does not
|
||||
affect the membership.
|
||||
affect the existing membership.
|
||||
|
||||
```
|
||||
POST /projects/:id/members
|
||||
|
@ -190,7 +209,7 @@ Parameters:
|
|||
|
||||
### Edit project team member
|
||||
|
||||
Update project team member to specified access level.
|
||||
Updates project team member to a specified access level.
|
||||
|
||||
```
|
||||
PUT /projects/:id/members/:user_id
|
||||
|
@ -398,81 +417,90 @@ Returns values:
|
|||
+ `404 Not Found` if project with id or the branch with `ref_name` not found
|
||||
|
||||
|
||||
## Snippets
|
||||
|
||||
### List snippets
|
||||
## Deploy Keys
|
||||
|
||||
Lists the snippets of a project.
|
||||
### List deploy keys
|
||||
|
||||
Get a list of a project's deploy keys.
|
||||
|
||||
```
|
||||
GET /projects/:id/snippets
|
||||
GET /projects/:id/keys
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of the project
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id": 1,
|
||||
"title" : "Public key"
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
|
||||
596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
|
||||
soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0=",
|
||||
},
|
||||
{
|
||||
"id": 3,
|
||||
"title" : "Another Public key"
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
|
||||
596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
|
||||
soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
### List single snippet
|
||||
|
||||
Lists a single snippet of a project
|
||||
### Single deploy key
|
||||
|
||||
Get a single key.
|
||||
|
||||
```
|
||||
GET /projects/:id/snippets/:snippet_id
|
||||
GET /projects/:id/keys/:key_id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of the project
|
||||
+ `snippet_id` (required) - The ID of the snippet
|
||||
+ `key_id` (required) - The ID of the deploy key
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"title" : "Public key"
|
||||
"key": "ssh-rsa AAAAB3NzaC1yc2EAAAABJQAAAIEAiPWx6WM4lhHNedGfBpPJNPpZ7yKu+dnn1SJejgt4
|
||||
596k6YjzGGphH2TUxwKzxcKDKKezwkpfnxPkSMkuEspGRt/aZZ9wa++Oi7Qkr8prgHc4
|
||||
soW6NUlfDzpvZK2H5E7eQaSeP3SAwGmQKUFHCddNaP0L+hM7zhFNzjFvpaMgJw0="
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### Create snippet
|
||||
### Add deploy key
|
||||
|
||||
Creates a new project snippet.
|
||||
Creates a new deploy key for a project.
|
||||
|
||||
```
|
||||
POST /projects/:id/snippets
|
||||
POST /projects/:id/keys
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of the project
|
||||
+ `title` (required) - The title of the new snippet
|
||||
+ `file_name` (required) - The file name of the snippet
|
||||
+ `code` (required) - The content of the snippet
|
||||
+ `lifetime` (optional) - The expiration date of a snippet
|
||||
+ `title` (required) - New deploy key's title
|
||||
+ `key` (required) - New deploy key
|
||||
|
||||
|
||||
### Update snippet
|
||||
### Delete deploy key
|
||||
|
||||
Updates an existing project snippet.
|
||||
Delete a deploy key from a project
|
||||
|
||||
```
|
||||
PUT /projects/:id/snippets/:snippet_id
|
||||
DELETE /projects/:id/keys/:key_id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of the project
|
||||
+ `snippet_id` (required) - The id of the project snippet
|
||||
+ `title` (optional) - The new title of the project snippet
|
||||
+ `file_name` (optional) - The new file name of the project snippet
|
||||
+ `lifetime` (optional) - The new expiration date of the snippet
|
||||
+ `code` (optional) - The content of the snippet
|
||||
|
||||
|
||||
## Delete snippet
|
||||
|
||||
Deletes a project snippet. This is an idempotent function call and returns `200 Ok`
|
||||
even if the snippet with the id is not available.
|
||||
|
||||
```
|
||||
DELETE /projects/:id/snippets/:snippet_id
|
||||
```
|
||||
|
||||
Paramaters:
|
||||
|
||||
+ `id` (required) - The ID of the project
|
||||
+ `snippet_id` (required) - The ID of the snippet
|
||||
+ `key_id` (required) - The ID of the deploy key
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ Parameters:
|
|||
|
||||
## Create new snippet
|
||||
|
||||
Creates a new project snippet.
|
||||
Creates a new project snippet. The user must have permission to create new snippets.
|
||||
|
||||
```
|
||||
POST /projects/:id/snippets
|
||||
|
@ -61,9 +61,9 @@ Parameters:
|
|||
+ `code` (required) - The content of a snippet
|
||||
|
||||
|
||||
## Edit snippet
|
||||
## Update snippet
|
||||
|
||||
Updates an existing project snippet.
|
||||
Updates an existing project snippet. The user must have permission to change an existing snippet.
|
||||
|
||||
```
|
||||
PUT /projects/:id/snippets/:snippet_id
|
||||
|
@ -96,7 +96,7 @@ Parameters:
|
|||
|
||||
## Snippet content
|
||||
|
||||
Get a raw project snippet.
|
||||
Returns the raw project snippet as plain text.
|
||||
|
||||
```
|
||||
GET /projects/:id/snippets/:snippet_id/raw
|
||||
|
|
47
doc/api/system_hooks.md
Normal file
47
doc/api/system_hooks.md
Normal file
|
@ -0,0 +1,47 @@
|
|||
All methods require admin authorization.
|
||||
|
||||
## List system hooks
|
||||
|
||||
Get list of system hooks
|
||||
|
||||
```
|
||||
GET /hooks
|
||||
```
|
||||
|
||||
Will return hooks with status `200 OK` on success, or `404 Not found` on fail.
|
||||
|
||||
## Add new system hook hook
|
||||
|
||||
```
|
||||
POST /hooks
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `url` (required) - The hook URL
|
||||
|
||||
Will return status `201 Created` on success, or `404 Not found` on fail.
|
||||
|
||||
## Test system hook
|
||||
|
||||
```
|
||||
GET /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
|
||||
Will return hook with status `200 OK` on success, or `404 Not found` on fail.
|
||||
|
||||
## Delete system hook
|
||||
|
||||
```
|
||||
DELETE /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
|
||||
Will return status `200 OK` on success, or `404 Not found` on fail.
|
|
@ -235,6 +235,23 @@ Parameters:
|
|||
+ `key` (required) - new SSH key
|
||||
|
||||
|
||||
## Add SSH key for user
|
||||
|
||||
Create new key owned by specified user. Available only for admin
|
||||
|
||||
```
|
||||
POST /users/:id/keys
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - id of specified user
|
||||
+ `title` (required) - new SSH Key's title
|
||||
+ `key` (required) - new SSH key
|
||||
|
||||
Will return created key with status `201 Created` on success, or `404 Not
|
||||
found` on fail.
|
||||
|
||||
## Delete SSH key
|
||||
|
||||
Deletes key owned by currently authenticated user. This is an idempotent function and calling it on a key that is already
|
||||
|
|
|
@ -288,7 +288,7 @@ a different host, you can configure its connection string via the
|
|||
`config/resque.yml` file.
|
||||
|
||||
# example
|
||||
production: redis.example.tld:6379
|
||||
production: redis://redis.example.tld:6379
|
||||
|
||||
## Custom SSH Connection
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
|
|||
|
||||
And 'I switch ref to "stable"' do
|
||||
page.select 'stable', :from => 'ref'
|
||||
sleep 2
|
||||
end
|
||||
|
||||
And 'page should select "stable" in select box' do
|
||||
|
@ -44,6 +45,7 @@ class ProjectNetworkGraph < Spinach::FeatureSteps
|
|||
fill_in 'q', :with => '98d6492'
|
||||
find('button').click
|
||||
end
|
||||
sleep 2
|
||||
end
|
||||
|
||||
And 'page should have "v2.1.0" on graph' do
|
||||
|
|
|
@ -33,5 +33,6 @@ module Gitlab
|
|||
mount MergeRequests
|
||||
mount Notes
|
||||
mount Internal
|
||||
mount SystemHooks
|
||||
end
|
||||
end
|
||||
|
|
|
@ -56,6 +56,24 @@ module Gitlab
|
|||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
# Transfer a project to the Group namespace
|
||||
#
|
||||
# Parameters:
|
||||
# id - group id
|
||||
# project_id - project id
|
||||
# Example Request:
|
||||
# POST /groups/:id/projects/:project_id
|
||||
post ":id/projects/:project_id" do
|
||||
authenticated_as_admin!
|
||||
@group = Group.find(params[:id])
|
||||
project = Project.find(params[:project_id])
|
||||
if project.transfer(@group)
|
||||
present @group
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,6 +8,8 @@ module Gitlab
|
|||
def handle_merge_request_errors!(errors)
|
||||
if errors[:project_access].any?
|
||||
error!(errors[:project_access], 422)
|
||||
elsif errors[:branch_conflict].any?
|
||||
error!(errors[:branch_conflict], 422)
|
||||
end
|
||||
not_found!
|
||||
end
|
||||
|
|
|
@ -64,6 +64,38 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# Create new project for a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# user_id (required) - The ID of a user
|
||||
# name (required) - name for new project
|
||||
# description (optional) - short project description
|
||||
# default_branch (optional) - 'master' by default
|
||||
# issues_enabled (optional) - enabled by default
|
||||
# wall_enabled (optional) - enabled by default
|
||||
# merge_requests_enabled (optional) - enabled by default
|
||||
# wiki_enabled (optional) - enabled by default
|
||||
# Example Request
|
||||
# POST /projects/user/:user_id
|
||||
post "user/:user_id" do
|
||||
authenticated_as_admin!
|
||||
user = User.find(params[:user_id])
|
||||
attrs = attributes_for_keys [:name,
|
||||
:description,
|
||||
:default_branch,
|
||||
:issues_enabled,
|
||||
:wall_enabled,
|
||||
:merge_requests_enabled,
|
||||
:wiki_enabled]
|
||||
@project = ::Projects::CreateContext.new(user, attrs).execute
|
||||
if @project.saved?
|
||||
present @project, with: Entities::Project
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
# Get a project team members
|
||||
#
|
||||
# Parameters:
|
||||
|
@ -471,6 +503,49 @@ module Gitlab
|
|||
present tree.data
|
||||
end
|
||||
|
||||
# Get a specific project's keys
|
||||
#
|
||||
# Example Request:
|
||||
# GET /projects/:id/keys
|
||||
get ":id/keys" do
|
||||
present user_project.deploy_keys, with: Entities::SSHKey
|
||||
end
|
||||
|
||||
# Get single key owned by currently authenticated user
|
||||
#
|
||||
# Example Request:
|
||||
# GET /projects/:id/keys/:id
|
||||
get ":id/keys/:key_id" do
|
||||
key = user_project.deploy_keys.find params[:key_id]
|
||||
present key, with: Entities::SSHKey
|
||||
end
|
||||
|
||||
# Add new ssh key to currently authenticated user
|
||||
#
|
||||
# Parameters:
|
||||
# key (required) - New SSH Key
|
||||
# title (required) - New SSH Key's title
|
||||
# Example Request:
|
||||
# POST /projects/:id/keys
|
||||
post ":id/keys" do
|
||||
attrs = attributes_for_keys [:title, :key]
|
||||
key = user_project.deploy_keys.new attrs
|
||||
if key.save
|
||||
present key, with: Entities::SSHKey
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
# Delete existed ssh key of currently authenticated user
|
||||
#
|
||||
# Example Request:
|
||||
# DELETE /projects/:id/keys/:id
|
||||
delete ":id/keys/:key_id" do
|
||||
key = user_project.deploy_keys.find params[:key_id]
|
||||
key.delete
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
60
lib/api/system_hooks.rb
Normal file
60
lib/api/system_hooks.rb
Normal file
|
@ -0,0 +1,60 @@
|
|||
module Gitlab
|
||||
# Hooks API
|
||||
class SystemHooks < Grape::API
|
||||
before { authenticated_as_admin! }
|
||||
|
||||
resource :hooks do
|
||||
# Get the list of system hooks
|
||||
#
|
||||
# Example Request:
|
||||
# GET /hooks
|
||||
get do
|
||||
@hooks = SystemHook.all
|
||||
present @hooks, with: Entities::Hook
|
||||
end
|
||||
|
||||
# Create new system hook
|
||||
#
|
||||
# Parameters:
|
||||
# url (required) - url for system hook
|
||||
# Example Request
|
||||
# POST /hooks
|
||||
post do
|
||||
attrs = attributes_for_keys [:url]
|
||||
@hook = SystemHook.new attrs
|
||||
if @hook.save
|
||||
present @hook, with: Entities::Hook
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
# Test a hook
|
||||
#
|
||||
# Example Request
|
||||
# GET /hooks/:id
|
||||
get ":id" do
|
||||
@hook = SystemHook.find(params[:id])
|
||||
data = {
|
||||
event_name: "project_create",
|
||||
name: "Ruby",
|
||||
path: "ruby",
|
||||
project_id: 1,
|
||||
owner_name: "Someone",
|
||||
owner_email: "example@gitlabhq.com"
|
||||
}
|
||||
@hook.execute(data)
|
||||
data
|
||||
end
|
||||
|
||||
# Delete a hook
|
||||
#
|
||||
# Example Request:
|
||||
# DELETE /hooks/:id
|
||||
delete ":id" do
|
||||
@hook = SystemHook.find(params[:id])
|
||||
@hook.destroy
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -81,6 +81,26 @@ module Gitlab
|
|||
end
|
||||
end
|
||||
|
||||
# Add ssh key to a specified user. Only available to admin users.
|
||||
#
|
||||
# Parameters:
|
||||
# id (required) - The ID of a user
|
||||
# key (required) - New SSH Key
|
||||
# title (required) - New SSH Key's title
|
||||
# Example Request:
|
||||
# POST /users/:id/keys
|
||||
post ":id/keys" do
|
||||
authenticated_as_admin!
|
||||
user = User.find(params[:id])
|
||||
attrs = attributes_for_keys [:title, :key]
|
||||
key = user.keys.new attrs
|
||||
if key.save
|
||||
present key, with: Entities::SSHKey
|
||||
else
|
||||
not_found!
|
||||
end
|
||||
end
|
||||
|
||||
# Delete user. Available only for admin
|
||||
#
|
||||
# Example Request:
|
||||
|
|
|
@ -105,12 +105,6 @@ module ExtractsPath
|
|||
# Automatically renders `not_found!` if a valid tree path could not be
|
||||
# resolved (e.g., when a user inserts an invalid path or ref).
|
||||
def assign_ref_vars
|
||||
# Handle formats embedded in the id
|
||||
if params[:id].ends_with?('.atom')
|
||||
params[:id].gsub!(/\.atom$/, '')
|
||||
request.format = :atom
|
||||
end
|
||||
|
||||
path = CGI::unescape(request.fullpath.dup)
|
||||
|
||||
@ref, @path = extract_ref(path)
|
||||
|
|
|
@ -7,10 +7,12 @@ namespace :gitlab do
|
|||
def setup_db
|
||||
warn_user_is_not_gitlab
|
||||
|
||||
puts "This will create the necessary database tables and seed the database."
|
||||
puts "You will lose any previous data stored in the database."
|
||||
ask_to_continue
|
||||
puts ""
|
||||
unless ENV['force'] == 'yes'
|
||||
puts "This will create the necessary database tables and seed the database."
|
||||
puts "You will lose any previous data stored in the database."
|
||||
ask_to_continue
|
||||
puts ""
|
||||
end
|
||||
|
||||
Rake::Task["db:setup"].invoke
|
||||
Rake::Task["db:seed_fu"].invoke
|
||||
|
|
|
@ -13,7 +13,7 @@ describe CommitsController do
|
|||
describe "GET show" do
|
||||
context "as atom feed" do
|
||||
it "should render as atom" do
|
||||
get :show, project_id: project.path, id: "master.atom"
|
||||
get :show, project_id: project.path, id: "master", format: "atom"
|
||||
response.should be_success
|
||||
response.content_type.should == 'application/atom+xml'
|
||||
end
|
||||
|
|
|
@ -100,4 +100,27 @@ describe Gitlab::API do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /groups/:id/projects/:project_id" do
|
||||
let(:project) { create(:project) }
|
||||
before(:each) do
|
||||
project.stub!(:transfer).and_return(true)
|
||||
Project.stub(:find).and_return(project)
|
||||
end
|
||||
|
||||
|
||||
context "when authenticated as user" do
|
||||
it "should not transfer project to group" do
|
||||
post api("/groups/#{group1.id}/projects/#{project.id}", user2)
|
||||
response.status.should == 403
|
||||
end
|
||||
end
|
||||
|
||||
context "when authenticated as admin" do
|
||||
it "should transfer project to group" do
|
||||
project.should_receive(:transfer)
|
||||
post api("/groups/#{group1.id}/projects/#{project.id}", admin)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -105,13 +105,6 @@ describe Gitlab::API do
|
|||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
|
||||
context "when notable is invalid" do
|
||||
it "should return a 404 error" do
|
||||
get api("/projects/#{project.id}/unknown/#{snippet.id}/notes", user)
|
||||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/noteable/:noteable_id/notes/:note_id" do
|
||||
|
@ -180,12 +173,5 @@ describe Gitlab::API do
|
|||
response.status.should == 401
|
||||
end
|
||||
end
|
||||
|
||||
context "when noteable is invalid" do
|
||||
it "should return a 404 error" do
|
||||
post api("/projects/#{project.id}/invalid/#{snippet.id}/notes", user)
|
||||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,11 +6,14 @@ describe Gitlab::API do
|
|||
let(:user) { create(:user) }
|
||||
let(:user2) { create(:user) }
|
||||
let(:user3) { create(:user) }
|
||||
let(:admin) { create(:admin) }
|
||||
let!(:project) { create(:project, namespace: user.namespace ) }
|
||||
let!(:hook) { create(:project_hook, project: project, url: "http://example.com") }
|
||||
let!(:snippet) { create(:snippet, author: user, project: project, title: 'example') }
|
||||
let!(:users_project) { create(:users_project, user: user, project: project, project_access: UsersProject::MASTER) }
|
||||
let!(:users_project2) { create(:users_project, user: user3, project: project, project_access: UsersProject::DEVELOPER) }
|
||||
let(:key) { create(:key, project: project) }
|
||||
|
||||
before { project.team << [user, :reporter] }
|
||||
|
||||
describe "GET /projects" do
|
||||
|
@ -103,6 +106,46 @@ describe Gitlab::API do
|
|||
end
|
||||
end
|
||||
|
||||
describe "POST /projects/user/:id" do
|
||||
before { admin }
|
||||
|
||||
it "should create new project without path" do
|
||||
expect { post api("/projects/user/#{user.id}", admin), name: 'foo' }.to change {Project.count}.by(1)
|
||||
end
|
||||
|
||||
it "should not create new project without name" do
|
||||
expect { post api("/projects/user/#{user.id}", admin) }.to_not change {Project.count}
|
||||
end
|
||||
|
||||
it "should respond with 201 on success" do
|
||||
post api("/projects/user/#{user.id}", admin), name: 'foo'
|
||||
response.status.should == 201
|
||||
end
|
||||
|
||||
it "should respond with 404 on failure" do
|
||||
post api("/projects/user/#{user.id}", admin)
|
||||
response.status.should == 404
|
||||
end
|
||||
|
||||
it "should assign attributes to project" do
|
||||
project = attributes_for(:project, {
|
||||
description: Faker::Lorem.sentence,
|
||||
default_branch: 'stable',
|
||||
issues_enabled: false,
|
||||
wall_enabled: false,
|
||||
merge_requests_enabled: false,
|
||||
wiki_enabled: false
|
||||
})
|
||||
|
||||
post api("/projects/user/#{user.id}", admin), project
|
||||
|
||||
project.each_pair do |k,v|
|
||||
next if k == :path
|
||||
json_response[k.to_s].should == v
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id" do
|
||||
it "should return a project by id" do
|
||||
get api("/projects/#{project.id}", user)
|
||||
|
@ -591,4 +634,59 @@ describe Gitlab::API do
|
|||
response.status.should == 400
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/keys" do
|
||||
it "should return array of ssh keys" do
|
||||
project.deploy_keys << key
|
||||
project.save
|
||||
get api("/projects/#{project.id}/keys", user)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.first['title'].should == key.title
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /projects/:id/keys/:key_id" do
|
||||
it "should return a single key" do
|
||||
project.deploy_keys << key
|
||||
project.save
|
||||
get api("/projects/#{project.id}/keys/#{key.id}", user)
|
||||
response.status.should == 200
|
||||
json_response['title'].should == key.title
|
||||
end
|
||||
|
||||
it "should return 404 Not Found with invalid ID" do
|
||||
get api("/projects/#{project.id}/keys/404", user)
|
||||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /projects/:id/keys" do
|
||||
it "should not create an invalid ssh key" do
|
||||
post api("/projects/#{project.id}/keys", user), { title: "invalid key" }
|
||||
response.status.should == 404
|
||||
end
|
||||
|
||||
it "should create new ssh key" do
|
||||
key_attrs = attributes_for :key
|
||||
expect {
|
||||
post api("/projects/#{project.id}/keys", user), key_attrs
|
||||
}.to change{ project.deploy_keys.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /projects/:id/keys/:key_id" do
|
||||
it "should delete existing key" do
|
||||
project.deploy_keys << key
|
||||
project.save
|
||||
expect {
|
||||
delete api("/projects/#{project.id}/keys/#{key.id}", user)
|
||||
}.to change{ project.deploy_keys.count }.by(-1)
|
||||
end
|
||||
|
||||
it "should return 404 Not Found with invalid ID" do
|
||||
delete api("/projects/#{project.id}/keys/404", user)
|
||||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
69
spec/requests/api/system_hooks_spec.rb
Normal file
69
spec/requests/api/system_hooks_spec.rb
Normal file
|
@ -0,0 +1,69 @@
|
|||
require 'spec_helper'
|
||||
|
||||
describe Gitlab::API do
|
||||
include ApiHelpers
|
||||
|
||||
let(:user) { create(:user) }
|
||||
let(:admin) { create(:admin) }
|
||||
let!(:hook) { create(:system_hook, url: "http://example.com") }
|
||||
|
||||
before { stub_request(:post, hook.url) }
|
||||
|
||||
describe "GET /hooks" do
|
||||
context "when not an admin" do
|
||||
it "should return forbidden error" do
|
||||
get api("/hooks", user)
|
||||
response.status.should == 403
|
||||
end
|
||||
end
|
||||
|
||||
context "when authenticated as admin" do
|
||||
it "should return an array of hooks" do
|
||||
get api("/hooks", admin)
|
||||
response.status.should == 200
|
||||
json_response.should be_an Array
|
||||
json_response.first['url'].should == hook.url
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "POST /hooks" do
|
||||
it "should create new hook" do
|
||||
expect {
|
||||
post api("/hooks", admin), url: 'http://example.com'
|
||||
}.to change { SystemHook.count }.by(1)
|
||||
end
|
||||
|
||||
it "should respond with 404 on failure" do
|
||||
post api("/hooks", admin)
|
||||
response.status.should == 404
|
||||
end
|
||||
|
||||
it "should not create new hook without url" do
|
||||
expect {
|
||||
post api("/hooks", admin)
|
||||
}.to_not change { SystemHook.count }
|
||||
end
|
||||
end
|
||||
|
||||
describe "GET /hooks/:id" do
|
||||
it "should return hook by id" do
|
||||
get api("/hooks/#{hook.id}", admin)
|
||||
response.status.should == 200
|
||||
json_response['event_name'].should == 'project_create'
|
||||
end
|
||||
|
||||
it "should return 404 on failure" do
|
||||
get api("/hooks/404", admin)
|
||||
response.status.should == 404
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /hooks/:id" do
|
||||
it "should delete a hook" do
|
||||
expect {
|
||||
delete api("/hooks/#{hook.id}", admin)
|
||||
}.to change { SystemHook.count }.by(-1)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -167,6 +167,22 @@ describe Gitlab::API do
|
|||
end
|
||||
end
|
||||
|
||||
describe "POST /users/:id/keys" do
|
||||
before { admin }
|
||||
|
||||
it "should not create invalid ssh key" do
|
||||
post api("/users/#{user.id}/keys", admin), { title: "invalid key" }
|
||||
response.status.should == 404
|
||||
end
|
||||
|
||||
it "should create ssh key" do
|
||||
key_attrs = attributes_for :key
|
||||
expect {
|
||||
post api("/users/#{user.id}/keys", admin), key_attrs
|
||||
}.to change{ user.keys.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
describe "DELETE /users/:id" do
|
||||
before { admin }
|
||||
|
||||
|
|
|
@ -56,7 +56,6 @@ end
|
|||
# projects POST /projects(.:format) projects#create
|
||||
# new_project GET /projects/new(.:format) projects#new
|
||||
# wall_project GET /:id/wall(.:format) projects#wall
|
||||
# graph_project GET /:id/graph(.:format) projects#graph
|
||||
# files_project GET /:id/files(.:format) projects#files
|
||||
# edit_project GET /:id/edit(.:format) projects#edit
|
||||
# project GET /:id(.:format) projects#show
|
||||
|
@ -75,10 +74,6 @@ describe ProjectsController, "routing" do
|
|||
get("/gitlabhq/wall").should route_to('projects#wall', id: 'gitlabhq')
|
||||
end
|
||||
|
||||
it "to #graph" do
|
||||
get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
|
||||
end
|
||||
|
||||
it "to #files" do
|
||||
get("/gitlabhq/files").should route_to('projects#files', id: 'gitlabhq')
|
||||
end
|
||||
|
@ -202,6 +197,7 @@ describe RefsController, "routing" do
|
|||
it "to #logs_tree" do
|
||||
get("/gitlabhq/refs/stable/logs_tree").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable')
|
||||
get("/gitlabhq/refs/stable/logs_tree/foo/bar/baz").should route_to('refs#logs_tree', project_id: 'gitlabhq', id: 'stable', path: 'foo/bar/baz')
|
||||
get("/gitlab/gitlabhq/refs/stable/logs_tree/files.scss").should route_to('refs#logs_tree', project_id: 'gitlab/gitlabhq', id: 'stable', path: 'files.scss')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -301,6 +297,10 @@ describe CommitsController, "routing" do
|
|||
let(:actions) { [:show] }
|
||||
let(:controller) { 'commits' }
|
||||
end
|
||||
|
||||
it "to #show" do
|
||||
get("/gitlab/gitlabhq/commits/master.atom").should route_to('commits#show', project_id: 'gitlab/gitlabhq', id: "master", format: "atom")
|
||||
end
|
||||
end
|
||||
|
||||
# project_team_members GET /:project_id/team_members(.:format) team_members#index
|
||||
|
@ -385,6 +385,7 @@ end
|
|||
describe BlameController, "routing" do
|
||||
it "to #show" do
|
||||
get("/gitlabhq/blame/master/app/models/project.rb").should route_to('blame#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
|
||||
get("/gitlab/gitlabhq/blame/master/files.scss").should route_to('blame#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -393,6 +394,7 @@ describe BlobController, "routing" do
|
|||
it "to #show" do
|
||||
get("/gitlabhq/blob/master/app/models/project.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
|
||||
get("/gitlabhq/blob/master/app/models/compare.rb").should route_to('blob#show', project_id: 'gitlabhq', id: 'master/app/models/compare.rb')
|
||||
get("/gitlab/gitlabhq/blob/master/files.scss").should route_to('blob#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -400,6 +402,7 @@ end
|
|||
describe TreeController, "routing" do
|
||||
it "to #show" do
|
||||
get("/gitlabhq/tree/master/app/models/project.rb").should route_to('tree#show', project_id: 'gitlabhq', id: 'master/app/models/project.rb')
|
||||
get("/gitlab/gitlabhq/tree/master/files.scss").should route_to('tree#show', project_id: 'gitlab/gitlabhq', id: 'master/files.scss')
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -420,3 +423,10 @@ describe CompareController, "routing" do
|
|||
get("/gitlabhq/compare/issue/1234...stable").should route_to('compare#show', project_id: 'gitlabhq', from: 'issue/1234', to: 'stable')
|
||||
end
|
||||
end
|
||||
|
||||
describe GraphController, "routing" do
|
||||
it "to #show" do
|
||||
get("/gitlabhq/graph/master").should route_to('graph#show', project_id: 'gitlabhq', id: 'master')
|
||||
get("/gitlabhq/graph/master.json").should route_to('graph#show', project_id: 'gitlabhq', id: 'master', format: "json")
|
||||
end
|
||||
end
|
||||
|
|
|
@ -43,6 +43,11 @@ class GitLabTestRepo < Repository
|
|||
def repo
|
||||
@repo ||= Grit::Repo.new(Rails.root.join('tmp', 'repositories', 'gitlabhq'))
|
||||
end
|
||||
|
||||
# patch repo size (in mb)
|
||||
def size
|
||||
12.45
|
||||
end
|
||||
end
|
||||
|
||||
module Gitlab
|
||||
|
|
Loading…
Reference in a new issue