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-11-24 18:12:40 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-11-24 18:12:40 +0300
commit92849dc177d5e0d11f89b4ca75f4e3e45ad6341b (patch)
tree6dd67ad9b1edc1ca2ded39077c041ffdd0ea38e0
parent83ffdf48518e121c1ccab9d7913d3f7e79d7766c (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/workhorse.gitlab-ci.yml2
-rw-r--r--.rubocop_todo/capybara/testid_finders.yml12
-rw-r--r--.rubocop_todo/rspec/file_path.yml1
-rw-r--r--.rubocop_todo/rspec/named_subject.yml9
-rw-r--r--.rubocop_todo/style/inline_disable_annotation.yml18
-rw-r--r--app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue14
-rw-r--r--app/assets/javascripts/editor/schema/ci.json33
-rw-r--r--app/assets/javascripts/projects/settings_service_desk/custom_email_constants.js2
-rw-r--r--app/validators/json_schema_validator.rb15
-rw-r--r--app/views/notify/service_desk_verification_result_email.html.haml2
-rw-r--r--app/views/notify/service_desk_verification_result_email.text.erb2
-rw-r--r--app/workers/bulk_imports/entity_worker.rb20
-rw-r--r--app/workers/packages/npm/create_metadata_cache_worker.rb2
-rw-r--r--config/feature_flags/development/npm_metadata_cache.yml8
-rw-r--r--config/initializers/doorkeeper.rb2
-rw-r--r--config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml3
-rw-r--r--config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml3
-rw-r--r--config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml3
-rw-r--r--config/metrics/counts_28d/20210216175554_ci_pipelines.yml1
-rw-r--r--config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml1
-rw-r--r--config/metrics/counts_28d/20210216180814_events.yml1
-rw-r--r--config/metrics/counts_28d/20210216181057_projects_with_packages.yml3
-rw-r--r--config/metrics/counts_28d/20210216181139_issues.yml3
-rw-r--r--config/metrics/counts_28d/20210216181158_epics.yml3
-rw-r--r--config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20210216181935_deployments.yml1
-rw-r--r--config/metrics/counts_28d/20210216181939_releases.yml3
-rw-r--r--config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml1
-rw-r--r--config/metrics/counts_28d/20210216182051_protected_branches.yml3
-rw-r--r--config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml3
-rw-r--r--config/metrics/counts_28d/20220621085114_unique_active_users_monthly.yml2
-rw-r--r--config/metrics/counts_all/20210216175525_ci_builds.yml2
-rw-r--r--config/metrics/counts_all/20210514141520_project_imports_total.yml2
-rw-r--r--db/post_migrate/20231122125550_drop_index_bulk_import_export_batches_on_export_id.rb18
-rw-r--r--db/schema_migrations/202311221255501
-rw-r--r--db/structure.sql2
-rw-r--r--doc/architecture/blueprints/cells/index.md11
-rw-r--r--doc/ci/yaml/index.md67
-rw-r--r--doc/user/project/service_desk/configure.md32
-rw-r--r--lib/api/concerns/packages/npm_endpoints.rb2
-rw-r--r--lib/api/entities/ci/job_request/image.rb1
-rw-r--r--lib/api/entities/ci/job_request/service.rb1
-rw-r--r--lib/api/helpers/packages/npm.rb2
-rw-r--r--lib/gitlab/ci/build/image.rb4
-rw-r--r--lib/gitlab/ci/config/entry/image.rb15
-rw-r--r--lib/gitlab/ci/config/entry/imageable.rb34
-rw-r--r--lib/gitlab/ci/config/entry/schemas/imageable/executor_opts.json19
-rw-r--r--lib/gitlab/ci/config/entry/service.rb12
-rw-r--r--locale/gitlab.pot18
-rw-r--r--spec/features/groups/milestone_spec.rb2
-rw-r--r--spec/features/groups/packages_spec.rb2
-rw-r--r--spec/features/groups/settings/ci_cd_spec.rb2
-rw-r--r--spec/features/groups/settings/packages_and_registries_spec.rb8
-rw-r--r--spec/features/groups/show_spec.rb8
-rw-r--r--spec/features/groups_spec.rb8
-rw-r--r--spec/features/incidents/incident_details_spec.rb25
-rw-r--r--spec/features/incidents/incident_timeline_events_spec.rb4
-rw-r--r--spec/features/issuables/shortcuts_issuable_spec.rb2
-rw-r--r--spec/features/issues/form_spec.rb22
-rw-r--r--spec/features/issues/incident_issue_spec.rb2
-rw-r--r--spec/features/issues/issue_detail_spec.rb8
-rw-r--r--spec/frontend/editor/schema/ci/ci_schema_spec.js4
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/image.yml38
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/negative_tests/services.yml14
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/image.yml41
-rw-r--r--spec/frontend/editor/schema/ci/yaml_tests/positive_tests/services.yml7
-rw-r--r--spec/lib/api/entities/ci/job_request/image_spec.rb9
-rw-r--r--spec/lib/api/entities/ci/job_request/service_spec.rb2
-rw-r--r--spec/lib/gitlab/ci/build/image_spec.rb11
-rw-r--r--spec/lib/gitlab/ci/config/entry/image_spec.rb58
-rw-r--r--spec/lib/gitlab/ci/config/entry/service_spec.rb51
-rw-r--r--spec/lib/gitlab/ci/yaml_processor_spec.rb40
-rw-r--r--spec/requests/api/ci/runner/jobs_request_post_spec.rb57
-rw-r--r--spec/requests/api/ci/runner/jobs_request_yamls_spec.rb64
-rw-r--r--spec/requests/api/ci/runner/yamls/README.md15
-rw-r--r--spec/requests/api/ci/runner/yamls/image-basic.yml19
-rw-r--r--spec/requests/api/ci/runner/yamls/image-executor_opts-platform.yml25
-rw-r--r--spec/requests/api/ci/runner/yamls/service-basic.yml23
-rw-r--r--spec/requests/api/ci/runner/yamls/service-executor_opts-platform.yml27
-rw-r--r--spec/requests/api/ci/runner/yamls/service-variables.yml30
-rw-r--r--spec/requests/api/npm_project_packages_spec.rb8
-rw-r--r--spec/requests/oauth/tokens_controller_spec.rb27
-rw-r--r--spec/support/helpers/database/duplicate_indexes.yml3
-rw-r--r--spec/support/shared_examples/npm_sync_metadata_cache_worker_shared_examples.rb8
-rw-r--r--spec/validators/json_schema_validator_spec.rb25
-rw-r--r--spec/workers/bulk_imports/entity_worker_spec.rb24
-rw-r--r--spec/workers/packages/npm/create_metadata_cache_worker_spec.rb8
87 files changed, 955 insertions, 198 deletions
diff --git a/.gitlab/ci/workhorse.gitlab-ci.yml b/.gitlab/ci/workhorse.gitlab-ci.yml
index f10ef3ac41f..9aa0b349c16 100644
--- a/.gitlab/ci/workhorse.gitlab-ci.yml
+++ b/.gitlab/ci/workhorse.gitlab-ci.yml
@@ -47,7 +47,7 @@ workhorse:test fips:
extends: .workhorse:test
parallel:
matrix:
- - GO_VERSION: ["1.19", "1.20", "1.21"]
+ - GO_VERSION: ["1.20", "1.21"]
REDIS_VERSION: ["7.0", "6.2"]
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/ubi-${UBI_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.36-exiftool-12.60
variables:
diff --git a/.rubocop_todo/capybara/testid_finders.yml b/.rubocop_todo/capybara/testid_finders.yml
index ddaf1e27beb..f78470479e9 100644
--- a/.rubocop_todo/capybara/testid_finders.yml
+++ b/.rubocop_todo/capybara/testid_finders.yml
@@ -15,18 +15,6 @@ Capybara/TestidFinders:
- 'spec/features/groups/members/sort_members_spec.rb'
- 'spec/features/groups/members/tabs_spec.rb'
- 'spec/features/groups/merge_requests_spec.rb'
- - 'spec/features/groups/milestone_spec.rb'
- - 'spec/features/groups/packages_spec.rb'
- - 'spec/features/groups/settings/ci_cd_spec.rb'
- - 'spec/features/groups/settings/packages_and_registries_spec.rb'
- - 'spec/features/groups/show_spec.rb'
- - 'spec/features/groups_spec.rb'
- - 'spec/features/incidents/incident_details_spec.rb'
- - 'spec/features/incidents/incident_timeline_events_spec.rb'
- - 'spec/features/issuables/shortcuts_issuable_spec.rb'
- - 'spec/features/issues/form_spec.rb'
- - 'spec/features/issues/incident_issue_spec.rb'
- - 'spec/features/issues/issue_detail_spec.rb'
- 'spec/features/issues/issue_sidebar_spec.rb'
- 'spec/features/issues/issue_state_spec.rb'
- 'spec/features/issues/user_creates_issue_spec.rb'
diff --git a/.rubocop_todo/rspec/file_path.yml b/.rubocop_todo/rspec/file_path.yml
index 06832184c04..cf457973e0e 100644
--- a/.rubocop_todo/rspec/file_path.yml
+++ b/.rubocop_todo/rspec/file_path.yml
@@ -31,6 +31,7 @@ RSpec/FilePath:
- 'spec/requests/api/ci/runner/jobs_artifacts_spec.rb'
- 'spec/requests/api/ci/runner/jobs_put_spec.rb'
- 'spec/requests/api/ci/runner/jobs_request_post_spec.rb'
+ - 'spec/requests/api/ci/runner/jobs_request_yamls_spec.rb'
- 'spec/requests/api/ci/runner/jobs_trace_spec.rb'
- 'spec/requests/api/ci/runner/runners_delete_spec.rb'
- 'spec/requests/api/ci/runner/runners_post_spec.rb'
diff --git a/.rubocop_todo/rspec/named_subject.yml b/.rubocop_todo/rspec/named_subject.yml
index 960b5bb5a05..230c2928343 100644
--- a/.rubocop_todo/rspec/named_subject.yml
+++ b/.rubocop_todo/rspec/named_subject.yml
@@ -830,7 +830,6 @@ RSpec/NamedSubject:
- 'ee/spec/requests/groups/settings/merge_requests_controller_spec.rb'
- 'ee/spec/requests/groups_controller_spec.rb'
- 'ee/spec/requests/projects/analytics/cycle_analytics/stages_controller_spec.rb'
- - 'ee/spec/requests/projects/metrics_controller_spec.rb'
- 'ee/spec/requests/projects/pipelines_controller_spec.rb'
- 'ee/spec/requests/projects/requirements_management/requirements_controller_spec.rb'
- 'ee/spec/requests/projects/security/policies_controller_spec.rb'
@@ -894,7 +893,6 @@ RSpec/NamedSubject:
- 'ee/spec/serializers/vulnerability_entity_spec.rb'
- 'ee/spec/serializers/vulnerability_note_entity_spec.rb'
- 'ee/spec/services/admin/email_service_spec.rb'
- - 'ee/spec/services/ai/service_access_tokens_storage_service_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/stages/list_service_spec.rb'
- 'ee/spec/services/analytics/cycle_analytics/value_streams/update_service_spec.rb'
- 'ee/spec/services/analytics/devops_adoption/enabled_namespaces/find_or_create_service_spec.rb'
@@ -1018,7 +1016,6 @@ RSpec/NamedSubject:
- 'ee/spec/services/ee/projects/autocomplete_service_spec.rb'
- 'ee/spec/services/ee/projects/deploy_tokens/create_service_spec.rb'
- 'ee/spec/services/ee/projects/deploy_tokens/destroy_service_spec.rb'
- - 'ee/spec/services/ee/projects/unlink_fork_service_spec.rb'
- 'ee/spec/services/ee/resource_events/change_labels_service_spec.rb'
- 'ee/spec/services/ee/system_notes/issuables_service_spec.rb'
- 'ee/spec/services/ee/terraform/states/destroy_service_spec.rb'
@@ -1096,7 +1093,6 @@ RSpec/NamedSubject:
- 'ee/spec/services/llm/generate_test_file_service_spec.rb'
- 'ee/spec/services/llm/git_command_service_spec.rb'
- 'ee/spec/services/llm/resolve_vulnerability_service_spec.rb'
- - 'ee/spec/services/member_roles/create_service_spec.rb'
- 'ee/spec/services/merge_request_approval_settings/update_service_spec.rb'
- 'ee/spec/services/merge_requests/merge_service_spec.rb'
- 'ee/spec/services/merge_requests/mergeability/check_external_status_checks_passed_service_spec.rb'
@@ -1778,6 +1774,7 @@ RSpec/NamedSubject:
- 'spec/lib/bulk_imports/projects/graphql/get_project_query_spec.rb'
- 'spec/lib/bulk_imports/projects/graphql/get_repository_query_spec.rb'
- 'spec/lib/bulk_imports/projects/graphql/get_snippet_repository_query_spec.rb'
+ - 'spec/lib/bulk_imports/projects/pipelines/legacy_references_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/pipelines/references_pipeline_spec.rb'
- 'spec/lib/bulk_imports/projects/stage_spec.rb'
- 'spec/lib/bulk_imports/source_url_builder_spec.rb'
@@ -2589,7 +2586,6 @@ RSpec/NamedSubject:
- 'spec/mailers/emails/imports_spec.rb'
- 'spec/mailers/emails/issues_spec.rb'
- 'spec/mailers/emails/merge_requests_spec.rb'
- - 'spec/mailers/emails/service_desk_spec.rb'
- 'spec/mailers/notify_spec.rb'
- 'spec/metrics_server/metrics_server_spec.rb'
- 'spec/migrations/20221028022627_add_index_on_password_last_changed_at_to_user_details_spec.rb'
@@ -2744,7 +2740,6 @@ RSpec/NamedSubject:
- 'spec/models/integrations/bamboo_spec.rb'
- 'spec/models/integrations/base_chat_notification_spec.rb'
- 'spec/models/integrations/base_issue_tracker_spec.rb'
- - 'spec/models/integrations/base_third_party_wiki_spec.rb'
- 'spec/models/integrations/bugzilla_spec.rb'
- 'spec/models/integrations/buildkite_spec.rb'
- 'spec/models/integrations/campfire_spec.rb'
@@ -2776,7 +2771,6 @@ RSpec/NamedSubject:
- 'spec/models/integrations/pivotaltracker_spec.rb'
- 'spec/models/integrations/pushover_spec.rb'
- 'spec/models/integrations/redmine_spec.rb'
- - 'spec/models/integrations/shimo_spec.rb'
- 'spec/models/integrations/squash_tm_spec.rb'
- 'spec/models/integrations/teamcity_spec.rb'
- 'spec/models/integrations/telegram_spec.rb'
@@ -2864,7 +2858,6 @@ RSpec/NamedSubject:
- 'spec/models/terraform/state_version_spec.rb'
- 'spec/models/timelog_spec.rb'
- 'spec/models/todo_spec.rb'
- - 'spec/models/tree_spec.rb'
- 'spec/models/upload_spec.rb'
- 'spec/models/uploads/fog_spec.rb'
- 'spec/models/uploads/local_spec.rb'
diff --git a/.rubocop_todo/style/inline_disable_annotation.yml b/.rubocop_todo/style/inline_disable_annotation.yml
index 37c6c6b93b4..e49171b0362 100644
--- a/.rubocop_todo/style/inline_disable_annotation.yml
+++ b/.rubocop_todo/style/inline_disable_annotation.yml
@@ -327,7 +327,6 @@ Style/InlineDisableAnnotation:
- 'app/graphql/types/user_preferences_type.rb'
- 'app/graphql/types/user_status_type.rb'
- 'app/graphql/types/work_item_id_type.rb'
- - 'app/graphql/types/work_items/linked_item_type.rb'
- 'app/graphql/types/work_items/widgets/assignees_type.rb'
- 'app/graphql/types/work_items/widgets/award_emoji_type.rb'
- 'app/graphql/types/work_items/widgets/current_user_todos_type.rb'
@@ -688,10 +687,8 @@ Style/InlineDisableAnnotation:
- 'app/services/packages/conan/single_package_search_service.rb'
- 'app/services/packages/create_dependency_service.rb'
- 'app/services/packages/create_package_service.rb'
- - 'app/services/packages/debian/extract_metadata_service.rb'
- 'app/services/packages/debian/generate_distribution_key_service.rb'
- 'app/services/packages/debian/generate_distribution_service.rb'
- - 'app/services/packages/helm/extract_file_metadata_service.rb'
- 'app/services/packages/npm/create_package_service.rb'
- 'app/services/packages/nuget/create_dependency_service.rb'
- 'app/services/packages/nuget/extract_remote_metadata_file_service.rb'
@@ -806,6 +803,7 @@ Style/InlineDisableAnnotation:
- 'app/workers/bulk_imports/pipeline_worker.rb'
- 'app/workers/bulk_imports/relation_batch_export_worker.rb'
- 'app/workers/bulk_imports/stuck_import_worker.rb'
+ - 'app/workers/bulk_imports/transform_references_worker.rb'
- 'app/workers/chaos/cpu_spin_worker.rb'
- 'app/workers/chaos/db_spin_worker.rb'
- 'app/workers/chaos/kill_worker.rb'
@@ -1987,7 +1985,6 @@ Style/InlineDisableAnnotation:
- 'ee/lib/gitlab/insights/executors/issuable_executor.rb'
- 'ee/lib/gitlab/insights/finders/issuable_finder.rb'
- 'ee/lib/gitlab/insights/reducers/count_per_period_reducer.rb'
- - 'ee/lib/gitlab/llm/ai_message.rb'
- 'ee/lib/gitlab/llm/chain/tools/identifier.rb'
- 'ee/lib/gitlab/llm/chain/tools/json_reader/executor.rb'
- 'ee/lib/gitlab/llm/chain/tools/summarize_comments/executor.rb'
@@ -2011,7 +2008,6 @@ Style/InlineDisableAnnotation:
- 'ee/lib/product_analytics/settings.rb'
- 'ee/lib/quality/seeders/vulnerabilities.rb'
- 'ee/lib/system_check/geo/authorized_keys_check.rb'
- - 'ee/lib/system_check/geo/geo_database_configured_check.rb'
- 'ee/lib/tasks/geo.rake'
- 'ee/lib/tasks/gitlab/elastic.rake'
- 'ee/locale/unfound_translations.rb'
@@ -2284,7 +2280,6 @@ Style/InlineDisableAnnotation:
- 'lib/bulk_imports/file_downloads/filename_fetch.rb'
- 'lib/bulk_imports/groups/transformers/group_attributes_transformer.rb'
- 'lib/bulk_imports/pipeline/runner.rb'
- - 'lib/bulk_imports/projects/pipelines/references_pipeline.rb'
- 'lib/bulk_imports/uniquify.rb'
- 'lib/click_house/models/base_model.rb'
- 'lib/click_house/query_builder.rb'
@@ -2464,7 +2459,6 @@ Style/InlineDisableAnnotation:
- 'lib/gitlab/console.rb'
- 'lib/gitlab/container_repository/tags/cache.rb'
- 'lib/gitlab/content_security_policy/config_loader.rb'
- - 'lib/gitlab/contributions_calendar.rb'
- 'lib/gitlab/current_settings.rb'
- 'lib/gitlab/daemon.rb'
- 'lib/gitlab/data_builder/pipeline.rb'
@@ -2526,7 +2520,6 @@ Style/InlineDisableAnnotation:
- 'lib/gitlab/encoding_helper.rb'
- 'lib/gitlab/encrypted_command_base.rb'
- 'lib/gitlab/encrypted_incoming_email_command.rb'
- - 'lib/gitlab/encrypted_ldap_command.rb'
- 'lib/gitlab/encrypted_redis_command.rb'
- 'lib/gitlab/encrypted_service_desk_email_command.rb'
- 'lib/gitlab/encrypted_smtp_command.rb'
@@ -2561,7 +2554,6 @@ Style/InlineDisableAnnotation:
- 'lib/gitlab/github_import/importer/labels_importer.rb'
- 'lib/gitlab/github_import/importer/milestones_importer.rb'
- 'lib/gitlab/github_import/importer/note_importer.rb'
- - 'lib/gitlab/github_import/importer/pull_requests/review_importer.rb'
- 'lib/gitlab/github_import/importer/pull_requests/review_requests_importer.rb'
- 'lib/gitlab/github_import/importer/releases_importer.rb'
- 'lib/gitlab/github_import/importer/repository_importer.rb'
@@ -2767,8 +2759,6 @@ Style/InlineDisableAnnotation:
- 'qa/qa/ee/page/main/banner.rb'
- 'qa/qa/ee/page/project/monitor/on_call_schedule/index.rb'
- 'qa/qa/ee/page/project/settings/merge_request.rb'
- - 'qa/qa/ee/page/workspace/action.rb'
- - 'qa/qa/ee/page/workspace/list.rb'
- 'qa/qa/page/admin/applications.rb'
- 'qa/qa/page/component/access_tokens.rb'
- 'qa/qa/page/component/ci_icon.rb'
@@ -2784,11 +2774,6 @@ Style/InlineDisableAnnotation:
- 'qa/qa/page/project/settings/branch_rules_details.rb'
- 'qa/qa/page/project/settings/integrations.rb'
- 'qa/qa/page/project/settings/mirroring_repositories.rb'
- - 'qa/qa/page/project/settings/runners.rb'
- - 'qa/qa/page/project/settings/services/jenkins.rb'
- - 'qa/qa/page/project/settings/services/jira.rb'
- - 'qa/qa/page/project/settings/services/pipeline_status_emails.rb'
- - 'qa/qa/page/search/results.rb'
- 'qa/qa/page/sub_menus/super_sidebar/global_search_modal.rb'
- 'qa/qa/resource/api_fabricator.rb'
- 'qa/qa/resource/base.rb'
@@ -2807,7 +2792,6 @@ Style/InlineDisableAnnotation:
- 'qa/qa/scenario/test/integration/registry_with_cdn.rb'
- 'qa/qa/service/docker_run/gitlab_runner.rb'
- 'qa/qa/service/shellout.rb'
- - 'qa/qa/specs/features/api/1_manage/import/import_large_github_repo_spec.rb'
- 'qa/qa/specs/features/api/1_manage/migration/gitlab_migration_large_project_spec.rb'
- 'qa/qa/specs/features/browser_ui/10_govern/user/user_access_termination_spec.rb'
- 'qa/qa/specs/features/browser_ui/1_manage/integrations/jira/jira_basic_integration_spec.rb'
diff --git a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
index 504d3d38275..6e4ad5d60de 100644
--- a/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
+++ b/app/assets/javascripts/ci/catalog/components/list/ci_resources_list_item.vue
@@ -1,6 +1,6 @@
<script>
import { GlAvatar, GlBadge, GlIcon, GlLink, GlSprintf, GlTooltipDirective } from '@gitlab/ui';
-import { s__ } from '~/locale';
+import { s__, n__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { formatDate, getTimeago } from '~/lib/utils/datetime_utility';
import { cleanLeadingSeparator } from '~/lib/utils/url_utility';
@@ -49,6 +49,9 @@ export default {
starIcon() {
return this.starCount > 0 ? 'star' : 'star-o';
},
+ starCountText() {
+ return n__('Star', 'Stars', this.starCount);
+ },
hasReleasedVersion() {
return Boolean(this.latestVersion?.releasedAt);
},
@@ -115,7 +118,12 @@ export default {
<div class="gl-display-flex gl-flex-grow-1 gl-md-justify-content-space-between">
<gl-badge size="sm" class="gl-h-5 gl-align-self-center">{{ tagName }}</gl-badge>
<span class="gl-display-flex gl-align-items-center gl-ml-5">
- <span class="gl--flex-center" data-testid="stats-favorites">
+ <span
+ v-gl-tooltip.top
+ :title="starCountText"
+ class="gl--flex-center"
+ data-testid="stats-favorites"
+ >
<gl-icon :name="starIcon" :size="14" class="gl-mr-2" />
<span class="gl-mr-3">{{ starCount }}</span>
</span>
@@ -130,7 +138,7 @@ export default {
<span v-if="hasReleasedVersion">
<gl-sprintf :message="$options.i18n.releasedMessage">
<template #timeAgo>
- <span v-gl-tooltip.bottom :title="formattedDate">
+ <span v-gl-tooltip.top :title="formattedDate">
{{ releasedAt }}
</span>
</template>
diff --git a/app/assets/javascripts/editor/schema/ci.json b/app/assets/javascripts/editor/schema/ci.json
index 308a68544bc..b8d3606d23e 100644
--- a/app/assets/javascripts/editor/schema/ci.json
+++ b/app/assets/javascripts/editor/schema/ci.json
@@ -509,6 +509,18 @@
"description": "Command or script that should be executed as the container's entrypoint. It will be translated to Docker's --entrypoint option while creating the container. The syntax is similar to Dockerfile's ENTRYPOINT directive, where each shell token is a separate string in the array.",
"minItems": 1
},
+ "docker": {
+ "type": "object",
+ "markdownDescription": "Options to pass to Runners Docker Executor. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#imagedocker)",
+ "additionalProperties": false,
+ "properties": {
+ "platform": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Image architecture to pull."
+ }
+ }
+ },
"pull_policy": {
"markdownDescription": "Specifies how to pull the image in Runner. It can be one of `always`, `never` or `if-not-present`. The default value is `always`. [Learn more](https://docs.gitlab.com/ee/ci/yaml/#imagepull_policy).",
"default": "always",
@@ -540,13 +552,6 @@
"required": [
"name"
]
- },
- {
- "type": "array",
- "minLength": 1,
- "items": {
- "type": "string"
- }
}
],
"markdownDescription": "Specifies the docker image to use for the job or globally for all jobs. Job configuration takes precedence over global setting. Requires a certain kind of Gitlab runner executor. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#image)."
@@ -579,8 +584,20 @@
"type": "string"
}
},
+ "docker": {
+ "type": "object",
+ "markdownDescription": "Options to pass to Runners Docker Executor. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#servicesdocker)",
+ "additionalProperties": false,
+ "properties": {
+ "platform": {
+ "type": "string",
+ "minLength": 1,
+ "description": "Image architecture to pull."
+ }
+ }
+ },
"pull_policy": {
- "markdownDescription": "Specifies how to pull the image in Runner. It can be one of `always`, `never` or `if-not-present`. The default value is `always`. [Learn more](https://docs.gitlab.com/ee/ci/yaml/#servicepull_policy).",
+ "markdownDescription": "Specifies how to pull the image in Runner. It can be one of `always`, `never` or `if-not-present`. The default value is `always`. [Learn more](https://docs.gitlab.com/ee/ci/yaml/#servicespull_policy).",
"default": "always",
"oneOf": [
{
diff --git a/app/assets/javascripts/projects/settings_service_desk/custom_email_constants.js b/app/assets/javascripts/projects/settings_service_desk/custom_email_constants.js
index 5b0266c95df..7a3d74e1e93 100644
--- a/app/assets/javascripts/projects/settings_service_desk/custom_email_constants.js
+++ b/app/assets/javascripts/projects/settings_service_desk/custom_email_constants.js
@@ -112,7 +112,7 @@ export const I18N_ERROR_SMTP_HOST_ISSUE_DESC = s__(
);
export const I18N_ERROR_INVALID_CREDENTIALS_LABEL = s__('ServiceDesk|Invalid credentials');
export const I18N_ERROR_INVALID_CREDENTIALS_DESC = s__(
- 'ServiceDesk|The given credentials (username and password) were rejected by the SMTP server.',
+ 'ServiceDesk|The given credentials (username and password) were rejected by the SMTP server, or you need to explicitly set an authentication method.',
);
export const I18N_ERROR_MAIL_NOT_RECEIVED_IN_TIMEFRAME_LABEL = s__(
'ServiceDesk|Verification email not received within timeframe',
diff --git a/app/validators/json_schema_validator.rb b/app/validators/json_schema_validator.rb
index 2ef011df73e..f661392082f 100644
--- a/app/validators/json_schema_validator.rb
+++ b/app/validators/json_schema_validator.rb
@@ -1,4 +1,5 @@
# frozen_string_literal: true
+
#
# JsonSchemaValidator
#
@@ -24,11 +25,19 @@ class JsonSchemaValidator < ActiveModel::EachValidator
end
def validate_each(record, attribute, value)
- value = value.to_h.stringify_keys if options[:hash_conversion] == true
+ value = value.to_h.deep_stringify_keys if options[:hash_conversion] == true
value = Gitlab::Json.parse(value.to_s) if options[:parse_json] == true && !value.nil?
- unless valid_schema?(value)
- record.errors.add(attribute, _("must be a valid json schema"))
+ if options[:detail_errors]
+ validator.validate(value).each do |error|
+ message = format(
+ _("'%{data_pointer}' must be a valid '%{type}'"),
+ data_pointer: error['data_pointer'], type: error['type']
+ )
+ record.errors.add(attribute, message)
+ end
+ else
+ record.errors.add(attribute, _("must be a valid json schema")) unless valid_schema?(value)
end
end
diff --git a/app/views/notify/service_desk_verification_result_email.html.haml b/app/views/notify/service_desk_verification_result_email.html.haml
index faf8ae2e28c..651f94533ec 100644
--- a/app/views/notify/service_desk_verification_result_email.html.haml
+++ b/app/views/notify/service_desk_verification_result_email.html.haml
@@ -35,7 +35,7 @@
%p
%b
= s_('Notify|Invalid credentials:')
- = s_('Notify|The given credentials (username and password) were rejected by the SMTP server.')
+ = s_('Notify|The given credentials (username and password) were rejected by the SMTP server, or you need to explicitly set an authentication method.')
- if @verification.mail_not_received_within_timeframe?
%p
%b
diff --git a/app/views/notify/service_desk_verification_result_email.text.erb b/app/views/notify/service_desk_verification_result_email.text.erb
index fd2e4446d0b..134b6592197 100644
--- a/app/views/notify/service_desk_verification_result_email.text.erb
+++ b/app/views/notify/service_desk_verification_result_email.text.erb
@@ -18,7 +18,7 @@
<%= s_('Notify|We were not able to make a connection to the specified host or there was an SSL issue.') %>
<% elsif @verification.invalid_credentials? %>
<%= s_('Notify|Invalid credentials:') %>
- <%= s_('Notify|The given credentials (username and password) were rejected by the SMTP server.') %>
+ <%= s_('Notify|The given credentials (username and password) were rejected by the SMTP server, or you need to explicitly set an authentication method.') %>
<% elsif @verification.mail_not_received_within_timeframe? %>
<%= s_('Notify|Verification email not received within timeframe:') %>
<%= s_('Notify|We did not receive the verification email we sent out to %{strong_open}%{email_address}%{strong_close} in time.') % { email_address: verify_email_address, strong_open: '', strong_close: '' } %>
diff --git a/app/workers/bulk_imports/entity_worker.rb b/app/workers/bulk_imports/entity_worker.rb
index caee292a504..6ff2d15d6e8 100644
--- a/app/workers/bulk_imports/entity_worker.rb
+++ b/app/workers/bulk_imports/entity_worker.rb
@@ -3,9 +3,10 @@
module BulkImports
class EntityWorker
include ApplicationWorker
+ include ExclusiveLeaseGuard
idempotent!
- deduplicate :until_executed, if_deduplicated: :reschedule_once
+ deduplicate :until_executing
data_consistency :always
feature_category :importers
sidekiq_options retry: 3, dead: false
@@ -27,7 +28,10 @@ module BulkImports
if running_tracker.present?
log_info(message: 'Stage running', entity_stage: running_tracker.stage)
else
- start_next_stage
+ # Use lease guard to prevent duplicated workers from starting multiple stages
+ try_obtain_lease do
+ start_next_stage
+ end
end
re_enqueue
@@ -78,6 +82,18 @@ module BulkImports
end
end
+ def lease_timeout
+ PERFORM_DELAY
+ end
+
+ def lease_key
+ "gitlab:bulk_imports:entity_worker:#{entity.id}"
+ end
+
+ def log_lease_taken
+ log_info(message: lease_taken_message)
+ end
+
def source_version
entity.bulk_import.source_version_info.to_s
end
diff --git a/app/workers/packages/npm/create_metadata_cache_worker.rb b/app/workers/packages/npm/create_metadata_cache_worker.rb
index 0b6e34b13eb..cff7871dab7 100644
--- a/app/workers/packages/npm/create_metadata_cache_worker.rb
+++ b/app/workers/packages/npm/create_metadata_cache_worker.rb
@@ -16,7 +16,7 @@ module Packages
def perform(project_id, package_name)
project = Project.find_by_id(project_id)
- return unless project && Feature.enabled?(:npm_metadata_cache, project)
+ return unless project
::Packages::Npm::CreateMetadataCacheService
.new(project, package_name)
diff --git a/config/feature_flags/development/npm_metadata_cache.yml b/config/feature_flags/development/npm_metadata_cache.yml
deleted file mode 100644
index ddd1afa37e6..00000000000
--- a/config/feature_flags/development/npm_metadata_cache.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: npm_metadata_cache
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/121714
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/393745
-milestone: '16.1'
-type: development
-group: group::package registry
-default_enabled: false
diff --git a/config/initializers/doorkeeper.rb b/config/initializers/doorkeeper.rb
index 3572c30cdd3..c5640ce260b 100644
--- a/config/initializers/doorkeeper.rb
+++ b/config/initializers/doorkeeper.rb
@@ -26,7 +26,7 @@ Doorkeeper.configure do
user = User.find_by_login(params[:username])
next unless user
- next if user.password_automatically_set?
+ next if user.password_automatically_set? && !user.password_based_omniauth_user?
next if user.two_factor_enabled? || Gitlab::Auth::TwoFactorAuthVerifier.new(user).two_factor_authentication_enforced?
Gitlab::Auth.find_with_user_password(params[:username], params[:password], increment_failed_attempts: true)
diff --git a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
index d91b965765d..cfbcdf9c3ed 100644
--- a/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175546_ci_internal_pipelines.yml
@@ -16,6 +16,7 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "12.9"
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26441"
diff --git a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
index 341cc40bba4..dc72934d8ea 100644
--- a/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
+++ b/config/metrics/counts_28d/20210216175550_ci_pipeline_config_repository.yml
@@ -16,6 +16,7 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "12.9"
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26441"
diff --git a/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml b/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
index ed88363f2e4..1aca43b481c 100644
--- a/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
+++ b/config/metrics/counts_28d/20210216175552_ci_pipeline_schedules.yml
@@ -16,6 +16,7 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "12.9"
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26441"
diff --git a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
index 4cbd7791013..85574876681 100644
--- a/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
+++ b/config/metrics/counts_28d/20210216175554_ci_pipelines.yml
@@ -21,5 +21,6 @@ performance_indicator_type:
- smau
- gmau
- paid_gmau
+- customer_health_score
milestone: "12.9"
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26441"
diff --git a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
index 6953cbc2ce3..618d65d14f8 100644
--- a/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
+++ b/config/metrics/counts_28d/20210216180327_action_monthly_active_users_ide_edit.yml
@@ -28,4 +28,5 @@ tier:
performance_indicator_type:
- gmau
- paid_gmau
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216180814_events.yml b/config/metrics/counts_28d/20210216180814_events.yml
index e30babe377d..d32c6b21000 100644
--- a/config/metrics/counts_28d/20210216180814_events.yml
+++ b/config/metrics/counts_28d/20210216180814_events.yml
@@ -18,4 +18,5 @@ tier:
- ultimate
performance_indicator_type:
- umau
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181057_projects_with_packages.yml b/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
index a1e10881251..2ae56078fb3 100644
--- a/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
+++ b/config/metrics/counts_28d/20210216181057_projects_with_packages.yml
@@ -16,5 +16,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181139_issues.yml b/config/metrics/counts_28d/20210216181139_issues.yml
index ffb7a16e611..931a6d2cfc0 100644
--- a/config/metrics/counts_28d/20210216181139_issues.yml
+++ b/config/metrics/counts_28d/20210216181139_issues.yml
@@ -17,5 +17,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181158_epics.yml b/config/metrics/counts_28d/20210216181158_epics.yml
index d3f6b0805f5..51eca7b3009 100644
--- a/config/metrics/counts_28d/20210216181158_epics.yml
+++ b/config/metrics/counts_28d/20210216181158_epics.yml
@@ -14,5 +14,6 @@ distribution:
tier:
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml b/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
index 105c05cf675..fa4b3d5ec13 100644
--- a/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
+++ b/config/metrics/counts_28d/20210216181337_g_project_management_issue_milestone_changed_monthly.yml
@@ -23,5 +23,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181935_deployments.yml b/config/metrics/counts_28d/20210216181935_deployments.yml
index 3c2160e9640..ecf3840bd1d 100644
--- a/config/metrics/counts_28d/20210216181935_deployments.yml
+++ b/config/metrics/counts_28d/20210216181935_deployments.yml
@@ -18,4 +18,5 @@ tier:
performance_indicator_type:
- gmau
- paid_gmau
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216181939_releases.yml b/config/metrics/counts_28d/20210216181939_releases.yml
index 6818cd31fe8..390c3e913d8 100644
--- a/config/metrics/counts_28d/20210216181939_releases.yml
+++ b/config/metrics/counts_28d/20210216181939_releases.yml
@@ -16,5 +16,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml b/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
index 308b55d9a90..80913319bd6 100644
--- a/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
+++ b/config/metrics/counts_28d/20210216182040_action_monthly_active_users_project_repo.yml
@@ -24,4 +24,5 @@ performance_indicator_type:
- smau
- gmau
- paid_gmau
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216182051_protected_branches.yml b/config/metrics/counts_28d/20210216182051_protected_branches.yml
index 8f6589b5c37..36c67780088 100644
--- a/config/metrics/counts_28d/20210216182051_protected_branches.yml
+++ b/config/metrics/counts_28d/20210216182051_protected_branches.yml
@@ -17,5 +17,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
index d01b08ea827..fef381fb775 100644
--- a/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
+++ b/config/metrics/counts_28d/20210216184303_o_pipeline_authoring_unique_users_committing_ciconfigfile_monthly.yml
@@ -21,5 +21,6 @@ tier:
- free
- premium
- ultimate
-performance_indicator_type: []
+performance_indicator_type:
+- customer_health_score
milestone: "<13.9"
diff --git a/config/metrics/counts_28d/20220621085114_unique_active_users_monthly.yml b/config/metrics/counts_28d/20220621085114_unique_active_users_monthly.yml
index 06b1cbcc3cc..ac3aede50b2 100644
--- a/config/metrics/counts_28d/20220621085114_unique_active_users_monthly.yml
+++ b/config/metrics/counts_28d/20220621085114_unique_active_users_monthly.yml
@@ -22,3 +22,5 @@ tier:
- free
- premium
- ultimate
+performance_indicator_type:
+- customer_health_score
diff --git a/config/metrics/counts_all/20210216175525_ci_builds.yml b/config/metrics/counts_all/20210216175525_ci_builds.yml
index c44a35960c4..8b060470454 100644
--- a/config/metrics/counts_all/20210216175525_ci_builds.yml
+++ b/config/metrics/counts_all/20210216175525_ci_builds.yml
@@ -17,3 +17,5 @@ tier:
- premium
- ultimate
milestone: "<13.9"
+performance_indicator_type:
+- customer_health_score
diff --git a/config/metrics/counts_all/20210514141520_project_imports_total.yml b/config/metrics/counts_all/20210514141520_project_imports_total.yml
index d3462f48afb..1eb380e9716 100644
--- a/config/metrics/counts_all/20210514141520_project_imports_total.yml
+++ b/config/metrics/counts_all/20210514141520_project_imports_total.yml
@@ -19,3 +19,5 @@ tier:
- free
- premium
- ultimate
+performance_indicator_type:
+- customer_health_score
diff --git a/db/post_migrate/20231122125550_drop_index_bulk_import_export_batches_on_export_id.rb b/db/post_migrate/20231122125550_drop_index_bulk_import_export_batches_on_export_id.rb
new file mode 100644
index 00000000000..295eae13c06
--- /dev/null
+++ b/db/post_migrate/20231122125550_drop_index_bulk_import_export_batches_on_export_id.rb
@@ -0,0 +1,18 @@
+# frozen_string_literal: true
+
+class DropIndexBulkImportExportBatchesOnExportId < Gitlab::Database::Migration[2.2]
+ disable_ddl_transaction!
+
+ milestone '16.7'
+
+ INDEX_NAME = :index_bulk_import_export_batches_on_export_id
+ TABLE_NAME = :bulk_import_export_batches
+
+ def up
+ remove_concurrent_index_by_name TABLE_NAME, INDEX_NAME
+ end
+
+ def down
+ add_concurrent_index TABLE_NAME, :export_id, name: INDEX_NAME
+ end
+end
diff --git a/db/schema_migrations/20231122125550 b/db/schema_migrations/20231122125550
new file mode 100644
index 00000000000..8f8364313f8
--- /dev/null
+++ b/db/schema_migrations/20231122125550
@@ -0,0 +1 @@
+50b84382c713219deda4f271ebffcfb786aa89d137d5693597d98183478da687 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 31d19255a15..b915344d7cb 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -31856,8 +31856,6 @@ CREATE INDEX index_bulk_import_entities_on_parent_id ON bulk_import_entities USI
CREATE INDEX index_bulk_import_entities_on_project_id ON bulk_import_entities USING btree (project_id);
-CREATE INDEX index_bulk_import_export_batches_on_export_id ON bulk_import_export_batches USING btree (export_id);
-
CREATE INDEX index_bulk_import_export_uploads_on_export_id ON bulk_import_export_uploads USING btree (export_id);
CREATE INDEX index_bulk_import_failures_on_bulk_import_entity_id ON bulk_import_failures USING btree (bulk_import_entity_id);
diff --git a/doc/architecture/blueprints/cells/index.md b/doc/architecture/blueprints/cells/index.md
index e77ee750b92..6274a440810 100644
--- a/doc/architecture/blueprints/cells/index.md
+++ b/doc/architecture/blueprints/cells/index.md
@@ -96,6 +96,10 @@ The first 2-3 quarters are required to define a general split of data, and build
The purpose is to make `users` cluster-wide.
+1. **User can create Organization.**
+
+ The purpose is to create Organizations that are isolated from each other.
+
1. **User can create Group.** ✓ ([demo](https://www.youtube.com/watch?v=LUyV0ncfdRs))
The purpose is to perform a targeted decomposition of `users` and `namespaces`, because `namespaces` will be stored locally in the Cell.
@@ -104,9 +108,9 @@ The first 2-3 quarters are required to define a general split of data, and build
The purpose is to perform a targeted decomposition of `users` and `projects`, because `projects` will be stored locally in the Cell.
-1. **User can create Organization on Cell 2.**
+1. **User can create files in repository**
- The purpose is to create Organizations that are isolated from each other.
+ The purpose is to allow `users` to create files in a repository.
1. **User can change profile avatar that is shared in cluster.**
@@ -159,7 +163,7 @@ flowchart TD
A --> L[Manage members]
B --> L
C --> L
- L --> E[Create file in project]
+ L --> E[Create file in repository]
```
### 3. Additional workflows
@@ -316,6 +320,7 @@ It is expected that initial iterations will be rather slow, because they require
- Data access layer: Data access layer.
- Routing: User can use single domain to interact with many Cells.
- Cell deployment: Extend GitLab Dedicated to support GCP.
+- Essential workflows: User can create files in repository.
- Essential workflows: User can push to Git repository.
- Essential workflows: User can run CI pipeline.
- Essential workflows: Instance-wide settings are shared across cluster.
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 799b05df1b1..aa736884529 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -2441,6 +2441,37 @@ image:
- [Override the entrypoint of an image](../docker/using_docker_images.md#override-the-entrypoint-of-an-image).
+#### `image:docker`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27919) in GitLab 16.7. Requires GitLab Runner 16.7 or later.
+
+Use `image:docker` to pass options to the Docker executor of a GitLab Runner.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**:
+
+A hash of options for the Docker executor, which can include:
+
+- `platform`: Selects the architecture of the image to pull. When not specified,
+ the default is the same platform as the host runner.
+
+**Example of `image:docker`**:
+
+```yaml
+arm-sql-job:
+ script: echo "Run sql tests"
+ image:
+ name: super/sql:experimental
+ docker:
+ platform: arm64/v8
+```
+
+**Additional details**:
+
+- `image:docker:platform` maps to the [`docker pull --platform` option](https://docs.docker.com/engine/reference/commandline/pull/#options).
+
#### `image:pull_policy`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21619) in GitLab 15.1 [with a flag](../../administration/feature_flags.md) named `ci_docker_image_pull_policy`. Disabled by default.
@@ -4257,7 +4288,39 @@ In this example, GitLab launches two containers for the job:
- [Run your CI/CD jobs in Docker containers](../docker/using_docker_images.md).
- [Use Docker to build Docker images](../docker/using_docker_build.md).
-#### `service:pull_policy`
+#### `services:docker`
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/27919) in GitLab 16.7. Requires GitLab Runner 16.7 or later.
+
+Use `services:docker` to pass options to the Docker executor of a GitLab Runner.
+
+**Keyword type**: Job keyword. You can use it only as part of a job or in the
+[`default` section](#default).
+
+**Possible inputs**:
+
+A hash of options for the Docker executor, which can include:
+
+- `platform`: Selects the architecture of the image to pull. When not specified,
+ the default is the same platform as the host runner.
+
+**Example of `services:docker`**:
+
+```yaml
+arm-sql-job:
+ script: echo "Run sql tests in service container"
+ image: ruby:2.6
+ services:
+ - name: super/sql:experimental
+ docker:
+ platform: arm64/v8
+```
+
+**Additional details**:
+
+- `services:docker:platform` maps to the [`docker pull --platform` option](https://docs.docker.com/engine/reference/commandline/pull/#options).
+
+#### `services:pull_policy`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21619) in GitLab 15.1 [with a flag](../../administration/feature_flags.md) named `ci_docker_image_pull_policy`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/363186) in GitLab 15.2.
@@ -4273,7 +4336,7 @@ The pull policy that the runner uses to fetch the Docker image.
- A single pull policy, or multiple pull policies in an array.
Can be `always`, `if-not-present`, or `never`.
-**Examples of `service:pull_policy`**:
+**Examples of `services:pull_policy`**:
```yaml
job1:
diff --git a/doc/user/project/service_desk/configure.md b/doc/user/project/service_desk/configure.md
index 06f0854953d..8a9e28a6d0d 100644
--- a/doc/user/project/service_desk/configure.md
+++ b/doc/user/project/service_desk/configure.md
@@ -159,6 +159,7 @@ To edit the custom email display name:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/329990) in GitLab 16.3 [with a flag](../../../administration/feature_flags.md) named `service_desk_custom_email`. Disabled by default.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/387003) in GitLab 16.4.
+> - Ability to select the SMTP authentication method [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429680) in GitLab 16.6.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature per project or for
@@ -237,6 +238,36 @@ If the verification failed, the email also contains details of the reason.
If the verification was successful, the custom email address is ready to be used.
You can now enable sending Service Desk emails via the custom email address.
+#### Troubleshooting your configuration
+
+When configuring a custom email you might encounter the following issues.
+
+##### Invalid credentials
+
+You might get an error that states that invalid credentials were used.
+
+This occurs when the SMTP server returns that the authentication wasn't successful.
+
+To troubleshoot this:
+
+1. Check your SMTP credentials, especially the username and password.
+1. Sometimes GitLab cannot automatically select an authentication method that the SMTP server supports. Either:
+ - Try the available authentication methods (**Plain**, **Login** and **CRAM-MD5**).
+ - Check which authentication methods your SMTP server supports, using the
+ [`swaks` command line tool](https://www.jetmore.org/john/code/swaks/):
+ 1. Run the following command with your credentials and look for a line that starts with `250-AUTH`:
+
+ ```shell
+ swaks --to user@example.com \
+ --from support@example.com \
+ --auth-user support@example.com \
+ --server smtp@example.com:587 \
+ -tls-optional \
+ --auth-password your-app-password
+ ```
+
+ 1. Select one of the supported authentication methods in the custom email setup form.
+
### Enable or disable the custom email address
After the custom email address has been verified, administrators can enable or disable sending Service Desk emails via the custom email address.
@@ -353,6 +384,7 @@ In GitLab:
- **SMTP port**: `587`.
- **SMTP username**: Prefilled with the custom email address.
- **SMTP password**: The app password you previously created for the custom email account.
+ - **SMTP authentication method**: Let GitLab select a server-supported method (recommended)
1. Select **Save and test connection**
1. After the [verification process](#verification) you should be able to
[enable the custom email address](#enable-or-disable-the-custom-email-address).
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
index 19d63a39242..69d23c408ab 100644
--- a/lib/api/concerns/packages/npm_endpoints.rb
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -238,7 +238,7 @@ module API
not_found!('Packages') if available_packages.empty?
- if endpoint_scope == :project && Feature.enabled?(:npm_metadata_cache, project)
+ if endpoint_scope == :project
if metadata_cache&.file&.exists?
metadata_cache.touch_last_downloaded_at
present_carrierwave_file!(metadata_cache.file)
diff --git a/lib/api/entities/ci/job_request/image.rb b/lib/api/entities/ci/job_request/image.rb
index 92d68269265..08b0075a657 100644
--- a/lib/api/entities/ci/job_request/image.rb
+++ b/lib/api/entities/ci/job_request/image.rb
@@ -8,6 +8,7 @@ module API
expose :name, :entrypoint
expose :ports, using: Entities::Ci::JobRequest::Port
+ expose :executor_opts
expose :pull_policy
end
end
diff --git a/lib/api/entities/ci/job_request/service.rb b/lib/api/entities/ci/job_request/service.rb
index 128591058fe..ae726a6b888 100644
--- a/lib/api/entities/ci/job_request/service.rb
+++ b/lib/api/entities/ci/job_request/service.rb
@@ -8,6 +8,7 @@ module API
expose :name, :entrypoint
expose :ports, using: Entities::Ci::JobRequest::Port
+ expose :executor_opts
expose :pull_policy
expose :alias, :command
expose :variables
diff --git a/lib/api/helpers/packages/npm.rb b/lib/api/helpers/packages/npm.rb
index c91eef0c4b0..0ab3b64a2c6 100644
--- a/lib/api/helpers/packages/npm.rb
+++ b/lib/api/helpers/packages/npm.rb
@@ -86,8 +86,6 @@ module API
strong_memoize_attr :project_id_or_nil
def enqueue_sync_metadata_cache_worker(project, package_name)
- return unless Feature.enabled?(:npm_metadata_cache, project)
-
::Packages::Npm::CreateMetadataCacheWorker.perform_async(project.id, package_name)
end
diff --git a/lib/gitlab/ci/build/image.rb b/lib/gitlab/ci/build/image.rb
index 84f8eae8deb..660d7701a8f 100644
--- a/lib/gitlab/ci/build/image.rb
+++ b/lib/gitlab/ci/build/image.rb
@@ -4,7 +4,7 @@ module Gitlab
module Ci
module Build
class Image
- attr_reader :alias, :command, :entrypoint, :name, :ports, :variables, :pull_policy
+ attr_reader :alias, :command, :entrypoint, :name, :ports, :variables, :executor_opts, :pull_policy
class << self
def from_image(job)
@@ -28,6 +28,7 @@ module Gitlab
when String
@name = image
@ports = []
+ @executor_opts = {}
when Hash
@alias = image[:alias]
@command = image[:command]
@@ -35,6 +36,7 @@ module Gitlab
@name = image[:name]
@ports = build_ports(image).select(&:valid?)
@variables = build_variables(image)
+ @executor_opts = image.fetch(:executor_opts, {})
@pull_policy = image[:pull_policy]
end
end
diff --git a/lib/gitlab/ci/config/entry/image.rb b/lib/gitlab/ci/config/entry/image.rb
index 84e31ca1fc6..58ab488d833 100644
--- a/lib/gitlab/ci/config/entry/image.rb
+++ b/lib/gitlab/ci/config/entry/image.rb
@@ -13,21 +13,6 @@ module Gitlab
validations do
validates :config, allowed_keys: IMAGEABLE_ALLOWED_KEYS
end
-
- def value
- if string?
- { name: @config }
- elsif hash?
- {
- name: @config[:name],
- entrypoint: @config[:entrypoint],
- ports: (ports_value if ports_defined?),
- pull_policy: pull_policy_value
- }.compact
- else
- {}
- end
- end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/imageable.rb b/lib/gitlab/ci/config/entry/imageable.rb
index 1aecfee9ab9..53b810b3037 100644
--- a/lib/gitlab/ci/config/entry/imageable.rb
+++ b/lib/gitlab/ci/config/entry/imageable.rb
@@ -12,7 +12,9 @@ module Gitlab
include ::Gitlab::Config::Entry::Attributable
include ::Gitlab::Config::Entry::Configurable
- IMAGEABLE_ALLOWED_KEYS = %i[name entrypoint ports pull_policy].freeze
+ EXECUTOR_OPTS_KEYS = %i[docker].freeze
+
+ IMAGEABLE_ALLOWED_KEYS = EXECUTOR_OPTS_KEYS + %i[name entrypoint ports pull_policy].freeze
included do
include ::Gitlab::Config::Entry::Validatable
@@ -23,9 +25,15 @@ module Gitlab
validates :name, type: String, presence: true
validates :entrypoint, array_of_strings: true, allow_nil: true
+ validates :executor_opts, json_schema: {
+ base_directory: "lib/gitlab/ci/config/entry/schemas/imageable",
+ detail_errors: true,
+ filename: "executor_opts",
+ hash_conversion: true
+ }, allow_nil: true
end
- attributes :ports, :pull_policy
+ attributes :docker, :ports, :pull_policy
entry :ports, Entry::Ports,
description: 'Ports used to expose the image/service'
@@ -49,6 +57,28 @@ module Gitlab
def skip_config_hash_validation?
true
end
+
+ def executor_opts
+ return unless config.is_a?(Hash)
+
+ config.slice(*EXECUTOR_OPTS_KEYS).compact.presence
+ end
+
+ def value
+ if string?
+ { name: config }
+ elsif hash?
+ {
+ name: config[:name],
+ entrypoint: config[:entrypoint],
+ executor_opts: executor_opts,
+ ports: (ports_value if ports_defined?),
+ pull_policy: pull_policy_value
+ }.compact
+ else
+ {}
+ end
+ end
end
end
end
diff --git a/lib/gitlab/ci/config/entry/schemas/imageable/executor_opts.json b/lib/gitlab/ci/config/entry/schemas/imageable/executor_opts.json
new file mode 100644
index 00000000000..a31374650e6
--- /dev/null
+++ b/lib/gitlab/ci/config/entry/schemas/imageable/executor_opts.json
@@ -0,0 +1,19 @@
+{
+ "$schema": "http://json-schema.org/draft-07/schema#",
+ "description": "Describe `image:` and `service:` options like `docker:`",
+ "type": "object",
+ "properties": {
+ "docker": {
+ "type": "object",
+ "properties": {
+ "platform": {
+ "type": "string",
+ "minLength": 1,
+ "maxLength": 64
+ }
+ },
+ "additionalProperties": false
+ }
+ },
+ "additionalProperties": false
+}
diff --git a/lib/gitlab/ci/config/entry/service.rb b/lib/gitlab/ci/config/entry/service.rb
index 4b3a9990df4..94fd28badb7 100644
--- a/lib/gitlab/ci/config/entry/service.rb
+++ b/lib/gitlab/ci/config/entry/service.rb
@@ -34,14 +34,14 @@ module Gitlab
end
def value
- if string?
- { name: @config }
- elsif hash?
- @config.merge(
- pull_policy: pull_policy_value
+ if hash?
+ super.merge(
+ command: @config[:command],
+ alias: @config[:alias],
+ variables: (variables_value if variables_defined?)
).compact
else
- {}
+ super
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 06db6608955..36c271bec7c 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1363,6 +1363,9 @@ msgstr ""
msgid "%{wildcards_link_start}Wildcards%{wildcards_link_end} such as %{code_tag_start}v*%{code_tag_end} or %{code_tag_start}*-release%{code_tag_end} are supported."
msgstr ""
+msgid "'%{data_pointer}' must be a valid '%{type}'"
+msgstr ""
+
msgid "'%{level}' is not a valid visibility level"
msgstr ""
@@ -30283,6 +30286,9 @@ msgstr ""
msgid "MetricImages|There was an issue uploading your image."
msgstr ""
+msgid "Metrics"
+msgstr ""
+
msgid "Metrics - Grafana"
msgstr ""
@@ -32705,7 +32711,7 @@ msgstr ""
msgid "Notify|The errors we encountered were:"
msgstr ""
-msgid "Notify|The given credentials (username and password) were rejected by the SMTP server."
+msgid "Notify|The given credentials (username and password) were rejected by the SMTP server, or you need to explicitly set an authentication method."
msgstr ""
msgid "Notify|The project is now located under %{project_full_name_link_start}%{project_full_name}%{link_end}."
@@ -32873,6 +32879,9 @@ msgstr ""
msgid "ObservabilityMetrics|Error: Failed to load metrics details. Try reloading the page."
msgstr ""
+msgid "ObservabilityMetrics|Metric Details"
+msgstr ""
+
msgid "ObservabilityMetrics|Metrics"
msgstr ""
@@ -44719,7 +44728,7 @@ msgstr ""
msgid "ServiceDesk|The SMTP server did not respond in time."
msgstr ""
-msgid "ServiceDesk|The given credentials (username and password) were rejected by the SMTP server."
+msgid "ServiceDesk|The given credentials (username and password) were rejected by the SMTP server, or you need to explicitly set an authentication method."
msgstr ""
msgid "ServiceDesk|The received email didn't contain the verification token that was sent to your email address."
@@ -46418,6 +46427,11 @@ msgstr ""
msgid "Standard"
msgstr ""
+msgid "Star"
+msgid_plural "Stars"
+msgstr[0] ""
+msgstr[1] ""
+
msgid "Star labels to start sorting by priority."
msgstr ""
diff --git a/spec/features/groups/milestone_spec.rb b/spec/features/groups/milestone_spec.rb
index bb7cc3db452..1374aa96578 100644
--- a/spec/features/groups/milestone_spec.rb
+++ b/spec/features/groups/milestone_spec.rb
@@ -98,7 +98,7 @@ RSpec.describe 'Group milestones', feature_category: :groups_and_projects do
end
it 'counts milestones correctly' do
- page.within '[data-testid="milestones-filter"]' do
+ within_testid 'milestones-filter' do
expect(page).to have_content('Open 3')
expect(page).to have_content('Closed 3')
expect(page).to have_content('All 6')
diff --git a/spec/features/groups/packages_spec.rb b/spec/features/groups/packages_spec.rb
index 7819b1f0ab6..6b2a15daf72 100644
--- a/spec/features/groups/packages_spec.rb
+++ b/spec/features/groups/packages_spec.rb
@@ -52,7 +52,7 @@ RSpec.describe 'Group Packages', feature_category: :package_registry do
it_behaves_like 'package details link'
it 'allows you to navigate to the project page' do
- find('[data-testid="root-link"]', text: project.name).click
+ find_by_testid('root-link', text: project.name).click
expect(page).to have_current_path(project_path(project))
expect(page).to have_content(project.name)
diff --git a/spec/features/groups/settings/ci_cd_spec.rb b/spec/features/groups/settings/ci_cd_spec.rb
index a1acb73178b..bf056f535f2 100644
--- a/spec/features/groups/settings/ci_cd_spec.rb
+++ b/spec/features/groups/settings/ci_cd_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe 'Group CI/CD settings', feature_category: :continuous_integration
end
describe 'Runners section' do
- let(:shared_runners_toggle) { page.find('[data-testid="shared-runners-toggle"]') }
+ let(:shared_runners_toggle) { find_by_testid('shared-runners-toggle') }
before do
visit group_settings_ci_cd_path(group)
diff --git a/spec/features/groups/settings/packages_and_registries_spec.rb b/spec/features/groups/settings/packages_and_registries_spec.rb
index cbd26441e2b..934234aa171 100644
--- a/spec/features/groups/settings/packages_and_registries_spec.rb
+++ b/spec/features/groups/settings/packages_and_registries_spec.rb
@@ -65,8 +65,10 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
wait_for_requests
+ # rubocop:disable Capybara/TestidFinders -- Helper within_testid doesn't cover use case
expect(page).to be_axe_clean.within('[data-testid="packages-and-registries-group-settings"]')
.skipping :'link-in-text-block', :'heading-order'
+ # rubocop:enable Capybara/TestidFinders
end
it 'has a Duplicate packages section', :js do
@@ -81,7 +83,7 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
visit_settings_page
wait_for_requests
- within '[data-testid="maven-settings"]' do
+ within_testid 'maven-settings' do
expect(page).to have_field _('Exceptions'), disabled: true
click_button class: 'gl-toggle'
@@ -98,7 +100,7 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
visit_settings_page
wait_for_requests
- within '[data-testid="maven-settings"]' do
+ within_testid 'maven-settings' do
click_button class: 'gl-toggle'
fill_in _('Exceptions'), with: ')'
@@ -115,7 +117,7 @@ RSpec.describe 'Group Package and registry settings', feature_category: :package
visit_sub_group_settings_page
wait_for_requests
- within '[data-testid="maven-settings"]' do
+ within_testid 'maven-settings' do
expect(page).to have_content('Allow duplicates')
expect(page).to have_field _('Exceptions'), disabled: true
diff --git a/spec/features/groups/show_spec.rb b/spec/features/groups/show_spec.rb
index cf18f3cb4e5..c2ab5edf79c 100644
--- a/spec/features/groups/show_spec.rb
+++ b/spec/features/groups/show_spec.rb
@@ -38,7 +38,7 @@ RSpec.describe 'Group show page', feature_category: :groups_and_projects do
expect(page).to have_content('Collaborate with your team')
- page.within(find('[data-testid="invite-members-banner"]')) do
+ within_testid('invite-members-banner') do
click_button('Invite your colleagues')
end
@@ -48,8 +48,8 @@ RSpec.describe 'Group show page', feature_category: :groups_and_projects do
click_button('Cancel')
end
- page.within(find('[data-testid="invite-members-banner"]')) do
- find('[data-testid="close-icon"]').click
+ within_testid('invite-members-banner') do
+ find_by_testid('close-icon').click
end
expect(page).not_to have_content('Collaborate with your team')
@@ -119,7 +119,7 @@ RSpec.describe 'Group show page', feature_category: :groups_and_projects do
wait_for_requests
- page.within("[data-testid=\"group-overview-item-#{public_project.id}\"]") do
+ within_testid("group-overview-item-#{public_project.id}") do
click_button _('Less restrictive visibility')
end
diff --git a/spec/features/groups_spec.rb b/spec/features/groups_spec.rb
index 578f39181d1..c0aaa7f818a 100644
--- a/spec/features/groups_spec.rb
+++ b/spec/features/groups_spec.rb
@@ -485,7 +485,7 @@ RSpec.describe 'Group', feature_category: :groups_and_projects do
it 'only displays "New subgroup" button' do
visit group_path(group)
- page.within '[data-testid="group-buttons"]' do
+ within_testid 'group-buttons' do
expect(page).to have_link('New subgroup')
expect(page).not_to have_link('New project')
end
@@ -502,7 +502,7 @@ RSpec.describe 'Group', feature_category: :groups_and_projects do
sign_in(user)
visit group_path(group)
- page.within '[data-testid="group-buttons"]' do
+ within_testid 'group-buttons' do
expect(page).to have_link('New project')
expect(page).not_to have_link('New subgroup')
end
@@ -515,7 +515,7 @@ RSpec.describe 'Group', feature_category: :groups_and_projects do
visit group_path(group)
- page.within '[data-testid="group-buttons"]' do
+ within_testid 'group-buttons' do
expect(page).to have_link('New subgroup')
expect(page).to have_link('New project')
end
@@ -542,7 +542,7 @@ RSpec.describe 'Group', feature_category: :groups_and_projects do
it 'does not display the "New project" button' do
visit group_path(group)
- page.within '[data-testid="group-buttons"]' do
+ within_testid 'group-buttons' do
expect(page).not_to have_link('New project')
end
end
diff --git a/spec/features/incidents/incident_details_spec.rb b/spec/features/incidents/incident_details_spec.rb
index 693f2599de5..bc0674c4886 100644
--- a/spec/features/incidents/incident_details_spec.rb
+++ b/spec/features/incidents/incident_details_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
# shows the incident tabs
page.within('.issuable-details') do
- incident_tabs = find('[data-testid="incident-tabs"]')
+ incident_tabs = find_by_testid('incident-tabs')
expect(find('h1')).to have_content(incident.title)
expect(incident_tabs).to have_content('Summary')
@@ -66,14 +66,21 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
describe 'escalation status' do
let(:sidebar) { page.find('.right-sidebar') }
- let(:widget) { sidebar.find('[data-testid="escalation_status_container"]') }
+ let(:widget) do
+ within sidebar do
+ find_by_testid('escalation_status_container')
+ end
+ end
+
let(:expected_dropdown_options) { escalation_status.class::STATUSES.keys.take(3).map { |key| key.to_s.titleize } }
it 'has an interactable escalation status widget', :aggregate_failures do
expect(current_status).to have_text(escalation_status.status_name.to_s.titleize)
# list the available statuses
- widget.find('[data-testid="edit-button"]').click
+ within widget do
+ find_by_testid('edit-button').click
+ end
expect(dropdown_options.map(&:text)).to eq(expected_dropdown_options)
expect(widget).not_to have_selector('#escalation-status-help')
@@ -95,7 +102,9 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
end
def current_status
- widget.find('[data-testid="collapsed-content"]')
+ within widget do
+ find_by_testid('collapsed-content')
+ end
end
end
end
@@ -108,9 +117,9 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
click_button 'Edit title and description'
wait_for_requests
- page.within('[data-testid="issuable-form"]') do
+ within_testid('issuable-form') do
click_button 'Issue'
- find('[data-testid="issue-type-list-item"]', text: 'Incident').click
+ find_by_testid('issue-type-list-item', text: 'Incident').click
click_button 'Save changes'
end
@@ -130,9 +139,9 @@ RSpec.describe 'Incident details', :js, feature_category: :incident_management d
click_button 'Edit title and description'
wait_for_requests
- page.within('[data-testid="issuable-form"]') do
+ within_testid('issuable-form') do
click_button 'Incident'
- find('[data-testid="issue-type-list-item"]', text: 'Issue').click
+ find_by_testid('issue-type-list-item', text: 'Issue').click
click_button 'Save changes'
end
diff --git a/spec/features/incidents/incident_timeline_events_spec.rb b/spec/features/incidents/incident_timeline_events_spec.rb
index bd3658ab60f..4ceae0f8780 100644
--- a/spec/features/incidents/incident_timeline_events_spec.rb
+++ b/spec/features/incidents/incident_timeline_events_spec.rb
@@ -86,8 +86,8 @@ RSpec.describe 'Incident timeline events', :js, feature_category: :incident_mana
def trigger_dropdown_action(text)
click_button _('More actions')
- page.within '[data-testid="disclosure-content"]' do
- page.find('[data-testid="disclosure-dropdown-item"]', text: text).click
+ within_testid 'disclosure-content' do
+ find_by_testid('disclosure-dropdown-item', text: text).click
end
end
end
diff --git a/spec/features/issuables/shortcuts_issuable_spec.rb b/spec/features/issuables/shortcuts_issuable_spec.rb
index 6bb453c34e6..13bec61e4da 100644
--- a/spec/features/issuables/shortcuts_issuable_spec.rb
+++ b/spec/features/issuables/shortcuts_issuable_spec.rb
@@ -86,7 +86,7 @@ RSpec.describe 'Blob shortcuts', :js, feature_category: :team_planning do
it "opens milestones dropdown for editing" do
find('body').native.send_key('m')
- expect(find('[data-testid="milestone-edit"]')).to have_selector('.gl-dropdown-inner')
+ expect(find_by_testid('milestone-edit')).to have_selector('.gl-dropdown-inner')
end
end
diff --git a/spec/features/issues/form_spec.rb b/spec/features/issues/form_spec.rb
index 2fb30469691..896d86e4004 100644
--- a/spec/features/issues/form_spec.rb
+++ b/spec/features/issues/form_spec.rb
@@ -148,12 +148,12 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
click_button _('Select label')
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid('sidebar-labels') do
click_button label.title
click_button label2.title
click_button _('Close')
wait_for_requests
- page.within('[data-testid="embedded-labels-list"]') do
+ within_testid('embedded-labels-list') do
expect(page).to have_content(label.title)
expect(page).to have_content(label2.title)
end
@@ -188,13 +188,13 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid 'sidebar-labels' do
click_button label.title
click_button _('Close')
wait_for_requests
- page.within('[data-testid="embedded-labels-list"]') do
+ within_testid('embedded-labels-list') do
expect(page).to have_content(label.title)
end
@@ -205,7 +205,7 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid 'sidebar-labels' do
click_button label.title, class: 'dropdown-item'
click_button _('Close')
@@ -221,7 +221,7 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid 'sidebar-labels' do
search_field = find('input[type="search"]')
search_field.native.send_keys(label.title)
@@ -238,7 +238,7 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
it 'displays an error message when submitting an invalid form' do
click_button 'Create issue'
- page.within('[data-testid="issue-title-input-field"]') do
+ within_testid('issue-title-input-field') do
expect(page).to have_text(_('This field is required.'))
end
end
@@ -463,14 +463,14 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid 'sidebar-labels' do
click_button label.title
click_button label2.title
click_button _('Close')
wait_for_requests
- page.within('[data-testid="embedded-labels-list"]') do
+ within_testid('embedded-labels-list') do
expect(page).to have_content(label.title)
expect(page).to have_content(label2.title)
end
@@ -580,14 +580,14 @@ RSpec.describe 'New/edit issue', :js, feature_category: :team_planning do
wait_for_all_requests
- page.within '[data-testid="sidebar-labels"]' do
+ within_testid 'sidebar-labels' do
click_button _('Create project label')
wait_for_requests
end
page.within '.js-labels-create' do
- find('[data-testid="label-title-input"]').fill_in with: 'test label'
+ find_by_testid('label-title-input').fill_in with: 'test label'
first('.suggest-colors-dropdown a').click
click_button 'Create'
diff --git a/spec/features/issues/incident_issue_spec.rb b/spec/features/issues/incident_issue_spec.rb
index 5197f5d1e33..9225ba03003 100644
--- a/spec/features/issues/incident_issue_spec.rb
+++ b/spec/features/issues/incident_issue_spec.rb
@@ -35,7 +35,7 @@ RSpec.describe 'Incident Detail', :js, feature_category: :team_planning do
it 'shows incident and alert data' do
page.within('.issuable-details') do
- incident_tabs = find('[data-testid="incident-tabs"]')
+ incident_tabs = find_by_testid('incident-tabs')
aggregate_failures 'shows title and Summary tab' do
expect(find('h1')).to have_content(incident.title)
diff --git a/spec/features/issues/issue_detail_spec.rb b/spec/features/issues/issue_detail_spec.rb
index c8802a9cc71..15cb1678c55 100644
--- a/spec/features/issues/issue_detail_spec.rb
+++ b/spec/features/issues/issue_detail_spec.rb
@@ -138,7 +138,7 @@ RSpec.describe 'Issue Detail', :js, feature_category: :team_planning do
it 'cannot see Incident option' do
open_issue_edit_form
- page.within('[data-testid="issuable-form"]') do
+ within_testid('issuable-form') do
expect(page).to have_content('Issue')
expect(page).not_to have_content('Incident')
end
@@ -151,7 +151,7 @@ RSpec.describe 'Issue Detail', :js, feature_category: :team_planning do
it 'routes the user to the incident details page when the `issue_type` is set to incident' do
open_issue_edit_form
- page.within('[data-testid="issuable-form"]') do
+ within_testid('issuable-form') do
update_type_select('Issue', 'Incident')
expect(page).to have_current_path(incident_project_issues_path(project, issue))
@@ -181,7 +181,7 @@ RSpec.describe 'Issue Detail', :js, feature_category: :team_planning do
it 'routes the user to the issue details page when the `issue_type` is set to issue' do
open_issue_edit_form
- page.within('[data-testid="issuable-form"]') do
+ within_testid('issuable-form') do
update_type_select('Incident', 'Issue')
expect(page).to have_current_path(project_issue_path(project, incident))
@@ -193,7 +193,7 @@ RSpec.describe 'Issue Detail', :js, feature_category: :team_planning do
def update_type_select(from, to)
click_button from
- find('[data-testid="issue-type-list-item"]', text: to).click
+ find_by_testid('issue-type-list-item', text: to).click
click_button 'Save changes'
wait_for_requests
diff --git a/spec/frontend/editor/schema/ci/ci_schema_spec.js b/spec/frontend/editor/schema/ci/ci_schema_spec.js
index 0f380f13679..8e7f6e8e00a 100644
--- a/spec/frontend/editor/schema/ci/ci_schema_spec.js
+++ b/spec/frontend/editor/schema/ci/ci_schema_spec.js
@@ -23,6 +23,7 @@ import RetryUnknownWhenJson from './json_tests/negative_tests/retry_unknown_when
// YAML POSITIVE TEST
import ArtifactsYaml from './yaml_tests/positive_tests/artifacts.yml';
+import ImageYaml from './yaml_tests/positive_tests/image.yml';
import CacheYaml from './yaml_tests/positive_tests/cache.yml';
import FilterYaml from './yaml_tests/positive_tests/filter.yml';
import IncludeYaml from './yaml_tests/positive_tests/include.yml';
@@ -40,6 +41,7 @@ import ScriptYaml from './yaml_tests/positive_tests/script.yml';
// YAML NEGATIVE TEST
import ArtifactsNegativeYaml from './yaml_tests/negative_tests/artifacts.yml';
+import ImageNegativeYaml from './yaml_tests/negative_tests/image.yml';
import CacheKeyNeative from './yaml_tests/negative_tests/cache.yml';
import IncludeNegativeYaml from './yaml_tests/negative_tests/include.yml';
import JobWhenNegativeYaml from './yaml_tests/negative_tests/job_when.yml';
@@ -90,6 +92,7 @@ describe('positive tests', () => {
// YAML
ArtifactsYaml,
+ ImageYaml,
CacheYaml,
FilterYaml,
IncludeYaml,
@@ -126,6 +129,7 @@ describe('negative tests', () => {
// YAML
ArtifactsNegativeYaml,
+ ImageNegativeYaml,
CacheKeyNeative,
HooksNegative,
IdTokensNegativeYaml,
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/image.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/image.yml
new file mode 100644
index 00000000000..ad37cd6c3ba
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/image.yml
@@ -0,0 +1,38 @@
+empty_image:
+ image:
+
+multi_image_array:
+ image:
+ - alpine:latest
+ - ubuntu:latest
+
+image_without_name:
+ image:
+ entrypoint: ["/bin/sh", "-c"]
+
+image_with_invalid_entrypoint:
+ image:
+ name: my-postgres:11.7
+ entrypoint: "/usr/local/bin/db-postgres" # must be array
+
+image_with_empty_pull_policy:
+ image:
+ name: postgres:11.6
+ pull_policy: []
+
+invalid_image_platform:
+ image:
+ name: alpine:latest
+ docker:
+ platform: ["arm64"] # The expected value is a string, not an array
+
+invalid_image_executor_opts:
+ image:
+ name: alpine:latest
+ docker:
+ unknown_key: test
+
+image_with_empty_executor_opts:
+ image:
+ name: alpine:latest
+ docker:
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/services.yml b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/services.yml
index 6761a603a0a..e14ac9ca86e 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/services.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/negative_tests/services.yml
@@ -36,3 +36,17 @@ empty_pull_policy:
services:
- name: postgres:11.6
pull_policy: []
+
+invalid_service_executor_opts:
+ script: echo "Specifying platform."
+ services:
+ - name: mysql:5.7
+ docker:
+ unknown_key: test
+
+invalid_service_platform:
+ script: echo "Specifying platform."
+ services:
+ - name: mysql:5.7
+ docker:
+ platform: ["arm64"] # The expected value is a string, not an array
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/image.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/image.yml
new file mode 100644
index 00000000000..4c2559d0800
--- /dev/null
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/image.yml
@@ -0,0 +1,41 @@
+valid_image:
+ image: alpine:latest
+
+valid_image_basic:
+ image:
+ name: alpine:latest
+
+valid_image_with_entrypoint:
+ image:
+ name: alpine:latest
+ entrypoint:
+ - /bin/sh
+ - -c
+
+valid_image_with_pull_policy:
+ image:
+ name: alpine:latest
+ pull_policy: always
+
+valid_image_with_pull_policies:
+ image:
+ name: alpine:latest
+ pull_policy:
+ - always
+ - if-not-present
+
+valid_image_with_docker:
+ image:
+ name: alpine:latest
+ docker:
+ platform: linux/amd64
+
+valid_image_full:
+ image:
+ name: alpine:latest
+ entrypoint:
+ - /bin/sh
+ - -c
+ docker:
+ platform: linux/amd64
+ pull_policy: if-not-present
diff --git a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/services.yml b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/services.yml
index 8a0f59d1dfd..1d19ee52cc3 100644
--- a/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/services.yml
+++ b/spec/frontend/editor/schema/ci/yaml_tests/positive_tests/services.yml
@@ -29,3 +29,10 @@ pull_policy_array:
services:
- name: postgres:11.6
pull_policy: [always, if-not-present]
+
+services_platform_string:
+ script: echo "Specifying platform."
+ services:
+ - name: mysql:5.7
+ docker:
+ platform: arm64
diff --git a/spec/lib/api/entities/ci/job_request/image_spec.rb b/spec/lib/api/entities/ci/job_request/image_spec.rb
index 14d4a074fce..666ec31d3d9 100644
--- a/spec/lib/api/entities/ci/job_request/image_spec.rb
+++ b/spec/lib/api/entities/ci/job_request/image_spec.rb
@@ -4,7 +4,10 @@ require 'spec_helper'
RSpec.describe API::Entities::Ci::JobRequest::Image do
let(:ports) { [{ number: 80, protocol: 'http', name: 'name' }] }
- let(:image) { double(name: 'image_name', entrypoint: ['foo'], ports: ports, pull_policy: ['if-not-present']) }
+ let(:image) do
+ double(name: 'image_name', entrypoint: ['foo'], executor_opts: {}, ports: ports, pull_policy: ['if-not-present'])
+ end
+
let(:entity) { described_class.new(image) }
subject { entity.as_json }
@@ -29,6 +32,10 @@ RSpec.describe API::Entities::Ci::JobRequest::Image do
end
end
+ it 'returns the executor_opts options' do
+ expect(subject[:executor_opts]).to eq({})
+ end
+
it 'returns the pull policy' do
expect(subject[:pull_policy]).to eq(['if-not-present'])
end
diff --git a/spec/lib/api/entities/ci/job_request/service_spec.rb b/spec/lib/api/entities/ci/job_request/service_spec.rb
index 11350f7c41b..c2331799314 100644
--- a/spec/lib/api/entities/ci/job_request/service_spec.rb
+++ b/spec/lib/api/entities/ci/job_request/service_spec.rb
@@ -9,6 +9,7 @@ RSpec.describe API::Entities::Ci::JobRequest::Service do
::Gitlab::Ci::Build::Image,
name: 'image_name',
entrypoint: ['foo'],
+ executor_opts: {},
ports: ports,
pull_policy: ['if-not-present'],
alias: 'alias',
@@ -25,6 +26,7 @@ RSpec.describe API::Entities::Ci::JobRequest::Service do
expect(result).to eq(
name: 'image_name',
entrypoint: ['foo'],
+ executor_opts: {},
ports: ports,
pull_policy: ['if-not-present'],
alias: 'alias',
diff --git a/spec/lib/gitlab/ci/build/image_spec.rb b/spec/lib/gitlab/ci/build/image_spec.rb
index 4895077a731..f8c0d69be2e 100644
--- a/spec/lib/gitlab/ci/build/image_spec.rb
+++ b/spec/lib/gitlab/ci/build/image_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Gitlab::Ci::Build::Image do
context 'when image is defined in job' do
let(:image_name) { 'image:1.0' }
- let(:job) { create(:ci_build, options: { image: image_name } ) }
+ let(:job) { create(:ci_build, options: { image: image_name }) }
context 'when image is defined as string' do
it 'fabricates an object of the proper class' do
@@ -29,12 +29,14 @@ RSpec.describe Gitlab::Ci::Build::Image do
context 'when image is defined as hash' do
let(:entrypoint) { '/bin/sh' }
let(:pull_policy) { %w[always if-not-present] }
+ let(:executor_opts) { { docker: { platform: 'arm64' } } }
let(:job) do
create(:ci_build, options: { image: { name: image_name,
entrypoint: entrypoint,
ports: [80],
- pull_policy: pull_policy } } )
+ executor_opts: executor_opts,
+ pull_policy: pull_policy } })
end
it 'fabricates an object of the proper class' do
@@ -44,6 +46,7 @@ RSpec.describe Gitlab::Ci::Build::Image do
it 'populates fabricated object with the proper attributes' do
expect(subject.name).to eq(image_name)
expect(subject.entrypoint).to eq(entrypoint)
+ expect(subject.executor_opts).to eq(executor_opts)
expect(subject.pull_policy).to eq(pull_policy)
end
@@ -98,11 +101,12 @@ RSpec.describe Gitlab::Ci::Build::Image do
let(:service_entrypoint) { '/bin/sh' }
let(:service_alias) { 'db' }
let(:service_command) { 'sleep 30' }
+ let(:executor_opts) { { docker: { platform: 'amd64' } } }
let(:pull_policy) { %w[always if-not-present] }
let(:job) do
create(:ci_build, options: { services: [{ name: service_image_name, entrypoint: service_entrypoint,
alias: service_alias, command: service_command, ports: [80],
- pull_policy: pull_policy }] })
+ executor_opts: executor_opts, pull_policy: pull_policy }] })
end
it 'fabricates an non-empty array of objects' do
@@ -116,6 +120,7 @@ RSpec.describe Gitlab::Ci::Build::Image do
expect(subject.first.entrypoint).to eq(service_entrypoint)
expect(subject.first.alias).to eq(service_alias)
expect(subject.first.command).to eq(service_command)
+ expect(subject.first.executor_opts).to eq(executor_opts)
expect(subject.first.pull_policy).to eq(pull_policy)
port = subject.first.ports.first
diff --git a/spec/lib/gitlab/ci/config/entry/image_spec.rb b/spec/lib/gitlab/ci/config/entry/image_spec.rb
index 17c45ec4c2c..99a6e25b313 100644
--- a/spec/lib/gitlab/ci/config/entry/image_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/image_spec.rb
@@ -42,6 +42,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do
end
end
+ describe '#executor_opts' do
+ it "returns nil" do
+ expect(entry.executor_opts).to be_nil
+ end
+ end
+
describe '#ports' do
it "returns image's ports" do
expect(entry.ports).to be_nil
@@ -88,6 +94,54 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do
end
end
+ context 'when configuration specifies docker' do
+ let(:config) { { name: 'image:1.0', docker: {} } }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+
+ describe '#value' do
+ it "returns value" do
+ expect(entry.value).to eq(
+ name: 'image:1.0',
+ executor_opts: {
+ docker: {}
+ }
+ )
+ end
+ end
+
+ context "when docker specifies an option" do
+ let(:config) { { name: 'image:1.0', docker: { platform: 'amd64' } } }
+
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+
+ describe '#value' do
+ it "returns value" do
+ expect(entry.value).to eq(
+ name: 'image:1.0',
+ executor_opts: {
+ docker: { platform: 'amd64' }
+ }
+ )
+ end
+ end
+ end
+
+ context "when docker specifies an invalid option" do
+ let(:config) { { name: 'image:1.0', docker: { platform: 1 } } }
+
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ expect(entry.errors.first)
+ .to match %r{image executor opts '/docker/platform' must be a valid 'string'}
+ end
+ end
+ end
+
context 'when configuration has ports' do
let(:ports) { [{ number: 80, protocol: 'http', name: 'foobar' }] }
let(:config) { { name: 'image:1.0', entrypoint: %w[/bin/sh run], ports: ports } }
@@ -146,7 +200,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do
describe '#errors' do
it 'saves errors' do
expect(entry.errors.first)
- .to match /config should be a hash or a string/
+ .to match(/config should be a hash or a string/)
end
end
@@ -163,7 +217,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Image do
describe '#errors' do
it 'saves errors' do
expect(entry.errors.first)
- .to match /config contains unknown keys: non_existing/
+ .to match(/config contains unknown keys: non_existing/)
end
end
diff --git a/spec/lib/gitlab/ci/config/entry/service_spec.rb b/spec/lib/gitlab/ci/config/entry/service_spec.rb
index bfe45645192..82747e7b521 100644
--- a/spec/lib/gitlab/ci/config/entry/service_spec.rb
+++ b/spec/lib/gitlab/ci/config/entry/service_spec.rb
@@ -47,6 +47,12 @@ RSpec.describe Gitlab::Ci::Config::Entry::Service do
expect(entry.ports).to be_nil
end
end
+
+ describe '#executor_opts' do
+ it "returns service's executor_opts configuration" do
+ expect(entry.executor_opts).to be_nil
+ end
+ end
end
context 'when configuration is a hash' do
@@ -147,6 +153,51 @@ RSpec.describe Gitlab::Ci::Config::Entry::Service do
end
end
+ context 'when configuration has docker options' do
+ let(:config) { { name: 'postgresql:9.5', docker: { platform: 'amd64' } } }
+
+ describe '#valid?' do
+ it 'is valid' do
+ expect(entry).to be_valid
+ end
+ end
+
+ describe '#value' do
+ it "returns value" do
+ expect(entry.value).to eq(
+ name: 'postgresql:9.5',
+ executor_opts: {
+ docker: { platform: 'amd64' }
+ }
+ )
+ end
+ end
+ end
+
+ context 'when docker options have an invalid property' do
+ let(:config) { { name: 'postgresql:9.5', docker: { invalid: 'option' } } }
+
+ describe '#valid?' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ expect(entry.errors.first)
+ .to match %r{service executor opts '/docker/invalid' must be a valid 'schema'}
+ end
+ end
+ end
+
+ context 'when docker options platform is not string' do
+ let(:config) { { name: 'postgresql:9.5', docker: { platform: 123 } } }
+
+ describe '#valid?' do
+ it 'is not valid' do
+ expect(entry).not_to be_valid
+ expect(entry.errors.first)
+ .to match %r{service executor opts '/docker/platform' must be a valid 'string'}
+ end
+ end
+ end
+
context 'when configuration has pull_policy' do
let(:config) { { name: 'postgresql:9.5', pull_policy: 'if-not-present' } }
diff --git a/spec/lib/gitlab/ci/yaml_processor_spec.rb b/spec/lib/gitlab/ci/yaml_processor_spec.rb
index f01c1c7d053..e44e01b2ffa 100644
--- a/spec/lib/gitlab/ci/yaml_processor_spec.rb
+++ b/spec/lib/gitlab/ci/yaml_processor_spec.rb
@@ -1313,6 +1313,46 @@ module Gitlab
})
end
end
+
+ context 'when image and service have docker options' do
+ let(:config) do
+ <<~YAML
+ test:
+ script: exit 0
+ image:
+ name: ruby:2.7
+ docker:
+ platform: linux/amd64
+ services:
+ - name: postgres:11.9
+ docker:
+ platform: linux/amd64
+ YAML
+ end
+
+ it { is_expected.to be_valid }
+
+ it "returns with image" do
+ expect(processor.builds).to contain_exactly({
+ stage: "test",
+ stage_idx: 2,
+ name: "test",
+ only: { refs: %w[branches tags] },
+ options: {
+ script: ["exit 0"],
+ image: { name: "ruby:2.7",
+ executor_opts: { docker: { platform: 'linux/amd64' } } },
+ services: [{ name: "postgres:11.9",
+ executor_opts: { docker: { platform: 'linux/amd64' } } }]
+ },
+ allow_failure: false,
+ when: "on_success",
+ job_variables: [],
+ root_variables_inheritance: true,
+ scheduling_type: :stage
+ })
+ end
+ end
end
describe 'Variables' do
diff --git a/spec/requests/api/ci/runner/jobs_request_post_spec.rb b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
index 2a870a25ea6..3d6d86335eb 100644
--- a/spec/requests/api/ci/runner/jobs_request_post_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_request_post_spec.rb
@@ -272,16 +272,19 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
expect(json_response['job_info']).to include(expected_job_info)
expect(json_response['git_info']).to eq(expected_git_info)
expect(json_response['image']).to eq(
- { 'name' => 'image:1.0', 'entrypoint' => '/bin/sh', 'ports' => [], 'pull_policy' => nil }
+ { 'name' => 'image:1.0', 'entrypoint' => '/bin/sh', 'ports' => [], 'executor_opts' => {},
+ 'pull_policy' => nil }
)
expect(json_response['services']).to eq(
[
{ 'name' => 'postgres', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
- 'variables' => nil, 'pull_policy' => nil },
- { 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh', 'alias' => 'docker', 'command' => 'sleep 30',
- 'ports' => [], 'variables' => [], 'pull_policy' => nil },
+ 'variables' => nil, 'executor_opts' => {}, 'pull_policy' => nil },
+ { 'name' => 'docker:stable-dind', 'entrypoint' => '/bin/sh', 'alias' => 'docker',
+ 'command' => 'sleep 30', 'ports' => [], 'variables' => [], 'executor_opts' => {},
+ 'pull_policy' => nil },
{ 'name' => 'mysql:latest', 'entrypoint' => nil, 'alias' => nil, 'command' => nil, 'ports' => [],
- 'variables' => [{ 'key' => 'MYSQL_ROOT_PASSWORD', 'value' => 'root123.' }], 'pull_policy' => nil }
+ 'variables' => [{ 'key' => 'MYSQL_ROOT_PASSWORD', 'value' => 'root123.' }], 'executor_opts' => {},
+ 'pull_policy' => nil }
])
expect(json_response['steps']).to eq(expected_steps)
expect(json_response['hooks']).to eq(expected_hooks)
@@ -920,6 +923,41 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
end
end
+ context 'when image has docker options' do
+ let(:job) { create(:ci_build, :pending, :queued, pipeline: pipeline, options: options) }
+
+ let(:options) do
+ {
+ image: {
+ name: 'ruby',
+ executor_opts: {
+ docker: {
+ platform: 'amd64'
+ }
+ }
+ }
+ }
+ end
+
+ it 'returns the image with docker options' do
+ request_job
+
+ expect(response).to have_gitlab_http_status(:created)
+ expect(json_response).to include(
+ 'id' => job.id,
+ 'image' => { 'name' => 'ruby',
+ 'executor_opts' => {
+ 'docker' => {
+ 'platform' => 'amd64'
+ }
+ },
+ 'pull_policy' => nil,
+ 'entrypoint' => nil,
+ 'ports' => [] }
+ )
+ end
+ end
+
context 'when image has pull_policy' do
let(:job) { create(:ci_build, :pending, :queued, pipeline: pipeline, options: options) }
@@ -938,7 +976,11 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to include(
'id' => job.id,
- 'image' => { 'name' => 'ruby', 'pull_policy' => ['if-not-present'], 'entrypoint' => nil, 'ports' => [] }
+ 'image' => { 'name' => 'ruby',
+ 'executor_opts' => {},
+ 'pull_policy' => ['if-not-present'],
+ 'entrypoint' => nil,
+ 'ports' => [] }
)
end
end
@@ -962,7 +1004,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
expect(json_response).to include(
'id' => job.id,
'services' => [{ 'alias' => nil, 'command' => nil, 'entrypoint' => nil, 'name' => 'postgres:11.9',
- 'ports' => [], 'pull_policy' => ['if-not-present'], 'variables' => [] }]
+ 'ports' => [], 'executor_opts' => {}, 'pull_policy' => ['if-not-present'],
+ 'variables' => [] }]
)
end
end
diff --git a/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb b/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb
new file mode 100644
index 00000000000..f399c3e310e
--- /dev/null
+++ b/spec/requests/api/ci/runner/jobs_request_yamls_spec.rb
@@ -0,0 +1,64 @@
+# frozen_string_literal: true
+
+require 'spec_helper'
+
+RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_category: :continuous_integration do
+ include StubGitlabCalls
+
+ let_it_be(:user) { create(:user) }
+ let_it_be(:project) { create(:project, :repository, shared_runners_enabled: false) }
+ let_it_be(:runner) { create(:ci_runner, :project, projects: [project]) }
+
+ let(:user_agent) { 'gitlab-runner 9.0.0 (9-0-stable; go1.7.4; linux/amd64)' }
+
+ before_all do
+ project.add_maintainer(user)
+ end
+
+ Dir[Rails.root.join("spec/requests/api/ci/runner/yamls/*.yml")].each do |yml_file|
+ context "for #{File.basename(yml_file)}" do
+ let(:yaml_content) { YAML.load_file(yml_file) }
+ let(:gitlab_ci_yml) { yaml_content.fetch("gitlab_ci") }
+ let(:request_response) { yaml_content.fetch("request_response") }
+
+ it 'runs a job' do
+ stub_ci_pipeline_yaml_file(YAML.dump(gitlab_ci_yml))
+
+ pipeline_response = create_pipeline!
+ expect(pipeline_response).to be_success, pipeline_response.message
+ expect(pipeline_response.payload).to be_created_successfully
+ expect(pipeline_response.payload.builds).to be_one
+
+ build = pipeline_response.payload.builds.first
+
+ process_pipeline!(pipeline_response.payload)
+ expect(build.reload).to be_pending
+
+ request_job(runner.token)
+ expect(response).to have_gitlab_http_status(:created)
+ expect(response.headers['Content-Type']).to eq('application/json')
+ expect(json_response).to include('id' => build.id, 'token' => build.token)
+ expect(json_response).to include(request_response)
+ end
+ end
+ end
+
+ def create_pipeline!
+ params = { ref: 'master',
+ before: '00000000',
+ after: project.commit.id,
+ commits: [{ message: 'some commit' }] }
+
+ Ci::CreatePipelineService.new(project, user, params).execute(:push)
+ end
+
+ def process_pipeline!(pipeline)
+ PipelineProcessWorker.new.perform(pipeline.id)
+ end
+
+ def request_job(token, **params)
+ new_params = params.merge(token: token)
+ post api('/jobs/request'), params: new_params.to_json,
+ headers: { 'User-Agent' => user_agent, 'Content-Type': 'application/json' }
+ end
+end
diff --git a/spec/requests/api/ci/runner/yamls/README.md b/spec/requests/api/ci/runner/yamls/README.md
new file mode 100644
index 00000000000..db8ef51ff9c
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/README.md
@@ -0,0 +1,15 @@
+# .gitlab-ci.yml end-to-end tests
+
+The purpose of this folder is to provide a single job `.gitlab-ci.yml`
+that will be validated against end-to-end response that is send to runner.
+
+This allows to easily test end-to-end all CI job transformation that
+and impact on how such job is rendered to be executed by the GitLab Runner.
+
+```yaml
+gitlab_ci:
+ # .gitlab-ci.yml to stub
+
+request_response:
+ # exact payload that is checked as returned by `/api/v4/jobs/request`
+```
diff --git a/spec/requests/api/ci/runner/yamls/image-basic.yml b/spec/requests/api/ci/runner/yamls/image-basic.yml
new file mode 100644
index 00000000000..0c01dbc6e8b
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/image-basic.yml
@@ -0,0 +1,19 @@
+gitlab_ci:
+ rspec:
+ image: alpine:latest
+ script: echo Hello World
+
+request_response:
+ image:
+ name: alpine:latest
+ entrypoint: null
+ executor_opts: {}
+ ports: []
+ pull_policy: null
+ steps:
+ - name: script
+ script: ["echo Hello World"]
+ timeout: 3600
+ when: on_success
+ allow_failure: false
+ services: []
diff --git a/spec/requests/api/ci/runner/yamls/image-executor_opts-platform.yml b/spec/requests/api/ci/runner/yamls/image-executor_opts-platform.yml
new file mode 100644
index 00000000000..62e301f2e9a
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/image-executor_opts-platform.yml
@@ -0,0 +1,25 @@
+gitlab_ci:
+ rspec:
+ image:
+ name: alpine:latest
+ docker:
+ platform: amd64
+ script: echo Hello World
+
+request_response:
+ image:
+ name: alpine:latest
+ entrypoint: null
+ executor_opts:
+ docker:
+ platform: amd64
+ ports: []
+ pull_policy: null
+ steps:
+ - name: script
+ script: ["echo Hello World"]
+ timeout: 3600
+ when: on_success
+ allow_failure: false
+ services: []
+
diff --git a/spec/requests/api/ci/runner/yamls/service-basic.yml b/spec/requests/api/ci/runner/yamls/service-basic.yml
new file mode 100644
index 00000000000..5438837c496
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/service-basic.yml
@@ -0,0 +1,23 @@
+gitlab_ci:
+ rspec:
+ services:
+ - docker:dind
+ script: echo Hello World
+
+request_response:
+ image: null
+ steps:
+ - name: script
+ script: ["echo Hello World"]
+ timeout: 3600
+ when: on_success
+ allow_failure: false
+ services:
+ - name: docker:dind
+ alias: null
+ command: null
+ entrypoint: null
+ executor_opts: {}
+ ports: []
+ pull_policy: null
+ variables: []
diff --git a/spec/requests/api/ci/runner/yamls/service-executor_opts-platform.yml b/spec/requests/api/ci/runner/yamls/service-executor_opts-platform.yml
new file mode 100644
index 00000000000..6483d749c45
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/service-executor_opts-platform.yml
@@ -0,0 +1,27 @@
+gitlab_ci:
+ rspec:
+ services:
+ - name: docker:dind
+ docker:
+ platform: amd64
+ script: echo Hello World
+
+request_response:
+ image: null
+ steps:
+ - name: script
+ script: ["echo Hello World"]
+ timeout: 3600
+ when: on_success
+ allow_failure: false
+ services:
+ - name: docker:dind
+ alias: null
+ command: null
+ entrypoint: null
+ executor_opts:
+ docker:
+ platform: amd64
+ ports: []
+ pull_policy: null
+ variables: []
diff --git a/spec/requests/api/ci/runner/yamls/service-variables.yml b/spec/requests/api/ci/runner/yamls/service-variables.yml
new file mode 100644
index 00000000000..c8e4dde674b
--- /dev/null
+++ b/spec/requests/api/ci/runner/yamls/service-variables.yml
@@ -0,0 +1,30 @@
+gitlab_ci:
+ rspec:
+ services:
+ - name: docker:dind
+ variables:
+ DOCKER_HOST: tcp://docker:2375
+ DOCKER_DRIVER: overlay2
+ script: echo Hello World
+
+request_response:
+ image: null
+ steps:
+ - name: script
+ script: ["echo Hello World"]
+ timeout: 3600
+ when: on_success
+ allow_failure: false
+ services:
+ - name: docker:dind
+ alias: null
+ command: null
+ entrypoint: null
+ executor_opts: {}
+ ports: []
+ pull_policy: null
+ variables:
+ - key: DOCKER_HOST
+ value: tcp://docker:2375
+ - key: DOCKER_DRIVER
+ value: overlay2
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index b5f38698857..17cb5cf893e 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -54,14 +54,6 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
it_behaves_like 'does not enqueue a worker to sync a metadata cache'
- context 'when npm_metadata_cache disabled' do
- before do
- stub_feature_flags(npm_metadata_cache: false)
- end
-
- it_behaves_like 'generates metadata response "on-the-fly"'
- end
-
context 'when metadata cache file does not exist' do
before do
FileUtils.rm_rf(npm_metadata_cache.file.path)
diff --git a/spec/requests/oauth/tokens_controller_spec.rb b/spec/requests/oauth/tokens_controller_spec.rb
index aaacfce0ce8..b7755a30a78 100644
--- a/spec/requests/oauth/tokens_controller_spec.rb
+++ b/spec/requests/oauth/tokens_controller_spec.rb
@@ -55,6 +55,33 @@ RSpec.describe Oauth::TokensController, feature_category: :system_access do
expect(response).to have_gitlab_http_status(:bad_request)
expect(user.reload.failed_attempts).to eq(0)
end
+
+ context 'when the user has an identity matching a provider that is not password-based' do
+ before do
+ create(:identity, provider: 'google_oauth2', user: user)
+ end
+
+ it 'fails to authenticate and does not call GitLab::Auth' do
+ expect(::Gitlab::Auth).not_to receive(:find_with_user_password)
+
+ authenticate(password)
+
+ expect(response).to have_gitlab_http_status(:bad_request)
+ expect(user.reload.failed_attempts).to eq(0)
+ end
+ end
+
+ context 'when the user is a password-based omniauth user' do
+ before do
+ create(:identity, provider: 'ldapmain', user: user)
+ end
+
+ it 'forwards the request to Gitlab::Auth' do
+ expect(::Gitlab::Auth).to receive(:find_with_user_password)
+
+ authenticate(password)
+ end
+ end
end
end
end
diff --git a/spec/support/helpers/database/duplicate_indexes.yml b/spec/support/helpers/database/duplicate_indexes.yml
index 0a01cb13e84..37aa4374608 100644
--- a/spec/support/helpers/database/duplicate_indexes.yml
+++ b/spec/support/helpers/database/duplicate_indexes.yml
@@ -27,9 +27,6 @@ boards_epic_board_recent_visits:
boards_epic_user_preferences:
index_boards_epic_user_preferences_on_board_user_epic_unique:
- index_boards_epic_user_preferences_on_board_id
-bulk_import_export_batches:
- i_bulk_import_export_batches_id_batch_number:
- - index_bulk_import_export_batches_on_export_id
ci_job_artifacts:
index_ci_job_artifacts_on_id_project_id_and_created_at:
- index_ci_job_artifacts_on_project_id
diff --git a/spec/support/shared_examples/npm_sync_metadata_cache_worker_shared_examples.rb b/spec/support/shared_examples/npm_sync_metadata_cache_worker_shared_examples.rb
index de2dc4c3725..39870c41e1c 100644
--- a/spec/support/shared_examples/npm_sync_metadata_cache_worker_shared_examples.rb
+++ b/spec/support/shared_examples/npm_sync_metadata_cache_worker_shared_examples.rb
@@ -19,12 +19,4 @@ RSpec.shared_examples 'enqueue a worker to sync a metadata cache' do
subject
end
-
- context 'with npm_metadata_cache disabled' do
- before do
- stub_feature_flags(npm_metadata_cache: false)
- end
-
- it_behaves_like 'does not enqueue a worker to sync a metadata cache'
- end
end
diff --git a/spec/validators/json_schema_validator_spec.rb b/spec/validators/json_schema_validator_spec.rb
index 01caf4ab0bd..f3a22892407 100644
--- a/spec/validators/json_schema_validator_spec.rb
+++ b/spec/validators/json_schema_validator_spec.rb
@@ -58,5 +58,30 @@ RSpec.describe JsonSchemaValidator do
end
end
end
+
+ context 'when detail_errors is true' do
+ let(:validator) { described_class.new(attributes: [:data], detail_errors: true, filename: "build_report_result_data") }
+
+ context 'when data is valid' do
+ it 'returns no errors' do
+ subject
+
+ expect(build_report_result.errors).to be_empty
+ end
+ end
+
+ context 'when data is invalid' do
+ it 'returns json schema is invalid' do
+ build_report_result.data = { invalid: 'data' }
+
+ subject
+
+ expect(build_report_result.errors.size).to eq(1)
+ expect(build_report_result.errors.full_messages).to match_array(
+ ["Data '/invalid' must be a valid 'schema'"]
+ )
+ end
+ end
+ end
end
end
diff --git a/spec/workers/bulk_imports/entity_worker_spec.rb b/spec/workers/bulk_imports/entity_worker_spec.rb
index 690555aa08f..4988a368598 100644
--- a/spec/workers/bulk_imports/entity_worker_spec.rb
+++ b/spec/workers/bulk_imports/entity_worker_spec.rb
@@ -49,10 +49,6 @@ RSpec.describe BulkImports::EntityWorker, feature_category: :importers do
end
end
- it 'has the option to reschedule once if deduplicated' do
- expect(described_class.get_deduplication_options).to include({ if_deduplicated: :reschedule_once })
- end
-
context 'when pipeline workers from a stage are running' do
before do
pipeline_tracker.enqueue!
@@ -92,6 +88,26 @@ RSpec.describe BulkImports::EntityWorker, feature_category: :importers do
worker.perform(entity.id)
end
+
+ context 'when exclusive lease cannot be obtained' do
+ it 'does not start next stage and re-enqueue worker' do
+ expect_next_instance_of(Gitlab::ExclusiveLease) do |lease|
+ expect(lease).to receive(:try_obtain).and_return(false)
+ end
+
+ expect_next_instance_of(BulkImports::Logger) do |logger|
+ expect(logger).to receive(:info).with(
+ hash_including(
+ 'message' => 'Cannot obtain an exclusive lease. There must be another instance already in execution.'
+ )
+ )
+ end
+
+ expect(described_class).to receive(:perform_in)
+
+ worker.perform(entity.id)
+ end
+ end
end
context 'when there are no next stage to run' do
diff --git a/spec/workers/packages/npm/create_metadata_cache_worker_spec.rb b/spec/workers/packages/npm/create_metadata_cache_worker_spec.rb
index 360cc4223b4..a061d97ddf5 100644
--- a/spec/workers/packages/npm/create_metadata_cache_worker_spec.rb
+++ b/spec/workers/packages/npm/create_metadata_cache_worker_spec.rb
@@ -58,13 +58,5 @@ RSpec.describe Packages::Npm::CreateMetadataCacheWorker, type: :worker, feature_
it_behaves_like 'does not trigger service to create npm metadata cache'
end
-
- context 'when npm_metadata_cache flag is disabled' do
- before do
- stub_feature_flags(npm_metadata_cache: false)
- end
-
- it_behaves_like 'does not trigger service to create npm metadata cache'
- end
end
end