Commit 532815ac authored by Valery Sizov's avatar Valery Sizov

Merge branch 'master' of gitlab.com:gitlab-org/gitlab-ce into ce_upstream

parents 2fdbb2e1 d9042e8b
...@@ -2,6 +2,7 @@ image: "ruby:2.1" ...@@ -2,6 +2,7 @@ image: "ruby:2.1"
services: services:
- mysql:latest - mysql:latest
- postgres:latest
- redis:latest - redis:latest
- elasticsearch:latest - elasticsearch:latest
...@@ -12,17 +13,20 @@ cache: ...@@ -12,17 +13,20 @@ cache:
variables: variables:
MYSQL_ALLOW_EMPTY_PASSWORD: "1" MYSQL_ALLOW_EMPTY_PASSWORD: "1"
# retry tests only in CI environment
RSPEC_RETRY_RETRY_COUNT: "3"
ELASTIC_HOST: "elasticsearch" ELASTIC_HOST: "elasticsearch"
before_script: before_script:
- source ./scripts/prepare_build.sh - source ./scripts/prepare_build.sh
- ruby -v - ruby -v
- which ruby - which ruby
- gem install bundler --no-ri --no-rdoc - retry gem install bundler --no-ri --no-rdoc
- cp config/gitlab.yml.example config/gitlab.yml - cp config/gitlab.yml.example config/gitlab.yml
- touch log/application.log - touch log/application.log
- touch log/test.log - touch log/test.log
- bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}" - retry bundle install --without postgres production --jobs $(nproc) "${FLAGS[@]}"
- RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate - RAILS_ENV=test bundle exec rake db:drop db:create db:schema:load db:migrate
stages: stages:
...@@ -331,4 +335,4 @@ notify:slack: ...@@ -331,4 +335,4 @@ notify:slack:
- master@gitlab-org/gitlab-ce - master@gitlab-org/gitlab-ce
- tags@gitlab-org/gitlab-ce - tags@gitlab-org/gitlab-ce
- master@gitlab-org/gitlab-ee - master@gitlab-org/gitlab-ee
- tags@gitlab-org/gitlab-ee - tags@gitlab-org/gitlab-ee
\ No newline at end of file
...@@ -17,10 +17,16 @@ v 8.6.0 (unreleased) ...@@ -17,10 +17,16 @@ v 8.6.0 (unreleased)
- Add support for cross-project label references - Add support for cross-project label references
- Update documentation to reflect Guest role not being enforced on internal projects - Update documentation to reflect Guest role not being enforced on internal projects
- Allow search for logged out users - Allow search for logged out users
- Fix bug where Bitbucket `closed` issues were imported as `opened` (Iuri de Silvio)
- Don't show Issues/MRs from archived projects in Groups view - Don't show Issues/MRs from archived projects in Groups view
- Increase the notes polling timeout over time (Roberto Dip) - Increase the notes polling timeout over time (Roberto Dip)
- Show labels in dashboard and group milestone views - Show labels in dashboard and group milestone views
- Add main language of a project in the list of projects (Tiago Botelho) - Add main language of a project in the list of projects (Tiago Botelho)
- Add ability to show archived projects on dashboard, explore and group pages
v 8.5.5
- Ensure removing a project removes associated Todo entries.
- Prevent a 500 error in Todos when author was removed.
v 8.5.4 v 8.5.4
- Do not cache requests for badges (including builds badge) - Do not cache requests for badges (including builds badge)
......
...@@ -273,7 +273,9 @@ group :development, :test do ...@@ -273,7 +273,9 @@ group :development, :test do
gem 'database_cleaner', '~> 1.4.0' gem 'database_cleaner', '~> 1.4.0'
gem 'factory_girl_rails', '~> 4.6.0' gem 'factory_girl_rails', '~> 4.6.0'
gem 'rspec-rails', '~> 3.3.0' gem 'rspec-rails', '~> 3.3.0'
gem 'rspec-retry'
gem 'spinach-rails', '~> 0.2.1' gem 'spinach-rails', '~> 0.2.1'
gem 'spinach-rerun-reporter', '~> 0.0.2'
# Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826) # Prevent occasions where minitest is not bundled in packaged versions of ruby (see #3826)
gem 'minitest', '~> 5.7.0' gem 'minitest', '~> 5.7.0'
...@@ -283,7 +285,7 @@ group :development, :test do ...@@ -283,7 +285,7 @@ group :development, :test do
gem 'capybara', '~> 2.4.0' gem 'capybara', '~> 2.4.0'
gem 'capybara-screenshot', '~> 1.0.0' gem 'capybara-screenshot', '~> 1.0.0'
gem 'poltergeist', '~> 1.8.1' gem 'poltergeist', '~> 1.9.0'
gem 'teaspoon', '~> 1.0.0' gem 'teaspoon', '~> 1.0.0'
gem 'teaspoon-jasmine', '~> 2.2.0' gem 'teaspoon-jasmine', '~> 2.2.0'
......
...@@ -576,7 +576,7 @@ GEM ...@@ -576,7 +576,7 @@ GEM
parser (2.2.3.0) parser (2.2.3.0)
ast (>= 1.1, < 3.0) ast (>= 1.1, < 3.0)
pg (0.18.4) pg (0.18.4)
poltergeist (1.8.1) poltergeist (1.9.0)
capybara (~> 2.1) capybara (~> 2.1)
cliver (~> 0.3.1) cliver (~> 0.3.1)
multi_json (~> 1.0) multi_json (~> 1.0)
...@@ -703,6 +703,8 @@ GEM ...@@ -703,6 +703,8 @@ GEM
rspec-expectations (~> 3.3.0) rspec-expectations (~> 3.3.0)
rspec-mocks (~> 3.3.0) rspec-mocks (~> 3.3.0)
rspec-support (~> 3.3.0) rspec-support (~> 3.3.0)
rspec-retry (0.4.5)
rspec-core
rspec-support (3.3.0) rspec-support (3.3.0)
rubocop (0.35.1) rubocop (0.35.1)
astrolabe (~> 1.3) astrolabe (~> 1.3)
...@@ -788,6 +790,8 @@ GEM ...@@ -788,6 +790,8 @@ GEM
capybara (>= 2.0.0) capybara (>= 2.0.0)
railties (>= 3) railties (>= 3)
spinach (>= 0.4) spinach (>= 0.4)
spinach-rerun-reporter (0.0.2)
spinach (~> 0.8)
spring (1.6.4) spring (1.6.4)
spring-commands-rspec (1.0.4) spring-commands-rspec (1.0.4)
spring (>= 0.9.1) spring (>= 0.9.1)
...@@ -1011,7 +1015,7 @@ DEPENDENCIES ...@@ -1011,7 +1015,7 @@ DEPENDENCIES
org-ruby (~> 0.9.12) org-ruby (~> 0.9.12)
paranoia (~> 2.0) paranoia (~> 2.0)
pg (~> 0.18.2) pg (~> 0.18.2)
poltergeist (~> 1.8.1) poltergeist (~> 1.9.0)
pry-rails pry-rails
quiet_assets (~> 1.0.2) quiet_assets (~> 1.0.2)
rack-attack (~> 4.3.1) rack-attack (~> 4.3.1)
...@@ -1032,6 +1036,7 @@ DEPENDENCIES ...@@ -1032,6 +1036,7 @@ DEPENDENCIES
rouge (~> 1.10.1) rouge (~> 1.10.1)
rqrcode-rails3 (~> 0.1.7) rqrcode-rails3 (~> 0.1.7)
rspec-rails (~> 3.3.0) rspec-rails (~> 3.3.0)
rspec-retry
rubocop (~> 0.35.0) rubocop (~> 0.35.0)
ruby-fogbugz (~> 0.2.1) ruby-fogbugz (~> 0.2.1)
sanitize (~> 2.0) sanitize (~> 2.0)
...@@ -1050,6 +1055,7 @@ DEPENDENCIES ...@@ -1050,6 +1055,7 @@ DEPENDENCIES
six (~> 0.2.0) six (~> 0.2.0)
slack-notifier (~> 1.2.0) slack-notifier (~> 1.2.0)
spinach-rails (~> 0.2.1) spinach-rails (~> 0.2.1)
spinach-rerun-reporter (~> 0.0.2)
spring (~> 1.6.4) spring (~> 1.6.4)
spring-commands-rspec (~> 1.0.4) spring-commands-rspec (~> 1.0.4)
spring-commands-spinach (~> 1.0.0) spring-commands-spinach (~> 1.0.0)
......
...@@ -81,8 +81,9 @@ ...@@ -81,8 +81,9 @@
&::before { &::before {
content: "\f00c"; content: "\f00c";
position: absolute; position: absolute;
left: 4px; left: 5px;
top: 8px; top: 50%;
margin-top: -7px;
font: normal normal normal 14px/1 FontAwesome; font: normal normal normal 14px/1 FontAwesome;
font-size: inherit; font-size: inherit;
text-rendering: auto; text-rendering: auto;
...@@ -94,8 +95,8 @@ ...@@ -94,8 +95,8 @@
} }
.dropdown-header { .dropdown-header {
padding-left: 10px; padding-left: 5px;
padding-right: 10px; padding-right: 5px;
color: $dropdown-header-color; color: $dropdown-header-color;
font-size: 13px; font-size: 13px;
line-height: 22px; line-height: 22px;
......
...@@ -26,5 +26,5 @@ ...@@ -26,5 +26,5 @@
margin-right: 10px; margin-right: 10px;
font-size: $gl-font-size; font-size: $gl-font-size;
border: 1px solid; border: 1px solid;
line-height: 40px; line-height: 32px;
} }
# == FilterProjects
#
# Controller concern to handle projects filtering
# * by name
# * by archived state
#
module FilterProjects
extend ActiveSupport::Concern
def filter_projects(projects)
projects = projects.search(params[:filter_projects]) if params[:filter_projects].present?
projects = projects.non_archived if params[:archived].blank?
projects
end
end
class Dashboard::ProjectsController < Dashboard::ApplicationController class Dashboard::ProjectsController < Dashboard::ApplicationController
include FilterProjects
before_action :event_filter before_action :event_filter
def index def index
@projects = current_user.authorized_projects.sorted_by_activity.non_archived @projects = current_user.authorized_projects.sorted_by_activity
@projects = @projects.sort(@sort = params[:sort]) @projects = filter_projects(@projects)
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
terms = params[:filter_projects]
if terms.present?
@projects = @projects.search(terms)
end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank?
@last_push = current_user.recent_push @last_push = current_user.recent_push
respond_to do |format| respond_to do |format|
...@@ -32,16 +29,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController ...@@ -32,16 +29,11 @@ class Dashboard::ProjectsController < Dashboard::ApplicationController
def starred def starred
@projects = current_user.starred_projects.sorted_by_activity @projects = current_user.starred_projects.sorted_by_activity
@projects = filter_projects(@projects)
@projects = @projects.includes(:namespace, :forked_from_project, :tags) @projects = @projects.includes(:namespace, :forked_from_project, :tags)
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
terms = params[:filter_projects]
if terms.present?
@projects = @projects.search(terms)
end
@projects = @projects.page(params[:page]).per(PER_PAGE) if terms.blank?
@last_push = current_user.recent_push @last_push = current_user.recent_push
@groups = [] @groups = []
......
class Explore::ProjectsController < Explore::ApplicationController class Explore::ProjectsController < Explore::ApplicationController
include FilterProjects
def index def index
@projects = ProjectsFinder.new.execute(current_user) @projects = ProjectsFinder.new.execute(current_user)
@tags = @projects.tags_on(:tags) @tags = @projects.tags_on(:tags)
@projects = @projects.tagged_with(params[:tag]) if params[:tag].present? @projects = @projects.tagged_with(params[:tag]) if params[:tag].present?
@projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present? @projects = @projects.where(visibility_level: params[:visibility_level]) if params[:visibility_level].present?
@projects = @projects.non_archived @projects = filter_projects(@projects)
@projects = @projects.search(params[:search]) if params[:search].present?
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.sort(@sort = params[:sort]) @projects = @projects.sort(@sort = params[:sort])
@projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.includes(:namespace).page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
...@@ -22,8 +22,7 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -22,8 +22,7 @@ class Explore::ProjectsController < Explore::ApplicationController
def trending def trending
@projects = TrendingProjectsFinder.new.execute(current_user) @projects = TrendingProjectsFinder.new.execute(current_user)
@projects = @projects.non_archived @projects = filter_projects(@projects)
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present?
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
respond_to do |format| respond_to do |format|
...@@ -38,7 +37,7 @@ class Explore::ProjectsController < Explore::ApplicationController ...@@ -38,7 +37,7 @@ class Explore::ProjectsController < Explore::ApplicationController
def starred def starred
@projects = ProjectsFinder.new.execute(current_user) @projects = ProjectsFinder.new.execute(current_user)
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present? @projects = filter_projects(@projects)
@projects = @projects.reorder('star_count DESC') @projects = @projects.reorder('star_count DESC')
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
......
class GroupsController < Groups::ApplicationController class GroupsController < Groups::ApplicationController
include FilterProjects
include IssuesAction include IssuesAction
include MergeRequestsAction include MergeRequestsAction
...@@ -41,7 +42,8 @@ class GroupsController < Groups::ApplicationController ...@@ -41,7 +42,8 @@ class GroupsController < Groups::ApplicationController
def show def show
@last_push = current_user.recent_push if current_user @last_push = current_user.recent_push if current_user
@projects = @projects.includes(:namespace) @projects = @projects.includes(:namespace)
@projects = @projects.search(params[:filter_projects]) if params[:filter_projects].present? @projects = filter_projects(@projects)
@projects = @projects.sort(@sort = params[:sort])
@projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank? @projects = @projects.page(params[:page]).per(PER_PAGE) if params[:filter_projects].blank?
@shared_projects = @group.shared_projects @shared_projects = @group.shared_projects
...@@ -106,7 +108,7 @@ class GroupsController < Groups::ApplicationController ...@@ -106,7 +108,7 @@ class GroupsController < Groups::ApplicationController
end end
def load_projects def load_projects
@projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity.non_archived @projects ||= ProjectsFinder.new.execute(current_user, group: group).sorted_by_activity
end end
# Dont allow unauthorized access to group # Dont allow unauthorized access to group
......
...@@ -4,7 +4,7 @@ class SnippetsFinder ...@@ -4,7 +4,7 @@ class SnippetsFinder
case filter case filter
when :all then when :all then
snippets(current_user).fresh.non_expired snippets(current_user).fresh
when :by_user then when :by_user then
by_user(current_user, params[:user], params[:scope]) by_user(current_user, params[:user], params[:scope])
when :by_project when :by_project
...@@ -27,7 +27,7 @@ class SnippetsFinder ...@@ -27,7 +27,7 @@ class SnippetsFinder
end end
def by_user(current_user, user, scope) def by_user(current_user, user, scope)
snippets = user.snippets.fresh.non_expired snippets = user.snippets.fresh
return snippets.are_public unless current_user return snippets.are_public unless current_user
...@@ -48,7 +48,7 @@ class SnippetsFinder ...@@ -48,7 +48,7 @@ class SnippetsFinder
end end
def by_project(current_user, project) def by_project(current_user, project)
snippets = project.snippets.fresh.non_expired snippets = project.snippets.fresh
if current_user if current_user
if project.team.member?(current_user.id) if project.team.member?(current_user.id)
......
...@@ -72,7 +72,7 @@ module ApplicationHelper ...@@ -72,7 +72,7 @@ module ApplicationHelper
if user_or_email.is_a?(User) if user_or_email.is_a?(User)
user = user_or_email user = user_or_email
else else
user = User.find_by(email: user_or_email.downcase) user = User.find_by(email: user_or_email.try(:downcase))
end end
if user if user
......
...@@ -211,4 +211,15 @@ module CommitsHelper ...@@ -211,4 +211,15 @@ module CommitsHelper
def clean(string) def clean(string)
Sanitize.clean(string, remove_contents: true) Sanitize.clean(string, remove_contents: true)
end end
def limited_commits(commits)
if commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE
[
commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE),
commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE
]
else
[commits, 0]
end
end
end end
module ExploreHelper module ExploreHelper
def explore_projects_filter_path(options={}) def filter_projects_path(options={})
exist_opts = { exist_opts = {
sort: params[:sort], sort: params[:sort],
scope: params[:scope], scope: params[:scope],
...@@ -9,15 +9,7 @@ module ExploreHelper ...@@ -9,15 +9,7 @@ module ExploreHelper
} }
options = exist_opts.merge(options) options = exist_opts.merge(options)
path = request.path
path = if explore_controller?
explore_projects_path
elsif current_action?(:starred)
starred_dashboard_projects_path
else
dashboard_projects_path
end
path << "?#{options.to_param}" path << "?#{options.to_param}"
path path
end end
......
module SnippetsHelper module SnippetsHelper
def lifetime_select_options
options = [
['forever', nil],
['1 day', "#{Date.current + 1.day}"],
['1 week', "#{Date.current + 1.week}"],
['1 month', "#{Date.current + 1.month}"]
]
options_for_select(options)
end
def reliable_snippet_path(snippet) def reliable_snippet_path(snippet)
if snippet.project_id? if snippet.project_id?
namespace_project_snippet_path(snippet.project.namespace, namespace_project_snippet_path(snippet.project.namespace,
......
...@@ -16,6 +16,16 @@ module SortingHelper ...@@ -16,6 +16,16 @@ module SortingHelper
} }
end end
def projects_sort_options_hash
{
sort_value_name => sort_title_name,
sort_value_recently_updated => sort_title_recently_updated,
sort_value_oldest_updated => sort_title_oldest_updated,
sort_value_recently_created => sort_title_recently_created,
sort_value_oldest_created => sort_title_oldest_created,
}
end
def sort_title_oldest_updated def sort_title_oldest_updated
'Oldest updated' 'Oldest updated'
end end
......
...@@ -10,6 +10,7 @@ class Ability ...@@ -10,6 +10,7 @@ class Ability
when CommitStatus then commit_status_abilities(user, subject) when CommitStatus then commit_status_abilities(user, subject)
when Project then project_abilities(user, subject) when Project then project_abilities(user, subject)
when Issue then issue_abilities(user, subject) when Issue then issue_abilities(user, subject)
when ExternalIssue then external_issue_abilities(user, subject)
when Note then note_abilities(user, subject) when Note then note_abilities(user, subject)
when ProjectSnippet then project_snippet_abilities(user, subject) when ProjectSnippet then project_snippet_abilities(user, subject)
when PersonalSnippet then personal_snippet_abilities(user, subject) when PersonalSnippet then personal_snippet_abilities(user, subject)
...@@ -446,6 +447,10 @@ class Ability ...@@ -446,6 +447,10 @@ class Ability
end end
end end
def external_issue_abilities(user, subject)
project_abilities(user, subject.project)
end
private private
def named_abilities(name) def named_abilities(name)
......
...@@ -17,7 +17,7 @@ class MergeRequestDiff < ActiveRecord::Base ...@@ -17,7 +17,7 @@ class MergeRequestDiff < ActiveRecord::Base
include Sortable include Sortable
# Prevent store of diff if commits amount more then 500 # Prevent store of diff if commits amount more then 500
COMMITS_SAFE_SIZE = 500 COMMITS_SAFE_SIZE = 100
belongs_to :merge_request belongs_to :merge_request
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# file_name :string(255) # file_name :string(255)
# expires_at :datetime
# type :string(255) # type :string(255)
# visibility_level :integer default(0), not null # visibility_level :integer default(0), not null
# #
......
...@@ -163,6 +163,7 @@ class Project < ActiveRecord::Base ...@@ -163,6 +163,7 @@ class Project < ActiveRecord::Base
has_many :project_group_links, dependent: :destroy has_many :project_group_links, dependent: :destroy
has_many :invited_groups, through: :project_group_links, source: :group has_many :invited_groups, through: :project_group_links, source: :group
has_many :pages_domains, dependent: :destroy has_many :pages_domains, dependent: :destroy
has_many :todos, dependent: :destroy
has_one :import_data, dependent: :destroy, class_name: "ProjectImportData" has_one :import_data, dependent: :destroy, class_name: "ProjectImportData"
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# file_name :string(255) # file_name :string(255)
# expires_at :datetime
# type :string(255) # type :string(255)
# visibility_level :integer default(0), not null # visibility_level :integer default(0), not null
# #
...@@ -28,6 +27,4 @@ class ProjectSnippet < Snippet ...@@ -28,6 +27,4 @@ class ProjectSnippet < Snippet
# Scopes # Scopes
scope :fresh, -> { order("created_at DESC") } scope :fresh, -> { order("created_at DESC") }
scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) }
scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) }
end end
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# file_name :string(255) # file_name :string(255)
# expires_at :datetime
# type :string(255) # type :string(255)
# visibility_level :integer default(0), not null # visibility_level :integer default(0), not null
# #
...@@ -47,8 +46,6 @@ class Snippet < ActiveRecord::Base ...@@ -47,8 +46,6 @@ class Snippet < ActiveRecord::Base
scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) } scope :are_public, -> { where(visibility_level: Snippet::PUBLIC) }
scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) } scope :public_and_internal, -> { where(visibility_level: [Snippet::PUBLIC, Snippet::INTERNAL]) }
scope :fresh, -> { order("created_at DESC") } scope :fresh, -> { order("created_at DESC") }
scope :expired, -> { where(["expires_at IS NOT NULL AND expires_at < ?", Time.current]) }
scope :non_expired, -> { where(["expires_at IS NULL OR expires_at > ?", Time.current]) }
participant :author, :notes participant :author, :notes
...@@ -112,10 +109,6 @@ class Snippet < ActiveRecord::Base ...@@ -112,10 +109,6 @@ class Snippet < ActiveRecord::Base
nil nil
end end
def expired?
expires_at && expires_at < Time.current
end
def visibility_level_field def visibility_level_field
visibility_level visibility_level
end end
......
...@@ -124,7 +124,9 @@ class GitPushService < BaseService ...@@ -124,7 +124,9 @@ class GitPushService < BaseService
# a different branch. # a different branch.
closed_issues = commit.closes_issues(current_user) closed_issues = commit.closes_issues(current_user)
closed_issues.each do |issue| closed_issues.each do |issue|
Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit) if can?(current_user, :update_issue, issue)
Issues::CloseService.new(project, authors[commit], {}).execute(issue, commit)
end
end end
end end
......
...@@ -21,7 +21,9 @@ module MergeRequests ...@@ -21,7 +21,9 @@ module MergeRequests
closed_issues = merge_request.closes_issues(current_user) closed_issues = merge_request.closes_issues(current_user)
closed_issues.each do |issue| closed_issues.each do |issue|
Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request) if can?(current_user, :update_issue, issue)
Issues::CloseService.new(project, current_user, {}).execute(issue, merge_request)
end
end end
end end
......
...@@ -15,7 +15,7 @@ ...@@ -15,7 +15,7 @@
.nav-controls .nav-controls
= form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
= search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control input-short projects-list-filter', spellcheck: false, id: 'project-filter-form-field', tabindex: "2" = search_field_tag :filter_projects, params[:filter_projects], placeholder: 'Filter by name...', class: 'project-filter-form-field form-control input-short projects-list-filter', spellcheck: false, id: 'project-filter-form-field', tabindex: "2"
= render 'explore/projects/dropdown' = render 'shared/projects/dropdown'
- if current_user.can_create_project? - if current_user.can_create_project?
= link_to new_project_path, class: 'btn btn-new' do = link_to new_project_path, class: 'btn btn-new' do
= icon('plus') = icon('plus')
......
...@@ -4,7 +4,10 @@ ...@@ -4,7 +4,10 @@
.todo-title .todo-title
%span.author-name %span.author-name
= link_to_author todo - if todo.author
= link_to_author(todo)
- else
(removed)
%span.todo-label %span.todo-label
= todo_action_name(todo) = todo_action_name(todo)
= todo_target_link(todo) = todo_target_link(todo)
......
.dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light
- if @sort.present?
= sort_options_hash[@sort]
- else
= sort_title_recently_updated
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right
%li
= link_to explore_projects_filter_path(sort: sort_value_name) do
= sort_title_name
= link_to explore_projects_filter_path(sort: sort_value_recently_created) do
= sort_title_recently_created
= link_to explore_projects_filter_path(sort: sort_value_oldest_created) do
= sort_title_oldest_created
= link_to explore_projects_filter_path(sort: sort_value_recently_updated) do
= sort_title_recently_updated
= link_to explore_projects_filter_path(sort: sort_value_oldest_updated) do
= sort_title_oldest_updated
...@@ -10,11 +10,11 @@ ...@@ -10,11 +10,11 @@
%b.caret %b.caret
%ul.dropdown-menu %ul.dropdown-menu
%li %li
= link_to explore_projects_filter_path(visibility_level: nil) do = link_to filter_projects_path(visibility_level: nil) do
Any Any
- Gitlab::VisibilityLevel.values.each do |level| - Gitlab::VisibilityLevel.values.each do |level|
%li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' } %li{ class: (level.to_s == params[:visibility_level]) ? 'active' : 'light' }
= link_to explore_projects_filter_path(visibility_level: level) do = link_to filter_projects_path(visibility_level: level) do
= visibility_level_icon(level) = visibility_level_icon(level)
= visibility_level_label(level) = visibility_level_label(level)
...@@ -30,11 +30,11 @@ ...@@ -30,11 +30,11 @@
%b.caret %b.caret
%ul.dropdown-menu %ul.dropdown-menu
%li %li
= link_to explore_projects_filter_path(tag: nil) do = link_to filter_projects_path(tag: nil) do
Any Any
- @tags.each do |tag| - @tags.each do |tag|
%li{ class: (tag.name == params[:tag]) ? 'active' : 'light' } %li{ class: (tag.name == params[:tag]) ? 'active' : 'light' }
= link_to explore_projects_filter_path(tag: tag.name) do = link_to filter_projects_path(tag: tag.name) do
%i.fa.fa-tag = icon('tag')
= tag.name = tag.name
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
= form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f| = form_tag request.original_url, method: :get, class: 'project-filter-form', id: 'project-filter-form' do |f|
- if @projects.present? - if @projects.present?
= search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false = search_field_tag :filter_projects, nil, placeholder: 'Filter by name', class: 'projects-list-filter form-control', spellcheck: false
- if can? current_user, :create_projects, @group = render 'shared/projects/dropdown'
= link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new pull-right' do - if can? current_user, :create_projects, @group
= icon('plus') = link_to new_project_path(namespace_id: @group.id), class: 'btn btn-new pull-right' do
New Project = icon('plus')
New Project
= render 'shared/projects/list', projects: @projects, stars: false, skip_namespace: true = render 'shared/projects/list', projects: @projects, stars: false, skip_namespace: true
- commits, hidden = limited_commits(@commits)
- commits = Commit.decorate(commits, @project)
%div.panel.panel-default %div.panel.panel-default
.panel-heading .panel-heading
Commits (#{@commits.count}) Commits (#{@commits.count})
- if @commits.size > MergeRequestDiff::COMMITS_SAFE_SIZE - if hidden > 0
%ul.well-list %ul.well-list
- Commit.decorate(@commits.first(MergeRequestDiff::COMMITS_SAFE_SIZE), @project).each do |commit| - commits.each do |commit|
= render "projects/commits/inline_commit", commit: commit, project: @project = render "projects/commits/inline_commit", commit: commit, project: @project
%li.warning-row.unstyled %li.warning-row.unstyled
other #{@commits.size - MergeRequestDiff::COMMITS_SAFE_SIZE} commits hidden to prevent performance issues. #{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
- else - else
%ul.well-list= render Commit.decorate(@commits, @project), project: @project %ul.well-list= render commits, project: @project
- unless defined?(project) - unless defined?(project)
- project = @project - project = @project
- @commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits| - commits, hidden = limited_commits(@commits)
- commits.group_by { |c| c.committed_date.to_date }.sort.reverse.each do |day, commits|
.row.commits-row .row.commits-row
.col-md-2.hidden-xs.hidden-sm .col-md-2.hidden-xs.hidden-sm
%h5.commits-row-date %h5.commits-row-date
...@@ -13,3 +15,7 @@ ...@@ -13,3 +15,7 @@
%ul.bordered-list %ul.bordered-list
= render commits, project: project = render commits, project: project
%hr.lists-separator %hr.lists-separator
- if hidden > 0
.alert.alert-warning
#{number_with_delimiter(hidden)} additional commits have been omitted to prevent performance issues.
- @sort ||= sort_value_recently_updated
- archived = params[:archived]
.dropdown.inline
%button.dropdown-toggle.btn{type: 'button', 'data-toggle' => 'dropdown'}
%span.light
= projects_sort_options_hash[@sort]
%b.caret
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-selectable
%li.dropdown-header
Sort by
- projects_sort_options_hash.each do |value, title|
%li
= link_to filter_projects_path(sort: value, archived: archived), class: ("is-active" if @sort == value) do
= title
%li.divider
%li
= link_to filter_projects_path(sort: @sort, archived: nil), class: ("is-active" unless params[:archived].present?) do
Hide archived projects
%li
= link_to filter_projects_path(sort: @sort, archived: true), class: ("is-active" if params[:archived].present?) do
Show archived projects
class RemoveExpiresAtFromSnippets < ActiveRecord::Migration
def change
remove_column :snippets, :expires_at, :datetime
end
end
class FixTodos < ActiveRecord::Migration
def up
execute <<-SQL
DELETE FROM todos
WHERE todos.target_type IN ('Commit', 'ProjectSnippet')
OR NOT EXISTS (
SELECT *
FROM projects
WHERE projects.id = todos.project_id
)
SQL
end
def down
end
end
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20160302141317) do ActiveRecord::Schema.define(version: 20160309140734) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
...@@ -893,7 +893,6 @@ ActiveRecord::Schema.define(version: 20160302141317) do ...@@ -893,7 +893,6 @@ ActiveRecord::Schema.define(version: 20160302141317) do
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "file_name" t.string "file_name"
t.datetime "expires_at"
t.string "type" t.string "type"
t.integer "visibility_level", default: 0, null: false t.integer "visibility_level", default: 0, null: false
end end
...@@ -901,7 +900,6 @@ ActiveRecord::Schema.define(version: 20160302141317) do ...@@ -901,7 +900,6 @@ ActiveRecord::Schema.define(version: 20160302141317) do
add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree add_index "snippets", ["author_id"], name: "index_snippets_on_author_id", using: :btree
add_index "snippets", ["created_at", "id"], name: "index_snippets_on_created_at_and_id", using: :btree add_index "snippets", ["created_at", "id"], name: "index_snippets_on_created_at_and_id", using: :btree
add_index "snippets", ["created_at"], name: "index_snippets_on_created_at", using: :btree add_index "snippets", ["created_at"], name: "index_snippets_on_created_at", using: :btree
add_index "snippets", ["expires_at"], name: "index_snippets_on_expires_at", using: :btree
add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree add_index "snippets", ["project_id"], name: "index_snippets_on_project_id", using: :btree
add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree add_index "snippets", ["updated_at"], name: "index_snippets_on_updated_at", using: :btree
add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree add_index "snippets", ["visibility_level"], name: "index_snippets_on_visibility_level", using: :btree
......
...@@ -145,7 +145,6 @@ Parameters: ...@@ -145,7 +145,6 @@ Parameters:
"state": "active", "state": "active",
"created_at": "2013-09-30T13:46:01Z" "created_at": "2013-09-30T13:46:01Z"
}, },
"expires_at": null,
"updated_at": "2013-10-02T07:34:20Z", "updated_at": "2013-10-02T07:34:20Z",
"created_at": "2013-10-02T07:34:20Z" "created_at": "2013-10-02T07:34:20Z"
} }
......
...@@ -51,7 +51,6 @@ Parameters: ...@@ -51,7 +51,6 @@ Parameters:
"state": "active", "state": "active",
"created_at": "2012-05-23T08:00:58Z" "created_at": "2012-05-23T08:00:58Z"
}, },
"expires_at": null,
"updated_at": "2012-06-28T10:52:04Z", "updated_at": "2012-06-28T10:52:04Z",
"created_at": "2012-06-28T10:52:04Z" "created_at": "2012-06-28T10:52:04Z"
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
Although deprecated, if someone wants to make this script into a gem or otherwise improve it merge requests are welcome. Although deprecated, if someone wants to make this script into a gem or otherwise improve it merge requests are welcome.
*Make sure you view this [upgrade guide from the 'master' branch](../../../master/doc/update/upgrader.md) for the most up to date instructions.* *Make sure you view this [upgrade guide from the 'master' branch](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/update/upgrader.md) for the most up to date instructions.*
GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version. GitLab Upgrader - a ruby script that allows you easily upgrade GitLab to latest minor version.
......
...@@ -586,7 +586,6 @@ X-Gitlab-Event: Note Hook ...@@ -586,7 +586,6 @@ X-Gitlab-Event: Note Hook
"created_at": "2015-04-09 02:40:38 UTC", "created_at": "2015-04-09 02:40:38 UTC",
"updated_at": "2015-04-09 02:40:38 UTC", "updated_at": "2015-04-09 02:40:38 UTC",
"file_name": "test.rb", "file_name": "test.rb",
"expires_at": null,
"type": "ProjectSnippet", "type": "ProjectSnippet",
"visibility_level": 0 "visibility_level": 0
} }
......
...@@ -10,3 +10,8 @@ Feature: Dashboard Archived Projects ...@@ -10,3 +10,8 @@ Feature: Dashboard Archived Projects
Scenario: I should see non-archived projects on dashboard Scenario: I should see non-archived projects on dashboard
Then I should see "Shop" project link Then I should see "Shop" project link
And I should not see "Forum" project link And I should not see "Forum" project link
Scenario: I toggle show of archived projects on dashboard
When I click "Show archived projects" link
Then I should see "Shop" project link
And I should see "Forum" project link
...@@ -140,4 +140,4 @@ Feature: Explore Projects ...@@ -140,4 +140,4 @@ Feature: Explore Projects
When I visit the explore starred projects When I visit the explore starred projects
Then I should see project "Community" Then I should see project "Community"
And I should see project "Internal" And I should see project "Internal"
And I should see project "Archive" And I should not see project "Archive"
...@@ -19,4 +19,8 @@ class Spinach::Features::DashboardArchivedProjects < Spinach::FeatureSteps ...@@ -19,4 +19,8 @@ class Spinach::Features::DashboardArchivedProjects < Spinach::FeatureSteps
step 'I should see "Forum" project link' do step 'I should see "Forum" project link' do
expect(page).to have_link "Forum" expect(page).to have_link "Forum"
end end
step 'I click "Show archived projects" link' do
click_link "Show archived projects"
end
end end
...@@ -14,6 +14,7 @@ require 'sidekiq/testing/inline' ...@@ -14,6 +14,7 @@ require 'sidekiq/testing/inline'
require_relative 'capybara' require_relative 'capybara'
require_relative 'db_cleaner' require_relative 'db_cleaner'
require_relative 'rerun'
%w(select2_helper test_env repo_helpers license).each do |f| %w(select2_helper test_env repo_helpers license).each do |f|
require Rails.root.join('spec', 'support', f) require Rails.root.join('spec', 'support', f)
......
# The spinach-rerun-reporter doesn't define the on_undefined_step
# See it here: https://github.com/javierav/spinach-rerun-reporter/blob/master/lib/spinach/reporter/rerun.rb
module Spinach
class Reporter
class Rerun
def on_undefined_step(step_data, failure, step_definitions = nil)
super step_data, failure, step_definitions
# save feature file and scenario line
@rerun << "#{current_feature.filename}:#{current_scenario.line}"
end
end
end
end
...@@ -153,7 +153,7 @@ module API ...@@ -153,7 +153,7 @@ module API
class ProjectSnippet < Grape::Entity class ProjectSnippet < Grape::Entity
expose :id, :title, :file_name expose :id, :title, :file_name
expose :author, using: Entities::UserBasic expose :author, using: Entities::UserBasic
expose :expires_at, :updated_at, :created_at expose :updated_at, :created_at
end end
class ProjectEntity < Grape::Entity class ProjectEntity < Grape::Entity
......
...@@ -76,7 +76,7 @@ module Gitlab ...@@ -76,7 +76,7 @@ module Gitlab
project.issues.create!( project.issues.create!(
description: body, description: body,
title: issue["title"], title: issue["title"],
state: %w(resolved invalid duplicate wontfix).include?(issue["status"]) ? 'closed' : 'opened', state: %w(resolved invalid duplicate wontfix closed).include?(issue["status"]) ? 'closed' : 'opened',
author_id: gl_user_id(project, reporter) author_id: gl_user_id(project, reporter)
) )
end end
......
# This task will generate a standard and Retina sprite of all of the current
# Gemojione Emojis, with the accompanying SCSS map.
#
# It will not appear in `rake -T` output, and the dependent gems are not
# included in the Gemfile by default, because this task will only be needed
# occasionally, such as when new Emojis are added to Gemojione.
begin
require 'sprite_factory'
require 'rmagick'
rescue LoadError
# noop
end
namespace :gemojione do
task sprite: :environment do
check_requirements!
SIZE = 20
RETINA = SIZE * 2
Dir.mktmpdir do |tmpdir|
# Copy the Gemojione assets to the temporary folder for resizing
FileUtils.cp_r(Gemojione.index.images_path, tmpdir)
Dir.chdir(tmpdir) do
Dir["**/*.png"].each do |png|
resize!(File.join(tmpdir, png), SIZE)
end
end
style_path = Rails.root.join(*%w(app assets stylesheets pages emojis.scss))
# Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.cssurl = "image-url('$IMAGE')"
SpriteFactory.run!(File.join(tmpdir, 'images'), {
output_style: style_path,
output_image: "app/assets/images/emoji.png",
selector: '.emoji-',
style: :scss,
nocomments: true,
pngcrush: true,
layout: :packed
})
# SpriteFactory's SCSS is a bit too verbose for our purposes here, so
# let's simplify it
system(%Q(sed -i '' "s/width: #{SIZE}px; height: #{SIZE}px; background: image-url('emoji.png')/background-position:/" #{style_path}))
system(%Q(sed -i '' "s/ no-repeat//" #{style_path}))
# Append a generic rule that applies to all Emojis
File.open(style_path, 'a') do |f|
f.puts
f.puts <<-CSS.strip_heredoc
.emoji-icon {
background-image: image-url('emoji.png');
background-repeat: no-repeat;
height: #{SIZE}px;
width: #{SIZE}px;
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min--moz-device-pixel-ratio: 2),
only screen and (-o-min-device-pixel-ratio: 2/1),
only screen and (min-device-pixel-ratio: 2),
only screen and (min-resolution: 192dpi),
only screen and (min-resolution: 2dppx) {
background-image: image-url('emoji@2x.png');
background-size: 840px 820px;
}
}
CSS
end
end
# Now do it again but for Retina
Dir.mktmpdir do |tmpdir|
# Copy the Gemojione assets to the temporary folder for resizing
FileUtils.cp_r(Gemojione.index.images_path, tmpdir)
Dir.chdir(tmpdir) do
Dir["**/*.png"].each do |png|
resize!(File.join(tmpdir, png), RETINA)
end
end
# Combine the resized assets into a packed sprite and re-generate the SCSS
SpriteFactory.run!(File.join(tmpdir, 'images'), {
output_image: "app/assets/images/emoji@2x.png",
style: false,
nocomments: true,
pngcrush: true,
layout: :packed
})
end
end
def check_requirements!
return if defined?(SpriteFactory) && defined?(Magick)
puts <<-MSG.strip_heredoc
This task is disabled by default and should only be run when the Gemojione
gem is updated with new Emojis.
To enable this task, *temporarily* add the following lines to Gemfile and
re-bundle:
gem 'sprite-factory'
gem 'rmagick'
MSG
exit 1
end
def resize!(image_path, size)
# Resize the image in-place, save it, and free the object
image = Magick::Image.read(image_path).first
image.resize!(size, size)
image.write(image_path) { self.quality = 100 }
image.destroy!
end
end
...@@ -4,53 +4,59 @@ namespace :spinach do ...@@ -4,53 +4,59 @@ namespace :spinach do
namespace :project do namespace :project do
desc "GitLab | Spinach | Run project commits, issues and merge requests spinach features" desc "GitLab | Spinach | Run project commits, issues and merge requests spinach features"
task :half do task :half do
cmds = [ run_spinach_tests('@project_commits,@project_issues,@project_merge_requests')
%W(rake gitlab:setup),
%W(spinach --tags @project_commits,@project_issues,@project_merge_requests),
]
run_commands(cmds)
end end
desc "GitLab | Spinach | Run remaining project spinach features" desc "GitLab | Spinach | Run remaining project spinach features"
task :rest do task :rest do
cmds = [ run_spinach_tests('~@admin,~@dashboard,~@profile,~@public,~@snippets,~@project_commits,~@project_issues,~@project_merge_requests')
%W(rake gitlab:setup),
%W(spinach --tags ~@admin,~@dashboard,~@profile,~@public,~@snippets,~@project_commits,~@project_issues,~@project_merge_requests),
]
run_commands(cmds)
end end
end end
desc "GitLab | Spinach | Run project spinach features" desc "GitLab | Spinach | Run project spinach features"
task :project do task :project do
cmds = [ run_spinach_tests('~@admin,~@dashboard,~@profile,~@public,~@snippets')
%W(rake gitlab:setup),
%W(spinach --tags ~@admin,~@dashboard,~@profile,~@public,~@snippets),
]
run_commands(cmds)
end end
desc "GitLab | Spinach | Run other spinach features" desc "GitLab | Spinach | Run other spinach features"
task :other do task :other do
cmds = [ run_spinach_tests('@admin,@dashboard,@profile,@public,@snippets')
%W(rake gitlab:setup), end
%W(spinach --tags @admin,@dashboard,@profile,@public,@snippets),
] desc "GitLab | Spinach | Run other spinach features"
run_commands(cmds) task :builds do
run_spinach_tests('@builds')
end end
end end
desc "GitLab | Run spinach" desc "GitLab | Run spinach"
task :spinach do task :spinach do
cmds = [ run_spinach_tests(nil)
%W(rake gitlab:setup), end
%W(spinach),
] def run_command(cmd)
run_commands(cmds) system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd)
end end
def run_commands(cmds) def run_spinach_command(args)
cmds.each do |cmd| run_command(%w(spinach -r rerun) + args)
system({'RAILS_ENV' => 'test', 'force' => 'yes'}, *cmd) or raise("#{cmd} failed!") end
def run_spinach_tests(tags)
#run_command(%w(rake gitlab:setup)) or raise('gitlab:setup failed!')
success = run_spinach_command(%W(--tags #{tags}))
3.times do |_|
break if success
break unless File.exists?('tmp/spinach-rerun.txt')
tests = File.foreach('tmp/spinach-rerun.txt').map(&:chomp)
puts ''
puts "Spinach tests for #{tags}: Retrying tests... #{tests}".red
puts ''
sleep(3)
success = run_spinach_command(tests)
end end
raise("spinach tests for #{tags} failed!") unless success
end end
#!/bin/bash #!/bin/bash
retry() {
for i in $(seq 1 3); do
if eval "$@"; then
return 0
fi
sleep 3s
echo "Retrying..."
done
return 1
}
if [ -f /.dockerinit ]; then if [ -f /.dockerinit ]; then
mkdir -p vendor mkdir -p vendor
if [ ! -e vendor/phantomjs_1.9.8-0jessie_amd64.deb ]; then
# Install phantomjs package
pushd vendor
if [ ! -e phantomjs_1.9.8-0jessie_amd64.deb ]; then
wget -q https://gitlab.com/axil/phantomjs-debian/raw/master/phantomjs_1.9.8-0jessie_amd64.deb wget -q https://gitlab.com/axil/phantomjs-debian/raw/master/phantomjs_1.9.8-0jessie_amd64.deb
mv phantomjs_1.9.8-0jessie_amd64.deb vendor/
fi fi
dpkg -i vendor/phantomjs_1.9.8-0jessie_amd64.deb dpkg -i phantomjs_1.9.8-0jessie_amd64.deb
popd
apt-get update -qq # Try to install packages
apt-get -o dir::cache::archives="vendor/apt" install -y -qq --force-yes \ retry 'apt-get update -yqqq; apt-get -o dir::cache::archives="vendor/apt" install -y -qq --force-yes \
libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client unzip libicu-dev libkrb5-dev cmake nodejs postgresql-client mysql-client unzip'
cp config/database.yml.mysql config/database.yml cp config/database.yml.mysql config/database.yml
sed -i 's/username:.*/username: root/g' config/database.yml sed -i 's/username:.*/username: root/g' config/database.yml
...@@ -20,7 +34,7 @@ if [ -f /.dockerinit ]; then ...@@ -20,7 +34,7 @@ if [ -f /.dockerinit ]; then
cp config/resque.yml.example config/resque.yml cp config/resque.yml.example config/resque.yml
sed -i 's/localhost/redis/g' config/resque.yml sed -i 's/localhost/redis/g' config/resque.yml
export FLAGS=(--path vendor) export FLAGS=(--path vendor --retry 3)
else else
export PATH=$HOME/bin:/usr/local/bin:/usr/bin:/bin export PATH=$HOME/bin:/usr/local/bin:/usr/bin:/bin
cp config/database.yml.mysql config/database.yml cp config/database.yml.mysql config/database.yml
......
...@@ -2,7 +2,7 @@ require 'spec_helper' ...@@ -2,7 +2,7 @@ require 'spec_helper'
describe Projects::ForksController do describe Projects::ForksController do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:project) { create(:project, visibility_level: Project::PUBLIC) } let(:project) { create(:project, :public) }
let(:forked_project) { Projects::ForkService.new(project, user).execute } let(:forked_project) { Projects::ForkService.new(project, user).execute }
let(:group) { create(:group, owner: forked_project.creator) } let(:group) { create(:group, owner: forked_project.creator) }
......
FactoryGirl.define do FactoryGirl.define do
factory :personal_snippet, parent: :snippet, class: :PersonalSnippet do factory :personal_snippet, parent: :snippet, class: :PersonalSnippet do
trait :public do
visibility_level PersonalSnippet::PUBLIC
end
trait :internal do
visibility_level PersonalSnippet::INTERNAL
end
trait :private do
visibility_level PersonalSnippet::PRIVATE
end
end end
end end
FactoryGirl.define do FactoryGirl.define do
factory :project_snippet do factory :project_snippet, parent: :snippet, class: :ProjectSnippet do
project project
author
title
content
file_name
end end
end end
...@@ -12,5 +12,17 @@ FactoryGirl.define do ...@@ -12,5 +12,17 @@ FactoryGirl.define do
title title
content content
file_name file_name
trait :public do
visibility_level Snippet::PUBLIC
end
trait :internal do
visibility_level Snippet::INTERNAL
end
trait :private do
visibility_level Snippet::PRIVATE
end
end end
end end
...@@ -5,15 +5,14 @@ describe SnippetsFinder do ...@@ -5,15 +5,14 @@ describe SnippetsFinder do
let(:user1) { create :user } let(:user1) { create :user }
let(:group) { create :group } let(:group) { create :group }
let(:project1) { create(:empty_project, :public, group: group) } let(:project1) { create(:empty_project, :public, group: group) }
let(:project2) { create(:empty_project, :private, group: group) } let(:project2) { create(:empty_project, :private, group: group) }
context ':all filter' do context ':all filter' do
before do before do
@snippet1 = create(:personal_snippet, visibility_level: Snippet::PRIVATE) @snippet1 = create(:personal_snippet, :private)
@snippet2 = create(:personal_snippet, visibility_level: Snippet::INTERNAL) @snippet2 = create(:personal_snippet, :internal)
@snippet3 = create(:personal_snippet, visibility_level: Snippet::PUBLIC) @snippet3 = create(:personal_snippet, :public)
end end
it "returns all private and internal snippets" do it "returns all private and internal snippets" do
...@@ -31,9 +30,9 @@ describe SnippetsFinder do ...@@ -31,9 +30,9 @@ describe SnippetsFinder do
context ':by_user filter' do context ':by_user filter' do
before do before do
@snippet1 = create(:personal_snippet, visibility_level: Snippet::PRIVATE, author: user) @snippet1 = create(:personal_snippet, :private, author: user)
@snippet2 = create(:personal_snippet, visibility_level: Snippet::INTERNAL, author: user) @snippet2 = create(:personal_snippet, :internal, author: user)
@snippet3 = create(:personal_snippet, visibility_level: Snippet::PUBLIC, author: user) @snippet3 = create(:personal_snippet, :public, author: user)
end end
it "returns all public and internal snippets" do it "returns all public and internal snippets" do
...@@ -75,9 +74,9 @@ describe SnippetsFinder do ...@@ -75,9 +74,9 @@ describe SnippetsFinder do
context 'by_project filter' do context 'by_project filter' do
before do before do
@snippet1 = create(:project_snippet, visibility_level: Snippet::PRIVATE, project: project1) @snippet1 = create(:project_snippet, :private, project: project1)
@snippet2 = create(:project_snippet, visibility_level: Snippet::INTERNAL, project: project1) @snippet2 = create(:project_snippet, :internal, project: project1)
@snippet3 = create(:project_snippet, visibility_level: Snippet::PUBLIC, project: project1) @snippet3 = create(:project_snippet, :public, project: project1)
end end
it "returns public snippets for unauthorized user" do it "returns public snippets for unauthorized user" do
...@@ -93,7 +92,7 @@ describe SnippetsFinder do ...@@ -93,7 +92,7 @@ describe SnippetsFinder do
end end
it "returns all snippets for project members" do it "returns all snippets for project members" do
project1.team << [user, :developer] project1.team << [user, :developer]
snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1) snippets = SnippetsFinder.new.execute(user, filter: :by_project, project: project1)
expect(snippets).to include(@snippet1, @snippet2, @snippet3) expect(snippets).to include(@snippet1, @snippet2, @snippet3)
end end
......
...@@ -58,7 +58,7 @@ describe VisibilityLevelHelper do ...@@ -58,7 +58,7 @@ describe VisibilityLevelHelper do
describe "skip_level?" do describe "skip_level?" do
describe "forks" do describe "forks" do
let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::INTERNAL) } let(:project) { create(:project, :internal) }
let(:fork_project) { create(:forked_project_with_submodules) } let(:fork_project) { create(:forked_project_with_submodules) }
before do before do
...@@ -74,7 +74,7 @@ describe VisibilityLevelHelper do ...@@ -74,7 +74,7 @@ describe VisibilityLevelHelper do
end end
describe "non-forked project" do describe "non-forked project" do
let(:project) { create(:project, visibility_level: Gitlab::VisibilityLevel::INTERNAL) } let(:project) { create(:project, :internal) }
it "skips levels" do it "skips levels" do
expect(skip_level?(project, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey expect(skip_level?(project, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey
...@@ -84,7 +84,7 @@ describe VisibilityLevelHelper do ...@@ -84,7 +84,7 @@ describe VisibilityLevelHelper do
end end
describe "Snippet" do describe "Snippet" do
let(:snippet) { create(:snippet, visibility_level: Gitlab::VisibilityLevel::INTERNAL) } let(:snippet) { create(:snippet, :internal) }
it "skips levels" do it "skips levels" do
expect(skip_level?(snippet, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey expect(skip_level?(snippet, Gitlab::VisibilityLevel::PUBLIC)).to be_falsey
......
require 'spec_helper'
describe Gitlab::BitbucketImport::Importer, lib: true do
before do
Gitlab.config.omniauth.providers << OpenStruct.new(app_id: "asd123", app_secret: "asd123", name: "bitbucket")
end
let(:statuses) do
[
"open",
"resolved",
"on hold",
"invalid",
"duplicate",
"wontfix",
"closed" # undocumented status
]
end
let(:sample_issues_statuses) do
issues = []
statuses.map.with_index do |status, index|
issues << {
local_id: index,
status: status,
title: "Issue #{index}",
content: "Some content to issue #{index}"
}
end
issues
end
let(:project_identifier) { 'namespace/repo' }
let(:data) do
{
bb_session: {
bitbucket_access_token: "123456",
bitbucket_access_token_secret: "secret"
}
}
end
let(:project) do
create(
:project,
import_source: project_identifier,
import_data: ProjectImportData.new(data: data)
)
end
let(:importer) { Gitlab::BitbucketImport::Importer.new(project) }
let(:issues_statuses_sample_data) do
{
count: sample_issues_statuses.count,
issues: sample_issues_statuses
}
end
context 'issues statuses' do
before do
stub_request(
:get,
"https://bitbucket.org/api/1.0/repositories/#{project_identifier}"
).to_return(status: 200, body: { has_issues: true }.to_json)
stub_request(
:get,
"https://bitbucket.org/api/1.0/repositories/#{project_identifier}/issues?limit=50&sort=utc_created_on&start=0"
).to_return(status: 200, body: issues_statuses_sample_data.to_json)
sample_issues_statuses.each_with_index do |issue, index|
stub_request(
:get,
"https://bitbucket.org/api/1.0/repositories/#{project_identifier}/issues/#{issue[:local_id]}/comments"
).to_return(
status: 200,
body: [{ author_info: { username: "username" }, utc_created_on: index }].to_json
)
end
end
it 'map statuses to open or closed' do
importer.execute
expect(project.issues.where(state: "closed").size).to eq(5)
expect(project.issues.where(state: "opened").size).to eq(2)
end
end
end
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# file_name :string(255) # file_name :string(255)
# expires_at :datetime
# type :string(255) # type :string(255)
# visibility_level :integer default(0), not null # visibility_level :integer default(0), not null
# #
......
...@@ -69,6 +69,7 @@ describe Project, models: true do ...@@ -69,6 +69,7 @@ describe Project, models: true do
it { is_expected.to have_many(:variables) } it { is_expected.to have_many(:variables) }
it { is_expected.to have_many(:triggers) } it { is_expected.to have_many(:triggers) }
it { is_expected.to have_many(:pages_domains) } it { is_expected.to have_many(:pages_domains) }
it { is_expected.to have_many(:todos).dependent(:destroy) }
end end
describe 'modules' do describe 'modules' do
...@@ -600,7 +601,7 @@ describe Project, models: true do ...@@ -600,7 +601,7 @@ describe Project, models: true do
end end
describe '#visibility_level_allowed?' do describe '#visibility_level_allowed?' do
let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL } let(:project) { create(:project, :internal) }
context 'when checking on non-forked project' do context 'when checking on non-forked project' do
it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy } it { expect(project.visibility_level_allowed?(Gitlab::VisibilityLevel::PRIVATE)).to be_truthy }
......
...@@ -10,7 +10,6 @@ ...@@ -10,7 +10,6 @@
# created_at :datetime # created_at :datetime
# updated_at :datetime # updated_at :datetime
# file_name :string(255) # file_name :string(255)
# expires_at :datetime
# type :string(255) # type :string(255)
# visibility_level :integer default(0), not null # visibility_level :integer default(0), not null
# #
......
...@@ -287,22 +287,24 @@ describe GitPushService, services: true do ...@@ -287,22 +287,24 @@ describe GitPushService, services: true do
allow(project.repository).to receive(:commits_between). allow(project.repository).to receive(:commits_between).
and_return([closing_commit]) and_return([closing_commit])
project.team << [commit_author, :master]
end end
context "to default branches" do context "to default branches" do
it "closes issues" do it "closes issues" do
execute_service(project, user, @oldrev, @newrev, @ref ) execute_service(project, commit_author, @oldrev, @newrev, @ref )
expect(Issue.find(issue.id)).to be_closed expect(Issue.find(issue.id)).to be_closed
end end
it "adds a note indicating that the issue is now closed" do it "adds a note indicating that the issue is now closed" do
expect(SystemNoteService).to receive(:change_status).with(issue, project, commit_author, "closed", closing_commit) expect(SystemNoteService).to receive(:change_status).with(issue, project, commit_author, "closed", closing_commit)
execute_service(project, user, @oldrev, @newrev, @ref ) execute_service(project, commit_author, @oldrev, @newrev, @ref )
end end
it "doesn't create additional cross-reference notes" do it "doesn't create additional cross-reference notes" do
expect(SystemNoteService).not_to receive(:cross_reference) expect(SystemNoteService).not_to receive(:cross_reference)
execute_service(project, user, @oldrev, @newrev, @ref ) execute_service(project, commit_author, @oldrev, @newrev, @ref )
end end
it "doesn't close issues when external issue tracker is in use" do it "doesn't close issues when external issue tracker is in use" do
...@@ -310,7 +312,7 @@ describe GitPushService, services: true do ...@@ -310,7 +312,7 @@ describe GitPushService, services: true do
# The push still shouldn't create cross-reference notes. # The push still shouldn't create cross-reference notes.
expect do expect do
execute_service(project, user, @oldrev, @newrev, 'refs/heads/hurf' ) execute_service(project, commit_author, @oldrev, @newrev, 'refs/heads/hurf' )
end.not_to change { Note.where(project_id: project.id, system: true).count } end.not_to change { Note.where(project_id: project.id, system: true).count }
end end
end end
...@@ -332,7 +334,6 @@ describe GitPushService, services: true do ...@@ -332,7 +334,6 @@ describe GitPushService, services: true do
end end
end end
# EE-only tests
context "for jira issue tracker" do context "for jira issue tracker" do
include JiraServiceHelper include JiraServiceHelper
...@@ -382,7 +383,7 @@ describe GitPushService, services: true do ...@@ -382,7 +383,7 @@ describe GitPushService, services: true do
} }
}.to_json }.to_json
execute_service(project, user, @oldrev, @newrev, @ref ) execute_service(project, commit_author, @oldrev, @newrev, @ref )
expect(WebMock).to have_requested(:post, jira_api_transition_url).with( expect(WebMock).to have_requested(:post, jira_api_transition_url).with(
body: transition_body body: transition_body
).once ).once
...@@ -393,7 +394,7 @@ describe GitPushService, services: true do ...@@ -393,7 +394,7 @@ describe GitPushService, services: true do
body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]." body: "Issue solved with [#{closing_commit.id}|http://localhost/#{project.path_with_namespace}/commit/#{closing_commit.id}]."
}.to_json }.to_json
execute_service(project, user, @oldrev, @newrev, @ref ) execute_service(project, commit_author, @oldrev, @newrev, @ref )
expect(WebMock).to have_requested(:post, jira_api_comment_url).with( expect(WebMock).to have_requested(:post, jira_api_comment_url).with(
body: comment_body body: comment_body
).once ).once
......
...@@ -102,8 +102,8 @@ describe Projects::UpdateService, services: true do ...@@ -102,8 +102,8 @@ describe Projects::UpdateService, services: true do
describe :visibility_level do describe :visibility_level do
let(:user) { create :user, admin: true } let(:user) { create :user, admin: true }
let(:project) { create :project, visibility_level: Gitlab::VisibilityLevel::INTERNAL } let(:project) { create(:project, :internal) }
let(:forked_project) { create :forked_project_with_submodules, visibility_level: Gitlab::VisibilityLevel::INTERNAL } let(:forked_project) { create(:forked_project_with_submodules, :internal) }
let(:opts) { {} } let(:opts) { {} }
before do before do
......
...@@ -15,6 +15,7 @@ require 'rspec/rails' ...@@ -15,6 +15,7 @@ require 'rspec/rails'
require 'shoulda/matchers' require 'shoulda/matchers'
require 'sidekiq/testing/inline' require 'sidekiq/testing/inline'
require 'benchmark/ips' require 'benchmark/ips'
require 'rspec/retry'
# Requires supporting ruby files with custom matchers and macros, etc, # Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories. # in spec/support/ and its subdirectories.
...@@ -25,6 +26,9 @@ RSpec.configure do |config| ...@@ -25,6 +26,9 @@ RSpec.configure do |config|
config.use_instantiated_fixtures = false config.use_instantiated_fixtures = false
config.mock_with :rspec config.mock_with :rspec
config.verbose_retry = true
config.display_try_failure_messages = true
config.include Devise::TestHelpers, type: :controller config.include Devise::TestHelpers, type: :controller
config.include LoginHelpers, type: :feature config.include LoginHelpers, type: :feature
config.include LoginHelpers, type: :request config.include LoginHelpers, type: :request
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment