Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
901ecdbf5c
commit
41b2e83ad6
|
@ -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';
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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>
|
|
@ -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',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -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),
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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');
|
||||
},
|
||||
});
|
||||
});
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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}.")
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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 -->
|
||||
|
|
|
@ -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. |
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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**.
|
||||
|
|
|
@ -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**.
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
---
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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"
|
||||
```
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
|
@ -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);
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -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`', () => {
|
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -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"
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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')
|
||||
|
|
Loading…
Reference in New Issue