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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-12-18 15:07:35 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-12-18 15:07:35 +0300
commit00cfeb7c25bdbd460efb83ad846cb924e73ee150 (patch)
tree944cb1af2640f1958efe878de969844ef578cbef
parent92de2642b384f7d6ac3bf3c1f0862b067306c9be (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/frontend.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb4
-rw-r--r--.gitlab/ci/rails/shared.gitlab-ci.yml6
-rw-r--r--.gitlab/ci/reports.gitlab-ci.yml2
-rw-r--r--.rubocop_todo/layout/hash_alignment.yml1
-rw-r--r--.rubocop_todo/lint/unused_method_argument.yml3
-rw-r--r--.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml1
-rw-r--r--.rubocop_todo/style/inline_disable_annotation.yml1
-rw-r--r--GITLAB_PAGES_VERSION2
-rw-r--r--Gemfile2
-rw-r--r--app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue62
-rw-r--r--app/assets/javascripts/content_editor/services/serialization_helpers.js44
-rw-r--r--app/assets/javascripts/projects/new/components/app.vue2
-rw-r--r--app/assets/javascripts/webhooks/components/form_url_app.vue24
-rw-r--r--app/graphql/mutations/ci/catalog/resources/unpublish.rb30
-rw-r--r--app/graphql/types/mutation_type.rb1
-rw-r--r--app/helpers/ci/pipeline_editor_helper.rb2
-rw-r--r--app/models/ci/catalog/resource.rb4
-rw-r--r--app/models/user_custom_attribute.rb8
-rw-r--r--config/feature_categories.yml1
-rw-r--r--config/feature_flags/development/soft_limit_daily_phone_verifications.yml8
-rw-r--r--config/initializers/rspec_profiling.rb51
-rw-r--r--config/sidekiq_queues.yml2
-rw-r--r--db/docs/automation_rules.yml4
-rw-r--r--db/docs/batched_background_migrations/backfill_uuid_conversion_column_in_vulnerability_occurrences.yml4
-rw-r--r--db/migrate/20231126200904_rename_index_i_container_protection_unique_project_id_container_path_pattern.rb6
-rw-r--r--db/post_migrate/20231207221056_finalize_backfill_uuid_conversion_column_in_vulnerability_occurrences.rb21
-rw-r--r--db/schema_migrations/202312072210561
-rw-r--r--doc/api/graphql/reference/index.md22
-rw-r--r--doc/development/documentation/styleguide/word_list.md11
-rw-r--r--doc/user/enterprise_user/index.md2
-rw-r--r--gems/gitlab-housekeeper/lib/gitlab/housekeeper/keep.rb23
-rw-r--r--gems/gitlab-housekeeper/lib/gitlab/housekeeper/runner.rb5
-rw-r--r--gems/gitlab-housekeeper/spec/gitlab/housekeeper/git_spec.rb2
-rw-r--r--gems/gitlab-housekeeper/spec/gitlab/housekeeper/runner_spec.rb6
-rw-r--r--keeps/overdue_finalize_background_migration.rb21
-rw-r--r--lib/gitlab/ci/config/entry/release.rb6
-rw-r--r--lib/organization/current_organization.rb23
-rw-r--r--locale/gitlab.pot9
-rw-r--r--scripts/rspec_helpers.sh4
-rw-r--r--spec/factories/user_custom_attributes.rb5
-rw-r--r--spec/features/search/user_uses_header_search_field_spec.rb2
-rw-r--r--spec/frontend/ci/pipeline_editor/components/validate/ci_validate_spec.js15
-rw-r--r--spec/frontend/content_editor/services/markdown_serializer_spec.js33
-rw-r--r--spec/frontend/webhooks/components/form_url_app_spec.js20
-rw-r--r--spec/helpers/ci/pipeline_editor_helper_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb1
-rw-r--r--spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb15
-rw-r--r--spec/lib/organization/current_organization_spec.rb66
-rw-r--r--spec/models/ci/catalog/resource_spec.rb23
-rw-r--r--spec/models/user_custom_attribute_spec.rb30
-rw-r--r--spec/requests/api/graphql/mutations/ci/catalog/resources/unpublish_spec.rb52
-rw-r--r--vendor/gems/sidekiq-reliable-fetch/lib/sidekiq/base_reliable_fetch.rb1
-rw-r--r--vendor/gems/sidekiq-reliable-fetch/spec/base_reliable_fetch_spec.rb12
55 files changed, 447 insertions, 269 deletions
diff --git a/.gitlab/ci/frontend.gitlab-ci.yml b/.gitlab/ci/frontend.gitlab-ci.yml
index 278ee26d48d..9d78fb102f9 100644
--- a/.gitlab/ci/frontend.gitlab-ci.yml
+++ b/.gitlab/ci/frontend.gitlab-ci.yml
@@ -153,7 +153,7 @@ retrieve-frontend-fixtures:
- run_timed_command "gem install knapsack --no-document"
- section_start "gitaly-test-spawn" "Spawning Gitaly"; scripts/gitaly-test-spawn; section_end "gitaly-test-spawn"; # Do not use 'bundle exec' here
- source ./scripts/rspec_helpers.sh
- - rspec_paralellized_job
+ - rspec_parallelized_job
artifacts:
name: frontend-fixtures
expire_in: 31d
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index c9d85d2a3f8..7efcc4b58a3 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -769,7 +769,7 @@ rspec-ee unit gitlab-duo-chat-zeroshot pg14:
- .rails:rules:ee-gitlab-duo-chat-optional
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--tag zeroshot_executor"
+ - rspec_parallelized_job "--tag zeroshot_executor"
rspec-ee unit gitlab-duo-chat-qa-fast pg14:
extends:
@@ -777,7 +777,7 @@ rspec-ee unit gitlab-duo-chat-qa-fast pg14:
- .rails:rules:ee-gitlab-duo-chat-always
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--tag fast_chat_qa_evaluation"
+ - rspec_parallelized_job "--tag fast_chat_qa_evaluation"
rspec-ee unit gitlab-duo pg14:
extends:
@@ -785,7 +785,7 @@ rspec-ee unit gitlab-duo pg14:
- .rails:rules:ee-gitlab-duo-chat-always
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--tag gitlab_duo"
+ - rspec_parallelized_job "--tag gitlab_duo"
rspec-ee unit gitlab-duo-chat-qa pg14:
variables:
diff --git a/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb b/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
index 4584cba0282..8a36848b363 100644
--- a/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
+++ b/.gitlab/ci/rails/rspec-foss-impact.gitlab-ci.yml.erb
@@ -39,7 +39,7 @@ dont-interrupt-me:
RSPEC_TESTS_MAPPING_ENABLED: "true"
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~zoekt --tag ~click_house"
+ - rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~zoekt --tag ~click_house"
artifacts:
expire_in: 7d
paths:
@@ -54,7 +54,7 @@ rspec migration foss-impact:
<% end %>
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
+ - rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
<% end %>
<% if rspec_files_per_test_level[:background_migration][:files].size > 0 %>
diff --git a/.gitlab/ci/rails/shared.gitlab-ci.yml b/.gitlab/ci/rails/shared.gitlab-ci.yml
index 636fefcb707..3194ac0c26f 100644
--- a/.gitlab/ci/rails/shared.gitlab-ci.yml
+++ b/.gitlab/ci/rails/shared.gitlab-ci.yml
@@ -80,7 +80,7 @@ include:
# spec/lib, yet background migration tests are also sitting there,
# and they should run on their own jobs so we don't need to run them
# in unit tests again.
- - rspec_paralellized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house --tag ~real_ai_request"
+ - rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~level:background_migration --tag ~click_house --tag ~real_ai_request"
after_script:
- echo -e "\e[0Ksection_start:`date +%s`:report_results_section[collapsed=true]\r\e[0KReport results"
- bundle exec gem list gitlab_quality-test_tooling
@@ -133,7 +133,7 @@ include:
.rspec-base-migration:
script:
- !reference [.base-script, script]
- - rspec_paralellized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
+ - rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag ~quarantine --tag ~zoekt --tag ~click_house"
after_script:
- !reference [.rspec-base, after_script]
@@ -155,7 +155,7 @@ include:
- cp config/click_house.yml.example config/click_house.yml
- 'sed -i "s|url:.*$|url: http://clickhouse:8123|g" config/click_house.yml'
- !reference [.base-script, script]
- - rspec_paralellized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag click_house"
+ - rspec_parallelized_job "--fail-fast=${RSPEC_FAIL_FAST_THRESHOLD} --tag click_house"
.rspec-base-pg14-as-if-foss:
extends:
diff --git a/.gitlab/ci/reports.gitlab-ci.yml b/.gitlab/ci/reports.gitlab-ci.yml
index 0290d0158b6..2e963b7857a 100644
--- a/.gitlab/ci/reports.gitlab-ci.yml
+++ b/.gitlab/ci/reports.gitlab-ci.yml
@@ -80,7 +80,7 @@ gemnasium-python-dependency_scanning:
extends: .default-retry
stage: test
image:
- name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/security-products/package-hunter-cli:v2.1.0@sha256:1f1d31fdc81f6cf0ee305ff0291bfb56f22c5764fe042948ff1676f2f8c60352
+ name: ${REGISTRY_HOST}/${REGISTRY_GROUP}/security-products/package-hunter-cli:v3.0.0@sha256:e281525b3be870d6618b6bad2685733dcb9908e4eb21f0e5b4fe4bb6f6083f91
entrypoint: [""]
variables:
HTR_user: '$PACKAGE_HUNTER_USER'
diff --git a/.rubocop_todo/layout/hash_alignment.yml b/.rubocop_todo/layout/hash_alignment.yml
index cf32e66d3e0..01a6e4ddeb4 100644
--- a/.rubocop_todo/layout/hash_alignment.yml
+++ b/.rubocop_todo/layout/hash_alignment.yml
@@ -2,7 +2,6 @@
# Cop supports --autocorrect.
Layout/HashAlignment:
Exclude:
- - 'config/initializers/rspec_profiling.rb'
- 'ee/spec/lib/ee/gitlab/usage_data_spec.rb'
- 'ee/spec/support/shared_examples/controllers/analytics/cycle_analytics/value_stream_shared_examples.rb'
- 'lib/gitlab/redis/multi_store.rb'
diff --git a/.rubocop_todo/lint/unused_method_argument.yml b/.rubocop_todo/lint/unused_method_argument.yml
index 7e5714ef918..2c9d5c3da14 100644
--- a/.rubocop_todo/lint/unused_method_argument.yml
+++ b/.rubocop_todo/lint/unused_method_argument.yml
@@ -217,7 +217,6 @@ Lint/UnusedMethodArgument:
- 'config/initializers/active_record_preloader.rb'
- 'config/initializers/active_record_table_definition.rb'
- 'config/initializers/forbid_sidekiq_in_transactions.rb'
- - 'config/initializers/rspec_profiling.rb'
- 'config/object_store_settings.rb'
- 'ee/app/controllers/ee/projects/protected_branches_controller.rb'
- 'ee/app/controllers/groups/omniauth_callbacks_controller.rb'
@@ -266,7 +265,6 @@ Lint/UnusedMethodArgument:
- 'ee/app/serializers/analytics/cycle_analytics/value_stream_errors_serializer.rb'
- 'ee/app/services/app_sec/dast/scans/run_service.rb'
- 'ee/app/services/audit_events/runners_token_audit_event_service.rb'
- - 'ee/app/services/automation/dispatch_service.rb'
- 'ee/app/services/boards/epic_lists/update_service.rb'
- 'ee/app/services/concerns/incident_management/oncall_rotations/shared_rotation_logic.rb'
- 'ee/app/services/ee/merge_requests/merge_base_service.rb'
@@ -276,7 +274,6 @@ Lint/UnusedMethodArgument:
- 'ee/app/services/projects/update_mirror_service.rb'
- 'ee/app/services/security/security_orchestration_policies/process_scan_result_policy_service.rb'
- 'ee/app/validators/vulnerabilities/cvss_vector_validator.rb'
- - 'ee/app/workers/automation/execute_rule_worker.rb'
- 'ee/app/workers/gitlab_subscriptions/refresh_seats_worker.rb'
- 'ee/db/fixtures/development/20_burndown.rb'
- 'ee/lib/audit/compliance_framework_changes_auditor.rb'
diff --git a/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml b/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
index 45c060ebe03..c0f48f83492 100644
--- a/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
+++ b/.rubocop_todo/sidekiq_load_balancing/worker_data_consistency.yml
@@ -315,7 +315,6 @@ SidekiqLoadBalancing/WorkerDataConsistency:
- 'ee/app/workers/approval_rules/external_approval_rule_payload_worker.rb'
- 'ee/app/workers/arkose/blocked_users_report_worker.rb'
- 'ee/app/workers/auth/saml_group_sync_worker.rb'
- - 'ee/app/workers/automation/execute_rule_worker.rb'
- 'ee/app/workers/ci/minutes/refresh_cached_data_worker.rb'
- 'ee/app/workers/ci/minutes/update_project_and_namespace_usage_worker.rb'
- 'ee/app/workers/ci/sync_reports_to_report_approval_rules_worker.rb'
diff --git a/.rubocop_todo/style/inline_disable_annotation.yml b/.rubocop_todo/style/inline_disable_annotation.yml
index 1119f212b4f..1a6226514e6 100644
--- a/.rubocop_todo/style/inline_disable_annotation.yml
+++ b/.rubocop_todo/style/inline_disable_annotation.yml
@@ -1108,7 +1108,6 @@ Style/InlineDisableAnnotation:
- 'config/initializers/mail_starttls_patch.rb'
- 'config/initializers/postgres_cte_as_materialized.rb'
- 'config/initializers/rack_VULNDB-255039_patch.rb'
- - 'config/initializers/rspec_profiling.rb'
- 'config/initializers/safe_session_store_patch.rb'
- 'config/initializers/sidekiq.rb'
- 'config/initializers/warden.rb'
diff --git a/GITLAB_PAGES_VERSION b/GITLAB_PAGES_VERSION
index d35f1128be3..f02cef6123f 100644
--- a/GITLAB_PAGES_VERSION
+++ b/GITLAB_PAGES_VERSION
@@ -1 +1 @@
-38a79230add5dc453d8fafa48f7f3e218a70f0be
+bf6cd6ddf529f8958adee206ac0f93953e9ac39c
diff --git a/Gemfile b/Gemfile
index f08b2bc2e48..4e7048ddc80 100644
--- a/Gemfile
+++ b/Gemfile
@@ -464,7 +464,7 @@ group :development, :test do
gem 'vite_rails', '~> 3.0.17', feature_category: :shared
gem 'vite_ruby', '~> 3.5.0', feature_category: :shared
- gem 'gitlab-housekeeper', path: 'gems/gitlab-housekeeper' # rubocop:todo Gemfile/MissingFeatureCategory
+ gem 'gitlab-housekeeper', path: 'gems/gitlab-housekeeper', feature_category: :tooling
end
group :development, :test, :danger do
diff --git a/app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue b/app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue
index 617088f303b..1d152a63407 100644
--- a/app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue
+++ b/app/assets/javascripts/ci/pipeline_editor/components/validate/ci_validate.vue
@@ -9,6 +9,7 @@ import {
GlTooltip,
GlTooltipDirective,
GlSprintf,
+ GlEmptyState,
} from '@gitlab/ui';
import { s__, __ } from '~/locale';
import Tracking from '~/tracking';
@@ -67,6 +68,7 @@ export default {
GlLink,
GlSprintf,
GlTooltip,
+ GlEmptyState,
ValidatePipelinePopover,
},
directives: {
@@ -226,38 +228,44 @@ export default {
</gl-button>
</div>
</div>
- <div v-if="isInitState" :class="$options.BASE_CLASSES">
- <img :src="validateTabIllustrationPath" />
- <h1 class="gl-font-size-h1 gl-mb-6">{{ $options.i18n.title }}</h1>
- <ul>
- <li class="gl-mb-3">{{ $options.i18n.contentNote }}</li>
- <li class="gl-mb-3">
+ <gl-empty-state
+ v-if="isInitState"
+ :svg-path="validateTabIllustrationPath"
+ :title="$options.i18n.title"
+ :primary-button-link="validateYaml"
+ :primary-button-text="$options.i18n.cta"
+ >
+ <template #description>
+ <p>{{ $options.i18n.contentNote }}</p>
+ <p>
<gl-sprintf :message="$options.i18n.simulationNote">
<template #code="{ content }">
<code>{{ content }}</code>
</template>
</gl-sprintf>
- </li>
- </ul>
- <div ref="simulatePipelineButton">
- <gl-button
- ref="simulatePipelineButton"
- variant="confirm"
- class="gl-mt-3"
- :disabled="isInitialCiContentLoading"
- data-testid="simulate-pipeline-button"
- @click="validateYaml"
- >
- {{ $options.i18n.cta }}
- </gl-button>
- </div>
- <gl-tooltip
- v-if="isInitialCiContentLoading"
- :target="() => $refs.simulatePipelineButton"
- :title="$options.i18n.ctaDisabledTooltip"
- data-testid="cta-tooltip"
- />
- </div>
+ </p>
+ </template>
+ <template #actions>
+ <div ref="simulatePipelineButton">
+ <gl-button
+ ref="simulatePipelineButton"
+ variant="confirm"
+ class="gl-mt-3"
+ :disabled="isInitialCiContentLoading"
+ data-testid="simulate-pipeline-button"
+ @click="validateYaml"
+ >
+ {{ $options.i18n.cta }}
+ </gl-button>
+ </div>
+ <gl-tooltip
+ v-if="isInitialCiContentLoading"
+ :target="() => $refs.simulatePipelineButton"
+ :title="$options.i18n.ctaDisabledTooltip"
+ data-testid="cta-tooltip"
+ />
+ </template>
+ </gl-empty-state>
<div v-else-if="isSimulationLoading" :class="$options.BASE_CLASSES">
<gl-loading-icon size="lg" class="gl-m-3" />
<h1 class="gl-font-size-h1 gl-mb-6">{{ $options.i18n.loading }}</h1>
diff --git a/app/assets/javascripts/content_editor/services/serialization_helpers.js b/app/assets/javascripts/content_editor/services/serialization_helpers.js
index f06ce59d3ff..87959a44560 100644
--- a/app/assets/javascripts/content_editor/services/serialization_helpers.js
+++ b/app/assets/javascripts/content_editor/services/serialization_helpers.js
@@ -480,6 +480,22 @@ export function renderReferenceLabel(state, node) {
state.write(node.attrs.originalText || `~${state.quote(node.attrs.text)}`);
}
+const findChildWithMark = (mark, parent) => {
+ let child;
+ let offset;
+ let index;
+
+ parent.forEach((_child, _offset, _index) => {
+ if (mark.isInSet(_child.marks)) {
+ child = _child;
+ offset = _offset;
+ index = _index;
+ }
+ });
+
+ return child ? { child, offset, index } : null;
+};
+
const generateBoldTags = (wrapTagName = openTag) => {
return (_, mark) => {
const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1];
@@ -531,13 +547,23 @@ export const italic = {
};
const generateCodeTag = (wrapTagName = openTag) => {
- return (_, mark) => {
+ const isOpen = wrapTagName === openTag;
+
+ return (_, mark, parent) => {
const type = /^(`|<code).*/.exec(mark.attrs.sourceMarkdown)?.[1];
if (type === '<code') {
return wrapTagName(type.substring(1));
}
+ const childText = findChildWithMark(mark, parent).child?.text || '';
+ if (childText.includes('`')) {
+ let tag = '``';
+ if (childText.startsWith('`') || childText.endsWith('`'))
+ tag = isOpen ? `${tag} ` : ` ${tag}`;
+ return tag;
+ }
+
return '`';
};
};
@@ -581,22 +607,6 @@ const normalizeUrl = (url) => {
const isValidAutolinkURL = (url) =>
/(https?:\/\/)?([\w-])+\.{1}([a-zA-Z]{2,63})([/\w-]*)*\/?\??([^#\n\r]*)?#?([^\n\r]*)/.test(url);
-const findChildWithMark = (mark, parent) => {
- let child;
- let offset;
- let index;
-
- parent.forEach((_child, _offset, _index) => {
- if (mark.isInSet(_child.marks)) {
- child = _child;
- offset = _offset;
- index = _index;
- }
- });
-
- return child ? { child, offset, index } : null;
-};
-
/**
* This function detects whether a link should be serialized
* as an autolink.
diff --git a/app/assets/javascripts/projects/new/components/app.vue b/app/assets/javascripts/projects/new/components/app.vue
index a841766a93c..7b55fe6c01c 100644
--- a/app/assets/javascripts/projects/new/components/app.vue
+++ b/app/assets/javascripts/projects/new/components/app.vue
@@ -2,7 +2,7 @@
import PROJECT_CREATE_FROM_TEMPLATE_SVG_URL from '@gitlab/svgs/dist/illustrations/project-create-from-template-sm.svg?url';
import PROJECT_CREATE_NEW_SVG_URL from '@gitlab/svgs/dist/illustrations/project-create-new-sm.svg?url';
import PROJECT_IMPORT_SVG_URL from '@gitlab/svgs/dist/illustrations/project-import-sm.svg?url';
-import PROJECT_RUN_CICD_PIPELINES_SVG_URL from '@gitlab/svgs/dist/illustrations/project-run-CICD-pipelines-sm.svg?url';
+import PROJECT_RUN_CICD_PIPELINES_SVG_URL from '@gitlab/svgs/dist/illustrations/empty-state/empty-devops-md.svg?url';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { s__ } from '~/locale';
import NewNamespacePage from '~/vue_shared/new_namespace/new_namespace_page.vue';
diff --git a/app/assets/javascripts/webhooks/components/form_url_app.vue b/app/assets/javascripts/webhooks/components/form_url_app.vue
index f20d4d9312b..25f994c1e6e 100644
--- a/app/assets/javascripts/webhooks/components/form_url_app.vue
+++ b/app/assets/javascripts/webhooks/components/form_url_app.vue
@@ -1,6 +1,13 @@
<script>
import { cloneDeep, isEmpty } from 'lodash';
-import { GlFormGroup, GlFormInput, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
+import {
+ GlFormGroup,
+ GlFormInput,
+ GlFormRadio,
+ GlFormRadioGroup,
+ GlLink,
+ GlAlert,
+} from '@gitlab/ui';
import { __, s__ } from '~/locale';
import { scrollToElement } from '~/lib/utils/common_utils';
@@ -14,6 +21,7 @@ export default {
GlFormRadio,
GlFormRadioGroup,
GlLink,
+ GlAlert,
},
props: {
initialUrl: {
@@ -40,6 +48,9 @@ export default {
urlState() {
return !this.isValidated || !isEmpty(this.url);
},
+ urlHasChanged() {
+ return this.url !== this.initialUrl;
+ },
maskedUrl() {
if (!this.url) {
return null;
@@ -152,6 +163,9 @@ export default {
urlPlaceholder: 'http://example.com/trigger-ci.json',
urlPreview: s__('Webhooks|URL preview'),
valuePartOfUrl: s__('Webhooks|Must match part of URL'),
+ tokenWillBeCleared: s__(
+ 'Webhooks|Secret token will be cleared on save unless token is updated.',
+ ),
},
};
</script>
@@ -175,6 +189,14 @@ export default {
:placeholder="$options.i18n.urlPlaceholder"
data-testid="form-url"
/>
+ <gl-alert
+ v-if="urlHasChanged"
+ variant="warning"
+ :dismissible="false"
+ class="gl-my-4 gl-form-input-xl"
+ >
+ {{ $options.i18n.tokenWillBeCleared }}
+ </gl-alert>
</gl-form-group>
<div class="gl-mt-5">
<gl-form-radio-group v-model="maskEnabled">
diff --git a/app/graphql/mutations/ci/catalog/resources/unpublish.rb b/app/graphql/mutations/ci/catalog/resources/unpublish.rb
deleted file mode 100644
index e45e9646147..00000000000
--- a/app/graphql/mutations/ci/catalog/resources/unpublish.rb
+++ /dev/null
@@ -1,30 +0,0 @@
-# frozen_string_literal: true
-
-module Mutations
- module Ci
- module Catalog
- module Resources
- class Unpublish < BaseMutation
- graphql_name 'CatalogResourceUnpublish'
-
- authorize :add_catalog_resource
-
- argument :id, ::Types::GlobalIDType[::Ci::Catalog::Resource],
- required: true,
- description: 'Global ID of the catalog resource to unpublish.'
-
- def resolve(id:)
- catalog_resource = ::Gitlab::Graphql::Lazy.force(GitlabSchema.find_by_gid(id))
- authorize!(catalog_resource&.project)
-
- catalog_resource.unpublish!
-
- {
- errors: []
- }
- end
- end
- end
- end
- end
-end
diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb
index 8ec41af0be4..590bc0ed282 100644
--- a/app/graphql/types/mutation_type.rb
+++ b/app/graphql/types/mutation_type.rb
@@ -145,7 +145,6 @@ module Types
mount_mutation Mutations::ContainerRepositories::DestroyTags
mount_mutation Mutations::Ci::Catalog::Resources::Create, alpha: { milestone: '15.11' }
mount_mutation Mutations::Ci::Catalog::Resources::Destroy, alpha: { milestone: '16.6' }
- mount_mutation Mutations::Ci::Catalog::Resources::Unpublish, alpha: { milestone: '16.6' }
mount_mutation Mutations::Ci::Job::Cancel
mount_mutation Mutations::Ci::Job::Play
mount_mutation Mutations::Ci::Job::Retry
diff --git a/app/helpers/ci/pipeline_editor_helper.rb b/app/helpers/ci/pipeline_editor_helper.rb
index b40d633dc69..f78a4aeaa49 100644
--- a/app/helpers/ci/pipeline_editor_helper.rb
+++ b/app/helpers/ci/pipeline_editor_helper.rb
@@ -35,7 +35,7 @@ module Ci
"simulate-pipeline-help-page-path" => help_page_path('ci/pipeline_editor/index', anchor: 'simulate-a-cicd-pipeline'),
"total-branches" => total_branches,
"uses-external-config" => uses_external_config?(project) ? 'true' : 'false',
- "validate-tab-illustration-path" => image_path('illustrations/project-run-CICD-pipelines-sm.svg'),
+ "validate-tab-illustration-path" => image_path('illustrations/empty-state/empty-devops-md.svg'),
"yml-help-page-path" => help_page_path('ci/yaml/index')
}
end
diff --git a/app/models/ci/catalog/resource.rb b/app/models/ci/catalog/resource.rb
index ed42f8f1900..d1b3a3a4d8a 100644
--- a/app/models/ci/catalog/resource.rb
+++ b/app/models/ci/catalog/resource.rb
@@ -68,10 +68,6 @@ module Ci
full_path
end
- def unpublish!
- update!(state: :draft)
- end
-
def publish!
update!(state: :published)
end
diff --git a/app/models/user_custom_attribute.rb b/app/models/user_custom_attribute.rb
index fb385b787bd..d294ea49352 100644
--- a/app/models/user_custom_attribute.rb
+++ b/app/models/user_custom_attribute.rb
@@ -23,6 +23,7 @@ class UserCustomAttribute < ApplicationRecord
IDENTITY_VERIFICATION_EXEMPT = 'identity_verification_exempt'
DELETED_OWN_ACCOUNT_AT = 'deleted_own_account_at'
SKIPPED_ACCOUNT_DELETION_AT = 'skipped_account_deletion_at'
+ ASSUMED_HIGH_RISK_REASON = 'assumed_high_risk_reason'
class << self
def upsert_custom_attributes(custom_attributes)
@@ -81,6 +82,13 @@ class UserCustomAttribute < ApplicationRecord
upsert_custom_attribute(user_id: user.id, key: SKIPPED_ACCOUNT_DELETION_AT, value: Time.zone.now.to_s)
end
+ def set_assumed_high_risk_reason(user:, reason:)
+ return unless user
+ return unless reason
+
+ upsert_custom_attribute(user_id: user.id, key: ASSUMED_HIGH_RISK_REASON, value: reason)
+ end
+
private
def blocked_users
diff --git a/config/feature_categories.yml b/config/feature_categories.yml
index c5ad97c9eb5..4391673b360 100644
--- a/config/feature_categories.yml
+++ b/config/feature_categories.yml
@@ -86,7 +86,6 @@
- mlops
- mobile_devops
- navigation
-- no_code_automation
- omnibus_package
- on_call_schedule_management
- onboarding
diff --git a/config/feature_flags/development/soft_limit_daily_phone_verifications.yml b/config/feature_flags/development/soft_limit_daily_phone_verifications.yml
new file mode 100644
index 00000000000..d0cc0290f86
--- /dev/null
+++ b/config/feature_flags/development/soft_limit_daily_phone_verifications.yml
@@ -0,0 +1,8 @@
+---
+name: soft_limit_daily_phone_verifications
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138287
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433220
+milestone: '16.7'
+type: development
+group: group::anti-abuse
+default_enabled: false
diff --git a/config/initializers/rspec_profiling.rb b/config/initializers/rspec_profiling.rb
index b0b7ea85cae..5830a3d5af2 100644
--- a/config/initializers/rspec_profiling.rb
+++ b/config/initializers/rspec_profiling.rb
@@ -48,31 +48,46 @@ module RspecProfilingExt
end
module Run
- def example_finished(*args)
- # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ # rubocop:disable Gitlab/ModuleWithInstanceVariables -- patching class which requires setting ivars
+ def example_finished(notification)
+ # If available, use the spec location where (deeply nested) shared examples are used.
+ file, line_number = notification
+ .example
+ .metadata
+ .fetch(:shared_group_inclusion_backtrace)
+ .reverse
+ .lazy
+ .map { |bt| bt.formatted_inclusion_location&.split(':') }
+ .first
+
+ unless file && line_number
+ file = @current_example.file
+ line_number = @current_example.line_number
+ end
+
collector.insert({
branch: vcs.branch,
- commit_hash: vcs.sha,
- date: vcs.time,
- file: @current_example.file,
- line_number: @current_example.line_number,
- description: @current_example.description,
- status: @current_example.status,
- exception: @current_example.exception,
- time: @current_example.time,
- query_count: @current_example.query_count,
- query_time: @current_example.query_time,
- request_count: @current_example.request_count,
- request_time: @current_example.request_time,
- feature_category: @current_example.feature_category
+ commit_hash: vcs.sha,
+ date: vcs.time,
+ file: file,
+ line_number: line_number,
+ description: @current_example.description,
+ status: @current_example.status,
+ exception: @current_example.exception,
+ time: @current_example.time,
+ query_count: @current_example.query_count,
+ query_time: @current_example.query_time,
+ request_count: @current_example.request_count,
+ request_time: @current_example.request_time,
+ feature_category: @current_example.feature_category
})
- # rubocop:enable Gitlab/ModuleWithInstanceVariables
rescue StandardError => err
- return if @already_logged_example_finished_error # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ return if @already_logged_example_finished_error
warn "rspec_profiling couldn't collect an example: #{err}. Further warnings suppressed."
- @already_logged_example_finished_error = true # rubocop:disable Gitlab/ModuleWithInstanceVariables
+ @already_logged_example_finished_error = true
end
+ # rubocop:enable Gitlab/ModuleWithInstanceVariables
alias_method :example_passed, :example_finished
alias_method :example_failed, :example_finished
diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml
index 74f97e3bbe9..92f034ba7e9 100644
--- a/config/sidekiq_queues.yml
+++ b/config/sidekiq_queues.yml
@@ -75,8 +75,6 @@
- 2
- - auto_merge
- 3
-- - automation_execute_rule
- - 1
- - background_migration
- 1
- - background_migration_ci_database
diff --git a/db/docs/automation_rules.yml b/db/docs/automation_rules.yml
index fcbbf247f9d..2465bd3a059 100644
--- a/db/docs/automation_rules.yml
+++ b/db/docs/automation_rules.yml
@@ -1,10 +1,8 @@
---
table_name: automation_rules
description: Stores automation rules and their trigger events
-classes:
-- Automation::Rule
feature_categories:
-- no_code_automation
+-
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/111021
milestone: '15.9'
gitlab_schema: gitlab_main
diff --git a/db/docs/batched_background_migrations/backfill_uuid_conversion_column_in_vulnerability_occurrences.yml b/db/docs/batched_background_migrations/backfill_uuid_conversion_column_in_vulnerability_occurrences.yml
index 2735933a58c..3c4e56dc883 100644
--- a/db/docs/batched_background_migrations/backfill_uuid_conversion_column_in_vulnerability_occurrences.yml
+++ b/db/docs/batched_background_migrations/backfill_uuid_conversion_column_in_vulnerability_occurrences.yml
@@ -1,6 +1,8 @@
---
migration_job_name: BackfillUuidConversionColumnInVulnerabilityOccurrences
-description: backfill values for `uuid_convert_string_to_uuid` column in vulnerability_occurrences table
+description: backfill values for `uuid_convert_string_to_uuid` column in vulnerability_occurrences
+ table
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/124986
milestone: '16.2'
+finalized_by: '20231207221056'
diff --git a/db/migrate/20231126200904_rename_index_i_container_protection_unique_project_id_container_path_pattern.rb b/db/migrate/20231126200904_rename_index_i_container_protection_unique_project_id_container_path_pattern.rb
index e8129b5020b..66e53a5da66 100644
--- a/db/migrate/20231126200904_rename_index_i_container_protection_unique_project_id_container_path_pattern.rb
+++ b/db/migrate/20231126200904_rename_index_i_container_protection_unique_project_id_container_path_pattern.rb
@@ -6,11 +6,17 @@ class RenameIndexIContainerProtectionUniqueProjectIdContainerPathPattern < Gitla
disable_ddl_transaction!
def up
+ # Precaution in case the index is missing for some reason
+ return unless index_exists_by_name?(:container_registry_protection_rules, :idx_copy_d01a85dee8)
+
rename_index :container_registry_protection_rules, :idx_copy_d01a85dee8,
:i_container_protection_unique_project_repository_path_pattern
end
def down
+ return unless index_exists_by_name?(:container_registry_protection_rules,
+ :i_container_protection_unique_project_repository_path_pattern)
+
rename_index :container_registry_protection_rules, :i_container_protection_unique_project_repository_path_pattern,
:idx_copy_d01a85dee8
end
diff --git a/db/post_migrate/20231207221056_finalize_backfill_uuid_conversion_column_in_vulnerability_occurrences.rb b/db/post_migrate/20231207221056_finalize_backfill_uuid_conversion_column_in_vulnerability_occurrences.rb
new file mode 100644
index 00000000000..4426a915526
--- /dev/null
+++ b/db/post_migrate/20231207221056_finalize_backfill_uuid_conversion_column_in_vulnerability_occurrences.rb
@@ -0,0 +1,21 @@
+# frozen_string_literal: true
+
+class FinalizeBackfillUuidConversionColumnInVulnerabilityOccurrences < Gitlab::Database::Migration[2.2]
+ milestone '16.7'
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ ensure_batched_background_migration_is_finished(
+ job_class_name: 'BackfillUuidConversionColumnInVulnerabilityOccurrences',
+ table_name: :vulnerability_occurrences,
+ column_name: :id,
+ job_arguments: [],
+ finalize: true
+ )
+ end
+
+ def down; end
+end
diff --git a/db/schema_migrations/20231207221056 b/db/schema_migrations/20231207221056
new file mode 100644
index 00000000000..369ccababfd
--- /dev/null
+++ b/db/schema_migrations/20231207221056
@@ -0,0 +1 @@
+3bdc91047eca270076e85f80b215b7944b29e00ba4a859e73ef03dab15234370 \ No newline at end of file
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index d92495dafdd..5a3495aaff0 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -2066,28 +2066,6 @@ Input type: `BulkRunnerDeleteInput`
| <a id="mutationbulkrunnerdeletedeletedids"></a>`deletedIds` | [`[CiRunnerID!]`](#cirunnerid) | IDs of records effectively deleted. Only present if operation was performed synchronously. |
| <a id="mutationbulkrunnerdeleteerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-### `Mutation.catalogResourceUnpublish`
-
-WARNING:
-**Introduced** in 16.6.
-This feature is an Experiment. It can be changed or removed at any time.
-
-Input type: `CatalogResourceUnpublishInput`
-
-#### Arguments
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationcatalogresourceunpublishclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcatalogresourceunpublishid"></a>`id` | [`CiCatalogResourceID!`](#cicatalogresourceid) | Global ID of the catalog resource to unpublish. |
-
-#### Fields
-
-| Name | Type | Description |
-| ---- | ---- | ----------- |
-| <a id="mutationcatalogresourceunpublishclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
-| <a id="mutationcatalogresourceunpublisherrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
-
### `Mutation.catalogResourcesCreate`
WARNING:
diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md
index 598d95d3190..9d0d59e27c5 100644
--- a/doc/development/documentation/styleguide/word_list.md
+++ b/doc/development/documentation/styleguide/word_list.md
@@ -650,6 +650,17 @@ Do not confuse with [download](#download).
We want users to find information quickly, and they rarely search for the term **FAQ**.
Information in FAQs belongs with other similar information, under an easily searchable topic title.
+## feature
+
+You should rarely need to use the word **feature**. Instead, explain what GitLab does.
+For example, use:
+
+- Use merge requests to incorporate changes into the target branch.
+
+Instead of:
+
+- Use the merge request feature to incorporate changes into the target branch.
+
## field
Use **text box** instead of **field** or **box**.
diff --git a/doc/user/enterprise_user/index.md b/doc/user/enterprise_user/index.md
index 099cea58df9..cc7e0e3b499 100644
--- a/doc/user/enterprise_user/index.md
+++ b/doc/user/enterprise_user/index.md
@@ -7,7 +7,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Enterprise users **(PREMIUM SAAS)**
Enterprise users have user accounts that are administered by an organization that
-has purchased a [GitLab subscription](../../subscriptions/index.md).
+has [verified their email domain](../project/pages/custom_domains_ssl_tls_certification/index.md) and purchased a [GitLab subscription](../../subscriptions/index.md).
Enterprise users are identified by the **Enterprise** badge
next to their names on the [Members list](../group/index.md#filter-and-sort-members-in-a-group).
diff --git a/gems/gitlab-housekeeper/lib/gitlab/housekeeper/keep.rb b/gems/gitlab-housekeeper/lib/gitlab/housekeeper/keep.rb
index 06d4c6d1afe..ecd55008a80 100644
--- a/gems/gitlab-housekeeper/lib/gitlab/housekeeper/keep.rb
+++ b/gems/gitlab-housekeeper/lib/gitlab/housekeeper/keep.rb
@@ -2,7 +2,28 @@
module Gitlab
module Housekeeper
- class Keep # rubocop:disable Lint/EmptyClass
+ # A Keep is analogous to a Cop in RuboCop. The Keep is responsible for:
+ # - Detecting a specific code change that should be made (eg. removing an old feature flag)
+ # - Making the code change (eg. delete the feature flag YML file)
+ # - Yielding a Change object that describes this change, For example:
+ # ```
+ # yield Gitlab::Housekeeper::Change.new(
+ # identifiers: ['remove-old-ff', 'old_ff_name'], # Unique and stable identifier for branch name
+ # title: "Remove old feature flag old_ff_name as it has been enabled since %15.0",
+ # description: "This feature flag was enabled in 15.0 and is not needed anymore ...",
+ # changed_files: ["config/feature_flags/ops/old_ff_name.yml", "app/models/user.rb"]
+ # )
+ # ```
+ class Keep
+ # The each_change method must update local working copy files and yield a Change object which describes the
+ # specific changed files and other data that will be used to generate a merge request. This is the core
+ # implementation details for a specific housekeeper keep. This does not need to commit the changes or create the
+ # merge request as that is handled by the gitlab-housekeeper gem.
+ #
+ # @yieldparam [Gitlab::Housekeeper::Change]
+ def each_change
+ raise NotImplementedError, "A Keep must implement each_change method"
+ end
end
end
end
diff --git a/gems/gitlab-housekeeper/lib/gitlab/housekeeper/runner.rb b/gems/gitlab-housekeeper/lib/gitlab/housekeeper/runner.rb
index 98e28d3de97..76d629e29a3 100644
--- a/gems/gitlab-housekeeper/lib/gitlab/housekeeper/runner.rb
+++ b/gems/gitlab-housekeeper/lib/gitlab/housekeeper/runner.rb
@@ -27,8 +27,9 @@ module Gitlab
created = 0
git.with_branch_from_branch do
- @keeps.each do |keep|
- keep.new.each do |change|
+ @keeps.each do |keep_class|
+ keep = keep_class.new
+ keep.each_change do |change|
branch_name = git.commit_in_branch(change)
if @dry_run
diff --git a/gems/gitlab-housekeeper/spec/gitlab/housekeeper/git_spec.rb b/gems/gitlab-housekeeper/spec/gitlab/housekeeper/git_spec.rb
index 23aba5fc791..8cf69d2b62c 100644
--- a/gems/gitlab-housekeeper/spec/gitlab/housekeeper/git_spec.rb
+++ b/gems/gitlab-housekeeper/spec/gitlab/housekeeper/git_spec.rb
@@ -40,7 +40,7 @@ RSpec.describe ::Gitlab::Housekeeper::Git do
end
after do
- Dir.chdir(@previous_dir) if @previous_dir # rubocop:disable RSpec/InstanceVariable
+ Dir.chdir(@previous_dir) if @previous_dir # rubocop:disable RSpec/InstanceVariable -- let not suitable for before/after cleanup
FileUtils.rm_rf(repository_path)
end
diff --git a/gems/gitlab-housekeeper/spec/gitlab/housekeeper/runner_spec.rb b/gems/gitlab-housekeeper/spec/gitlab/housekeeper/runner_spec.rb
index be9ced21fba..49b4926dbdd 100644
--- a/gems/gitlab-housekeeper/spec/gitlab/housekeeper/runner_spec.rb
+++ b/gems/gitlab-housekeeper/spec/gitlab/housekeeper/runner_spec.rb
@@ -4,7 +4,7 @@ require 'spec_helper'
require 'gitlab/housekeeper/runner'
RSpec.describe ::Gitlab::Housekeeper::Runner do
- let(:fake_keep) { double(:fake_keep) } # rubocop:disable RSpec/VerifiedDoubles
+ let(:fake_keep) { instance_double(Class) }
let(:change1) do
::Gitlab::Housekeeper::Change.new(
@@ -34,10 +34,10 @@ RSpec.describe ::Gitlab::Housekeeper::Runner do
end
before do
- fake_keep_instance = double(:fake_keep_instance) # rubocop:disable RSpec/VerifiedDoubles
+ fake_keep_instance = instance_double(::Gitlab::Housekeeper::Keep)
allow(fake_keep).to receive(:new).and_return(fake_keep_instance)
- allow(fake_keep_instance).to receive(:each)
+ allow(fake_keep_instance).to receive(:each_change)
.and_yield(change1)
.and_yield(change2)
.and_yield(change3)
diff --git a/keeps/overdue_finalize_background_migration.rb b/keeps/overdue_finalize_background_migration.rb
index ebeca23a17c..aaaa9ab1159 100644
--- a/keeps/overdue_finalize_background_migration.rb
+++ b/keeps/overdue_finalize_background_migration.rb
@@ -1,16 +1,33 @@
# frozen_string_literal: true
-require ::File.expand_path('../config/environment', __dir__)
+require_relative '../config/environment'
require_relative '../lib/generators/post_deployment_migration/post_deployment_migration_generator'
require_relative './helpers/postgres_ai'
module Keeps
+ # This is an implementation of a ::Gitlab::Housekeeper::Keep. This keep will locate any old batched background
+ # migrations that were added before CUTOFF_MILESTONE and then check if they are finished by querying Postgres.ai
+ # database archive. Once it has determined it is safe to finalize the batched background migration it will generate a
+ # new migration which calls `ensure_batched_background_migration_is_finished` for this migration. It also updates the
+ # `db/docs/batched_background_migrations` file with `finalized_by` and generates the `schema_migrations` file.
+ #
+ # This keep requires the following additional environment variables to be set:
+ # - POSTGRES_AI_CONNECTION_STRING: A valid postgres connection string
+ # - POSTGRES_AI_PASSWORD: The password for the postgres database in connection string
+ #
+ # You can run it individually with:
+ #
+ # ```
+ # bundle exec gitlab-housekeeper -d \
+ # -r keeps/overdue_finalize_background_migration.rb \
+ # -k Keeps::OverdueFinalizeBackgroundMigration
+ # ```
class OverdueFinalizeBackgroundMigration < ::Gitlab::Housekeeper::Keep
CUTOFF_MILESTONE = '16.4'
def initialize; end
- def each
+ def each_change
each_batched_background_migration do |migration_yaml_file, migration|
next unless before_cuttoff_milestone?(migration['milestone'])
diff --git a/lib/gitlab/ci/config/entry/release.rb b/lib/gitlab/ci/config/entry/release.rb
index 2be0eae120b..113e6fefd6a 100644
--- a/lib/gitlab/ci/config/entry/release.rb
+++ b/lib/gitlab/ci/config/entry/release.rb
@@ -16,12 +16,6 @@ module Gitlab
attributes %i[tag_name tag_message name ref milestones assets].freeze
attr_reader :released_at
- # Attributable description conflicts with
- # ::Gitlab::Config::Entry::Node.description
- def has_description?
- true
- end
-
def description
config[:description]
end
diff --git a/lib/organization/current_organization.rb b/lib/organization/current_organization.rb
new file mode 100644
index 00000000000..d1f50aba7a1
--- /dev/null
+++ b/lib/organization/current_organization.rb
@@ -0,0 +1,23 @@
+# frozen_string_literal: true
+
+module Organization
+ module CurrentOrganization
+ CURRENT_ORGANIZATION_THREAD_VAR = :current_organization
+
+ def current_organization
+ Thread.current[CURRENT_ORGANIZATION_THREAD_VAR]
+ end
+
+ def current_organization=(organization)
+ Thread.current[CURRENT_ORGANIZATION_THREAD_VAR] = organization
+ end
+
+ def with_current_organization(organization, &_blk)
+ previous_organization = current_organization
+ self.current_organization = organization
+ yield
+ ensure
+ self.current_organization = previous_organization
+ end
+ end
+end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index f5478c84e57..7ded76268b3 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7352,12 +7352,6 @@ msgstr ""
msgid "Automatically update this project's branches and tags from the upstream repository."
msgstr ""
-msgid "Automation"
-msgstr ""
-
-msgid "Automation|Automation App"
-msgstr ""
-
msgid "Autosave|Note"
msgstr ""
@@ -54530,6 +54524,9 @@ msgstr ""
msgid "Webhooks|Secret token"
msgstr ""
+msgid "Webhooks|Secret token will be cleared on save unless token is updated."
+msgstr ""
+
msgid "Webhooks|Sensitive portion of URL"
msgstr ""
diff --git a/scripts/rspec_helpers.sh b/scripts/rspec_helpers.sh
index 6873a2d637a..60b0db1eaf2 100644
--- a/scripts/rspec_helpers.sh
+++ b/scripts/rspec_helpers.sh
@@ -226,8 +226,8 @@ function handle_retry_rspec_in_new_process() {
exit "${rspec_run_status}"
}
-function rspec_paralellized_job() {
- echo "[$(date '+%H:%M:%S')] Starting rspec_paralellized_job"
+function rspec_parallelized_job() {
+ echo "[$(date '+%H:%M:%S')] Starting rspec_parallelized_job"
read -ra job_name <<< "${CI_JOB_NAME}"
local test_tool="${job_name[0]}"
diff --git a/spec/factories/user_custom_attributes.rb b/spec/factories/user_custom_attributes.rb
index 7bd5c06f4ef..c068da9a39f 100644
--- a/spec/factories/user_custom_attributes.rb
+++ b/spec/factories/user_custom_attributes.rb
@@ -5,5 +5,10 @@ FactoryBot.define do
user
sequence(:key) { |n| "key#{n}" }
sequence(:value) { |n| "value#{n}" }
+
+ trait :assumed_high_risk_reason do
+ key { UserCustomAttribute::ASSUMED_HIGH_RISK_REASON }
+ value { 'reason' }
+ end
end
end
diff --git a/spec/features/search/user_uses_header_search_field_spec.rb b/spec/features/search/user_uses_header_search_field_spec.rb
index 1ab47f6fd59..e36b04636ce 100644
--- a/spec/features/search/user_uses_header_search_field_spec.rb
+++ b/spec/features/search/user_uses_header_search_field_spec.rb
@@ -83,7 +83,7 @@ RSpec.describe 'User uses header search field', :js, :disable_rate_limiter, feat
end
end
- context 'when clicking merge requests', quarantine: 'https://gitlab.com/gitlab-org/gitlab/-/issues/332317' do
+ context 'when clicking merge requests' do
let!(:merge_request) { create(:merge_request, source_project: project, author: user, assignees: [user]) }
it 'shows assigned merge requests' do
diff --git a/spec/frontend/ci/pipeline_editor/components/validate/ci_validate_spec.js b/spec/frontend/ci/pipeline_editor/components/validate/ci_validate_spec.js
index f2818277c59..b66b44e5f06 100644
--- a/spec/frontend/ci/pipeline_editor/components/validate/ci_validate_spec.js
+++ b/spec/frontend/ci/pipeline_editor/components/validate/ci_validate_spec.js
@@ -1,5 +1,12 @@
import Vue from 'vue';
-import { GlAlert, GlDisclosureDropdown, GlIcon, GlLoadingIcon, GlPopover } from '@gitlab/ui';
+import {
+ GlAlert,
+ GlDisclosureDropdown,
+ GlEmptyState,
+ GlIcon,
+ GlLoadingIcon,
+ GlPopover,
+} from '@gitlab/ui';
import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
@@ -70,7 +77,7 @@ describe('Pipeline Editor Validate Tab', () => {
const findCta = () => wrapper.findByTestId('simulate-pipeline-button');
const findDisabledCtaTooltip = () => wrapper.findByTestId('cta-tooltip');
const findHelpIcon = () => wrapper.findComponent(GlIcon);
- const findIllustration = () => wrapper.findByRole('img');
+ const findEmptyState = () => wrapper.findComponent(GlEmptyState);
const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon);
const findPipelineSource = () => wrapper.findComponent(GlDisclosureDropdown);
const findPopover = () => wrapper.findComponent(GlPopover);
@@ -283,7 +290,7 @@ describe('Pipeline Editor Validate Tab', () => {
it('returns to init state', async () => {
// init state
- expect(findIllustration().exists()).toBe(true);
+ expect(findEmptyState().exists()).toBe(true);
expect(findCiLintResults().exists()).toBe(false);
// mutations should have successful results
@@ -294,7 +301,7 @@ describe('Pipeline Editor Validate Tab', () => {
await findCancelBtn().vm.$emit('click');
// should still render init state
- expect(findIllustration().exists()).toBe(true);
+ expect(findEmptyState().exists()).toBe(true);
expect(findCiLintResults().exists()).toBe(false);
});
});
diff --git a/spec/frontend/content_editor/services/markdown_serializer_spec.js b/spec/frontend/content_editor/services/markdown_serializer_spec.js
index 4dcbbfee64a..c329a12bcc4 100644
--- a/spec/frontend/content_editor/services/markdown_serializer_spec.js
+++ b/spec/frontend/content_editor/services/markdown_serializer_spec.js
@@ -152,19 +152,26 @@ describe('markdownSerializer', () => {
expect(serialize(paragraph(italic('italics')))).toBe('_italics_');
});
- it('correctly serializes code blocks wrapped by italics and bold marks', () => {
- const codeBlockContent = 'code block';
-
- expect(serialize(paragraph(italic(code(codeBlockContent))))).toBe(`_\`${codeBlockContent}\`_`);
- expect(serialize(paragraph(code(italic(codeBlockContent))))).toBe(`_\`${codeBlockContent}\`_`);
- expect(serialize(paragraph(bold(code(codeBlockContent))))).toBe(`**\`${codeBlockContent}\`**`);
- expect(serialize(paragraph(code(bold(codeBlockContent))))).toBe(`**\`${codeBlockContent}\`**`);
- expect(serialize(paragraph(strike(code(codeBlockContent))))).toBe(
- `~~\`${codeBlockContent}\`~~`,
- );
- expect(serialize(paragraph(code(strike(codeBlockContent))))).toBe(
- `~~\`${codeBlockContent}\`~~`,
- );
+ it.each`
+ input | output
+ ${'code'} | ${'`code`'}
+ ${'code `with` backticks'} | ${'``code `with` backticks``'}
+ ${'this is `inline-code`'} | ${'`` this is `inline-code` ``'}
+ ${'`inline-code` in markdown'} | ${'`` `inline-code` in markdown ``'}
+ ${'```js'} | ${'`` ```js ``'}
+ `('correctly serializes inline code ("$input")', ({ input, output }) => {
+ expect(serialize(paragraph(code(input)))).toBe(output);
+ });
+
+ it('correctly serializes inline code wrapped by italics and bold marks', () => {
+ const content = 'code';
+
+ expect(serialize(paragraph(italic(code(content))))).toBe(`_\`${content}\`_`);
+ expect(serialize(paragraph(code(italic(content))))).toBe(`_\`${content}\`_`);
+ expect(serialize(paragraph(bold(code(content))))).toBe(`**\`${content}\`**`);
+ expect(serialize(paragraph(code(bold(content))))).toBe(`**\`${content}\`**`);
+ expect(serialize(paragraph(strike(code(content))))).toBe(`~~\`${content}\`~~`);
+ expect(serialize(paragraph(code(strike(content))))).toBe(`~~\`${content}\`~~`);
});
it('correctly serializes inline diff', () => {
diff --git a/spec/frontend/webhooks/components/form_url_app_spec.js b/spec/frontend/webhooks/components/form_url_app_spec.js
index cbeff184e9d..fe8bba68610 100644
--- a/spec/frontend/webhooks/components/form_url_app_spec.js
+++ b/spec/frontend/webhooks/components/form_url_app_spec.js
@@ -1,5 +1,5 @@
import { nextTick } from 'vue';
-import { GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink } from '@gitlab/ui';
+import { GlFormGroup, GlFormRadio, GlFormRadioGroup, GlLink, GlAlert } from '@gitlab/ui';
import { scrollToElement } from '~/lib/utils/common_utils';
import FormUrlApp from '~/webhooks/components/form_url_app.vue';
@@ -30,6 +30,7 @@ describe('FormUrlApp', () => {
const findFormUrlPreview = () => wrapper.findByTestId('form-url-preview');
const findUrlMaskSection = () => wrapper.findByTestId('url-mask-section');
const findFormEl = () => document.querySelector('.js-webhook-form');
+ const findAlert = () => wrapper.findComponent(GlAlert);
const submitForm = () => findFormEl().dispatchEvent(new Event('submit'));
describe('template', () => {
@@ -156,6 +157,23 @@ describe('FormUrlApp', () => {
});
});
+ describe('token will be cleared warning', () => {
+ beforeEach(() => {
+ createComponent({ initialUrl: 'url' });
+ });
+
+ it('is hidden when URL has not changed', () => {
+ expect(findAlert().exists()).toBe(false);
+ });
+
+ it('is displayed when URL has changed', async () => {
+ findFormUrl().vm.$emit('input', 'another_url');
+ await nextTick();
+
+ expect(findAlert().exists()).toBe(true);
+ });
+ });
+
describe('validations', () => {
const inputRequiredText = FormUrlApp.i18n.inputRequired;
diff --git a/spec/helpers/ci/pipeline_editor_helper_spec.rb b/spec/helpers/ci/pipeline_editor_helper_spec.rb
index f86b6e3847d..7a80aff27c1 100644
--- a/spec/helpers/ci/pipeline_editor_helper_spec.rb
+++ b/spec/helpers/ci/pipeline_editor_helper_spec.rb
@@ -62,7 +62,7 @@ RSpec.describe Ci::PipelineEditorHelper, feature_category: :pipeline_composition
allow(helper)
.to receive(:image_path)
- .with('illustrations/project-run-CICD-pipelines-sm.svg')
+ .with('illustrations/empty-state/empty-devops-md.svg')
.and_return('illustrations/validate.svg')
allow(helper)
diff --git a/spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb b/spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb
index 7cd9b0acb99..c0d21385ce6 100644
--- a/spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/inherit/default_spec.rb
@@ -31,6 +31,7 @@ RSpec.describe ::Gitlab::Ci::Config::Entry::Inherit::Default do
false | false
%w[image] | true
%w[before_script] | false
+ '123' | false
end
with_them do
diff --git a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
index 85b1337438e..60934eb06a5 100644
--- a/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
+++ b/spec/lib/gitlab/database/no_cross_db_foreign_keys_spec.rb
@@ -11,7 +11,6 @@ RSpec.describe 'cross-database foreign keys' do
# should be added as a comment along with the name of the column.
let!(:allowed_cross_database_foreign_keys) do
[
- 'events.author_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/429803
'gitlab_subscriptions.hosted_plan_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/422012
'group_import_states.user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/421210
'identities.saml_provider_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/422010
@@ -29,7 +28,6 @@ RSpec.describe 'cross-database foreign keys' do
'path_locks.user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/429380
'protected_branch_push_access_levels.user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/431054
'protected_branch_merge_access_levels.user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/431055
- 'security_orchestration_policy_configurations.bot_user_id', # https://gitlab.com/gitlab-org/gitlab/-/issues/429438
'user_group_callouts.user_id' # https://gitlab.com/gitlab-org/gitlab/-/issues/421287
]
end
@@ -58,4 +56,17 @@ RSpec.describe 'cross-database foreign keys' do
end
end
end
+
+ it 'only allows existing foreign keys to be present in the exempted list', :aggregate_failures do
+ allowed_cross_database_foreign_keys.each do |entry|
+ table, _ = entry.split('.')
+
+ all_foreign_keys_for_table = foreign_keys_for(table)
+ fk_entry = all_foreign_keys_for_table.find { |fk| "#{fk.from_table}.#{fk.column}" == entry }
+
+ expect(fk_entry).to be_present,
+ "`#{entry}` is no longer a foreign key. " \
+ "You must remove this entry from the `allowed_cross_database_foreign_keys` list."
+ end
+ end
end
diff --git a/spec/lib/organization/current_organization_spec.rb b/spec/lib/organization/current_organization_spec.rb
new file mode 100644
index 00000000000..ffd37ac4de9
--- /dev/null
+++ b/spec/lib/organization/current_organization_spec.rb
@@ -0,0 +1,66 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe Organization::CurrentOrganization, feature_category: :organization do
+ include described_class
+
+ after do
+ # Wipe thread variables between specs.
+ Thread.current[described_class::CURRENT_ORGANIZATION_THREAD_VAR] = nil
+ end
+
+ describe '.current_organization' do
+ subject { current_organization }
+
+ context 'when current organization is set' do
+ let(:some_organization) { create(:organization) }
+
+ before do
+ self.current_organization = some_organization
+ end
+
+ it { is_expected.to eq some_organization }
+ end
+
+ context 'when organization is not set' do
+ it { is_expected.to be_nil }
+ end
+ end
+
+ describe '.current_organization=' do
+ subject(:setter) { self.current_organization = some_organization }
+
+ let(:some_organization) { create(:organization) }
+
+ it 'sets current organization' do
+ expect { setter }.to change { current_organization }.from(nil).to(some_organization)
+ end
+ end
+
+ describe '.with_current_organization' do
+ let(:some_organization) { create(:organization) }
+
+ it 'sets current organization within block' do
+ expect(current_organization).to be_nil
+ with_current_organization(some_organization) do
+ expect(current_organization).to eq some_organization
+ end
+ expect(current_organization).to be_nil
+ end
+
+ context 'when an error is raised' do
+ it 'resets current organization' do
+ begin
+ with_current_organization(some_organization) do
+ raise StandardError
+ end
+ rescue StandardError
+ nil
+ end
+
+ expect(current_organization).to be_nil
+ end
+ end
+ end
+end
diff --git a/spec/models/ci/catalog/resource_spec.rb b/spec/models/ci/catalog/resource_spec.rb
index b597586e899..15d8b4f440b 100644
--- a/spec/models/ci/catalog/resource_spec.rb
+++ b/spec/models/ci/catalog/resource_spec.rb
@@ -222,29 +222,6 @@ RSpec.describe Ci::Catalog::Resource, feature_category: :pipeline_composition do
end
end
- describe '#unpublish!' do
- context 'when the catalog resource is in published state' do
- it 'updates the state of the catalog resource to draft' do
- resource_a.update!(state: :published)
- expect(resource_a.state).to eq('published')
-
- resource_a.unpublish!
-
- expect(resource_a.reload.state).to eq('draft')
- end
- end
-
- context 'when the catalog resource is already in draft state' do
- it 'leaves the state as draft' do
- expect(resource_a.state).to eq('draft')
-
- resource_a.unpublish!
-
- expect(resource_a.reload.state).to eq('draft')
- end
- end
- end
-
describe 'synchronizing denormalized columns with `projects` table', :sidekiq_inline do
let_it_be_with_reload(:project) { create(:project, name: 'Test project', description: 'Test description') }
diff --git a/spec/models/user_custom_attribute_spec.rb b/spec/models/user_custom_attribute_spec.rb
index 3df1f074329..6eaa1452651 100644
--- a/spec/models/user_custom_attribute_spec.rb
+++ b/spec/models/user_custom_attribute_spec.rb
@@ -168,4 +168,34 @@ RSpec.describe UserCustomAttribute, feature_category: :user_profile do
end
end
end
+
+ describe '.set_assumed_high_risk_reason' do
+ let_it_be(:user) { create(:user) }
+ let(:reason) { 'Because' }
+
+ subject(:call_method) { described_class.set_assumed_high_risk_reason(user: user, reason: reason) }
+
+ it 'creates a custom attribute with correct attribute values for the user' do
+ expect { call_method }.to change { user.custom_attributes.count }.by(1)
+
+ record = user.custom_attributes.find_by_key(UserCustomAttribute::ASSUMED_HIGH_RISK_REASON)
+ expect(record.value).to eq 'Because'
+ end
+
+ context 'when passed in user is nil' do
+ let(:user) { nil }
+
+ it 'does nothing' do
+ expect { call_method }.not_to change { UserCustomAttribute.count }
+ end
+ end
+
+ context 'when there is no reason passed in' do
+ let(:reason) { nil }
+
+ it 'does nothing' do
+ expect { call_method }.not_to change { UserCustomAttribute.count }
+ end
+ end
+ end
end
diff --git a/spec/requests/api/graphql/mutations/ci/catalog/resources/unpublish_spec.rb b/spec/requests/api/graphql/mutations/ci/catalog/resources/unpublish_spec.rb
deleted file mode 100644
index 07465777263..00000000000
--- a/spec/requests/api/graphql/mutations/ci/catalog/resources/unpublish_spec.rb
+++ /dev/null
@@ -1,52 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe 'CatalogResourceUnpublish', feature_category: :pipeline_composition do
- include GraphqlHelpers
-
- let_it_be(:current_user) { create(:user) }
- let_it_be_with_reload(:resource) { create(:ci_catalog_resource) }
-
- let(:mutation) do
- graphql_mutation(
- :catalog_resource_unpublish,
- id: resource.to_gid.to_s
- )
- end
-
- subject(:post_query) { post_graphql_mutation(mutation, current_user: current_user) }
-
- context 'when unauthorized' do
- it_behaves_like 'a mutation that returns a top-level access error'
- end
-
- context 'when authorized' do
- before_all do
- resource.project.add_owner(current_user)
- end
-
- context 'when the catalog resource is in published state' do
- it 'updates the state to draft' do
- resource.update!(state: :published)
- expect(resource.state).to eq('published')
-
- post_query
-
- expect(resource.reload.state).to eq('draft')
- expect_graphql_errors_to_be_empty
- end
- end
-
- context 'when the catalog resource is already in draft state' do
- it 'leaves the state as draft' do
- expect(resource.state).to eq('draft')
-
- post_query
-
- expect(resource.reload.state).to eq('draft')
- expect_graphql_errors_to_be_empty
- end
- end
- end
-end
diff --git a/vendor/gems/sidekiq-reliable-fetch/lib/sidekiq/base_reliable_fetch.rb b/vendor/gems/sidekiq-reliable-fetch/lib/sidekiq/base_reliable_fetch.rb
index 006aad87abe..e8ee6d7df45 100644
--- a/vendor/gems/sidekiq-reliable-fetch/lib/sidekiq/base_reliable_fetch.rb
+++ b/vendor/gems/sidekiq-reliable-fetch/lib/sidekiq/base_reliable_fetch.rb
@@ -179,6 +179,7 @@ module Sidekiq
Sidekiq.logger.info(
message: "Pushed job #{msg['jid']} back to queue #{queue}",
jid: msg['jid'],
+ class: msg['class'],
queue: queue
)
end
diff --git a/vendor/gems/sidekiq-reliable-fetch/spec/base_reliable_fetch_spec.rb b/vendor/gems/sidekiq-reliable-fetch/spec/base_reliable_fetch_spec.rb
index 32e62925aaf..990d699e2f8 100644
--- a/vendor/gems/sidekiq-reliable-fetch/spec/base_reliable_fetch_spec.rb
+++ b/vendor/gems/sidekiq-reliable-fetch/spec/base_reliable_fetch_spec.rb
@@ -5,7 +5,7 @@ require 'sidekiq/reliable_fetch'
require 'sidekiq/semi_reliable_fetch'
describe Sidekiq::BaseReliableFetch do
- let(:job) { Sidekiq.dump_json(class: 'Bob', args: [1, 2, 'foo']) }
+ let(:job) { Sidekiq.dump_json(class: 'Bob', args: [1, 2, 'foo'], jid: 55) }
before { Sidekiq.redis(&:flushdb) }
@@ -47,6 +47,16 @@ describe Sidekiq::BaseReliableFetch do
it 'requeues the bulk' do
uow = described_class::UnitOfWork
jobs = [ uow.new('queue:foo', job), uow.new('queue:foo', job), uow.new('queue:bar', job) ]
+
+ jobs.map(&:queue).each do |q|
+ expect(Sidekiq.logger).to receive(:info).with(
+ message: "Pushed job 55 back to queue #{q}",
+ jid: 55,
+ class: 'Bob',
+ queue: q
+ )
+ end
+
described_class.new(options).bulk_requeue(jobs, nil)
expect(queue1.size).to eq 2