Commit 79216161 authored by GitLab Bot's avatar GitLab Bot

Add latest changes from gitlab-org/gitlab@master

parent c1924b86
...@@ -91,7 +91,7 @@ export default { ...@@ -91,7 +91,7 @@ export default {
</template> </template>
<li> <li>
<item-button <item-button
:label="__('Rename')" :label="__('Rename/Move')"
class="d-flex" class="d-flex"
icon="pencil" icon="pencil"
icon-classes="mr-2" icon-classes="mr-2"
......
...@@ -3,6 +3,8 @@ ...@@ -3,6 +3,8 @@
class IssueAssignee < ApplicationRecord class IssueAssignee < ApplicationRecord
belongs_to :issue belongs_to :issue
belongs_to :assignee, class_name: "User", foreign_key: :user_id belongs_to :assignee, class_name: "User", foreign_key: :user_id
validates :assignee, uniqueness: { scope: :issue_id }
end end
IssueAssignee.prepend_if_ee('EE::IssueAssignee') IssueAssignee.prepend_if_ee('EE::IssueAssignee')
...@@ -3,4 +3,6 @@ ...@@ -3,4 +3,6 @@
class MergeRequestAssignee < ApplicationRecord class MergeRequestAssignee < ApplicationRecord
belongs_to :merge_request belongs_to :merge_request
belongs_to :assignee, class_name: "User", foreign_key: :user_id belongs_to :assignee, class_name: "User", foreign_key: :user_id
validates :assignee, uniqueness: { scope: :merge_request_id }
end end
...@@ -4,6 +4,7 @@ class VariableEntity < Grape::Entity ...@@ -4,6 +4,7 @@ class VariableEntity < Grape::Entity
expose :id expose :id
expose :key expose :key
expose :value expose :value
expose :variable_type
expose :protected?, as: :protected expose :protected?, as: :protected
expose :masked?, as: :masked expose :masked?, as: :masked
......
---
title: Use POSTGRES_VERSION variable in Auto DevOps Test stage
merge_request: 22884
author: Serban Marti
type: fixed
---
title: Fix error when assigning an existing asignee
merge_request: 23416
author:
type: fixed
---
title: "Change `Rename` to `Rename/Move` in Web IDE Dropdown"
merge_request: 23877
author:
type: added
---
title: Fix outdated MR security warning message
merge_request: 23496
author:
type: fixed
---
title: Copy issues routing under - scope
merge_request: 23779
author:
type: changed
# frozen_string_literal: true
get :issues, to: 'issues#calendar', constraints: lambda { |req| req.format == :ics }
resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do
member do
post :toggle_subscription
post :mark_as_spam
post :move
put :reorder
get :related_branches
get :can_create_branch
get :realtime_changes
post :create_merge_request
get :discussions, format: :json
end
collection do
post :bulk_update
post :import_csv
end
end
...@@ -401,25 +401,15 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do ...@@ -401,25 +401,15 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
end end
end end
get :issues, to: 'issues#calendar', constraints: lambda { |req| req.format == :ics } # Unscoped route. It will be replaced with redirect to /-/issues/
# Issue https://gitlab.com/gitlab-org/gitlab/issues/118849
resources :issues, concerns: :awardable, constraints: { id: /\d+/ } do draw :issues
member do
post :toggle_subscription
post :mark_as_spam
post :move
put :reorder
get :related_branches
get :can_create_branch
get :realtime_changes
post :create_merge_request
get :discussions, format: :json
end
collection do # To ensure an old unscoped routing is used for the UI we need to
post :bulk_update # add prefix 'as' to the scope routing and place it below original routing.
post :import_csv # Issue https://gitlab.com/gitlab-org/gitlab/issues/118849
end scope '-', as: 'scoped' do
draw :issues
end end
resources :notes, only: [:create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do resources :notes, only: [:create, :destroy, :update], concerns: :awardable, constraints: { id: /\d+/ } do
......
...@@ -35,6 +35,8 @@ the `author` field. GitLab team members **should not**. ...@@ -35,6 +35,8 @@ the `author` field. GitLab team members **should not**.
- Any change that introduces a database migration, whether it's regular, post, - Any change that introduces a database migration, whether it's regular, post,
or data migration, **must** have a changelog entry. or data migration, **must** have a changelog entry.
- [Security fixes] **must** have a changelog entry, without `merge_request` value
and with `type` set to `security`.
- Any user-facing change **should** have a changelog entry. Example: "GitLab now - Any user-facing change **should** have a changelog entry. Example: "GitLab now
uses system fonts for all text." uses system fonts for all text."
- Performance improvements **should** have a changelog entry. - Performance improvements **should** have a changelog entry.
...@@ -289,6 +291,7 @@ and then compiling the entries into the overall `CHANGELOG.md` file during the ...@@ -289,6 +291,7 @@ and then compiling the entries into the overall `CHANGELOG.md` file during the
[release managers]: https://gitlab.com/gitlab-org/release/docs/blob/master/quickstart/release-manager.md [release managers]: https://gitlab.com/gitlab-org/release/docs/blob/master/quickstart/release-manager.md
[started brainstorming]: https://gitlab.com/gitlab-org/gitlab-foss/issues/17826 [started brainstorming]: https://gitlab.com/gitlab-org/gitlab-foss/issues/17826
[release process]: https://gitlab.com/gitlab-org/release-tools [release process]: https://gitlab.com/gitlab-org/release-tools
[Security fixes]: https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md
--- ---
......
test: test:
services: services:
- postgres:latest - "postgres:${POSTGRES_VERSION}"
variables: variables:
POSTGRES_DB: test POSTGRES_DB: test
stage: test stage: test
......
...@@ -12,6 +12,15 @@ module Gitlab ...@@ -12,6 +12,15 @@ module Gitlab
explanation do |users| explanation do |users|
_('Assigns %{assignee_users_sentence}.') % { assignee_users_sentence: assignee_users_sentence(users) } _('Assigns %{assignee_users_sentence}.') % { assignee_users_sentence: assignee_users_sentence(users) }
end end
execution_message do |users = nil|
if users.blank?
_("Failed to assign a user because no user was found.")
else
users = [users.first] unless quick_action_target.allows_multiple_assignees?
_('Assigned %{assignee_users_sentence}.') % { assignee_users_sentence: assignee_users_sentence(users) }
end
end
params do params do
quick_action_target.allows_multiple_assignees? ? '@user1 @user2' : '@user' quick_action_target.allows_multiple_assignees? ? '@user1 @user2' : '@user'
end end
...@@ -23,19 +32,14 @@ module Gitlab ...@@ -23,19 +32,14 @@ module Gitlab
extract_users(assignee_param) extract_users(assignee_param)
end end
command :assign do |users| command :assign do |users|
if users.empty? next if users.empty?
@execution_message[:assign] = _("Failed to assign a user because no user was found.")
next
end
if quick_action_target.allows_multiple_assignees? if quick_action_target.allows_multiple_assignees?
@updates[:assignee_ids] ||= quick_action_target.assignees.map(&:id) @updates[:assignee_ids] ||= quick_action_target.assignees.map(&:id)
@updates[:assignee_ids] += users.map(&:id) @updates[:assignee_ids] |= users.map(&:id)
else else
@updates[:assignee_ids] = [users.first.id] @updates[:assignee_ids] = [users.first.id]
end end
@execution_message[:assign] = _('Assigned %{assignee_users_sentence}.') % { assignee_users_sentence: assignee_users_sentence(users) }
end end
desc do desc do
...@@ -249,7 +253,7 @@ module Gitlab ...@@ -249,7 +253,7 @@ module Gitlab
def assignees_for_removal(users) def assignees_for_removal(users)
assignees = quick_action_target.assignees assignees = quick_action_target.assignees
if users.present? && quick_action_target.allows_multiple_assignees? if users.present? && quick_action_target.allows_multiple_assignees?
assignees & users users
else else
assignees assignees
end end
......
...@@ -15694,15 +15694,15 @@ msgstr "" ...@@ -15694,15 +15694,15 @@ msgstr ""
msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc." msgid "Removing the project will delete its repository and all related resources including issues, merge requests etc."
msgstr "" msgstr ""
msgid "Rename"
msgstr ""
msgid "Rename file" msgid "Rename file"
msgstr "" msgstr ""
msgid "Rename folder" msgid "Rename folder"
msgstr "" msgstr ""
msgid "Rename/Move"
msgstr ""
msgid "Reopen epic" msgid "Reopen epic"
msgstr "" msgstr ""
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"value": { "type": "string" }, "value": { "type": "string" },
"masked": { "type": "boolean" }, "masked": { "type": "boolean" },
"protected": { "type": "boolean" }, "protected": { "type": "boolean" },
"variable_type": { "type": "string" },
"environment_scope": { "type": "string", "optional": true } "environment_scope": { "type": "string", "optional": true }
}, },
"additionalProperties": false "additionalProperties": false
......
import { shallowMount } from '@vue/test-utils';
import EmptyState from '~/environments/components/empty_state.vue';
describe('environments empty state', () => {
let vm;
beforeEach(() => {
vm = shallowMount(EmptyState, {
propsData: {
newPath: 'foo',
canCreateEnvironment: true,
helpPath: 'bar',
},
});
});
afterEach(() => {
vm.destroy();
});
it('renders the empty state', () => {
expect(vm.find('.js-blank-state-title').text()).toEqual(
"You don't have any environments right now",
);
});
it('renders the new environment button', () => {
expect(vm.find('.js-new-environment-button').attributes('href')).toEqual('foo');
});
describe('without permission', () => {
beforeEach(() => {
vm.setProps({ canCreateEnvironment: false });
});
it('does not render the new environment button', () => {
expect(vm.find('.js-new-environment-button').exists()).toBe(false);
});
});
});
import Vue from 'vue';
import mountComponent from 'spec/helpers/vue_mount_component_helper';
import emptyState from '~/environments/components/empty_state.vue';
describe('environments empty state', () => {
let vm;
let Component;
beforeEach(() => {
Component = Vue.extend(emptyState);
});
afterEach(() => {
vm.$destroy();
});
describe('With permissions', () => {
beforeEach(() => {
vm = mountComponent(Component, {
newPath: 'foo',
canCreateEnvironment: true,
helpPath: 'bar',
});
});
it('renders empty state and new environment button', () => {
expect(vm.$el.querySelector('.js-blank-state-title').textContent.trim()).toEqual(
"You don't have any environments right now",
);
expect(vm.$el.querySelector('.js-new-environment-button').getAttribute('href')).toEqual(
'foo',
);
});
});
describe('Without permission', () => {
beforeEach(() => {
vm = mountComponent(Component, {
newPath: 'foo',
canCreateEnvironment: false,
helpPath: 'bar',
});
});
it('renders empty state without new button', () => {
expect(vm.$el.querySelector('.js-blank-state-title').textContent.trim()).toEqual(
"You don't have any environments right now",
);
expect(vm.$el.querySelector('.js-new-environment-button')).toBeNull();
});
});
});
# frozen_string_literal: true
require 'spec_helper'
describe IssueAssignee do
let(:issue) { create(:issue) }
subject { issue.issue_assignees.build(assignee: create(:user)) }
describe 'associations' do
it { is_expected.to belong_to(:issue).class_name('Issue') }
it { is_expected.to belong_to(:assignee).class_name('User') }
end
describe 'validations' do
it { is_expected.to validate_uniqueness_of(:assignee).scoped_to(:issue_id) }
end
end
# frozen_string_literal: true
require 'spec_helper'
describe MergeRequestAssignee do
let(:merge_request) { create(:merge_request) }
subject { merge_request.merge_request_assignees.build(assignee: create(:user)) }
describe 'associations' do
it { is_expected.to belong_to(:merge_request).class_name('MergeRequest') }
it { is_expected.to belong_to(:assignee).class_name('User') }
end
describe 'validations' do
it { is_expected.to validate_uniqueness_of(:assignee).scoped_to(:merge_request_id) }
end
end
...@@ -10,7 +10,7 @@ describe VariableEntity do ...@@ -10,7 +10,7 @@ describe VariableEntity do
subject { entity.as_json } subject { entity.as_json }
it 'contains required fields' do it 'contains required fields' do
expect(subject).to include(:id, :key, :value, :protected, :environment_scope) expect(subject).to include(:id, :key, :value, :protected, :environment_scope, :variable_type)
end end
end end
end end
...@@ -804,7 +804,7 @@ describe QuickActions::InterpretService do ...@@ -804,7 +804,7 @@ describe QuickActions::InterpretService do
let(:issuable) { issue } let(:issuable) { issue }
end end
it_behaves_like 'empty command' do it_behaves_like 'empty command', "Failed to assign a user because no user was found." do
let(:content) { '/assign' } let(:content) { '/assign' }
let(:issuable) { issue } let(:issuable) { issue }
end end
......
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