Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f5f6cb45c7
commit
27484d1465
38 changed files with 562 additions and 198 deletions
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import { GlButton, GlSafeHtmlDirective } from '@gitlab/ui';
|
||||
import { snakeCase } from 'lodash';
|
||||
import highlight from '~/lib/utils/highlight';
|
||||
import { truncateNamespace } from '~/lib/utils/text_utility';
|
||||
import { mapVuexModuleState } from '~/lib/utils/vuex_module_mappers';
|
||||
|
@ -56,6 +57,9 @@ export default {
|
|||
highlightedItemName() {
|
||||
return highlight(this.itemName, this.matcher);
|
||||
},
|
||||
itemTrackingLabel() {
|
||||
return `${this.dropdownType}_dropdown_frequent_items_list_item_${snakeCase(this.itemName)}`;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
@ -66,7 +70,7 @@ export default {
|
|||
category="tertiary"
|
||||
:href="webUrl"
|
||||
class="gl-text-left gl-justify-content-start!"
|
||||
@click="track('click_link', { label: `${dropdownType}_dropdown_frequent_items_list_item` })"
|
||||
@click="track('click_link', { label: itemTrackingLabel })"
|
||||
>
|
||||
<project-avatar
|
||||
class="gl-float-left gl-mr-3"
|
||||
|
|
|
@ -30,12 +30,46 @@ export const integrationFormSections = {
|
|||
CONNECTION: 'connection',
|
||||
JIRA_TRIGGER: 'jira_trigger',
|
||||
JIRA_ISSUES: 'jira_issues',
|
||||
TRIGGER: 'trigger',
|
||||
};
|
||||
|
||||
export const integrationFormSectionComponents = {
|
||||
[integrationFormSections.CONNECTION]: 'IntegrationSectionConnection',
|
||||
[integrationFormSections.JIRA_TRIGGER]: 'IntegrationSectionJiraTrigger',
|
||||
[integrationFormSections.JIRA_ISSUES]: 'IntegrationSectionJiraIssues',
|
||||
[integrationFormSections.TRIGGER]: 'IntegrationSectionTrigger',
|
||||
};
|
||||
|
||||
export const integrationTriggerEvents = {
|
||||
PUSH: 'push_events',
|
||||
ISSUE: 'issues_events',
|
||||
CONFIDENTIAL_ISSUE: 'confidential_issues_events',
|
||||
MERGE_REQUEST: 'merge_requests_events',
|
||||
NOTE: 'note_events',
|
||||
CONFIDENTIAL_NOTE: 'confidential_note_events',
|
||||
TAG_PUSH: 'tag_push_events',
|
||||
PIPELINE: 'pipeline_events',
|
||||
WIKI_PAGE: 'wiki_page_events',
|
||||
};
|
||||
|
||||
export const integrationTriggerEventTitles = {
|
||||
[integrationTriggerEvents.PUSH]: s__('IntegrationEvents|A push is made to the repository'),
|
||||
[integrationTriggerEvents.ISSUE]: s__(
|
||||
'IntegrationEvents|An issue is created, updated, or closed',
|
||||
),
|
||||
[integrationTriggerEvents.CONFIDENTIAL_ISSUE]: s__(
|
||||
'IntegrationEvents|A confidential issue is created, updated, or closed',
|
||||
),
|
||||
[integrationTriggerEvents.MERGE_REQUEST]: s__(
|
||||
'IntegrationEvents|A merge request is created, updated, or merged',
|
||||
),
|
||||
[integrationTriggerEvents.NOTE]: s__('IntegrationEvents|A comment is added on an issue'),
|
||||
[integrationTriggerEvents.CONFIDENTIAL_NOTE]: s__(
|
||||
'IntegrationEvents|A comment is added on a confidential issue',
|
||||
),
|
||||
[integrationTriggerEvents.TAG_PUSH]: s__('IntegrationEvents|A tag is pushed to the repository'),
|
||||
[integrationTriggerEvents.PIPELINE]: s__('IntegrationEvents|A pipeline status changes'),
|
||||
[integrationTriggerEvents.WIKI_PAGE]: s__('IntegrationEvents|A wiki page is created or updated'),
|
||||
};
|
||||
|
||||
export const billingPlans = {
|
||||
|
|
|
@ -49,6 +49,10 @@ export default {
|
|||
import(
|
||||
/* webpackChunkName: 'integrationSectionJiraTrigger' */ '~/integrations/edit/components/sections/jira_trigger.vue'
|
||||
),
|
||||
IntegrationSectionTrigger: () =>
|
||||
import(
|
||||
/* webpackChunkName: 'integrationSectionTrigger' */ '~/integrations/edit/components/sections/trigger.vue'
|
||||
),
|
||||
GlBadge,
|
||||
GlButton,
|
||||
GlForm,
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
<script>
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import TriggerField from '../trigger_field.vue';
|
||||
|
||||
export default {
|
||||
name: 'IntegrationSectionTrigger',
|
||||
components: {
|
||||
TriggerField,
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['currentKey', 'propsSource']),
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<trigger-field
|
||||
v-for="event in propsSource.triggerEvents"
|
||||
:key="`${currentKey}-trigger-fields-${event.name}`"
|
||||
:event="event"
|
||||
class="gl-mb-3"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
|
@ -0,0 +1,46 @@
|
|||
<script>
|
||||
import { GlFormCheckbox } from '@gitlab/ui';
|
||||
import { mapGetters } from 'vuex';
|
||||
|
||||
import { integrationTriggerEventTitles } from '~/integrations/constants';
|
||||
|
||||
export default {
|
||||
name: 'TriggerField',
|
||||
components: {
|
||||
GlFormCheckbox,
|
||||
},
|
||||
props: {
|
||||
event: {
|
||||
type: Object,
|
||||
required: false,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
value: false,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['isInheriting']),
|
||||
name() {
|
||||
return `service[${this.event.name}]`;
|
||||
},
|
||||
title() {
|
||||
return integrationTriggerEventTitles[this.event.name];
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.value = this.event.value || false;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div>
|
||||
<input :name="name" type="hidden" :value="value" />
|
||||
<gl-form-checkbox v-model="value" :disabled="isInheriting">
|
||||
{{ title }}
|
||||
</gl-form-checkbox>
|
||||
</div>
|
||||
</template>
|
|
@ -83,7 +83,7 @@ function parseDatasetToProps(data) {
|
|||
learnMorePath,
|
||||
aboutPricingUrl,
|
||||
triggerEvents: JSON.parse(triggerEvents),
|
||||
sections: JSON.parse(sections, { deep: true }),
|
||||
sections: JSON.parse(sections),
|
||||
fields: convertObjectPropsToCamelCase(JSON.parse(fields), { deep: true }),
|
||||
inheritFromId: parseInt(inheritFromId, 10),
|
||||
integrationLevel,
|
||||
|
|
|
@ -45,7 +45,7 @@ module Registrations
|
|||
end
|
||||
|
||||
def update_params
|
||||
params.require(:user).permit(:role, :other_role, :setup_for_company)
|
||||
params.require(:user).permit(:role, :setup_for_company)
|
||||
end
|
||||
|
||||
def requires_confirmation?(user)
|
||||
|
|
|
@ -127,7 +127,7 @@ module Nav
|
|||
href: dashboard_milestones_path,
|
||||
active: active_nav_link?(controller: 'dashboard/milestones'),
|
||||
icon: 'clock',
|
||||
data: { qa_selector: 'milestones_link' },
|
||||
data: { qa_selector: 'milestones_link', **menu_data_tracking_attrs('milestones') },
|
||||
shortcut_class: 'dashboard-shortcuts-milestones'
|
||||
)
|
||||
end
|
||||
|
@ -135,7 +135,7 @@ module Nav
|
|||
if dashboard_nav_link?(:snippets)
|
||||
builder.add_primary_menu_item_with_shortcut(
|
||||
active: active_nav_link?(controller: 'dashboard/snippets'),
|
||||
data: { qa_selector: 'snippets_link' },
|
||||
data: { qa_selector: 'snippets_link', **menu_data_tracking_attrs('snippets') },
|
||||
href: dashboard_snippets_path,
|
||||
**snippets_menu_item_attrs
|
||||
)
|
||||
|
@ -148,7 +148,7 @@ module Nav
|
|||
href: activity_dashboard_path,
|
||||
active: active_nav_link?(path: 'dashboard#activity'),
|
||||
icon: 'history',
|
||||
data: { qa_selector: 'activity_link' },
|
||||
data: { qa_selector: 'activity_link', **menu_data_tracking_attrs('activity') },
|
||||
shortcut_class: 'dashboard-shortcuts-activity'
|
||||
)
|
||||
end
|
||||
|
@ -158,13 +158,16 @@ module Nav
|
|||
# we should be good.
|
||||
# rubocop: disable Cop/UserAdmin
|
||||
if current_user&.admin?
|
||||
title = _('Admin')
|
||||
|
||||
builder.add_secondary_menu_item(
|
||||
id: 'admin',
|
||||
title: _('Admin'),
|
||||
title: title,
|
||||
active: active_nav_link?(controller: 'admin/dashboard'),
|
||||
icon: 'admin',
|
||||
css_class: 'qa-admin-area-link',
|
||||
href: admin_root_path
|
||||
href: admin_root_path,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
|
||||
)
|
||||
end
|
||||
|
||||
|
@ -176,15 +179,18 @@ module Nav
|
|||
active: active_nav_link?(controller: 'admin/sessions'),
|
||||
icon: 'lock-open',
|
||||
href: destroy_admin_session_path,
|
||||
data: { method: 'post' }
|
||||
data: { method: 'post', **menu_data_tracking_attrs('leave_admin_mode') }
|
||||
)
|
||||
elsif current_user.admin?
|
||||
title = _('Enter Admin Mode')
|
||||
|
||||
builder.add_secondary_menu_item(
|
||||
id: 'enter_admin_mode',
|
||||
title: _('Enter Admin Mode'),
|
||||
title: title,
|
||||
active: active_nav_link?(controller: 'admin/sessions'),
|
||||
icon: 'lock',
|
||||
href: new_admin_session_path
|
||||
href: new_admin_session_path,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
|
||||
)
|
||||
end
|
||||
end
|
||||
|
@ -218,6 +224,14 @@ module Nav
|
|||
}
|
||||
end
|
||||
|
||||
def menu_data_tracking_attrs(label)
|
||||
tracking_attrs(
|
||||
"menu_#{label.underscore.parameterize(separator: '_')}",
|
||||
'click_dropdown',
|
||||
'navigation'
|
||||
)[:data] || {}
|
||||
end
|
||||
|
||||
def container_view_props(namespace:, current_item:, submenu:)
|
||||
{
|
||||
namespace: namespace,
|
||||
|
@ -260,21 +274,51 @@ module Nav
|
|||
|
||||
def projects_submenu_items(builder:)
|
||||
# These project links come from `app/views/layouts/nav/projects_dropdown/_show.html.haml`
|
||||
builder.add_primary_menu_item(id: 'your', title: _('Your projects'), href: dashboard_projects_path)
|
||||
builder.add_primary_menu_item(id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path)
|
||||
builder.add_primary_menu_item(id: 'explore', title: _('Explore projects'), href: explore_root_path)
|
||||
builder.add_primary_menu_item(id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path)
|
||||
builder.add_secondary_menu_item(id: 'create', title: _('Create new project'), href: new_project_path)
|
||||
[
|
||||
{ id: 'your', title: _('Your projects'), href: dashboard_projects_path },
|
||||
{ id: 'starred', title: _('Starred projects'), href: starred_dashboard_projects_path },
|
||||
{ id: 'explore', title: _('Explore projects'), href: explore_root_path },
|
||||
{ id: 'topics', title: _('Explore topics'), href: topics_explore_projects_path }
|
||||
].each do |item|
|
||||
builder.add_primary_menu_item(
|
||||
**item,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
|
||||
)
|
||||
end
|
||||
|
||||
title = _('Create new project')
|
||||
|
||||
builder.add_secondary_menu_item(
|
||||
id: 'create',
|
||||
title: title,
|
||||
href: new_project_path,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
|
||||
)
|
||||
end
|
||||
|
||||
def groups_submenu
|
||||
# These group links come from `app/views/layouts/nav/groups_dropdown/_show.html.haml`
|
||||
builder = ::Gitlab::Nav::TopNavMenuBuilder.new
|
||||
builder.add_primary_menu_item(id: 'your', title: _('Your groups'), href: dashboard_groups_path)
|
||||
builder.add_primary_menu_item(id: 'explore', title: _('Explore groups'), href: explore_groups_path)
|
||||
|
||||
[
|
||||
{ id: 'your', title: _('Your groups'), href: dashboard_groups_path },
|
||||
{ id: 'explore', title: _('Explore groups'), href: explore_groups_path }
|
||||
].each do |item|
|
||||
builder.add_primary_menu_item(
|
||||
**item,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: item[:title], **menu_data_tracking_attrs(item[:title]) }
|
||||
)
|
||||
end
|
||||
|
||||
if current_user.can_create_group?
|
||||
builder.add_secondary_menu_item(id: 'create', title: _('Create group'), href: new_group_path)
|
||||
title = _('Create group')
|
||||
|
||||
builder.add_secondary_menu_item(
|
||||
id: 'create',
|
||||
title: title,
|
||||
href: new_group_path,
|
||||
data: { qa_selector: 'menu_item_link', qa_title: title, **menu_data_tracking_attrs(title) }
|
||||
)
|
||||
end
|
||||
|
||||
builder.build
|
||||
|
|
|
@ -338,7 +338,6 @@ class User < ApplicationRecord
|
|||
|
||||
delegate :path, to: :namespace, allow_nil: true, prefix: true
|
||||
delegate :job_title, :job_title=, to: :user_detail, allow_nil: true
|
||||
delegate :other_role, :other_role=, to: :user_detail, allow_nil: true
|
||||
delegate :bio, :bio=, to: :user_detail, allow_nil: true
|
||||
delegate :webauthn_xid, :webauthn_xid=, to: :user_detail, allow_nil: true
|
||||
delegate :pronouns, :pronouns=, to: :user_detail, allow_nil: true
|
||||
|
|
|
@ -2,6 +2,9 @@
|
|||
|
||||
class UserDetail < ApplicationRecord
|
||||
extend ::Gitlab::Utils::Override
|
||||
include IgnorableColumns
|
||||
|
||||
ignore_columns :other_role, remove_after: '2022-07-22', remove_with: '15.3'
|
||||
|
||||
REGISTRATION_OBJECTIVE_PAIRS = { basics: 0, move_repository: 1, code_storage: 2, exploring: 3, ci: 4, other: 5, joining_team: 6 }.freeze
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
= _('Next')
|
||||
|
||||
- if current_user
|
||||
.gl-display-none.gl-sm-display-block{ **tracking_attrs('Menu', 'click_dropdown', 'navigation') }
|
||||
.gl-display-none.gl-sm-display-block
|
||||
= render "layouts/nav/top_nav"
|
||||
- else
|
||||
- experiment(:logged_out_marketing_header, actor: nil) do |e|
|
||||
|
|
|
@ -24,11 +24,6 @@
|
|||
.form-group.col-sm-12
|
||||
= f.label :role, _('Role'), class: 'label-bold'
|
||||
= f.select :role, ::User.roles.keys.map { |role| [role.titleize, role] }, { include_blank: _('Select a role') }, class: 'form-control js-user-role-dropdown', autofocus: true, required: true, data: { qa_selector: 'role_dropdown' }
|
||||
- if Feature.enabled?(:user_other_role_details)
|
||||
.row
|
||||
.form-group.col-sm-12.js-other-role-group.hidden
|
||||
= f.label :other_role, _('What is your job title? (optional)')
|
||||
= f.text_field :other_role, class: 'form-control'
|
||||
= render_if_exists "registrations/welcome/jobs_to_be_done", f: f
|
||||
= render_if_exists "registrations/welcome/setup_for_company", f: f
|
||||
= render_if_exists "registrations/welcome/joining_project"
|
||||
|
|
|
@ -13,8 +13,6 @@ module Database
|
|||
version 1
|
||||
|
||||
def perform
|
||||
return if Feature.disabled?(:ci_namespace_mirrors_consistency_check)
|
||||
|
||||
results = ConsistencyCheckService.new(
|
||||
source_model: Namespace,
|
||||
target_model: Ci::NamespaceMirror,
|
||||
|
|
|
@ -13,8 +13,6 @@ module Database
|
|||
version 1
|
||||
|
||||
def perform
|
||||
return if Feature.disabled?(:ci_project_mirrors_consistency_check)
|
||||
|
||||
results = ConsistencyCheckService.new(
|
||||
source_model: Project,
|
||||
target_model: Ci::ProjectMirror,
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_namespace_mirrors_consistency_check
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81836
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/356577
|
||||
milestone: '14.10'
|
||||
type: development
|
||||
group: group::sharding
|
||||
default_enabled: true
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_project_mirrors_consistency_check
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81836
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/356583
|
||||
milestone: '14.10'
|
||||
type: development
|
||||
group: group::sharding
|
||||
default_enabled: true
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: user_other_role_details
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45635
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/282
|
||||
milestone: '13.7'
|
||||
type: development
|
||||
group: group::conversion
|
||||
default_enabled: false
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: vsa_incremental_worker
|
||||
introduced_by_url:
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/353453
|
||||
milestone: '14.9'
|
||||
type: development
|
||||
group: group::optimize
|
||||
default_enabled: true
|
|
@ -138,3 +138,28 @@ installed Ruby manually or via tools like `asdf`. Users of the `gitlab-developme
|
|||
are also affected by this problem.
|
||||
|
||||
Build images are not affected because they include the patch set addressing this bug.
|
||||
|
||||
## Deprecations are not caught in DeprecationToolkit if the method is stubbed
|
||||
|
||||
We rely on `deprecation_toolkit` to fail fast when using functionality that is deprecated in Ruby 2 and removed in Ruby 3.
|
||||
A common issue caught during the transition from Ruby 2 to Ruby 3 relates to
|
||||
the [separation of positional and keyword arguments in Ruby 3.0](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/).
|
||||
|
||||
Unfortunately, if the author has stubbed such methods in tests, deprecations would not be caught.
|
||||
We run automated detection for this warning in tests via `deprecation_toolkit`,
|
||||
but it relies on the fact that `Kernel#warn` emits a warning, so stubbing out this call will effectively remove the call to warn, which means `deprecation_toolkit` will never see the deprecation warnings.
|
||||
Stubbing out the implementation removes that warning, and we never pick it up, so the build is green.
|
||||
|
||||
Please refer to [issue 364099](https://gitlab.com/gitlab-org/gitlab/-/issues/364099) for more context.
|
||||
|
||||
## Testing in `irb` and `rails console`
|
||||
|
||||
Another pitfall is that testing in `irb`/`rails c` silences the deprecation warning,
|
||||
since `irb` in Ruby 2.7.x has a [bug](https://bugs.ruby-lang.org/issues/17377) that prevents deprecation warnings from showing.
|
||||
|
||||
When writing code and performing code reviews, pay extra attention to method calls of the form `f({k: v})`.
|
||||
This is valid in Ruby 2 when `f` takes either a `Hash` or keyword arguments, but Ruby 3 only considers this valid if `f` takes a `Hash`.
|
||||
For Ruby 3 compliance, this should be changed to one of the following invocations if `f` takes keyword arguments:
|
||||
|
||||
- `f(**{k: v})`
|
||||
- `f(k: v)`
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Check a user's access to perform a git action. All public methods in this
|
||||
# class return an instance of `GitlabAccessStatus`
|
||||
# Checks a user's access to perform a git action.
|
||||
# All public methods in this class return an instance of `GitlabAccessStatus`
|
||||
|
||||
module Gitlab
|
||||
class GitAccess
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
@ -99,7 +100,7 @@ module Gitlab
|
|||
@logger ||= Checks::TimedLogger.new(timeout: INTERNAL_TIMEOUT, header: LOG_HEADER)
|
||||
end
|
||||
|
||||
def guest_can_download_code?
|
||||
def guest_can_download?
|
||||
Guest.can?(download_ability, container)
|
||||
end
|
||||
|
||||
|
@ -110,7 +111,7 @@ module Gitlab
|
|||
(project? && project&.repository_access_level != ::Featurable::DISABLED)
|
||||
end
|
||||
|
||||
def user_can_download_code?
|
||||
def user_can_download?
|
||||
authentication_abilities.include?(:download_code) &&
|
||||
user_access.can_do_action?(download_ability)
|
||||
end
|
||||
|
@ -125,10 +126,6 @@ module Gitlab
|
|||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def build_can_download_code?
|
||||
authentication_abilities.include?(:build_download_code) && user_access.can_do_action?(:build_download_code)
|
||||
end
|
||||
|
||||
def request_from_ci_build?
|
||||
return false unless protocol == 'http'
|
||||
|
||||
|
@ -141,6 +138,31 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
# when accessing via the CI_JOB_TOKEN
|
||||
def build_can_download_code?
|
||||
authentication_abilities.include?(:build_download_code) && user_access.can_do_action?(:build_download_code)
|
||||
end
|
||||
|
||||
def build_can_download?
|
||||
build_can_download_code?
|
||||
end
|
||||
|
||||
def deploy_token_can_download?
|
||||
deploy_token?
|
||||
end
|
||||
|
||||
# When overriding this method, be careful using super
|
||||
# as deploy_token_can_download? and build_can_download?
|
||||
# do not consider the download_ability in the inheriting class
|
||||
# for deploy tokens and builds
|
||||
def can_download?
|
||||
deploy_key_can_download_code? ||
|
||||
deploy_token_can_download? ||
|
||||
build_can_download? ||
|
||||
user_can_download? ||
|
||||
guest_can_download?
|
||||
end
|
||||
|
||||
def check_container!
|
||||
# Strict nil check, to avoid any surprises with Object#present?
|
||||
# which can delegate to #empty?
|
||||
|
@ -273,16 +295,10 @@ module Gitlab
|
|||
end
|
||||
|
||||
def check_download_access!
|
||||
passed = deploy_key_can_download_code? ||
|
||||
deploy_token? ||
|
||||
user_can_download_code? ||
|
||||
build_can_download_code? ||
|
||||
guest_can_download_code?
|
||||
return if can_download?
|
||||
|
||||
unless passed
|
||||
raise ForbiddenError, download_forbidden_message
|
||||
end
|
||||
end
|
||||
|
||||
def download_forbidden_message
|
||||
error_message(:download)
|
||||
|
|
|
@ -90,13 +90,14 @@ module Gitlab
|
|||
super
|
||||
end
|
||||
|
||||
override :check_download_access!
|
||||
def check_download_access!
|
||||
passed = guest_can_download_code? || user_can_download_code?
|
||||
|
||||
unless passed
|
||||
raise ForbiddenError, error_message(:read_snippet)
|
||||
override :can_download?
|
||||
def can_download?
|
||||
guest_can_download? || user_can_download?
|
||||
end
|
||||
|
||||
override :download_forbidden_message
|
||||
def download_forbidden_message
|
||||
error_message(:read_snippet)
|
||||
end
|
||||
|
||||
override :check_change_access!
|
||||
|
|
|
@ -27,12 +27,16 @@ module Gitlab
|
|||
:create_wiki
|
||||
end
|
||||
|
||||
override :check_download_access!
|
||||
def check_download_access!
|
||||
super
|
||||
private
|
||||
|
||||
raise ForbiddenError, download_forbidden_message if build_cannot_download?
|
||||
raise ForbiddenError, download_forbidden_message if deploy_token_cannot_download?
|
||||
override :build_can_download?
|
||||
def build_can_download?
|
||||
super && user_access.can_do_action?(download_ability)
|
||||
end
|
||||
|
||||
override :deploy_token_can_download?
|
||||
def deploy_token_can_download?
|
||||
super && deploy_token.can?(download_ability, container)
|
||||
end
|
||||
|
||||
override :check_change_access!
|
||||
|
@ -53,17 +57,6 @@ module Gitlab
|
|||
def not_found_message
|
||||
error_message(:not_found)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# when accessing via the CI_JOB_TOKEN
|
||||
def build_cannot_download?
|
||||
build_can_download_code? && !user_access.can_do_action?(download_ability)
|
||||
end
|
||||
|
||||
def deploy_token_cannot_download?
|
||||
deploy_token && !deploy_token.can?(download_ability, container)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -20464,6 +20464,33 @@ msgstr ""
|
|||
msgid "Integration Settings"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A comment is added on a confidential issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A comment is added on an issue"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A confidential issue is created, updated, or closed"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A merge request is created, updated, or merged"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A pipeline status changes"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A push is made to the repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A tag is pushed to the repository"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|A wiki page is created or updated"
|
||||
msgstr ""
|
||||
|
||||
msgid "IntegrationEvents|An issue is created, updated, or closed"
|
||||
msgstr ""
|
||||
|
||||
msgid "Integrations"
|
||||
msgstr ""
|
||||
|
||||
|
@ -42780,9 +42807,6 @@ msgstr ""
|
|||
msgid "What is squashing?"
|
||||
msgstr ""
|
||||
|
||||
msgid "What is your job title? (optional)"
|
||||
msgstr ""
|
||||
|
||||
msgid "What templates can I create?"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -57,7 +57,7 @@
|
|||
"@gitlab/at.js": "1.5.7",
|
||||
"@gitlab/favicon-overlay": "2.0.0",
|
||||
"@gitlab/svgs": "2.14.0",
|
||||
"@gitlab/ui": "40.6.6",
|
||||
"@gitlab/ui": "40.7.1",
|
||||
"@gitlab/visual-review-tools": "1.7.3",
|
||||
"@rails/actioncable": "6.1.4-7",
|
||||
"@rails/ujs": "6.1.4-7",
|
||||
|
|
|
@ -95,7 +95,7 @@ RSpec.describe 'User adds pages domain', :js do
|
|||
|
||||
fill_in 'Domain', with: 'my.test.domain.com'
|
||||
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle button').click
|
||||
|
||||
fill_in 'Certificate (PEM)', with: certificate_pem
|
||||
fill_in 'Key (PEM)', with: certificate_key
|
||||
|
|
|
@ -50,7 +50,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
expect(page).to have_selector '.card-header', text: 'Certificate'
|
||||
expect(page).to have_text domain.subject
|
||||
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle button').click
|
||||
|
||||
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'true'
|
||||
expect(page).not_to have_selector '.card-header', text: 'Certificate'
|
||||
|
@ -74,7 +74,7 @@ RSpec.describe "Pages with Let's Encrypt", :https_pages_enabled do
|
|||
expect(page).not_to have_field 'Certificate (PEM)', type: 'textarea'
|
||||
expect(page).not_to have_field 'Key (PEM)', type: 'textarea'
|
||||
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle').click
|
||||
find('.js-auto-ssl-toggle-container .js-project-feature-toggle button').click
|
||||
|
||||
expect(find("#pages_domain_auto_ssl_enabled", visible: false).value).to eq 'false'
|
||||
expect(page).to have_field 'Certificate (PEM)', type: 'textarea'
|
||||
|
|
|
@ -117,7 +117,7 @@ describe('FrequentItemsListItemComponent', () => {
|
|||
link.vm.$emit('click');
|
||||
|
||||
expect(trackingSpy).toHaveBeenCalledWith(undefined, 'click_link', {
|
||||
label: 'projects_dropdown_frequent_items_list_item',
|
||||
label: 'projects_dropdown_frequent_items_list_item_git_lab_community_edition',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
|
||||
import IntegrationSectionTrigger from '~/integrations/edit/components/sections/trigger.vue';
|
||||
import TriggerField from '~/integrations/edit/components/trigger_field.vue';
|
||||
import { createStore } from '~/integrations/edit/store';
|
||||
|
||||
import { mockIntegrationProps } from '../../mock_data';
|
||||
|
||||
describe('IntegrationSectionTrigger', () => {
|
||||
let wrapper;
|
||||
|
||||
const createComponent = () => {
|
||||
const store = createStore({
|
||||
customState: { ...mockIntegrationProps },
|
||||
});
|
||||
wrapper = shallowMount(IntegrationSectionTrigger, {
|
||||
store,
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
const findAllTriggerFields = () => wrapper.findAllComponents(TriggerField);
|
||||
|
||||
describe('template', () => {
|
||||
it('renders correct number of TriggerField components', () => {
|
||||
createComponent();
|
||||
|
||||
const fields = findAllTriggerFields();
|
||||
expect(fields.length).toBe(mockIntegrationProps.triggerEvents.length);
|
||||
fields.wrappers.forEach((field, index) => {
|
||||
expect(field.props('event')).toBe(mockIntegrationProps.triggerEvents[index]);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,71 @@
|
|||
import { nextTick } from 'vue';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import { GlFormCheckbox } from '@gitlab/ui';
|
||||
|
||||
import TriggerField from '~/integrations/edit/components/trigger_field.vue';
|
||||
import { integrationTriggerEventTitles } from '~/integrations/constants';
|
||||
|
||||
describe('TriggerField', () => {
|
||||
let wrapper;
|
||||
|
||||
const defaultProps = {
|
||||
event: { name: 'push_events' },
|
||||
};
|
||||
|
||||
const createComponent = ({ props = {}, isInheriting = false } = {}) => {
|
||||
wrapper = shallowMount(TriggerField, {
|
||||
propsData: { ...defaultProps, ...props },
|
||||
computed: {
|
||||
isInheriting: () => isInheriting,
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
afterEach(() => {
|
||||
wrapper.destroy();
|
||||
});
|
||||
|
||||
const findGlFormCheckbox = () => wrapper.findComponent(GlFormCheckbox);
|
||||
const findHiddenInput = () => wrapper.find('input[type="hidden"]');
|
||||
|
||||
describe('template', () => {
|
||||
it('renders enabled GlFormCheckbox', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findGlFormCheckbox().attributes('disabled')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('when isInheriting is true, renders disabled GlFormCheckbox', () => {
|
||||
createComponent({ isInheriting: true });
|
||||
|
||||
expect(findGlFormCheckbox().attributes('disabled')).toBe('true');
|
||||
});
|
||||
|
||||
it('renders correct title', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findGlFormCheckbox().text()).toMatchInterpolatedText(
|
||||
integrationTriggerEventTitles[defaultProps.event.name],
|
||||
);
|
||||
});
|
||||
|
||||
it('sets default value for hidden input', () => {
|
||||
createComponent();
|
||||
|
||||
expect(findHiddenInput().attributes('value')).toBe('false');
|
||||
});
|
||||
|
||||
it('toggles value of hidden input on checkbox input', async () => {
|
||||
createComponent({
|
||||
props: { event: { name: 'push_events', value: true } },
|
||||
});
|
||||
await nextTick;
|
||||
|
||||
expect(findHiddenInput().attributes('value')).toBe('true');
|
||||
|
||||
await findGlFormCheckbox().vm.$emit('input', false);
|
||||
|
||||
expect(findHiddenInput().attributes('value')).toBe('false');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -9,7 +9,10 @@ export const mockIntegrationProps = {
|
|||
initialEnableComments: false,
|
||||
},
|
||||
jiraIssuesProps: {},
|
||||
triggerEvents: [],
|
||||
triggerEvents: [
|
||||
{ name: 'push_events', title: 'Push', value: true },
|
||||
{ name: 'issues_events', title: 'Issue', value: true },
|
||||
],
|
||||
sections: [],
|
||||
fields: [],
|
||||
type: '',
|
||||
|
|
|
@ -10,6 +10,7 @@ RSpec.describe Nav::TopNavHelper do
|
|||
let(:current_user) { nil }
|
||||
|
||||
before do
|
||||
stub_application_setting(snowplow_enabled: true)
|
||||
allow(helper).to receive(:current_user) { current_user }
|
||||
end
|
||||
|
||||
|
@ -50,49 +51,40 @@ RSpec.describe Nav::TopNavHelper do
|
|||
context 'when current_user is nil (anonymous)' do
|
||||
it 'has expected :primary' do
|
||||
expected_primary = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
href: '/explore',
|
||||
icon: 'project',
|
||||
id: 'project',
|
||||
title: 'Projects'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
href: '/explore/groups',
|
||||
icon: 'group',
|
||||
id: 'groups',
|
||||
title: 'Groups'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
href: '/explore/snippets',
|
||||
icon: 'snippet',
|
||||
id: 'snippets',
|
||||
title: 'Snippets'
|
||||
)
|
||||
]
|
||||
{ href: '/explore', icon: 'project', id: 'project', title: 'Projects' },
|
||||
{ href: '/explore/groups', icon: 'group', id: 'groups', title: 'Groups' },
|
||||
{ href: '/explore/snippets', icon: 'snippet', id: 'snippets', title: 'Snippets' }
|
||||
].map do |item|
|
||||
::Gitlab::Nav::TopNavMenuItem.build(**item)
|
||||
end
|
||||
|
||||
expect(subject[:primary]).to eq(expected_primary)
|
||||
end
|
||||
|
||||
it 'has expected :shortcuts' do
|
||||
expected_shortcuts = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
{
|
||||
href: '/explore',
|
||||
id: 'project-shortcut',
|
||||
title: 'Projects',
|
||||
css_class: 'dashboard-shortcuts-projects'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
},
|
||||
{
|
||||
href: '/explore/groups',
|
||||
id: 'groups-shortcut',
|
||||
title: 'Groups',
|
||||
css_class: 'dashboard-shortcuts-groups'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
},
|
||||
{
|
||||
href: '/explore/snippets',
|
||||
id: 'snippets-shortcut',
|
||||
title: 'Snippets',
|
||||
css_class: 'dashboard-shortcuts-snippets'
|
||||
)
|
||||
]
|
||||
}
|
||||
].map do |item|
|
||||
::Gitlab::Nav::TopNavMenuItem.build(**item)
|
||||
end
|
||||
|
||||
expect(subject[:shortcuts]).to eq(expected_shortcuts)
|
||||
end
|
||||
|
||||
|
@ -171,21 +163,41 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :linksPrimary' do
|
||||
expected_links_primary = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Your projects',
|
||||
**menu_data_tracking_attrs('your_projects')
|
||||
},
|
||||
href: '/dashboard/projects',
|
||||
id: 'your',
|
||||
title: 'Your projects'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Starred projects',
|
||||
**menu_data_tracking_attrs('starred_projects')
|
||||
},
|
||||
href: '/dashboard/projects/starred',
|
||||
id: 'starred',
|
||||
title: 'Starred projects'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Explore projects',
|
||||
**menu_data_tracking_attrs('explore_projects')
|
||||
},
|
||||
href: '/explore',
|
||||
id: 'explore',
|
||||
title: 'Explore projects'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Explore topics',
|
||||
**menu_data_tracking_attrs('explore_topics')
|
||||
},
|
||||
href: '/explore/projects/topics',
|
||||
id: 'topics',
|
||||
title: 'Explore topics'
|
||||
|
@ -197,6 +209,11 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :linksSecondary' do
|
||||
expected_links_secondary = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Create new project',
|
||||
**menu_data_tracking_attrs('create_new_project')
|
||||
},
|
||||
href: '/projects/new',
|
||||
id: 'create',
|
||||
title: 'Create new project'
|
||||
|
@ -282,11 +299,21 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :linksPrimary' do
|
||||
expected_links_primary = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Your groups',
|
||||
**menu_data_tracking_attrs('your_groups')
|
||||
},
|
||||
href: '/dashboard/groups',
|
||||
id: 'your',
|
||||
title: 'Your groups'
|
||||
),
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Explore groups',
|
||||
**menu_data_tracking_attrs('explore_groups')
|
||||
},
|
||||
href: '/explore/groups',
|
||||
id: 'explore',
|
||||
title: 'Explore groups'
|
||||
|
@ -298,6 +325,11 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :linksSecondary' do
|
||||
expected_links_secondary = [
|
||||
::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Create group',
|
||||
**menu_data_tracking_attrs('create_group')
|
||||
},
|
||||
href: '/groups/new',
|
||||
id: 'create',
|
||||
title: 'Create group'
|
||||
|
@ -356,7 +388,8 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :primary' do
|
||||
expected_primary = ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'milestones_link'
|
||||
qa_selector: 'milestones_link',
|
||||
**menu_data_tracking_attrs('milestones')
|
||||
},
|
||||
href: '/dashboard/milestones',
|
||||
icon: 'clock',
|
||||
|
@ -383,7 +416,8 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :primary' do
|
||||
expected_primary = ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'snippets_link'
|
||||
qa_selector: 'snippets_link',
|
||||
**menu_data_tracking_attrs('snippets')
|
||||
},
|
||||
href: '/dashboard/snippets',
|
||||
icon: 'snippet',
|
||||
|
@ -410,7 +444,8 @@ RSpec.describe Nav::TopNavHelper do
|
|||
it 'has expected :primary' do
|
||||
expected_primary = ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'activity_link'
|
||||
qa_selector: 'activity_link',
|
||||
**menu_data_tracking_attrs('activity')
|
||||
},
|
||||
href: '/dashboard/activity',
|
||||
icon: 'history',
|
||||
|
@ -439,6 +474,11 @@ RSpec.describe Nav::TopNavHelper do
|
|||
|
||||
it 'has admin as first :secondary item' do
|
||||
expected_admin_item = ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Admin',
|
||||
**menu_data_tracking_attrs('admin')
|
||||
},
|
||||
id: 'admin',
|
||||
title: 'Admin',
|
||||
icon: 'admin',
|
||||
|
@ -458,7 +498,7 @@ RSpec.describe Nav::TopNavHelper do
|
|||
title: 'Leave Admin Mode',
|
||||
icon: 'lock-open',
|
||||
href: '/admin/session/destroy',
|
||||
data: { method: 'post' }
|
||||
data: { method: 'post', **menu_data_tracking_attrs('leave_admin_mode') }
|
||||
)
|
||||
expect(subject[:secondary].last).to eq(expected_leave_admin_mode_item)
|
||||
end
|
||||
|
@ -469,6 +509,11 @@ RSpec.describe Nav::TopNavHelper do
|
|||
|
||||
it 'has enter_admin_mode as last :secondary item' do
|
||||
expected_enter_admin_mode_item = ::Gitlab::Nav::TopNavMenuItem.build(
|
||||
data: {
|
||||
qa_selector: 'menu_item_link',
|
||||
qa_title: 'Enter Admin Mode',
|
||||
**menu_data_tracking_attrs('enter_admin_mode')
|
||||
},
|
||||
id: 'enter_admin_mode',
|
||||
title: 'Enter Admin Mode',
|
||||
icon: 'lock',
|
||||
|
@ -533,4 +578,12 @@ RSpec.describe Nav::TopNavHelper do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
def menu_data_tracking_attrs(label)
|
||||
{
|
||||
track_label: "menu_#{label}",
|
||||
track_action: 'click_dropdown',
|
||||
track_property: 'navigation'
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
@ -121,13 +121,19 @@ RSpec.describe Gitlab::GitAccessSnippet do
|
|||
if Ability.allowed?(user, :update_snippet, snippet)
|
||||
expect { push_access_check }.not_to raise_error
|
||||
else
|
||||
expect { push_access_check }.to raise_error(described_class::ForbiddenError)
|
||||
expect { push_access_check }.to raise_error(
|
||||
described_class::ForbiddenError,
|
||||
described_class::ERROR_MESSAGES[:update_snippet]
|
||||
)
|
||||
end
|
||||
|
||||
if Ability.allowed?(user, :read_snippet, snippet)
|
||||
expect { pull_access_check }.not_to raise_error
|
||||
else
|
||||
expect { pull_access_check }.to raise_error(described_class::ForbiddenError)
|
||||
expect { pull_access_check }.to raise_error(
|
||||
described_class::ForbiddenError,
|
||||
described_class::ERROR_MESSAGES[:read_snippet]
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -18,7 +18,7 @@ RSpec.describe Gitlab::GitAccessWiki do
|
|||
redirected_path: redirected_path)
|
||||
end
|
||||
|
||||
RSpec.shared_examples 'wiki access by level' do
|
||||
RSpec.shared_examples 'download wiki access by level' do
|
||||
where(:project_visibility, :project_member?, :wiki_access_level, :wiki_repo?, :expected_behavior) do
|
||||
[
|
||||
# Private project - is a project member
|
||||
|
@ -103,7 +103,7 @@ RSpec.describe Gitlab::GitAccessWiki do
|
|||
subject { access.check('git-upload-pack', Gitlab::GitAccess::ANY) }
|
||||
|
||||
context 'when actor is a user' do
|
||||
it_behaves_like 'wiki access by level'
|
||||
it_behaves_like 'download wiki access by level'
|
||||
end
|
||||
|
||||
context 'when the actor is a deploy token' do
|
||||
|
@ -116,17 +116,23 @@ RSpec.describe Gitlab::GitAccessWiki do
|
|||
|
||||
subject { access.check('git-upload-pack', changes) }
|
||||
|
||||
context 'when the wiki is enabled' do
|
||||
context 'when the wiki feature is enabled' do
|
||||
let(:wiki_access_level) { ProjectFeature::ENABLED }
|
||||
|
||||
it { expect { subject }.not_to raise_error }
|
||||
end
|
||||
|
||||
context 'when the wiki is disabled' do
|
||||
context 'when the wiki feature is disabled' do
|
||||
let(:wiki_access_level) { ProjectFeature::DISABLED }
|
||||
|
||||
it { expect { subject }.to raise_wiki_forbidden }
|
||||
end
|
||||
|
||||
context 'when the wiki feature is private' do
|
||||
let(:wiki_access_level) { ProjectFeature::PRIVATE }
|
||||
|
||||
it { expect { subject }.to raise_wiki_forbidden }
|
||||
end
|
||||
end
|
||||
|
||||
describe 'when actor is a user provided by build via CI_JOB_TOKEN' do
|
||||
|
@ -140,7 +146,7 @@ RSpec.describe Gitlab::GitAccessWiki do
|
|||
|
||||
subject { access.check('git-upload-pack', changes) }
|
||||
|
||||
it_behaves_like 'wiki access by level'
|
||||
it_behaves_like 'download wiki access by level'
|
||||
end
|
||||
end
|
||||
|
||||
|
|
10
spec/requests/api/markdown_snapshot_spec.rb
Normal file
10
spec/requests/api/markdown_snapshot_spec.rb
Normal file
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
# See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#markdown-snapshot-testing
|
||||
# for documentation on this spec.
|
||||
RSpec.describe API::Markdown, 'Snapshot' do
|
||||
glfm_example_snapshots_dir = File.expand_path('../../fixtures/glfm/example_snapshots', __dir__)
|
||||
include_context 'API::Markdown Snapshot shared context', glfm_example_snapshots_dir
|
||||
end
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
# See https://docs.gitlab.com/ee/development/gitlab_flavored_markdown/specification_guide/#markdown-snapshot-testing
|
||||
# for documentation on this spec.
|
||||
RSpec.shared_context 'API::Markdown Snapshot shared context' do |glfm_example_snapshots_dir|
|
||||
include ApiHelpers
|
||||
|
||||
markdown_examples, html_examples = %w[markdown.yml html.yml].map do |file_name|
|
||||
yaml = File.read("#{glfm_example_snapshots_dir}/#{file_name}")
|
||||
YAML.safe_load(yaml, symbolize_names: true, aliases: true)
|
||||
end
|
||||
|
||||
if focused_markdown_examples_string = ENV['FOCUSED_MARKDOWN_EXAMPLES']
|
||||
focused_markdown_examples = focused_markdown_examples_string.split(',').map(&:strip).map(&:to_sym)
|
||||
markdown_examples.select! { |example_name| focused_markdown_examples.include?(example_name) }
|
||||
end
|
||||
|
||||
markdown_examples.each do |name, markdown|
|
||||
context "for #{name}" do
|
||||
let(:html) { html_examples.fetch(name).fetch(:static) }
|
||||
|
||||
it "verifies conversion of GLFM to HTML", :unlimited_max_formatted_output_length do
|
||||
api_url = api "/markdown"
|
||||
|
||||
post api_url, params: { text: markdown, gfm: true }
|
||||
expect(response).to be_successful
|
||||
response_body = Gitlab::Json.parse(response.body)
|
||||
# Some requests have the HTML in the `html` key, others in the `body` key.
|
||||
response_html = response_body['body'] ? response_body.fetch('body') : response_body.fetch('html')
|
||||
|
||||
expect(response_html).to eq(html)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -6,30 +6,12 @@ RSpec.describe Database::CiNamespaceMirrorsConsistencyCheckWorker do
|
|||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
context 'feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_namespace_mirrors_consistency_check: false)
|
||||
end
|
||||
|
||||
it 'does not perform the consistency check on namespaces' do
|
||||
expect(Database::ConsistencyCheckService).not_to receive(:new)
|
||||
expect(worker).not_to receive(:log_extra_metadata_on_done)
|
||||
worker.perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_namespace_mirrors_consistency_check: true)
|
||||
end
|
||||
|
||||
it 'executes the consistency check on namespaces' do
|
||||
expect(Database::ConsistencyCheckService).to receive(:new).and_call_original
|
||||
expected_result = { batches: 0, matches: 0, mismatches: 0, mismatches_details: [] }
|
||||
expect(worker).to receive(:log_extra_metadata_on_done).with(:results, expected_result)
|
||||
worker.perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'logs should contain the detailed mismatches' do
|
||||
let(:first_namespace) { Namespace.all.order(:id).limit(1).first }
|
||||
|
@ -37,7 +19,6 @@ RSpec.describe Database::CiNamespaceMirrorsConsistencyCheckWorker do
|
|||
|
||||
before do
|
||||
redis_shared_state_cleanup!
|
||||
stub_feature_flags(ci_namespace_mirrors_consistency_check: true)
|
||||
create_list(:namespace, 10) # This will also create Ci::NameSpaceMirror objects
|
||||
missing_namespace.delete
|
||||
|
||||
|
|
|
@ -6,30 +6,12 @@ RSpec.describe Database::CiProjectMirrorsConsistencyCheckWorker do
|
|||
let(:worker) { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
context 'feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_project_mirrors_consistency_check: false)
|
||||
end
|
||||
|
||||
it 'does not perform the consistency check on projects' do
|
||||
expect(Database::ConsistencyCheckService).not_to receive(:new)
|
||||
expect(worker).not_to receive(:log_extra_metadata_on_done)
|
||||
worker.perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'feature flag is enabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_project_mirrors_consistency_check: true)
|
||||
end
|
||||
|
||||
it 'executes the consistency check on projects' do
|
||||
expect(Database::ConsistencyCheckService).to receive(:new).and_call_original
|
||||
expected_result = { batches: 0, matches: 0, mismatches: 0, mismatches_details: [] }
|
||||
expect(worker).to receive(:log_extra_metadata_on_done).with(:results, expected_result)
|
||||
worker.perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'logs should contain the detailed mismatches' do
|
||||
let(:first_project) { Project.all.order(:id).limit(1).first }
|
||||
|
@ -37,7 +19,6 @@ RSpec.describe Database::CiProjectMirrorsConsistencyCheckWorker do
|
|||
|
||||
before do
|
||||
redis_shared_state_cleanup!
|
||||
stub_feature_flags(ci_project_mirrors_consistency_check: true)
|
||||
create_list(:project, 10) # This will also create Ci::ProjectMirror objects
|
||||
missing_project.delete
|
||||
|
||||
|
|
|
@ -968,10 +968,10 @@
|
|||
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.14.0.tgz#92b36bc98ccbed49a4dbca310862146275091cb2"
|
||||
integrity sha512-U9EYmEIiTMl7R3X5DmCrw6fz7gz8c1kjvQtaF6HfJ15xDtR7trRAyCNbn3z7YGk1QJ8Cv/Ifw2/T5SxXwYd7dw==
|
||||
|
||||
"@gitlab/ui@40.6.6":
|
||||
version "40.6.6"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.6.6.tgz#07e95edd1b0afe8cb2f42880f634657ffbcaa3cd"
|
||||
integrity sha512-hHwu63oldEtALYS3KPkU0CUVIznpoScAURzCKscw2/wNmXc+siVOA4iGPJ012h5Jza7itTeQg0UFCWGjigUaYA==
|
||||
"@gitlab/ui@40.7.1":
|
||||
version "40.7.1"
|
||||
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.7.1.tgz#e6595c5cc37d994e3f0ba780626fbf4e8174df2a"
|
||||
integrity sha512-u100mDpdI7RfNVcAYi8n0RRH2FfIiYuMVgt5jPrQ7AAL+QrwLAkqfBZtkT9pSMpycBuuQsxSMHJK5FlnXum46g==
|
||||
dependencies:
|
||||
"@popperjs/core" "^2.11.2"
|
||||
bootstrap-vue "2.20.1"
|
||||
|
|
Loading…
Reference in a new issue