diff --git a/.travis.yml b/.travis.yml
index d7c65286cf..6bff3752b2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -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
diff --git a/CHANGELOG b/CHANGELOG
index 031536816a..441f36a5bd 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -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)
diff --git a/Gemfile b/Gemfile
index a433c85a80..b486c97c5e 100644
--- a/Gemfile
+++ b/Gemfile
@@ -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"
diff --git a/Gemfile.lock b/Gemfile.lock
index ef041c9439..5866ccf90d 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -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)
diff --git a/VERSION b/VERSION
index 5870f72108..acfb750c90 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-6.7.0.pre-ee
+6.7.0.rc1-ee
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 4a393dbfe8..f69b750bb6 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -29,3 +29,5 @@
//= require_tree .
//= require d3
//= require underscore
+//= require nprogress
+//= require nprogress-turbolinks
diff --git a/app/assets/javascripts/main.js.coffee b/app/assets/javascripts/main.js.coffee
index 70e8972d24..89f6a547ff 100644
--- a/app/assets/javascripts/main.js.coffee
+++ b/app/assets/javascripts/main.js.coffee
@@ -41,19 +41,11 @@ window.linkify = (str) ->
window.simpleFormat = (str) ->
linkify(sanitize(str).replace(/\n/g, '
'))
-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
diff --git a/app/assets/stylesheets/application.scss b/app/assets/stylesheets/application.scss
index 3346671468..4b7103010b 100644
--- a/app/assets/stylesheets/application.scss
+++ b/app/assets/stylesheets/application.scss
@@ -7,6 +7,8 @@
*= require select2
*= require highlightjs.min
*= require_self
+ *= require nprogress
+ *= require nprogress-bootstrap
*/
@import "main/variables.scss";
diff --git a/app/controllers/passwords_controller.rb b/app/controllers/passwords_controller.rb
new file mode 100644
index 0000000000..988ede3007
--- /dev/null
+++ b/app/controllers/passwords_controller.rb
@@ -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
diff --git a/app/controllers/profiles/keys_controller.rb b/app/controllers/profiles/keys_controller.rb
index b4f14e649e..6713cd7c8c 100644
--- a/app/controllers/profiles/keys_controller.rb
+++ b/app/controllers/profiles/keys_controller.rb
@@ -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
diff --git a/app/helpers/tree_helper.rb b/app/helpers/tree_helper.rb
index 2dbc1cffb1..50501dffef 100644
--- a/app/helpers/tree_helper.rb
+++ b/app/helpers/tree_helper.rb
@@ -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)
diff --git a/app/models/note.rb b/app/models/note.rb
index 48c03c9d58..906de4855a 100644
--- a/app/models/note.rb
+++ b/app/models/note.rb
@@ -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
diff --git a/app/models/project.rb b/app/models/project.rb
index a6d9d663e6..5d340f6364 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -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?
diff --git a/app/models/project_services/slack_message.rb b/app/models/project_services/slack_message.rb
new file mode 100644
index 0000000000..b2b8d6fed7
--- /dev/null
+++ b/app/models/project_services/slack_message.rb
@@ -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
diff --git a/app/models/project_services/slack_service.rb b/app/models/project_services/slack_service.rb
new file mode 100644
index 0000000000..754fd87db0
--- /dev/null
+++ b/app/models/project_services/slack_service.rb
@@ -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
diff --git a/app/models/user.rb b/app/models/user.rb
index 6557622aa4..7854c47a84 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -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
diff --git a/app/views/devise/sessions/_oauth_providers.html.haml b/app/views/devise/sessions/_oauth_providers.html.haml
index 935bc6af50..2b1cb9c694 100644
--- a/app/views/devise/sessions/_oauth_providers.html.haml
+++ b/app/views/devise/sessions/_oauth_providers.html.haml
@@ -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
diff --git a/app/views/layouts/_head_panel.html.haml b/app/views/layouts/_head_panel.html.haml
index 5080a1b7ef..d8001fd76d 100644
--- a/app/views/layouts/_head_panel.html.haml
+++ b/app/views/layouts/_head_panel.html.haml
@@ -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
diff --git a/app/views/layouts/_init_auto_complete.html.haml b/app/views/layouts/_init_auto_complete.html.haml
index 6a20dedf62..fd6097dcc7 100644
--- a/app/views/layouts/_init_auto_complete.html.haml
+++ b/app/views/layouts/_init_auto_complete.html.haml
@@ -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();
diff --git a/app/views/projects/notes/_note.html.haml b/app/views/projects/notes/_note.html.haml
index 217e36e38d..81bf0611ec 100644
--- a/app/views/projects/notes/_note.html.haml
+++ b/app/views/projects/notes/_note.html.haml
@@ -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
diff --git a/config/initializers/gemoji.rb b/config/initializers/gemoji.rb
deleted file mode 100644
index 6cc33aced7..0000000000
--- a/config/initializers/gemoji.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-# Workaround for https://github.com/github/gemoji/pull/18
-require 'gemoji'
-Gitlab::Application.config.assets.paths << Emoji.images_path
diff --git a/config/routes.rb b/config/routes.rb
index 7e70926ef5..e17f0014f1 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -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
diff --git a/doc/api/system_hooks.md b/doc/api/system_hooks.md
index 355ce31c12..2e87ada1d7 100644
--- a/doc/api/system_hooks.md
+++ b/doc/api/system_hooks.md
@@ -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
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index ab74af4faf..805e115047 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -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).
diff --git a/doc/release/monthly.md b/doc/release/monthly.md
index 28fc260b33..e440f5d5ab 100644
--- a/doc/release/monthly.md
+++ b/doc/release/monthly.md
@@ -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
diff --git a/doc/ssh/deploy_keys.md b/doc/ssh/deploy_keys.md
new file mode 100644
index 0000000000..56fe98bb10
--- /dev/null
+++ b/doc/ssh/deploy_keys.md
@@ -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.
diff --git a/features/project/service.feature b/features/project/service.feature
index 46b983e8f9..a5af065c9e 100644
--- a/features/project/service.feature
+++ b/features/project/service.feature
@@ -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
diff --git a/features/steps/project/redirects.rb b/features/steps/project/redirects.rb
index 76ffea1bb6..cfa4ce82be 100644
--- a/features/steps/project/redirects.rb
+++ b/features/steps/project/redirects.rb
@@ -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
diff --git a/features/steps/project/services.rb b/features/steps/project/services.rb
index 54b3f18e08..0594a08a5e 100644
--- a/features/steps/project/services.rb
+++ b/features/steps/project/services.rb
@@ -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
diff --git a/features/steps/public/projects.rb b/features/steps/public/projects.rb
index eb1d235f43..7c7311bb91 100644
--- a/features/steps/public/projects.rb
+++ b/features/steps/public/projects.rb
@@ -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
diff --git a/features/steps/shared/project.rb b/features/steps/shared/project.rb
index f35beab8af..f8cb753b78 100644
--- a/features/steps/shared/project.rb
+++ b/features/steps/shared/project.rb
@@ -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
diff --git a/lib/gitlab/git_access.rb b/lib/gitlab/git_access.rb
index ed33f60c67..2228f4e2ca 100644
--- a/lib/gitlab/git_access.rb
+++ b/lib/gitlab/git_access.rb
@@ -48,7 +48,6 @@ module Gitlab
else
:push_code
end
-
user.can?(action, project) &&
pass_git_hooks?(user, project, ref, oldrev, newrev)
else
diff --git a/lib/gitlab/markdown.rb b/lib/gitlab/markdown.rb
index e72f4f5d0c..80bb00821f 100644
--- a/lib/gitlab/markdown.rb
+++ b/lib/gitlab/markdown.rb
@@ -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
diff --git a/lib/tasks/gitlab/check.rake b/lib/tasks/gitlab/check.rake
index 64ff7330d7..067735d66b 100644
--- a/lib/tasks/gitlab/check.rake
+++ b/lib/tasks/gitlab/check.rake
@@ -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} ? ... "
diff --git a/spec/controllers/profile_keys_controller_spec.rb b/spec/controllers/profile_keys_controller_spec.rb
index 121012d5d4..593d3e9eb5 100644
--- a/spec/controllers/profile_keys_controller_spec.rb
+++ b/spec/controllers/profile_keys_controller_spec.rb
@@ -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
diff --git a/spec/factories.rb b/spec/factories.rb
index 7fc2b7c5e9..148477d638 100644
--- a/spec/factories.rb
+++ b/spec/factories.rb
@@ -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
diff --git a/spec/features/notes_on_merge_requests_spec.rb b/spec/features/notes_on_merge_requests_spec.rb
index a3d8c462bf..25a86b11fa 100644
--- a/spec/features/notes_on_merge_requests_spec.rb
+++ b/spec/features/notes_on_merge_requests_spec.rb
@@ -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")
diff --git a/spec/features/security/group/internal_group_access_spec.rb b/spec/features/security/group/internal_group_access_spec.rb
index 0c354f0245..79a6aee41b 100644
--- a/spec/features/security/group/internal_group_access_spec.rb
+++ b/spec/features/security/group/internal_group_access_spec.rb
@@ -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
diff --git a/spec/features/security/group/mixed_group_access_spec.rb b/spec/features/security/group/mixed_group_access_spec.rb
index 82e816e388..028cd32d2b 100644
--- a/spec/features/security/group/mixed_group_access_spec.rb
+++ b/spec/features/security/group/mixed_group_access_spec.rb
@@ -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
diff --git a/spec/features/security/group/public_group_access_spec.rb b/spec/features/security/group/public_group_access_spec.rb
index a9c0afbb60..f0ed7649eb 100644
--- a/spec/features/security/group/public_group_access_spec.rb
+++ b/spec/features/security/group/public_group_access_spec.rb
@@ -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
diff --git a/spec/features/security/project/internal_access_spec.rb b/spec/features/security/project/internal_access_spec.rb
index 8bb1e259ef..152cf66dcf 100644
--- a/spec/features/security/project/internal_access_spec.rb
+++ b/spec/features/security/project/internal_access_spec.rb
@@ -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
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 76f9e753dd..0bd2ccafcc 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -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)
diff --git a/spec/finders/projects_finder_spec.rb b/spec/finders/projects_finder_spec.rb
index cc6ee82ab7..6e3ae4d615 100644
--- a/spec/finders/projects_finder_spec.rb
+++ b/spec/finders/projects_finder_spec.rb
@@ -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) }
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 6bae5951b7..839350bafb 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -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
diff --git a/spec/models/slack_message_spec.rb b/spec/models/slack_message_spec.rb
new file mode 100644
index 0000000000..b39cd4edf8
--- /dev/null
+++ b/spec/models/slack_message_spec.rb
@@ -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 of ' <<
+ ' ()' <<
+ "\n - message1 ()" <<
+ "\n - message2 ()"
+ 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 to ' <<
+ ''
+ 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 '
+ end
+ end
+end
diff --git a/spec/models/slack_service_spec.rb b/spec/models/slack_service_spec.rb
new file mode 100644
index 0000000000..387455cb25
--- /dev/null
+++ b/spec/models/slack_service_spec.rb
@@ -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
diff --git a/spec/requests/api/projects_spec.rb b/spec/requests/api/projects_spec.rb
index 69088799c3..d3d1973025 100644
--- a/spec/requests/api/projects_spec.rb
+++ b/spec/requests/api/projects_spec.rb
@@ -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
diff --git a/spec/seed_project.tar.gz b/spec/seed_project.tar.gz
index 92b9587e3f..8d32a927da 100644
Binary files a/spec/seed_project.tar.gz and b/spec/seed_project.tar.gz differ
diff --git a/spec/services/search_service_spec.rb b/spec/services/search_service_spec.rb
index 457cb3c0ca..b467282a5d 100644
--- a/spec/services/search_service_spec.rb
+++ b/spec/services/search_service_spec.rb
@@ -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