Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue1
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/composer_installation.vue8
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/conan_installation.vue7
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/maven_installation.vue7
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/npm_installation.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/nuget_installation.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue6
-rw-r--r--app/assets/javascripts/packages_and_registries/package_registry/constants.js6
-rw-r--r--app/assets/javascripts/pipelines/components/jobs/jobs_app.vue2
-rw-r--r--app/helpers/packages_helper.rb6
-rw-r--r--app/models/application_setting.rb3
-rw-r--r--app/models/members/project_namespace_member.rb7
-rw-r--r--app/views/admin/application_settings/appearances/_form.html.haml12
-rw-r--r--app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml2
-rw-r--r--app/views/projects/pages/_list.html.haml6
-rw-r--r--doc/topics/autodevops/customize.md65
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md6
-rw-r--r--lib/gitlab/regex.rb26
-rw-r--r--spec/features/commits_spec.rb54
-rw-r--r--spec/features/projects/pipelines/pipeline_spec.rb97
-rw-r--r--spec/frontend/__helpers__/matchers.js68
-rw-r--r--spec/frontend/__helpers__/matchers/index.js2
-rw-r--r--spec/frontend/__helpers__/matchers/to_have_sprite_icon.js36
-rw-r--r--spec/frontend/__helpers__/matchers/to_match_interpolated_text.js30
-rw-r--r--spec/frontend/__helpers__/matchers/to_match_interpolated_text_spec.js46
-rw-r--r--spec/frontend/__helpers__/matchers_spec.js48
-rw-r--r--spec/frontend/__helpers__/shared_test_setup.js2
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/conan_installation_spec.js.snap12
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap32
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/npm_installation_spec.js.snap12
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/nuget_installation_spec.js.snap12
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap20
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js4
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js18
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js15
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js13
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js12
-rw-r--r--spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js14
-rw-r--r--spec/lib/gitlab/regex_spec.rb2
-rw-r--r--spec/models/application_setting_spec.rb17
-rw-r--r--spec/models/packages/package_spec.rb10
42 files changed, 517 insertions, 243 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 5b4911bd23f..078498e0d3f 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-7bb80f713fccac70cd4f17211f1f5435b5014c7a
+a7b614916005688cb1c290f323adaf9dd37d0b27
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
index d49c1be5202..7dd090a7b47 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/app.vue
@@ -74,7 +74,6 @@ export default {
'canDelete',
'svgPath',
'npmPath',
- 'npmHelpPath',
'projectListUrl',
'groupListUrl',
],
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/composer_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/composer_installation.vue
index cc629ae394c..4ef37a3cbbe 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/composer_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/composer_installation.vue
@@ -6,6 +6,7 @@ import {
TRACKING_ACTION_COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND,
TRACKING_ACTION_COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
+ COMPOSER_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -17,7 +18,7 @@ export default {
GlLink,
GlSprintf,
},
- inject: ['composerHelpPath', 'composerConfigRepositoryName', 'composerPath', 'groupListUrl'],
+ inject: ['composerConfigRepositoryName', 'composerPath', 'groupListUrl'],
props: {
packageEntity: {
type: Object,
@@ -51,6 +52,9 @@ export default {
TRACKING_ACTION_COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
},
+ links: {
+ COMPOSER_HELP_PATH,
+ },
installOptions: [{ value: 'composer', label: s__('PackageRegistry|Show Composer commands') }],
};
</script>
@@ -79,7 +83,7 @@ export default {
<span data-testid="help-text">
<gl-sprintf :message="$options.i18n.infoLine">
<template #link="{ content }">
- <gl-link :href="composerHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.COMPOSER_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</span>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/conan_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/conan_installation.vue
index 99e27c9d44a..72e6a26e15f 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/conan_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/conan_installation.vue
@@ -6,6 +6,7 @@ import {
TRACKING_ACTION_COPY_CONAN_COMMAND,
TRACKING_ACTION_COPY_CONAN_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
+ CONAN_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -17,7 +18,7 @@ export default {
GlLink,
GlSprintf,
},
- inject: ['conanHelpPath', 'conanPath'],
+ inject: ['conanPath'],
props: {
packageEntity: {
type: Object,
@@ -44,7 +45,7 @@ export default {
TRACKING_ACTION_COPY_CONAN_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
},
-
+ links: { CONAN_HELP_PATH },
installOptions: [{ value: 'conan', label: s__('PackageRegistry|Show Conan commands') }],
};
</script>
@@ -72,7 +73,7 @@ export default {
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="conanHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.CONAN_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/maven_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/maven_installation.vue
index 2070f0bbca0..9757838ccfb 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/maven_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/maven_installation.vue
@@ -12,6 +12,7 @@ import {
TRACKING_ACTION_COPY_KOTLIN_ADD_TO_SOURCE_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
TRACKING_LABEL_MAVEN_INSTALLATION,
+ MAVEN_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -23,7 +24,7 @@ export default {
GlLink,
GlSprintf,
},
- inject: ['mavenHelpPath', 'mavenPath'],
+ inject: ['mavenPath'],
props: {
packageEntity: {
type: Object,
@@ -126,7 +127,7 @@ export default {
TRACKING_LABEL_CODE_INSTRUCTION,
TRACKING_LABEL_MAVEN_INSTALLATION,
},
-
+ links: { MAVEN_HELP_PATH },
installOptions: [
{ value: 'maven', label: s__('PackageRegistry|Maven XML') },
{ value: 'groovy', label: s__('PackageRegistry|Gradle Groovy DSL') },
@@ -185,7 +186,7 @@ export default {
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="mavenHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.MAVEN_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</template>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/npm_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/npm_installation.vue
index 2448324549e..7af9a2ade56 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/npm_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/npm_installation.vue
@@ -13,6 +13,7 @@ import {
YARN_PACKAGE_MANAGER,
PROJECT_PACKAGE_ENDPOINT_TYPE,
INSTANCE_PACKAGE_ENDPOINT_TYPE,
+ NPM_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -25,7 +26,7 @@ export default {
GlSprintf,
GlFormRadioGroup,
},
- inject: ['npmHelpPath', 'npmPath', 'npmProjectPath'],
+ inject: ['npmPath', 'npmProjectPath'],
props: {
packageEntity: {
type: Object,
@@ -89,6 +90,7 @@ export default {
'PackageRegistry|You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more.',
),
},
+ links: { NPM_HELP_PATH },
installOptions: [
{ value: NPM_PACKAGE_MANAGER, label: s__('PackageRegistry|Show NPM commands') },
{ value: YARN_PACKAGE_MANAGER, label: s__('PackageRegistry|Show Yarn commands') },
@@ -150,7 +152,7 @@ export default {
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="npmHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.NPM_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/nuget_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/nuget_installation.vue
index 2e9991b7be5..ca48da70bb4 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/nuget_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/nuget_installation.vue
@@ -6,6 +6,7 @@ import {
TRACKING_ACTION_COPY_NUGET_INSTALL_COMMAND,
TRACKING_ACTION_COPY_NUGET_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
+ NUGET_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -17,7 +18,7 @@ export default {
GlLink,
GlSprintf,
},
- inject: ['nugetHelpPath', 'nugetPath'],
+ inject: ['nugetPath'],
props: {
packageEntity: {
type: Object,
@@ -42,6 +43,7 @@ export default {
'PackageRegistry|For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}.',
),
},
+ links: { NUGET_HELP_PATH },
installOptions: [{ value: 'nuget', label: s__('PackageRegistry|Show Nuget commands') }],
};
</script>
@@ -68,7 +70,7 @@ export default {
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="nugetHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.NUGET_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
index 669adab9df6..1c4ef21a2cf 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
+++ b/app/assets/javascripts/packages_and_registries/package_registry/components/details/pypi_installation.vue
@@ -7,6 +7,7 @@ import {
TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND,
TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
TRACKING_LABEL_CODE_INSTRUCTION,
+ PYPI_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstruction from '~/vue_shared/components/registry/code_instruction.vue';
@@ -18,7 +19,7 @@ export default {
GlLink,
GlSprintf,
},
- inject: ['pypiHelpPath', 'pypiPath', 'pypiSetupPath'],
+ inject: ['pypiPath', 'pypiSetupPath'],
props: {
packageEntity: {
type: Object,
@@ -50,6 +51,7 @@ password = <your personal access token>`;
'PackageRegistry|For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}.',
),
},
+ links: { PYPI_HELP_PATH },
installOptions: [{ value: 'pypi', label: s__('PackageRegistry|Show PyPi commands') }],
};
</script>
@@ -86,7 +88,7 @@ password = <your personal access token>`;
/>
<gl-sprintf :message="$options.i18n.helpText">
<template #link="{ content }">
- <gl-link :href="pypiHelpPath" target="_blank">{{ content }}</gl-link>
+ <gl-link :href="$options.links.PYPI_HELP_PATH" target="_blank">{{ content }}</gl-link>
</template>
</gl-sprintf>
</div>
diff --git a/app/assets/javascripts/packages_and_registries/package_registry/constants.js b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
index ab6541e4264..af4e586231c 100644
--- a/app/assets/javascripts/packages_and_registries/package_registry/constants.js
+++ b/app/assets/javascripts/packages_and_registries/package_registry/constants.js
@@ -142,3 +142,9 @@ export const PACKAGE_TYPES = [
export const EMPTY_LIST_HELP_URL = helpPagePath('user/packages/package_registry/index');
export const PACKAGE_HELP_URL = helpPagePath('user/packages/index');
+export const NPM_HELP_PATH = helpPagePath('user/packages/npm_registry/index');
+export const MAVEN_HELP_PATH = helpPagePath('user/packages/maven_repository/index');
+export const CONAN_HELP_PATH = helpPagePath('user/packages/conan_repository/index');
+export const NUGET_HELP_PATH = helpPagePath('user/packages/nuget_repository/index');
+export const PYPI_HELP_PATH = helpPagePath('user/packages/pypi_repository/index');
+export const COMPOSER_HELP_PATH = helpPagePath('user/packages/composer_repository/index');
diff --git a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
index ffac8206b58..e11073aee33 100644
--- a/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
+++ b/app/assets/javascripts/pipelines/components/jobs/jobs_app.vue
@@ -112,7 +112,7 @@ export default {
</gl-skeleton-loader>
</div>
- <jobs-table v-else :jobs="jobs" :table-fields="$options.fields" />
+ <jobs-table v-else :jobs="jobs" :table-fields="$options.fields" data-testid="jobs-tab-table" />
<gl-intersection-observer v-if="jobsPageInfo.hasNextPage" @appear="fetchMoreJobs">
<gl-loading-icon v-if="$apollo.loading" size="md" />
diff --git a/app/helpers/packages_helper.rb b/app/helpers/packages_helper.rb
index 66f80e7eeb8..9e2b27de5b3 100644
--- a/app/helpers/packages_helper.rb
+++ b/app/helpers/packages_helper.rb
@@ -61,18 +61,12 @@ module PackagesHelper
svg_path: image_path('illustrations/no-packages.svg'),
npm_path: package_registry_instance_url(:npm),
npm_project_path: package_registry_project_url(project.id, :npm),
- npm_help_path: help_page_path('user/packages/npm_registry/index'),
maven_path: package_registry_project_url(project.id, :maven),
- maven_help_path: help_page_path('user/packages/maven_repository/index'),
conan_path: package_registry_project_url(project.id, :conan),
- conan_help_path: help_page_path('user/packages/conan_repository/index'),
nuget_path: nuget_package_registry_url(project.id),
- nuget_help_path: help_page_path('user/packages/nuget_repository/index'),
pypi_path: pypi_registry_url(project.id),
pypi_setup_path: package_registry_project_url(project.id, :pypi),
- pypi_help_path: help_page_path('user/packages/pypi_repository/index'),
composer_path: composer_registry_url(project&.group&.id),
- composer_help_path: help_page_path('user/packages/composer_repository/index'),
project_name: project.name,
project_list_url: project_packages_path(project),
group_list_url: project.group ? group_packages_path(project.group) : '',
diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb
index d5345bd5e02..ef5e72342fb 100644
--- a/app/models/application_setting.rb
+++ b/app/models/application_setting.rb
@@ -9,6 +9,7 @@ class ApplicationSetting < ApplicationRecord
include Sanitizable
ignore_columns %i[elasticsearch_shards elasticsearch_replicas], remove_with: '14.4', remove_after: '2021-09-22'
+ ignore_columns %i[static_objects_external_storage_auth_token], remove_with: '14.9', remove_after: '2022-03-22'
INSTANCE_REVIEW_MIN_USERS = 50
GRAFANA_URL_ERROR_MESSAGE = 'Please check your Grafana URL setting in ' \
@@ -21,7 +22,7 @@ class ApplicationSetting < ApplicationRecord
add_authentication_token_field :runners_registration_token, encrypted: -> { Feature.enabled?(:application_settings_tokens_optional_encryption) ? :optional : :required }
add_authentication_token_field :health_check_access_token
- add_authentication_token_field :static_objects_external_storage_auth_token, encrypted: :optional
+ add_authentication_token_field :static_objects_external_storage_auth_token, encrypted: :required
belongs_to :self_monitoring_project, class_name: "Project", foreign_key: 'instance_administration_project_id'
belongs_to :push_rule
diff --git a/app/models/members/project_namespace_member.rb b/app/models/members/project_namespace_member.rb
new file mode 100644
index 00000000000..0e0c52ee3ca
--- /dev/null
+++ b/app/models/members/project_namespace_member.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+# TODO: https://gitlab.com/groups/gitlab-org/-/epics/7054
+# This file is a part of the Consolidate Group and Project member management epic,
+# and will be developed further as we progress through that epic.
+class ProjectNamespaceMember < ProjectMember # rubocop:disable Gitlab/NamespacedClass
+end
diff --git a/app/views/admin/application_settings/appearances/_form.html.haml b/app/views/admin/application_settings/appearances/_form.html.haml
index 3bd16e4c344..0f7f0109a54 100644
--- a/app/views/admin/application_settings/appearances/_form.html.haml
+++ b/app/views/admin/application_settings/appearances/_form.html.haml
@@ -20,7 +20,7 @@
%hr
= f.hidden_field :header_logo_cache
= f.file_field :header_logo, class: "", accept: 'image/*'
- .hint
+ .form-text.text-muted
= _('Maximum file size is 1MB. Pages are optimized for a 28px tall header logo')
%hr
.row
@@ -39,7 +39,7 @@
%hr
= f.hidden_field :favicon_cache
= f.file_field :favicon, class: '', accept: 'image/*'
- .hint
+ .form-text.text-muted
= _("Maximum file size is 1 MB. Image size must be 32 x 32 pixels. Allowed image formats are %{favicon_extension_whitelist}.") % { favicon_extension_whitelist: favicon_extension_whitelist }
%br
= _("Images with incorrect dimensions are not resized automatically, and may result in unexpected behavior.")
@@ -58,7 +58,7 @@
.form-group
= f.label :description, class: 'col-form-label label-bold'
= f.text_area :description, class: "form-control gl-form-input", rows: 10
- .hint
+ .form-text.text-muted
= parsed_with_gfm
.form-group
= f.label :logo, class: 'col-form-label label-bold pt-0'
@@ -71,7 +71,7 @@
%hr
= f.hidden_field :logo_cache
= f.file_field :logo, class: "", accept: 'image/*'
- .hint
+ .form-text.text-muted
= _('Maximum file size is 1MB. Pages are optimized for a 640x360 px logo.')
%hr
@@ -84,7 +84,7 @@
= f.label :new_project_guidelines, class: 'col-form-label label-bold'
%p
= f.text_area :new_project_guidelines, class: "form-control gl-form-input", rows: 10
- .hint
+ .form-text.text-muted
= parsed_with_gfm
%hr
@@ -97,7 +97,7 @@
= f.label :profile_image_guidelines, class: 'col-form-label label-bold'
%p
= f.text_area :profile_image_guidelines, class: "form-control gl-form-input", rows: 10
- .hint
+ .form-text.text-muted
= parsed_with_gfm
.gl-mt-3.gl-mb-3
diff --git a/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml b/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml
index 4571d34a497..1ce79e61ac6 100644
--- a/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml
+++ b/app/views/admin/application_settings/appearances/_system_header_footer_form.html.haml
@@ -19,7 +19,7 @@
= form.label :email_header_and_footer_enabled, class: 'label-bold' do
= _('Enable header and footer in emails')
- .hint
+ .form-text.text-muted
= _('Add header and footer to emails. Please note that color settings will only be applied within the application interface')
.form-group.js-toggle-colors-container
diff --git a/app/views/projects/pages/_list.html.haml b/app/views/projects/pages/_list.html.haml
index 40352e79175..4e9c77564da 100644
--- a/app/views/projects/pages/_list.html.haml
+++ b/app/views/projects/pages/_list.html.haml
@@ -15,11 +15,9 @@
= external_link(domain.url, domain.url)
- if domain.certificate
%div
- %span.badge.badge-gray
- = s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject }
+ = gl_badge_tag(s_('GitLabPages|Certificate: %{subject}') % { subject: domain.pages_domain.subject })
- if domain.expired?
- %span.badge.badge-danger
- = s_('GitLabPages|Expired')
+ = gl_badge_tag s_('GitLabPages|Expired'), variant: :danger
%div
= link_to s_('GitLabPages|Edit'), project_pages_domain_path(@project, domain), class: "btn gl-button btn-sm btn-grouped btn-confirm btn-inverted"
= link_to s_('GitLabPages|Remove'), project_pages_domain_path(@project, domain), data: { confirm: s_('GitLabPages|Are you sure?')}, method: :delete, class: "btn gl-button btn-danger btn-sm btn-grouped"
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index 925f657c099..88f25e4a453 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -131,7 +131,7 @@ You can extend and manage your Auto DevOps configuration with GitLab APIs:
## Forward CI/CD variables to the build environment
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) in GitLab 12.3, but available in versions 11.9 and above.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) in GitLab 12.3, but available in GitLab 12.0 and later.
CI/CD variables can be forwarded into the build environment using the
`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` CI/CD variable.
@@ -408,14 +408,14 @@ applications.
| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI/CD variable names](#forward-cicd-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). |
| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app). |
| `AUTO_DEVOPS_CHART_REPOSITORY` | Helm Chart repository used to search for charts. Defaults to `https://charts.gitlab.io`. |
-| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | From GitLab 11.11, used to set the name of the Helm repository. Defaults to `gitlab`. |
-| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | From GitLab 11.11, used to set a username to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD`. |
-| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | From GitLab 11.11, used to set a password to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME`. |
+| `AUTO_DEVOPS_CHART_REPOSITORY_NAME` | Used to set the name of the Helm repository. Defaults to `gitlab`. |
+| `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME` | Used to set a username to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD`. |
+| `AUTO_DEVOPS_CHART_REPOSITORY_PASSWORD` | Used to set a password to connect to the Helm repository. Defaults to no credentials. Also set `AUTO_DEVOPS_CHART_REPOSITORY_USERNAME`. |
| `AUTO_DEVOPS_CHART_REPOSITORY_PASS_CREDENTIALS` | From GitLab 14.2, set to a non-empty value to enable forwarding of the Helm repository credentials to the chart server when the chart artifacts are on a different host than repository. |
| `AUTO_DEVOPS_DEPLOY_DEBUG` | From GitLab 13.1, if this variable is present, Helm outputs debug logs. |
| `AUTO_DEVOPS_ALLOW_TO_FORCE_DEPLOY_V<N>` | From [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image) v1.0.0, if this variable is present, a new major version of chart is forcibly deployed. For more information, see [Ignore warnings and continue deploying](upgrading_auto_deploy_dependencies.md#ignore-warnings-and-continue-deploying). |
| `BUILDPACK_URL` | Buildpack's full URL. [Must point to a URL supported by Pack or Herokuish](#custom-buildpacks). |
-| `CANARY_ENABLED` | From GitLab 11.0, used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
+| `CANARY_ENABLED` | Used to define a [deploy policy for canary environments](#deploy-policy-for-canary-environments). |
| `CANARY_PRODUCTION_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md) in the production environment. Takes precedence over `CANARY_REPLICAS`. Defaults to 1. |
| `CANARY_REPLICAS` | Number of canary replicas to deploy for [Canary Deployments](../../user/project/canary_deployments.md). Defaults to 1. |
| `CI_APPLICATION_REPOSITORY` | The repository of container image being built or deployed, `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`. For more details, read [Custom container image](#custom-container-image). |
@@ -424,18 +424,18 @@ applications.
| `DOCKERFILE_PATH` | From GitLab 13.2, allows overriding the [default Dockerfile path for the build stage](#custom-dockerfile) |
| `HELM_RELEASE_NAME` | From GitLab 12.1, allows the `helm` release name to be overridden. Can be used to assign unique release names when deploying multiple projects to a single namespace. |
| `HELM_UPGRADE_VALUES_FILE` | From GitLab 12.6, allows the `helm upgrade` values file to be overridden. Defaults to `.gitlab/auto-deploy-values.yaml`. |
-| `HELM_UPGRADE_EXTRA_ARGS` | From GitLab 11.11, allows extra options in `helm upgrade` commands when deploying the application. Note that using quotes doesn't prevent word splitting. |
-| `INCREMENTAL_ROLLOUT_MODE` | From GitLab 11.4, if present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
-| `K8S_SECRET_*` | From GitLab 11.7, any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) is made available by Auto DevOps as environment variables to the deployed application. |
+| `HELM_UPGRADE_EXTRA_ARGS` | Allows extra options in `helm upgrade` commands when deploying the application. Note that using quotes doesn't prevent word splitting. |
+| `INCREMENTAL_ROLLOUT_MODE` | If present, can be used to enable an [incremental rollout](#incremental-rollout-to-production) of your application for the production environment. Set to `manual` for manual deployment jobs or `timed` for automatic rollout deployments with a 5 minute delay each one. |
+| `K8S_SECRET_*` | Any variable prefixed with [`K8S_SECRET_`](#application-secret-variables) is made available by Auto DevOps as environment variables to the deployed application. |
| `KUBE_CONTEXT` | From GitLab 14.5, can be used to select which context to use from `KUBECONFIG`. When `KUBE_CONTEXT` is blank, the default context in `KUBECONFIG` (if any) will be used. A context must be selected when using the [CI/CD tunnel](../../user/clusters/agent/ci_cd_tunnel.md). |
-| `KUBE_INGRESS_BASE_DOMAIN` | From GitLab 11.8, can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/gitlab_managed_clusters.md#base-domain) for more information. |
+| `KUBE_INGRESS_BASE_DOMAIN` | Can be used to set a domain per cluster. See [cluster domains](../../user/project/clusters/gitlab_managed_clusters.md#base-domain) for more information. |
| `KUBE_NAMESPACE` | The namespace used for deployments. When using certificate-based clusters, [this value should not be overwritten directly](../../user/project/clusters/deploy_to_cluster.md#custom-namespace). |
| `KUBECONFIG` | The kubeconfig to use for deployments. User-provided values take priority over GitLab-provided values. |
| `PRODUCTION_REPLICAS` | Number of replicas to deploy in the production environment. Takes precedence over `REPLICAS` and defaults to 1. For zero downtime upgrades, set to 2 or greater. |
| `REPLICAS` | Number of replicas to deploy. Defaults to 1. |
-| `ROLLOUT_RESOURCE_TYPE` | From GitLab 11.9, allows specification of the resource type being deployed when using a custom Helm chart. Default value is `deployment`. |
+| `ROLLOUT_RESOURCE_TYPE` | Allows specification of the resource type being deployed when using a custom Helm chart. Default value is `deployment`. |
| `ROLLOUT_STATUS_DISABLED` | From GitLab 12.0, used to disable rollout status check because it does not support all resource types, for example, `cronjob`. |
-| `STAGING_ENABLED` | From GitLab 10.8, used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
+| `STAGING_ENABLED` | Used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
NOTE:
After you set up your replica variables using a
@@ -453,8 +453,8 @@ The following table lists CI/CD variables related to the database.
| **CI/CD Variable** | **Description** |
|-----------------------------------------|------------------------------------|
-| `DB_INITIALIZE` | From GitLab 11.4, used to specify the command to run to initialize the application's PostgreSQL database. Runs inside the application pod. |
-| `DB_MIGRATE` | From GitLab 11.4, used to specify the command to run to migrate the application's PostgreSQL database. Runs inside the application pod. |
+| `DB_INITIALIZE` | Used to specify the command to run to initialize the application's PostgreSQL database. Runs inside the application pod. |
+| `DB_MIGRATE` | Used to specify the command to run to migrate the application's PostgreSQL database. Runs inside the application pod. |
| `POSTGRES_ENABLED` | Whether PostgreSQL is enabled. Defaults to `true`. Set to `false` to disable the automatic deployment of PostgreSQL. |
| `POSTGRES_USER` | The PostgreSQL user. Defaults to `user`. Set it to use a custom username. |
| `POSTGRES_PASSWORD` | The PostgreSQL password. Defaults to `testing-password`. Set it to use a custom password. |
@@ -478,12 +478,11 @@ The following table lists variables used to disable jobs.
| `bundler-audit-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `canary` | `CANARY_ENABLED` | | This manual job is created if the variable is present. |
| `code_intelligence` | `CODE_INTELLIGENCE_DISABLED` | From GitLab 13.6 | If the variable is present, the job isn't created. |
-| `codequality` | `CODE_QUALITY_DISABLED` | Until GitLab 11.0 | If the variable is present, the job isn't created. |
-| `code_quality` | `CODE_QUALITY_DISABLED` | [From GitLab 11.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5773) | If the variable is present, the job isn't created. |
-| `container_scanning` | `CONTAINER_SCANNING_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
-| `dast` | `DAST_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
+| `code_quality` | `CODE_QUALITY_DISABLED` | | If the variable is present, the job isn't created. |
+| `container_scanning` | `CONTAINER_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
+| `dast` | `DAST_DISABLED` | | If the variable is present, the job isn't created. |
| `dast_environment_deploy` | `DAST_DISABLED_FOR_DEFAULT_BRANCH` or `DAST_DISABLED` | [From GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17789) | If either variable is present, the job isn't created. |
-| `dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
+| `dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `eslint-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `flawfinder-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `gemnasium-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
@@ -491,34 +490,32 @@ The following table lists variables used to disable jobs.
| `gemnasium-python-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `gosec-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `kubesec-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
-| `license_management` | `LICENSE_MANAGEMENT_DISABLED` | GitLab 11.0 to 12.7 | If the variable is present, the job isn't created. Job deprecated [from GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22773) |
+| `license_management` | `LICENSE_MANAGEMENT_DISABLED` | GitLab 12.7 and earlier | If the variable is present, the job isn't created. Job deprecated [from GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22773) |
| `license_scanning` | `LICENSE_MANAGEMENT_DISABLED` | [From GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22773) | If the variable is present, the job isn't created. |
| `load_performance` | `LOAD_PERFORMANCE_DISABLED` | From GitLab 13.2 | If the variable is present, the job isn't created. |
| `nodejs-scan-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
-| `performance` | `PERFORMANCE_DISABLED` | GitLab 11.0 to GitLab 13.12 | Browser performance. If the variable is present, the job isn't created. Replaced by `browser_performance`. |
+| `performance` | `PERFORMANCE_DISABLED` | GitLab 13.12 and earlier | Browser performance. If the variable is present, the job isn't created. Replaced by `browser_performance`. |
| `browser_performance` | `BROWSER_PERFORMANCE_DISABLED` | From GitLab 14.0 | Browser performance. If the variable is present, the job isn't created. Replaces `performance`. |
| `phpcs-security-audit-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `pmd-apex-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `retire-js-dependency_scanning` | `DEPENDENCY_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
-| `review` | `REVIEW_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
-| `review:stop` | `REVIEW_DISABLED` | From GitLab 11.0 | Manual job. If the variable is present, the job isn't created. |
-| `sast` | `SAST_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
-| `sast:container` | `CONTAINER_SCANNING_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
+| `review` | `REVIEW_DISABLED` | | If the variable is present, the job isn't created. |
+| `review:stop` | `REVIEW_DISABLED` | | Manual job. If the variable is present, the job isn't created. |
+| `sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
+| `sast:container` | `CONTAINER_SCANNING_DISABLED` | | If the variable is present, the job isn't created. |
| `secret_detection` | `SECRET_DETECTION_DISABLED` | From GitLab 13.1 | If the variable is present, the job isn't created. |
| `secret_detection_default_branch` | `SECRET_DETECTION_DISABLED` | [From GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/22773) | If the variable is present, the job isn't created. |
| `security-code-scan-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
-| `secrets-sast` | `SAST_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
+| `secrets-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `sobelaw-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
| `stop_dast_environment` | `DAST_DISABLED_FOR_DEFAULT_BRANCH` or `DAST_DISABLED` | [From GitLab 12.4](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/17789) | If either variable is present, the job isn't created. |
| `spotbugs-sast` | `SAST_DISABLED` | | If the variable is present, the job isn't created. |
-| `test` | `TEST_DISABLED` | From GitLab 11.0 | If the variable is present, the job isn't created. |
+| `test` | `TEST_DISABLED` | | If the variable is present, the job isn't created. |
| `staging` | `STAGING_ENABLED` | | The job is created if the variable is present. |
| `stop_review` | `REVIEW_DISABLED` | | If the variable is present, the job isn't created. |
### Application secret variables
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/49056) in GitLab 11.7.
-
Some applications need to define secret variables that are accessible by the deployed
application. Auto DevOps detects CI/CD variables starting with `K8S_SECRET_`, and makes
these prefixed variables available to the deployed application as environment variables.
@@ -623,8 +620,6 @@ service:
### Deploy policy for staging and production environments
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/160) in GitLab 10.8.
-
NOTE:
You can also set this inside your [project's settings](requirements.md#auto-devops-deployment-strategy).
@@ -640,8 +635,6 @@ you when you're ready to manually deploy to production.
### Deploy policy for canary environments **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-ci-yml/-/merge_requests/171) in GitLab 11.0.
-
You can use a [canary environment](../../user/project/canary_deployments.md) before
deploying any changes to production.
@@ -652,8 +645,6 @@ If you define `CANARY_ENABLED` with a non-empty value, then two manual jobs are
### Incremental rollout to production **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5415) in GitLab 10.8.
-
NOTE:
You can also set this inside your [project's settings](requirements.md#auto-devops-deployment-strategy).
@@ -703,14 +694,10 @@ With `INCREMENTAL_ROLLOUT_MODE` set to `manual` and with `STAGING_ENABLED`
![Rollout and staging enabled](img/rollout_staging_enabled.png)
WARNING:
-Before GitLab 11.4, the presence of the `INCREMENTAL_ROLLOUT_ENABLED` CI/CD variable
-enabled this feature. This configuration is deprecated, and is scheduled to be
-removed in the future.
+This configuration is deprecated, and is scheduled to be removed in the future.
### Timed incremental rollout to production **(PREMIUM)**
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) in GitLab 11.4.
-
NOTE:
You can also set this inside your [project's settings](requirements.md#auto-devops-deployment-strategy).
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index e07a961375b..f748f575419 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -201,11 +201,7 @@ To set a limit on how long these sessions are valid:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1007) in GitLab 14.6 [with a flag](../../../administration/feature_flags.md) named `ff_limit_ssh_key_lifetime`. Disabled by default.
> - [Enabled on self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/346753) in GitLab 14.6.
-
-FLAG:
-On self-managed GitLab, by default this feature is available. To hide the feature,
-ask an administrator to [disable the feature flag](../../../administration/feature_flags.md) named `ff_limit_ssh_key_lifetime`.
-On GitLab.com, this feature is not available.
+> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/1007) in GitLab 14.7. [Feature flag ff_limit_ssh_key_lifetime](https://gitlab.com/gitlab-org/gitlab/-/issues/347408) removed.
Users can optionally specify a lifetime for
[SSH keys](../../../ssh/index.md).
diff --git a/lib/gitlab/regex.rb b/lib/gitlab/regex.rb
index 8e139ae0709..b07b9c79858 100644
--- a/lib/gitlab/regex.rb
+++ b/lib/gitlab/regex.rb
@@ -79,7 +79,11 @@ module Gitlab
def nuget_version_regex
@nuget_version_regex ||= /
- \A#{_semver_major_minor_patch_regex}(\.\d*)?#{_semver_prerelease_build_regex}\z
+ \A#{_semver_major_regex}
+ \.#{_semver_minor_regex}
+ (\.#{_semver_patch_regex})?
+ (\.\d*)?
+ #{_semver_prerelease_build_regex}\z
/x.freeze
end
@@ -167,9 +171,25 @@ module Gitlab
# regexes rather than being used alone.
def _semver_major_minor_patch_regex
@_semver_major_minor_patch_regex ||= /
+ #{_semver_major_regex}\.#{_semver_minor_regex}\.#{_semver_patch_regex}
+ /x.freeze
+ end
+
+ def _semver_major_regex
+ @_semver_major_regex ||= /
(?<major>0|[1-9]\d*)
- \.(?<minor>0|[1-9]\d*)
- \.(?<patch>0|[1-9]\d*)
+ /x.freeze
+ end
+
+ def _semver_minor_regex
+ @_semver_minor_regex ||= /
+ (?<minor>0|[1-9]\d*)
+ /x.freeze
+ end
+
+ def _semver_patch_regex
+ @_semver_patch_regex ||= /
+ (?<patch>0|[1-9]\d*)
/x.freeze
end
diff --git a/spec/features/commits_spec.rb b/spec/features/commits_spec.rb
index 4378e88f7c1..e600a99e3b6 100644
--- a/spec/features/commits_spec.rb
+++ b/spec/features/commits_spec.rb
@@ -30,10 +30,10 @@ RSpec.describe 'Commits' do
project.add_reporter(user)
end
- describe 'Commit builds with jobs_tab_feature flag off' do
+ describe 'Commit builds with jobs_tab_vue feature flag off' do
before do
stub_feature_flags(jobs_tab_vue: false)
- visit pipeline_path(pipeline)
+ visit builds_project_pipeline_path(project, pipeline)
end
it { expect(page).to have_content pipeline.sha[0..7] }
@@ -45,6 +45,23 @@ RSpec.describe 'Commits' do
end
end
end
+
+ describe 'Commit builds with jobs_tab_vue feature flag on', :js do
+ before do
+ visit builds_project_pipeline_path(project, pipeline)
+
+ wait_for_requests
+ end
+
+ it { expect(page).to have_content pipeline.sha[0..7] }
+
+ it 'contains generic commit status build' do
+ page.within('[data-testid="jobs-tab-table"]') do
+ expect(page).to have_content "##{status.id}" # build id
+ expect(page).to have_content 'generic' # build name
+ end
+ end
+ end
end
context 'commit status is Ci Build' do
@@ -103,6 +120,18 @@ RSpec.describe 'Commits' do
end
end
+ context 'Download artifacts with jobs_tab_vue feature flag on', :js do
+ before do
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
+ end
+
+ it do
+ visit builds_project_pipeline_path(project, pipeline)
+ wait_for_requests
+ expect(page).to have_link('Download artifacts', href: download_project_job_artifacts_path(project, build, file_type: :archive))
+ end
+ end
+
describe 'Cancel all builds' do
it 'cancels commit', :js, :sidekiq_might_not_need_inline do
visit pipeline_path(pipeline)
@@ -141,6 +170,27 @@ RSpec.describe 'Commits' do
end
end
+ context "when logged as reporter and with jobs_tab_vue feature flag on", :js do
+ before do
+ project.add_reporter(user)
+ create(:ci_job_artifact, :archive, file: artifacts_file, job: build)
+ visit builds_project_pipeline_path(project, pipeline)
+ wait_for_requests
+ end
+
+ it 'renders header' do
+ expect(page).to have_content pipeline.sha[0..7]
+ expect(page).to have_content pipeline.git_commit_message.gsub!(/\s+/, ' ')
+ expect(page).to have_content pipeline.user.name
+ expect(page).not_to have_link('Cancel running')
+ expect(page).not_to have_link('Retry')
+ end
+
+ it do
+ expect(page).to have_link('Download artifacts')
+ end
+ end
+
context 'when accessing internal project with disallowed access', :js, quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/299575' do
before do
project.update!(
diff --git a/spec/features/projects/pipelines/pipeline_spec.rb b/spec/features/projects/pipelines/pipeline_spec.rb
index 6ddc8e43762..5176a7ec5a1 100644
--- a/spec/features/projects/pipelines/pipeline_spec.rb
+++ b/spec/features/projects/pipelines/pipeline_spec.rb
@@ -1020,6 +1020,103 @@ RSpec.describe 'Pipeline', :js do
end
end
+ describe 'GET /:project/-/pipelines/:id/builds with jobs_tab_vue feature flag turned on' do
+ include_context 'pipeline builds'
+
+ let_it_be(:project) { create(:project, :repository) }
+
+ let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
+
+ before do
+ visit builds_project_pipeline_path(project, pipeline)
+ end
+
+ it 'shows a list of jobs' do
+ expect(page).to have_content('Test')
+ expect(page).to have_content(build_passed.id)
+ expect(page).to have_content('Deploy')
+ expect(page).to have_content(build_failed.id)
+ expect(page).to have_content(build_running.id)
+ expect(page).to have_content(build_external.id)
+ expect(page).to have_content('Retry')
+ expect(page).to have_content('Cancel running')
+ expect(page).to have_button('Play')
+ end
+
+ it 'shows jobs tab pane as active' do
+ expect(page).to have_css('#js-tab-builds.active')
+ end
+
+ context 'page tabs' do
+ it 'shows Pipeline, Jobs and DAG tabs with link' do
+ expect(page).to have_link('Pipeline')
+ expect(page).to have_link('Jobs')
+ expect(page).to have_link('Needs')
+ end
+
+ it 'shows counter in Jobs tab' do
+ expect(page.find('.js-builds-counter').text).to eq(pipeline.total_size.to_s)
+ end
+
+ it 'shows Jobs tab as active' do
+ expect(page).to have_css('li.js-builds-tab-link .active')
+ end
+ end
+
+ context 'retrying jobs' do
+ it { expect(page).not_to have_content('retried') }
+
+ context 'when retrying' do
+ before do
+ find('[data-testid="retry"]', match: :first).click
+ end
+
+ it 'does not show a "Retry" button', :sidekiq_might_not_need_inline do
+ expect(page).not_to have_content('Retry')
+ end
+ end
+ end
+
+ context 'canceling jobs' do
+ it { expect(page).not_to have_selector('.ci-canceled') }
+
+ context 'when canceling' do
+ before do
+ click_on 'Cancel running'
+ end
+
+ it 'does not show a "Cancel running" button', :sidekiq_might_not_need_inline do
+ expect(page).not_to have_content('Cancel running')
+ end
+ end
+ end
+
+ context 'playing manual job' do
+ before do
+ within '[data-testid="jobs-tab-table"]' do
+ click_button('Play')
+
+ wait_for_requests
+ end
+ end
+
+ it { expect(build_manual.reload).to be_pending }
+ end
+
+ context 'when user unschedules a delayed job' do
+ before do
+ within '[data-testid="jobs-tab-table"]' do
+ click_button('Unschedule')
+ end
+ end
+
+ it 'unschedules the delayed job and shows play button as a manual job' do
+ expect(page).to have_button('Play')
+ expect(page).not_to have_button('Unschedule')
+ end
+ end
+ end
+
describe 'GET /:project/-/pipelines/:id/failures' do
let(:pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: '1234') }
let(:pipeline_failures_page) { failures_project_pipeline_path(project, pipeline) }
diff --git a/spec/frontend/__helpers__/matchers.js b/spec/frontend/__helpers__/matchers.js
deleted file mode 100644
index 945abdafe9a..00000000000
--- a/spec/frontend/__helpers__/matchers.js
+++ /dev/null
@@ -1,68 +0,0 @@
-export default {
- toHaveSpriteIcon: (element, iconName) => {
- if (!iconName) {
- throw new Error('toHaveSpriteIcon is missing iconName argument!');
- }
-
- if (!(element instanceof HTMLElement)) {
- throw new Error(`${element} is not a DOM element!`);
- }
-
- const iconReferences = [].slice.apply(element.querySelectorAll('svg use'));
- const matchingIcon = iconReferences.find(
- (reference) => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
- );
-
- const pass = Boolean(matchingIcon);
-
- let message;
- if (pass) {
- message = `${element.outerHTML} contains the sprite icon "${iconName}"!`;
- } else {
- message = `${element.outerHTML} does not contain the sprite icon "${iconName}"!`;
-
- const existingIcons = iconReferences.map((reference) => {
- const iconUrl = reference.getAttribute('href');
- return `"${iconUrl.replace(/^.+#/, '')}"`;
- });
- if (existingIcons.length > 0) {
- message += ` (only found ${existingIcons.join(',')})`;
- }
- }
-
- return {
- pass,
- message: () => message,
- };
- },
- toMatchInterpolatedText(received, match) {
- let clearReceived;
- let clearMatch;
-
- try {
- clearReceived = received.replace(/\s\s+/gm, ' ').replace(/\s\./gm, '.').trim();
- } catch (e) {
- return { actual: received, message: 'The received value is not a string', pass: false };
- }
- try {
- clearMatch = match.replace(/%{\w+}/gm, '').trim();
- } catch (e) {
- return { message: 'The comparator value is not a string', pass: false };
- }
- const pass = clearReceived === clearMatch;
- const message = pass
- ? () => `
- \n\n
- Expected: ${this.utils.printExpected(clearReceived)}
- To not equal: ${this.utils.printReceived(clearMatch)}
- `
- : () =>
- `
- \n\n
- Expected: ${this.utils.printExpected(clearReceived)}
- To equal: ${this.utils.printReceived(clearMatch)}
- `;
-
- return { actual: received, message, pass };
- },
-};
diff --git a/spec/frontend/__helpers__/matchers/index.js b/spec/frontend/__helpers__/matchers/index.js
new file mode 100644
index 00000000000..4fcde89d421
--- /dev/null
+++ b/spec/frontend/__helpers__/matchers/index.js
@@ -0,0 +1,2 @@
+export * from './to_have_sprite_icon';
+export * from './to_match_interpolated_text';
diff --git a/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js b/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js
new file mode 100644
index 00000000000..bce9d93bea8
--- /dev/null
+++ b/spec/frontend/__helpers__/matchers/to_have_sprite_icon.js
@@ -0,0 +1,36 @@
+export const toHaveSpriteIcon = (element, iconName) => {
+ if (!iconName) {
+ throw new Error('toHaveSpriteIcon is missing iconName argument!');
+ }
+
+ if (!(element instanceof HTMLElement)) {
+ throw new Error(`${element} is not a DOM element!`);
+ }
+
+ const iconReferences = [].slice.apply(element.querySelectorAll('svg use'));
+ const matchingIcon = iconReferences.find(
+ (reference) => reference.parentNode.getAttribute('data-testid') === `${iconName}-icon`,
+ );
+
+ const pass = Boolean(matchingIcon);
+
+ let message;
+ if (pass) {
+ message = `${element.outerHTML} contains the sprite icon "${iconName}"!`;
+ } else {
+ message = `${element.outerHTML} does not contain the sprite icon "${iconName}"!`;
+
+ const existingIcons = iconReferences.map((reference) => {
+ const iconUrl = reference.getAttribute('href');
+ return `"${iconUrl.replace(/^.+#/, '')}"`;
+ });
+ if (existingIcons.length > 0) {
+ message += ` (only found ${existingIcons.join(',')})`;
+ }
+ }
+
+ return {
+ pass,
+ message: () => message,
+ };
+};
diff --git a/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js b/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js
new file mode 100644
index 00000000000..4ce814a01b4
--- /dev/null
+++ b/spec/frontend/__helpers__/matchers/to_match_interpolated_text.js
@@ -0,0 +1,30 @@
+export const toMatchInterpolatedText = (received, match) => {
+ let clearReceived;
+ let clearMatch;
+
+ try {
+ clearReceived = received.replace(/\s\s+/gm, ' ').replace(/\s\./gm, '.').trim();
+ } catch (e) {
+ return { actual: received, message: 'The received value is not a string', pass: false };
+ }
+ try {
+ clearMatch = match.replace(/%{\w+}/gm, '').trim();
+ } catch (e) {
+ return { message: 'The comparator value is not a string', pass: false };
+ }
+ const pass = clearReceived === clearMatch;
+ const message = pass
+ ? () => `
+ \n\n
+ Expected: ${this.utils.printExpected(clearReceived)}
+ To not equal: ${this.utils.printReceived(clearMatch)}
+ `
+ : () =>
+ `
+ \n\n
+ Expected: ${this.utils.printExpected(clearReceived)}
+ To equal: ${this.utils.printReceived(clearMatch)}
+ `;
+
+ return { actual: received, message, pass };
+};
diff --git a/spec/frontend/__helpers__/matchers/to_match_interpolated_text_spec.js b/spec/frontend/__helpers__/matchers/to_match_interpolated_text_spec.js
new file mode 100644
index 00000000000..f6fd00011fe
--- /dev/null
+++ b/spec/frontend/__helpers__/matchers/to_match_interpolated_text_spec.js
@@ -0,0 +1,46 @@
+describe('custom matcher toMatchInterpolatedText', () => {
+ describe('malformed input', () => {
+ it.each([null, 1, Symbol, Array, Object])(
+ 'fails graciously if the expected value is %s',
+ (expected) => {
+ expect(expected).not.toMatchInterpolatedText('null');
+ },
+ );
+ });
+ describe('malformed matcher', () => {
+ it.each([null, 1, Symbol, Array, Object])(
+ 'fails graciously if the matcher is %s',
+ (matcher) => {
+ expect('null').not.toMatchInterpolatedText(matcher);
+ },
+ );
+ });
+
+ describe('positive assertion', () => {
+ it.each`
+ htmlString | templateString
+ ${'foo'} | ${'foo'}
+ ${'foo'} | ${'foo%{foo}'}
+ ${'foo '} | ${'foo'}
+ ${'foo '} | ${'foo%{foo}'}
+ ${'foo . '} | ${'foo%{foo}.'}
+ ${'foo bar . '} | ${'foo%{foo} bar.'}
+ ${'foo\n\nbar . '} | ${'foo%{foo} bar.'}
+ ${'foo bar . .'} | ${'foo%{fooStart} bar.%{fooEnd}.'}
+ `('$htmlString equals $templateString', ({ htmlString, templateString }) => {
+ expect(htmlString).toMatchInterpolatedText(templateString);
+ });
+ });
+
+ describe('negative assertion', () => {
+ it.each`
+ htmlString | templateString
+ ${'foo'} | ${'bar'}
+ ${'foo'} | ${'bar%{foo}'}
+ ${'foo'} | ${'@{lol}foo%{foo}'}
+ ${' fo o '} | ${'foo'}
+ `('$htmlString does not equal $templateString', ({ htmlString, templateString }) => {
+ expect(htmlString).not.toMatchInterpolatedText(templateString);
+ });
+ });
+});
diff --git a/spec/frontend/__helpers__/matchers_spec.js b/spec/frontend/__helpers__/matchers_spec.js
deleted file mode 100644
index dfd6f754c72..00000000000
--- a/spec/frontend/__helpers__/matchers_spec.js
+++ /dev/null
@@ -1,48 +0,0 @@
-describe('Custom jest matchers', () => {
- describe('toMatchInterpolatedText', () => {
- describe('malformed input', () => {
- it.each([null, 1, Symbol, Array, Object])(
- 'fails graciously if the expected value is %s',
- (expected) => {
- expect(expected).not.toMatchInterpolatedText('null');
- },
- );
- });
- describe('malformed matcher', () => {
- it.each([null, 1, Symbol, Array, Object])(
- 'fails graciously if the matcher is %s',
- (matcher) => {
- expect('null').not.toMatchInterpolatedText(matcher);
- },
- );
- });
-
- describe('positive assertion', () => {
- it.each`
- htmlString | templateString
- ${'foo'} | ${'foo'}
- ${'foo'} | ${'foo%{foo}'}
- ${'foo '} | ${'foo'}
- ${'foo '} | ${'foo%{foo}'}
- ${'foo . '} | ${'foo%{foo}.'}
- ${'foo bar . '} | ${'foo%{foo} bar.'}
- ${'foo\n\nbar . '} | ${'foo%{foo} bar.'}
- ${'foo bar . .'} | ${'foo%{fooStart} bar.%{fooEnd}.'}
- `('$htmlString equals $templateString', ({ htmlString, templateString }) => {
- expect(htmlString).toMatchInterpolatedText(templateString);
- });
- });
-
- describe('negative assertion', () => {
- it.each`
- htmlString | templateString
- ${'foo'} | ${'bar'}
- ${'foo'} | ${'bar%{foo}'}
- ${'foo'} | ${'@{lol}foo%{foo}'}
- ${' fo o '} | ${'foo'}
- `('$htmlString does not equal $templateString', ({ htmlString, templateString }) => {
- expect(htmlString).not.toMatchInterpolatedText(templateString);
- });
- });
- });
-});
diff --git a/spec/frontend/__helpers__/shared_test_setup.js b/spec/frontend/__helpers__/shared_test_setup.js
index 03389e16b65..7b5df18ee0f 100644
--- a/spec/frontend/__helpers__/shared_test_setup.js
+++ b/spec/frontend/__helpers__/shared_test_setup.js
@@ -8,7 +8,7 @@ import setWindowLocation from './set_window_location_helper';
import { setGlobalDateToFakeDate } from './fake_date';
import { loadHTMLFixture, setHTMLFixture } from './fixtures';
import { TEST_HOST } from './test_constants';
-import customMatchers from './matchers';
+import * as customMatchers from './matchers';
import './dom_shims';
import './jquery';
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/conan_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/conan_installation_spec.js.snap
index e9f80d5f512..8c260c0acfb 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/conan_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/conan_installation_spec.js.snap
@@ -28,9 +28,13 @@ exports[`ConanInstallation renders all the messages 1`] = `
trackingaction="copy_conan_setup_command"
trackinglabel="code_instruction"
/>
-
- <gl-sprintf-stub
- message="For more information on the Conan registry, %{linkStart}see the documentation%{linkEnd}."
- />
+ For more information on the Conan registry,
+ <gl-link-stub
+ href="/help/user/packages/conan_repository/index"
+ target="_blank"
+ >
+ see the documentation
+ </gl-link-stub>
+ .
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
index 4865b8205ab..1626d464298 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/maven_installation_spec.js.snap
@@ -64,9 +64,15 @@ exports[`MavenInstallation maven renders all the messages 1`] = `
/>
<p>
- <gl-sprintf-stub
- message="Copy and paste this inside your %{codeStart}pom.xml%{codeEnd} %{codeStart}dependencies%{codeEnd} block."
- />
+ Copy and paste this inside your
+ <code>
+ pom.xml
+ </code>
+
+ <code>
+ dependencies
+ </code>
+ block.
</p>
<code-instruction-stub
@@ -97,9 +103,11 @@ exports[`MavenInstallation maven renders all the messages 1`] = `
</h3>
<p>
- <gl-sprintf-stub
- message="If you haven't already done so, you will need to add the below to your %{codeStart}pom.xml%{codeEnd} file."
- />
+ If you haven't already done so, you will need to add the below to your
+ <code>
+ pom.xml
+ </code>
+ file.
</p>
<code-instruction-stub
@@ -127,9 +135,13 @@ exports[`MavenInstallation maven renders all the messages 1`] = `
trackingaction="copy_maven_setup_xml"
trackinglabel="code_instruction"
/>
-
- <gl-sprintf-stub
- message="For more information on the Maven registry, %{linkStart}see the documentation%{linkEnd}."
- />
+ For more information on the Maven registry,
+ <gl-link-stub
+ href="/help/user/packages/maven_repository/index"
+ target="_blank"
+ >
+ see the documentation
+ </gl-link-stub>
+ .
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/npm_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/npm_installation_spec.js.snap
index d5649e39561..16b573bb4a0 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/npm_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/npm_installation_spec.js.snap
@@ -37,9 +37,13 @@ exports[`NpmInstallation renders all the messages 1`] = `
trackingaction="copy_npm_setup_command"
trackinglabel="code_instruction"
/>
-
- <gl-sprintf-stub
- message="You may also need to setup authentication using an auth token. %{linkStart}See the documentation%{linkEnd} to find out more."
- />
+ You may also need to setup authentication using an auth token.
+ <gl-link-stub
+ href="/help/user/packages/npm_registry/index"
+ target="_blank"
+ >
+ See the documentation
+ </gl-link-stub>
+ to find out more.
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/nuget_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/nuget_installation_spec.js.snap
index 29ddd7b77ed..b1f05d7cc6d 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/nuget_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/nuget_installation_spec.js.snap
@@ -28,9 +28,13 @@ exports[`NugetInstallation renders all the messages 1`] = `
trackingaction="copy_nuget_setup_command"
trackinglabel="code_instruction"
/>
-
- <gl-sprintf-stub
- message="For more information on the NuGet registry, %{linkStart}see the documentation%{linkEnd}."
- />
+ For more information on the NuGet registry,
+ <gl-link-stub
+ href="/help/user/packages/nuget_repository/index"
+ target="_blank"
+ >
+ see the documentation
+ </gl-link-stub>
+ .
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
index 158bbbc3463..3d3e3021026 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/__snapshots__/pypi_installation_spec.js.snap
@@ -23,9 +23,11 @@ exports[`PypiInstallation renders all the messages 1`] = `
</h3>
<p>
- <gl-sprintf-stub
- message="If you haven't already done so, you will need to add the below to your %{codeStart}.pypirc%{codeEnd} file."
- />
+ If you haven't already done so, you will need to add the below to your
+ <code>
+ .pypirc
+ </code>
+ file.
</p>
<code-instruction-stub
@@ -40,9 +42,13 @@ password = <your personal access token>"
trackingaction="copy_pypi_setup_command"
trackinglabel="code_instruction"
/>
-
- <gl-sprintf-stub
- message="For more information on the PyPi registry, %{linkStart}see the documentation%{linkEnd}."
- />
+ For more information on the PyPi registry,
+ <gl-link-stub
+ href="/help/user/packages/pypi_repository/index"
+ target="_blank"
+ >
+ see the documentation
+ </gl-link-stub>
+ .
</div>
`;
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
index aedf20e873a..9906da6c0bc 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/composer_installation_spec.js
@@ -7,6 +7,7 @@ import {
TRACKING_ACTION_COPY_COMPOSER_REGISTRY_INCLUDE_COMMAND,
TRACKING_ACTION_COPY_COMPOSER_PACKAGE_INCLUDE_COMMAND,
PACKAGE_TYPE_COMPOSER,
+ COMPOSER_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
const packageEntity = { ...packageData(), packageType: PACKAGE_TYPE_COMPOSER };
@@ -24,7 +25,6 @@ describe('ComposerInstallation', () => {
function createComponent(groupListUrl = 'groupListUrl') {
wrapper = shallowMountExtended(ComposerInstallation, {
provide: {
- composerHelpPath: 'composerHelpPath',
composerConfigRepositoryName: 'composerConfigRepositoryName',
composerPath: 'composerPath',
groupListUrl,
@@ -96,7 +96,7 @@ describe('ComposerInstallation', () => {
'For more information on Composer packages in GitLab, see the documentation.',
);
expect(findHelpLink().attributes()).toMatchObject({
- href: 'composerHelpPath',
+ href: COMPOSER_HELP_PATH,
target: '_blank',
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
index 6b642cc21b7..c5a2fb6606b 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/conan_installation_spec.js
@@ -1,8 +1,12 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { packageData } from 'jest/packages_and_registries/package_registry/mock_data';
import ConanInstallation from '~/packages_and_registries/package_registry/components/details/conan_installation.vue';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
-import { PACKAGE_TYPE_CONAN } from '~/packages_and_registries/package_registry/constants';
+import {
+ PACKAGE_TYPE_CONAN,
+ CONAN_HELP_PATH,
+} from '~/packages_and_registries/package_registry/constants';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
const packageEntity = { ...packageData(), packageType: PACKAGE_TYPE_CONAN };
@@ -12,16 +16,19 @@ describe('ConanInstallation', () => {
const findCodeInstructions = () => wrapper.findAllComponents(CodeInstructions);
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
+ const findSetupDocsLink = () => wrapper.findComponent(GlLink);
function createComponent() {
wrapper = shallowMountExtended(ConanInstallation, {
provide: {
- conanHelpPath: 'conanHelpPath',
conanPath: 'conanPath',
},
propsData: {
packageEntity,
},
+ stubs: {
+ GlSprintf,
+ },
});
}
@@ -61,5 +68,12 @@ describe('ConanInstallation', () => {
'conan remote add gitlab conanPath',
);
});
+
+ it('has a link to the docs', () => {
+ expect(findSetupDocsLink().attributes()).toMatchObject({
+ href: CONAN_HELP_PATH,
+ target: '_blank',
+ });
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
index eed7e903833..dd74d106e83 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/maven_installation_spec.js
@@ -1,3 +1,4 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -16,6 +17,7 @@ import {
TRACKING_ACTION_COPY_KOTLIN_INSTALL_COMMAND,
TRACKING_ACTION_COPY_KOTLIN_ADD_TO_SOURCE_COMMAND,
PACKAGE_TYPE_MAVEN,
+ MAVEN_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
@@ -28,7 +30,6 @@ describe('MavenInstallation', () => {
metadata: mavenMetadata(),
};
- const mavenHelpPath = 'mavenHelpPath';
const mavenPath = 'mavenPath';
const xmlCodeBlock = `<dependency>
@@ -64,11 +65,11 @@ describe('MavenInstallation', () => {
const findCodeInstructions = () => wrapper.findAllComponents(CodeInstructions);
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
+ const findSetupDocsLink = () => wrapper.findComponent(GlLink);
function createComponent({ data = {} } = {}) {
wrapper = shallowMountExtended(MavenInstallation, {
provide: {
- mavenHelpPath,
mavenPath,
},
propsData: {
@@ -77,6 +78,9 @@ describe('MavenInstallation', () => {
data() {
return data;
},
+ stubs: {
+ GlSprintf,
+ },
});
}
@@ -148,6 +152,13 @@ describe('MavenInstallation', () => {
trackingAction: TRACKING_ACTION_COPY_MAVEN_SETUP,
});
});
+
+ it('has a setup link', () => {
+ expect(findSetupDocsLink().attributes()).toMatchObject({
+ href: MAVEN_HELP_PATH,
+ target: '_blank',
+ });
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
index b89410ede13..98204160110 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/npm_installation_spec.js
@@ -1,4 +1,4 @@
-import { GlFormRadioGroup } from '@gitlab/ui';
+import { GlLink, GlSprintf, GlFormRadioGroup } from '@gitlab/ui';
import { nextTick } from 'vue';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
@@ -15,6 +15,7 @@ import {
YARN_PACKAGE_MANAGER,
PROJECT_PACKAGE_ENDPOINT_TYPE,
INSTANCE_PACKAGE_ENDPOINT_TYPE,
+ NPM_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
@@ -29,11 +30,11 @@ describe('NpmInstallation', () => {
const findCodeInstructions = () => wrapper.findAllComponents(CodeInstructions);
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
const findEndPointTypeSector = () => wrapper.findComponent(GlFormRadioGroup);
+ const findSetupDocsLink = () => wrapper.findComponent(GlLink);
function createComponent({ data = {} } = {}) {
wrapper = shallowMountExtended(NpmInstallation, {
provide: {
- npmHelpPath: 'npmHelpPath',
npmPath: 'npmPath',
npmProjectPath: 'npmProjectPath',
},
@@ -43,6 +44,7 @@ describe('NpmInstallation', () => {
data() {
return data;
},
+ stubs: { GlSprintf },
});
}
@@ -58,6 +60,13 @@ describe('NpmInstallation', () => {
expect(wrapper.element).toMatchSnapshot();
});
+ it('has a setup link', () => {
+ expect(findSetupDocsLink().attributes()).toMatchObject({
+ href: NPM_HELP_PATH,
+ target: '_blank',
+ });
+ });
+
describe('endpoint type selector', () => {
it('has the endpoint type selector', () => {
expect(findEndPointTypeSector().exists()).toBe(true);
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
index c48a3f07299..204ed702a05 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/nuget_installation_spec.js
@@ -1,3 +1,4 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { packageData } from 'jest/packages_and_registries/package_registry/mock_data';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
@@ -6,6 +7,7 @@ import {
TRACKING_ACTION_COPY_NUGET_INSTALL_COMMAND,
TRACKING_ACTION_COPY_NUGET_SETUP_COMMAND,
PACKAGE_TYPE_NUGET,
+ NUGET_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
import CodeInstructions from '~/vue_shared/components/registry/code_instruction.vue';
@@ -20,16 +22,17 @@ describe('NugetInstallation', () => {
const findCodeInstructions = () => wrapper.findAllComponents(CodeInstructions);
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
+ const findSetupDocsLink = () => wrapper.findComponent(GlLink);
function createComponent() {
wrapper = shallowMountExtended(NugetInstallation, {
provide: {
- nugetHelpPath: 'nugetHelpPath',
nugetPath: 'nugetPath',
},
propsData: {
packageEntity,
},
+ stubs: { GlSprintf },
});
}
@@ -71,5 +74,12 @@ describe('NugetInstallation', () => {
trackingAction: TRACKING_ACTION_COPY_NUGET_SETUP_COMMAND,
});
});
+
+ it('it has docs link', () => {
+ expect(findSetupDocsLink().attributes()).toMatchObject({
+ href: NUGET_HELP_PATH,
+ target: '_blank',
+ });
+ });
});
});
diff --git a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
index 410c1b65348..5714a567e14 100644
--- a/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
+++ b/spec/frontend/packages_and_registries/package_registry/components/details/pypi_installation_spec.js
@@ -1,3 +1,4 @@
+import { GlLink, GlSprintf } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import { packageData } from 'jest/packages_and_registries/package_registry/mock_data';
import InstallationTitle from '~/packages_and_registries/package_registry/components/details/installation_title.vue';
@@ -6,6 +7,7 @@ import {
PACKAGE_TYPE_PYPI,
TRACKING_ACTION_COPY_PIP_INSTALL_COMMAND,
TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
+ PYPI_HELP_PATH,
} from '~/packages_and_registries/package_registry/constants';
const packageEntity = { ...packageData(), packageType: PACKAGE_TYPE_PYPI };
@@ -23,17 +25,20 @@ password = <your personal access token>`;
const setupInstruction = () => wrapper.findByTestId('pypi-setup-content');
const findInstallationTitle = () => wrapper.findComponent(InstallationTitle);
+ const findSetupDocsLink = () => wrapper.findComponent(GlLink);
function createComponent() {
wrapper = shallowMountExtended(PypiInstallation, {
provide: {
- pypiHelpPath: 'pypiHelpPath',
pypiPath: 'pypiPath',
pypiSetupPath: 'pypiSetupPath',
},
propsData: {
packageEntity,
},
+ stubs: {
+ GlSprintf,
+ },
});
}
@@ -76,5 +81,12 @@ password = <your personal access token>`;
trackingAction: TRACKING_ACTION_COPY_PYPI_SETUP_COMMAND,
});
});
+
+ it('has a link to the docs', () => {
+ expect(findSetupDocsLink().attributes()).toMatchObject({
+ href: PYPI_HELP_PATH,
+ target: '_blank',
+ });
+ });
});
});
diff --git a/spec/lib/gitlab/regex_spec.rb b/spec/lib/gitlab/regex_spec.rb
index 83f85cc73d0..8d67350f0f3 100644
--- a/spec/lib/gitlab/regex_spec.rb
+++ b/spec/lib/gitlab/regex_spec.rb
@@ -433,6 +433,7 @@ RSpec.describe Gitlab::Regex do
describe '.nuget_version_regex' do
subject { described_class.nuget_version_regex }
+ it { is_expected.to match('1.2') }
it { is_expected.to match('1.2.3') }
it { is_expected.to match('1.2.3.4') }
it { is_expected.to match('1.2.3.4-stable.1') }
@@ -440,7 +441,6 @@ RSpec.describe Gitlab::Regex do
it { is_expected.to match('1.2.3-alpha.3') }
it { is_expected.to match('1.0.7+r3456') }
it { is_expected.not_to match('1') }
- it { is_expected.not_to match('1.2') }
it { is_expected.not_to match('1./2.3') }
it { is_expected.not_to match('../../../../../1.2.3') }
it { is_expected.not_to match('%2e%2e%2f1.2.3') }
diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb
index afea20b31b9..81728432a30 100644
--- a/spec/models/application_setting_spec.rb
+++ b/spec/models/application_setting_spec.rb
@@ -1244,7 +1244,7 @@ RSpec.describe ApplicationSetting do
end
end
- describe '#static_objects_external_storage_auth_token=' do
+ describe '#static_objects_external_storage_auth_token=', :aggregate_failures do
subject { setting.static_objects_external_storage_auth_token = token }
let(:token) { 'Test' }
@@ -1268,5 +1268,20 @@ RSpec.describe ApplicationSetting do
expect(setting.static_objects_external_storage_auth_token).to be_nil
end
end
+
+ context 'with plaintext token only' do
+ let(:token) { '' }
+
+ it 'ignores the plaintext token' do
+ subject
+
+ ApplicationSetting.update_all(static_objects_external_storage_auth_token: 'Test')
+
+ setting.reload
+ expect(setting[:static_objects_external_storage_auth_token]).to be_nil
+ expect(setting[:static_objects_external_storage_auth_token_encrypted]).to be_nil
+ expect(setting.static_objects_external_storage_auth_token).to be_nil
+ end
+ end
end
end
diff --git a/spec/models/packages/package_spec.rb b/spec/models/packages/package_spec.rb
index 923ec173368..122340f7bec 100644
--- a/spec/models/packages/package_spec.rb
+++ b/spec/models/packages/package_spec.rb
@@ -413,9 +413,17 @@ RSpec.describe Packages::Package, type: :model do
it_behaves_like 'validating version to be SemVer compliant for', :terraform_module_package
context 'nuget package' do
- it_behaves_like 'validating version to be SemVer compliant for', :nuget_package
+ subject { build_stubbed(:nuget_package) }
+ it { is_expected.to allow_value('1.2').for(:version) }
+ it { is_expected.to allow_value('1.2.3').for(:version) }
it { is_expected.to allow_value('1.2.3.4').for(:version) }
+ it { is_expected.to allow_value('1.2.3-beta').for(:version) }
+ it { is_expected.to allow_value('1.2.3-alpha.3').for(:version) }
+ it { is_expected.not_to allow_value('1').for(:version) }
+ it { is_expected.not_to allow_value('1./2.3').for(:version) }
+ it { is_expected.not_to allow_value('../../../../../1.2.3').for(:version) }
+ it { is_expected.not_to allow_value('%2e%2e%2f1.2.3').for(:version) }
end
end