diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-18 15:07:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-12-18 15:07:35 +0300 |
commit | 00cfeb7c25bdbd460efb83ad846cb924e73ee150 (patch) | |
tree | 944cb1af2640f1958efe878de969844ef578cbef | |
parent | 92de2642b384f7d6ac3bf3c1f0862b067306c9be (diff) |
Add latest changes from gitlab-org/gitlab@master
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 @@ -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 |