mirror of
https://github.com/wahyd4/gitlabhq.git
synced 2026-08-18 00:56:41 +10:00
Merge branch 'master' of dev.gitlab.org:gitlab/gitlabhq into ce-6-7-rc
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> Conflicts: Gemfile.lock VERSION lib/gitlab/git_access.rb
This commit is contained in:
+2
-2
@@ -19,10 +19,10 @@ rvm:
|
||||
services:
|
||||
- redis-server
|
||||
before_script:
|
||||
- "bundle exec rake db:setup"
|
||||
- "bundle exec rake db:seed_fu"
|
||||
- "cp config/database.yml.$DB config/database.yml"
|
||||
- "cp config/gitlab.yml.example config/gitlab.yml"
|
||||
- "bundle exec rake db:setup"
|
||||
- "bundle exec rake db:seed_fu"
|
||||
script: "bundle exec rake $TASK --trace"
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
@@ -9,6 +9,7 @@ v 6.7.0
|
||||
- Show contribution guide link for new issue form (Jeroen van Baarsen)
|
||||
- Fix CI status for merge requests from fork
|
||||
- Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard)
|
||||
- New page load indicator that includes a spinner that scrolls with the page
|
||||
- Converted all the help sections into markdown
|
||||
- LDAP user filters
|
||||
- Streamline the content of notification emails (Pierre de La Morinerie)
|
||||
@@ -24,6 +25,12 @@ v 6.7.0
|
||||
- Faster authorized_keys rebuilding in `rake gitlab:shell:setup` (requires gitlab-shell 1.8.5)
|
||||
- Create and Update MR calls now support the description parameter (Greg Messner)
|
||||
- Markdown relative links in the wiki link to wiki pages, markdown relative links in repositories link to files in the repository
|
||||
- Added Slack service integration (Federico Ravasio)
|
||||
- Better API responses for access_levels (sponsored by O'Reilly Media)
|
||||
- Requires at least 2 unicorn workers
|
||||
- Requires gitlab-shell v1.9+
|
||||
- Replaced gemoji(due to closed licencing problem) with Phantom Open Emoji library(combined SIL Open Font License, MIT License and the CC 3.0 License)
|
||||
- Fix `/:username.keys` response content type (Dmitry Medvinsky)
|
||||
|
||||
v 6.6.5
|
||||
- Added option to remove issue assignee on project issue page and issue edit page (Jason Blanchard)
|
||||
|
||||
@@ -133,6 +133,9 @@ gem "gitlab-flowdock-git-hook", "~> 0.4.2"
|
||||
# Gemnasium integration
|
||||
gem "gemnasium-gitlab-service", "~> 0.2"
|
||||
|
||||
# Slack integration
|
||||
gem "slack-notifier", "~> 0.2.0"
|
||||
|
||||
# d3
|
||||
gem "d3_rails", "~> 3.1.4"
|
||||
|
||||
@@ -163,8 +166,9 @@ gem "modernizr", "2.6.2"
|
||||
gem "raphael-rails", "~> 2.1.2"
|
||||
gem 'bootstrap-sass', '~> 3.0'
|
||||
gem "font-awesome-rails", '~> 3.2'
|
||||
gem "gemoji", "~> 1.3.0"
|
||||
gem "gitlab_emoji", "~> 0.0.1.1"
|
||||
gem "gon", '~> 5.0.0'
|
||||
gem 'nprogress-rails'
|
||||
|
||||
group :development do
|
||||
gem "annotate", "~> 2.6.0.beta2"
|
||||
|
||||
+9
-2
@@ -128,6 +128,8 @@ GEM
|
||||
mail (~> 2.2)
|
||||
email_validator (1.4.0)
|
||||
activemodel
|
||||
emoji (1.0.1)
|
||||
json
|
||||
enumerize (0.7.0)
|
||||
activesupport (>= 3.2)
|
||||
equalizer (0.0.8)
|
||||
@@ -165,7 +167,6 @@ GEM
|
||||
formatador (0.2.4)
|
||||
gemnasium-gitlab-service (0.2.1)
|
||||
rugged (~> 0.19)
|
||||
gemoji (1.3.1)
|
||||
gherkin-ruby (0.3.1)
|
||||
racc
|
||||
github-markdown (0.5.5)
|
||||
@@ -190,6 +191,8 @@ GEM
|
||||
charlock_holmes (~> 0.6.6)
|
||||
escape_utils (~> 0.2.4)
|
||||
mime-types (~> 1.19)
|
||||
gitlab_emoji (0.0.1.1)
|
||||
emoji (~> 1.0.1)
|
||||
gitlab_git (5.7.1)
|
||||
activesupport (~> 4.0.0)
|
||||
charlock_holmes (~> 0.6.9)
|
||||
@@ -297,6 +300,7 @@ GEM
|
||||
net-ssh (>= 1.99.1)
|
||||
net-ssh (2.7.0)
|
||||
nokogiri (1.5.10)
|
||||
nprogress-rails (0.1.2.3)
|
||||
oauth (0.4.7)
|
||||
oauth2 (0.8.1)
|
||||
faraday (~> 0.8)
|
||||
@@ -468,6 +472,7 @@ GEM
|
||||
rack-protection (~> 1.4)
|
||||
tilt (~> 1.3, >= 1.3.4)
|
||||
six (0.2.0)
|
||||
slack-notifier (0.2.0)
|
||||
slim (2.0.2)
|
||||
temple (~> 0.6.6)
|
||||
tilt (>= 1.3.3, < 2.1)
|
||||
@@ -591,12 +596,12 @@ DEPENDENCIES
|
||||
font-awesome-rails (~> 3.2)
|
||||
foreman
|
||||
gemnasium-gitlab-service (~> 0.2)
|
||||
gemoji (~> 1.3.0)
|
||||
github-markup (~> 0.7.4)!
|
||||
gitlab-flowdock-git-hook (~> 0.4.2)
|
||||
gitlab-gollum-lib (~> 1.1.0)
|
||||
gitlab-grack (~> 2.0.0.pre)
|
||||
gitlab-linguist (~> 3.0.0)
|
||||
gitlab_emoji (~> 0.0.1.1)
|
||||
gitlab_git (~> 5.7.1)
|
||||
gitlab_meta (= 6.0)
|
||||
gitlab_omniauth-ldap (= 1.0.4)
|
||||
@@ -621,6 +626,7 @@ DEPENDENCIES
|
||||
modernizr (= 2.6.2)
|
||||
mysql2
|
||||
net-ldap
|
||||
nprogress-rails
|
||||
omniauth (~> 1.1.3)
|
||||
omniauth-github
|
||||
omniauth-google-oauth2
|
||||
@@ -653,6 +659,7 @@ DEPENDENCIES
|
||||
simplecov
|
||||
sinatra
|
||||
six
|
||||
slack-notifier (~> 0.2.0)
|
||||
slim
|
||||
spinach-rails
|
||||
spork (~> 1.0rc)
|
||||
|
||||
@@ -29,3 +29,5 @@
|
||||
//= require_tree .
|
||||
//= require d3
|
||||
//= require underscore
|
||||
//= require nprogress
|
||||
//= require nprogress-turbolinks
|
||||
|
||||
@@ -41,19 +41,11 @@ window.linkify = (str) ->
|
||||
window.simpleFormat = (str) ->
|
||||
linkify(sanitize(str).replace(/\n/g, '<br />'))
|
||||
|
||||
window.startSpinner = ->
|
||||
$('.turbolink-spinner').fadeIn()
|
||||
|
||||
window.stopSpinner = ->
|
||||
$('.turbolink-spinner').fadeOut()
|
||||
|
||||
window.unbindEvents = ->
|
||||
$(document).unbind('scroll')
|
||||
$(document).off('scroll')
|
||||
|
||||
document.addEventListener("page:fetch", startSpinner)
|
||||
document.addEventListener("page:fetch", unbindEvents)
|
||||
document.addEventListener("page:change", stopSpinner)
|
||||
|
||||
$ ->
|
||||
# Click a .one_click_select field, select the contents
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
*= require select2
|
||||
*= require highlightjs.min
|
||||
*= require_self
|
||||
*= require nprogress
|
||||
*= require nprogress-bootstrap
|
||||
*/
|
||||
|
||||
@import "main/variables.scss";
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
class PasswordsController < Devise::PasswordsController
|
||||
|
||||
def create
|
||||
email = resource_params[:email]
|
||||
resource_found = resource_class.find_by_email(email)
|
||||
if resource_found && resource_found.ldap_user?
|
||||
flash[:alert] = "Cannot reset password for LDAP user."
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name)) and return
|
||||
end
|
||||
|
||||
self.resource = resource_class.send_reset_password_instructions(resource_params)
|
||||
if successfully_sent?(resource)
|
||||
respond_with({}, :location => after_sending_reset_password_instructions_path_for(resource_name))
|
||||
else
|
||||
respond_with(resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -41,7 +41,7 @@ class Profiles::KeysController < ApplicationController
|
||||
begin
|
||||
user = User.find_by_username(params[:username])
|
||||
if user.present?
|
||||
render text: user.all_ssh_keys.join("\n")
|
||||
render text: user.all_ssh_keys.join("\n"), content_type: "text/plain"
|
||||
else
|
||||
render_404 and return
|
||||
end
|
||||
|
||||
@@ -40,7 +40,7 @@ module TreeHelper
|
||||
# Returns boolean
|
||||
def markup?(filename)
|
||||
filename.downcase.end_with?(*%w(.textile .rdoc .org .creole
|
||||
.mediawiki .rst .asciidoc .pod))
|
||||
.mediawiki .rst .adoc .asciidoc .pod))
|
||||
end
|
||||
|
||||
def gitlab_markdown?(filename)
|
||||
|
||||
+4
-2
@@ -199,7 +199,8 @@ class Note < ActiveRecord::Base
|
||||
def downvote?
|
||||
votable? && (note.start_with?('-1') ||
|
||||
note.start_with?(':-1:') ||
|
||||
note.start_with?(':thumbsdown:')
|
||||
note.start_with?(':thumbsdown:') ||
|
||||
note.start_with?(':thumbs_down_sign:')
|
||||
)
|
||||
end
|
||||
|
||||
@@ -249,7 +250,8 @@ class Note < ActiveRecord::Base
|
||||
def upvote?
|
||||
votable? && (note.start_with?('+1') ||
|
||||
note.start_with?(':+1:') ||
|
||||
note.start_with?(':thumbsup:')
|
||||
note.start_with?(':thumbsup:') ||
|
||||
note.start_with?(':thumbs_up_sign:')
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -57,6 +57,7 @@ class Project < ActiveRecord::Base
|
||||
has_one :flowdock_service, dependent: :destroy
|
||||
has_one :assembla_service, dependent: :destroy
|
||||
has_one :gemnasium_service, dependent: :destroy
|
||||
has_one :slack_service, dependent: :destroy
|
||||
has_one :forked_project_link, dependent: :destroy, foreign_key: "forked_to_project_id"
|
||||
has_one :forked_from_project, through: :forked_project_link
|
||||
# Merge Requests for target project should be removed with it
|
||||
@@ -308,7 +309,7 @@ class Project < ActiveRecord::Base
|
||||
end
|
||||
|
||||
def available_services_names
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium)
|
||||
%w(gitlab_ci campfire hipchat pivotaltracker flowdock assembla emails_on_push gemnasium slack)
|
||||
end
|
||||
|
||||
def gitlab_ci?
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
require 'slack-notifier'
|
||||
|
||||
class SlackMessage
|
||||
def initialize(params)
|
||||
@after = params.fetch(:after)
|
||||
@before = params.fetch(:before)
|
||||
@commits = params.fetch(:commits, [])
|
||||
@project_name = params.fetch(:project_name)
|
||||
@project_url = params.fetch(:project_url)
|
||||
@ref = params.fetch(:ref).gsub('refs/heads/', '')
|
||||
@username = params.fetch(:user_name)
|
||||
end
|
||||
|
||||
def compose
|
||||
format(message)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :after
|
||||
attr_reader :before
|
||||
attr_reader :commits
|
||||
attr_reader :project_name
|
||||
attr_reader :project_url
|
||||
attr_reader :ref
|
||||
attr_reader :username
|
||||
|
||||
def message
|
||||
if new_branch?
|
||||
new_branch_message
|
||||
elsif removed_branch?
|
||||
removed_branch_message
|
||||
else
|
||||
push_message << commit_messages
|
||||
end
|
||||
end
|
||||
|
||||
def format(string)
|
||||
Slack::Notifier::LinkFormatter.format(string)
|
||||
end
|
||||
|
||||
def new_branch_message
|
||||
"#{username} pushed new branch #{branch_link} to #{project_link}"
|
||||
end
|
||||
|
||||
def removed_branch_message
|
||||
"#{username} removed branch #{ref} from #{project_link}"
|
||||
end
|
||||
|
||||
def push_message
|
||||
"#{username} pushed to branch #{branch_link} of #{project_link} (#{compare_link})"
|
||||
end
|
||||
|
||||
def commit_messages
|
||||
commits.each_with_object('') do |commit, str|
|
||||
str << compose_commit_message(commit)
|
||||
end
|
||||
end
|
||||
|
||||
def compose_commit_message(commit)
|
||||
id = commit.fetch(:id)[0..5]
|
||||
message = commit.fetch(:message)
|
||||
url = commit.fetch(:url)
|
||||
|
||||
"\n - #{message} ([#{id}](#{url}))"
|
||||
end
|
||||
|
||||
def new_branch?
|
||||
before =~ /000000/
|
||||
end
|
||||
|
||||
def removed_branch?
|
||||
after =~ /000000/
|
||||
end
|
||||
|
||||
def branch_url
|
||||
"#{project_url}/commits/#{ref}"
|
||||
end
|
||||
|
||||
def compare_url
|
||||
"#{project_url}/compare/#{before}...#{after}"
|
||||
end
|
||||
|
||||
def branch_link
|
||||
"[#{ref}](#{branch_url})"
|
||||
end
|
||||
|
||||
def project_link
|
||||
"[#{project_name}](#{project_url})"
|
||||
end
|
||||
|
||||
def compare_link
|
||||
"[Compare changes](#{compare_url})"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,67 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# title :string(255)
|
||||
# token :string(255)
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# active :boolean default(FALSE), not null
|
||||
# project_url :string(255)
|
||||
# subdomain :string(255)
|
||||
# room :string(255)
|
||||
# api_key :string(255)
|
||||
#
|
||||
|
||||
class SlackService < Service
|
||||
attr_accessible :room
|
||||
attr_accessible :subdomain
|
||||
|
||||
validates :room, presence: true, if: :activated?
|
||||
validates :subdomain, presence: true, if: :activated?
|
||||
validates :token, presence: true, if: :activated?
|
||||
|
||||
def title
|
||||
'Slack'
|
||||
end
|
||||
|
||||
def description
|
||||
'A team communication tool for the 21st century'
|
||||
end
|
||||
|
||||
def to_param
|
||||
'slack'
|
||||
end
|
||||
|
||||
def fields
|
||||
[
|
||||
{ type: 'text', name: 'subdomain', placeholder: '' },
|
||||
{ type: 'text', name: 'token', placeholder: '' },
|
||||
{ type: 'text', name: 'room', placeholder: 'Ex. #general' },
|
||||
]
|
||||
end
|
||||
|
||||
def execute(push_data)
|
||||
message = SlackMessage.new(push_data.merge(
|
||||
project_url: project_url,
|
||||
project_name: project_name
|
||||
))
|
||||
|
||||
notifier = Slack::Notifier.new(subdomain, token)
|
||||
notifier.channel = room
|
||||
notifier.ping(message.compose)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def project_name
|
||||
project.name_with_namespace.gsub(/\s/, '')
|
||||
end
|
||||
|
||||
def project_url
|
||||
project.web_url
|
||||
end
|
||||
end
|
||||
+1
-1
@@ -249,7 +249,7 @@ class User < ActiveRecord::Base
|
||||
def namespace_uniq
|
||||
namespace_name = self.username
|
||||
if Namespace.find_by(path: namespace_name)
|
||||
self.errors.add :username, "already exist"
|
||||
self.errors.add :username, "already exists"
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -2,10 +2,12 @@
|
||||
- if providers.present?
|
||||
%hr
|
||||
%div{:'data-no-turbolink' => 'data-no-turbolink'}
|
||||
%span Sign in with:
|
||||
%span Sign in with*:
|
||||
- providers.each do |provider|
|
||||
%span
|
||||
- if default_providers.include?(provider)
|
||||
= link_to authbutton(provider, 32), omniauth_authorize_path(resource_name, provider)
|
||||
- else
|
||||
= link_to provider.to_s.titleize, omniauth_authorize_path(resource_name, provider), class: "btn"
|
||||
%br
|
||||
%small * Make sure your email address is public
|
||||
|
||||
@@ -14,10 +14,6 @@
|
||||
|
||||
.navbar-collapse.collapse
|
||||
%ul.nav.navbar-nav
|
||||
%li.hidden-sm.hidden-xs
|
||||
%a
|
||||
%div.hide.turbolink-spinner
|
||||
%i.icon-refresh.icon-spin
|
||||
%li.hidden-sm.hidden-xs
|
||||
= render "layouts/search"
|
||||
%li.visible-sm.visible-xs
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
:javascript
|
||||
GitLab.GfmAutoComplete.dataSource = "#{autocomplete_sources_project_path(@project)}"
|
||||
GitLab.GfmAutoComplete.Emoji.assetBase = "#{Gitlab.config.gitlab.relative_url_root + '/assets/emoji'}"
|
||||
GitLab.GfmAutoComplete.Emoji.assetBase = "#{Gitlab.config.gitlab.relative_url_root + Emoji.asset_path}"
|
||||
GitLab.GfmAutoComplete.setup();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
%i.icon-thumbs-up
|
||||
\+1
|
||||
- if note.downvote?
|
||||
%span.vote.downvote.label.label-error
|
||||
%span.vote.downvote.label.label-danger
|
||||
%i.icon-thumbs-down
|
||||
\-1
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
# Workaround for https://github.com/github/gemoji/pull/18
|
||||
require 'gemoji'
|
||||
Gitlab::Application.config.assets.paths << Emoji.images_path
|
||||
+1
-1
@@ -175,7 +175,7 @@ Gitlab::Application.routes.draw do
|
||||
|
||||
resources :projects, constraints: { id: /[^\/]+/ }, only: [:new, :create]
|
||||
|
||||
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations }
|
||||
devise_for :users, controllers: { omniauth_callbacks: :omniauth_callbacks, registrations: :registrations , passwords: :passwords}
|
||||
|
||||
#
|
||||
# Project Area
|
||||
|
||||
+70
-70
@@ -1,70 +1,70 @@
|
||||
All methods require admin authorization.
|
||||
|
||||
The url endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks).
|
||||
|
||||
## List system hooks
|
||||
|
||||
Get list of system hooks
|
||||
|
||||
```
|
||||
GET /hooks
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ **none**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id":3,
|
||||
"url":"http://example.com/hook",
|
||||
"created_at":"2013-10-02T10:15:31Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Add new system hook hook
|
||||
|
||||
```
|
||||
POST /hooks
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `url` (required) - The hook URL
|
||||
|
||||
|
||||
## Test system hook
|
||||
|
||||
```
|
||||
GET /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
|
||||
```json
|
||||
{
|
||||
"event_name":"project_create",
|
||||
"name":"Ruby",
|
||||
"path":"ruby",
|
||||
"project_id":1,
|
||||
"owner_name":"Someone",
|
||||
"owner_email":"example@gitlabhq.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Delete system hook
|
||||
|
||||
Deletes a system hook. This is an idempotent API function and returns `200 Ok` even if the hook
|
||||
is not available. If the hook is deleted it is also returned as JSON.
|
||||
|
||||
```
|
||||
DELETE /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
All methods require admin authorization.
|
||||
|
||||
The url endpoint of the system hooks can be configured in [the admin area under hooks](/admin/hooks).
|
||||
|
||||
## List system hooks
|
||||
|
||||
Get list of system hooks
|
||||
|
||||
```
|
||||
GET /hooks
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ **none**
|
||||
|
||||
```json
|
||||
[
|
||||
{
|
||||
"id":3,
|
||||
"url":"http://example.com/hook",
|
||||
"created_at":"2013-10-02T10:15:31Z"
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
## Add new system hook hook
|
||||
|
||||
```
|
||||
POST /hooks
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `url` (required) - The hook URL
|
||||
|
||||
|
||||
## Test system hook
|
||||
|
||||
```
|
||||
GET /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
|
||||
```json
|
||||
{
|
||||
"event_name":"project_create",
|
||||
"name":"Ruby",
|
||||
"path":"ruby",
|
||||
"project_id":1,
|
||||
"owner_name":"Someone",
|
||||
"owner_email":"example@gitlabhq.com"
|
||||
}
|
||||
```
|
||||
|
||||
## Delete system hook
|
||||
|
||||
Deletes a system hook. This is an idempotent API function and returns `200 Ok` even if the hook
|
||||
is not available. If the hook is deleted it is also returned as JSON.
|
||||
|
||||
```
|
||||
DELETE /hooks/:id
|
||||
```
|
||||
|
||||
Parameters:
|
||||
|
||||
+ `id` (required) - The ID of hook
|
||||
|
||||
@@ -18,7 +18,7 @@ New releases are generally around the same time as GitLab CE releases with excep
|
||||
|
||||
# System Layout
|
||||
|
||||
When referring to ~git in the picures it means the home directory of the git user which is typically /home/git.
|
||||
When referring to ~git in the pictures it means the home directory of the git user which is typically /home/git.
|
||||
|
||||
GitLab is primarily installed within the `/home/git` user home directory as `git` user.
|
||||
Within the home directory is where the gitlabhq server software resides as well as the repositories (though the repository location is configurable).
|
||||
|
||||
@@ -61,11 +61,11 @@ After making the release branch new commits are cherry-picked from master. When
|
||||
* 17th: feature freeze (stop merging new features in master)
|
||||
* 18th: UI freeze (stop merging changes to the user interface)
|
||||
* 19th: code freeze (stop merging non-essential code improvements)
|
||||
* 20th: release candidate 1 (VERSION x.x.0.rc1, tag and tweet about x.x.0.rc1)
|
||||
* 20th: release candidate 1 (VERSION x.x.0.rc1, tag, tweet and upgrade Cloud)
|
||||
* 21st: optional release candidate 2 (x.x.0.rc2, only if rc1 had problems)
|
||||
* 22nd: release (VERSION x.x.0, create x-x-stable branch, tag, blog and tweet)
|
||||
* 23nd: optional patch releases (x.x.1, x.x.2, etc., only if there are serious problems)
|
||||
* 24-end of month: release Enterprise Edition and upgrade GitLab Cloud
|
||||
* 23nd: optional patch releases (x.x.1, x.x.2, etc., only if there are serious regressions)
|
||||
* 24-end of month: release Enterprise Edition and upgrade GitLab Cloud to latest patch
|
||||
* 1-7th: official merge window (see contributing guide)
|
||||
* 8-16th: bugfixes and sponsored features
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
Deploy keys allow read-only access one or multiple projects with a single SSH key.
|
||||
|
||||
This is really useful for cloning repositories to your Continuous Integration (CI) server.
|
||||
By using a deploy keys you don't have to setup a dummy user account.
|
||||
|
||||
If you are a project master or owner you can add a deploy key in the project settings under the section Deploy Keys.
|
||||
Press the 'New Deploy Key' button and upload a public ssh key.
|
||||
After this the machine that uses the corresponding private key has read-only access to the project.
|
||||
|
||||
You can't add the same deploy key twice with the 'New Deploy Key' option.
|
||||
If you want to add the same key to another project please enable it in the list that says 'Deploy keys from projects available to you'.
|
||||
You need to be the owner of the deploy key to see it in this list.
|
||||
@@ -37,6 +37,12 @@ Feature: Project Services
|
||||
And I fill Assembla settings
|
||||
Then I should see Assembla service settings saved
|
||||
|
||||
Scenario: Activate Slack service
|
||||
When I visit project "Shop" services page
|
||||
And I click Slack service link
|
||||
And I fill Slack settings
|
||||
Then I should see Slack service settings saved
|
||||
|
||||
Scenario: Activate email on push service
|
||||
When I visit project "Shop" services page
|
||||
And I click email on push service link
|
||||
|
||||
@@ -4,7 +4,7 @@ class Spinach::Features::ProjectRedirects < Spinach::FeatureSteps
|
||||
include SharedProject
|
||||
|
||||
step 'public project "Community"' do
|
||||
create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
|
||||
create :project, :public, name: 'Community'
|
||||
end
|
||||
|
||||
step 'private project "Enterprise"' do
|
||||
|
||||
@@ -100,4 +100,22 @@ class ProjectServices < Spinach::FeatureSteps
|
||||
step 'I should see email on push service settings saved' do
|
||||
find_field('Recipients').value.should == 'qa@company.name'
|
||||
end
|
||||
|
||||
step 'I click Slack service link' do
|
||||
click_link 'Slack'
|
||||
end
|
||||
|
||||
step 'I fill Slack settings' do
|
||||
check 'Active'
|
||||
fill_in 'Subdomain', with: 'gitlab'
|
||||
fill_in 'Room', with: '#gitlab'
|
||||
fill_in 'Token', with: 'verySecret'
|
||||
click_button 'Save'
|
||||
end
|
||||
|
||||
step 'I should see Slack service settings saved' do
|
||||
find_field('Subdomain').value.should == 'gitlab'
|
||||
find_field('Room').value.should == '#gitlab'
|
||||
find_field('Token').value.should == 'verySecret'
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,7 +4,7 @@ class Spinach::Features::PublicProjectsFeature < Spinach::FeatureSteps
|
||||
include SharedProject
|
||||
|
||||
step 'public empty project "Empty Public Project"' do
|
||||
create :empty_project, name: 'Empty Public Project', visibility_level: Gitlab::VisibilityLevel::PUBLIC
|
||||
create :empty_project, :public, name: 'Empty Public Project'
|
||||
end
|
||||
|
||||
step 'I should see project "Empty Public Project"' do
|
||||
|
||||
@@ -79,7 +79,7 @@ module SharedProject
|
||||
end
|
||||
|
||||
step 'internal project "Internal"' do
|
||||
create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
|
||||
create :project, :internal, name: 'Internal'
|
||||
end
|
||||
|
||||
step 'I should see project "Internal"' do
|
||||
@@ -91,7 +91,7 @@ module SharedProject
|
||||
end
|
||||
|
||||
step 'public project "Community"' do
|
||||
create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
|
||||
create :project, :public, name: 'Community'
|
||||
end
|
||||
|
||||
step 'I should see project "Community"' do
|
||||
@@ -112,14 +112,14 @@ module SharedProject
|
||||
step '"John Doe" is authorized to internal project "Internal"' do
|
||||
user = user_exists("John Doe", username: "john_doe")
|
||||
project = Project.find_by(name: "Internal")
|
||||
project ||= create :project, name: 'Internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL
|
||||
project ||= create :project, :internal, name: 'Internal'
|
||||
project.team << [user, :master]
|
||||
end
|
||||
|
||||
step '"John Doe" is authorized to public project "Community"' do
|
||||
user = user_exists("John Doe", username: "john_doe")
|
||||
project = Project.find_by(name: "Community")
|
||||
project ||= create :project, name: 'Community', visibility_level: Gitlab::VisibilityLevel::PUBLIC
|
||||
project ||= create :project, :public, name: 'Community'
|
||||
project.team << [user, :master]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -48,7 +48,6 @@ module Gitlab
|
||||
else
|
||||
:push_code
|
||||
end
|
||||
|
||||
user.can?(action, project) &&
|
||||
pass_git_hooks?(user, project, ref, oldrev, newrev)
|
||||
else
|
||||
|
||||
@@ -152,7 +152,7 @@ module Gitlab
|
||||
#
|
||||
# Returns boolean
|
||||
def valid_emoji?(emoji)
|
||||
Emoji.names.include? emoji
|
||||
Emoji.find_by_name emoji
|
||||
end
|
||||
|
||||
# Private: Dispatches to a dedicated processing method based on reference
|
||||
|
||||
@@ -66,6 +66,7 @@ namespace :gitlab do
|
||||
puts "no".green
|
||||
else
|
||||
puts "yes".red
|
||||
puts "Please fix this by removing the SQLite entry from the database.yml".blue
|
||||
for_more_information(
|
||||
"https://github.com/gitlabhq/gitlabhq/wiki/Migrate-from-SQLite-to-MySQL",
|
||||
see_database_guide
|
||||
@@ -741,7 +742,7 @@ namespace :gitlab do
|
||||
end
|
||||
|
||||
def check_gitlab_shell
|
||||
required_version = Gitlab::VersionInfo.new(1, 8, 5)
|
||||
required_version = Gitlab::VersionInfo.new(1, 9, 0)
|
||||
current_version = Gitlab::VersionInfo.parse(gitlab_shell_version)
|
||||
|
||||
print "GitLab Shell version >= #{required_version} ? ... "
|
||||
|
||||
@@ -24,6 +24,11 @@ describe Profiles::KeysController do
|
||||
|
||||
expect(response.body).to eq("")
|
||||
end
|
||||
|
||||
it "should respond with text/plain content type" do
|
||||
get :get_keys, username: user.username
|
||||
expect(response.content_type).to eq("text/plain")
|
||||
end
|
||||
end
|
||||
|
||||
describe "user with keys" do
|
||||
@@ -44,6 +49,11 @@ describe Profiles::KeysController do
|
||||
expect(response.body).not_to eq("")
|
||||
expect(response.body).to eq(user.all_ssh_keys.join("\n"))
|
||||
end
|
||||
|
||||
it "should respond with text/plain content type" do
|
||||
get :get_keys, username: user.username
|
||||
expect(response.content_type).to eq("text/plain")
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
+17
-1
@@ -32,6 +32,18 @@ FactoryGirl.define do
|
||||
path { name.downcase.gsub(/\s/, '_') }
|
||||
namespace
|
||||
creator
|
||||
|
||||
trait :public do
|
||||
visibility_level Gitlab::VisibilityLevel::PUBLIC
|
||||
end
|
||||
|
||||
trait :internal do
|
||||
visibility_level Gitlab::VisibilityLevel::INTERNAL
|
||||
end
|
||||
|
||||
trait :private do
|
||||
visibility_level Gitlab::VisibilityLevel::PRIVATE
|
||||
end
|
||||
end
|
||||
|
||||
# Generates a test repository from the repository stored under `spec/seed_project.tar.gz`.
|
||||
@@ -146,6 +158,11 @@ FactoryGirl.define do
|
||||
state :reopened
|
||||
end
|
||||
|
||||
trait :simple do
|
||||
source_branch "simple_merge_request"
|
||||
target_branch "master"
|
||||
end
|
||||
|
||||
factory :closed_merge_request, traits: [:closed]
|
||||
factory :reopened_merge_request, traits: [:reopened]
|
||||
factory :merge_request_with_diffs, traits: [:with_diffs]
|
||||
@@ -161,7 +178,6 @@ FactoryGirl.define do
|
||||
factory :note_on_issue, traits: [:on_issue], aliases: [:votable_note]
|
||||
factory :note_on_merge_request, traits: [:on_merge_request]
|
||||
factory :note_on_merge_request_diff, traits: [:on_merge_request, :on_diff]
|
||||
factory :note_on_merge_request_with_attachment, traits: [:on_merge_request, :with_attachment]
|
||||
|
||||
trait :on_commit do
|
||||
project factory: :project
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "On a merge request", js: true do
|
||||
let!(:project) { create(:project) }
|
||||
let!(:merge_request) { create(:merge_request, source_project: project, target_project: project) }
|
||||
let!(:note) { create(:note_on_merge_request_with_attachment, project: project) }
|
||||
let!(:merge_request) { create(:merge_request, :simple) }
|
||||
let!(:project) { merge_request.source_project }
|
||||
let!(:note) { create(:note_on_merge_request, :with_attachment, project: project) }
|
||||
|
||||
before do
|
||||
login_as :user
|
||||
project.team << [@user, :master]
|
||||
|
||||
login_as :admin
|
||||
visit project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
@@ -134,22 +132,20 @@ describe "On a merge request", js: true do
|
||||
end
|
||||
end
|
||||
|
||||
describe "On a merge request diff", js: true, focus: true do
|
||||
let!(:project) { create(:project) }
|
||||
let!(:merge_request) { create(:merge_request_with_diffs, source_project: project, target_project: project) }
|
||||
describe "On a merge request diff", js: true do
|
||||
let(:merge_request) { create(:merge_request, :with_diffs, :simple) }
|
||||
let(:project) { merge_request.source_project }
|
||||
|
||||
before do
|
||||
login_as :user
|
||||
project.team << [@user, :master]
|
||||
login_as :admin
|
||||
visit diffs_project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
|
||||
subject { page }
|
||||
|
||||
describe "when adding a note" do
|
||||
before do
|
||||
find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185"]').click
|
||||
find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click
|
||||
end
|
||||
|
||||
describe "the notes holder" do
|
||||
@@ -160,13 +156,13 @@ describe "On a merge request diff", js: true, focus: true do
|
||||
|
||||
describe "the note form" do
|
||||
it "shouldn't add a second form for same row" do
|
||||
find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185"]').click
|
||||
find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click
|
||||
|
||||
should have_css("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185'] + .js-temp-notes-holder form", count: 1)
|
||||
should have_css("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7'] + .js-temp-notes-holder form", count: 1)
|
||||
end
|
||||
|
||||
it "should be removed when canceled" do
|
||||
within(".diff-file form[rel$='4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185']") do
|
||||
within(".diff-file form[rel$='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7']") do
|
||||
find(".js-close-discussion-note-form").trigger("click")
|
||||
end
|
||||
|
||||
@@ -176,12 +172,9 @@ describe "On a merge request diff", js: true, focus: true do
|
||||
end
|
||||
|
||||
describe "with muliple note forms" do
|
||||
let!(:project) { create(:project) }
|
||||
let!(:merge_request) { create(:merge_request_with_diffs, source_project: project, target_project: project) }
|
||||
|
||||
before do
|
||||
find('a[data-line-code="4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185"]').click
|
||||
find('a[data-line-code="342e16cbbd482ac2047dc679b2749d248cc1428f_18_17"]').click
|
||||
find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7"]').click
|
||||
find('a[data-line-code="8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10"]').click
|
||||
end
|
||||
|
||||
it { should have_css(".js-temp-notes-holder", count: 2) }
|
||||
@@ -189,12 +182,12 @@ describe "On a merge request diff", js: true, focus: true do
|
||||
describe "previewing them separately" do
|
||||
before do
|
||||
# add two separate texts and trigger previews on both
|
||||
within("tr[id='4735dfc552ad7bf15ca468adc3cad9d05b624490_172_185'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "One comment on line 185"
|
||||
within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_7_7'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "One comment on line 7"
|
||||
find(".js-note-preview-button").trigger("click")
|
||||
end
|
||||
within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "Another comment on line 17"
|
||||
within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "Another comment on line 10"
|
||||
find(".js-note-preview-button").trigger("click")
|
||||
end
|
||||
end
|
||||
@@ -202,14 +195,14 @@ describe "On a merge request diff", js: true, focus: true do
|
||||
|
||||
describe "posting a note" do
|
||||
before do
|
||||
within("tr[id='342e16cbbd482ac2047dc679b2749d248cc1428f_18_17'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "Another comment on line 17"
|
||||
within("tr[id='8ec9a00bfd09b3190ac6b22251dbb1aa95a0579d_10_10'] + .js-temp-notes-holder") do
|
||||
fill_in "note[note]", with: "Another comment on line 10"
|
||||
click_button("Add Comment")
|
||||
end
|
||||
end
|
||||
|
||||
it 'should be added as discussion' do
|
||||
should have_content("Another comment on line 17")
|
||||
should have_content("Another comment on line 10")
|
||||
should have_css(".notes_holder")
|
||||
should have_css(".notes_holder .note", count: 1)
|
||||
should have_link("Reply")
|
||||
|
||||
@@ -16,7 +16,7 @@ describe "Group with internal project access" do
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
|
||||
create(:project, :internal, group: group)
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
|
||||
@@ -16,8 +16,8 @@ describe "Group access" do
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, path: "internal_project", group: group, visibility_level: Gitlab::VisibilityLevel::INTERNAL)
|
||||
create(:project, path: "public_project", group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
|
||||
create(:project, :internal, path: "internal_project", group: group)
|
||||
create(:project, :public, path: "public_project", group: group)
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
|
||||
@@ -16,7 +16,7 @@ describe "Group with public project access" do
|
||||
group.add_user(reporter, Gitlab::Access::REPORTER)
|
||||
group.add_user(guest, Gitlab::Access::GUEST)
|
||||
|
||||
create(:project, group: group, visibility_level: Gitlab::VisibilityLevel::PUBLIC)
|
||||
create(:project, :public, group: group)
|
||||
end
|
||||
|
||||
describe "GET /groups/:path" do
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe "Internal Project Access" do
|
||||
let(:project) { create(:project) }
|
||||
let(:project) { create(:project, :internal) }
|
||||
|
||||
let(:master) { create(:user) }
|
||||
let(:guest) { create(:user) }
|
||||
let(:reporter) { create(:user) }
|
||||
|
||||
before do
|
||||
# internal project
|
||||
project.visibility_level = Gitlab::VisibilityLevel::INTERNAL
|
||||
project.save!
|
||||
|
||||
# full access
|
||||
project.team << [master, :master]
|
||||
|
||||
# readonly
|
||||
project.team << [reporter, :reporter]
|
||||
|
||||
end
|
||||
|
||||
describe "Project should be internal" do
|
||||
|
||||
@@ -1,13 +1,15 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe MergeRequestsFinder do
|
||||
let(:user) { create :user }
|
||||
let(:user) { create :user }
|
||||
let(:user2) { create :user }
|
||||
|
||||
let(:project1) { create(:project) }
|
||||
let(:project2) { create(:project) }
|
||||
let(:merge_request1) { create(:merge_request, author: user, source_project: project1, target_project: project2) }
|
||||
let(:merge_request2) { create(:merge_request, author: user, source_project: project2, target_project: project1) }
|
||||
let(:merge_request3) { create(:merge_request, author: user, source_project: project2, target_project: project2) }
|
||||
|
||||
let!(:merge_request1) { create(:merge_request, :simple, author: user, source_project: project1, target_project: project2) }
|
||||
let!(:merge_request2) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project1) }
|
||||
let!(:merge_request3) { create(:merge_request, :simple, author: user, source_project: project2, target_project: project2) }
|
||||
|
||||
before do
|
||||
project1.team << [user, :master]
|
||||
@@ -15,13 +17,7 @@ describe MergeRequestsFinder do
|
||||
project2.team << [user2, :developer]
|
||||
end
|
||||
|
||||
describe :execute do
|
||||
before :each do
|
||||
merge_request1
|
||||
merge_request2
|
||||
merge_request3
|
||||
end
|
||||
|
||||
describe "#execute" do
|
||||
it 'should filter by scope' do
|
||||
params = { scope: 'authored', state: 'opened' }
|
||||
merge_requests = MergeRequestsFinder.new.execute(user, params)
|
||||
|
||||
@@ -4,10 +4,10 @@ describe ProjectsFinder do
|
||||
let(:user) { create :user }
|
||||
let(:group) { create :group }
|
||||
|
||||
let(:project1) { create(:empty_project, group: group, visibility_level: Project::PUBLIC) }
|
||||
let(:project2) { create(:empty_project, group: group, visibility_level: Project::INTERNAL) }
|
||||
let(:project3) { create(:empty_project, group: group, visibility_level: Project::PRIVATE) }
|
||||
let(:project4) { create(:empty_project, group: group, visibility_level: Project::PRIVATE) }
|
||||
let(:project1) { create(:empty_project, :public, group: group) }
|
||||
let(:project2) { create(:empty_project, :internal, group: group) }
|
||||
let(:project3) { create(:empty_project, :private, group: group) }
|
||||
let(:project4) { create(:empty_project, :private, group: group) }
|
||||
|
||||
context 'non authenticated' do
|
||||
subject { ProjectsFinder.new.execute(nil, group: group) }
|
||||
|
||||
@@ -47,6 +47,7 @@ describe Project do
|
||||
it { should have_many(:hooks).dependent(:destroy) }
|
||||
it { should have_many(:protected_branches).dependent(:destroy) }
|
||||
it { should have_one(:forked_project_link).dependent(:destroy) }
|
||||
it { should have_one(:slack_service).dependent(:destroy) }
|
||||
end
|
||||
|
||||
describe "Mass assignment" do
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
require_relative '../../app/models/project_services/slack_message'
|
||||
|
||||
describe SlackMessage do
|
||||
subject { SlackMessage.new(args) }
|
||||
|
||||
let(:args) {
|
||||
{
|
||||
after: 'after',
|
||||
before: 'before',
|
||||
project_name: 'project_name',
|
||||
ref: 'refs/heads/master',
|
||||
user_name: 'user_name',
|
||||
project_url: 'url'
|
||||
}
|
||||
}
|
||||
|
||||
context 'push' do
|
||||
before do
|
||||
args[:commits] = [
|
||||
{ message: 'message1', url: 'url1', id: 'abcdefghi' },
|
||||
{ message: 'message2', url: 'url2', id: '123456789' },
|
||||
]
|
||||
end
|
||||
|
||||
it 'returns a message regarding pushes' do
|
||||
subject.compose.should ==
|
||||
'user_name pushed to branch <url/commits/master|master> of ' <<
|
||||
'<url|project_name> (<url/compare/before...after|Compare changes>)' <<
|
||||
"\n - message1 (<url1|abcdef>)" <<
|
||||
"\n - message2 (<url2|123456>)"
|
||||
end
|
||||
end
|
||||
|
||||
context 'new branch' do
|
||||
before do
|
||||
args[:before] = '000000'
|
||||
end
|
||||
|
||||
it 'returns a message regarding a new branch' do
|
||||
subject.compose.should ==
|
||||
'user_name pushed new branch <url/commits/master|master> to ' <<
|
||||
'<url|project_name>'
|
||||
end
|
||||
end
|
||||
|
||||
context 'removed branch' do
|
||||
before do
|
||||
args[:after] = '000000'
|
||||
end
|
||||
|
||||
it 'returns a message regarding a removed branch' do
|
||||
subject.compose.should ==
|
||||
'user_name removed branch master from <url|project_name>'
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,69 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: services
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# type :string(255)
|
||||
# title :string(255)
|
||||
# token :string(255)
|
||||
# project_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# active :boolean default(FALSE), not null
|
||||
# project_url :string(255)
|
||||
# subdomain :string(255)
|
||||
# room :string(255)
|
||||
# api_key :string(255)
|
||||
#
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe SlackService do
|
||||
describe "Associations" do
|
||||
it { should belong_to :project }
|
||||
it { should have_one :service_hook }
|
||||
end
|
||||
|
||||
describe "Validations" do
|
||||
context "active" do
|
||||
before do
|
||||
subject.active = true
|
||||
end
|
||||
|
||||
it { should validate_presence_of :room }
|
||||
it { should validate_presence_of :subdomain }
|
||||
it { should validate_presence_of :token }
|
||||
end
|
||||
end
|
||||
|
||||
describe "Execute" do
|
||||
let(:slack) { SlackService.new }
|
||||
let(:user) { create(:user) }
|
||||
let(:project) { create(:project) }
|
||||
let(:sample_data) { GitPushService.new.sample_data(project, user) }
|
||||
let(:subdomain) { 'gitlab' }
|
||||
let(:token) { 'verySecret' }
|
||||
let(:api_url) {
|
||||
"https://#{subdomain}.slack.com/services/hooks/incoming-webhook?token=#{token}"
|
||||
}
|
||||
|
||||
before do
|
||||
slack.stub(
|
||||
project: project,
|
||||
project_id: project.id,
|
||||
room: '#gitlab',
|
||||
service_hook: true,
|
||||
subdomain: subdomain,
|
||||
token: token
|
||||
)
|
||||
|
||||
WebMock.stub_request(:post, api_url)
|
||||
end
|
||||
|
||||
it "should call Slack API" do
|
||||
slack.execute(sample_data)
|
||||
|
||||
WebMock.should have_requested(:post, api_url).once
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -133,7 +133,7 @@ describe API::API do
|
||||
end
|
||||
|
||||
it "should set a project as public" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::PUBLIC })
|
||||
project = attributes_for(:project, :public)
|
||||
post api("/projects", user), project
|
||||
json_response['public'].should be_true
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
|
||||
@@ -147,21 +147,21 @@ describe API::API do
|
||||
end
|
||||
|
||||
it "should set a project as internal" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::INTERNAL })
|
||||
project = attributes_for(:project, :internal)
|
||||
post api("/projects", user), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
|
||||
end
|
||||
|
||||
it "should set a project as internal overriding :public" do
|
||||
project = attributes_for(:project, { public: true, visibility_level: Gitlab::VisibilityLevel::INTERNAL })
|
||||
project = attributes_for(:project, :internal, { public: true })
|
||||
post api("/projects", user), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
|
||||
end
|
||||
|
||||
it "should set a project as private" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
|
||||
project = attributes_for(:project, :private)
|
||||
post api("/projects", user), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
|
||||
@@ -215,7 +215,7 @@ describe API::API do
|
||||
end
|
||||
|
||||
it "should set a project as public" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::PUBLIC })
|
||||
project = attributes_for(:project, :public)
|
||||
post api("/projects/user/#{user.id}", admin), project
|
||||
json_response['public'].should be_true
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::PUBLIC
|
||||
@@ -229,21 +229,21 @@ describe API::API do
|
||||
end
|
||||
|
||||
it "should set a project as internal" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::INTERNAL })
|
||||
project = attributes_for(:project, :internal)
|
||||
post api("/projects/user/#{user.id}", admin), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
|
||||
end
|
||||
|
||||
it "should set a project as internal overriding :public" do
|
||||
project = attributes_for(:project, { public: true, visibility_level: Gitlab::VisibilityLevel::INTERNAL })
|
||||
project = attributes_for(:project, :internal, { public: true })
|
||||
post api("/projects/user/#{user.id}", admin), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::INTERNAL
|
||||
end
|
||||
|
||||
it "should set a project as private" do
|
||||
project = attributes_for(:project, { visibility_level: Gitlab::VisibilityLevel::PRIVATE })
|
||||
project = attributes_for(:project, :private)
|
||||
post api("/projects/user/#{user.id}", admin), project
|
||||
json_response['public'].should be_false
|
||||
json_response['visibility_level'].should == Gitlab::VisibilityLevel::PRIVATE
|
||||
@@ -490,10 +490,10 @@ describe API::API do
|
||||
|
||||
describe :fork_admin do
|
||||
let(:project_fork_target) { create(:project) }
|
||||
let(:project_fork_source) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
|
||||
let(:project_fork_source) { create(:project, :public) }
|
||||
|
||||
describe "POST /projects/:id/fork/:forked_from_id" do
|
||||
let(:new_project_fork_source) { create(:project, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
|
||||
let(:new_project_fork_source) { create(:project, :public) }
|
||||
|
||||
it "shouldn't available for non admin users" do
|
||||
post api("/projects/#{project_fork_target.id}/fork/#{project_fork_source.id}", user)
|
||||
@@ -593,10 +593,10 @@ describe API::API do
|
||||
let!(:post) { create(:empty_project, name: "#{query}_post", creator_id: user.id, namespace: user.namespace) }
|
||||
let!(:pre_post) { create(:empty_project, name: "pre_#{query}_post", creator_id: user.id, namespace: user.namespace) }
|
||||
let!(:unfound) { create(:empty_project, name: 'unfound', creator_id: user.id, namespace: user.namespace) }
|
||||
let!(:internal) { create(:empty_project, name: "internal #{query}", visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||
let!(:unfound_internal) { create(:empty_project, name: 'unfound internal', visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||
let!(:public) { create(:empty_project, name: "public #{query}", visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
|
||||
let!(:unfound_public) { create(:empty_project, name: 'unfound public', visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
|
||||
let!(:internal) { create(:empty_project, :internal, name: "internal #{query}") }
|
||||
let!(:unfound_internal) { create(:empty_project, :internal, name: 'unfound internal') }
|
||||
let!(:public) { create(:empty_project, :public, name: "public #{query}") }
|
||||
let!(:unfound_public) { create(:empty_project, :public, name: 'unfound public') }
|
||||
|
||||
context "when unauthenticated" do
|
||||
it "should return authentication error" do
|
||||
|
||||
Binary file not shown.
@@ -1,28 +1,26 @@
|
||||
require 'spec_helper'
|
||||
|
||||
describe 'Search::GlobalService' do
|
||||
let(:found_namespace) { create(:namespace, name: 'searchable namespace', path:'another_thing') }
|
||||
let(:user) { create(:user, namespace: found_namespace) }
|
||||
let!(:found_project) { create(:project, name: 'searchable_project', creator_id: user.id, namespace: found_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
|
||||
|
||||
let(:unfound_namespace) { create(:namespace, name: 'unfound namespace', path: 'yet_something_else') }
|
||||
let!(:unfound_project) { create(:project, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace, visibility_level: Gitlab::VisibilityLevel::PRIVATE) }
|
||||
|
||||
let(:internal_namespace) { create(:namespace, path: 'something_internal',name: 'searchable internal namespace') }
|
||||
let(:internal_user) { create(:user, namespace: internal_namespace) }
|
||||
let!(:internal_project) { create(:project, name: 'searchable_internal_project', creator_id: internal_user.id, namespace: internal_namespace, visibility_level: Gitlab::VisibilityLevel::INTERNAL) }
|
||||
|
||||
let(:public_namespace) { create(:namespace, path: 'something_public',name: 'searchable public namespace') }
|
||||
let(:public_user) { create(:user, namespace: public_namespace) }
|
||||
let!(:public_project) { create(:project, name: 'searchable_public_project', creator_id: public_user.id, namespace: public_namespace, visibility_level: Gitlab::VisibilityLevel::PUBLIC) }
|
||||
let(:internal_user) { create(:user, namespace: internal_namespace) }
|
||||
|
||||
let(:found_namespace) { create(:namespace, name: 'searchable namespace', path:'another_thing') }
|
||||
let(:unfound_namespace) { create(:namespace, name: 'unfound namespace', path: 'yet_something_else') }
|
||||
let(:internal_namespace) { create(:namespace, name: 'searchable internal namespace', path: 'something_internal') }
|
||||
let(:public_namespace) { create(:namespace, name: 'searchable public namespace', path: 'something_public') }
|
||||
|
||||
let!(:found_project) { create(:project, :private, name: 'searchable_project', creator_id: user.id, namespace: found_namespace) }
|
||||
let!(:unfound_project) { create(:project, :private, name: 'unfound_project', creator_id: user.id, namespace: unfound_namespace) }
|
||||
let!(:internal_project) { create(:project, :internal, name: 'searchable_internal_project', creator_id: internal_user.id, namespace: internal_namespace) }
|
||||
let!(:public_project) { create(:project, :public, name: 'searchable_public_project', creator_id: public_user.id, namespace: public_namespace) }
|
||||
|
||||
describe '#execute' do
|
||||
context 'unauthenticated' do
|
||||
it 'should return public projects only' do
|
||||
context = Search::GlobalService.new(nil, search: "searchable")
|
||||
results = context.execute
|
||||
results[:projects].should have(1).items
|
||||
results[:projects].should include(public_project)
|
||||
results[:projects].should match_array [public_project]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,24 +28,19 @@ describe 'Search::GlobalService' do
|
||||
it 'should return public, internal and private projects' do
|
||||
context = Search::GlobalService.new(user, search: "searchable")
|
||||
results = context.execute
|
||||
results[:projects].should have(3).items
|
||||
results[:projects].should include(public_project)
|
||||
results[:projects].should include(found_project)
|
||||
results[:projects].should include(internal_project)
|
||||
results[:projects].should match_array [public_project, found_project, internal_project]
|
||||
end
|
||||
|
||||
it 'should return only public & internal projects' do
|
||||
context = Search::GlobalService.new(internal_user, search: "searchable")
|
||||
results = context.execute
|
||||
results[:projects].should have(2).items
|
||||
results[:projects].should include(internal_project)
|
||||
results[:projects].should include(public_project)
|
||||
results[:projects].should match_array [internal_project, public_project]
|
||||
end
|
||||
|
||||
it 'namespace name should be searchable' do
|
||||
context = Search::GlobalService.new(user, search: "searchable namespace")
|
||||
results = context.execute
|
||||
results[:projects].should == [found_project]
|
||||
results[:projects].should match_array [found_project]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user