Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-10-12 18:10:44 +00:00
parent 901ecdbf5c
commit 41b2e83ad6
92 changed files with 698 additions and 342 deletions

View File

@ -91,3 +91,5 @@ export const placeholderForType = {
[INTEGRATION_TYPE_SLACK]: __('#general, #development'),
[INTEGRATION_TYPE_MATTERMOST]: __('my-channel'),
};
export const INTEGRATION_FORM_TYPE_SLACK = 'gitlab_slack_application';

View File

@ -14,12 +14,14 @@ import {
I18N_FETCH_TEST_SETTINGS_DEFAULT_ERROR_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
INTEGRATION_FORM_TYPE_SLACK,
integrationLevels,
integrationFormSectionComponents,
billingPlanNames,
} from '~/integrations/constants';
import { refreshCurrentPage } from '~/lib/utils/url_utility';
import csrf from '~/lib/utils/csrf';
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { testIntegrationSettings } from '../api';
import ActiveCheckbox from './active_checkbox.vue';
import ConfirmationModal from './confirmation_modal.vue';
@ -65,6 +67,7 @@ export default {
GlModal: GlModalDirective,
SafeHtml,
},
mixins: [glFeatureFlagsMixin()],
inject: {
helpHtml: {
default: '',
@ -101,6 +104,9 @@ export default {
return Boolean(this.isSaving || this.isResetting || this.isTesting);
},
hasSections() {
if (this.hasSlackNotificationsDisabled) {
return false;
}
return this.customState.sections.length !== 0;
},
fieldsWithoutSection() {
@ -109,8 +115,23 @@ export default {
: this.propsSource.fields;
},
hasFieldsWithoutSection() {
if (this.hasSlackNotificationsDisabled) {
return false;
}
return this.fieldsWithoutSection.length;
},
isSlackIntegration() {
return this.propsSource.type === INTEGRATION_FORM_TYPE_SLACK;
},
hasSlackNotificationsDisabled() {
return this.isSlackIntegration && !this.glFeatures.integrationSlackAppNotifications;
},
showHelpHtml() {
if (this.isSlackIntegration) {
return this.helpHtml;
}
return !this.hasSections && this.helpHtml;
},
},
methods: {
...mapActions(['setOverride', 'requestJiraIssueTypes']),
@ -230,11 +251,17 @@ export default {
@change="setOverride"
/>
<section v-if="showHelpHtml" class="gl-lg-display-flex gl-justify-content-end gl-mb-6">
<!-- helpHtml is trusted input -->
<div
v-safe-html:[$options.helpHtmlConfig]="helpHtml"
data-testid="help-html"
class="gl-flex-basis-two-thirds"
></div>
</section>
<section v-if="!hasSections" class="gl-lg-display-flex gl-justify-content-end">
<div class="gl-flex-basis-two-thirds">
<!-- helpHtml is trusted input -->
<div v-if="helpHtml" v-safe-html:[$options.helpHtmlConfig]="helpHtml"></div>
<active-checkbox
v-if="propsSource.showActive"
:key="`${currentKey}-active-checkbox`"
@ -257,7 +284,7 @@ export default {
data-testid="integration-section"
>
<section class="gl-lg-display-flex">
<div class="gl-flex-basis-third">
<div class="gl-flex-basis-third gl-mr-4">
<h4 class="gl-mt-0">
{{ section.title
}}<gl-badge

View File

@ -1,10 +1,9 @@
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { __ } from '~/locale';
import { ISSUE_STATUS_SELECT_OPTIONS } from '../constants';
import { statusDropdownOptions } from '../constants';
export default {
name: 'StatusSelect',
components: {
GlDropdown,
GlDropdownItem,
@ -36,7 +35,7 @@ export default {
dropdownTitle: __('Change status'),
defaultDropdownText: __('Select status'),
},
ISSUE_STATUS_SELECT_OPTIONS,
statusDropdownOptions,
};
</script>
<template>
@ -44,7 +43,7 @@ export default {
<input type="hidden" name="update[state_event]" :value="selectedValue" />
<gl-dropdown :text="dropdownText" :title="$options.i18n.dropdownTitle" class="gl-w-full">
<gl-dropdown-item
v-for="statusOption in $options.ISSUE_STATUS_SELECT_OPTIONS"
v-for="statusOption in $options.statusDropdownOptions"
:key="statusOption.value"
:is-checked="selectedValue === statusOption.value"
is-check-item

View File

@ -0,0 +1,51 @@
<script>
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { __ } from '~/locale';
import { subscriptionsDropdownOptions } from '../constants';
export default {
subscriptionsDropdownOptions,
i18n: {
defaultDropdownText: __('Select subscription'),
headerText: __('Change subscription'),
},
components: {
GlDropdown,
GlDropdownItem,
},
data() {
return {
subscription: undefined,
};
},
computed: {
dropdownText() {
return this.subscription?.text ?? this.$options.i18n.defaultDropdownText;
},
selectedValue() {
return this.subscription?.value;
},
},
methods: {
handleClick(option) {
this.subscription = option.value === this.subscription?.value ? undefined : option;
},
},
};
</script>
<template>
<div>
<input type="hidden" name="update[subscription_event]" :value="selectedValue" />
<gl-dropdown class="gl-w-full" :header-text="$options.i18n.headerText" :text="dropdownText">
<gl-dropdown-item
v-for="subscriptionsOption in $options.subscriptionsDropdownOptions"
:key="subscriptionsOption.value"
is-check-item
:is-checked="selectedValue === subscriptionsOption.value"
@click="handleClick(subscriptionsOption)"
>
{{ subscriptionsOption.text }}
</gl-dropdown-item>
</gl-dropdown>
</div>
</template>

View File

@ -1,17 +1,23 @@
import { __ } from '~/locale';
export const ISSUE_STATUS_MODIFIERS = {
REOPEN: 'reopen',
CLOSE: 'close',
};
export const ISSUE_STATUS_SELECT_OPTIONS = [
export const statusDropdownOptions = [
{
value: ISSUE_STATUS_MODIFIERS.REOPEN,
text: __('Open'),
value: 'reopen',
},
{
value: ISSUE_STATUS_MODIFIERS.CLOSE,
text: __('Closed'),
value: 'close',
},
];
export const subscriptionsDropdownOptions = [
{
text: __('Subscribe'),
value: 'subscribe',
},
{
text: __('Unsubscribe'),
value: 'unsubscribe',
},
];

View File

@ -1,5 +1,6 @@
import Vue from 'vue';
import StatusSelect from './components/status_select.vue';
import StatusDropdown from './components/status_dropdown.vue';
import SubscriptionsDropdown from './components/subscriptions_dropdown.vue';
import issuableBulkUpdateActions from './issuable_bulk_update_actions';
import IssuableBulkUpdateSidebar from './issuable_bulk_update_sidebar';
@ -14,8 +15,8 @@ export function initBulkUpdateSidebar(prefixId) {
new IssuableBulkUpdateSidebar(); // eslint-disable-line no-new
}
export function initIssueStatusSelect() {
const el = document.querySelector('.js-issue-status');
export function initStatusDropdown() {
const el = document.querySelector('.js-status-dropdown');
if (!el) {
return null;
@ -23,7 +24,21 @@ export function initIssueStatusSelect() {
return new Vue({
el,
name: 'StatusSelectRoot',
render: (createElement) => createElement(StatusSelect),
name: 'StatusDropdownRoot',
render: (createElement) => createElement(StatusDropdown),
});
}
export function initSubscriptionsDropdown() {
const el = document.querySelector('.js-subscriptions-dropdown');
if (!el) {
return null;
}
return new Vue({
el,
name: 'SubscriptionsDropdownRoot',
render: (createElement) => createElement(SubscriptionsDropdown),
});
}

View File

@ -5,7 +5,6 @@ import issuableEventHub from '~/issues/list/eventhub';
import LabelsSelect from '~/labels/labels_select';
import MilestoneSelect from '~/milestones/milestone_select';
import IssuableBulkUpdateActions from './issuable_bulk_update_actions';
import subscriptionSelect from './subscription_select';
const HIDDEN_CLASS = 'hidden';
const DISABLED_CONTENT_CLASS = 'disabled-content';
@ -52,7 +51,6 @@ export default class IssuableBulkUpdateSidebar {
initDropdowns() {
new LabelsSelect();
new MilestoneSelect();
subscriptionSelect();
// Checking IS_EE and using ee_else_ce is odd, but we do it here to satisfy
// the import/no-unresolved lint rule when FOSS_ONLY=1, even though at

View File

@ -1,28 +0,0 @@
import $ from 'jquery';
import initDeprecatedJQueryDropdown from '~/deprecated_jquery_dropdown';
import { __ } from '~/locale';
export default function subscriptionSelect() {
$('.js-subscription-event').each((i, element) => {
const fieldName = $(element).data('fieldName');
return initDeprecatedJQueryDropdown($(element), {
selectable: true,
fieldName,
toggleLabel(selected, el, instance) {
let label = __('Subscription');
const $item = instance.dropdown.find('.is-active');
if ($item.length) {
label = $item.text();
}
return label;
},
clicked(options) {
return options.e.preventDefault();
},
id(obj, el) {
return $(el).data('id');
},
});
});
}

View File

@ -563,7 +563,8 @@ export default {
if (!this.hasInitBulkEdit) {
const bulkUpdateSidebar = await import('~/issuable/bulk_update_sidebar');
bulkUpdateSidebar.initBulkUpdateSidebar('issuable_');
bulkUpdateSidebar.initIssueStatusSelect();
bulkUpdateSidebar.initStatusDropdown();
bulkUpdateSidebar.initSubscriptionsDropdown();
const usersSelect = await import('~/users_select');
const UsersSelect = usersSelect.default;

View File

@ -1,6 +1,10 @@
import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra_tokens_for_merge_requests';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { initBulkUpdateSidebar } from '~/issuable/bulk_update_sidebar';
import {
initBulkUpdateSidebar,
initStatusDropdown,
initSubscriptionsDropdown,
} from '~/issuable/bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import projectSelect from '~/project_select';
@ -9,6 +13,8 @@ const ISSUABLE_BULK_UPDATE_PREFIX = 'merge_request_';
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
initBulkUpdateSidebar(ISSUABLE_BULK_UPDATE_PREFIX);
initStatusDropdown();
initSubscriptionsDropdown();
initFilteredSearch({
page: FILTERED_SEARCH.MERGE_REQUESTS,

View File

@ -2,14 +2,19 @@ import addExtraTokensForMergeRequests from 'ee_else_ce/filtered_search/add_extra
import ShortcutsNavigation from '~/behaviors/shortcuts/shortcuts_navigation';
import IssuableFilteredSearchTokenKeys from '~/filtered_search/issuable_filtered_search_token_keys';
import { initCsvImportExportButtons, initIssuableByEmail } from '~/issuable';
import { initBulkUpdateSidebar, initIssueStatusSelect } from '~/issuable/bulk_update_sidebar';
import {
initBulkUpdateSidebar,
initStatusDropdown,
initSubscriptionsDropdown,
} from '~/issuable/bulk_update_sidebar';
import { FILTERED_SEARCH } from '~/filtered_search/constants';
import { ISSUABLE_INDEX } from '~/issuable/constants';
import initFilteredSearch from '~/pages/search/init_filtered_search';
import UsersSelect from '~/users_select';
initBulkUpdateSidebar(ISSUABLE_INDEX.MERGE_REQUEST);
initIssueStatusSelect();
initStatusDropdown();
initSubscriptionsDropdown();
addExtraTokensForMergeRequests(IssuableFilteredSearchTokenKeys);
IssuableFilteredSearchTokenKeys.removeTokensForKeys('iteration');

View File

@ -74,7 +74,7 @@ export default {
</script>
<template>
<div class="gl-display-flex">
<div class="gl-display-flex gl-align-items-flex-start">
<gl-dropdown
v-if="tertiaryButtons.length"
v-gl-tooltip

View File

@ -7,7 +7,7 @@ module Ci
FILE_SIZE_LIMIT = 5.megabytes.freeze
CHECKSUM_ALGORITHM = 'sha256'
PARSABLE_EXTENSIONS = ['cer'].freeze
PARSABLE_EXTENSIONS = %w[cer p12].freeze
self.limit_scope = :project
self.limit_name = 'project_ci_secure_files'
@ -49,6 +49,8 @@ module Ci
case file_extension
when 'cer'
Gitlab::Ci::SecureFiles::Cer.new(file.read)
when 'p12'
Gitlab::Ci::SecureFiles::P12.new(file.read)
end
end
@ -58,7 +60,7 @@ module Ci
begin
parser = metadata_parser
self.metadata = parser.metadata
self.expires_at = parser.expires_at if parser.respond_to?(:expires_at)
self.expires_at = parser.metadata[:expires_at]
save!
rescue StandardError => err
Gitlab::AppLogger.error("Secure File Parser Failure (#{id}): #{err.message} - #{parser.error}.")

View File

@ -14,7 +14,7 @@
.block
.title
= _('Status')
.js-issue-status
.js-status-dropdown
.block
.title
= _('Assignee')
@ -41,15 +41,7 @@
.block
.title
= _('Subscriptions')
.filter-item
= dropdown_tag(_("Select subscription"), options: { toggle_class: "js-subscription-event", title: _("Change subscription"), dropdown_class: "dropdown-menu-selectable", data: { field_name: "update[subscription_event]", default_label: _("Subscription") } } ) do
%ul
%li
%a{ href: "#", data: { id: "subscribe" } }
= _('Subscribe')
%li
%a{ href: "#", data: { id: "unsubscribe" } }
= _('Unsubscribe')
.js-subscriptions-dropdown
= hidden_field_tag "update[issuable_ids]", []
= hidden_field_tag :state_event, params[:state_event]

View File

@ -0,0 +1,8 @@
---
name: integration_slack_app_notifications
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/98663
rollout_issue_url:
milestone: '15.5'
type: development
group: group::integrations
default_enabled: false

View File

@ -0,0 +1,13 @@
- name: "vulnerabilityFindingDismiss GraphQL mutation"
announcement_milestone: "15.5"
announcement_date: "2022-10-22"
removal_milestone: "16.0"
removal_date: "2023-05-22"
breaking_change: true
reporter: matt_wilson
stage: govern
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/375645
body: |
The `VulnerabilityFindingDismiss` GraphQL mutation is being deprecated and will be removed in GitLab 16.0. This mutation was not used often as the Vulnerability Finding ID was not available to users (this field was [deprecated in 15.3](https://docs.gitlab.com/ee/update/deprecations.html#use-of-id-field-in-vulnerabilityfindingdismiss-mutation)). Users should instead use `VulnerabilityDismiss` to dismiss vulnerabilities in the Vulnerability Report or `SecurityFindingDismiss` for security findings in the CI Pipeline Security tab.
tiers: "Ultimate"
documentation_url: https://docs.gitlab.com/ee/api/graphql/reference/index.html#mutationvulnerabilityfindingdismiss

View File

@ -173,96 +173,6 @@ namespace = Namespace.find_by_full_path("<new_namespace>")
::Projects::TransferService.new(p, current_user).execute(namespace)
```
### Bulk update push rules for _all_ projects
For example, enable **Check whether the commit author is a GitLab user** and **Do not allow users to remove Git tags with `git push`** checkboxes, and create a filter for allowing commits from a specific email domain only:
``` ruby
Project.find_each do |p|
pr = p.push_rule || PushRule.new(project: p)
# Check whether the commit author is a GitLab user
pr.member_check = true
# Do not allow users to remove Git tags with `git push`
pr.deny_delete_tag = true
# Commit author's email
pr.author_email_regex = '@domain\.com$'
pr.save!
end
```
### Bulk update to disable the Slack Notification service
To disable notifications for all projects that have Slack service enabled, do:
```ruby
# Grab all projects that have the Slack notifications enabled
p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN services s ON p.id = s.project_id WHERE s.type = 'SlackService' AND s.active = true")
# Disable the service on each of the projects that were found.
p.each do |project|
project.slack_service.update_attribute(:active, false)
end
```
### Incorrect repository statistics shown in the GUI
After [reducing a repository size with third-party tools](../../user/project/repository/reducing_the_repo_size_using_git.md)
the displayed size may still show old sizes or commit numbers. To force an update, do:
```ruby
p = Project.find_by_full_path('<namespace>/<project>')
pp p.statistics
p.statistics.refresh!
pp p.statistics
# compare with earlier values
# check the total artifact storage space separately
builds_with_artifacts = p.builds.with_downloadable_artifacts.all
artifact_storage = 0
builds_with_artifacts.find_each do |build|
artifact_storage += build.artifacts_size
end
puts "#{artifact_storage} bytes"
```
### Identify deploy keys associated with blocked and non-member users
When the user who created a deploy key is blocked or removed from the project, the key
can no longer be used to push to protected branches in a private project (see [issue #329742](https://gitlab.com/gitlab-org/gitlab/-/issues/329742)).
The following script identifies unusable deploy keys:
```ruby
ghost_user_id = User.ghost.id
DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
project = deploy_key_mapping.project
deploy_key = deploy_key_mapping.deploy_key
user = deploy_key.user
access_checker = Gitlab::DeployKeyAccess.new(deploy_key, container: project)
# can_push_for_ref? tests if deploy_key can push to default branch, which is likely to be protected
can_push = access_checker.can_do_action?(:push_code)
can_push_to_default = access_checker.can_push_for_ref?(project.repository.root_ref)
next if access_checker.allowed? && can_push && can_push_to_default
if user.nil? || user.id == ghost_user_id
username = 'none'
state = '-'
else
username = user.username
user_state = user.state
end
puts "Deploy key: #{deploy_key.id}, Project: #{project.full_path}, Can push?: " + (can_push ? 'YES' : 'NO') +
", Can push to default branch #{project.repository.root_ref}?: " + (can_push_to_default ? 'YES' : 'NO') +
", User: #{username}, User state: #{user_state}"
end
```
### Find projects using an SQL query
Find and store an array of projects based on an SQL query:

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
type: reference, api

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -4,17 +4,15 @@ group: Incubation
info: Cloud Seed (formerly 5mp) is a GitLab Incubation Engineering program. No technical writer assigned to this group.
---
# Cloud Seed
# Cloud Seed **(FREE)**
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371332) in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `google_cloud`. Disabled by default.
> - [Enabled on self-managed and GitLab.com](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/100545) in GitLab 15.5.
Cloud Seed is an open-source program led
by [GitLab Incubation Engineering](https://about.gitlab.com/handbook/engineering/incubation/) in collaboration with
[Google Cloud](https://cloud.google.com/).
Cloud Seed is in `private-testing` mode and is available to a select group of users. If you are interested in joining
this group, please fill in
the [Cloud Seed Trusted Testers invitation form](https://docs.google.com/forms/d/e/1FAIpQLSeJPtFE8Vpqs_YTAKkFK42p5mO9zIYA2jr_PiP2h32cs8R39Q/viewform)
and we will reach out to you.
## Purpose
We believe that it should be **trivial** to deploy web applications (and other workloads) from GitLab to major cloud

View File

@ -358,7 +358,7 @@ using the Git CLI.
## Preferred method to blur elements
To blur an element, the preferred method is to click another element that does not alter the test state.
To blur an element, the preferred method is to select another element that does not alter the test state.
If there's a mask that blocks the page elements, such as may occur with some dropdowns,
use WebDriver's native mouse events to simulate a click event on the coordinates of an element. Use the following method: `click_element_coordinates`.

View File

@ -125,7 +125,7 @@ For example, when we [dequarantine](https://about.gitlab.com/handbook/engineerin
a flaky test we first want to make sure that it's no longer flaky.
We can do that using the `ce:custom-parallel` and `ee:custom-parallel` jobs.
Both are manual jobs that you can configure using custom variables.
When clicking the name (not the play icon) of one of the parallel jobs,
When selecting the name (not the play icon) of one of the parallel jobs,
you are prompted to enter variables. You can use any of
[the variables that can be used with `gitlab-qa`](https://gitlab.com/gitlab-org/gitlab-qa/blob/master/docs/what_tests_can_be_run.md#supported-gitlab-environment-variables)
as well as these:

View File

@ -10,7 +10,7 @@ In GitLab QA we are using a known pattern, called _Page Objects_.
This means that we have built an abstraction for all pages in GitLab that we use
to drive GitLab QA scenarios. Whenever we do something on a page, like filling
in a form or clicking a button, we do that only through a page object
in a form or selecting a button, we do that only through a page object
associated with this area of GitLab.
For example, when GitLab QA test harness signs in into GitLab, it needs to fill

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
@ -278,7 +278,7 @@ attributes.
- `summary`, `time_summary` - Top-level aggregations, most of the metrics are using different APIs/
finders and not invoking the aggregated backend.
When clicking on a specific stage, the `records` endpoint is invoked, which returns the related
When selecting a specific stage, the `records` endpoint is invoked, which returns the related
records (paginated) for the chosen stage in a specific order.
### Database decomposition

View File

@ -65,7 +65,7 @@ Instances running on Community Edition (CE) require a migration to Enterprise Ed
NOTE:
Because any given GitLab upgrade might involve data disk updates or database schema upgrades, swapping out the AMI is not sufficient for taking upgrades.
1. Log in to the AWS Web Console, so that clicking the links in the following step take you directly to the AMI list.
1. Log in to the AWS Web Console, so that selecting the links in the following step take you directly to the AMI list.
1. Pick the edition you want:
- [GitLab Enterprise Edition](https://console.aws.amazon.com/ec2/v2/home?region=us-east-1#Images:visibility=public-images;ownerAlias=782774275127;search=GitLab%20EE;sort=desc:name): If you want to unlock the enterprise features, a license is needed.

View File

@ -465,7 +465,7 @@ We need a preconfigured, custom GitLab AMI to use in our launch configuration la
From the EC2 dashboard:
1. Use the section below titled "[Find official GitLab-created AMI IDs on AWS](#find-official-gitlab-created-ami-ids-on-aws)" to find the correct AMI to launch.
1. After clicking **Launch** on the desired AMI, select an instance type based on your workload. Consult the [hardware requirements](../../install/requirements.md#hardware-requirements) to choose one that fits your needs (at least `c5.xlarge`, which is sufficient to accommodate 100 users).
1. After selecting **Launch** on the desired AMI, select an instance type based on your workload. Consult the [hardware requirements](../../install/requirements.md#hardware-requirements) to choose one that fits your needs (at least `c5.xlarge`, which is sufficient to accommodate 100 users).
1. Select **Configure Instance Details**:
1. In the **Network** dropdown list, select `gitlab-vpc`, the VPC we created earlier.
1. In the **Subnet** dropdown list, select `gitlab-private-10.0.1.0` from the list of subnets we created earlier.

View File

@ -126,7 +126,7 @@ application can perform. Available scopes are depicted in the following table.
| `profile` | Grants read-only access to the user's profile data using [OpenID Connect](openid_connect_provider.md). |
| `email` | Grants read-only access to the user's primary email address using [OpenID Connect](openid_connect_provider.md). |
At any time you can revoke any access by clicking **Revoke**.
At any time you can revoke any access by selecting **Revoke**.
## Hashed OAuth application secrets

View File

@ -88,7 +88,7 @@ Here, you can filter errors by title or by status (one of Ignored , Resolved, or
## Error Details
From error list, users can navigate to the error details page by clicking the title of any error.
From error list, users can navigate to the error details page by selecting the title of any error.
This page has:
@ -112,7 +112,7 @@ You can take action on Sentry Errors from within the GitLab UI. Marking errors i
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39665) in GitLab 12.7.
From within the [Error Details](#error-details) page you can ignore a Sentry error by clicking the **Ignore** button near the top of the page.
From within the [Error Details](#error-details) page you can ignore a Sentry error by selecting the **Ignore** button near the top of the page.
Ignoring an error prevents it from appearing in the [Error Tracking List](#error-tracking-list), and silences notifications that were set up within Sentry.
@ -121,7 +121,7 @@ Ignoring an error prevents it from appearing in the [Error Tracking List](#error
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/39825) in GitLab 12.7.
From within the [Error Details](#error-details) page you can resolve a Sentry error by
clicking the **Resolve** button near the top of the page.
selecting the **Resolve** button near the top of the page.
Marking an error as resolved indicates that the error has stopped firing events. If a GitLab issue is linked to the error, then the issue closes.

View File

@ -13,7 +13,7 @@ Alerts are a critical entity in your incident management workflow. They represen
Users with at least the Developer role can
access the Alert list at **Monitor > Alerts** in your project's
sidebar. The Alert list displays alerts sorted by start time, but
you can change the sort order by clicking the headers in the Alert list.
you can change the sort order by selecting the headers in the Alert list.
The alert list displays the following information:

View File

@ -194,7 +194,7 @@ When you upload an image, you can associate the image with text or a link to the
![Text link modal](img/incident_metrics_tab_text_link_modal_v14_9.png)
If you add a link, you can access the original graph by clicking the hyperlink above the uploaded image.
If you add a link, you can access the original graph by selecting the hyperlink above the uploaded image.
### Alert details

View File

@ -14,7 +14,7 @@ overview of recent incidents:
![Status Page landing page](img/status_page_incidents_v12_10.png)
Clicking an incident displays a detail page with more information about a particular incident:
Selecting an incident displays a detail page with more information about a particular incident:
![Status Page detail](img/status_page_detail_v12_10.png)
@ -140,7 +140,7 @@ you provided during setup. As part of publication, GitLab:
- Publishes any files attached to incident issue descriptions, up to 5000 per issue.
([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/205166) in GitLab 13.1.)
After publication, you can access the incident's details page by clicking the
After publication, you can access the incident's details page by selecting the
**Published on status page** button displayed under the Incident's title.
![Status Page detail link](img/status_page_detail_link_v13_1.png)

View File

@ -124,7 +124,7 @@ can manage [the settings](settings.md) for your metrics dashboard.
## Chart Context Menu
You can take action related to a chart's data by clicking the
You can take action related to a chart's data by selecting the
**{ellipsis_v}** **More actions** dropdown box above the upper right corner of
any chart on a dashboard:

View File

@ -147,7 +147,7 @@ suggested if this feature is used.
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208976) in GitLab 12.9.
You can edit existing additional custom metrics for your dashboard by clicking the
You can edit existing additional custom metrics for your dashboard by selecting the
**{ellipsis_v}** **More actions** dropdown and selecting **Edit metric**.
![Edit metric](img/prometheus_dashboard_edit_metric_link_v_12_9.png)

View File

@ -262,9 +262,9 @@ To view or change automatic subscription renewal (at the same tier as the
previous period), sign in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in), and:
- If a **Resume subscription** button is displayed, your subscription was canceled
previously. Click it to resume automatic renewal.
previously. Select it to resume automatic renewal.
- If a **Cancel subscription** button is displayed, your subscription is set to automatically
renew at the end of the subscription period. Click it to cancel automatic renewal.
renew at the end of the subscription period. Select it to cancel automatic renewal.
If you have difficulty during the renewal process, contact the
[Support team](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293) for assistance.

View File

@ -45,6 +45,25 @@ sole discretion of GitLab Inc.
<div class="announcement-milestone">
## Announced in 15.5
<div class="deprecation removal-160 breaking-change">
### vulnerabilityFindingDismiss GraphQL mutation
Planned removal: GitLab <span class="removal-milestone">16.0</span> (2023-05-22)
WARNING:
This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_guidelines/).
Review the details carefully before upgrading.
The `VulnerabilityFindingDismiss` GraphQL mutation is being deprecated and will be removed in GitLab 16.0. This mutation was not used often as the Vulnerability Finding ID was not available to users (this field was [deprecated in 15.3](https://docs.gitlab.com/ee/update/deprecations.html#use-of-id-field-in-vulnerabilityfindingdismiss-mutation)). Users should instead use `VulnerabilityDismiss` to dismiss vulnerabilities in the Vulnerability Report or `SecurityFindingDismiss` for security findings in the CI Pipeline Security tab.
</div>
</div>
<div class="announcement-milestone">
## Announced in 15.4
<div class="deprecation removal-160 breaking-change">

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -41,7 +41,7 @@ of the page to activate it in the GitLab instance.
You can add a small header message, a small footer message, or both, to the interface
of your GitLab instance. These messages appear on all projects and pages of the
instance, including the sign in / sign up page. The default color is white text on
an orange background, but this can be customized by clicking on **Customize colors**.
an orange background, but this can be customized by selecting **Customize colors**.
Limited [Markdown](../markdown.md) is supported, such as bold, italics, and links, for
example. Other Markdown features, including lists, images, and quotes are not supported

View File

@ -1,6 +1,6 @@
---
description: "Learn how long your open merge requests have spent in code review, and what distinguishes the longest-running." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
type: reference
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
description: "Merge request analytics help you understand the efficiency of your code review process, and the productivity of your team." # Up to ~200 chars long. They will be displayed in Google Search snippets. It may help to write the page intro first, and then reuse it here.
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -337,14 +337,14 @@ To use coverage fuzzing in an offline environment:
After a vulnerability is found, you can [address it](../vulnerabilities/index.md).
The merge request widget lists the vulnerability and contains a button for downloading the fuzzing
artifacts. By clicking one of the detected vulnerabilities, you can see its details.
artifacts. By selecting one of the detected vulnerabilities, you can see its details.
![Coverage Fuzzing Security Report](img/coverage_fuzzing_report_v13_6.png)
You can also view the vulnerability from the [Security Dashboard](../security_dashboard/index.md),
which shows an overview of all the security vulnerabilities in your groups, projects, and pipelines.
Clicking the vulnerability opens a modal that provides additional information about the
Selecting the vulnerability opens a modal that provides additional information about the
vulnerability:
<!-- vale gitlab.Acronyms = NO -->

View File

@ -19,7 +19,7 @@ ensuring DAST coverage.
The browser-based scanner works by loading the target application into a specially-instrumented
Chromium browser. A snapshot of the page is taken before a search to find any actions that a user
might perform, such as clicking on a link or filling in a form. For each action found, the
might perform, such as selecting on a link or filling in a form. For each action found, the
browser-based scanner executes it, takes a new snapshot, and determines what in the page changed
from the previous snapshot. Crawling continues by taking more snapshots and finding subsequent
actions. The benefit of scanning by following user actions in a browser is that the crawler can
@ -64,7 +64,7 @@ The browser-based crawler can be configured using CI/CD variables.
| `DAST_BROWSER_EXCLUDED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are considered excluded and connections are forcibly dropped. |
| `DAST_BROWSER_EXCLUDED_ELEMENTS` | selector | `a[href='2.html'],css:.no-follow` | Comma-separated list of selectors that are ignored when scanning. |
| `DAST_BROWSER_IGNORED_HOSTS` | List of strings | `site.com,another.com` | Hostnames included in this variable are accessed but not reported against. |
| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, clicking a link, or filling a form. |
| `DAST_BROWSER_MAX_ACTIONS` | number | `10000` | The maximum number of actions that the crawler performs. For example, selecting a link, or filling a form. |
| `DAST_BROWSER_MAX_DEPTH` | number | `10` | The maximum number of chained actions that the crawler takes. For example, `Click -> Form Fill -> Click` is a depth of three. |
| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For shared runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. |
| `DAST_BROWSER_COOKIES` | dictionary | `abtesting_group:3,region:locked` | A cookie name and value to be added to every request. |

View File

@ -637,11 +637,11 @@ including a large number of false positives.
| `DAST_AUTH_VERIFICATION_SELECTOR` <sup>2</sup> | selector | Verifies successful authentication by checking for presence of a selector once the login form has been submitted. Example: `css:.user-photo`. |
| `DAST_AUTH_VERIFICATION_URL` <sup>1,2</sup> | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST exits if it cannot access the URL. Example: `"http://example.com/loggedin_page"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. |
| `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false`. |
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that are clicked on prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
| `DAST_BROWSER_PATH_TO_LOGIN_FORM` <sup>1,2</sup> | selector | Comma-separated list of selectors that are selected prior to attempting to enter `DAST_USERNAME` and `DAST_PASSWORD` into the login form. Example: `"css:.navigation-menu,css:.login-menu-item"`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/326633) in GitLab 14.1. |
| `DAST_DEBUG` <sup>1</sup> | boolean | Enable debug message output. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_EXCLUDE_RULES` | string | Set to a comma-separated list of Vulnerability Rule IDs to exclude them from running during the scan. Rule IDs are numbers and can be found from the DAST log or on the [ZAP project](https://www.zaproxy.org/docs/alerts/). For example, `HTTP Parameter Override` has a rule ID of `10026`. Cannot be used when `DAST_ONLY_INCLUDE_RULES` is set. **Note:** In earlier versions of GitLab the excluded rules were executed but vulnerabilities they generated were suppressed. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118641) in GitLab 12.10. |
| `DAST_EXCLUDE_URLS` <sup>1,2</sup> | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. Example, `http://example.com/sign-out`. |
| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FIRST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when selected submits the username form of a multi-page login process. For example, `css:button[type='user-submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | **{warning}** **[Removed](https://gitlab.com/gitlab-org/gitlab/-/issues/293595)** in GitLab 14.0. Set to `true` to require domain validation when running DAST full scans. Not supported for API scans. Default: `false` |
| `DAST_FULL_SCAN_ENABLED` <sup>1</sup> | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` |
| `DAST_HTML_REPORT` | string | The filename of the HTML report written at the end of a scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
@ -660,7 +660,7 @@ including a large number of false positives.
| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. |
| `DAST_SPIDER_MINS` <sup>1</sup> | number | The maximum duration of the spider scan in minutes. Set to `0` for unlimited. Default: One minute, or unlimited when the scan is a full scan. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. |
| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when clicked submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_SUBMIT_FIELD` <sup>2</sup> | string | The `id` or `name` of the element that when selected submits the login form or the password form of a multi-page login process. For example, `css:button[type='submit']`. [Introduced](https://gitlab.com/gitlab-org/gitlab-ee/issues/9894) in GitLab 12.4. |
| `DAST_TARGET_AVAILABILITY_TIMEOUT` <sup>1</sup> | number | Time limit in seconds to wait for target availability. |
| `DAST_USE_AJAX_SPIDER` <sup>1</sup> | boolean | Set to `true` to use the AJAX spider in addition to the traditional spider, useful for crawling sites that require JavaScript. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12652) in GitLab 13.1. |
| `DAST_USERNAME` <sup>1,2</sup> | string | The username to authenticate to in the website. Example: `admin` |
@ -765,10 +765,10 @@ Automatic detection is "best-effort", and depending on the application being sca
Login process:
1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
1. If a form contains a username and password field, `DAST_USERNAME` and `DAST_PASSWORD` is inputted into the respective fields, the form submit button is clicked and the user is logged in.
1. If a form contains a username and password field, `DAST_USERNAME` and `DAST_PASSWORD` is inputted into the respective fields, the form submit button is selected and the user is logged in.
1. If a form contains only a username field, it is assumed that the login form is multi-step.
1. The `DAST_USERNAME` is inputted into the username field and the form submit button is clicked.
1. The subsequent pages loads where it is expected that a form exists and contains a password field. If found, `DAST_PASSWORD` is inputted, form submit button is clicked and the user is logged in.
1. The `DAST_USERNAME` is inputted into the username field and the form submit button is selected.
1. The subsequent pages loads where it is expected that a form exists and contains a password field. If found, `DAST_PASSWORD` is inputted, form submit button is selected and the user is logged in.
### Log in using explicit selection of the login form
@ -779,10 +779,10 @@ Most applications benefit from this approach to authentication.
Login process:
1. The `DAST_AUTH_URL` is loaded into the browser, and any forms on the page are located.
1. If the `DAST_FIRST_SUBMIT_FIELD` is not defined, then `DAST_USERNAME` is inputted into `DAST_USERNAME_FIELD`, `DAST_PASSWORD` is inputted into `DAST_PASSWORD_FIELD`, `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
1. If the `DAST_FIRST_SUBMIT_FIELD` is not defined, then `DAST_USERNAME` is inputted into `DAST_USERNAME_FIELD`, `DAST_PASSWORD` is inputted into `DAST_PASSWORD_FIELD`, `DAST_SUBMIT_FIELD` is selected and the user is logged in.
1. If the `DAST_FIRST_SUBMIT_FIELD` is defined, then it is assumed that the login form is multi-step.
1. The `DAST_USERNAME` is inputted into the `DAST_USERNAME_FIELD` field and the `DAST_FIRST_SUBMIT_FIELD` is clicked.
1. The subsequent pages loads where the `DAST_PASSWORD` is inputted into the `DAST_PASSWORD_FIELD` field, the `DAST_SUBMIT_FIELD` is clicked and the user is logged in.
1. The `DAST_USERNAME` is inputted into the `DAST_USERNAME_FIELD` field and the `DAST_FIRST_SUBMIT_FIELD` is selected.
1. The subsequent pages loads where the `DAST_PASSWORD` is inputted into the `DAST_PASSWORD_FIELD` field, the `DAST_SUBMIT_FIELD` is selected and the user is logged in.
### Verifying successful login
@ -1170,7 +1170,7 @@ A site profile contains:
- **Password**: The password used to authenticate to the website.
- **Username form field**: The name of username field at the sign-in HTML form.
- **Password form field**: The name of password field at the sign-in HTML form.
- **Submit form field**: The `id` or `name` of the element that when clicked submits the sign-in HTML form.
- **Submit form field**: The `id` or `name` of the element that when selected submits the sign-in HTML form.
When an API site type is selected, a [host override](#host-override) is used to ensure the API being scanned is on the same host as the target. This is done to reduce the risk of running an active scan against the wrong API.

View File

@ -48,7 +48,7 @@ can also be sorted by name or by the packager that installed them.
### Vulnerabilities
If a dependency has known vulnerabilities, view them by clicking the arrow next to the
If a dependency has known vulnerabilities, view them by selecting the arrow next to the
dependency's name or the badge that indicates how many known vulnerabilities exist. For each
vulnerability, its severity and description appears below it. To view more details of a vulnerability,
select the vulnerability's description. The [vulnerability's details](../vulnerabilities) page is opened.

View File

@ -191,7 +191,7 @@ If a vulnerability is dismissed in error, reverse the dismissal by changing its
By default, vulnerabilities are sorted by severity level, with the highest-severity vulnerabilities listed at the top.
To sort vulnerabilities by the date each vulnerability was detected, click the "Detected" column header.
To sort vulnerabilities by the date each vulnerability was detected, select the "Detected" column header.
## Export vulnerability details

View File

@ -315,7 +315,7 @@ At the top of the page, the number of unresolved threads is updated:
If you have multiple unresolved threads in a merge request, you can
create an issue to resolve them separately. In the merge request, at the top of the page,
click the ellipsis icon button (**{ellipsis_v}**) in the threads control and then select **Create issue to resolve all threads**:
select the ellipsis icon button (**{ellipsis_v}**) in the threads control and then select **Create issue to resolve all threads**:
![Open new issue for all unresolved threads](img/create_new_issue_v15_4.png)

View File

@ -1,6 +1,6 @@
---
type: reference
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -1,6 +1,6 @@
---
type: reference
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -85,7 +85,7 @@ To manually configure a GitLab Terraform Report artifact:
![merge request Terraform widget](img/terraform_plan_widget_v13_2.png)
1. Clicking the **View Full Log** button in the widget takes you directly to the
1. Selecting the **View Full Log** button in the widget takes you directly to the
plan output present in the pipeline logs:
![Terraform plan logs](img/terraform_plan_log_v13_0.png)

View File

@ -399,10 +399,10 @@ To delete images from within GitLab:
1. From the **Container Registry** page, you can select what you want to delete,
by either:
- Deleting the entire repository, and all the tags it contains, by clicking
- Deleting the entire repository, and all the tags it contains, by selecting
the red **{remove}** **Trash** icon.
- Navigating to the repository, and deleting tags individually or in bulk
by clicking the red **{remove}** **Trash** icon next to the tag you want
by selecting the red **{remove}** **Trash** icon next to the tag you want
to delete.
1. In the dialog box, select **Remove tag**.

View File

@ -31,7 +31,7 @@ To download and run a Harbor image hosted in the GitLab Harbor Registry:
1. Copy the link to your container image:
1. Go to your project or group's **Packages and registries > Harbor Registry** and find the image you want.
1. Click the **Copy** icon next to the image name.
1. Select the **Copy** icon next to the image name.
1. Use the command to run the container image you want.
@ -41,7 +41,7 @@ To view the list of tags associated with a specific artifact:
1. Go to your project or group.
1. Go to **Packages and registries > Harbor Registry**.
1. Click the image name to view its artifacts.
1. Select the image name to view its artifacts.
1. Select the artifact you want.
This brings up the list of tags. You can view the tag count and the time published.
@ -62,7 +62,7 @@ To view these commands, go to your project's **Packages and registries > Harbor
To remove the Harbor Registry for a project:
1. Go to your project/group's **Settings > Integrations** page.
1. Click **Harbor** under **Active integrations**.
1. Select **Harbor** under **Active integrations**.
1. Clear the **Active** checkbox under **Enable integration**.
1. Select **Save changes**.

View File

@ -66,7 +66,7 @@ cluster certificates:
- **Main menu > Admin > Kubernetes** page, for an instance-level cluster.
1. Select **Integrate with a cluster certificate**.
1. Under the **Create new cluster** tab, select **Google GKE**.
1. Connect your Google account if you haven't done already by clicking the
1. Connect your Google account if you haven't done already by selecting the
**Sign in with Google** button.
1. Choose your cluster's settings:
- **Kubernetes cluster name** - The name you wish to give the cluster.

View File

@ -156,3 +156,38 @@ There are a few scenarios where a deploy key will fail to push to a
All deploy keys are associated to an account. Since the permissions for an account can change, this might lead to scenarios where a deploy key that was working is suddenly unable to push to a protected branch.
We recommend you create a service account, and associate a deploy key to the service account, for projects using deploy keys.
#### Identify deploy keys associated with non-member and blocked users
If you need to find the keys that belong to a non-member or blocked user,
you can use [the Rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session) to identify unusable deploy keys using a script similar to the following:
```ruby
ghost_user_id = User.ghost.id
DeployKeysProject.with_write_access.find_each do |deploy_key_mapping|
project = deploy_key_mapping.project
deploy_key = deploy_key_mapping.deploy_key
user = deploy_key.user
access_checker = Gitlab::DeployKeyAccess.new(deploy_key, container: project)
# can_push_for_ref? tests if deploy_key can push to default branch, which is likely to be protected
can_push = access_checker.can_do_action?(:push_code)
can_push_to_default = access_checker.can_push_for_ref?(project.repository.root_ref)
next if access_checker.allowed? && can_push && can_push_to_default
if user.nil? || user.id == ghost_user_id
username = 'none'
state = '-'
else
username = user.username
user_state = user.state
end
puts "Deploy key: #{deploy_key.id}, Project: #{project.full_path}, Can push?: " + (can_push ? 'YES' : 'NO') +
", Can push to default branch #{project.repository.root_ref}?: " + (can_push_to_default ? 'YES' : 'NO') +
", User: #{username}, User state: #{user_state}"
end
```

View File

@ -1,5 +1,5 @@
---
stage: Manage
stage: Plan
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---

View File

@ -22,7 +22,7 @@ The simplest way to enable the GitLab Slack application for your workspace is to
install the [GitLab application](https://slack-platform.slack.com/apps/A676ADMV5-gitlab) from
the [Slack App Directory](https://slack.com/apps).
Clicking install takes you to the [GitLab Slack application landing page](https://gitlab.com/-/profile/slack/edit)
Selecting install takes you to the [GitLab Slack application landing page](https://gitlab.com/-/profile/slack/edit)
where you can select a project to enable the GitLab Slack application for.
## Configuration

View File

@ -127,3 +127,21 @@ the GitLab OpenSSL trust store is incorrect. Typical causes are:
- Overriding the trust store with `gitlab_rails['env'] = {"SSL_CERT_FILE" => "/path/to/file.pem"}`.
- Accidentally modifying the default CA bundle `/opt/gitlab/embedded/ssl/certs/cacert.pem`.
### Bulk update to disable the Slack Notification service
To disable notifications for all projects that have Slack integration enabled,
[start a rails console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session) and use a script similar to the following:
WARNING:
Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
```ruby
# Grab all projects that have the Slack notifications enabled
p = Project.find_by_sql("SELECT p.id FROM projects p LEFT JOIN integrations s ON p.id = s.project_id WHERE s.type_new = 'Slack' AND s.active = true")
# Disable the service on each of the projects that were found.
p.each do |project|
project.slack_service.update!(:active, false)
end
```

View File

@ -243,13 +243,13 @@ This allows you to create unique boards according to your team's need.
![Create scoped board](img/issue_board_creation_v13_6.png)
You can define the scope of your board when creating it or by clicking the **Edit board** button.
You can define the scope of your board when creating it or by selecting the **Edit board** button.
After a milestone, iteration, assignee, or weight is assigned to an issue board, you can no longer
filter through these in the search bar. In order to do that, you need to remove the desired scope
(for example, milestone, assignee, or weight) from the issue board.
If you don't have editing permission in a board, you're still able to see the configuration by
clicking **View scope**.
selecting **View scope**.
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
Watch a [video presentation](https://youtu.be/m5UTNCSqaDk) of
@ -474,7 +474,7 @@ Additionally, you can also see the time tracking value.
### Create a new list
Create a new list by clicking the **Create** button in the upper right corner of the issue board.
Create a new list by selecting the **Create** button in the upper right corner of the issue board.
![creating a new list in an issue board](img/issue_board_add_list_v14_1.png)
@ -698,8 +698,8 @@ A few things to remember:
and adds the label from the list it goes to.
- An issue can exist in multiple lists if it has more than one label.
- Lists are populated with issues automatically if the issues are labeled.
- Clicking the issue title inside a card takes you to that issue.
- Clicking a label inside a card quickly filters the entire issue board
- Selecting the issue title inside a card takes you to that issue.
- Selecting a label inside a card quickly filters the entire issue board
and show only the issues from all lists that have that label.
- For performance and visibility reasons, each list shows the first 20 issues
by default. If you have more than 20 issues, start scrolling down and the next

View File

@ -68,7 +68,7 @@ To create an issue from a group:
The newly created issue opens.
The project you selected most recently becomes the default for your next visit.
This can save you a lot of time and clicks, if you mostly create issues for the same project.
This can save you a lot of time, if you mostly create issues for the same project.
### From another issue or incident

View File

@ -112,7 +112,7 @@ Sometimes when you have hundreds of branches you may want a more flexible matchi
![Before swap revisions](img/swap_revisions_before_v13_12.png)
The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is clicked, the selected revisions for Source and Target is swapped.
The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is selected, the selected revisions for Source and Target is swapped.
![After swap revisions](img/swap_revisions_after_v13_12.png)

View File

@ -293,3 +293,28 @@ enabled, unsigned commits may still appear in the commit history if a commit was
created in GitLab itself. As expected, commits created outside GitLab and
pushed to the repository are rejected. For more information about this issue,
read [issue #19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
### Bulk update push rules for _all_ projects
To update the push rules to be the same for all projects,
you need to use [the rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session),
or write a script to update each project using the [Push Rules API endpoint](../../../api/projects.md#push-rules).
For example, to enable **Check whether the commit author is a GitLab user** and **Do not allow users to remove Git tags with `git push`** checkboxes,
and create a filter for allowing commits from a specific email domain only through rails console:
WARNING:
Any command that changes data directly could be damaging if not run correctly, or under the right conditions. We highly recommend running them in a test environment with a backup of the instance ready to be restored, just in case.
``` ruby
Project.find_each do |p|
pr = p.push_rule || PushRule.new(project: p)
# Check whether the commit author is a GitLab user
pr.member_check = true
# Do not allow users to remove Git tags with `git push`
pr.deny_delete_tag = true
# Commit author's email
pr.author_email_regex = '@domain\.com$'
pr.save!
end
```

View File

@ -257,4 +257,28 @@ increased, your only option is to:
### Incorrect repository statistics shown in the GUI
If the displayed size or commit number is different from the exported `.tar.gz` or local repository,
you can ask a GitLab administrator to [force an update](../../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#incorrect-repository-statistics-shown-in-the-gui).
you can ask a GitLab administrator to force an update.
Using [the rails console](../../../administration/operations/rails_console.md#starting-a-rails-console-session):
```ruby
p = Project.find_by_full_path('<namespace>/<project>')
pp p.statistics
p.statistics.refresh!
pp p.statistics
# compare with earlier values
# An alternate method to clear project statistics
p.repository.expire_all_method_caches
UpdateProjectStatisticsWorker.perform_async(p.id, ["commit_count","repository_size","storage_size","lfs_objects_size"])
# check the total artifact storage space separately
builds_with_artifacts = p.builds.with_downloadable_artifacts.all
artifact_storage = 0
builds_with_artifacts.find_each do |build|
artifact_storage += build.artifacts_size
end
puts "#{artifact_storage} bytes"
```

View File

@ -40,7 +40,7 @@ might need. GitLab displays a message to help you:
![First file for your project](img/web_editor_template_dropdown_first_file_v14_1.png)
When clicking on either `LICENSE` or `.gitignore` and so on, a dropdown displays
When selecting either `LICENSE` or `.gitignore` and so on, a dropdown displays
to provide you a template that may be suitable for your project:
![MIT license selected](img/web_editor_template_dropdown_mit_license_v14_1.png)

View File

@ -193,7 +193,7 @@ shows you a preview of the merge request diff if you commit your changes.
You can use the Web IDE to quickly fix failing tests by opening
the branch or merge request in the Web IDE and opening the logs of the failed
job. You can access the status of all jobs for the most recent pipeline and job
traces for the current commit by clicking the **Pipelines** button in the top
traces for the current commit by selecting the **Pipelines** button in the top
right.
The pipeline status is also shown at all times in the status bar in the bottom
@ -375,7 +375,7 @@ may be disabled:
- `.gitlab/.gitlab-webide.yml` does not exist or is set up incorrectly.
- No active private runners are available for the project.
If active, clicking the **Start Web Terminal** button loads the terminal view
If active, selecting the **Start Web Terminal** button loads the terminal view
and start connecting to the runner's terminal. At any time, the **Terminal** tab
can be closed and reopened and the state of the terminal is not affected.
@ -384,7 +384,7 @@ runner's shell prompt appears in the terminal. From here, you can enter
commands executed in the runner's environment. This is similar
to running commands in a local terminal or through SSH.
While the terminal is running, it can be stopped by clicking **Stop Terminal**.
While the terminal is running, it can be stopped by selecting **Stop Terminal**.
This disconnects the terminal and stops the runner's terminal job. From here,
select **Restart Terminal** to start a new terminal session.
@ -454,7 +454,7 @@ The Web IDE has a few limitations:
### Troubleshooting
- If the terminal's text is gray and unresponsive, then the terminal has stopped
and it can no longer be used. A stopped terminal can be restarted by clicking
and it can no longer be used. A stopped terminal can be restarted by selecting
**Restart Terminal**.
- If the terminal displays **Connection Failure**, then the terminal could not
connect to the runner. Please try to stop and restart the terminal. If the

View File

@ -141,7 +141,7 @@ in your browser. To run a search from history:
## Removing search filters
Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button or via <kbd></kbd> (Mac) + <kbd></kbd>.
Individual filters can be removed by selecting the filter's (x) button or backspacing. The entire search filter can be cleared by selecting the search box's (x) button or via <kbd></kbd> (Mac) + <kbd></kbd>.
To delete filter tokens one at a time, the <kbd></kbd> (Mac) / <kbd>Control</kbd> + <kbd></kbd> keyboard combination can be used.

View File

@ -4,6 +4,8 @@ module Gitlab
module Ci
module SecureFiles
class Cer
include Gitlab::Utils::StrongMemoize
attr_reader :error
def initialize(filedata)
@ -12,13 +14,12 @@ module Gitlab
end
def certificate_data
@certificate_data ||= begin
OpenSSL::X509::Certificate.new(@filedata)
rescue StandardError => err
@error = err.to_s
nil
end
OpenSSL::X509::Certificate.new(@filedata)
rescue OpenSSL::X509::CertificateError => err
@error = err.to_s
nil
end
strong_memoize_attr :certificate_data
def metadata
return {} unless certificate_data
@ -30,15 +31,14 @@ module Gitlab
expires_at: expires_at
}
end
def expires_at
return unless certificate_data
certificate_data.not_before
end
strong_memoize_attr :metadata
private
def expires_at
certificate_data.not_before
end
def id
certificate_data.serial.to_s
end

View File

@ -0,0 +1,56 @@
# frozen_string_literal: true
module Gitlab
module Ci
module SecureFiles
class P12
include Gitlab::Utils::StrongMemoize
attr_reader :error
def initialize(filedata, password = nil)
@filedata = filedata
@password = password
end
def certificate_data
OpenSSL::PKCS12.new(@filedata, @password).certificate
rescue OpenSSL::PKCS12::PKCS12Error => err
@error = err.to_s
nil
end
strong_memoize_attr :certificate_data
def metadata
return {} unless certificate_data
{
issuer: issuer,
subject: subject,
id: serial,
expires_at: expires_at
}
end
strong_memoize_attr :metadata
private
def expires_at
certificate_data.not_before
end
def serial
certificate_data.serial.to_s
end
def issuer
X509Name.parse(certificate_data.issuer)
end
def subject
X509Name.parse(certificate_data.subject)
end
end
end
end
end

View File

@ -44,7 +44,7 @@ module Gitlab
mutually_exclusive_keys = value.try(:keys).to_a & options[:in]
if mutually_exclusive_keys.length > 1
record.errors.add(attribute, "please use only one the following keys: " +
record.errors.add(attribute, "please use only one of the following keys: " +
mutually_exclusive_keys.join(', '))
end
end

View File

@ -57,6 +57,7 @@ module Gitlab
push_frontend_feature_flag(:new_header_search)
push_frontend_feature_flag(:source_editor_toolbar)
push_frontend_feature_flag(:gl_listbox_for_sort_dropdowns)
push_frontend_feature_flag(:integration_slack_app_notifications)
end
# Exposes the state of a feature flag to the frontend code.

View File

@ -44717,6 +44717,9 @@ msgstr ""
msgid "Vulnerability|Status"
msgstr ""
msgid "Vulnerability|Status:"
msgstr ""
msgid "Vulnerability|The scanner determined this vulnerability to be a false positive. Verify the evaluation before changing its status. %{linkStart}Learn more about false positive detection.%{linkEnd}"
msgstr ""

View File

@ -107,7 +107,7 @@ GEM
gitlab (4.18.0)
httparty (~> 0.18)
terminal-table (>= 1.5.1)
gitlab-qa (8.5.0)
gitlab-qa (8.7.0)
activesupport (~> 6.1)
gitlab (~> 4.18.0)
http (~> 5.0)

View File

@ -499,7 +499,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'when a squash commit message is passed' do
let(:message) { 'My custom squash commit message' }
it 'passes the same message to SquashService', :sidekiq_might_not_need_inline do
it 'passes the same message to SquashService', :sidekiq_inline do
params = { squash: '1',
squash_commit_message: message,
sha: merge_request.diff_head_sha }
@ -791,7 +791,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'with private builds' do
context 'for the target project member' do
it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do
it 'does not respond with serialized pipelines' do
expect(json_response['pipelines']).to be_empty
expect(json_response['count']['all']).to eq(0)
expect(response).to include_pagination_headers
@ -801,7 +801,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'for the source project member' do
let(:user) { fork_user }
it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do
it 'responds with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@ -817,7 +817,7 @@ RSpec.describe Projects::MergeRequestsController do
end
context 'for the target project member' do
it 'does not respond with serialized pipelines', :sidekiq_might_not_need_inline do
it 'does not respond with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@ -827,7 +827,7 @@ RSpec.describe Projects::MergeRequestsController do
context 'for the source project member' do
let(:user) { fork_user }
it 'responds with serialized pipelines', :sidekiq_might_not_need_inline do
it 'responds with serialized pipelines' do
expect(json_response['pipelines']).to be_present
expect(json_response['count']['all']).to eq(1)
expect(response).to include_pagination_headers
@ -1856,13 +1856,13 @@ RSpec.describe Projects::MergeRequestsController do
create(:merge_request, source_project: forked, target_project: project, target_branch: 'master', head_pipeline: pipeline)
end
it 'links to the environment on that project', :sidekiq_might_not_need_inline do
it 'links to the environment on that project' do
get_ci_environments_status
expect(json_response.first['url']).to match(/#{forked.full_path}/)
end
context "when environment_target is 'merge_commit'", :sidekiq_might_not_need_inline do
context "when environment_target is 'merge_commit'" do
it 'returns nothing' do
get_ci_environments_status(environment_target: 'merge_commit')
@ -1892,13 +1892,13 @@ RSpec.describe Projects::MergeRequestsController do
# we're trying to reduce the overall number of queries for this method.
# set a hard limit for now. https://gitlab.com/gitlab-org/gitlab-foss/issues/52287
it 'keeps queries in check', :sidekiq_might_not_need_inline do
it 'keeps queries in check' do
control_count = ActiveRecord::QueryRecorder.new { get_ci_environments_status }.count
expect(control_count).to be <= 137
end
it 'has no N+1 SQL issues for environments', :request_store, :sidekiq_might_not_need_inline, retry: 0 do
it 'has no N+1 SQL issues for environments', :request_store, retry: 0 do
# First run to insert test data from lets, which does take up some 30 queries
get_ci_environments_status
@ -2145,7 +2145,7 @@ RSpec.describe Projects::MergeRequestsController do
sign_in(fork_owner)
end
it 'returns 200', :sidekiq_might_not_need_inline do
it 'returns 200' do
expect_rebase_worker_for(fork_owner)
post_rebase

BIN
spec/fixtures/ci_secure_files/sample.p12 vendored Normal file

Binary file not shown.

View File

@ -18,6 +18,7 @@ import {
integrationLevels,
I18N_SUCCESSFUL_CONNECTION_MESSAGE,
I18N_DEFAULT_ERROR_MESSAGE,
INTEGRATION_FORM_TYPE_SLACK,
billingPlans,
billingPlanNames,
} from '~/integrations/constants';
@ -88,6 +89,7 @@ describe('IntegrationForm', () => {
const findConnectionSection = () => findAllSections().at(0);
const findConnectionSectionComponent = () =>
findConnectionSection().findComponent(IntegrationSectionConnection);
const findHelpHtml = () => wrapper.findByTestId('help-html');
beforeEach(() => {
mockAxios = new MockAdapter(axios);
@ -712,5 +714,48 @@ describe('IntegrationForm', () => {
expect(refreshCurrentPage).toHaveBeenCalledTimes(1);
});
});
describe('Help and sections rendering', () => {
const dummyHelp = 'Foo Help';
it.each`
integration | flagIsOn | helpHtml | sections | shouldShowSections | shouldShowHelp
${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${''} | ${[]} | ${false} | ${false}
${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${false} | ${false}
${INTEGRATION_FORM_TYPE_SLACK} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${false} | ${true}
${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${''} | ${[]} | ${false} | ${false}
${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
${INTEGRATION_FORM_TYPE_SLACK} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${true}
${'foo'} | ${false} | ${''} | ${[]} | ${false} | ${false}
${'foo'} | ${false} | ${dummyHelp} | ${[]} | ${false} | ${true}
${'foo'} | ${false} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
${'foo'} | ${false} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
${'foo'} | ${true} | ${''} | ${[]} | ${false} | ${false}
${'foo'} | ${true} | ${dummyHelp} | ${[]} | ${false} | ${true}
${'foo'} | ${true} | ${undefined} | ${[mockSectionConnection]} | ${true} | ${false}
${'foo'} | ${true} | ${dummyHelp} | ${[mockSectionConnection]} | ${true} | ${false}
`(
'$sections sections, and "$helpHtml" helpHtml when the FF is "$flagIsOn" for "$integration" integration',
({ integration, flagIsOn, helpHtml, sections, shouldShowSections, shouldShowHelp }) => {
createComponent({
provide: {
helpHtml,
glFeatures: { integrationSlackAppNotifications: flagIsOn },
},
customStateProps: {
sections,
type: integration,
},
});
expect(findAllSections().length > 0).toEqual(shouldShowSections);
expect(findHelpHtml().exists()).toBe(shouldShowHelp);
if (shouldShowHelp) {
expect(findHelpHtml().html()).toContain(helpHtml);
}
},
);
});
});
});

View File

@ -1,9 +1,9 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import StatusSelect from '~/issuable/bulk_update_sidebar/components/status_select.vue';
import { ISSUE_STATUS_SELECT_OPTIONS } from '~/issuable/bulk_update_sidebar/constants';
import StatusDropdown from '~/issuable/bulk_update_sidebar/components/status_dropdown.vue';
import { statusDropdownOptions } from '~/issuable/bulk_update_sidebar/constants';
describe('StatusSelect', () => {
describe('SubscriptionsDropdown component', () => {
let wrapper;
const findDropdown = () => wrapper.findComponent(GlDropdown);
@ -11,7 +11,7 @@ describe('StatusSelect', () => {
const findHiddenInput = () => wrapper.find('input');
function createComponent() {
wrapper = shallowMount(StatusSelect);
wrapper = shallowMount(StatusDropdown);
}
afterEach(() => {
@ -45,14 +45,12 @@ describe('StatusSelect', () => {
it('updates value of the hidden input', () => {
expect(findHiddenInput().attributes('value')).toBe(
ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].value,
statusDropdownOptions[selectItemAtIndex].value,
);
});
it('updates the dropdown text prop', () => {
expect(findDropdown().props('text')).toBe(
ISSUE_STATUS_SELECT_OPTIONS[selectItemAtIndex].text,
);
expect(findDropdown().props('text')).toBe(statusDropdownOptions[selectItemAtIndex].text);
});
it('sets dropdown item `is-checked` prop to `true`', () => {

View File

@ -0,0 +1,76 @@
import { GlDropdown, GlDropdownItem } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import SubscriptionsDropdown from '~/issuable/bulk_update_sidebar/components/subscriptions_dropdown.vue';
import { subscriptionsDropdownOptions } from '~/issuable/bulk_update_sidebar/constants';
describe('SubscriptionsDropdown component', () => {
let wrapper;
const findDropdown = () => wrapper.findComponent(GlDropdown);
const findAllDropdownItems = () => wrapper.findAllComponents(GlDropdownItem);
const findHiddenInput = () => wrapper.find('input');
function createComponent() {
wrapper = shallowMount(SubscriptionsDropdown);
}
afterEach(() => {
wrapper.destroy();
});
describe('with no value selected', () => {
beforeEach(() => {
createComponent();
});
it('hidden input value is undefined', () => {
expect(findHiddenInput().attributes('value')).toBeUndefined();
});
it('renders default text', () => {
expect(findDropdown().props('text')).toBe(SubscriptionsDropdown.i18n.defaultDropdownText);
});
it('renders dropdown items with `is-checked` prop set to `false`', () => {
const dropdownItems = findAllDropdownItems();
expect(dropdownItems.at(0).props('isChecked')).toBe(false);
expect(dropdownItems.at(1).props('isChecked')).toBe(false);
});
});
describe('when selecting a value', () => {
beforeEach(() => {
createComponent();
findAllDropdownItems().at(0).vm.$emit('click');
});
it('updates value of the hidden input', () => {
expect(findHiddenInput().attributes('value')).toBe(subscriptionsDropdownOptions[0].value);
});
it('updates the dropdown text prop', () => {
expect(findDropdown().props('text')).toBe(subscriptionsDropdownOptions[0].text);
});
it('sets dropdown item `is-checked` prop to `true`', () => {
const dropdownItems = findAllDropdownItems();
expect(dropdownItems.at(0).props('isChecked')).toBe(true);
expect(dropdownItems.at(1).props('isChecked')).toBe(false);
});
describe('when selecting the value that is already selected', () => {
it('clears dropdown selection', async () => {
findAllDropdownItems().at(0).vm.$emit('click');
await nextTick();
const dropdownItems = findAllDropdownItems();
expect(dropdownItems.at(0).props('isChecked')).toBe(false);
expect(dropdownItems.at(1).props('isChecked')).toBe(false);
expect(findDropdown().props('text')).toBe(SubscriptionsDropdown.i18n.defaultDropdownText);
});
});
});
});

View File

@ -73,7 +73,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
>
<div
class="gl-display-flex"
class="gl-display-flex gl-align-items-flex-start"
>
<div
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"
@ -250,7 +250,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
>
<div
class="gl-display-flex"
class="gl-display-flex gl-align-items-flex-start"
>
<div
class="dropdown b-dropdown gl-new-dropdown gl-display-block gl-md-display-none! btn-group"

View File

@ -5,7 +5,6 @@ require 'spec_helper'
RSpec.describe Gitlab::Ci::SecureFiles::Cer do
context 'when the supplied certificate cannot be parsed' do
let(:invalid_certificate) { described_class.new('xyzabc') }
let(:subject) { described_class.new('xyzabc') }
describe '#certificate_data' do
it 'assigns the error message and returns nil' do
@ -22,7 +21,7 @@ RSpec.describe Gitlab::Ci::SecureFiles::Cer do
describe '#expires_at' do
it 'returns nil' do
expect(invalid_certificate.expires_at).to be_nil
expect(invalid_certificate.metadata[:expires_at]).to be_nil
end
end
end
@ -51,7 +50,7 @@ RSpec.describe Gitlab::Ci::SecureFiles::Cer do
describe '#expires_at' do
it 'returns the certificate expiration timestamp' do
expect(subject.expires_at).to eq('2022-04-26 19:20:40 UTC')
expect(subject.metadata[:expires_at]).to eq('2022-04-26 19:20:40 UTC')
end
end

View File

@ -0,0 +1,81 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Ci::SecureFiles::P12 do
context 'when the supplied certificate cannot be parsed' do
let(:invalid_certificate) { described_class.new('xyzabc') }
describe '#certificate_data' do
it 'assigns the error message and returns nil' do
expect(invalid_certificate.certificate_data).to be nil
expect(invalid_certificate.error).to eq('PKCS12_parse: mac verify failure')
end
end
describe '#metadata' do
it 'returns an empty hash' do
expect(invalid_certificate.metadata).to eq({})
end
end
describe '#expires_at' do
it 'returns nil' do
expect(invalid_certificate.metadata[:expires_at]).to be_nil
end
end
end
context 'when the supplied certificate can be parsed, but the password is invalid' do
let(:sample_file) { fixture_file('ci_secure_files/sample.p12') }
let(:subject) { described_class.new(sample_file, 'foo') }
describe '#certificate_data' do
it 'assigns the error message and returns nil' do
expect(subject.certificate_data).to be nil
expect(subject.error).to eq('PKCS12_parse: mac verify failure')
end
end
end
context 'when the supplied certificate can be parsed' do
let(:sample_file) { fixture_file('ci_secure_files/sample.p12') }
let(:subject) { described_class.new(sample_file) }
describe '#certificate_data' do
it 'returns an OpenSSL::X509::Certificate object' do
expect(subject.certificate_data.class).to be(OpenSSL::X509::Certificate)
end
end
describe '#metadata' do
it 'returns a hash with the expected keys' do
expect(subject.metadata.keys).to match_array([:issuer, :subject, :id, :expires_at])
end
end
describe '#id' do
it 'returns the certificate serial number' do
expect(subject.metadata[:id]).to eq('75949910542696343243264405377658443914')
end
end
describe '#expires_at' do
it 'returns the certificate expiration timestamp' do
expect(subject.metadata[:expires_at]).to eq('2022-09-21 14:56:00 UTC')
end
end
describe '#issuer' do
it 'calls parse on X509Name' do
expect(subject.metadata[:issuer]["O"]).to eq('Apple Inc.')
end
end
describe '#subject' do
it 'calls parse on X509Name' do
expect(subject.metadata[:subject]["OU"]).to eq('N7SYAN8PX8')
end
end
end
end

View File

@ -35,7 +35,7 @@ RSpec.describe Gitlab::Config::Entry::Validators do
expect(instance.valid?).to be(valid_result)
unless valid_result
expect(instance.errors.messages_for(:config)).to include /please use only one the following keys: foo, bar/
expect(instance.errors.messages_for(:config)).to include /please use only one of the following keys: foo, bar/
end
end
end

View File

@ -112,6 +112,11 @@ RSpec.describe Ci::SecureFile do
expect(file.metadata_parser).to be_an_instance_of(Gitlab::Ci::SecureFiles::Cer)
end
it 'returns an instance of Gitlab::Ci::SecureFiles::P12 when a .p12 file is supplied' do
file = build(:ci_secure_file, name: 'file1.p12')
expect(file.metadata_parser).to be_an_instance_of(Gitlab::Ci::SecureFiles::P12)
end
it 'returns nil when the file type is not supported by any parsers' do
file = build(:ci_secure_file, name: 'file1.foo')
expect(file.metadata_parser).to be nil

View File

@ -21,8 +21,6 @@ RSpec.describe Trigger do
'GITLAB_USER_NAME' => 'gitlab_user_name',
'GITLAB_USER_LOGIN' => 'gitlab_user_login',
'QA_IMAGE' => 'qa_image',
'OMNIBUS_GITLAB_CACHE_UPDATE' => 'omnibus_gitlab_cache_update',
'OMNIBUS_GITLAB_PROJECT_ACCESS_TOKEN' => nil,
'DOCS_PROJECT_API_TOKEN' => nil
}
end

View File

@ -248,74 +248,42 @@ RSpec.describe 'gitlab:app namespace rake task', :delete do
let!(:project) { create(:project, :repository) }
describe 'backup creation and deletion using custom_hooks' do
let(:user_backup_path) { "repositories/#{project.disk_path}" }
context 'with specific backup tasks' do
before do
stub_env('SKIP', 'db')
path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
File.join(project.repository.path_to_repo, 'custom_hooks')
end
FileUtils.mkdir_p(path)
FileUtils.touch(File.join(path, "dummy.txt"))
end
context 'when project uses custom_hooks and successfully creates backup' do
it 'creates custom_hooks.tar and project bundle' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
tar_contents, exit_status = Gitlab::Popen.popen(%W[tar -tvf #{backup_tar}])
expect(exit_status).to eq(0)
expect(tar_contents).to match(user_backup_path)
expect(tar_contents).to match("#{user_backup_path}/.+/001.custom_hooks.tar")
expect(tar_contents).to match("#{user_backup_path}/.+/001.bundle")
end
it 'restores files correctly' do
expect { run_rake_task('gitlab:backup:create') }.to output.to_stdout_from_any_process
expect { run_rake_task('gitlab:backup:restore') }.to output.to_stdout_from_any_process
repo_path = Gitlab::GitalyClient::StorageSettings.allow_disk_access do
project.repository.path
end
expect(Dir.entries(File.join(repo_path, 'custom_hooks'))).to include("dummy.txt")
it 'prints a progress message to stdout' do
backup_tasks.each do |task|
expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end
end
context 'with specific backup tasks' do
it 'prints a progress message to stdout' do
backup_tasks.each do |task|
expect { run_rake_task("gitlab:backup:#{task}:create") }.to output(/Dumping /).to_stdout_from_any_process
end
end
it 'logs the progress to log file' do
ci_database_status = Gitlab::Database.has_config?(:ci) ? "[SKIPPED]" : "[DISABLED]"
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping main_database ... [SKIPPED]")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping ci_database ... #{ci_database_status}")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... done")
it 'logs the progress to log file' do
ci_database_status = Gitlab::Database.has_config?(:ci) ? "[SKIPPED]" : "[DISABLED]"
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping main_database ... [SKIPPED]")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping ci_database ... #{ci_database_status}")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping repositories ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping uploads ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping builds ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping artifacts ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping pages ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping lfs objects ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping terraform states ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping container registry images ... done")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... ")
expect(Gitlab::BackupLogger).to receive(:info).with(message: "Dumping packages ... done")
backup_tasks.each do |task|
run_rake_task("gitlab:backup:#{task}:create")
end
backup_tasks.each do |task|
run_rake_task("gitlab:backup:#{task}:create")
end
end
end

View File

@ -69,7 +69,7 @@ RSpec.describe 'gitlab:usage data take tasks', :silence_stdout do
expect { run_rake_task('gitlab:usage_data:generate_and_send') }.to output(/.*201.*/).to_stdout
end
describe 'generate_ci_template_events' do
describe 'generate_ci_template_events', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/377698' do
it "generates #{Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH}" do
FileUtils.rm(Gitlab::UsageDataCounters::CiTemplateUniqueCounter::KNOWN_EVENTS_FILE_PATH)
run_rake_task('gitlab:usage_data:generate_ci_template_events')