Commit 21a1e156 authored by Alfredo Sumaran's avatar Alfredo Sumaran

Merge remote-tracking branch 'origin/master' into issue_3799

parents e0c07b5e d5398e96
...@@ -4,6 +4,7 @@ v 8.8.0 (unreleased) ...@@ -4,6 +4,7 @@ v 8.8.0 (unreleased)
v 8.7.0 (unreleased) v 8.7.0 (unreleased)
- Gitlab::GitAccess and Gitlab::GitAccessWiki are now instrumented - Gitlab::GitAccess and Gitlab::GitAccessWiki are now instrumented
- Fix vulnerability that made it possible to gain access to private labels and milestones
- The number of InfluxDB points stored per UDP packet can now be configured - The number of InfluxDB points stored per UDP packet can now be configured
- Fix error when cross-project label reference used with non-existent project - Fix error when cross-project label reference used with non-existent project
- Transactions for /internal/allowed now have an "action" tag set - Transactions for /internal/allowed now have an "action" tag set
...@@ -54,7 +55,7 @@ v 8.7.0 (unreleased) ...@@ -54,7 +55,7 @@ v 8.7.0 (unreleased)
- Add links to CI setup documentation from project settings and builds pages - Add links to CI setup documentation from project settings and builds pages
- Display project members page to all members - Display project members page to all members
- Handle nil descriptions in Slack issue messages (Stan Hu) - Handle nil descriptions in Slack issue messages (Stan Hu)
- Add automated repository integrity checks - Add automated repository integrity checks (OFF by default)
- API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling) - API: Expose open_issues_count, closed_issues_count, open_merge_requests_count for labels (Robert Schilling)
- API: Ability to star and unstar a project (Robert Schilling) - API: Ability to star and unstar a project (Robert Schilling)
- Add default scope to projects to exclude projects pending deletion - Add default scope to projects to exclude projects pending deletion
...@@ -81,6 +82,7 @@ v 8.7.0 (unreleased) ...@@ -81,6 +82,7 @@ v 8.7.0 (unreleased)
- Remove "Congratulations!" tweet button on newly-created project. (Connor Shea) - Remove "Congratulations!" tweet button on newly-created project. (Connor Shea)
- Fix admin/projects when using visibility levels on search (PotHix) - Fix admin/projects when using visibility levels on search (PotHix)
- Build status notifications - Build status notifications
- Update email confirmation interface
- API: Expose user location (Robert Schilling) - API: Expose user location (Robert Schilling)
- API: Do not leak group existence via return code (Robert Schilling) - API: Do not leak group existence via return code (Robert Schilling)
- ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591 - ClosingIssueExtractor regex now also works with colons. e.g. "Fixes: #1234" !3591
......
...@@ -31,7 +31,7 @@ class @LabelsSelect ...@@ -31,7 +31,7 @@ class @LabelsSelect
labelHTMLTemplate = _.template( labelHTMLTemplate = _.template(
'<% _.each(labels, function(label){ %> '<% _.each(labels, function(label){ %>
<a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= _.escape(label.title) %>"> <a href="<%= ["",issueURLSplit[1], issueURLSplit[2],""].join("/") %>issues?label_name=<%= _.escape(label.title) %>">
<span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>;"> <span class="label has-tooltip color-label" title="<%= _.escape(label.description) %>" style="background-color: <%= label.color %>; color: <%= label.text_color %>;">
<%= _.escape(label.title) %> <%= _.escape(label.title) %>
</span> </span>
</a> </a>
......
...@@ -144,6 +144,10 @@ ...@@ -144,6 +144,10 @@
} }
} }
.btn-lg {
padding: 12px 20px;
}
.btn-transparent { .btn-transparent {
color: $btn-transparent-color; color: $btn-transparent-color;
background-color: transparent; background-color: transparent;
......
...@@ -131,6 +131,11 @@ ...@@ -131,6 +131,11 @@
td.line-numbers { td.line-numbers {
float: none; float: none;
border-left: 1px solid #ddd; border-left: 1px solid #ddd;
i {
float: none;
margin-right: 0;
}
} }
td.lines { td.lines {
padding: 0; padding: 0;
......
.well-confirmation {
margin-bottom: 20px;
border-bottom: 1px solid #eee;
> h1 {
font-weight: 400;
}
.lead {
margin-bottom: 20px;
}
}
.confirmation-content {
a {
color: $md-link-color;
}
}
class ConfirmationsController < Devise::ConfirmationsController class ConfirmationsController < Devise::ConfirmationsController
def almost_there
flash[:notice] = nil
render layout: "devise_empty"
end
protected protected
def after_resending_confirmation_instructions_path_for(resource)
users_almost_there_path
end
def after_confirmation_path_for(resource_name, resource) def after_confirmation_path_for(resource_name, resource)
if signed_in?(resource_name) if signed_in?(resource_name)
after_sign_in_path_for(resource) after_sign_in_path_for(resource)
......
...@@ -83,8 +83,7 @@ class Projects::ApplicationController < ApplicationController ...@@ -83,8 +83,7 @@ class Projects::ApplicationController < ApplicationController
end end
def apply_diff_view_cookie! def apply_diff_view_cookie!
view = params[:view] || cookies[:diff_view] cookies.permanent[:diff_view] = params.delete(:view) if params[:view].present?
cookies.permanent[:diff_view] = params[:view] = view if view
end end
def builds_enabled def builds_enabled
......
...@@ -101,7 +101,6 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -101,7 +101,6 @@ class Projects::IssuesController < Projects::ApplicationController
end end
respond_to do |format| respond_to do |format|
format.js
format.html do format.html do
if @issue.valid? if @issue.valid?
redirect_to issue_path(@issue) redirect_to issue_path(@issue)
...@@ -110,7 +109,7 @@ class Projects::IssuesController < Projects::ApplicationController ...@@ -110,7 +109,7 @@ class Projects::IssuesController < Projects::ApplicationController
end end
end end
format.json do format.json do
render json: @issue.to_json(include: [:milestone, :labels, assignee: { methods: :avatar_url }]) render json: @issue.to_json(include: [:milestone, labels: { methods: :text_color }, assignee: { methods: :avatar_url }])
end end
end end
end end
......
...@@ -149,13 +149,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController ...@@ -149,13 +149,12 @@ class Projects::MergeRequestsController < Projects::ApplicationController
if @merge_request.valid? if @merge_request.valid?
respond_to do |format| respond_to do |format|
format.js
format.html do format.html do
redirect_to([@merge_request.target_project.namespace.becomes(Namespace), redirect_to([@merge_request.target_project.namespace.becomes(Namespace),
@merge_request.target_project, @merge_request]) @merge_request.target_project, @merge_request])
end end
format.json do format.json do
render json: @merge_request.to_json(include: [:milestone, :labels, assignee: { methods: :avatar_url }]) render json: @merge_request.to_json(include: [:milestone, labels: { methods: :text_color }, assignee: { methods: :avatar_url }])
end end
end end
else else
......
...@@ -31,11 +31,11 @@ class RegistrationsController < Devise::RegistrationsController ...@@ -31,11 +31,11 @@ class RegistrationsController < Devise::RegistrationsController
end end
def after_sign_up_path_for(_resource) def after_sign_up_path_for(_resource)
new_user_session_path users_almost_there_path
end end
def after_inactive_sign_up_path_for(_resource) def after_inactive_sign_up_path_for(_resource)
new_user_session_path users_almost_there_path
end end
private private
......
...@@ -278,9 +278,7 @@ class IssuableFinder ...@@ -278,9 +278,7 @@ class IssuableFinder
end end
end end
# When filtering by multiple labels we may end up duplicating issues (if one items
# has multiple labels). This ensures we only return unique issues.
items.distinct
end end
def by_due_date(items) def by_due_date(items)
......
...@@ -9,7 +9,13 @@ module DiffHelper ...@@ -9,7 +9,13 @@ module DiffHelper
end end
def diff_view def diff_view
params[:view] == 'parallel' ? 'parallel' : 'inline' diff_views = %w(inline parallel)
if diff_views.include?(cookies[:diff_view])
cookies[:diff_view]
else
diff_views.first
end
end end
def diff_hard_limit_enabled? def diff_hard_limit_enabled?
......
...@@ -37,8 +37,9 @@ class IssuableBaseService < BaseService ...@@ -37,8 +37,9 @@ class IssuableBaseService < BaseService
end end
def filter_params(issuable_ability_name = :issue) def filter_params(issuable_ability_name = :issue)
params[:assignee_id] = "" if params[:assignee_id] == IssuableFinder::NONE filter_assignee
params[:milestone_id] = "" if params[:milestone_id] == IssuableFinder::NONE filter_milestone
filter_labels
ability = :"admin_#{issuable_ability_name}" ability = :"admin_#{issuable_ability_name}"
...@@ -49,6 +50,29 @@ class IssuableBaseService < BaseService ...@@ -49,6 +50,29 @@ class IssuableBaseService < BaseService
end end
end end
def filter_assignee
if params[:assignee_id] == IssuableFinder::NONE
params[:assignee_id] = ''
end
end
def filter_milestone
milestone_id = params[:milestone_id]
return unless milestone_id
if milestone_id == IssuableFinder::NONE ||
project.milestones.find_by(id: milestone_id).nil?
params[:milestone_id] = ''
end
end
def filter_labels
return if params[:label_ids].to_a.empty?
params[:label_ids] =
project.labels.where(id: params[:label_ids]).pluck(:id)
end
def update(issuable) def update(issuable)
change_state(issuable) change_state(issuable)
filter_params filter_params
......
.well-confirmation.text-center
%h1.prepend-top-0
Almost there...
%p.lead
Please check your email to confirm your account
%p.confirmation-content.text-center
No confirmation email received? Please check your spam folder or
.append-bottom-20.prepend-top-20.text-center
%a.btn.btn-lg.btn-success{ href: new_user_confirmation_path }
Request new confirmation email
!!! 5
%html{ lang: "en"}
= render "layouts/head"
%body.ui_charcoal.login-page.application.navless
= render "layouts/header/empty"
= render "layouts/broadcast"
.container.navless-container
.content
= render "layouts/flash"
= yield
%hr
.container
.footer-links
= link_to "Explore", explore_root_path
= link_to "Help", help_path
= link_to "About GitLab", "https://about.gitlab.com/"
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
- page_card_attributes @merge_request.card_attributes - page_card_attributes @merge_request.card_attributes
- header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project)) - header_title project_title(@project, "Merge Requests", namespace_project_merge_requests_path(@project.namespace, @project))
- if params[:view] == 'parallel' - if diff_view == 'parallel'
- fluid_layout true - fluid_layout true
.merge-request{'data-url' => merge_request_path(@merge_request)} .merge-request{'data-url' => merge_request_path(@merge_request)}
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
%a.btn.btn-default.issuable-pager.disabled{href: '#'} %a.btn.btn-default.issuable-pager.disabled{href: '#'}
Next Next
= form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f| = form_for [@project.namespace.becomes(Namespace), @project, issuable], remote: true, format: :json, html: {class: 'issuable-context-form inline-update js-issuable-update'} do |f|
.block.assignee .block.assignee
.sidebar-collapsed-icon.sidebar-collapsed-user{data: {toggle: "tooltip", placement: "left", container: "body"}, title: (issuable.assignee.to_reference if issuable.assignee)} .sidebar-collapsed-icon.sidebar-collapsed-user{data: {toggle: "tooltip", placement: "left", container: "body"}, title: (issuable.assignee.to_reference if issuable.assignee)}
- if issuable.assignee - if issuable.assignee
......
...@@ -418,6 +418,7 @@ Rails.application.routes.draw do ...@@ -418,6 +418,7 @@ Rails.application.routes.draw do
devise_scope :user do devise_scope :user do
get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error get '/users/auth/:provider/omniauth_error' => 'omniauth_callbacks#omniauth_error', as: :omniauth_error
get '/users/almost_there' => 'confirmations#almost_there'
end end
root to: "root#index" root to: "root#index"
......
class DisableRepositoryChecks < ActiveRecord::Migration
def up
change_column_default :application_settings, :repository_checks_enabled, false
execute 'UPDATE application_settings SET repository_checks_enabled = false'
end
def down
change_column_default :application_settings, :repository_checks_enabled, true
execute 'UPDATE application_settings SET repository_checks_enabled = true'
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: 20160419120017) do ActiveRecord::Schema.define(version: 20160421130527) 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"
...@@ -77,7 +77,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do ...@@ -77,7 +77,7 @@ ActiveRecord::Schema.define(version: 20160419120017) do
t.string "akismet_api_key" t.string "akismet_api_key"
t.boolean "email_author_in_body", default: false t.boolean "email_author_in_body", default: false
t.integer "default_group_visibility" t.integer "default_group_visibility"
t.boolean "repository_checks_enabled", default: true t.boolean "repository_checks_enabled", default: false
t.integer "metrics_packet_size", default: 1 t.integer "metrics_packet_size", default: 1
t.text "shared_runners_text" t.text "shared_runners_text"
end end
......
# Repository checks # Repository checks
>**Note:** >**Note:**
This feature was [introduced][ce-3232] in GitLab 8.7. This feature was [introduced][ce-3232] in GitLab 8.7. It is OFF by
default because it still causes too many false alarms.
Git has a built-in mechanism, [git fsck][git-fsck], to verify the Git has a built-in mechanism, [git fsck][git-fsck], to verify the
integrity of all data commited to a repository. GitLab administrators integrity of all data commited to a repository. GitLab administrators
......
# Cherry-pick changes # Cherry-pick changes
_**Note:** This feature was [introduced][ce-3514] in GitLab 8.7._ >**Note:**
This feature was [introduced][ce-3514] in GitLab 8.7.
--- ---
......
# Import your project from GitHub to GitLab # Import your project from GitHub to GitLab
_**Note:** In order to enable the GitHub import setting, you should first >**Note:**
enable the [GitHub integration][gh-import] in your GitLab instance._ In order to enable the GitHub import setting, you should first
enable the [GitHub integration][gh-import] in your GitLab instance.
At its current state, GitHub importer can import: At its current state, GitHub importer can import:
...@@ -10,10 +11,13 @@ At its current state, GitHub importer can import: ...@@ -10,10 +11,13 @@ At its current state, GitHub importer can import:
- the issues (introduced in GitLab 7.7) - the issues (introduced in GitLab 7.7)
- the pull requests (introduced in GitLab 8.4) - the pull requests (introduced in GitLab 8.4)
- the wiki pages (introduced in GitLab 8.4) - the wiki pages (introduced in GitLab 8.4)
- the milestones (introduced in GitLab 8.7)
- the labels (introduced in GitLab 8.7)
It is not yet possible to import your labels, milestones and cross-repository With GitLab 8.7+, references to pull requests and issues are preserved.
pull requests (those from forks). We are working on improving this in the near
future. It is not yet possible to import your cross-repository pull requests (those from
forks). We are working on improving this in the near future.
The importer page is visible when you [create a new project][new-project]. The importer page is visible when you [create a new project][new-project].
Click on the **GitHub** link and you will be redirected to GitHub for Click on the **GitHub** link and you will be redirected to GitHub for
......
module Banzai module Banzai
module Filter module Filter
# HTML Filter to add a `rel="nofollow"` attribute to external links # HTML Filter to modify the attributes of external links
#
class ExternalLinkFilter < HTML::Pipeline::Filter class ExternalLinkFilter < HTML::Pipeline::Filter
def call def call
doc.search('a').each do |node| doc.search('a').each do |node|
...@@ -15,7 +14,7 @@ module Banzai ...@@ -15,7 +14,7 @@ module Banzai
# Skip internal links # Skip internal links
next if link.start_with?(internal_url) next if link.start_with?(internal_url)
node.set_attribute('rel', 'nofollow') node.set_attribute('rel', 'nofollow noreferrer')
end end
doc doc
......
...@@ -300,14 +300,6 @@ describe Projects::MergeRequestsController do ...@@ -300,14 +300,6 @@ describe Projects::MergeRequestsController do
expect(response.cookies['diff_view']).to eq('parallel') expect(response.cookies['diff_view']).to eq('parallel')
end end
it 'assigns :view param based on cookie' do
request.cookies['diff_view'] = 'parallel'
go
expect(controller.params[:view]).to eq 'parallel'
end
end end
describe 'GET commits' do describe 'GET commits' do
......
...@@ -178,6 +178,19 @@ describe 'Issues', feature: true do ...@@ -178,6 +178,19 @@ describe 'Issues', feature: true do
expect(first_issue).to include('foo') expect(first_issue).to include('foo')
end end
context 'with a filter on labels' do
let(:label) { create(:label, project: project) }
before { create(:label_link, label: label, target: foo) }
it 'sorts by least recently due date by excluding nil due dates' do
bar.update(due_date: nil)
visit namespace_project_issues_path(project.namespace, project, label_names: [label.name], sort: sort_value_due_date_later)
expect(first_issue).to include('foo')
end
end
end end
describe 'filtering by due date' do describe 'filtering by due date' do
......
...@@ -165,7 +165,12 @@ describe 'GitLab Markdown', feature: true do ...@@ -165,7 +165,12 @@ describe 'GitLab Markdown', feature: true do
describe 'ExternalLinkFilter' do describe 'ExternalLinkFilter' do
it 'adds nofollow to external link' do it 'adds nofollow to external link' do
link = doc.at_css('a:contains("Google")') link = doc.at_css('a:contains("Google")')
expect(link.attr('rel')).to match 'nofollow' expect(link.attr('rel')).to include('nofollow')
end
it 'adds noreferrer to external link' do
link = doc.at_css('a:contains("Google")')
expect(link.attr('rel')).to include('noreferrer')
end end
it 'ignores internal link' do it 'ignores internal link' do
......
...@@ -13,8 +13,8 @@ feature 'Signup', feature: true do ...@@ -13,8 +13,8 @@ feature 'Signup', feature: true do
fill_in 'user_password_sign_up', with: user.password fill_in 'user_password_sign_up', with: user.password
click_button "Sign up" click_button "Sign up"
expect(current_path).to eq user_session_path expect(current_path).to eq users_almost_there_path
expect(page).to have_content("A message with a confirmation link has been sent to your email address.") expect(page).to have_content("Please check your email to confirm your account")
end end
end end
......
...@@ -11,6 +11,26 @@ describe DiffHelper do ...@@ -11,6 +11,26 @@ describe DiffHelper do
let(:diff_refs) { [commit.parent, commit] } let(:diff_refs) { [commit.parent, commit] }
let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) } let(:diff_file) { Gitlab::Diff::File.new(diff, diff_refs) }
describe 'diff_view' do
it 'returns a valid value when cookie is set' do
helper.request.cookies[:diff_view] = 'parallel'
expect(helper.diff_view).to eq 'parallel'
end
it 'returns a default value when cookie is invalid' do
helper.request.cookies[:diff_view] = 'invalid'
expect(helper.diff_view).to eq 'inline'
end
it 'returns a default value when cookie is nil' do
expect(helper.request.cookies).to be_empty
expect(helper.diff_view).to eq 'inline'
end
end
describe 'diff_hard_limit_enabled?' do describe 'diff_hard_limit_enabled?' do
it 'should return true if param is provided' do it 'should return true if param is provided' do
allow(controller).to receive(:params) { { force_show_diff: true } } allow(controller).to receive(:params) { { force_show_diff: true } }
......
...@@ -24,6 +24,14 @@ describe Banzai::Filter::ExternalLinkFilter, lib: true do ...@@ -24,6 +24,14 @@ describe Banzai::Filter::ExternalLinkFilter, lib: true do
doc = filter(act) doc = filter(act)
expect(doc.at_css('a')).to have_attribute('rel') expect(doc.at_css('a')).to have_attribute('rel')
expect(doc.at_css('a')['rel']).to eq 'nofollow' expect(doc.at_css('a')['rel']).to include 'nofollow'
end
it 'adds rel="noreferrer" to external links' do
act = %q(<a href="https://google.com/">Google</a>)
doc = filter(act)
expect(doc.at_css('a')).to have_attribute('rel')
expect(doc.at_css('a')['rel']).to include 'noreferrer'
end end
end end
...@@ -100,7 +100,7 @@ describe Issues::BulkUpdateService, services: true do ...@@ -100,7 +100,7 @@ describe Issues::BulkUpdateService, services: true do
describe :update_milestone do describe :update_milestone do
before do before do
@milestone = create :milestone @milestone = create(:milestone, project: @project)
@params = { @params = {
issues_ids: [issue.id], issues_ids: [issue.id],
milestone_id: @milestone.id milestone_id: @milestone.id
......
...@@ -3,40 +3,75 @@ require 'spec_helper' ...@@ -3,40 +3,75 @@ require 'spec_helper'
describe Issues::CreateService, services: true do describe Issues::CreateService, services: true do
let(:project) { create(:empty_project) } let(:project) { create(:empty_project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:assignee) { create(:user) }
describe :execute do describe '#execute' do
context 'valid params' do let(:issue) { described_class.new(project, user, opts).execute }
context 'when params are valid' do
let(:assignee) { create(:user) }
let(:milestone) { create(:milestone, project: project) }
let(:labels) { create_pair(:label, project: project) }
before do before do
project.team << [user, :master] project.team << [user, :master]
project.team << [assignee, :master] project.team << [assignee, :master]
end
opts = { let(:opts) do
title: 'Awesome issue', { title: 'Awesome issue',
description: 'please fix', description: 'please fix',
assignee: assignee assignee: assignee,
} label_ids: labels.map(&:id),
milestone_id: milestone.id }
@issue = Issues::CreateService.new(project, user, opts).execute
end end
it { expect(@issue).to be_valid } it { expect(issue).to be_valid }
it { expect(@issue.title).to eq('Awesome issue') } it { expect(issue.title).to eq('Awesome issue') }
it { expect(@issue.assignee).to eq assignee } it { expect(issue.assignee).to eq assignee }
it { expect(issue.labels).to match_array labels }
it { expect(issue.milestone).to eq milestone }
it 'creates a pending todo for new assignee' do it 'creates a pending todo for new assignee' do
attributes = { attributes = {
project: project, project: project,
author: user, author: user,
user: assignee, user: assignee,
target_id: @issue.id, target_id: issue.id,
target_type: @issue.class.name, target_type: issue.class.name,
action: Todo::ASSIGNED, action: Todo::ASSIGNED,
state: :pending state: :pending
} }
expect(Todo.where(attributes).count).to eq 1 expect(Todo.where(attributes).count).to eq 1
end end
context 'when label belongs to different project' do
let(:label) { create(:label) }
let(:opts) do
{ title: 'Title',
description: 'Description',
label_ids: [label.id] }
end
it 'does not assign label'do
expect(issue.labels).to_not include label
end
end
context 'when milestone belongs to different project' do
let(:milestone) { create(:milestone) }
let(:opts) do
{ title: 'Title',
description: 'Description',
milestone_id: milestone.id }
end
it 'does not assign milestone' do
expect(issue.milestone).to_not eq milestone
end
end
end end
end end
end end
...@@ -4,10 +4,15 @@ describe Issues::UpdateService, services: true do ...@@ -4,10 +4,15 @@ describe Issues::UpdateService, services: true do
let(:user) { create(:user) } let(:user) { create(:user) }
let(:user2) { create(:user) } let(:user2) { create(:user) }
let(:user3) { create(:user) } let(:user3) { create(:user) }
let(:issue) { create(:issue, title: 'Old title', assignee_id: user3.id) } let(:project) { create(:empty_project) }
let(:label) { create(:label) } let(:label) { create(:label, project: project) }
let(:label2) { create(:label) } let(:label2) { create(:label) }
let(:project) { issue.project }
let(:issue) do
create(:issue, title: 'Old title',
assignee_id: user3.id,
project: project)
end
before do before do
project.team << [user, :master] project.team << [user, :master]
......
require 'spec_helper' require 'spec_helper'
describe MergeRequests::UpdateService, services: true do describe MergeRequests::UpdateService, services: true do
let(:project) { create(:project) }
let(:user) { create(:user) } let(:user) { create(:user) }
let(:user2) { create(:user) } let(:user2) { create(:user) }
let(:user3) { create(:user) } let(:user3) { create(:user) }
let(:merge_request) { create(:merge_request, :simple, title: 'Old title', assignee_id: user3.id) } let(:label) { create(:label, project: project) }
let(:project) { merge_request.project }
let(:label) { create(:label) }
let(:label2) { create(:label) } let(:label2) { create(:label) }
let(:merge_request) do
create(:merge_request, :simple, title: 'Old title',
assignee_id: user3.id,
source_project: project)
end
before do before do
project.team << [user, :master] project.team << [user, :master]
project.team << [user2, :developer] project.team << [user2, :developer]
......
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