Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
7de415dd5f
commit
bba263d1a3
|
|
@ -67,6 +67,10 @@ start-as-if-foss:
|
|||
variables:
|
||||
START_AS_IF_FOSS: $START_AS_IF_FOSS
|
||||
RUBY_VERSION: $RUBY_VERSION
|
||||
# Fake merge request variables to make `detect-tests` work from FOSS
|
||||
CI_MERGE_REQUEST_PROJECT_PATH: $CI_MERGE_REQUEST_PROJECT_PATH
|
||||
CI_MERGE_REQUEST_IID: $CI_MERGE_REQUEST_IID
|
||||
# Enabling each individual jobs
|
||||
ENABLE_RSPEC: $ENABLE_RSPEC
|
||||
ENABLE_RSPEC_FAST_SPEC_HELPER: $ENABLE_RSPEC_FAST_SPEC_HELPER
|
||||
ENABLE_RSPEC_PRAEFECT: $ENABLE_RSPEC_PRAEFECT
|
||||
|
|
@ -85,11 +89,13 @@ start-as-if-foss:
|
|||
ENABLE_COMPILE_STORYBOOK: $ENABLE_COMPILE_STORYBOOK
|
||||
ENABLE_COMPILE_TEST_ASSETS: $ENABLE_COMPILE_TEST_ASSETS
|
||||
ENABLE_CACHE_ASSETS: $ENABLE_CACHE_ASSETS
|
||||
ENABLE_DETECT_TESTS: $ENABLE_DETECT_TESTS
|
||||
ENABLE_ESLINT: $ENABLE_ESLINT
|
||||
ENABLE_GENERATE_APOLLO_GRAPHQL_SCHEMA: $ENABLE_GENERATE_APOLLO_GRAPHQL_SCHEMA
|
||||
ENABLE_GRAPHQL_SCHEMA_DUMP: $ENABLE_GRAPHQL_SCHEMA_DUMP
|
||||
ENABLE_JEST: $ENABLE_JEST
|
||||
ENABLE_JEST_INTEGRATION: $ENABLE_JEST_INTEGRATION
|
||||
ENABLE_RUBOCOP: $ENABLE_RUBOCOP
|
||||
ENABLE_QA_INTERNAL: $ENABLE_QA_INTERNAL
|
||||
ENABLE_QA_SELECTORS: $ENABLE_QA_SELECTORS
|
||||
ENABLE_STATIC_ANALYSIS: $ENABLE_STATIC_ANALYSIS
|
||||
|
|
|
|||
|
|
@ -2205,6 +2205,7 @@
|
|||
|
||||
.rails:rules:detect-tests:
|
||||
rules:
|
||||
- if: '$ENABLE_DETECT_TESTS == "true"'
|
||||
- <<: *if-merge-request-labels-run-all-rspec
|
||||
- <<: *if-merge-request
|
||||
changes: *code-backstage-qa-patterns
|
||||
|
|
@ -2347,6 +2348,7 @@
|
|||
|
||||
.static-analysis:rules:rubocop:
|
||||
rules:
|
||||
- if: '$ENABLE_RUBOCOP == "true"'
|
||||
- <<: *if-default-refs
|
||||
changes: *rubocop-patterns
|
||||
variables:
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -528,7 +528,7 @@ group :test do
|
|||
# Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527
|
||||
gem 'derailed_benchmarks', require: false # rubocop:todo Gemfile/MissingFeatureCategory
|
||||
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.21.0', require: false, feature_category: :tooling
|
||||
gem 'gitlab_quality-test_tooling', '~> 1.21.1', require: false, feature_category: :tooling
|
||||
end
|
||||
|
||||
gem 'octokit', '~> 8.0', feature_category: :importers
|
||||
|
|
|
|||
|
|
@ -226,7 +226,7 @@
|
|||
{"name":"gitlab-styles","version":"11.0.0","platform":"ruby","checksum":"0dd8ec066ce9955ac51d3616c6bfded30f75bb526f39ff392ece6f43d5b9406b"},
|
||||
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},
|
||||
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
|
||||
{"name":"gitlab_quality-test_tooling","version":"1.21.0","platform":"ruby","checksum":"b83555c80cffe5ef2709eb6e8674a4942c1bd44a47abea83effc19908d5a0b2c"},
|
||||
{"name":"gitlab_quality-test_tooling","version":"1.21.1","platform":"ruby","checksum":"83f2a115d21e921b0b540ba87765cad98f0766178244abc3d06d18dd1bd58ebc"},
|
||||
{"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"},
|
||||
{"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"},
|
||||
{"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"},
|
||||
|
|
|
|||
|
|
@ -741,7 +741,7 @@ GEM
|
|||
omniauth (>= 1.3, < 3)
|
||||
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
|
||||
rubyntlm (~> 0.5)
|
||||
gitlab_quality-test_tooling (1.21.0)
|
||||
gitlab_quality-test_tooling (1.21.1)
|
||||
activesupport (>= 6.1, < 7.2)
|
||||
amatch (~> 0.4.1)
|
||||
gitlab (~> 4.19)
|
||||
|
|
@ -1929,7 +1929,7 @@ DEPENDENCIES
|
|||
gitlab-utils!
|
||||
gitlab_chronic_duration (~> 0.12)
|
||||
gitlab_omniauth-ldap (~> 2.2.0)
|
||||
gitlab_quality-test_tooling (~> 1.21.0)
|
||||
gitlab_quality-test_tooling (~> 1.21.1)
|
||||
gon (~> 6.4.0)
|
||||
google-apis-androidpublisher_v3 (~> 0.34.0)
|
||||
google-apis-cloudbilling_v1 (~> 0.21.0)
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export default () => {
|
|||
expirationPolicy,
|
||||
isGroupPage,
|
||||
isAdmin,
|
||||
isMetadataDatabaseEnabled,
|
||||
showCleanupPolicyLink,
|
||||
showContainerRegistrySettings,
|
||||
showUnfinishedTagCleanupCallout,
|
||||
|
|
@ -74,6 +75,7 @@ export default () => {
|
|||
showUnfinishedTagCleanupCallout: parseBoolean(showUnfinishedTagCleanupCallout),
|
||||
connectionError: parseBoolean(connectionError),
|
||||
invalidPathError: parseBoolean(invalidPathError),
|
||||
isMetadataDatabaseEnabled: parseBoolean(isMetadataDatabaseEnabled),
|
||||
},
|
||||
/* eslint-disable @gitlab/require-i18n-strings */
|
||||
dockerBuildCommand: `docker build -t ${config.repositoryUrl} .`,
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@ import { fetchPolicies } from '~/lib/graphql';
|
|||
import Tracking from '~/tracking';
|
||||
import PersistedPagination from '~/packages_and_registries/shared/components/persisted_pagination.vue';
|
||||
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
|
||||
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
|
||||
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
import DeleteImage from '../components/delete_image.vue';
|
||||
import RegistryHeader from '../components/list_page/registry_header.vue';
|
||||
import DeleteModal from '../components/delete_modal.vue';
|
||||
|
||||
import {
|
||||
DELETE_IMAGE_SUCCESS_MESSAGE,
|
||||
DELETE_IMAGE_ERROR_MESSAGE,
|
||||
|
|
@ -64,6 +64,7 @@ export default {
|
|||
GlSkeletonLoader,
|
||||
RegistryHeader,
|
||||
DeleteImage,
|
||||
MetadataDatabaseAlert,
|
||||
PersistedPagination,
|
||||
PersistedSearch,
|
||||
},
|
||||
|
|
@ -233,6 +234,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<div>
|
||||
<metadata-database-alert v-if="!config.isMetadataDatabaseEnabled" />
|
||||
<gl-alert
|
||||
v-if="showDeleteAlert"
|
||||
:variant="deleteAlertType"
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import {
|
|||
import ContainerExpirationPolicy from '~/packages_and_registries/settings/project/components/container_expiration_policy.vue';
|
||||
import ContainerProtectionRules from '~/packages_and_registries/settings/project/components/container_protection_rules.vue';
|
||||
import PackagesCleanupPolicy from '~/packages_and_registries/settings/project/components/packages_cleanup_policy.vue';
|
||||
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
|
||||
export default {
|
||||
|
|
@ -20,6 +21,7 @@ export default {
|
|||
'ee_component/packages_and_registries/settings/project/components/dependency_proxy_packages_settings.vue'
|
||||
),
|
||||
GlAlert,
|
||||
MetadataDatabaseAlert,
|
||||
PackagesCleanupPolicy,
|
||||
PackagesProtectionRules: () =>
|
||||
import('~/packages_and_registries/settings/project/components/packages_protection_rules.vue'),
|
||||
|
|
@ -29,6 +31,7 @@ export default {
|
|||
'showContainerRegistrySettings',
|
||||
'showPackageRegistrySettings',
|
||||
'showDependencyProxySettings',
|
||||
'isContainerRegistryMetadataDatabaseEnabled',
|
||||
],
|
||||
i18n: {
|
||||
UPDATE_SETTINGS_SUCCESS_MESSAGE,
|
||||
|
|
@ -67,6 +70,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<div data-testid="packages-and-registries-project-settings">
|
||||
<metadata-database-alert v-if="!isContainerRegistryMetadataDatabaseEnabled" class="gl-mt-5" />
|
||||
<gl-alert
|
||||
v-if="showAlert"
|
||||
variant="success"
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ export default () => {
|
|||
cleanupSettingsPath,
|
||||
tagsRegexHelpPagePath,
|
||||
helpPagePath,
|
||||
isContainerRegistryMetadataDatabaseEnabled,
|
||||
showContainerRegistrySettings,
|
||||
showPackageRegistrySettings,
|
||||
showDependencyProxySettings,
|
||||
|
|
@ -39,6 +40,9 @@ export default () => {
|
|||
cleanupSettingsPath,
|
||||
tagsRegexHelpPagePath,
|
||||
helpPagePath,
|
||||
isContainerRegistryMetadataDatabaseEnabled: parseBoolean(
|
||||
isContainerRegistryMetadataDatabaseEnabled,
|
||||
),
|
||||
showContainerRegistrySettings: parseBoolean(showContainerRegistrySettings),
|
||||
showPackageRegistrySettings: parseBoolean(showPackageRegistrySettings),
|
||||
showDependencyProxySettings: parseBoolean(showDependencyProxySettings),
|
||||
|
|
|
|||
|
|
@ -0,0 +1,47 @@
|
|||
<script>
|
||||
import { GlAlert, GlLink, GlSprintf } from '@gitlab/ui';
|
||||
import { getCookie, parseBoolean, setCookie } from '~/lib/utils/common_utils';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
const HIDE_METADATA_DATABASE_ALERT_COOKIE = 'hide_metadata_database_alert';
|
||||
|
||||
export default {
|
||||
name: 'ContainerRegistryMetadataDatabaseAlert',
|
||||
components: {
|
||||
GlAlert,
|
||||
GlLink,
|
||||
GlSprintf,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showAlert: !parseBoolean(getCookie(HIDE_METADATA_DATABASE_ALERT_COOKIE)),
|
||||
};
|
||||
},
|
||||
metadataDatabaseHelpPagePath: helpPagePath(
|
||||
'administration/packages/container_registry_metadata_database',
|
||||
),
|
||||
methods: {
|
||||
hideAlert() {
|
||||
this.showAlert = false;
|
||||
setCookie(HIDE_METADATA_DATABASE_ALERT_COOKIE, 'true');
|
||||
this.$emit('dismiss');
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<gl-alert v-if="showAlert" class="gl-mt-5" @dismiss="hideAlert">
|
||||
<gl-sprintf
|
||||
:message="
|
||||
s__(
|
||||
'ContainerRegistry|The %{linkStart}next-generation container registry%{linkEnd} is now available for upgrade and testing on self-managed instances as a Beta feature. This upgraded registry supports online garbage collection, and has significant performance and reliability improvements.',
|
||||
)
|
||||
"
|
||||
>
|
||||
<template #link="{ content }">
|
||||
<gl-link :href="$options.metadataDatabaseHelpPagePath"> {{ content }}</gl-link>
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</gl-alert>
|
||||
</template>
|
||||
|
|
@ -21,7 +21,13 @@ module Ci
|
|||
title = s_("Runners|Runner has never contacted this instance")
|
||||
icon = 'warning-solid'
|
||||
when :offline
|
||||
title = s_("Runners|Runner is offline; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) }
|
||||
title =
|
||||
if contacted_at
|
||||
s_("Runners|Runner is offline; last contact was %{runner_contact} ago") % { runner_contact: time_ago_in_words(contacted_at) }
|
||||
else
|
||||
s_("Runners|Runner is offline; it has never contacted this instance")
|
||||
end
|
||||
|
||||
icon = 'status-waiting'
|
||||
span_class = 'gl-text-gray-500'
|
||||
when :stale
|
||||
|
|
|
|||
|
|
@ -80,27 +80,28 @@ module PackagesHelper
|
|||
Ability.allowed?(current_user, :destroy_package, group)
|
||||
end
|
||||
|
||||
def cleanup_settings_data
|
||||
def cleanup_settings_data(project)
|
||||
{
|
||||
project_id: @project.id,
|
||||
project_path: @project.full_path,
|
||||
project_id: project.id,
|
||||
project_path: project.full_path,
|
||||
cadence_options: cadence_options.to_json,
|
||||
keep_n_options: keep_n_options.to_json,
|
||||
older_than_options: older_than_options.to_json,
|
||||
is_admin: current_user&.admin.to_s,
|
||||
admin_settings_path: ci_cd_admin_application_settings_path(anchor: 'js-registry-settings'),
|
||||
project_settings_path: project_settings_packages_and_registries_path(@project),
|
||||
project_settings_path: project_settings_packages_and_registries_path(project),
|
||||
enable_historic_entries: container_expiration_policies_historic_entry_enabled?.to_s,
|
||||
help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'cleanup-policy'),
|
||||
show_cleanup_policy_link: show_cleanup_policy_link(@project).to_s,
|
||||
show_cleanup_policy_link: show_cleanup_policy_link(project).to_s,
|
||||
tags_regex_help_page_path: help_page_path('user/packages/container_registry/reduce_container_registry_storage', anchor: 'regex-pattern-examples')
|
||||
}
|
||||
end
|
||||
|
||||
def settings_data(project)
|
||||
cleanup_settings_data.merge(
|
||||
cleanup_settings_data(project).merge(
|
||||
show_container_registry_settings: show_container_registry_settings(project).to_s,
|
||||
show_package_registry_settings: show_package_registry_settings(project).to_s,
|
||||
is_container_registry_metadata_database_enabled: (show_container_registry_settings(project) && ContainerRegistry::GitlabApiClient.supports_gitlab_api?).to_s,
|
||||
cleanup_settings_path: cleanup_image_tags_project_settings_packages_and_registries_path(project)
|
||||
)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1413,8 +1413,6 @@ module Ci
|
|||
end
|
||||
|
||||
def cancel_async_on_job_failure
|
||||
return unless Feature.enabled?(:auto_cancel_pipeline_on_job_failure, project)
|
||||
|
||||
case auto_cancel_on_job_failure
|
||||
when 'none'
|
||||
# no-op
|
||||
|
|
|
|||
|
|
@ -34,6 +34,11 @@ module Ci
|
|||
project_type: 3
|
||||
}
|
||||
|
||||
enum creation_state: {
|
||||
started: 0,
|
||||
finished: 100
|
||||
}, _suffix: true
|
||||
|
||||
enum registration_type: {
|
||||
registration_token: 0,
|
||||
authenticated_user: 1
|
||||
|
|
@ -454,7 +459,11 @@ module Ci
|
|||
#
|
||||
::Gitlab::Database::LoadBalancing::Session.without_sticky_writes do
|
||||
values = values&.slice(:version, :revision, :platform, :architecture, :ip_address, :config, :executor) || {}
|
||||
values[:contacted_at] = Time.current if update_contacted_at
|
||||
|
||||
if update_contacted_at
|
||||
values.merge!(contacted_at: Time.current, creation_state: :finished)
|
||||
end
|
||||
|
||||
if values.include?(:executor)
|
||||
values[:executor_type] = EXECUTOR_NAME_TO_TYPES.fetch(values.delete(:executor), :unknown)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -17,6 +17,11 @@ module Ci
|
|||
|
||||
belongs_to :runner
|
||||
|
||||
enum creation_state: {
|
||||
started: 0,
|
||||
finished: 100
|
||||
}, _suffix: true
|
||||
|
||||
has_many :runner_manager_builds, inverse_of: :runner_manager, foreign_key: :runner_machine_id,
|
||||
class_name: 'Ci::RunnerManagerBuild'
|
||||
has_many :builds, through: :runner_manager_builds, class_name: 'Ci::Build'
|
||||
|
|
@ -109,7 +114,9 @@ module Ci
|
|||
#
|
||||
::Gitlab::Database::LoadBalancing::Session.without_sticky_writes do
|
||||
values = values&.slice(:version, :revision, :platform, :architecture, :ip_address, :config, :executor) || {}
|
||||
values[:contacted_at] = Time.current if update_contacted_at
|
||||
|
||||
values.merge!(contacted_at: Time.current, creation_state: :finished) if update_contacted_at
|
||||
|
||||
if values.include?(:executor)
|
||||
values[:executor_type] = Ci::Runner::EXECUTOR_NAME_TO_TYPES.fetch(values.delete(:executor), :unknown)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ module Ci
|
|||
|
||||
def status
|
||||
return :stale if stale?
|
||||
return :never_contacted unless contacted_at
|
||||
return :never_contacted unless finished_creation_state?
|
||||
|
||||
online? ? :online : :offline
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,5 +3,13 @@
|
|||
module Achievements
|
||||
class AchievementPolicy < ::BasePolicy
|
||||
delegate { @subject.namespace }
|
||||
|
||||
condition(:achievement_recipient, scope: :subject) do
|
||||
@user && @user.user_achievements.any? { |user_achievement| user_achievement.achievement_id == @subject.id }
|
||||
end
|
||||
|
||||
rule { achievement_recipient }.policy do
|
||||
enable :read_achievement
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,14 +2,15 @@
|
|||
|
||||
module Achievements
|
||||
class UserAchievementPolicy < ::BasePolicy
|
||||
delegate { @subject.achievement }
|
||||
delegate { @subject.achievement.namespace }
|
||||
delegate { @subject.user }
|
||||
|
||||
condition(:user_is_owner) { @subject.user == @user }
|
||||
condition(:user_is_recipient) { @subject.user == @user }
|
||||
|
||||
rule { can?(:read_user_profile) | can?(:admin_achievement) }.enable :read_user_achievement
|
||||
|
||||
rule { user_is_owner }.enable :update_owned_user_achievement
|
||||
rule { user_is_recipient }.enable :update_owned_user_achievement
|
||||
|
||||
rule { can?(:update_owned_user_achievement) }.enable :update_user_achievement
|
||||
|
||||
|
|
|
|||
|
|
@ -165,16 +165,23 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy
|
|||
enable :read_namespace
|
||||
end
|
||||
|
||||
rule { achievements_enabled }.policy do
|
||||
rule { ~achievements_enabled }.policy do
|
||||
prevent :read_achievement
|
||||
prevent :admin_achievement
|
||||
prevent :award_achievement
|
||||
prevent :destroy_user_achievement
|
||||
end
|
||||
|
||||
rule { can?(:read_group) }.policy do
|
||||
enable :read_achievement
|
||||
end
|
||||
|
||||
rule { can?(:maintainer_access) & achievements_enabled }.policy do
|
||||
rule { can?(:maintainer_access) }.policy do
|
||||
enable :admin_achievement
|
||||
enable :award_achievement
|
||||
end
|
||||
|
||||
rule { can?(:owner_access) & achievements_enabled }.policy do
|
||||
rule { can?(:owner_access) }.policy do
|
||||
enable :destroy_user_achievement
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -19,4 +19,5 @@
|
|||
invalid_path_error: (!!@invalid_path_error).to_s,
|
||||
user_callouts_path: callouts_path,
|
||||
user_callout_id: Users::CalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
|
||||
is_metadata_database_enabled: ContainerRegistry::GitlabApiClient.supports_gitlab_api?.to_s,
|
||||
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s } }
|
||||
|
|
|
|||
|
|
@ -5,9 +5,9 @@
|
|||
- if total > 0
|
||||
- final_text = n_("%d approver", "%d approvers", total) % total
|
||||
- final_self_text = n_("%d approver (you've approved)", "%d approvers (you've approved)", total) % total
|
||||
- approval_tooltip = self_approved ? final_self_text : final_text
|
||||
- approval_icon = 'check'
|
||||
- badge_variant = :success
|
||||
- badge_label = _("Approved")
|
||||
|
||||
- approval_icon = sprite_icon((self_approved ? 'approval-solid' : 'approval'), css_class: 'align-middle')
|
||||
|
||||
%li.gl-display-none.gl-sm-display-inline-block.has-tooltip.text-success{ title: self_approved ? final_self_text : final_text }
|
||||
= approval_icon
|
||||
= _("Approved")
|
||||
%li.gl-display-flex= render Pajamas::BadgeComponent.new(badge_label, size: 'sm', variant: badge_variant, icon: approval_icon, title: approval_tooltip, class: 'has-tooltip', data: { 'testid': 'mr-appovals' })
|
||||
|
|
|
|||
|
|
@ -24,4 +24,5 @@
|
|||
invalid_path_error: (!!@invalid_path_error).to_s,
|
||||
user_callouts_path: callouts_path,
|
||||
user_callout_id: Users::CalloutsHelper::UNFINISHED_TAG_CLEANUP_CALLOUT,
|
||||
is_metadata_database_enabled: ContainerRegistry::GitlabApiClient.supports_gitlab_api?.to_s,
|
||||
show_unfinished_tag_cleanup_callout: show_unfinished_tag_cleanup_callout?.to_s, } }
|
||||
|
|
|
|||
|
|
@ -2,4 +2,4 @@
|
|||
- breadcrumb_title s_('ContainerRegistry|Cleanup policies')
|
||||
- page_title s_('ContainerRegistry|Cleanup policies'), _('Packages and registries settings')
|
||||
|
||||
#js-registry-settings-cleanup-image-tags{ data: cleanup_settings_data }
|
||||
#js-registry-settings-cleanup-image-tags{ data: cleanup_settings_data(@project) }
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: auto_cancel_pipeline_on_job_failure
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/137815
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433163
|
||||
milestone: '16.7'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
---
|
||||
name: ci_rule_exists_extension_optimization
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/227632
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143056
|
||||
rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17531
|
||||
milestone: '16.9'
|
||||
group: group::pipeline authoring
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -791,6 +791,8 @@
|
|||
- 1
|
||||
- - vulnerabilities_statistics_adjustment
|
||||
- 1
|
||||
- - vulnerabilities_update_archived_attribute_of_vulnerability_reads
|
||||
- 1
|
||||
- - vulnerabilities_update_namespace_ids_of_vulnerability_reads
|
||||
- 1
|
||||
- - vulnerability_exports_export
|
||||
|
|
@ -813,6 +815,8 @@
|
|||
- 1
|
||||
- - work_items_rolledup_dates_update_rolledup_dates
|
||||
- 1
|
||||
- - work_items_rolledup_dates_update_rolledup_dates_event_handler
|
||||
- 1
|
||||
- - work_items_update_parent_objectives_progress
|
||||
- 1
|
||||
- - work_items_validate_epic_work_item_sync
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian registry group-level architectures
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51265
|
||||
milestone: '13.8'
|
||||
gitlab_schema: gitlab_main
|
||||
gitlab_schema: gitlab_main_cell
|
||||
allow_cross_joins:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_transactions:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_foreign_keys:
|
||||
- gitlab_main_clusterwide
|
||||
desired_sharding_key:
|
||||
group_id:
|
||||
references: namespaces
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: distribution_id
|
||||
table: packages_debian_group_distributions
|
||||
sharding_key: group_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian package group-level distribution components
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51732
|
||||
milestone: '13.9'
|
||||
gitlab_schema: gitlab_main
|
||||
gitlab_schema: gitlab_main_cell
|
||||
allow_cross_joins:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_transactions:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_foreign_keys:
|
||||
- gitlab_main_clusterwide
|
||||
desired_sharding_key:
|
||||
group_id:
|
||||
references: namespaces
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: distribution_id
|
||||
table: packages_debian_group_distributions
|
||||
sharding_key: group_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -7,4 +7,19 @@ feature_categories:
|
|||
description: Debian group-level distribution keys
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60993
|
||||
milestone: '14.0'
|
||||
gitlab_schema: gitlab_main
|
||||
gitlab_schema: gitlab_main_cell
|
||||
allow_cross_joins:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_transactions:
|
||||
- gitlab_main_clusterwide
|
||||
allow_cross_foreign_keys:
|
||||
- gitlab_main_clusterwide
|
||||
desired_sharding_key:
|
||||
group_id:
|
||||
references: namespaces
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: distribution_id
|
||||
table: packages_debian_group_distributions
|
||||
sharding_key: group_id
|
||||
belongs_to: distribution
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ReplaceEpicsFkOnParentId < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
milestone '16.11'
|
||||
|
||||
NEW_FK_NAME = 'fk_epics_on_parent_id_with_on_delete_nullify'
|
||||
|
||||
def up
|
||||
# This will replace the existing fk_25b99c1be3
|
||||
add_concurrent_foreign_key(
|
||||
:epics,
|
||||
:epics,
|
||||
column: :parent_id,
|
||||
on_delete: :nullify,
|
||||
validate: false,
|
||||
name: NEW_FK_NAME
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists(
|
||||
:epics,
|
||||
column: :parent_id,
|
||||
on_delete: :nullify,
|
||||
name: NEW_FK_NAME
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ValidateEpicsFkOnParentIdWithOnDeleteNullify < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.11'
|
||||
|
||||
FK_NAME = 'fk_epics_on_parent_id_with_on_delete_nullify'
|
||||
|
||||
# foreign key added in db/migrate/20240403113607_replace_epics_fk_on_parent_id.rb
|
||||
def up
|
||||
validate_foreign_key(:epics, :parent_id, name: FK_NAME)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveFkEpicsParentId < Gitlab::Database::Migration[2.2]
|
||||
disable_ddl_transaction!
|
||||
|
||||
milestone '16.11'
|
||||
|
||||
FK_NAME = :fk_25b99c1be3
|
||||
|
||||
# new foreign key added in db/migrate/20240403113607_replace_epics_fk_on_parent_id.rb
|
||||
# and validated in db/migrate/20240403114400_validate_epics_fk_on_parent_id_with_on_delete_nullify.rb
|
||||
def up
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists(:epics, column: :parent_id, on_delete: :cascade, name: FK_NAME)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# Validation is skipped here, so if rolled back, this will need to be revalidated in a separate migration
|
||||
add_concurrent_foreign_key(:epics, :epics, column: :parent_id, on_delete: :cascade, validate: false, name: FK_NAME)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRunnerCreationStatusToCiRunner < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.11'
|
||||
|
||||
def change
|
||||
add_column :ci_runners, :creation_state, :integer, limit: 2, default: 100, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UpdateRunnerCreationStatusDefaultToZero < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.11'
|
||||
|
||||
def change
|
||||
change_column_default :ci_runners, :creation_state, from: 100, to: 0
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddRunnerCreationStatusToCiRunnerMachines < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.11'
|
||||
|
||||
def change
|
||||
add_column :ci_runner_machines, :creation_state, :integer, limit: 2, default: 100, null: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class UpdateCiRunnerMachinesRunnerCreationStatusDefaultToZero < Gitlab::Database::Migration[2.2]
|
||||
milestone '16.11'
|
||||
|
||||
def change
|
||||
change_column_default :ci_runner_machines, :creation_state, from: 100, to: 0
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
4dd96835a4134f77ea0df9731fcdbb2d436a42a0829bb7d712c93aa23eda5c06
|
||||
|
|
@ -0,0 +1 @@
|
|||
e8e5d64ac7ff6ecb9e91701a6b93a35a01a0786b565717c5852f15b5c9441b5b
|
||||
|
|
@ -0,0 +1 @@
|
|||
ec1ad441c0ceb0ed3a444ada51799b2f758bbadccaad37112745604019a4a231
|
||||
|
|
@ -0,0 +1 @@
|
|||
31a9c402bac291e3be11363976e10223991afe14868941c91d6d96ab7283bcf5
|
||||
|
|
@ -0,0 +1 @@
|
|||
1474b0983a8d7b469c6969a5949d8a185be263d23e23f1d9b5da21fb861e6674
|
||||
|
|
@ -0,0 +1 @@
|
|||
c1e3ee0f7f7dcb8577372d0649b84c0157da0e76b96ed0a23f4bdfcd319e5ee9
|
||||
|
|
@ -0,0 +1 @@
|
|||
9a0f82dab091ebbd9ec2146d96efed4c0a46e18021e5378913c9dba9244f9d55
|
||||
|
|
@ -6645,6 +6645,7 @@ CREATE TABLE ci_runner_machines (
|
|||
ip_address text,
|
||||
config jsonb DEFAULT '{}'::jsonb NOT NULL,
|
||||
system_xid text,
|
||||
creation_state smallint DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT check_1537c1f66f CHECK ((char_length(platform) <= 255)),
|
||||
CONSTRAINT check_5253913ae9 CHECK ((char_length(system_xid) <= 64)),
|
||||
CONSTRAINT check_6f45a91da7 CHECK ((char_length(version) <= 2048)),
|
||||
|
|
@ -6730,6 +6731,7 @@ CREATE TABLE ci_runners (
|
|||
allowed_plans text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
registration_type smallint DEFAULT 0 NOT NULL,
|
||||
creator_id bigint,
|
||||
creation_state smallint DEFAULT 0 NOT NULL,
|
||||
CONSTRAINT check_ce275cee06 CHECK ((char_length(maintainer_note) <= 1024))
|
||||
);
|
||||
|
||||
|
|
@ -29798,9 +29800,6 @@ ALTER TABLE ONLY agent_activity_events
|
|||
ALTER TABLE ONLY zoekt_repositories
|
||||
ADD CONSTRAINT fk_25a92aeccd FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY epics
|
||||
ADD CONSTRAINT fk_25b99c1be3 FOREIGN KEY (parent_id) REFERENCES epics(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_pipelines
|
||||
ADD CONSTRAINT fk_262d4c2d19 FOREIGN KEY (auto_canceled_by_id) REFERENCES ci_pipelines(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
@ -30746,6 +30745,9 @@ ALTER TABLE ONLY emails
|
|||
ALTER TABLE ONLY epics
|
||||
ADD CONSTRAINT fk_epics_issue_id_with_on_delete_nullify FOREIGN KEY (issue_id) REFERENCES issues(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY epics
|
||||
ADD CONSTRAINT fk_epics_on_parent_id_with_on_delete_nullify FOREIGN KEY (parent_id) REFERENCES epics(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY clusters
|
||||
ADD CONSTRAINT fk_f05c5e5a42 FOREIGN KEY (management_project_id) REFERENCES projects(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -447,6 +447,8 @@ Example response:
|
|||
|
||||
## Delete epic
|
||||
|
||||
- [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/452189) in GitLab 16.11. In GitLab 16.10 and earlier, if you delete an epic, all its child epics and their descendants are deleted as well. If needed, you can remove child epics from the parent epic before you delete it.
|
||||
|
||||
Deletes an epic
|
||||
|
||||
```plaintext
|
||||
|
|
|
|||
|
|
@ -15384,7 +15384,7 @@ Represents the approval policy.
|
|||
| <a id="approvalpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
|
||||
| <a id="approvalpolicygroupapprovers"></a>`groupApprovers` **{warning-solid}** | [`[Group!]`](#group) | **Deprecated** in GitLab 16.5. Use `allGroupApprovers`. |
|
||||
| <a id="approvalpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
|
||||
| <a id="approvalpolicypolicyscope"></a>`policyScope` **{warning-solid}** | [`PolicyScope`](#policyscope) | **Introduced** in GitLab 16.10. **Status**: Experiment. Scope of the policy. Returns `null` if Security Policy Scope experimental feature is disabled. |
|
||||
| <a id="approvalpolicypolicyscope"></a>`policyScope` | [`PolicyScope`](#policyscope) | Scope of the policy. |
|
||||
| <a id="approvalpolicyroleapprovers"></a>`roleApprovers` | [`[MemberAccessLevelName!]`](#memberaccesslevelname) | Approvers of the role type. Users belonging to these role(s) alone will be approvers. |
|
||||
| <a id="approvalpolicysource"></a>`source` | [`SecurityPolicySource!`](#securitypolicysource) | Source of the policy. Its fields depend on the source type. |
|
||||
| <a id="approvalpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
|
||||
|
|
@ -28298,7 +28298,7 @@ Represents the scan execution policy.
|
|||
| <a id="scanexecutionpolicyeditpath"></a>`editPath` | [`String!`](#string) | URL of policy edit page. |
|
||||
| <a id="scanexecutionpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
|
||||
| <a id="scanexecutionpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
|
||||
| <a id="scanexecutionpolicypolicyscope"></a>`policyScope` **{warning-solid}** | [`PolicyScope`](#policyscope) | **Introduced** in GitLab 16.10. **Status**: Experiment. Scope of the policy. Returns `null` if Security Policy Scope experimental feature is disabled. |
|
||||
| <a id="scanexecutionpolicypolicyscope"></a>`policyScope` | [`PolicyScope`](#policyscope) | Scope of the policy. |
|
||||
| <a id="scanexecutionpolicysource"></a>`source` | [`SecurityPolicySource!`](#securitypolicysource) | Source of the policy. Its fields depend on the source type. |
|
||||
| <a id="scanexecutionpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
|
||||
| <a id="scanexecutionpolicyyaml"></a>`yaml` | [`String!`](#string) | YAML definition of the policy. |
|
||||
|
|
@ -28318,7 +28318,7 @@ Represents the scan result policy.
|
|||
| <a id="scanresultpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
|
||||
| <a id="scanresultpolicygroupapprovers"></a>`groupApprovers` **{warning-solid}** | [`[Group!]`](#group) | **Deprecated** in GitLab 16.5. Use `allGroupApprovers`. |
|
||||
| <a id="scanresultpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
|
||||
| <a id="scanresultpolicypolicyscope"></a>`policyScope` **{warning-solid}** | [`PolicyScope`](#policyscope) | **Introduced** in GitLab 16.10. **Status**: Experiment. Scope of the policy. Returns `null` if Security Policy Scope experimental feature is disabled. |
|
||||
| <a id="scanresultpolicypolicyscope"></a>`policyScope` | [`PolicyScope`](#policyscope) | Scope of the policy. |
|
||||
| <a id="scanresultpolicyroleapprovers"></a>`roleApprovers` | [`[MemberAccessLevelName!]`](#memberaccesslevelname) | Approvers of the role type. Users belonging to these role(s) alone will be approvers. |
|
||||
| <a id="scanresultpolicysource"></a>`source` | [`SecurityPolicySource!`](#securitypolicysource) | Source of the policy. Its fields depend on the source type. |
|
||||
| <a id="scanresultpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
|
||||
|
|
@ -35165,7 +35165,7 @@ Implementations:
|
|||
| <a id="orchestrationpolicyeditpath"></a>`editPath` | [`String!`](#string) | URL of policy edit page. |
|
||||
| <a id="orchestrationpolicyenabled"></a>`enabled` | [`Boolean!`](#boolean) | Indicates whether this policy is enabled. |
|
||||
| <a id="orchestrationpolicyname"></a>`name` | [`String!`](#string) | Name of the policy. |
|
||||
| <a id="orchestrationpolicypolicyscope"></a>`policyScope` **{warning-solid}** | [`PolicyScope`](#policyscope) | **Introduced** in GitLab 16.10. **Status**: Experiment. Scope of the policy. Returns `null` if Security Policy Scope experimental feature is disabled. |
|
||||
| <a id="orchestrationpolicypolicyscope"></a>`policyScope` | [`PolicyScope`](#policyscope) | Scope of the policy. |
|
||||
| <a id="orchestrationpolicyupdatedat"></a>`updatedAt` | [`Time!`](#time) | Timestamp of when the policy YAML was last updated. |
|
||||
| <a id="orchestrationpolicyyaml"></a>`yaml` | [`String!`](#string) | YAML definition of the policy. |
|
||||
|
||||
|
|
|
|||
|
|
@ -531,11 +531,7 @@ In this example:
|
|||
#### `workflow:auto_cancel:on_job_failure`
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23605) in GitLab 16.10 [with a flag](../../administration/feature_flags.md) named `auto_cancel_pipeline_on_job_failure`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available.
|
||||
To enable the feature, an administrator can [enable the feature flag](../../administration/feature_flags.md) named `auto_cancel_pipeline_on_job_failure`.
|
||||
On GitLab.com and GitLab Dedicated, this feature is not available.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/433163) in GitLab 16.11. Feature flag `auto_cancel_pipeline_on_job_failure` removed.
|
||||
|
||||
Use `workflow:auto_cancel:on_job_failure` to configure which jobs should be cancelled as soon as one job fails.
|
||||
|
||||
|
|
@ -754,13 +750,17 @@ When the branch is something else:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/436467) in GitLab 16.8 [with a flag](../../administration/feature_flags.md) named `ci_workflow_auto_cancel_on_new_commit`. Disabled by default.
|
||||
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/434676) in GitLab 16.9.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/434676) in GitLab 16.10. Feature flag `ci_workflow_auto_cancel_on_new_commit` removed.
|
||||
> - `on_job_failure` option for `workflow:rules` [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23605) in GitLab 16.10 [with a flag](../../administration/feature_flags.md) named `auto_cancel_pipeline_on_job_failure`. Disabled by default.
|
||||
> - `on_job_failure` option for `workflow:rules` [generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/433163) in GitLab 16.11. Feature flag `auto_cancel_pipeline_on_job_failure` removed.
|
||||
|
||||
Use `workflow:rules:auto_cancel` to configure the behavior of
|
||||
the [`workflow:auto_cancel:on_new_commit`](#workflowauto_cancelon_new_commit) feature.
|
||||
the [`workflow:auto_cancel:on_new_commit`](#workflowauto_cancelon_new_commit) or
|
||||
the [`workflow:auto_cancel:on_job_failure`](#workflowauto_cancelon_job_failure) features.
|
||||
|
||||
**Possible inputs**:
|
||||
|
||||
- `on_new_commit`: [`workflow:auto_cancel:on_new_commit`](#workflowauto_cancelon_new_commit)
|
||||
- `on_job_failure`: [`workflow:auto_cancel:on_job_failure`](#workflowauto_cancelon_job_failure)
|
||||
|
||||
**Example of `workflow:rules:auto_cancel`**:
|
||||
|
||||
|
|
@ -768,10 +768,12 @@ the [`workflow:auto_cancel:on_new_commit`](#workflowauto_cancelon_new_commit) fe
|
|||
workflow:
|
||||
auto_cancel:
|
||||
on_new_commit: interruptible
|
||||
on_job_failure: all
|
||||
rules:
|
||||
- if: $CI_COMMIT_REF_PROTECTED == 'true'
|
||||
auto_cancel:
|
||||
on_new_commit: none
|
||||
on_job_failure: none
|
||||
- when: always # Run the pipeline in other cases
|
||||
|
||||
test-job1:
|
||||
|
|
@ -784,8 +786,9 @@ test-job2:
|
|||
```
|
||||
|
||||
In this example, [`workflow:auto_cancel:on_new_commit`](#workflowauto_cancelon_new_commit)
|
||||
is set to `interruptible` for all jobs by default. But if a pipeline runs for a protected branch,
|
||||
the rule overrides the default with `on_new_commit: none`. For example, if a pipeline
|
||||
is set to `interruptible` and [`workflow:auto_cancel:on_job_failure`](#workflowauto_cancelon_job_failure)
|
||||
is set to `all` for all jobs by default. But if a pipeline runs for a protected branch,
|
||||
the rule overrides the default with `on_new_commit: none` and `on_job_failure: none`. For example, if a pipeline
|
||||
is running for:
|
||||
|
||||
- A non-protected branch and a new commit is pushed, `test-job1` continues to run and `test-job2` is canceled.
|
||||
|
|
|
|||
|
|
@ -749,7 +749,7 @@ For basic guidance on choosing a cluster configuration you may refer to [Elastic
|
|||
|
||||
#### Number of Elasticsearch shards
|
||||
|
||||
You must set the number of Elasticsearch shards per index to at least `5`.
|
||||
Set the number of Elasticsearch shards per index to at least `5`.
|
||||
To update the shard size for an index, change the setting and trigger [zero-downtime reindexing](#zero-downtime-reindexing).
|
||||
|
||||
##### Indices with database data
|
||||
|
|
@ -777,12 +777,13 @@ For indices that contain repository data:
|
|||
Keep the average shard size between a few GB and 30 GB.
|
||||
If the average shard size grows to more than 30 GB, increase the shard size
|
||||
for the index and trigger [zero-downtime reindexing](#zero-downtime-reindexing).
|
||||
To ensure the health of your cluster, the number of shards per node must be fewer than 20 per GB heap.
|
||||
To ensure the cluster is healthy, the number of shards per node
|
||||
must not exceed 20 times the configured heap size.
|
||||
For example, a node with a 30 GB heap must have a maximum of 600 shards.
|
||||
|
||||
#### Number of Elasticsearch replicas
|
||||
|
||||
You must set the number of Elasticsearch replicas per index to `1` (each shard has one replica).
|
||||
Set the number of Elasticsearch replicas per index to `1` (each shard has one replica).
|
||||
The number must not be `0` because losing one node corrupts the index.
|
||||
|
||||
### How to index large instances efficiently
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 119 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 127 KiB |
|
|
@ -27,23 +27,21 @@ This feature is in [Beta](../policy/experiment-beta-support.md). For more inform
|
|||
|
||||
To configure distributed tracing:
|
||||
|
||||
1. [Create an access token and enable tracing.](#create-an-access-token-and-enable-tracing)
|
||||
1. [Create an access token and enable tracing.](#create-an-access-token)
|
||||
1. [Configure your application to use the OpenTelemetry exporter.](#configure-your-application-to-use-the-opentelemetry-exporter)
|
||||
|
||||
### Create an access token and enable tracing
|
||||
### Create an access token
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have at least the Maintainer role for the project.
|
||||
|
||||
To enable tracing in a project:
|
||||
To enable tracing in a project, you must first create an access token:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Settings > Access Tokens**.
|
||||
1. Create an access token with the following scopes: `read_api`, `read_observability`, `write_observability`.
|
||||
1. Copy the value of the access token.
|
||||
1. Select **Monitor > Tracing**.
|
||||
1. Select **Enable**.
|
||||
|
||||
### Configure your application to use the OpenTelemetry exporter
|
||||
|
||||
|
|
@ -61,7 +59,7 @@ Use the following values:
|
|||
|
||||
- `namespace-id`: The top-level namespace ID where your project is located.
|
||||
- `gitlab-project-id`: The project ID.
|
||||
- `gitlab-access-token`: The access token you [created previously](#create-an-access-token-and-enable-tracing).
|
||||
- `gitlab-access-token`: The access token you [created previously](#create-an-access-token).
|
||||
|
||||
When your application is configured, run it, and the OpenTelemetry exporter attempts to send
|
||||
traces to GitLab.
|
||||
|
|
@ -75,9 +73,9 @@ To view the list of traces:
|
|||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Monitor > Traces**.
|
||||
|
||||
To see the details of a trace, select it from the list. You can also select a trace directly from the scatterplot.
|
||||
To see the details of a trace, select it from the list.
|
||||
|
||||

|
||||

|
||||
|
||||
The trace details page and a list of spans are displayed.
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ group: Source Code
|
|||
info: "To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments"
|
||||
---
|
||||
|
||||
# Partial clone
|
||||
# Use partial clones to reduce clone size
|
||||
|
||||
As Git repositories grow in size, they can become cumbersome to work with
|
||||
because of:
|
||||
|
|
@ -39,7 +39,7 @@ git clone --filter=blob:limit=1m git@gitlab.com:gitlab-com/www-gitlab-com.git
|
|||
|
||||
This would produce the following output:
|
||||
|
||||
```plaintext
|
||||
```shell
|
||||
Cloning into 'www-gitlab-com'...
|
||||
remote: Enumerating objects: 832467, done.
|
||||
remote: Counting objects: 100% (832467/832467), done.
|
||||
|
|
@ -70,7 +70,7 @@ For repositories with millions of files and a long history, you can exclude all
|
|||
[`git sparse-checkout`](https://git-scm.com/docs/git-sparse-checkout) to reduce the size of
|
||||
your working copy.
|
||||
|
||||
```plaintext
|
||||
```shell
|
||||
# Clone the repo excluding all files
|
||||
$ git clone --filter=blob:none --sparse git@gitlab.com:gitlab-com/www-gitlab-com.git
|
||||
Cloning into 'www-gitlab-com'...
|
||||
|
|
@ -143,7 +143,6 @@ For more details, see the Git documentation for
|
|||
clone command is not fully integrated with sparse checkout.
|
||||
|
||||
```shell
|
||||
|
||||
# Clone the filtered set of objects using the filterspec stored on the
|
||||
# server. WARNING: this step may be very slow!
|
||||
git clone --sparse --filter=sparse:oid=master:shiny-app/.gitfilterspec <url>
|
||||
|
|
|
|||
|
|
@ -7,55 +7,30 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Analyze GitLab usage
|
||||
|
||||
> - Group-level analytics moved to GitLab Premium in 13.9.
|
||||
|
||||
GitLab provides different types of analytics insights at the instance, group, and project level.
|
||||
These insights appear on the left sidebar, under [**Analyze**](../project/settings/index.md#disable-project-analytics).
|
||||
|
||||
## Instance-level analytics
|
||||
## Analytics features
|
||||
|
||||
Use [instance-level analytics](../../administration/analytics/index.md) to aggregate analytics across GitLab,
|
||||
so that you can view information across multiple projects and groups in one place.
|
||||
|
||||
## Group-level analytics
|
||||
|
||||
> - Moved to GitLab Premium in 13.9.
|
||||
|
||||
Use group-level analytics to get insights into your groups':
|
||||
|
||||
- [Security Dashboards](../application_security/security_dashboard/index.md)
|
||||
- [Contribution analytics](../group/contribution_analytics/index.md)
|
||||
- [DevOps adoption](../group/devops_adoption/index.md)
|
||||
- [Insights](../project/insights/index.md)
|
||||
- [Issue analytics](../group/issues_analytics/index.md)
|
||||
- [Productivity analytics](productivity_analytics.md)
|
||||
- [Repository analytics](../group/repositories_analytics/index.md)
|
||||
- [Value Stream Management Analytics](../group/value_stream_analytics/index.md) and [Value Stream Management Dashboard](value_streams_dashboard.md)
|
||||
|
||||
## Project-level analytics
|
||||
|
||||
Use project-level analytics to get insights into your projects':
|
||||
|
||||
- [Analytics dashboards](analytics_dashboards.md)
|
||||
- [Security Dashboards](../application_security/security_dashboard/index.md)
|
||||
- [CI/CD analytics and DORA metrics](ci_cd_analytics.md)
|
||||
- [Code review analytics](code_review_analytics.md)
|
||||
- [Contributor analytics](../../user/analytics/contributor_analytics.md)
|
||||
- [Insights](../project/insights/index.md)
|
||||
- [Issue analytics](../group/issues_analytics/index.md)
|
||||
- [Merge request analytics](merge_request_analytics.md), enabled with the `project_merge_request_analytics`
|
||||
[feature flag](../../development/feature_flags/index.md#enabling-a-feature-flag-locally-in-development)
|
||||
- [Repository analytics](repository_analytics.md)
|
||||
- [Value Stream Management Analytics](../group/value_stream_analytics/index.md) and [Value Stream Management Dashboard](value_streams_dashboard.md)
|
||||
|
||||
## User-configurable analytics
|
||||
|
||||
View vulnerabilities of your selected projects in the [Security Center](../application_security/security_dashboard/index.md#security-center).
|
||||
|
||||
## Value streams management
|
||||
|
||||
Analyze and visualize the performance of your projects and groups with:
|
||||
|
||||
- [Value stream analytics for projects and groups](../group/value_stream_analytics/index.md)
|
||||
- [Value streams dashboard](value_streams_dashboard.md)
|
||||
| Feature | Description | Category | Project-level | Group-level | Instance-level |
|
||||
| ------- | ----------- | -------- | ------------- | ----------- | -------------- |
|
||||
| [Analytics dashboards](analytics_dashboards.md) | Built-in and customizable dashboards to visualize collected data. | End-to-end insight & visibility | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [CI/CD analytics and DORA metrics](ci_cd_analytics.md) | Pipeline duration and successes/failures, and DORA metrics over time. | CI/CD | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Code review analytics](code_review_analytics.md) | Open merge requests with information about merge request activity. | Productivity | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No |
|
||||
| [Contribution analytics](../group/contribution_analytics/index.md) | Overview of [contribution events](../../user/profile/contributions_calendar.md) made by group members, with bar chart of push events, merge requests, and issues. | Developer | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Contributor analytics](../../user/analytics/contributor_analytics.md) | Overview of commits made by project members, with line chart of number of commits. | Developer | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No |
|
||||
| [DevOps adoption](../group/devops_adoption/index.md) | Organization's maturity in DevOps adoption, with group-level feature adoption over time and adoption by subgroup. | End-to-end insight & visibility | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Insights](../project/insights/index.md) | Customizable reports to explore issues, merged merge requests, and triage hygiene. | End-to-end insight & visibility | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Instance-level analytics](../../administration/analytics/index.md) | Aggregated analytics across GitLab about multiple projects and groups in one place. | End-to-end insight & visibility | **{dotted-circle}** No | **{dotted-circle}** No | **{check-circle}** Yes |
|
||||
| [Issue analytics](../group/issues_analytics/index.md) | Visualization of issues created each month. | Productivity | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Merge request analytics](merge_request_analytics.md) | Overview of merge requests, with mean time to merge, throughput, and activity details. | Productivity | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No |
|
||||
| [Productivity analytics](productivity_analytics.md) | Merge request lifecycle, filterable down to author level. | Productivity | **{dotted-circle}** No | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Repository analytics](../group/repositories_analytics/index.md) | Programming languages used in the repository and code coverage statistics. | Developer | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Security Dashboards](../application_security/security_dashboard/index.md) | Collection of metrics, ratings, and charts for vulnerabilities detected by security scanners. | Security | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
| [Value Streams Dashboard](value_streams_dashboard.md) | Insights into DevSecOps trends, patterns, and opportunities for digital transformation improvements. | End-to-end insight & visibility | **{check-circle}** Yes | **{dotted-circle}** No | **{dotted-circle}** No |
|
||||
| [Value Stream Management Analytics](../group/value_stream_analytics/index.md) | Insights into time-to-value through customizable stages. | End-to-end insight & visibility | **{check-circle}** Yes | **{check-circle}** Yes | **{dotted-circle}** No |
|
||||
|
||||
## Glossary
|
||||
|
||||
|
|
|
|||
|
|
@ -139,6 +139,8 @@ To update multiple epics at the same time:
|
|||
|
||||
## Delete an epic
|
||||
|
||||
- [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/452189) in GitLab 16.11. In GitLab 16.10 and earlier, if you delete an epic, all its child epics and their descendants are deleted as well. If needed, you can [remove child epics](#remove-a-child-epic-from-a-parent-epic) from the parent epic before you delete it.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- You must have the Owner role for the epic's group.
|
||||
|
|
@ -150,9 +152,6 @@ To delete the epic:
|
|||
|
||||
Deleting an epic releases all existing issues from their associated epic in the system.
|
||||
|
||||
WARNING:
|
||||
If you delete an epic, all its child epics and their descendants are deleted as well. If needed, you can [remove child epics](#remove-a-child-epic-from-a-parent-epic) from the parent epic before you delete it.
|
||||
|
||||
## Close an epic
|
||||
|
||||
Prerequisites:
|
||||
|
|
|
|||
|
|
@ -59,8 +59,7 @@ To enable or disable individual features in a project:
|
|||
|
||||
## Disable project analytics
|
||||
|
||||
By default, [analytics for a project](../../analytics/index.md#project-level-analytics)
|
||||
are displayed under the **Analyze** item in the left sidebar.
|
||||
By default, project analytics are displayed under the **Analyze** item in the left sidebar.
|
||||
To disable this feature and remove the **Analyze** item from the left sidebar:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
|
|
|
|||
|
|
@ -16,10 +16,6 @@ module Gitlab
|
|||
end
|
||||
|
||||
def satisfied_by?(_pipeline, context)
|
||||
if ::Feature.disabled?(:ci_rule_exists_extension_optimization, context.project, type: :gitlab_com_derisk)
|
||||
return legacy_satisfied_by?(context)
|
||||
end
|
||||
|
||||
paths = worktree_paths(context)
|
||||
exact_globs, extension_globs, pattern_globs = separate_globs(context)
|
||||
|
||||
|
|
@ -30,18 +26,6 @@ module Gitlab
|
|||
|
||||
private
|
||||
|
||||
def legacy_satisfied_by?(context)
|
||||
paths = worktree_paths(context)
|
||||
exact_globs, pattern_globs = legacy_separate_globs(context)
|
||||
|
||||
exact_matches?(paths, exact_globs) || pattern_matches?(paths, pattern_globs)
|
||||
end
|
||||
|
||||
def legacy_separate_globs(context)
|
||||
expanded_globs = expand_globs(context)
|
||||
expanded_globs.partition(&method(:exact_glob?))
|
||||
end
|
||||
|
||||
def separate_globs(context)
|
||||
expanded_globs = expand_globs(context)
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,6 @@ module Gitlab
|
|||
end
|
||||
|
||||
def set_auto_cancel_on_job_failure(auto_cancel)
|
||||
return if Feature.disabled?(:auto_cancel_pipeline_on_job_failure, pipeline.project)
|
||||
|
||||
auto_cancel_on_job_failure = auto_cancel[:on_job_failure]
|
||||
|
||||
return if auto_cancel_on_job_failure.blank?
|
||||
|
|
|
|||
|
|
@ -540,6 +540,9 @@ msgstr ""
|
|||
msgid "%{address} is an invalid IP address range"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{approvals_given} of %{required} Approvals"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{argument_name} must be formatted correctly. For example: 1h 30m."
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -1100,9 +1103,6 @@ msgid_plural "%{releases} releases"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%{remaining_approvals} left"
|
||||
msgstr ""
|
||||
|
||||
msgid "%{requireStart}Require%{requireEnd} %{approvalsRequired} %{approvalStart}approval%{approvalEnd} from:"
|
||||
msgid_plural "%{requireStart}Require%{requireEnd} %{approvalsRequired} %{approvalStart}approvals%{approvalEnd} from:"
|
||||
msgstr[0] ""
|
||||
|
|
@ -14053,6 +14053,9 @@ msgstr ""
|
|||
msgid "ContainerRegistry|Tags with names that match this regex pattern are removed. %{linkStart}View regex examples.%{linkEnd}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|The %{linkStart}next-generation container registry%{linkEnd} is now available for upgrade and testing on self-managed instances as a Beta feature. This upgraded registry supports online garbage collection, and has significant performance and reliability improvements."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContainerRegistry|The cleanup policy timed out before it could delete all tags. An administrator can %{adminLinkStart}run cleanup now manually%{adminLinkEnd} or you can wait for the next scheduled run of the cleanup policy. %{docLinkStart}More information%{docLinkEnd}"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -42949,10 +42952,10 @@ msgstr ""
|
|||
msgid "Require expiration date"
|
||||
msgstr ""
|
||||
|
||||
msgid "Required approvals (%{approvals_given} given)"
|
||||
msgid "Required approvals (%{approvals_given} of %{required} given)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Required approvals (%{approvals_given} given, you've approved)"
|
||||
msgid "Required approvals (%{approvals_given} of %{required} given, you've approved)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Required in this project."
|
||||
|
|
@ -44067,6 +44070,9 @@ msgstr ""
|
|||
msgid "Runners|Runner is locked and available for currently assigned projects only. Only administrators can change the assigned projects."
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner is offline; it has never contacted this instance"
|
||||
msgstr ""
|
||||
|
||||
msgid "Runners|Runner is offline; last contact was %{runner_contact} ago"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -12,9 +12,11 @@ class GenerateAsIfFossEnv
|
|||
compile-production-assets
|
||||
compile-storybook
|
||||
compile-test-assets
|
||||
detect-tests
|
||||
eslint
|
||||
generate-apollo-graphql-schema
|
||||
graphql-schema-dump
|
||||
rubocop
|
||||
qa:internal
|
||||
qa:selectors
|
||||
static-analysis
|
||||
|
|
@ -47,7 +49,9 @@ class GenerateAsIfFossEnv
|
|||
|
||||
{
|
||||
START_AS_IF_FOSS: 'true',
|
||||
RUBY_VERSION: ENV['RUBY_VERSION']
|
||||
RUBY_VERSION: ENV['RUBY_VERSION'],
|
||||
CI_MERGE_REQUEST_PROJECT_PATH: ENV['CI_MERGE_REQUEST_PROJECT_PATH'],
|
||||
CI_MERGE_REQUEST_IID: ENV['CI_MERGE_REQUEST_IID']
|
||||
}.merge(rspec_variables).merge(other_jobs_variables)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,13 @@ FactoryBot.define do
|
|||
runner factory: :ci_runner
|
||||
system_xid { "r_#{SecureRandom.hex.slice(0, 10)}" }
|
||||
|
||||
creation_state { :finished }
|
||||
|
||||
trait :unregistered do
|
||||
contacted_at { nil }
|
||||
creation_state { :started }
|
||||
end
|
||||
|
||||
trait :stale do
|
||||
created_at { 1.year.ago }
|
||||
contacted_at { Ci::RunnerManager::STALE_TIMEOUT.ago }
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ FactoryBot.define do
|
|||
|
||||
runner_type { :instance_type }
|
||||
|
||||
creation_state { :finished }
|
||||
|
||||
transient do
|
||||
groups { [] }
|
||||
projects { [] }
|
||||
|
|
@ -41,6 +43,11 @@ FactoryBot.define do
|
|||
runner_type { :instance_type }
|
||||
end
|
||||
|
||||
trait :unregistered do
|
||||
contacted_at { nil }
|
||||
creation_state { :started }
|
||||
end
|
||||
|
||||
trait :group do
|
||||
runner_type { :group_type }
|
||||
|
||||
|
|
|
|||
|
|
@ -258,7 +258,7 @@ RSpec.describe "Admin Runners", feature_category: :fleet_visibility do
|
|||
|
||||
describe 'filter by status' do
|
||||
let_it_be(:never_contacted) do
|
||||
create(:ci_runner, :instance, description: 'runner-never-contacted', contacted_at: nil)
|
||||
create(:ci_runner, :instance, :unregistered, description: 'runner-never-contacted')
|
||||
end
|
||||
|
||||
before_all do
|
||||
|
|
@ -614,7 +614,7 @@ RSpec.describe "Admin Runners", feature_category: :fleet_visibility do
|
|||
describe "Runner edit page" do
|
||||
let_it_be(:project1) { create(:project) }
|
||||
let_it_be(:project2) { create(:project) }
|
||||
let_it_be(:project_runner) { create(:ci_runner, :project) }
|
||||
let_it_be(:project_runner) { create(:ci_runner, :unregistered, :project) }
|
||||
|
||||
before do
|
||||
visit edit_admin_runner_path(project_runner)
|
||||
|
|
|
|||
|
|
@ -11,12 +11,23 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
|
|||
create(:container_repository, name: 'my/image')
|
||||
end
|
||||
|
||||
let(:help_page_href) { help_page_path('administration/packages/container_registry_metadata_database') }
|
||||
|
||||
before do
|
||||
group.add_owner(user)
|
||||
sign_in(user)
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_tags(repository: :any, tags: [])
|
||||
stub_container_registry_info
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
it 'has link to next generation container registry docs' do
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
|
||||
|
||||
visit_container_registry
|
||||
|
||||
expect(page).to have_link('next-generation container registry', href: help_page_href)
|
||||
end
|
||||
|
||||
it 'has a page title set' do
|
||||
|
|
|
|||
|
|
@ -27,7 +27,11 @@ RSpec.describe 'Merge request > User approves', :js, feature_category: :code_rev
|
|||
|
||||
def verify_approvals_count_on_index!
|
||||
visit(project_merge_requests_path(project, state: :all))
|
||||
expect(page.all('li').any? { |item| item["title"] == "1 approver (you've approved)" }).to be true
|
||||
expect(
|
||||
page.all('[data-testid="mr-appovals"]').any? do |item|
|
||||
item["title"] == "1 approver (you've approved)"
|
||||
end
|
||||
).to be true
|
||||
visit project_merge_request_path(project, merge_request)
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -16,12 +16,15 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
|
|||
create(:container_repository, name: '')
|
||||
end
|
||||
|
||||
let(:help_page_href) { help_page_path('administration/packages/container_registry_metadata_database') }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
project.add_developer(user)
|
||||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_info
|
||||
stub_container_registry_tags(repository: :any, tags: [])
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
it 'has a page title set' do
|
||||
|
|
@ -30,6 +33,14 @@ RSpec.describe 'Container Registry', :js, feature_category: :container_registry
|
|||
expect(page).to have_title _('Container Registry')
|
||||
end
|
||||
|
||||
it 'has link to next generation container registry docs' do
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
|
||||
|
||||
visit_container_registry
|
||||
|
||||
expect(page).to have_link('next-generation container registry', href: help_page_href)
|
||||
end
|
||||
|
||||
it 'does not have link to settings' do
|
||||
visit_container_registry
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ RSpec.describe 'Project > Settings > Packages and registries > Container registr
|
|||
|
||||
sign_in(user)
|
||||
stub_container_registry_config(enabled: container_registry_enabled)
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
context 'as owner', :js do
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ RSpec.describe 'Project > Settings > Packages and registries > Container registr
|
|||
let(:container_registry_enabled) { true }
|
||||
let(:container_registry_enabled_on_project) { ProjectFeature::ENABLED }
|
||||
|
||||
let(:help_page_href) { help_page_path('administration/packages/container_registry_metadata_database') }
|
||||
|
||||
subject { visit project_settings_packages_and_registries_path(project) }
|
||||
|
||||
before do
|
||||
|
|
@ -18,6 +20,7 @@ RSpec.describe 'Project > Settings > Packages and registries > Container registr
|
|||
|
||||
sign_in(user)
|
||||
stub_container_registry_config(enabled: container_registry_enabled)
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
context 'as owner', :js do
|
||||
|
|
@ -51,6 +54,14 @@ RSpec.describe 'Project > Settings > Packages and registries > Container registr
|
|||
|
||||
expect(page).to have_link('Edit cleanup rules', href: cleanup_image_tags_project_settings_packages_and_registries_path(project))
|
||||
end
|
||||
|
||||
it 'has link to next generation container registry docs' do
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(false)
|
||||
|
||||
subject
|
||||
|
||||
expect(page).to have_link('next-generation container registry', href: help_page_href)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with a project without expiration policy', :js do
|
||||
|
|
|
|||
|
|
@ -555,6 +555,7 @@ RSpec.describe "Internal Project Access", feature_category: :system_access do
|
|||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_info
|
||||
project.container_repositories << container_repository
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
subject { project_container_registry_index_path(project) }
|
||||
|
|
|
|||
|
|
@ -574,6 +574,7 @@ RSpec.describe "Private Project Access", feature_category: :system_access do
|
|||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_info
|
||||
project.container_repositories << container_repository
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
subject { project_container_registry_index_path(project) }
|
||||
|
|
|
|||
|
|
@ -556,6 +556,7 @@ RSpec.describe "Public Project Access", feature_category: :system_access do
|
|||
stub_container_registry_config(enabled: true)
|
||||
stub_container_registry_info
|
||||
project.container_repositories << container_repository
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
subject { project_container_registry_index_path(project) }
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ RSpec.describe Ci::RunnerManagersFinder, '#execute', feature_category: :fleet_vi
|
|||
|
||||
let_it_be(:offline_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: 2.hours.ago) }
|
||||
let_it_be(:online_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: 1.second.ago) }
|
||||
let_it_be(:never_contacted_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: nil) }
|
||||
let_it_be(:never_contacted_runner_manager) { create(:ci_runner_machine, :unregistered, runner: runner) }
|
||||
let_it_be(:stale_runner_manager) do
|
||||
create(
|
||||
:ci_runner_machine,
|
||||
|
|
|
|||
|
|
@ -13,13 +13,18 @@ RSpec.describe 'Runner (JavaScript fixtures)', feature_category: :fleet_visibili
|
|||
let_it_be(:project) { create(:project, :repository, :public) }
|
||||
let_it_be(:project_2) { create(:project, :repository, :public) }
|
||||
|
||||
let_it_be(:runner) { create(:ci_runner, :instance, description: 'My Runner', creator: admin, version: '1.0.0') }
|
||||
let_it_be(:runner) do
|
||||
create(:ci_runner, :instance, :unregistered, description: 'My Runner', creator: admin, version: '1.0.0')
|
||||
end
|
||||
|
||||
let_it_be(:runner_manager_1) { create(:ci_runner_machine, runner: runner, contacted_at: Time.current) }
|
||||
let_it_be(:runner_manager_2) { create(:ci_runner_machine, runner: runner, contacted_at: Time.current) }
|
||||
|
||||
let_it_be(:group_runner) { create(:ci_runner, :group, groups: [group], version: '2.0.0') }
|
||||
let_it_be(:group_runner_2) { create(:ci_runner, :group, groups: [group], version: '2.0.0') }
|
||||
let_it_be(:project_runner) { create(:ci_runner, :project, projects: [project, project_2], version: '2.0.0') }
|
||||
let_it_be(:project_runner) do
|
||||
create(:ci_runner, :project, :unregistered, projects: [project, project_2], version: '2.0.0')
|
||||
end
|
||||
|
||||
let_it_be(:build) { create(:ci_build, runner: runner) }
|
||||
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import component from '~/packages_and_registries/container_registry/explorer/pag
|
|||
import Tracking from '~/tracking';
|
||||
import PersistedPagination from '~/packages_and_registries/shared/components/persisted_pagination.vue';
|
||||
import PersistedSearch from '~/packages_and_registries/shared/components/persisted_search.vue';
|
||||
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
|
||||
import { FILTERED_SEARCH_TERM } from '~/vue_shared/components/filtered_search_bar/constants';
|
||||
import TitleArea from '~/vue_shared/components/registry/title_area.vue';
|
||||
|
||||
|
|
@ -57,6 +58,7 @@ describe('List Page', () => {
|
|||
const findRegistryHeader = () => wrapper.findComponent(RegistryHeader);
|
||||
|
||||
const findDeleteAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findMetadataDatabaseAlert = () => wrapper.findComponent(MetadataDatabaseAlert);
|
||||
const findImageList = () => wrapper.findComponent(ImageList);
|
||||
const findPersistedSearch = () => wrapper.findComponent(PersistedSearch);
|
||||
const findEmptySearchMessage = () => wrapper.find('[data-testid="emptySearch"]');
|
||||
|
|
@ -139,6 +141,24 @@ describe('List Page', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('metadata database alert', () => {
|
||||
it('is rendered when metadata database is not enabled', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findMetadataDatabaseAlert().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('is not rendered when metadata database is enabled', () => {
|
||||
mountComponent({
|
||||
config: {
|
||||
isMetadataDatabaseEnabled: true,
|
||||
},
|
||||
});
|
||||
|
||||
expect(findMetadataDatabaseAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('link to settings', () => {
|
||||
beforeEach(() => {
|
||||
const config = {
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ import ContainerProtectionRules from '~/packages_and_registries/settings/project
|
|||
import PackagesCleanupPolicy from '~/packages_and_registries/settings/project/components/packages_cleanup_policy.vue';
|
||||
import PackagesProtectionRules from '~/packages_and_registries/settings/project/components/packages_protection_rules.vue';
|
||||
import DependencyProxyPackagesSettings from 'ee_component/packages_and_registries/settings/project/components/dependency_proxy_packages_settings.vue';
|
||||
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
|
||||
import {
|
||||
SHOW_SETUP_SUCCESS_ALERT,
|
||||
UPDATE_SETTINGS_SUCCESS_MESSAGE,
|
||||
|
|
@ -26,6 +27,7 @@ describe('Registry Settings app', () => {
|
|||
const findDependencyProxyPackagesSettings = () =>
|
||||
wrapper.findComponent(DependencyProxyPackagesSettings);
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
const findMetadataDatabaseAlert = () => wrapper.findComponent(MetadataDatabaseAlert);
|
||||
|
||||
const defaultProvide = {
|
||||
projectPath: 'path',
|
||||
|
|
@ -37,6 +39,7 @@ describe('Registry Settings app', () => {
|
|||
containerRegistryProtectedContainers: true,
|
||||
packagesProtectedPackages: true,
|
||||
},
|
||||
isContainerRegistryMetadataDatabaseEnabled: false,
|
||||
};
|
||||
|
||||
const mountComponent = (provide = defaultProvide) => {
|
||||
|
|
@ -45,6 +48,23 @@ describe('Registry Settings app', () => {
|
|||
});
|
||||
};
|
||||
|
||||
describe('metadata database alert', () => {
|
||||
it('is rendered when metadata database is not enabled', () => {
|
||||
mountComponent();
|
||||
|
||||
expect(findMetadataDatabaseAlert().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('is not rendered when metadata database is enabled', () => {
|
||||
mountComponent({
|
||||
...defaultProvide,
|
||||
isContainerRegistryMetadataDatabaseEnabled: true,
|
||||
});
|
||||
|
||||
expect(findMetadataDatabaseAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('container policy success alert handling', () => {
|
||||
const originalLocation = window.location.href;
|
||||
const search = `?${SHOW_SETUP_SUCCESS_ALERT}=true`;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
import { GlAlert } from '@gitlab/ui';
|
||||
import { shallowMount } from '@vue/test-utils';
|
||||
import MetadataDatabaseAlert from '~/packages_and_registries/shared/components/container_registry_metadata_database_alert.vue';
|
||||
import * as utils from '~/lib/utils/common_utils';
|
||||
|
||||
describe('container registry metadata database alert', () => {
|
||||
let wrapper;
|
||||
|
||||
const mountComponent = () => {
|
||||
wrapper = shallowMount(MetadataDatabaseAlert);
|
||||
};
|
||||
|
||||
const findAlert = () => wrapper.findComponent(GlAlert);
|
||||
|
||||
describe('with no cookie set', () => {
|
||||
beforeEach(() => {
|
||||
utils.setCookie = jest.fn();
|
||||
|
||||
mountComponent();
|
||||
});
|
||||
|
||||
it('displays the alert', () => {
|
||||
expect(findAlert().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('does not call setCookie', () => {
|
||||
expect(utils.setCookie).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('when the close button is clicked', () => {
|
||||
beforeEach(() => {
|
||||
findAlert().vm.$emit('dismiss');
|
||||
});
|
||||
|
||||
it('sets the dismissed cookie', () => {
|
||||
expect(utils.setCookie).toHaveBeenCalledWith('hide_metadata_database_alert', 'true');
|
||||
});
|
||||
|
||||
it('does not display the alert', () => {
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with the dismissed cookie set', () => {
|
||||
beforeEach(() => {
|
||||
jest.spyOn(utils, 'getCookie').mockReturnValue('true');
|
||||
|
||||
mountComponent();
|
||||
});
|
||||
|
||||
it('does not display the alert', () => {
|
||||
expect(findAlert().exists()).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -16,7 +16,7 @@ RSpec.describe Ci::RunnersHelper, feature_category: :fleet_visibility do
|
|||
end
|
||||
|
||||
it "returns never contacted" do
|
||||
runner = create(:ci_runner)
|
||||
runner = create(:ci_runner, :unregistered)
|
||||
expect(helper.runner_status_icon(runner)).to include("never contacted")
|
||||
end
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ RSpec.describe Ci::RunnersHelper, feature_category: :fleet_visibility do
|
|||
end
|
||||
|
||||
it "returns stale text, when runner never contacted" do
|
||||
runner = create(:ci_runner, created_at: 4.months.ago)
|
||||
runner = create(:ci_runner, :unregistered, created_at: 4.months.ago)
|
||||
expect(helper.runner_status_icon(runner)).to include("is stale")
|
||||
expect(helper.runner_status_icon(runner)).to include("never contacted")
|
||||
end
|
||||
|
|
|
|||
|
|
@ -252,6 +252,36 @@ RSpec.describe PackagesHelper, feature_category: :package_registry do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#settings_data' do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
subject { helper.settings_data(project) }
|
||||
|
||||
where(:config_registry, :permission, :supports_gitlab_api?, :expected_result) do
|
||||
false | false | false | false
|
||||
false | false | true | false
|
||||
false | true | false | false
|
||||
false | true | true | false
|
||||
true | false | false | false
|
||||
true | false | true | false
|
||||
true | true | false | false
|
||||
true | true | true | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
before do
|
||||
allow(helper).to receive(:current_user).and_return(user)
|
||||
stub_config(registry: { enabled: config_registry })
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(supports_gitlab_api?)
|
||||
allow(Ability).to receive(:allowed?).and_call_original
|
||||
allow(Ability).to receive(:allowed?).with(user, :admin_container_image, project).and_return(permission)
|
||||
allow(Ability).to receive(:allowed?).with(user, :admin_package, project).and_return(true)
|
||||
end
|
||||
|
||||
it { is_expected.to include(is_container_registry_metadata_database_enabled: expected_result.to_s) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '#can_delete_packages?' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
|
|
|||
|
|
@ -11,16 +11,6 @@ RSpec.describe Gitlab::Ci::Build::Rules::Rule::Clause::Exists, feature_category:
|
|||
let(:project) { create(:project, :custom_repo, files: files) }
|
||||
end
|
||||
|
||||
context 'with feature flag `ci_rule_exists_extension_optimization` disabled' do
|
||||
before do
|
||||
stub_feature_flags(ci_rule_exists_extension_optimization: false)
|
||||
end
|
||||
|
||||
it_behaves_like 'a glob matching rule' do
|
||||
let(:project) { create(:project, :custom_repo, files: files) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the rules:exists has a variable' do
|
||||
let_it_be(:project) { create(:project, :custom_repo, files: { 'helm/helm_file.txt' => '' }) }
|
||||
|
||||
|
|
|
|||
|
|
@ -228,19 +228,6 @@ RSpec.describe Gitlab::Ci::Pipeline::Chain::PopulateMetadata, feature_category:
|
|||
end
|
||||
end
|
||||
|
||||
context 'when auto_cancel_pipeline_on_job_failure feature is disabled' do
|
||||
before do
|
||||
stub_feature_flags(auto_cancel_pipeline_on_job_failure: false)
|
||||
end
|
||||
|
||||
it 'ignores the auto_cancel_on_job_failure value' do
|
||||
run_chain
|
||||
|
||||
expect(pipeline.pipeline_metadata.auto_cancel_on_job_failure).to eq('none')
|
||||
expect(pipeline.pipeline_metadata).not_to be_persisted
|
||||
end
|
||||
end
|
||||
|
||||
context 'with workflow:rules:auto_cancel' do
|
||||
context 'with auto_cancel:on_new_commit not set and rules:workflow:auto_cancel:on_new_commit set' do
|
||||
let(:config) do
|
||||
|
|
|
|||
|
|
@ -5949,29 +5949,7 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
|
|||
allow(pipeline).to receive(:auto_cancel_on_job_failure).and_return(auto_cancel_on_job_failure)
|
||||
end
|
||||
|
||||
shared_examples 'expected behaviour' do
|
||||
it 'cancels the pipeline when expected' do
|
||||
unless errors
|
||||
if cancels
|
||||
expect(::Ci::UserCancelPipelineWorker).to receive(:perform_async)
|
||||
else
|
||||
expect(::Ci::UserCancelPipelineWorker).not_to receive(:perform_async)
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
it 'raises errors when expected' do
|
||||
if errors
|
||||
expect { subject }.to raise_error(ArgumentError, 'Unknown auto_cancel_on_job_failure value: invalid value')
|
||||
else
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the auto_cancel_pipeline_on_job_failure feature flag is enabled' do
|
||||
context 'with different configurations' do
|
||||
where(:auto_cancel_on_job_failure, :cancels, :errors) do
|
||||
'none' | false | false
|
||||
'all' | true | false
|
||||
|
|
@ -5979,23 +5957,25 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep, feature_category:
|
|||
end
|
||||
|
||||
with_them do
|
||||
it_behaves_like 'expected behaviour'
|
||||
end
|
||||
end
|
||||
it 'cancels the pipeline when expected' do
|
||||
unless errors
|
||||
if cancels
|
||||
expect(::Ci::UserCancelPipelineWorker).to receive(:perform_async)
|
||||
else
|
||||
expect(::Ci::UserCancelPipelineWorker).not_to receive(:perform_async)
|
||||
end
|
||||
|
||||
context 'when the auto_cancel_pipeline_on_job_failure feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(auto_cancel_pipeline_on_job_failure: false)
|
||||
end
|
||||
subject
|
||||
end
|
||||
end
|
||||
|
||||
where(:auto_cancel_on_job_failure, :cancels, :errors) do
|
||||
'none' | false | false
|
||||
'all' | false | false
|
||||
'invalid value' | false | false
|
||||
end
|
||||
|
||||
with_them do
|
||||
it_behaves_like 'expected behaviour'
|
||||
it 'raises errors when expected' do
|
||||
if errors
|
||||
expect { subject }.to raise_error(ArgumentError, 'Unknown auto_cancel_on_job_failure value: invalid value')
|
||||
else
|
||||
expect { subject }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ RSpec.describe Ci::RunnerManager, feature_category: :fleet_visibility, type: :mo
|
|||
|
||||
let_it_be(:offline_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: 2.hours.ago) }
|
||||
let_it_be(:online_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: 1.second.ago) }
|
||||
let_it_be(:never_contacted_runner_manager) { create(:ci_runner_machine, runner: runner, contacted_at: nil) }
|
||||
let_it_be(:never_contacted_runner_manager) { create(:ci_runner_machine, :unregistered, runner: runner) }
|
||||
|
||||
describe '.online' do
|
||||
subject(:runner_managers) { described_class.online }
|
||||
|
|
@ -329,46 +329,34 @@ RSpec.describe Ci::RunnerManager, feature_category: :fleet_visibility, type: :mo
|
|||
end
|
||||
|
||||
describe '#status', :freeze_time do
|
||||
let(:runner_manager) { build(:ci_runner_machine, created_at: 8.days.ago) }
|
||||
|
||||
subject { runner_manager.status }
|
||||
|
||||
context 'if never connected' do
|
||||
before do
|
||||
runner_manager.contacted_at = nil
|
||||
end
|
||||
let(:runner_manager) { build(:ci_runner_machine, :unregistered, created_at: 8.days.ago) }
|
||||
|
||||
it { is_expected.to eq(:stale) }
|
||||
|
||||
context 'if created recently' do
|
||||
before do
|
||||
runner_manager.created_at = 1.day.ago
|
||||
end
|
||||
let(:runner_manager) { build(:ci_runner_machine, :unregistered, created_at: 1.day.ago) }
|
||||
|
||||
it { is_expected.to eq(:never_contacted) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'if contacted 1s ago' do
|
||||
before do
|
||||
runner_manager.contacted_at = 1.second.ago
|
||||
end
|
||||
let(:runner_manager) { build(:ci_runner_machine, contacted_at: 1.second.ago) }
|
||||
|
||||
it { is_expected.to eq(:online) }
|
||||
end
|
||||
|
||||
context 'if contacted recently' do
|
||||
before do
|
||||
runner_manager.contacted_at = 2.hours.ago
|
||||
end
|
||||
let(:runner_manager) { build(:ci_runner_machine, contacted_at: 2.hours.ago) }
|
||||
|
||||
it { is_expected.to eq(:offline) }
|
||||
end
|
||||
|
||||
context 'if contacted long time ago' do
|
||||
before do
|
||||
runner_manager.contacted_at = 7.days.ago
|
||||
end
|
||||
let(:runner_manager) { build(:ci_runner_machine, created_at: 8.days.ago, contacted_at: 7.days.ago) }
|
||||
|
||||
it { is_expected.to eq(:stale) }
|
||||
end
|
||||
|
|
@ -436,7 +424,7 @@ RSpec.describe Ci::RunnerManager, feature_category: :fleet_visibility, type: :mo
|
|||
end
|
||||
|
||||
it 'updates only ip_address' do
|
||||
expect_redis_update(values.merge(contacted_at: Time.current))
|
||||
expect_redis_update(values.merge(contacted_at: Time.current, creation_state: :finished))
|
||||
|
||||
heartbeat
|
||||
end
|
||||
|
|
|
|||
|
|
@ -493,7 +493,7 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
|
|||
let!(:runner3) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 2.months.ago) }
|
||||
let!(:runner4) { create(:ci_runner, :instance, contacted_at: 1.month.ago, created_at: 3.months.ago) }
|
||||
|
||||
it { is_expected.to eq([runner1, runner3, runner4]) }
|
||||
it { is_expected.to contain_exactly(runner1, runner3, runner4) }
|
||||
end
|
||||
|
||||
describe '.active' do
|
||||
|
|
@ -887,55 +887,40 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
|
|||
end
|
||||
|
||||
describe '#status', :freeze_time do
|
||||
let(:runner) { build(:ci_runner, :instance, created_at: 3.months.ago) }
|
||||
|
||||
subject { runner.status }
|
||||
|
||||
context 'never connected' do
|
||||
before do
|
||||
runner.contacted_at = nil
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, :unregistered, created_at: 3.months.ago) }
|
||||
|
||||
it { is_expected.to eq(:stale) }
|
||||
|
||||
context 'created recently' do
|
||||
before do
|
||||
runner.created_at = 1.day.ago
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, :unregistered, created_at: 1.day.ago) }
|
||||
|
||||
it { is_expected.to eq(:never_contacted) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'inactive but online' do
|
||||
before do
|
||||
runner.contacted_at = 1.second.ago
|
||||
runner.active = false
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, active: false, contacted_at: 1.second.ago) }
|
||||
|
||||
it { is_expected.to eq(:online) }
|
||||
end
|
||||
|
||||
context 'contacted 1s ago' do
|
||||
before do
|
||||
runner.contacted_at = 1.second.ago
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, contacted_at: 1.second.ago) }
|
||||
|
||||
it { is_expected.to eq(:online) }
|
||||
end
|
||||
|
||||
context 'contacted recently' do
|
||||
before do
|
||||
runner.contacted_at = (3.months - 1.second).ago
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, contacted_at: (3.months - 1.second).ago) }
|
||||
|
||||
it { is_expected.to eq(:offline) }
|
||||
end
|
||||
|
||||
context 'contacted long time ago' do
|
||||
before do
|
||||
runner.contacted_at = 3.months.ago
|
||||
end
|
||||
let(:runner) { build(:ci_runner, :instance, created_at: 3.months.ago, contacted_at: 3.months.ago) }
|
||||
|
||||
it { is_expected.to eq(:stale) }
|
||||
end
|
||||
|
|
@ -1100,7 +1085,7 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
|
|||
end
|
||||
|
||||
it 'updates only ip_address' do
|
||||
expect_redis_update(values.merge(contacted_at: Time.current))
|
||||
expect_redis_update(values.merge(contacted_at: Time.current, creation_state: :finished))
|
||||
|
||||
heartbeat
|
||||
end
|
||||
|
|
@ -2150,7 +2135,7 @@ RSpec.describe Ci::Runner, type: :model, feature_category: :runner do
|
|||
describe 'status scopes' do
|
||||
let_it_be(:online_runner) { create(:ci_runner, :instance, contacted_at: 1.second.ago) }
|
||||
let_it_be(:offline_runner) { create(:ci_runner, :instance, contacted_at: 2.hours.ago) }
|
||||
let_it_be(:never_contacted_runner) { create(:ci_runner, :instance, contacted_at: nil) }
|
||||
let_it_be(:never_contacted_runner) { create(:ci_runner, :instance, :unregistered) }
|
||||
|
||||
describe '.online' do
|
||||
subject(:runners) { described_class.online }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,51 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Achievements::AchievementPolicy, feature_category: :user_profile do
|
||||
let_it_be_with_reload(:current_user) { create(:user) }
|
||||
|
||||
subject { described_class.new(current_user, achievement) }
|
||||
|
||||
shared_examples 'disallowed when feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(achievements: false)
|
||||
end
|
||||
|
||||
it { is_expected.to be_disallowed(:read_achievement) }
|
||||
end
|
||||
|
||||
context 'in a public group' do
|
||||
let_it_be(:group) { create(:group, :public) }
|
||||
let_it_be(:achievement) { create(:achievement, namespace: group) }
|
||||
|
||||
it { is_expected.to be_allowed(:read_achievement) }
|
||||
|
||||
it_behaves_like 'disallowed when feature flag disabled'
|
||||
end
|
||||
|
||||
context 'in a private group' do
|
||||
let_it_be(:group) { create(:group, :private) }
|
||||
let_it_be(:achievement) { create(:achievement, namespace: group) }
|
||||
|
||||
it { is_expected.to be_disallowed(:read_achievement) }
|
||||
|
||||
context 'when a group member' do
|
||||
before_all do
|
||||
group.add_guest(current_user)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:read_achievement) }
|
||||
|
||||
it_behaves_like 'disallowed when feature flag disabled'
|
||||
end
|
||||
|
||||
context 'when the user has received the achievement' do
|
||||
let_it_be(:user_achievement) { create(:user_achievement, user: current_user, achievement: achievement) }
|
||||
|
||||
it { is_expected.to be_allowed(:read_achievement) }
|
||||
|
||||
it_behaves_like 'disallowed when feature flag disabled'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -70,8 +70,8 @@ RSpec.describe Achievements::UserAchievementPolicy, feature_category: :user_prof
|
|||
end
|
||||
|
||||
context 'for others' do
|
||||
it 'is visible' do
|
||||
is_expected.to be_allowed(:read_user_achievement)
|
||||
it 'is not visible' do
|
||||
is_expected.to be_disallowed(:read_user_achievement)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1727,10 +1727,16 @@ RSpec.describe GroupPolicy, feature_category: :system_access do
|
|||
specify { is_expected.to be_disallowed(:destroy_user_achievement) }
|
||||
end
|
||||
|
||||
context 'when current user can not see the group' do
|
||||
context 'when current user is not a group member' do
|
||||
let(:current_user) { non_group_member }
|
||||
|
||||
specify { is_expected.to be_allowed(:read_achievement) }
|
||||
specify { is_expected.to be_disallowed(:read_achievement) }
|
||||
|
||||
context 'when the group is public' do
|
||||
let_it_be(:group) { create(:group, :public) }
|
||||
|
||||
specify { is_expected.to be_allowed(:read_achievement) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when current user is not an owner' do
|
||||
|
|
|
|||
|
|
@ -708,7 +708,7 @@ RSpec.describe 'Query.runner(id)', :freeze_time, feature_category: :fleet_visibi
|
|||
end
|
||||
|
||||
let_it_be(:never_contacted_instance_runner) do
|
||||
create(:ci_runner, description: 'Missing runner 1', created_at: 1.month.ago, contacted_at: nil)
|
||||
create(:ci_runner, :unregistered, description: 'Missing runner 1', created_at: 1.month.ago)
|
||||
end
|
||||
|
||||
let(:query) do
|
||||
|
|
|
|||
|
|
@ -91,10 +91,8 @@ RSpec.describe 'UserAchievements', feature_category: :user_profile do
|
|||
context 'when current user is not a member of the private group' do
|
||||
let(:current_user) { create(:user) }
|
||||
|
||||
it 'returns all achievements' do
|
||||
expect(graphql_data_at(:user, :userAchievements, :nodes)).to contain_exactly(
|
||||
a_graphql_entity_for(non_revoked_achievement)
|
||||
)
|
||||
it 'returns no achievements' do
|
||||
expect(graphql_data_at(:user, :userAchievements, :nodes)).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ RSpec.describe Projects::Settings::PackagesAndRegistriesController, feature_cate
|
|||
|
||||
before do
|
||||
sign_in(user)
|
||||
allow(ContainerRegistry::GitlabApiClient).to receive(:supports_gitlab_api?).and_return(true)
|
||||
end
|
||||
|
||||
it 'pushes the feature flag "packages_protected_packages" to the view' do
|
||||
|
|
|
|||
|
|
@ -37,11 +37,13 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
'compile-storybook',
|
||||
'compile-test-assets',
|
||||
'cache-assets:test',
|
||||
'detect-tests',
|
||||
'eslint',
|
||||
'generate-apollo-graphql-schema',
|
||||
'graphql-schema-dump',
|
||||
'jest 1/5',
|
||||
'jest-integration',
|
||||
'rubocop',
|
||||
'qa:internal',
|
||||
'qa:selectors',
|
||||
'static-analysis'
|
||||
|
|
@ -66,6 +68,8 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
expect(generate.variables).to eq({
|
||||
START_AS_IF_FOSS: 'true',
|
||||
RUBY_VERSION: ENV['RUBY_VERSION'],
|
||||
CI_MERGE_REQUEST_PROJECT_PATH: ENV['CI_MERGE_REQUEST_PROJECT_PATH'],
|
||||
CI_MERGE_REQUEST_IID: ENV['CI_MERGE_REQUEST_IID'],
|
||||
ENABLE_RSPEC: 'true',
|
||||
ENABLE_RSPEC_FAST_SPEC_HELPER: 'true',
|
||||
ENABLE_RSPEC_UNIT: 'true',
|
||||
|
|
@ -84,11 +88,13 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
ENABLE_COMPILE_STORYBOOK: 'true',
|
||||
ENABLE_COMPILE_TEST_ASSETS: 'true',
|
||||
ENABLE_CACHE_ASSETS: 'true',
|
||||
ENABLE_DETECT_TESTS: 'true',
|
||||
ENABLE_ESLINT: 'true',
|
||||
ENABLE_GENERATE_APOLLO_GRAPHQL_SCHEMA: 'true',
|
||||
ENABLE_GRAPHQL_SCHEMA_DUMP: 'true',
|
||||
ENABLE_JEST: 'true',
|
||||
ENABLE_JEST_INTEGRATION: 'true',
|
||||
ENABLE_RUBOCOP: 'true',
|
||||
ENABLE_QA_INTERNAL: 'true',
|
||||
ENABLE_QA_SELECTORS: 'true',
|
||||
ENABLE_STATIC_ANALYSIS: 'true'
|
||||
|
|
@ -103,6 +109,8 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
expect { generate.display }.to output(<<~ENV).to_stdout
|
||||
START_AS_IF_FOSS=true
|
||||
RUBY_VERSION=#{ENV['RUBY_VERSION']}
|
||||
CI_MERGE_REQUEST_PROJECT_PATH=#{ENV['CI_MERGE_REQUEST_PROJECT_PATH']}
|
||||
CI_MERGE_REQUEST_IID=#{ENV['CI_MERGE_REQUEST_IID']}
|
||||
ENABLE_RSPEC=true
|
||||
ENABLE_RSPEC_FAST_SPEC_HELPER=true
|
||||
ENABLE_RSPEC_UNIT=true
|
||||
|
|
@ -121,11 +129,13 @@ RSpec.describe GenerateAsIfFossEnv, feature_category: :tooling do
|
|||
ENABLE_COMPILE_STORYBOOK=true
|
||||
ENABLE_COMPILE_TEST_ASSETS=true
|
||||
ENABLE_CACHE_ASSETS=true
|
||||
ENABLE_DETECT_TESTS=true
|
||||
ENABLE_ESLINT=true
|
||||
ENABLE_GENERATE_APOLLO_GRAPHQL_SCHEMA=true
|
||||
ENABLE_GRAPHQL_SCHEMA_DUMP=true
|
||||
ENABLE_JEST=true
|
||||
ENABLE_JEST_INTEGRATION=true
|
||||
ENABLE_RUBOCOP=true
|
||||
ENABLE_QA_INTERNAL=true
|
||||
ENABLE_QA_SELECTORS=true
|
||||
ENABLE_STATIC_ANALYSIS=true
|
||||
|
|
|
|||
|
|
@ -149,40 +149,6 @@ RSpec.describe Ci::CreatePipelineService, :yaml_processor_feature_flag_corectnes
|
|||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.pipeline_metadata.auto_cancel_on_job_failure).to eq('all')
|
||||
end
|
||||
|
||||
context 'when auto_cancel_pipeline_on_job_failure feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(auto_cancel_pipeline_on_job_failure: false)
|
||||
end
|
||||
|
||||
context 'when there are no other metadata settings present' do
|
||||
it 'creates a pipeline without metadata' do
|
||||
expect(pipeline).to be_persisted
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.pipeline_metadata).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when other metadata settings are present' do
|
||||
let(:config) do
|
||||
<<~YAML
|
||||
workflow:
|
||||
name: pipeline_name
|
||||
auto_cancel:
|
||||
on_job_failure: all
|
||||
|
||||
test1:
|
||||
script: exit 0
|
||||
YAML
|
||||
end
|
||||
|
||||
it 'creates a pipeline with on_job_failure' do
|
||||
expect(pipeline).to be_persisted
|
||||
expect(pipeline.errors).to be_empty
|
||||
expect(pipeline.pipeline_metadata.auto_cancel_on_job_failure).to eq('none')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when on_job_failure is set to invalid' do
|
||||
|
|
|
|||
|
|
@ -242,7 +242,7 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute', feature_categor
|
|||
|
||||
context 'when it exceeds the application limits' do
|
||||
before do
|
||||
create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 1.month.ago)
|
||||
create(:ci_runner, :unregistered, runner_type: :group_type, groups: [group], created_at: 1.month.ago)
|
||||
create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
|
||||
end
|
||||
|
||||
|
|
@ -261,7 +261,7 @@ RSpec.describe ::Ci::Runners::RegisterRunnerService, '#execute', feature_categor
|
|||
context 'when abandoned runners cause application limits to not be exceeded' do
|
||||
before do
|
||||
create(:ci_runner, runner_type: :group_type, groups: [group], created_at: 4.months.ago, contacted_at: 3.months.ago)
|
||||
create(:ci_runner, runner_type: :group_type, groups: [group], contacted_at: nil, created_at: 4.months.ago)
|
||||
create(:ci_runner, :unregistered, runner_type: :group_type, groups: [group], created_at: 4.months.ago)
|
||||
create(:plan_limits, :default_plan, ci_registered_group_runners: 1)
|
||||
end
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue