Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8015f09545
commit
e09f6bdfd1
|
@ -38,9 +38,9 @@ export const toggleContainerClasses = (containerEl, classList) => {
|
||||||
/**
|
/**
|
||||||
* Return a object mapping element dataset names to booleans.
|
* Return a object mapping element dataset names to booleans.
|
||||||
*
|
*
|
||||||
* This is useful for data- attributes whose presence represent
|
* This is useful for data- attributes whose presense represent
|
||||||
* a truthiness, no matter the value of the attribute. The absence of the
|
* a truthiness, no matter the value of the attribute. The absense of the
|
||||||
* attribute represents falsiness.
|
* attribute represents falsiness.
|
||||||
*
|
*
|
||||||
* This can be useful when Rails-provided boolean-like values are passed
|
* This can be useful when Rails-provided boolean-like values are passed
|
||||||
* directly to the HAML template, rather than cast to a string.
|
* directly to the HAML template, rather than cast to a string.
|
||||||
|
|
|
@ -4,9 +4,10 @@ import { __, s__ } from '~/locale';
|
||||||
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
|
import LocalStorageSync from '~/vue_shared/components/local_storage_sync.vue';
|
||||||
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
|
import UserCalloutDismisser from '~/vue_shared/components/user_callout_dismisser.vue';
|
||||||
import SectionLayout from '~/vue_shared/security_configuration/components/section_layout.vue';
|
import SectionLayout from '~/vue_shared/security_configuration/components/section_layout.vue';
|
||||||
|
import currentLicenseQuery from '~/security_configuration/graphql/current_license.query.graphql';
|
||||||
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
|
import AutoDevOpsAlert from './auto_dev_ops_alert.vue';
|
||||||
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
|
import AutoDevOpsEnabledAlert from './auto_dev_ops_enabled_alert.vue';
|
||||||
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY } from './constants';
|
import { AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY, LICENSE_ULTIMATE } from './constants';
|
||||||
import FeatureCard from './feature_card.vue';
|
import FeatureCard from './feature_card.vue';
|
||||||
import TrainingProviderList from './training_provider_list.vue';
|
import TrainingProviderList from './training_provider_list.vue';
|
||||||
import UpgradeBanner from './upgrade_banner.vue';
|
import UpgradeBanner from './upgrade_banner.vue';
|
||||||
|
@ -50,6 +51,17 @@ export default {
|
||||||
TrainingProviderList,
|
TrainingProviderList,
|
||||||
},
|
},
|
||||||
inject: ['projectFullPath', 'vulnerabilityTrainingDocsPath'],
|
inject: ['projectFullPath', 'vulnerabilityTrainingDocsPath'],
|
||||||
|
apollo: {
|
||||||
|
currentLicensePlan: {
|
||||||
|
query: currentLicenseQuery,
|
||||||
|
update({ currentLicense }) {
|
||||||
|
return currentLicense?.plan;
|
||||||
|
},
|
||||||
|
error() {
|
||||||
|
this.hasCurrentLicenseFetchError = true;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
props: {
|
props: {
|
||||||
augmentedSecurityFeatures: {
|
augmentedSecurityFeatures: {
|
||||||
type: Array,
|
type: Array,
|
||||||
|
@ -84,15 +96,13 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
securityTrainingEnabled: {
|
|
||||||
type: Boolean,
|
|
||||||
required: true,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
autoDevopsEnabledAlertDismissedProjects: [],
|
autoDevopsEnabledAlertDismissedProjects: [],
|
||||||
errorMessage: '',
|
errorMessage: '',
|
||||||
|
currentLicensePlan: '',
|
||||||
|
hasCurrentLicenseFetchError: false,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
@ -113,6 +123,12 @@ export default {
|
||||||
!this.autoDevopsEnabledAlertDismissedProjects.includes(this.projectFullPath)
|
!this.autoDevopsEnabledAlertDismissedProjects.includes(this.projectFullPath)
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
shouldShowVulnerabilityManagementTab() {
|
||||||
|
// if the query fails (if the plan is `null` also means an error has occurred) we still want to show the feature
|
||||||
|
const hasQueryError = this.hasCurrentLicenseFetchError || this.currentLicensePlan === null;
|
||||||
|
|
||||||
|
return hasQueryError || this.currentLicensePlan === LICENSE_ULTIMATE;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
dismissAutoDevopsEnabledAlert() {
|
dismissAutoDevopsEnabledAlert() {
|
||||||
|
@ -237,9 +253,9 @@ export default {
|
||||||
{{ $options.i18n.description }}
|
{{ $options.i18n.description }}
|
||||||
</p>
|
</p>
|
||||||
<p v-if="canViewCiHistory">
|
<p v-if="canViewCiHistory">
|
||||||
<gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">
|
<gl-link data-testid="compliance-view-history-link" :href="gitlabCiHistoryPath">{{
|
||||||
{{ $options.i18n.configurationHistory }}
|
$options.i18n.configurationHistory
|
||||||
</gl-link>
|
}}</gl-link>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template #features>
|
<template #features>
|
||||||
|
@ -254,18 +270,20 @@ export default {
|
||||||
</section-layout>
|
</section-layout>
|
||||||
</gl-tab>
|
</gl-tab>
|
||||||
<gl-tab
|
<gl-tab
|
||||||
v-if="securityTrainingEnabled"
|
v-if="shouldShowVulnerabilityManagementTab"
|
||||||
data-testid="vulnerability-management-tab"
|
data-testid="vulnerability-management-tab"
|
||||||
:title="$options.i18n.vulnerabilityManagement"
|
:title="$options.i18n.vulnerabilityManagement"
|
||||||
query-param-value="vulnerability-management"
|
query-param-value="vulnerability-management"
|
||||||
>
|
>
|
||||||
<section-layout :heading="$options.i18n.securityTraining">
|
<section-layout :heading="$options.i18n.securityTraining">
|
||||||
<template #description>
|
<template #description>
|
||||||
<p>{{ $options.i18n.securityTrainingDescription }}</p>
|
|
||||||
<p>
|
<p>
|
||||||
<gl-link :href="vulnerabilityTrainingDocsPath">
|
{{ $options.i18n.securityTrainingDescription }}
|
||||||
{{ $options.i18n.securityTrainingDoc }}
|
</p>
|
||||||
</gl-link>
|
<p>
|
||||||
|
<gl-link :href="vulnerabilityTrainingDocsPath">{{
|
||||||
|
$options.i18n.securityTrainingDoc
|
||||||
|
}}</gl-link>
|
||||||
</p>
|
</p>
|
||||||
</template>
|
</template>
|
||||||
<template #features>
|
<template #features>
|
||||||
|
|
|
@ -310,3 +310,7 @@ export const TEMP_PROVIDER_URLS = {
|
||||||
Kontra: 'https://application.security/',
|
Kontra: 'https://application.security/',
|
||||||
[__('Secure Code Warrior')]: 'https://www.securecodewarrior.com/',
|
[__('Secure Code Warrior')]: 'https://www.securecodewarrior.com/',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const LICENSE_ULTIMATE = 'ultimate';
|
||||||
|
export const LICENSE_FREE = 'free';
|
||||||
|
export const LICENSE_PREMIUM = 'premium';
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
query getCurrentLicensePlan {
|
||||||
|
currentLicense {
|
||||||
|
id
|
||||||
|
plan
|
||||||
|
}
|
||||||
|
}
|
|
@ -56,7 +56,6 @@ export const initSecurityConfiguration = (el) => {
|
||||||
'gitlabCiPresent',
|
'gitlabCiPresent',
|
||||||
'autoDevopsEnabled',
|
'autoDevopsEnabled',
|
||||||
'canEnableAutoDevops',
|
'canEnableAutoDevops',
|
||||||
'securityTrainingEnabled',
|
|
||||||
]),
|
]),
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -155,7 +155,7 @@ export default {
|
||||||
requests.forEach((request) => {
|
requests.forEach((request) => {
|
||||||
const poll = new Poll({
|
const poll = new Poll({
|
||||||
resource: {
|
resource: {
|
||||||
fetchData: () => request(this.$props),
|
fetchData: () => request(this),
|
||||||
},
|
},
|
||||||
method: 'fetchData',
|
method: 'fetchData',
|
||||||
successCallback: (response) => {
|
successCallback: (response) => {
|
||||||
|
@ -180,7 +180,7 @@ export default {
|
||||||
initExtensionPolling() {
|
initExtensionPolling() {
|
||||||
const poll = new Poll({
|
const poll = new Poll({
|
||||||
resource: {
|
resource: {
|
||||||
fetchData: () => this.fetchCollapsedData(this.$props),
|
fetchData: () => this.fetchCollapsedData(this),
|
||||||
},
|
},
|
||||||
method: 'fetchData',
|
method: 'fetchData',
|
||||||
successCallback: ({ data }) => {
|
successCallback: ({ data }) => {
|
||||||
|
@ -208,7 +208,7 @@ export default {
|
||||||
this.initExtensionPolling();
|
this.initExtensionPolling();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.fetchCollapsedData(this.$props)
|
this.fetchCollapsedData(this)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.setCollapsedData(data);
|
this.setCollapsedData(data);
|
||||||
})
|
})
|
||||||
|
@ -231,7 +231,7 @@ export default {
|
||||||
|
|
||||||
this.loadingState = LOADING_STATES.expandedLoading;
|
this.loadingState = LOADING_STATES.expandedLoading;
|
||||||
|
|
||||||
this.fetchFullData(this.$props)
|
this.fetchFullData(this)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
this.loadingState = null;
|
this.loadingState = null;
|
||||||
this.fullData = data.map((x, i) => ({ id: i, ...x }));
|
this.fullData = data.map((x, i) => ({ id: i, ...x }));
|
||||||
|
|
|
@ -34,13 +34,7 @@ export default {
|
||||||
{ ...extension },
|
{ ...extension },
|
||||||
{
|
{
|
||||||
props: {
|
props: {
|
||||||
...extension.props.reduce(
|
mr: this.mr,
|
||||||
(acc, key) => ({
|
|
||||||
...acc,
|
|
||||||
[key]: this.mr[key],
|
|
||||||
}),
|
|
||||||
{},
|
|
||||||
),
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -10,12 +10,26 @@ export const registerExtension = (extension) => {
|
||||||
registeredExtensions.extensions.push({
|
registeredExtensions.extensions.push({
|
||||||
extends: ExtensionBase,
|
extends: ExtensionBase,
|
||||||
name: extension.name,
|
name: extension.name,
|
||||||
props: extension.props,
|
props: {
|
||||||
|
mr: {
|
||||||
|
type: Object,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
i18n: extension.i18n,
|
i18n: extension.i18n,
|
||||||
expandEvent: extension.expandEvent,
|
expandEvent: extension.expandEvent,
|
||||||
enablePolling: extension.enablePolling,
|
enablePolling: extension.enablePolling,
|
||||||
modalComponent: extension.modalComponent,
|
modalComponent: extension.modalComponent,
|
||||||
computed: {
|
computed: {
|
||||||
|
...extension.props.reduce(
|
||||||
|
(acc, propKey) => ({
|
||||||
|
...acc,
|
||||||
|
[propKey]() {
|
||||||
|
return this.mr[propKey];
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
{},
|
||||||
|
),
|
||||||
...Object.keys(extension.computed).reduce(
|
...Object.keys(extension.computed).reduce(
|
||||||
(acc, computedKey) => ({
|
(acc, computedKey) => ({
|
||||||
...acc,
|
...acc,
|
||||||
|
|
|
@ -49,7 +49,7 @@ export default {
|
||||||
]"
|
]"
|
||||||
class="gl-rounded-full gl-mr-3 gl-relative gl-p-2"
|
class="gl-rounded-full gl-mr-3 gl-relative gl-p-2"
|
||||||
>
|
>
|
||||||
<gl-loading-icon v-if="isLoading" size="lg" inline class="gl-display-block" />
|
<gl-loading-icon v-if="isLoading" size="sm" inline class="gl-display-block" />
|
||||||
<gl-icon
|
<gl-icon
|
||||||
v-else
|
v-else
|
||||||
:name="$options.EXTENSION_ICON_NAMES[iconName]"
|
:name="$options.EXTENSION_ICON_NAMES[iconName]"
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
a {
|
a {
|
||||||
color: $gl-text-color;
|
color: $gl-text-color;
|
||||||
|
|
||||||
&.link,
|
&.link {
|
||||||
&.gl-link {
|
|
||||||
color: $blue-600;
|
color: $blue-600;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,13 +246,13 @@ module MergeRequestsHelper
|
||||||
''
|
''
|
||||||
end
|
end
|
||||||
|
|
||||||
link_to branch, branch_path, title: branch, class: 'gl-link gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mb-n2'
|
link_to branch, branch_path, title: branch, class: 'gl-text-blue-500! gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mb-n2'
|
||||||
end
|
end
|
||||||
|
|
||||||
def merge_request_header(project, merge_request)
|
def merge_request_header(project, merge_request)
|
||||||
link_to_author = link_to_member(project, merge_request.author, size: 24, extra_class: 'gl-font-weight-bold', avatar: false)
|
link_to_author = link_to_member(project, merge_request.author, size: 24, extra_class: 'gl-font-weight-bold', avatar: false)
|
||||||
copy_button = clipboard_button(text: merge_request.source_branch, title: _('Copy branch name'), class: 'btn btn-default btn-sm gl-button btn-default-tertiary btn-icon gl-display-none! gl-md-display-inline-block! js-source-branch-copy')
|
copy_button = clipboard_button(text: merge_request.source_branch, title: _('Copy branch name'), class: 'btn btn-default btn-sm gl-button btn-default-tertiary btn-icon gl-display-none! gl-md-display-inline-block! js-source-branch-copy')
|
||||||
target_branch = link_to merge_request.target_branch, project_tree_path(merge_request.target_project, merge_request.target_branch), title: merge_request.target_branch, class: 'gl-link gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mb-n2'
|
target_branch = link_to merge_request.target_branch, project_tree_path(merge_request.target_project, merge_request.target_branch), title: merge_request.target_branch, class: 'gl-text-blue-500! gl-font-monospace gl-bg-blue-50 gl-rounded-base gl-font-sm gl-px-2 gl-display-inline-block gl-text-truncate gl-max-w-26 gl-mb-n2'
|
||||||
|
|
||||||
_('%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}').html_safe % { author: link_to_author.html_safe, source_branch: merge_request_source_branch(merge_request).html_safe, copy_button: copy_button.html_safe, target_branch: target_branch.html_safe, created_at: time_ago_with_tooltip(merge_request.created_at, html_class: 'gl-display-inline-block').html_safe }
|
_('%{author} requested to merge %{source_branch} %{copy_button} into %{target_branch} %{created_at}').html_safe % { author: link_to_author.html_safe, source_branch: merge_request_source_branch(merge_request).html_safe, copy_button: copy_button.html_safe, target_branch: target_branch.html_safe, created_at: time_ago_with_tooltip(merge_request.created_at, html_class: 'gl-display-inline-block').html_safe }
|
||||||
end
|
end
|
||||||
|
|
|
@ -118,7 +118,7 @@ class Label < ApplicationRecord
|
||||||
| # Integer-based label ID, or
|
| # Integer-based label ID, or
|
||||||
(?<label_name>
|
(?<label_name>
|
||||||
# String-based single-word label title, or
|
# String-based single-word label title, or
|
||||||
[A-Za-z0-9_\-\?\.&]+
|
#{Gitlab::Regex.sep_by_1(/:{1,2}/, /[A-Za-z0-9_\-\?\.&]+/)}
|
||||||
(?<!\.|\?)
|
(?<!\.|\?)
|
||||||
|
|
|
|
||||||
# String-based multi-word label surrounded in quotes
|
# String-based multi-word label surrounded in quotes
|
||||||
|
|
|
@ -2906,10 +2906,6 @@ class Project < ApplicationRecord
|
||||||
build_artifacts_size_refresh&.started?
|
build_artifacts_size_refresh&.started?
|
||||||
end
|
end
|
||||||
|
|
||||||
def security_training_available?
|
|
||||||
licensed_feature_available?(:security_training)
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
# overridden in EE
|
# overridden in EE
|
||||||
|
|
|
@ -24,8 +24,7 @@ module Projects
|
||||||
gitlab_ci_history_path: gitlab_ci_history_path,
|
gitlab_ci_history_path: gitlab_ci_history_path,
|
||||||
auto_fix_enabled: autofix_enabled,
|
auto_fix_enabled: autofix_enabled,
|
||||||
can_toggle_auto_fix_settings: can_toggle_autofix,
|
can_toggle_auto_fix_settings: can_toggle_autofix,
|
||||||
auto_fix_user_path: auto_fix_user_path,
|
auto_fix_user_path: auto_fix_user_path
|
||||||
security_training_enabled: project.security_training_available?
|
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ instance of the [GraphiQL explorer](https://gitlab.com/-/graphql-explorer):
|
||||||
|
|
||||||
1. Open the [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer) page.
|
1. Open the [GraphiQL Explorer](https://gitlab.com/-/graphql-explorer) page.
|
||||||
1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
|
1. Paste the `query` listed above into the left window of your GraphiQL explorer tool.
|
||||||
1. Click Play to get the result shown here:
|
1. Select Play to get the result shown here:
|
||||||
|
|
||||||
![GraphiQL explorer search for boards](img/sample_issue_boards_v13_2.png)
|
![GraphiQL explorer search for boards](img/sample_issue_boards_v13_2.png)
|
||||||
|
|
||||||
|
|
|
@ -48,7 +48,7 @@ GET /runners?tag_list=tag1,tag2
|
||||||
|------------|--------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------|--------------|----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
||||||
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
||||||
| `status` | string | no | The status of runners to show, one of: `online`, `offline` and `never_contacted`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
| `status` | string | no | The status of runners to show, one of: `online`, `offline`, `stale`, and `never_contacted`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
||||||
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
||||||
| `tag_list` | string array | no | List of the runner's tags |
|
| `tag_list` | string array | no | List of the runner's tags |
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ GET /runners/all?tag_list=tag1,tag2
|
||||||
|------------|--------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------|--------------|----------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of runners to show, one of: `specific`, `shared`, `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
||||||
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
||||||
| `status` | string | no | The status of runners to show, one of: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
| `status` | string | no | The status of runners to show, one of: `online`, `offline`, `stale`, and `never_contacted`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
||||||
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
||||||
| `tag_list` | string array | no | List of the runner's tags |
|
| `tag_list` | string array | no | List of the runner's tags |
|
||||||
|
|
||||||
|
@ -464,7 +464,7 @@ GET /projects/:id/runners?tag_list=tag1,tag2
|
||||||
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
| `id` | integer/string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
|
||||||
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
| `scope` | string | no | Deprecated: Use `type` or `status` instead. The scope of specific runners to show, one of: `active`, `paused`, `online` and `offline`; showing all runners if none provided |
|
||||||
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type` |
|
||||||
| `status` | string | no | The status of runners to show, one of: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
| `status` | string | no | The status of runners to show, one of: `online`, `offline`, `stale`, and `never_contacted`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
||||||
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
||||||
| `tag_list` | string array | no | List of the runner's tags |
|
| `tag_list` | string array | no | List of the runner's tags |
|
||||||
|
|
||||||
|
@ -580,7 +580,7 @@ GET /groups/:id/runners?tag_list=tag1,tag2
|
||||||
|------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `id` | integer | yes | The ID of the group owned by the authenticated user |
|
| `id` | integer | yes | The ID of the group owned by the authenticated user |
|
||||||
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type`. The `project_type` value is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351466) and will be removed in GitLab 15.0 |
|
| `type` | string | no | The type of runners to show, one of: `instance_type`, `group_type`, `project_type`. The `project_type` value is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/351466) and will be removed in GitLab 15.0 |
|
||||||
| `status` | string | no | The status of runners to show, one of: `online` and `offline`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
| `status` | string | no | The status of runners to show, one of: `online`, `offline`, `stale`, and `never_contacted`. `active` and `paused` are also possible values which were deprecated in GitLab 14.8 and will be removed in GitLab 16.0 |
|
||||||
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
| `paused` | boolean | no | Whether to include only runners that are accepting or ignoring new jobs |
|
||||||
| `tag_list` | string array | no | List of the runner's tags |
|
| `tag_list` | string array | no | List of the runner's tags |
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ Supported attributes:
|
||||||
| Attribute | Type | Required | Description |
|
| Attribute | Type | Required | Description |
|
||||||
|-----------------|----------------|------------------------|-------------|
|
|-----------------|----------------|------------------------|-------------|
|
||||||
| `project_id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
|
| `project_id` | integer/string | **{check-circle}** Yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
|
||||||
| `name` | string | **{check-circle}** Yes | The `name` of the file being uploaded. The file name must be unique within the project. |
|
| `name` | string | **{check-circle}** Yes | The `name` of the file being uploaded. The filename must be unique within the project. |
|
||||||
| `file` | file | **{check-circle}** Yes | The `file` being uploaded (5 MB limit). |
|
| `file` | file | **{check-circle}** Yes | The `file` being uploaded (5 MB limit). |
|
||||||
|
|
||||||
Example request:
|
Example request:
|
||||||
|
|
|
@ -36,9 +36,9 @@ environments are not displayed.
|
||||||
|
|
||||||
To add a project to the dashboard:
|
To add a project to the dashboard:
|
||||||
|
|
||||||
1. Click the **Add projects** button in the home screen of the dashboard.
|
1. Select **Add projects** in the home screen of the dashboard.
|
||||||
1. Search and add one or more projects using the **Search your projects** field.
|
1. Search and add one or more projects using the **Search your projects** field.
|
||||||
1. Click the **Add projects** button.
|
1. Select **Add projects**.
|
||||||
|
|
||||||
Once added, you can see a summary of each project's environment operational
|
Once added, you can see a summary of each project's environment operational
|
||||||
health, including the latest commit, pipeline status, and deployment time.
|
health, including the latest commit, pipeline status, and deployment time.
|
||||||
|
|
|
@ -63,7 +63,7 @@ rollout 10%:
|
||||||
ROLLOUT_PERCENTAGE: 10
|
ROLLOUT_PERCENTAGE: 10
|
||||||
```
|
```
|
||||||
|
|
||||||
When the jobs are built, a **play** button appears next to the job's name. Click the **play** button
|
When the jobs are built, a **play** button appears next to the job's name. Select **play**
|
||||||
to release each stage of pods. You can also rollback by running a lower percentage job. Once 100%
|
to release each stage of pods. You can also rollback by running a lower percentage job. Once 100%
|
||||||
is reached, you cannot roll back using this method. It is still possible to roll back by redeploying
|
is reached, you cannot roll back using this method. It is still possible to roll back by redeploying
|
||||||
the old version using the **Rollback** button on the environment page.
|
the old version using the **Rollback** button on the environment page.
|
||||||
|
|
|
@ -92,7 +92,7 @@ For more information, see [Deployment safety](../environments/deployment_safety.
|
||||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211339) in GitLab 13.6.
|
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/211339) in GitLab 13.6.
|
||||||
|
|
||||||
A deployment job can fail because a newer one has run. If you retry the failed deployment job, the
|
A deployment job can fail because a newer one has run. If you retry the failed deployment job, the
|
||||||
environment could be overwritten with older source code. If you click **Retry**, a modal warns you
|
environment could be overwritten with older source code. If you select **Retry**, a modal warns you
|
||||||
about this and asks for confirmation.
|
about this and asks for confirmation.
|
||||||
|
|
||||||
For more information, see [Deployment safety](../environments/deployment_safety.md).
|
For more information, see [Deployment safety](../environments/deployment_safety.md).
|
||||||
|
|
|
@ -85,9 +85,9 @@ To protect or unprotect a runner:
|
||||||
|
|
||||||
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
|
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
|
||||||
1. Find the runner you want to protect or unprotect. Make sure it's enabled.
|
1. Find the runner you want to protect or unprotect. Make sure it's enabled.
|
||||||
1. Click the pencil button.
|
1. Select the pencil button.
|
||||||
1. Check the **Protected** option.
|
1. Check the **Protected** option.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
![specific runners edit icon](img/protected_runners_check_box_v14_1.png)
|
![specific runners edit icon](img/protected_runners_check_box_v14_1.png)
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ To reset the registration token:
|
||||||
|
|
||||||
1. Go to the project's **Settings > CI/CD**.
|
1. Go to the project's **Settings > CI/CD**.
|
||||||
1. Expand the **General pipelines settings** section.
|
1. Expand the **General pipelines settings** section.
|
||||||
1. Find the **Runner token** form field and click the **Reveal value** button.
|
1. Find the **Runner token** form field and select **Reveal value**.
|
||||||
1. Delete the value and save the form.
|
1. Delete the value and save the form.
|
||||||
1. After the page is refreshed, expand the **Runners settings** section
|
1. After the page is refreshed, expand the **Runners settings** section
|
||||||
and check the registration token - it should be changed.
|
and check the registration token - it should be changed.
|
||||||
|
@ -193,9 +193,9 @@ To make a runner pick untagged jobs:
|
||||||
|
|
||||||
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
|
1. Go to the project's **Settings > CI/CD** and expand the **Runners** section.
|
||||||
1. Find the runner you want to pick untagged jobs and make sure it's enabled.
|
1. Find the runner you want to pick untagged jobs and make sure it's enabled.
|
||||||
1. Click the pencil button.
|
1. Select the pencil button.
|
||||||
1. Check the **Run untagged jobs** option.
|
1. Check the **Run untagged jobs** option.
|
||||||
1. Click the **Save changes** button for the changes to take effect.
|
1. Select **Save changes** for the changes to take effect.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
The runner tags list can not be empty when it's not allowed to pick untagged jobs.
|
The runner tags list can not be empty when it's not allowed to pick untagged jobs.
|
||||||
|
|
|
@ -84,7 +84,7 @@ To disable shared runners for a group:
|
||||||
1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
|
1. Go to the group's **Settings > CI/CD** and expand the **Runners** section.
|
||||||
1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
|
1. In the **Shared runners** area, turn off the **Enable shared runners for this group** toggle.
|
||||||
1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
|
1. Optionally, to allow shared runners to be enabled for individual projects or subgroups,
|
||||||
click **Allow projects and subgroups to override the group setting**.
|
select **Allow projects and subgroups to override the group setting**.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
To re-enable the shared runners for a group, turn on the
|
To re-enable the shared runners for a group, turn on the
|
||||||
|
@ -200,11 +200,11 @@ You must have the Owner role for the group.
|
||||||
|
|
||||||
1. Go to the group you want to remove or pause the runner for.
|
1. Go to the group you want to remove or pause the runner for.
|
||||||
1. On the left sidebar, select **CI/CD > Runners**.
|
1. On the left sidebar, select **CI/CD > Runners**.
|
||||||
1. Click **Pause** or **Remove runner**.
|
1. Select **Pause** or **Remove runner**.
|
||||||
- If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
|
- If you pause a group runner that is used by multiple projects, the runner pauses for all projects.
|
||||||
- From the group view, you cannot remove a runner that is assigned to more than one project.
|
- From the group view, you cannot remove a runner that is assigned to more than one project.
|
||||||
You must remove it from each project first.
|
You must remove it from each project first.
|
||||||
1. On the confirmation dialog, click **OK**.
|
1. On the confirmation dialog, select **OK**.
|
||||||
|
|
||||||
## Specific runners
|
## Specific runners
|
||||||
|
|
||||||
|
|
|
@ -34,8 +34,8 @@ Additional features and capabilities are planned.
|
||||||
|
|
||||||
To add a secure file to a project:
|
To add a secure file to a project:
|
||||||
|
|
||||||
1. On the top bar, select **Menu > Projects** and find your project.
|
1. On the top bar, select **Menu > Projects** and find your project.
|
||||||
1. On the left sidebar, select **Settings > CI/CD**.
|
1. On the left sidebar, select **Settings > CI/CD**.
|
||||||
1. In the **Secure Files** section, select **Manage**.
|
1. In the **Secure Files** section, select **Manage**.
|
||||||
1. Select **Upload File**.
|
1. Select **Upload File**.
|
||||||
1. Find the file to upload, select **Open**, and the file upload begins immediately.
|
1. Find the file to upload, select **Open**, and the file upload begins immediately.
|
||||||
|
|
|
@ -115,6 +115,6 @@ There are several ways you can contribute to Cloud Seed:
|
||||||
and [share feedback](https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/issues/new?template=general_feedback).
|
and [share feedback](https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/feedback/-/issues/new?template=general_feedback).
|
||||||
- If you are familiar with Ruby on Rails or Vue.js,
|
- If you are familiar with Ruby on Rails or Vue.js,
|
||||||
consider [contributing to GitLab](../development/contributing/index.md) as a developer.
|
consider [contributing to GitLab](../development/contributing/index.md) as a developer.
|
||||||
- Much of Cloud Seed is an internal module within the GitLab code base.
|
- Much of Cloud Seed is an internal module within the GitLab codebase.
|
||||||
- If you are familiar with GitLab pipelines, consider contributing to
|
- If you are familiar with GitLab pipelines, consider contributing to
|
||||||
the [Cloud Seed Library](https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library) project.
|
the [Cloud Seed Library](https://gitlab.com/gitlab-org/incubation-engineering/five-minute-production/library) project.
|
||||||
|
|
|
@ -226,9 +226,9 @@ Download Ruby and compile it:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir /tmp/ruby && cd /tmp/ruby
|
mkdir /tmp/ruby && cd /tmp/ruby
|
||||||
curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.5.tar.gz"
|
curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.6.tar.gz"
|
||||||
echo '2755b900a21235b443bb16dadd9032f784d4a88f143d852bc5d154f22b8781f1 ruby-2.7.5.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.5.tar.gz
|
echo 'e7203b0cc09442ed2c08936d483f8ac140ec1c72e37bb5c401646b7866cb5d10 ruby-2.7.6.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.6.tar.gz
|
||||||
cd ruby-2.7.5
|
cd ruby-2.7.6
|
||||||
|
|
||||||
./configure --disable-install-rdoc --enable-shared
|
./configure --disable-install-rdoc --enable-shared
|
||||||
make
|
make
|
||||||
|
|
|
@ -97,6 +97,6 @@ application.
|
||||||
[restart GitLab](../administration/restart_gitlab.md#installations-from-source).
|
[restart GitLab](../administration/restart_gitlab.md#installations-from-source).
|
||||||
|
|
||||||
On the sign-in page there should now be an Auth0 icon below the regular sign-in
|
On the sign-in page there should now be an Auth0 icon below the regular sign-in
|
||||||
form. Click the icon to begin the authentication process. Auth0 asks the
|
form. Select the icon to begin the authentication process. Auth0 asks the
|
||||||
user to sign in and authorize the GitLab application. If the user authenticates
|
user to sign in and authorize the GitLab application. If the user authenticates
|
||||||
successfully, the user is returned to GitLab and signed in.
|
successfully, the user is returned to GitLab and signed in.
|
||||||
|
|
|
@ -261,7 +261,7 @@ To enable languages support:
|
||||||
1. On the left sidebar, select **Settings > Advanced Search**.
|
1. On the left sidebar, select **Settings > Advanced Search**.
|
||||||
1. Locate **Custom analyzers: language support**.
|
1. Locate **Custom analyzers: language support**.
|
||||||
1. Enable plugins support for **Indexing**.
|
1. Enable plugins support for **Indexing**.
|
||||||
1. Click **Save changes** for the changes to take effect.
|
1. Select **Save changes** for the changes to take effect.
|
||||||
1. Trigger [Zero downtime reindexing](#zero-downtime-reindexing) or reindex everything from scratch to create a new index with updated mappings.
|
1. Trigger [Zero downtime reindexing](#zero-downtime-reindexing) or reindex everything from scratch to create a new index with updated mappings.
|
||||||
1. Enable plugins support for **Searching** after the previous step is completed.
|
1. Enable plugins support for **Searching** after the previous step is completed.
|
||||||
|
|
||||||
|
@ -435,7 +435,7 @@ Some migrations are built with a retry limit. If the migration cannot finish wit
|
||||||
it is halted and a notification is displayed in the Advanced Search integration settings.
|
it is halted and a notification is displayed in the Advanced Search integration settings.
|
||||||
It is recommended to check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog) to
|
It is recommended to check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog) to
|
||||||
debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
|
debug why the migration was halted and make any changes before retrying the migration. Once you believe you've
|
||||||
fixed the cause of the failure, click "Retry migration", and the migration is scheduled to be retried
|
fixed the cause of the failure, select "Retry migration", and the migration is scheduled to be retried
|
||||||
in the background.
|
in the background.
|
||||||
|
|
||||||
If you cannot get the migration to succeed, you may
|
If you cannot get the migration to succeed, you may
|
||||||
|
@ -611,7 +611,7 @@ Sidekiq processes](../administration/operations/extra_sidekiq_processes.md).
|
||||||
|
|
||||||
This enqueues a Sidekiq job for each project that needs to be indexed.
|
This enqueues a Sidekiq job for each project that needs to be indexed.
|
||||||
You can view the jobs in **Menu > Admin > Monitoring > Background Jobs > Queues Tab**
|
You can view the jobs in **Menu > Admin > Monitoring > Background Jobs > Queues Tab**
|
||||||
and click `elastic_commit_indexer`, or you can query indexing status using a Rake task:
|
and select `elastic_commit_indexer`, or you can query indexing status using a Rake task:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
# Omnibus installations
|
# Omnibus installations
|
||||||
|
|
|
@ -91,7 +91,7 @@ To change your personal details, including name, billing address, and email addr
|
||||||
1. Select **My account > Account details**.
|
1. Select **My account > Account details**.
|
||||||
1. Expand the **Personal details** section.
|
1. Expand the **Personal details** section.
|
||||||
1. Edit your personal details.
|
1. Edit your personal details.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
### Change your company details
|
### Change your company details
|
||||||
|
|
||||||
|
@ -101,7 +101,7 @@ To change your company details, including company name and VAT number:
|
||||||
1. Select **My account > Account details**.
|
1. Select **My account > Account details**.
|
||||||
1. Expand the **Company details** section.
|
1. Expand the **Company details** section.
|
||||||
1. Edit the company details.
|
1. Edit the company details.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
### Change your payment method
|
### Change your payment method
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ To change your payment method:
|
||||||
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
||||||
1. Select **My account > Payment methods**.
|
1. Select **My account > Payment methods**.
|
||||||
1. **Edit** an existing payment method's information or **Add new payment method**.
|
1. **Edit** an existing payment method's information or **Add new payment method**.
|
||||||
1. Click **Save Changes**.
|
1. Select **Save Changes**.
|
||||||
|
|
||||||
#### Set a default payment method
|
#### Set a default payment method
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ method as the default:
|
||||||
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
||||||
1. Select **My account > Payment methods**.
|
1. Select **My account > Payment methods**.
|
||||||
1. **Edit** the selected payment method and check the **Make default payment method** checkbox.
|
1. **Edit** the selected payment method and check the **Make default payment method** checkbox.
|
||||||
1. Click **Save Changes**.
|
1. Select **Save Changes**.
|
||||||
|
|
||||||
### Change the linked account
|
### Change the linked account
|
||||||
|
|
||||||
|
@ -137,8 +137,8 @@ To change the GitLab.com account linked to your Customers Portal account:
|
||||||
[Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
[Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
||||||
1. In a separate browser tab, go to [GitLab SaaS](https://gitlab.com) and ensure you
|
1. In a separate browser tab, go to [GitLab SaaS](https://gitlab.com) and ensure you
|
||||||
are not logged in.
|
are not logged in.
|
||||||
1. On the Customers Portal page, click **My account > Account details**.
|
1. On the Customers Portal page, select **My account > Account details**.
|
||||||
1. Under **Your GitLab.com account**, click **Change linked account**.
|
1. Under **Your GitLab.com account**, select **Change linked account**.
|
||||||
1. Log in to the [GitLab SaaS](https://gitlab.com) account you want to link to the Customers Portal
|
1. Log in to the [GitLab SaaS](https://gitlab.com) account you want to link to the Customers Portal
|
||||||
account.
|
account.
|
||||||
|
|
||||||
|
@ -164,9 +164,9 @@ Only one namespace can be linked to a subscription.
|
||||||
To change the password for this customers portal account:
|
To change the password for this customers portal account:
|
||||||
|
|
||||||
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
1. Log in to the [Customers Portal](https://customers.gitlab.com/customers/sign_in).
|
||||||
1. Select the **My account** drop-down and click on **Account details**.
|
1. Select the **My account** drop-down and select on **Account details**.
|
||||||
1. Make the required changes to the **Your password** section.
|
1. Make the required changes to the **Your password** section.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
## Community program subscriptions
|
## Community program subscriptions
|
||||||
|
|
||||||
|
|
|
@ -69,9 +69,9 @@ Download Ruby and compile it:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
mkdir /tmp/ruby && cd /tmp/ruby
|
mkdir /tmp/ruby && cd /tmp/ruby
|
||||||
curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.5.tar.gz"
|
curl --remote-name --location --progress-bar "https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.6.tar.gz"
|
||||||
echo '2755b900a21235b443bb16dadd9032f784d4a88f143d852bc5d154f22b8781f1 ruby-2.7.5.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.5.tar.gz
|
echo 'e7203b0cc09442ed2c08936d483f8ac140ec1c72e37bb5c401646b7866cb5d10 ruby-2.7.6.tar.gz' | sha256sum -c - && tar xzf ruby-2.7.6.tar.gz
|
||||||
cd ruby-2.7.5
|
cd ruby-2.7.6
|
||||||
|
|
||||||
./configure --disable-install-rdoc --enable-shared
|
./configure --disable-install-rdoc --enable-shared
|
||||||
make
|
make
|
||||||
|
|
|
@ -235,7 +235,7 @@ v1.0, 2019-01-01
|
||||||
NOTE:
|
NOTE:
|
||||||
[Wiki pages](project/wiki/index.md#create-a-new-wiki-page) created with the AsciiDoc
|
[Wiki pages](project/wiki/index.md#create-a-new-wiki-page) created with the AsciiDoc
|
||||||
format are saved with the file extension `.asciidoc`. When working with AsciiDoc wiki
|
format are saved with the file extension `.asciidoc`. When working with AsciiDoc wiki
|
||||||
pages, change the file name from `.adoc` to `.asciidoc`.
|
pages, change the filename from `.adoc` to `.asciidoc`.
|
||||||
|
|
||||||
```plaintext
|
```plaintext
|
||||||
include::basics.adoc[]
|
include::basics.adoc[]
|
||||||
|
|
|
@ -49,7 +49,7 @@ In order to:
|
||||||
After you have successful deployments to your group-level or instance-level cluster:
|
After you have successful deployments to your group-level or instance-level cluster:
|
||||||
|
|
||||||
1. Navigate to your group's **Kubernetes** page.
|
1. Navigate to your group's **Kubernetes** page.
|
||||||
1. Click on the **Environments** tab.
|
1. Select the **Environments** tab.
|
||||||
|
|
||||||
Only successful deployments to the cluster are included in this page.
|
Only successful deployments to the cluster are included in this page.
|
||||||
Non-cluster environments aren't included.
|
Non-cluster environments aren't included.
|
||||||
|
|
|
@ -98,7 +98,7 @@ To enable the Prometheus integration for your cluster:
|
||||||
**Kubernetes** page.
|
**Kubernetes** page.
|
||||||
1. Select the **Integrations** tab.
|
1. Select the **Integrations** tab.
|
||||||
1. Check the **Enable Prometheus integration** checkbox.
|
1. Check the **Enable Prometheus integration** checkbox.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
1. Go to the **Health** tab to see your cluster's metrics.
|
1. Go to the **Health** tab to see your cluster's metrics.
|
||||||
|
|
||||||
## Elastic Stack cluster integration **(FREE SELF)**
|
## Elastic Stack cluster integration **(FREE SELF)**
|
||||||
|
@ -165,5 +165,5 @@ To enable the Elastic Stack integration for your cluster:
|
||||||
**Kubernetes** page.
|
**Kubernetes** page.
|
||||||
1. Select the **Integrations** tab.
|
1. Select the **Integrations** tab.
|
||||||
1. Check the **Enable Elastic Stack integration** checkbox.
|
1. Check the **Enable Elastic Stack integration** checkbox.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
1. Go to the **Health** tab to see your cluster's metrics.
|
1. Go to the **Health** tab to see your cluster's metrics.
|
||||||
|
|
|
@ -49,7 +49,7 @@ Select the desired period from the calendar dropdown.
|
||||||
|
|
||||||
## Sorting by different factors
|
## Sorting by different factors
|
||||||
|
|
||||||
Contributions per group member are also presented in tabular format. Click a column header to sort the table by that column:
|
Contributions per group member are also presented in tabular format. Select a column header to sort the table by that column:
|
||||||
|
|
||||||
- Member name
|
- Member name
|
||||||
- Number of pushed events
|
- Number of pushed events
|
||||||
|
|
|
@ -115,7 +115,7 @@ To set a limit on how long personal access tokens are valid for users in a group
|
||||||
1. Navigate to the **Settings > General** page in your group's sidebar.
|
1. Navigate to the **Settings > General** page in your group's sidebar.
|
||||||
1. Expand the **Permissions and group features** section.
|
1. Expand the **Permissions and group features** section.
|
||||||
1. Fill in the **Maximum allowable lifetime for access tokens (days)** field.
|
1. Fill in the **Maximum allowable lifetime for access tokens (days)** field.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
Once a lifetime for personal access tokens is set:
|
Once a lifetime for personal access tokens is set:
|
||||||
|
|
||||||
|
|
|
@ -577,7 +577,7 @@ To generate a SAML Response:
|
||||||
- [SAML-tracer](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) for Firefox.
|
- [SAML-tracer](https://addons.mozilla.org/en-US/firefox/addon/saml-tracer/) for Firefox.
|
||||||
1. Open a new browser tab.
|
1. Open a new browser tab.
|
||||||
1. Open the SAML tracer console:
|
1. Open the SAML tracer console:
|
||||||
- Chrome: Right click on the page, select **Inspect**, then click on the SAML tab in the opened developer console.
|
- Chrome: Right click on the page, select **Inspect**, then select the SAML tab in the opened developer console.
|
||||||
- Firefox: Select the SAML-tracer icon located on the browser toolbar.
|
- Firefox: Select the SAML-tracer icon located on the browser toolbar.
|
||||||
1. Go to the GitLab single sign-on URL for the group in the same browser tab with the SAML tracer open.
|
1. Go to the GitLab single sign-on URL for the group in the same browser tab with the SAML tracer open.
|
||||||
1. Select **Authorize** or attempt to log in. A SAML response is displayed in the tracer console that resembles this
|
1. Select **Authorize** or attempt to log in. A SAML response is displayed in the tracer console that resembles this
|
||||||
|
|
|
@ -82,7 +82,7 @@ table, use the Azure defaults. For a list of required attributes, refer to the [
|
||||||
|
|
||||||
For guidance, you can view [an example configuration in the troubleshooting reference](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory).
|
For guidance, you can view [an example configuration in the troubleshooting reference](../../../administration/troubleshooting/group_saml_scim.md#azure-active-directory).
|
||||||
|
|
||||||
1. Below the mapping list click on **Show advanced options > Edit attribute list for AppName**.
|
1. Below the mapping list select **Show advanced options > Edit attribute list for AppName**.
|
||||||
1. Ensure the `id` is the primary and required field, and `externalId` is also required.
|
1. Ensure the `id` is the primary and required field, and `externalId` is also required.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
|
|
|
@ -23,9 +23,9 @@ To add a project to the dashboard:
|
||||||
1. Ensure your alerts populate the `gitlab_environment_name` label on the alerts you set up in Prometheus.
|
1. Ensure your alerts populate the `gitlab_environment_name` label on the alerts you set up in Prometheus.
|
||||||
The value of this should match the name of your environment in GitLab.
|
The value of this should match the name of your environment in GitLab.
|
||||||
In GitLab 13.9, you can display alerts for the `production` environment only.
|
In GitLab 13.9, you can display alerts for the `production` environment only.
|
||||||
1. Click the **Add projects** button in the home screen of the dashboard.
|
1. Select **Add projects** in the home screen of the dashboard.
|
||||||
1. Search and add one or more projects using the **Search your projects** field.
|
1. Search and add one or more projects using the **Search your projects** field.
|
||||||
1. Click the **Add projects** button.
|
1. Select **Add projects**.
|
||||||
|
|
||||||
Once added, the dashboard displays the project's number of active alerts,
|
Once added, the dashboard displays the project's number of active alerts,
|
||||||
last commit, pipeline status, and when it was last deployed.
|
last commit, pipeline status, and when it was last deployed.
|
||||||
|
|
|
@ -57,7 +57,7 @@ To download and run a container image hosted in the GitLab Container Registry:
|
||||||
1. Copy the link to your container image:
|
1. Copy the link to your container image:
|
||||||
- Go to your project or group's **Packages & Registries > Container Registry**
|
- Go to your project or group's **Packages & Registries > Container Registry**
|
||||||
and find the image you want.
|
and find the image you want.
|
||||||
- Next to the image name, click the **Copy** button.
|
- Next to the image name, select **Copy**.
|
||||||
|
|
||||||
![Container Registry image URL](img/container_registry_hover_path_13_4.png)
|
![Container Registry image URL](img/container_registry_hover_path_13_4.png)
|
||||||
|
|
||||||
|
@ -404,7 +404,7 @@ To delete images from within GitLab:
|
||||||
by clicking the red **{remove}** **Trash** icon next to the tag you want
|
by clicking the red **{remove}** **Trash** icon next to the tag you want
|
||||||
to delete.
|
to delete.
|
||||||
|
|
||||||
1. In the dialog box, click **Remove tag**.
|
1. In the dialog box, select **Remove tag**.
|
||||||
|
|
||||||
### Delete images using the API
|
### Delete images using the API
|
||||||
|
|
||||||
|
@ -506,7 +506,7 @@ You can, however, remove the Container Registry for a project:
|
||||||
1. Go to your project's **Settings > General** page.
|
1. Go to your project's **Settings > General** page.
|
||||||
1. Expand the **Visibility, project features, permissions** section
|
1. Expand the **Visibility, project features, permissions** section
|
||||||
and disable **Container Registry**.
|
and disable **Container Registry**.
|
||||||
1. Click **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
The **Packages & Registries > Container Registry** entry is removed from the project's sidebar.
|
The **Packages & Registries > Container Registry** entry is removed from the project's sidebar.
|
||||||
|
|
||||||
|
|
|
@ -109,12 +109,12 @@ To create a cleanup policy in the UI:
|
||||||
| **Remove tags older than** | Remove only tags older than X days. |
|
| **Remove tags older than** | Remove only tags older than X days. |
|
||||||
| **Remove tags matching** | The regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
|
| **Remove tags matching** | The regex pattern that determines which tags to remove. This value cannot be blank. For all tags, use `.*`. See other [regex pattern examples](#regex-pattern-examples). |
|
||||||
|
|
||||||
1. Click **Save**.
|
1. Select **Save**.
|
||||||
|
|
||||||
Depending on the interval you chose, the policy is scheduled to run.
|
Depending on the interval you chose, the policy is scheduled to run.
|
||||||
|
|
||||||
NOTE:
|
NOTE:
|
||||||
If you edit the policy and click **Save** again, the interval is reset.
|
If you edit the policy and select **Save** again, the interval is reset.
|
||||||
|
|
||||||
### Regex pattern examples
|
### Regex pattern examples
|
||||||
|
|
||||||
|
|
|
@ -701,7 +701,7 @@ dependencies {
|
||||||
|
|
||||||
For your project, go to **Packages & Registries > Package Registry**.
|
For your project, go to **Packages & Registries > Package Registry**.
|
||||||
|
|
||||||
To remove a package, click the red trash icon or, from the package details, the **Delete** button.
|
To remove a package, select the red trash icon or, from the package details, the **Delete** button.
|
||||||
|
|
||||||
## Create Maven packages with GitLab CI/CD
|
## Create Maven packages with GitLab CI/CD
|
||||||
|
|
||||||
|
|
|
@ -171,7 +171,7 @@ To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet en
|
||||||
|
|
||||||
![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
|
![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
|
||||||
|
|
||||||
1. Click **Save**.
|
1. Select **Save**.
|
||||||
|
|
||||||
The source is displayed in your list.
|
The source is displayed in your list.
|
||||||
|
|
||||||
|
@ -200,7 +200,7 @@ To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endp
|
||||||
|
|
||||||
![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
|
![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png)
|
||||||
|
|
||||||
1. Click **Save**.
|
1. Select **Save**.
|
||||||
|
|
||||||
The source is displayed in your list.
|
The source is displayed in your list.
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ To delete a package in the UI, from your group or project:
|
||||||
|
|
||||||
1. Go to **Packages & Registries > Package Registry**.
|
1. Go to **Packages & Registries > Package Registry**.
|
||||||
1. Find the name of the package you want to delete.
|
1. Find the name of the package you want to delete.
|
||||||
1. Click **Delete**.
|
1. Select **Delete**.
|
||||||
|
|
||||||
The package is permanently deleted.
|
The package is permanently deleted.
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ Advanced Search searches default project branches only.
|
||||||
|
|
||||||
| Use | Description | Example |
|
| Use | Description | Example |
|
||||||
|--------------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|--------------|---------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| `filename:` | File name | [`filename:*spec.rb`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=filename%3A*spec.rb&group_id=9970&project_id=278964) |
|
| `filename:` | Filename | [`filename:*spec.rb`](https://gitlab.com/search?snippets=&scope=blobs&repository_ref=&search=filename%3A*spec.rb&group_id=9970&project_id=278964) |
|
||||||
| `path:` | Repository location | [`path:spec/workers/`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=path%3Aspec%2Fworkers&snippets=) |
|
| `path:` | Repository location | [`path:spec/workers/`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=path%3Aspec%2Fworkers&snippets=) |
|
||||||
| `extension:` | File extension, without the `.` | [`extension:js`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=extension%3Ajs&snippets=) |
|
| `extension:` | File extension, without the `.` | [`extension:js`](https://gitlab.com/search?group_id=9970&project_id=278964&repository_ref=&scope=blobs&search=extension%3Ajs&snippets=) |
|
||||||
| `blob:` | Git object ID | [`blob:998707*`](https://gitlab.com/search?snippets=false&scope=blobs&repository_ref=&search=blob%3A998707*&group_id=9970) |
|
| `blob:` | Git object ID | [`blob:998707*`](https://gitlab.com/search?snippets=false&scope=blobs&repository_ref=&search=blob%3A998707*&group_id=9970) |
|
||||||
|
|
|
@ -181,7 +181,7 @@ Search history is available for issues and merge requests, and is stored locally
|
||||||
in your browser. To run a search from history:
|
in your browser. To run a search from history:
|
||||||
|
|
||||||
1. In the top menu, select **Issues** or **Merge requests**.
|
1. In the top menu, select **Issues** or **Merge requests**.
|
||||||
1. To the left of the search bar, click **Recent searches**, and select a search from the list.
|
1. To the left of the search bar, select **Recent searches**, and select a search from the list.
|
||||||
|
|
||||||
## Removing search filters
|
## Removing search filters
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ sent within five minutes, with a link for users to re-confirm the subject email
|
||||||
|
|
||||||
## Do the confirmation emails expire?
|
## Do the confirmation emails expire?
|
||||||
|
|
||||||
The links in these re-confirmation emails expire after one day by default. Users who click an expired link are asked to request a new re-confirmation email. Any user can request a new re-confirmation email from `http://gitlab.example.com/users/confirmation/new`.
|
The links in these re-confirmation emails expire after one day by default. Users who select an expired link are asked to request a new re-confirmation email. Any user can request a new re-confirmation email from `http://gitlab.example.com/users/confirmation/new`.
|
||||||
|
|
||||||
## Generate a list of affected users
|
## Generate a list of affected users
|
||||||
|
|
||||||
|
|
|
@ -481,6 +481,11 @@ module Gitlab
|
||||||
"can contain only lowercase letters, digits, '_' and '-'. " \
|
"can contain only lowercase letters, digits, '_' and '-'. " \
|
||||||
"Must start with a letter, and cannot end with '-' or '_'"
|
"Must start with a letter, and cannot end with '-' or '_'"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# One or more `part`s, separated by separator
|
||||||
|
def sep_by_1(separator, part)
|
||||||
|
%r(#{part} (#{separator} #{part})*)x
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ module Sidebars
|
||||||
::Sidebars::MenuItem.new(
|
::Sidebars::MenuItem.new(
|
||||||
title: _('Contacts'),
|
title: _('Contacts'),
|
||||||
link: group_crm_contacts_path(context.group),
|
link: group_crm_contacts_path(context.group),
|
||||||
active_routes: { path: 'groups/crm#contacts' },
|
active_routes: { controller: 'groups/crm/contacts' },
|
||||||
item_id: :crm_contacts
|
item_id: :crm_contacts
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
@ -44,7 +44,7 @@ module Sidebars
|
||||||
::Sidebars::MenuItem.new(
|
::Sidebars::MenuItem.new(
|
||||||
title: _('Organizations'),
|
title: _('Organizations'),
|
||||||
link: group_crm_organizations_path(context.group),
|
link: group_crm_organizations_path(context.group),
|
||||||
active_routes: { path: 'groups/crm#organizations' },
|
active_routes: { controller: 'groups/crm/organizations' },
|
||||||
item_id: :crm_organizations
|
item_id: :crm_organizations
|
||||||
)
|
)
|
||||||
end
|
end
|
||||||
|
|
|
@ -2,6 +2,7 @@ import Vue, { nextTick } from 'vue';
|
||||||
import VueApollo from 'vue-apollo';
|
import VueApollo from 'vue-apollo';
|
||||||
import { GlTab, GlTabs, GlLink } from '@gitlab/ui';
|
import { GlTab, GlTabs, GlLink } from '@gitlab/ui';
|
||||||
import { mount } from '@vue/test-utils';
|
import { mount } from '@vue/test-utils';
|
||||||
|
|
||||||
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
import { useLocalStorageSpy } from 'helpers/local_storage_helper';
|
||||||
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
|
import { makeMockUserCalloutDismisser } from 'helpers/mock_user_callout_dismisser';
|
||||||
import stubChildren from 'helpers/stub_children';
|
import stubChildren from 'helpers/stub_children';
|
||||||
|
@ -19,14 +20,22 @@ import {
|
||||||
LICENSE_COMPLIANCE_DESCRIPTION,
|
LICENSE_COMPLIANCE_DESCRIPTION,
|
||||||
LICENSE_COMPLIANCE_HELP_PATH,
|
LICENSE_COMPLIANCE_HELP_PATH,
|
||||||
AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
|
AUTO_DEVOPS_ENABLED_ALERT_DISMISSED_STORAGE_KEY,
|
||||||
|
LICENSE_ULTIMATE,
|
||||||
|
LICENSE_PREMIUM,
|
||||||
|
LICENSE_FREE,
|
||||||
} from '~/security_configuration/components/constants';
|
} from '~/security_configuration/components/constants';
|
||||||
import FeatureCard from '~/security_configuration/components/feature_card.vue';
|
import FeatureCard from '~/security_configuration/components/feature_card.vue';
|
||||||
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
|
import TrainingProviderList from '~/security_configuration/components/training_provider_list.vue';
|
||||||
|
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||||
|
import currentLicenseQuery from '~/security_configuration/graphql/current_license.query.graphql';
|
||||||
|
import waitForPromises from 'helpers/wait_for_promises';
|
||||||
|
|
||||||
import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
|
import UpgradeBanner from '~/security_configuration/components/upgrade_banner.vue';
|
||||||
import {
|
import {
|
||||||
REPORT_TYPE_LICENSE_COMPLIANCE,
|
REPORT_TYPE_LICENSE_COMPLIANCE,
|
||||||
REPORT_TYPE_SAST,
|
REPORT_TYPE_SAST,
|
||||||
} from '~/vue_shared/security_reports/constants';
|
} from '~/vue_shared/security_reports/constants';
|
||||||
|
import { getCurrentLicensePlanResponse } from '../mock_data';
|
||||||
|
|
||||||
const upgradePath = '/upgrade';
|
const upgradePath = '/upgrade';
|
||||||
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
|
const autoDevopsHelpPagePath = '/autoDevopsHelpPagePath';
|
||||||
|
@ -41,40 +50,31 @@ Vue.use(VueApollo);
|
||||||
describe('App component', () => {
|
describe('App component', () => {
|
||||||
let wrapper;
|
let wrapper;
|
||||||
let userCalloutDismissSpy;
|
let userCalloutDismissSpy;
|
||||||
|
let mockApollo;
|
||||||
|
|
||||||
const securityFeaturesMock = [
|
const createComponent = ({
|
||||||
{
|
shouldShowCallout = true,
|
||||||
name: SAST_NAME,
|
licenseQueryResponse = LICENSE_ULTIMATE,
|
||||||
shortName: SAST_SHORT_NAME,
|
...propsData
|
||||||
description: SAST_DESCRIPTION,
|
}) => {
|
||||||
helpPath: SAST_HELP_PATH,
|
|
||||||
configurationHelpPath: SAST_CONFIG_HELP_PATH,
|
|
||||||
type: REPORT_TYPE_SAST,
|
|
||||||
available: true,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const complianceFeaturesMock = [
|
|
||||||
{
|
|
||||||
name: LICENSE_COMPLIANCE_NAME,
|
|
||||||
description: LICENSE_COMPLIANCE_DESCRIPTION,
|
|
||||||
helpPath: LICENSE_COMPLIANCE_HELP_PATH,
|
|
||||||
type: REPORT_TYPE_LICENSE_COMPLIANCE,
|
|
||||||
configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const createComponent = ({ shouldShowCallout = true, ...propsData } = {}) => {
|
|
||||||
userCalloutDismissSpy = jest.fn();
|
userCalloutDismissSpy = jest.fn();
|
||||||
|
|
||||||
|
mockApollo = createMockApollo([
|
||||||
|
[
|
||||||
|
currentLicenseQuery,
|
||||||
|
jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue(
|
||||||
|
licenseQueryResponse instanceof Error
|
||||||
|
? licenseQueryResponse
|
||||||
|
: getCurrentLicensePlanResponse(licenseQueryResponse),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
wrapper = extendedWrapper(
|
wrapper = extendedWrapper(
|
||||||
mount(SecurityConfigurationApp, {
|
mount(SecurityConfigurationApp, {
|
||||||
propsData: {
|
propsData,
|
||||||
augmentedSecurityFeatures: securityFeaturesMock,
|
|
||||||
augmentedComplianceFeatures: complianceFeaturesMock,
|
|
||||||
securityTrainingEnabled: true,
|
|
||||||
...propsData,
|
|
||||||
},
|
|
||||||
provide: {
|
provide: {
|
||||||
upgradePath,
|
upgradePath,
|
||||||
autoDevopsHelpPagePath,
|
autoDevopsHelpPagePath,
|
||||||
|
@ -82,6 +82,7 @@ describe('App component', () => {
|
||||||
projectFullPath,
|
projectFullPath,
|
||||||
vulnerabilityTrainingDocsPath,
|
vulnerabilityTrainingDocsPath,
|
||||||
},
|
},
|
||||||
|
apolloProvider: mockApollo,
|
||||||
stubs: {
|
stubs: {
|
||||||
...stubChildren(SecurityConfigurationApp),
|
...stubChildren(SecurityConfigurationApp),
|
||||||
GlLink: false,
|
GlLink: false,
|
||||||
|
@ -132,13 +133,40 @@ describe('App component', () => {
|
||||||
const findAutoDevopsEnabledAlert = () => wrapper.findComponent(AutoDevopsEnabledAlert);
|
const findAutoDevopsEnabledAlert = () => wrapper.findComponent(AutoDevopsEnabledAlert);
|
||||||
const findVulnerabilityManagementTab = () => wrapper.findByTestId('vulnerability-management-tab');
|
const findVulnerabilityManagementTab = () => wrapper.findByTestId('vulnerability-management-tab');
|
||||||
|
|
||||||
|
const securityFeaturesMock = [
|
||||||
|
{
|
||||||
|
name: SAST_NAME,
|
||||||
|
shortName: SAST_SHORT_NAME,
|
||||||
|
description: SAST_DESCRIPTION,
|
||||||
|
helpPath: SAST_HELP_PATH,
|
||||||
|
configurationHelpPath: SAST_CONFIG_HELP_PATH,
|
||||||
|
type: REPORT_TYPE_SAST,
|
||||||
|
available: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const complianceFeaturesMock = [
|
||||||
|
{
|
||||||
|
name: LICENSE_COMPLIANCE_NAME,
|
||||||
|
description: LICENSE_COMPLIANCE_DESCRIPTION,
|
||||||
|
helpPath: LICENSE_COMPLIANCE_HELP_PATH,
|
||||||
|
type: REPORT_TYPE_LICENSE_COMPLIANCE,
|
||||||
|
configurationHelpPath: LICENSE_COMPLIANCE_HELP_PATH,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
wrapper.destroy();
|
wrapper.destroy();
|
||||||
|
mockApollo = null;
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('basic structure', () => {
|
describe('basic structure', () => {
|
||||||
beforeEach(() => {
|
beforeEach(async () => {
|
||||||
createComponent();
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
});
|
||||||
|
await waitForPromises();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('renders main-heading with correct text', () => {
|
it('renders main-heading with correct text', () => {
|
||||||
|
@ -198,7 +226,10 @@ describe('App component', () => {
|
||||||
|
|
||||||
describe('Manage via MR Error Alert', () => {
|
describe('Manage via MR Error Alert', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('on initial load', () => {
|
describe('on initial load', () => {
|
||||||
|
@ -234,6 +265,8 @@ describe('App component', () => {
|
||||||
describe('given the right props', () => {
|
describe('given the right props', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent({
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
autoDevopsEnabled: false,
|
autoDevopsEnabled: false,
|
||||||
gitlabCiPresent: false,
|
gitlabCiPresent: false,
|
||||||
canEnableAutoDevops: true,
|
canEnableAutoDevops: true,
|
||||||
|
@ -255,7 +288,10 @@ describe('App component', () => {
|
||||||
|
|
||||||
describe('given the wrong props', () => {
|
describe('given the wrong props', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent();
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
it('should not show AutoDevopsAlert', () => {
|
it('should not show AutoDevopsAlert', () => {
|
||||||
expect(findAutoDevopsAlert().exists()).toBe(false);
|
expect(findAutoDevopsAlert().exists()).toBe(false);
|
||||||
|
@ -279,7 +315,11 @@ describe('App component', () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponent({ autoDevopsEnabled });
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
autoDevopsEnabled,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it(shouldRender ? 'renders' : 'does not render', () => {
|
it(shouldRender ? 'renders' : 'does not render', () => {
|
||||||
|
@ -305,7 +345,12 @@ describe('App component', () => {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
createComponent({ autoDevopsEnabled: true });
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
autoDevopsEnabled: true,
|
||||||
|
});
|
||||||
|
|
||||||
findAutoDevopsEnabledAlert().vm.$emit('dismiss');
|
findAutoDevopsEnabledAlert().vm.$emit('dismiss');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -330,6 +375,7 @@ describe('App component', () => {
|
||||||
describe('given at least one unavailable feature', () => {
|
describe('given at least one unavailable feature', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent({
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
|
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -350,6 +396,7 @@ describe('App component', () => {
|
||||||
describe('given at least one unavailable feature, but banner is already dismissed', () => {
|
describe('given at least one unavailable feature, but banner is already dismissed', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent({
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
|
augmentedComplianceFeatures: complianceFeaturesMock.map(makeAvailable(false)),
|
||||||
shouldShowCallout: false,
|
shouldShowCallout: false,
|
||||||
});
|
});
|
||||||
|
@ -376,7 +423,11 @@ describe('App component', () => {
|
||||||
|
|
||||||
describe('when given latestPipelinePath props', () => {
|
describe('when given latestPipelinePath props', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent({ latestPipelinePath: 'test/path' });
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
latestPipelinePath: 'test/path',
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
|
it('should show latest pipeline info on the security tab with correct link when latestPipelinePath is defined', () => {
|
||||||
|
@ -401,6 +452,8 @@ describe('App component', () => {
|
||||||
describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
|
describe('given gitlabCiPresent & gitlabCiHistoryPath props', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
createComponent({
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
gitlabCiPresent: true,
|
gitlabCiPresent: true,
|
||||||
gitlabCiHistoryPath,
|
gitlabCiHistoryPath,
|
||||||
});
|
});
|
||||||
|
@ -415,36 +468,48 @@ describe('App component', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('Vulnerability management tab', () => {
|
describe('Vulnerability management', () => {
|
||||||
it('does not show tab if security training is disabled', () => {
|
beforeEach(async () => {
|
||||||
createComponent({ securityTrainingEnabled: false });
|
createComponent({
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
expect(findVulnerabilityManagementTab().exists()).toBe(false);
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
});
|
||||||
|
await waitForPromises();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('security training enabled', () => {
|
it('renders TrainingProviderList component', () => {
|
||||||
beforeEach(() => {
|
expect(findTrainingProviderList().exists()).toBe(true);
|
||||||
createComponent();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('shows the tab if security training is enabled', () => {
|
|
||||||
expect(findVulnerabilityManagementTab().exists()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders TrainingProviderList component', () => {
|
|
||||||
expect(findTrainingProviderList().exists()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders security training description', () => {
|
|
||||||
expect(findVulnerabilityManagementTab().text()).toContain(i18n.securityTrainingDescription);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('renders link to help docs', () => {
|
|
||||||
const trainingLink = findVulnerabilityManagementTab().findComponent(GlLink);
|
|
||||||
|
|
||||||
expect(trainingLink.text()).toBe('Learn more about vulnerability training');
|
|
||||||
expect(trainingLink.attributes('href')).toBe(vulnerabilityTrainingDocsPath);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders security training description', () => {
|
||||||
|
expect(findVulnerabilityManagementTab().text()).toContain(i18n.securityTrainingDescription);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('renders link to help docs', () => {
|
||||||
|
const trainingLink = findVulnerabilityManagementTab().findComponent(GlLink);
|
||||||
|
|
||||||
|
expect(trainingLink.text()).toBe('Learn more about vulnerability training');
|
||||||
|
expect(trainingLink.attributes('href')).toBe(vulnerabilityTrainingDocsPath);
|
||||||
|
});
|
||||||
|
|
||||||
|
it.each`
|
||||||
|
licenseQueryResponse | display
|
||||||
|
${LICENSE_ULTIMATE} | ${true}
|
||||||
|
${LICENSE_PREMIUM} | ${false}
|
||||||
|
${LICENSE_FREE} | ${false}
|
||||||
|
${null} | ${true}
|
||||||
|
${new Error()} | ${true}
|
||||||
|
`(
|
||||||
|
'displays $display for license $licenseQueryResponse',
|
||||||
|
async ({ licenseQueryResponse, display }) => {
|
||||||
|
createComponent({
|
||||||
|
licenseQueryResponse,
|
||||||
|
augmentedSecurityFeatures: securityFeaturesMock,
|
||||||
|
augmentedComplianceFeatures: complianceFeaturesMock,
|
||||||
|
});
|
||||||
|
await waitForPromises();
|
||||||
|
expect(findVulnerabilityManagementTab().exists()).toBe(display);
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -111,3 +111,12 @@ export const tempProviderLogos = {
|
||||||
svg: `<svg>${[testProviderName[1]]}</svg>`,
|
svg: `<svg>${[testProviderName[1]]}</svg>`,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCurrentLicensePlanResponse = (plan) => ({
|
||||||
|
data: {
|
||||||
|
currentLicense: {
|
||||||
|
id: 'gid://gitlab/License/1',
|
||||||
|
plan,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
|
@ -21,8 +21,8 @@ describe('MR widget extension registering', () => {
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
extends: ExtensionBase,
|
extends: ExtensionBase,
|
||||||
name: 'Test',
|
name: 'Test',
|
||||||
props: ['helloWorld'],
|
|
||||||
computed: {
|
computed: {
|
||||||
|
helloWorld: expect.any(Function),
|
||||||
test: expect.any(Function),
|
test: expect.any(Function),
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
|
@ -8323,14 +8323,6 @@ RSpec.describe Project, factory_default: :keep do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '#security_training_available?' do
|
|
||||||
subject { build(:project) }
|
|
||||||
|
|
||||||
it 'returns false' do
|
|
||||||
expect(subject.security_training_available?).to eq false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def finish_job(export_job)
|
def finish_job(export_job)
|
||||||
|
|
|
@ -122,7 +122,7 @@ RSpec.describe QuickActions::InterpretService do
|
||||||
inprogress # populate the label
|
inprogress # populate the label
|
||||||
_, updates, _ = service.execute(content, issuable)
|
_, updates, _ = service.execute(content, issuable)
|
||||||
|
|
||||||
expect(updates).to eq(add_label_ids: [bug.id, inprogress.id])
|
expect(updates).to match(add_label_ids: contain_exactly(bug.id, inprogress.id))
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'returns the label message' do
|
it 'returns the label message' do
|
||||||
|
@ -130,7 +130,10 @@ RSpec.describe QuickActions::InterpretService do
|
||||||
inprogress # populate the label
|
inprogress # populate the label
|
||||||
_, _, message = service.execute(content, issuable)
|
_, _, message = service.execute(content, issuable)
|
||||||
|
|
||||||
expect(message).to eq("Added #{bug.to_reference(format: :name)} #{inprogress.to_reference(format: :name)} labels.")
|
# Compare message without making assumptions about ordering.
|
||||||
|
expect(message).to match %r{Added ~".*" ~".*" labels.}
|
||||||
|
expect(message).to include(bug.to_reference(format: :name))
|
||||||
|
expect(message).to include(inprogress.to_reference(format: :name))
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -1196,6 +1199,64 @@ RSpec.describe QuickActions::InterpretService do
|
||||||
let(:issuable) { merge_request }
|
let(:issuable) { merge_request }
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'with a colon label' do
|
||||||
|
let(:bug) { create(:label, project: project, title: 'Category:Bug') }
|
||||||
|
let(:inprogress) { create(:label, project: project, title: 'status:in:progress') }
|
||||||
|
|
||||||
|
context 'when quoted' do
|
||||||
|
let(:content) { %(/label ~"#{inprogress.title}" ~"#{bug.title}" ~unknown) }
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { merge_request }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { issue }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unquoted' do
|
||||||
|
let(:content) { %(/label ~#{inprogress.title} ~#{bug.title} ~unknown) }
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { merge_request }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { issue }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'with a scoped label' do
|
||||||
|
let(:bug) { create(:label, :scoped, project: project) }
|
||||||
|
let(:inprogress) { create(:label, project: project, title: 'three::part::label') }
|
||||||
|
|
||||||
|
context 'when quoted' do
|
||||||
|
let(:content) { %(/label ~"#{inprogress.title}" ~"#{bug.title}" ~unknown) }
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { merge_request }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { issue }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when unquoted' do
|
||||||
|
let(:content) { %(/label ~#{inprogress.title} ~#{bug.title} ~unknown) }
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { merge_request }
|
||||||
|
end
|
||||||
|
|
||||||
|
it_behaves_like 'label command' do
|
||||||
|
let(:issuable) { issue }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it_behaves_like 'multiple label command' do
|
it_behaves_like 'multiple label command' do
|
||||||
let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{bug.title}) }
|
let(:content) { %(/label ~"#{inprogress.title}" \n/label ~#{bug.title}) }
|
||||||
let(:issuable) { issue }
|
let(:issuable) { issue }
|
||||||
|
|
Loading…
Reference in New Issue