Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-06-24 09:07:22 +00:00
parent c81279ca90
commit 23b60ed2c1
38 changed files with 109 additions and 82 deletions

View File

@ -145,7 +145,7 @@ export default class FileTemplateMediator {
text: __('Undo'),
onClick: (e, toastObj) => {
self.restoreFromCache();
toastObj.goAway(0);
toastObj.hide();
},
},
});

View File

@ -78,7 +78,7 @@ export default {
} = await axios.put(this.resetPath);
this.email = newAddress;
} catch {
this.$toast.show(__('There was an error when reseting email token.'), { type: 'error' });
this.$toast.show(__('There was an error when reseting email token.'));
}
},
cancelHandler() {

View File

@ -73,7 +73,7 @@ export default {
this.events = this.buildEvents(events);
} catch (error) {
this.$toast.show(this.$options.i18n.loadNotificationLevelErrorMessage, { type: 'error' });
this.$toast.show(this.$options.i18n.loadNotificationLevelErrorMessage);
} finally {
this.isLoading = false;
}
@ -93,7 +93,7 @@ export default {
this.events = this.buildEvents(events);
} catch (error) {
this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage, { type: 'error' });
this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage);
}
},
},

View File

@ -104,7 +104,7 @@ export default {
this.selectedNotificationLevel = level;
this.openNotificationsModal();
} catch (error) {
this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage, { type: 'error' });
this.$toast.show(this.$options.i18n.updateNotificationLevelErrorMessage);
} finally {
this.isLoading = false;
}

View File

@ -12,16 +12,16 @@ export default {
GlSprintf,
},
computed: {
...mapState(['packageEntity', 'terraformHelpPath', 'projectPath']),
...mapState(['packageEntity', 'terraformHelpPath', 'gitlabHost', 'projectPath']),
provisionInstructions() {
// eslint-disable-next-line @gitlab/require-i18n-strings
return `module "${this.packageEntity.name}" {
source = "${this.projectPath}/${this.packageEntity.name}"
source = "${this.gitlabHost}/${this.projectPath}/${this.packageEntity.name}"
version = "${this.packageEntity.version}"
}`;
},
registrySetup() {
return `credentials "gitlab.com" {
return `credentials "${this.gitlabHost}" {
token = "<TOKEN>"
}`;
},

View File

@ -86,7 +86,7 @@ export default {
this.alertMessage = ERROR_UPDATING_SETTINGS;
} else {
this.dismissAlert();
this.$toast.show(SUCCESS_UPDATING_SETTINGS, { type: 'success' });
this.$toast.show(SUCCESS_UPDATING_SETTINGS);
}
})
.catch((e) => {

View File

@ -158,14 +158,14 @@ export default {
.then(({ data }) => {
const errorMessage = data?.updateContainerExpirationPolicy?.errors[0];
if (errorMessage) {
this.$toast.show(errorMessage, { type: 'error' });
this.$toast.show(errorMessage);
} else {
this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE, { type: 'success' });
this.$toast.show(UPDATE_SETTINGS_SUCCESS_MESSAGE);
}
})
.catch((error) => {
this.setApiErrors(error);
this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE, { type: 'error' });
this.$toast.show(UPDATE_SETTINGS_ERROR_MESSAGE);
})
.finally(() => {
this.mutationLoading = false;

View File

@ -82,7 +82,7 @@ export default {
text: this.alertContent.actionText,
onClick: (_, toastObject) => {
this[this.alertContent.actionName]();
toastObject.goAway(0);
toastObject.hide();
},
},
};

View File

@ -10,8 +10,11 @@ export const FILTER_CURRENT = 'Current';
export const OPERATOR_IS = '=';
export const OPERATOR_IS_TEXT = __('is');
export const OPERATOR_IS_NOT = '!=';
export const OPERATOR_IS_NOT_TEXT = __('is not');
export const OPERATOR_IS_ONLY = [{ value: OPERATOR_IS, description: OPERATOR_IS_TEXT }];
export const OPERATOR_IS_NOT_ONLY = [{ value: OPERATOR_IS_NOT, description: OPERATOR_IS_NOT_TEXT }];
export const OPERATOR_IS_AND_IS_NOT = [...OPERATOR_IS_ONLY, ...OPERATOR_IS_NOT_ONLY];
export const DEFAULT_LABEL_NONE = { value: FILTER_NONE, text: __(FILTER_NONE) };
export const DEFAULT_LABEL_ANY = { value: FILTER_ANY, text: __(FILTER_ANY) };

View File

@ -2,7 +2,7 @@ import { GlToast } from '@gitlab/ui';
import Vue from 'vue';
Vue.use(GlToast);
const instance = new Vue();
export const instance = new Vue();
export default function showGlobalToast(...args) {
return instance.$toast.show(...args);

View File

@ -162,6 +162,7 @@ class ProjectsController < Projects::ApplicationController
format.atom do
load_events
@events = @events.select { |event| event.visible_to_user?(current_user) }
render layout: 'xml.atom'
end
end

View File

@ -8,7 +8,7 @@ module Mutations
def track_event(event, scope)
::Packages::CreateEventService.new(nil, current_user, event_name: event, scope: scope).execute
::Gitlab::Tracking.event(event.to_s, scope.to_s)
::Gitlab::Tracking.event(event.to_s, scope.to_s, user: current_user)
end
end
end

View File

@ -390,16 +390,15 @@ class Event < ApplicationRecord
read_snippet: %i[personal_snippet_note? project_snippet_note?],
read_milestone: %i[milestone?],
read_wiki: %i[wiki_page?],
read_design: %i[design_note? design?]
read_design: %i[design_note? design?],
read_note: %i[note?]
}
end
private
def permission_object
if note?
note_target
elsif target_id.present?
if target_id.present?
target
else
project

View File

@ -59,6 +59,7 @@ class EventCollection
parents_for_lateral = parents.select(:id).to_sql
lateral = filtered_events
# Applying the limit here (before we filter (permissions) means we may get less than limit)
.limit(limit_for_join_lateral)
.where("events.#{parent_column} = parents_for_lateral.id") # rubocop:disable GitlabSecurity/SqlInjection
.to_sql

View File

@ -10,6 +10,7 @@
can_delete: can?(current_user, :destroy_package, @project).to_s,
svg_path: image_path('illustrations/no-packages.svg'),
project_name: @project.name,
project_path: expose_url(@project.full_path),
project_path: @project.root_ancestor.full_path,
gitlab_host: Gitlab.config.gitlab.host,
terraform_help_path: help_page_path('user/infrastructure/index'),
project_list_url: project_infrastructure_registry_index_path(@project)} }

View File

@ -20,6 +20,9 @@
#js-related-merge-requests{ data: { endpoint: expose_path(api_v4_projects_issues_related_merge_requests_path(id: @project.id, issue_iid: issuable.iid)), project_namespace: @project.namespace.path, project_path: @project.path } }
- if can?(current_user, :admin_feature_flags_issue_links, @project)
= render_if_exists 'projects/issues/related_feature_flags'
- if can?(current_user, :download_code, @project)
- add_page_startup_api_call related_branches_path
#related-branches{ data: { url: related_branches_path } }

View File

@ -392,8 +392,10 @@ end
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36617) in GitLab 13.2.
> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/251234) in GitLab 13.5.
> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/220333) in GitLab 14.1
You can link related issues to a feature flag. In the **Linked issues** section,
click the `+` button and input the issue reference number or the full URL of the issue.
The issue(s) will then appear in the related feautre flag and vice versa.
This feature is similar to the [linked issues](../user/project/issues/related_issues.md) feature.

View File

@ -89,7 +89,7 @@ module Gitlab
end
def track_event(result)
::Gitlab::Tracking.event("instance_administrators_group", "group_created")
::Gitlab::Tracking.event("instance_administrators_group", "group_created", namespace: result[:group])
success(result)
end

View File

@ -118,7 +118,8 @@ module Gitlab
end
def track_event(result)
::Gitlab::Tracking.event("self_monitoring", "project_created")
project = result[:project]
::Gitlab::Tracking.event("self_monitoring", "project_created", project: project, namespace: project.namespace)
success(result)
end

View File

@ -17027,6 +17027,9 @@ msgstr ""
msgid "InProductMarketing|you may %{unsubscribe_link} at any time."
msgstr ""
msgid "Inactive"
msgstr ""
msgid "Incident"
msgstr ""
@ -26890,6 +26893,9 @@ msgstr ""
msgid "Related Issues"
msgstr ""
msgid "Related feature flags"
msgstr ""
msgid "Related issues"
msgstr ""
@ -32859,6 +32865,9 @@ msgstr ""
msgid "There was an error loading merge request approval settings."
msgstr ""
msgid "There was an error loading related feature flags"
msgstr ""
msgid "There was an error loading users activity calendar."
msgstr ""

View File

@ -59,7 +59,7 @@
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "1.199.0",
"@gitlab/tributejs": "1.0.0",
"@gitlab/ui": "29.38.1",
"@gitlab/ui": "30.0.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.3-2",
"@rails/ujs": "6.1.3-2",

View File

@ -23,6 +23,7 @@ gitlab:
memory: 1500M
persistence:
size: 10G
storageClass: ssd
gitlab-exporter:
enabled: false
mailroom:

View File

@ -119,11 +119,6 @@ RSpec.describe ProjectsController do
get :activity, params: { namespace_id: project.namespace, id: project, format: :json }
expect(json_response['html']).to eq("\n")
end
it 'filters out invisible event when calculating the count' do
get :activity, params: { namespace_id: project.namespace, id: project, format: :json }
expect(json_response['count']).to eq(0)
end
end
@ -1484,6 +1479,30 @@ RSpec.describe ProjectsController do
end
end
context 'GET show.atom' do
let_it_be(:public_project) { create(:project, :public) }
let_it_be(:event) { create(:event, :commented, project: public_project, target: create(:note, project: public_project)) }
let_it_be(:invisible_event) { create(:event, :commented, project: public_project, target: create(:note, :confidential, project: public_project)) }
it 'filters by calling event.visible_to_user?' do
expect(EventCollection).to receive_message_chain(:new, :to_a).and_return([event, invisible_event])
expect(event).to receive(:visible_to_user?).and_return(true)
expect(invisible_event).to receive(:visible_to_user?).and_return(false)
get :show, format: :atom, params: { id: public_project, namespace_id: public_project.namespace }
expect(response).to render_template('xml.atom')
expect(assigns(:events)).to eq([event])
end
it 'filters by calling event.visible_to_user?' do
get :show, format: :atom, params: { id: public_project, namespace_id: public_project.namespace }
expect(response).to render_template('xml.atom')
expect(assigns(:events)).to eq([event])
end
end
describe 'GET resolve' do
shared_examples 'resolvable endpoint' do
it 'redirects to the project page' do

View File

@ -47,11 +47,11 @@ end
def check_undo_button_display
expect(page).to have_content('template applied')
expect(page).to have_css('.toasted-container')
expect(page).to have_css('.b-toaster')
end
def check_content_reverted(template_content)
find('.toasted-container a', text: 'Undo').click
find('.b-toaster a', text: 'Undo').click
expect(page).not_to have_content(template_content)
expect(page).to have_css('.template-type-selector .dropdown-toggle-text')
end

View File

@ -5,6 +5,7 @@ import * as actions from '~/emoji/awards_app/store/actions';
import axios from '~/lib/utils/axios_utils';
jest.mock('@sentry/browser');
jest.mock('~/vue_shared/plugins/global_toast');
describe('Awards app actions', () => {
afterEach(() => {

View File

@ -154,10 +154,7 @@ describe('IssuableByEmail', () => {
await clickResetEmail();
expect(mockToastShow).toHaveBeenCalledWith(
'There was an error when reseting email token.',
{ type: 'error' },
);
expect(mockToastShow).toHaveBeenCalledWith('There was an error when reseting email token.');
expect(findFormInputGroup().props('value')).toBe('user@gitlab.com');
});
});

View File

@ -177,11 +177,8 @@ describe('CustomNotificationsModal', () => {
await waitForPromises();
expect(
mockToastShow,
).toHaveBeenCalledWith(
expect(mockToastShow).toHaveBeenCalledWith(
'An error occurred while loading the notification settings. Please try again.',
{ type: 'error' },
);
});
});
@ -255,11 +252,8 @@ describe('CustomNotificationsModal', () => {
await waitForPromises();
expect(
mockToastShow,
).toHaveBeenCalledWith(
expect(mockToastShow).toHaveBeenCalledWith(
'An error occurred while updating the notification settings. Please try again.',
{ type: 'error' },
);
});
});

View File

@ -242,11 +242,8 @@ describe('NotificationsDropdown', () => {
await clickDropdownItemAt(1);
expect(wrapper.vm.selectedNotificationLevel).toBe('global');
expect(
mockToastShow,
).toHaveBeenCalledWith(
expect(mockToastShow).toHaveBeenCalledWith(
'An error occurred while updating the notification settings. Please try again.',
{ type: 'error' },
);
});

View File

@ -11,7 +11,7 @@ exports[`TerraformInstallation renders all the messages 1`] = `
<code-instruction-stub
copytext="Copy Terraform Command"
instruction="module \\"Test/system-22\\" {
source = \\"foo/Test/system-22\\"
source = \\"bar.dev/foo/Test/system-22\\"
version = \\"0.1\\"
}"
label="Copy and paste into your Terraform configuration, insert the variables, and run Terraform init:"
@ -28,7 +28,7 @@ exports[`TerraformInstallation renders all the messages 1`] = `
<code-instruction-stub
copytext="Copy Terraform Setup Command"
instruction="credentials \\"gitlab.com\\" {
instruction="credentials \\"bar.dev\\" {
token = \\"<TOKEN>\\"
}"
label="To authorize access to the Terraform registry:"

View File

@ -13,6 +13,7 @@ describe('TerraformInstallation', () => {
const store = new Vuex.Store({
state: {
packageEntity,
gitlabHost: 'bar.dev',
projectPath: 'foo',
},
});
@ -42,7 +43,7 @@ describe('TerraformInstallation', () => {
it('renders the correct command', () => {
expect(findCodeInstructions().at(0).props('instruction')).toMatchInlineSnapshot(`
"module \\"Test/system-22\\" {
source = \\"foo/Test/system-22\\"
source = \\"bar.dev/foo/Test/system-22\\"
version = \\"0.1\\"
}"
`);
@ -52,7 +53,7 @@ describe('TerraformInstallation', () => {
describe('setup commands', () => {
it('renders the correct command', () => {
expect(findCodeInstructions().at(1).props('instruction')).toMatchInlineSnapshot(`
"credentials \\"gitlab.com\\" {
"credentials \\"bar.dev\\" {
token = \\"<TOKEN>\\"
}"
`);

View File

@ -244,9 +244,7 @@ describe('Group Settings App', () => {
await waitForPromises();
expect(show).toHaveBeenCalledWith(SUCCESS_UPDATING_SETTINGS, {
type: 'success',
});
expect(show).toHaveBeenCalledWith(SUCCESS_UPDATING_SETTINGS);
});
it('has an optimistic response', async () => {

View File

@ -321,9 +321,7 @@ describe('Settings Form', () => {
await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE, {
type: 'success',
});
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_SUCCESS_MESSAGE);
});
describe('when submit fails', () => {
@ -339,9 +337,7 @@ describe('Settings Form', () => {
await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo', {
type: 'error',
});
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith('foo');
});
});
@ -355,9 +351,7 @@ describe('Settings Form', () => {
await waitForPromises();
await wrapper.vm.$nextTick();
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE, {
type: 'error',
});
expect(wrapper.vm.$toast.show).toHaveBeenCalledWith(UPDATE_SETTINGS_ERROR_MESSAGE);
});
it('parses the error messages', async () => {

View File

@ -1,11 +1,10 @@
import Vue from 'vue';
import toast from '~/vue_shared/plugins/global_toast';
import toast, { instance } from '~/vue_shared/plugins/global_toast';
describe('Global toast', () => {
let spyFunc;
beforeEach(() => {
spyFunc = jest.spyOn(Vue.prototype.$toast, 'show').mockImplementation(() => {});
spyFunc = jest.spyOn(instance.$toast, 'show').mockImplementation(() => {});
});
afterEach(() => {
@ -18,7 +17,7 @@ describe('Global toast', () => {
toast(arg1, arg2);
expect(Vue.prototype.$toast.show).toHaveBeenCalledTimes(1);
expect(Vue.prototype.$toast.show).toHaveBeenCalledWith(arg1, arg2);
expect(instance.$toast.show).toHaveBeenCalledTimes(1);
expect(instance.$toast.show).toHaveBeenCalledWith(arg1, arg2);
});
});

View File

@ -56,10 +56,10 @@ RSpec.describe Gitlab::DatabaseImporters::InstanceAdministrators::CreateGroup do
it "tracks successful install" do
expect(::Gitlab::Tracking).to receive(:event).with(
'instance_administrators_group', 'group_created'
'instance_administrators_group', 'group_created', namespace: group
)
result
subject.execute
end
it 'creates group' do

View File

@ -86,10 +86,10 @@ RSpec.describe Gitlab::DatabaseImporters::SelfMonitoring::Project::CreateService
end
it "tracks successful install" do
expect(::Gitlab::Tracking).to receive(:event).twice
expect(::Gitlab::Tracking).to receive(:event).with('self_monitoring', 'project_created')
expect(::Gitlab::Tracking).to receive(:event).with("instance_administrators_group", "group_created", namespace: project.namespace)
expect(::Gitlab::Tracking).to receive(:event).with('self_monitoring', 'project_created', project: project, namespace: project.namespace)
result
subject.execute
end
it 'creates group' do

View File

@ -54,6 +54,7 @@ issues:
- namespace
- note_authors
- issue_email_participants
- test_reports
events:
- author
- project

View File

@ -268,6 +268,7 @@ RSpec.describe Event do
let(:design) { create(:design, issue: issue, project: project) }
let(:note_on_commit) { create(:note_on_commit, project: project) }
let(:note_on_issue) { create(:note_on_issue, noteable: issue, project: project) }
let(:confidential_note) { create(:note, noteable: issue, project: project, confidential: true) }
let(:note_on_confidential_issue) { create(:note_on_issue, noteable: confidential_issue, project: project) }
let(:note_on_project_snippet) { create(:note_on_project_snippet, author: author, noteable: project_snippet, project: project) }
let(:note_on_personal_snippet) { create(:note_on_personal_snippet, author: author, noteable: personal_snippet, project: nil) }
@ -399,6 +400,16 @@ RSpec.describe Event do
include_examples 'visible to assignee and author', true
end
context 'confidential note' do
let(:target) { confidential_note }
include_examples 'visibility examples' do
let(:visibility) { visible_to_none_except(:member) }
end
include_examples 'visible to author', true
end
context 'private project' do
let(:project) { private_project }
let(:target) { note_on_issue }

View File

@ -908,13 +908,12 @@
resolved "https://registry.yarnpkg.com/@gitlab/tributejs/-/tributejs-1.0.0.tgz#672befa222aeffc83e7d799b0500a7a4418e59b8"
integrity sha512-nmKw1+hB6MHvlmPz63yPwVs1qQkycHwsKgxpEbzmky16Y6mL4EJMk3w1b8QlOAF/AIAzjCERPhe/R4MJiohbZw==
"@gitlab/ui@29.38.1":
version "29.38.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-29.38.1.tgz#93ab2ad7cb8008b3050599b452b626c109630e97"
integrity sha512-5sKdbZI9Q9S7KW3/ybN40tFS/KInm76cog8O0SMe2Ne026ZZ18CAHEMvkfoVXTN3XMkWZnMlk92s8f/WqM5//A==
"@gitlab/ui@30.0.0":
version "30.0.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-30.0.0.tgz#1f7c4bb2dfa1a987f5673f865384ebcbbe3d7a3e"
integrity sha512-+o8t4TVm8MOV6llX6zq9HKuggRWKuPDZfbmjptNJA0CwW3IGPV/WcgFuSozHW8x2lxE0ZfrD7vMwI0dfTwghwQ==
dependencies:
"@babel/standalone" "^7.0.0"
"@gitlab/vue-toasted" "^1.3.0"
bootstrap-vue "2.18.1"
copy-to-clipboard "^3.0.8"
dompurify "^2.2.9"
@ -932,11 +931,6 @@
resolved "https://registry.yarnpkg.com/@gitlab/visual-review-tools/-/visual-review-tools-1.6.1.tgz#0d8f3ff9f51b05f7c80b9a107727703d48997e4e"
integrity sha512-vY8K1igwZFoEOmU0h4E7XTLlilsQ4ylPr27O01UsSe6ZTKi6oEMREsRAEpNIUgRlxUARCsf+Opp4pgSFzFkFcw==
"@gitlab/vue-toasted@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@gitlab/vue-toasted/-/vue-toasted-1.3.0.tgz#f21550d4ce406ee5f99447a02abf36250ecc922d"
integrity sha512-xexu7YbbIkQS5FDqPaewrOTQ4/myth5VyU8+hWZ+Tj1e5CuAlDNha3dHbvwyLW8/2flm/2mfslFNPAX2DRe8ZQ==
"@istanbuljs/load-nyc-config@^1.0.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced"