Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
485728af8d
commit
4612d16c2d
|
@ -57,6 +57,84 @@ Dangerfile @gl-quality/eng-prod
|
|||
/ee/lib/ee/gitlab/auth/ldap/ @dblessing @mkozono
|
||||
/lib/gitlab/auth/ldap/ @dblessing @mkozono
|
||||
|
||||
^[Verify]
|
||||
/app/**/ci/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/admin/jobs_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/admin/runner_projects_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/admin/runners_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/artifacts_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/build_artifacts_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/builds_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/jobs_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/runner_setup_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/pipeline_schedules_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/pipelines_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/pipelines_settings_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/runner_projects_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/runners_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/triggers_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/usage_quotas_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/controllers/projects/variables_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/models/commit_status.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/models/external_pull_request.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/models/generic_commit_status.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/models/namespace_ci_cd_setting.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/models/project_ci_cd_setting.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/presenters/commit_status_presenter.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/presenters/generic_commit_status_presenter.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/artifacts/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/generic_commit_statuses/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/jobs/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/pipeline_schedules/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/pipelines/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/views/projects/triggers/ @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/build_hooks_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/build_queue_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/build_success_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/ci_platform_metrics_update_cron_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/create_pipeline_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/expire_build_artifacts_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/pipeline_hooks_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/pipeline_metrics_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/pipeline_notification_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/pipeline_process_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/pipeline_schedule_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/run_pipeline_schedule_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/stuck_ci_jobs_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/app/workers/update_external_pull_requests_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/lib/**/ci/ @gitlab-org/maintainers/cicd-verify
|
||||
/lib/api/commit_statuses.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/**/ci/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/**/merge_trains/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/models/merge_train.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/finders/merge_trains_finder.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/services/auto_merge/add_to_merge_train_when_pipeline_succeeds_service.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/services/auto_merge/merge_train_service.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/services/system_notes/merge_train_service.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/controllers/ee/admin/runners_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/controllers/ee/projects/pipelines_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/controllers/projects/pipelines/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/controllers/projects/subscriptions_controller.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/models/merge_train.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/helpers/ee/projects/pipeline_helper.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/views/ci_minutes_usage_mailer/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/views/projects/pipelines/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/views/projects/settings/ci_cd/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/app/workers/clear_shared_runners_minutes_worker.rb @gitlab-org/maintainers/cicd-verify
|
||||
/ee/lib/**/ci/ @gitlab-org/maintainers/cicd-verify
|
||||
/ee/lib/ee/api/entities/merge_train.rb @gitlab-org/maintainers/cicd-verify
|
||||
/**/javascripts/jobs/ @pburdette @jivanvl
|
||||
/**/javascripts/pipelines/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
|
||||
/app/assets/javascripts/pipeline_new/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
|
||||
/app/assets/javascripts/ci_lint/ @f_caplette @bsandlin @mgandres
|
||||
/app/assets/javascripts/ci_variable_list/ @pburdette @f_caplette @jivanvl @mfluharty @bsandlin @mgandres
|
||||
/app/assets/javascripts/pipeline_schedules/ @pburdette @jivanvl
|
||||
/app/assets/javascripts/pipeline_editor/ @f_caplette @bsandlin @mgandres
|
||||
/ee/app/assets/javascripts/ci_minutes_usage/ @pburdette @jivanvl
|
||||
/ee/app/assets/javascripts/usage_quotas/ci_minutes_usage/ @pburdette @jivanvl
|
||||
/ee/app/assets/javascripts/usage_quotas/pipelines/ @pburdette @jivanvl
|
||||
/ee/app/assets/javascripts/reports/ @mfluharty
|
||||
|
||||
^[Templates]
|
||||
/lib/gitlab/ci/templates/ @gitlab-org/maintainers/cicd-templates
|
||||
/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml @DylanGriffith @mayra-cabrera @tkuah
|
||||
|
|
|
@ -620,7 +620,7 @@ rspec:feature-flags:
|
|||
stage: post-test
|
||||
needs:
|
||||
- job: "feature-flags-usage"
|
||||
- job: "haml-lint foss"
|
||||
- job: "haml-lint"
|
||||
- job: "haml-lint ee"
|
||||
optional: true
|
||||
script:
|
||||
|
|
|
@ -264,7 +264,7 @@
|
|||
- "Dockerfile.assets"
|
||||
- "config/**/*.js"
|
||||
- "vendor/assets/**/*"
|
||||
- "{app/assets,app/helpers,app/presenters,app/views,locale,public,spec/frontend,symbol}/**/*"
|
||||
- "{app/assets,app/components,app/helpers,app/presenters,app/views,locale,public,spec/frontend,symbol}/**/*"
|
||||
|
||||
.controllers-patterns: &controllers-patterns
|
||||
- "{,ee/,jh/}{app/controllers}/**/*"
|
||||
|
@ -284,7 +284,7 @@
|
|||
- "Rakefile"
|
||||
- "config.ru"
|
||||
# List explicitly all the app/ dirs that are backend (i.e. all except app/assets).
|
||||
- "{,ee/,jh/}{app/channels,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
|
||||
- "{,ee/,jh/}{app/channels,app/components,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
|
||||
- "{,ee/,jh/}{bin,config,db,generator_templates,lib}/**/*"
|
||||
- "{,ee/,jh/}spec/**/*"
|
||||
# CI changes
|
||||
|
@ -299,7 +299,7 @@
|
|||
- "{,jh/}Gemfile.lock"
|
||||
- "GITLAB_ELASTICSEARCH_INDEXER_VERSION"
|
||||
# List explicitly all the app/ dirs that are backend (i.e. all except app/assets).
|
||||
- "{,ee/,jh/}{app/channels,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
|
||||
- "{,ee/,jh/}{app/channels,app/components,app/controllers,app/finders,app/graphql,app/helpers,app/mailers,app/models,app/policies,app/presenters,app/serializers,app/services,app/uploaders,app/validators,app/views,app/workers}/**/*"
|
||||
- "{,ee/,jh/}{bin,config,db,generator_templates,lib}/**/*"
|
||||
- "{,ee/,jh/}spec/**/*"
|
||||
|
||||
|
@ -494,9 +494,14 @@
|
|||
|
||||
.static-analysis-patterns: &static-analysis-patterns
|
||||
- ".{codeclimate,eslintrc,haml-lint,haml-lint_todo}.yml"
|
||||
- ".rubocop.yml"
|
||||
- ".rubocop_todo.yml"
|
||||
|
||||
.rubocop-patterns: &rubocop-patterns
|
||||
- ".{rubocop,rubocop_todo}.yml"
|
||||
- ".rubocop_todo/**/*.yml"
|
||||
- "{,ee/,jh/}rubocop/**/*" # We might be changing custom cops
|
||||
- "{,ee/,jh/}Gemfile.lock" # This should include gitlab-styles, rubocop itself, and any plugins we might be using
|
||||
- "lib/gitlab_edition.rb" # This is required in RuboCop::CodeReuseHelpers
|
||||
- ".gitlab/ci/static-analysis.gitlab-ci.yml"
|
||||
|
||||
.danger-patterns: &danger-patterns
|
||||
- "Dangerfile"
|
||||
|
@ -1427,24 +1432,42 @@
|
|||
# Static analysis rules #
|
||||
#########################
|
||||
|
||||
.static-analysis:rules:ee-and-foss:
|
||||
.static-analysis:rules:static-analysis:
|
||||
rules:
|
||||
- changes: *code-backstage-qa-patterns
|
||||
- changes: *static-analysis-patterns
|
||||
|
||||
.static-analysis:rules:ee-and-foss-qa:
|
||||
.static-analysis:rules:static-verification-with-database:
|
||||
rules:
|
||||
- changes: *code-backstage-qa-patterns
|
||||
|
||||
.static-analysis:rules:rubocop:
|
||||
rules:
|
||||
- changes: *rubocop-patterns
|
||||
variables:
|
||||
RUN_ALL_RUBOCOP: "true"
|
||||
- changes: *code-backstage-qa-patterns
|
||||
|
||||
.static-analysis:rules:qa:metadata-lint:
|
||||
rules:
|
||||
- changes: *qa-patterns
|
||||
- changes: *static-analysis-patterns
|
||||
- changes: [".gitlab/ci/static-analysis.gitlab-ci.yml"]
|
||||
|
||||
.static-analysis:rules:ee:
|
||||
.static-analysis:rules:haml-lint:
|
||||
rules:
|
||||
- changes: *rubocop-patterns
|
||||
- changes: *static-analysis-patterns
|
||||
- changes: *code-backstage-qa-patterns
|
||||
|
||||
.static-analysis:rules:haml-lint-ee:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
- changes: *code-backstage-qa-patterns
|
||||
- changes: *rubocop-patterns
|
||||
- changes: *static-analysis-patterns
|
||||
- changes: *code-backstage-qa-patterns
|
||||
|
||||
.static-analysis:rules:as-if-foss:
|
||||
.static-analysis:rules:static-analysis-as-if-foss:
|
||||
rules:
|
||||
- <<: *if-not-ee
|
||||
when: never
|
||||
|
@ -1453,7 +1476,7 @@
|
|||
- <<: *if-security-merge-request
|
||||
changes: *code-backstage-qa-patterns
|
||||
- <<: *if-merge-request
|
||||
changes: *ci-patterns
|
||||
changes: [".gitlab/ci/static-analysis.gitlab-ci.yml"]
|
||||
- <<: *if-merge-request
|
||||
changes: *static-analysis-patterns
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ static-analysis:
|
|||
extends:
|
||||
- .static-analysis-base
|
||||
- .static-analysis-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:static-analysis
|
||||
parallel: 2
|
||||
script:
|
||||
- run_timed_command "retry yarn install --frozen-lockfile"
|
||||
|
@ -34,14 +34,14 @@ static-analysis:
|
|||
static-analysis as-if-foss:
|
||||
extends:
|
||||
- static-analysis
|
||||
- .static-analysis:rules:as-if-foss
|
||||
- .static-analysis:rules:static-analysis-as-if-foss
|
||||
- .as-if-foss
|
||||
|
||||
static-verification-with-database:
|
||||
extends:
|
||||
- .static-analysis-base
|
||||
- .rubocop-job-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:static-verification-with-database
|
||||
- .use-pg12
|
||||
script:
|
||||
- bundle exec rake lint:static_verification_with_database
|
||||
|
@ -91,11 +91,11 @@ eslint as-if-foss:
|
|||
- .as-if-foss
|
||||
needs: ['generate-apollo-graphql-schema as-if-foss']
|
||||
|
||||
haml-lint foss:
|
||||
haml-lint:
|
||||
extends:
|
||||
- .static-analysis-base
|
||||
- .ruby-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:haml-lint
|
||||
script:
|
||||
- run_timed_command "bin/rake 'haml_lint[app/views]'"
|
||||
artifacts:
|
||||
|
@ -106,8 +106,8 @@ haml-lint foss:
|
|||
|
||||
haml-lint ee:
|
||||
extends:
|
||||
- "haml-lint foss"
|
||||
- .static-analysis:rules:ee
|
||||
- "haml-lint"
|
||||
- .static-analysis:rules:haml-lint-ee
|
||||
script:
|
||||
- run_timed_command "bin/rake 'haml_lint[ee/app/views]'"
|
||||
|
||||
|
@ -115,14 +115,21 @@ rubocop:
|
|||
extends:
|
||||
- .static-analysis-base
|
||||
- .rubocop-job-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:rubocop
|
||||
needs: ["detect-tests"]
|
||||
script:
|
||||
- run_timed_command "bundle exec rubocop --parallel"
|
||||
- |
|
||||
# For non-merge request, or when RUN_ALL_RUBOCOP is 'true', run all RuboCop rules
|
||||
if [ -z "${CI_MERGE_REQUEST_IID}" ] || [ "${RUN_ALL_RUBOCOP}" == "true" ]; then
|
||||
run_timed_command "bundle exec rubocop --parallel"
|
||||
else
|
||||
run_timed_command "bundle exec rubocop --parallel --force-exclusion $(cat tmp/changed_files.txt)"
|
||||
fi
|
||||
|
||||
qa:metadata-lint:
|
||||
extends:
|
||||
- .static-analysis-base
|
||||
- .static-analysis:rules:ee-and-foss-qa
|
||||
- .static-analysis:rules:qa:metadata-lint
|
||||
before_script:
|
||||
- !reference [.default-before_script, before_script]
|
||||
- cd qa/
|
||||
|
@ -149,7 +156,7 @@ feature-flags-usage:
|
|||
extends:
|
||||
- .static-analysis-base
|
||||
- .rubocop-job-cache
|
||||
- .static-analysis:rules:ee-and-foss
|
||||
- .static-analysis:rules:rubocop
|
||||
script:
|
||||
# We need to disable the cache for this cop since it creates files under tmp/feature_flags/*.used,
|
||||
# the cache would prevent these files from being created.
|
||||
|
|
|
@ -1,74 +0,0 @@
|
|||
---
|
||||
# Cop supports --auto-correct.
|
||||
Layout/SpaceInsideBlockBraces:
|
||||
Exclude:
|
||||
- 'spec/config/settings_spec.rb'
|
||||
- 'spec/controllers/admin/application_settings_controller_spec.rb'
|
||||
- 'spec/controllers/application_controller_spec.rb'
|
||||
- 'spec/controllers/groups/labels_controller_spec.rb'
|
||||
- 'spec/controllers/groups/releases_controller_spec.rb'
|
||||
- 'spec/controllers/import/manifest_controller_spec.rb'
|
||||
- 'spec/controllers/projects/blame_controller_spec.rb'
|
||||
- 'spec/controllers/projects/deploy_keys_controller_spec.rb'
|
||||
- 'spec/controllers/projects/feature_flags_controller_spec.rb'
|
||||
- 'spec/controllers/projects/jobs_controller_spec.rb'
|
||||
- 'spec/controllers/projects/labels_controller_spec.rb'
|
||||
- 'spec/controllers/projects/notes_controller_spec.rb'
|
||||
- 'spec/controllers/projects/releases_controller_spec.rb'
|
||||
- 'spec/controllers/projects/tree_controller_spec.rb'
|
||||
- 'spec/controllers/registrations/welcome_controller_spec.rb'
|
||||
- 'spec/controllers/snippets/notes_controller_spec.rb'
|
||||
- 'spec/dependencies/omniauth_saml_spec.rb'
|
||||
- 'spec/experiments/application_experiment_spec.rb'
|
||||
- 'spec/finders/ci/jobs_finder_spec.rb'
|
||||
- 'spec/finders/ci/runners_finder_spec.rb'
|
||||
- 'spec/finders/concerns/packages/finder_helper_spec.rb'
|
||||
- 'spec/finders/container_repositories_finder_spec.rb'
|
||||
- 'spec/finders/design_management/versions_finder_spec.rb'
|
||||
- 'spec/finders/milestones_finder_spec.rb'
|
||||
- 'spec/finders/packages/group_packages_finder_spec.rb'
|
||||
- 'spec/finders/packages/npm/package_finder_spec.rb'
|
||||
- 'spec/finders/projects_finder_spec.rb'
|
||||
- 'spec/helpers/application_settings_helper_spec.rb'
|
||||
- 'spec/helpers/blob_helper_spec.rb'
|
||||
- 'spec/helpers/gitlab_script_tag_helper_spec.rb'
|
||||
- 'spec/helpers/issuables_helper_spec.rb'
|
||||
- 'spec/helpers/projects/pipeline_helper_spec.rb'
|
||||
- 'spec/helpers/routing/pseudonymization_helper_spec.rb'
|
||||
- 'spec/helpers/search_helper_spec.rb'
|
||||
- 'spec/helpers/wiki_page_version_helper_spec.rb'
|
||||
- 'spec/initializers/carrierwave_patch_spec.rb'
|
||||
- 'spec/initializers/trusted_proxies_spec.rb'
|
||||
- 'spec/mailers/emails/service_desk_spec.rb'
|
||||
- 'spec/migrations/20210812013042_remove_duplicate_project_authorizations_spec.rb'
|
||||
- 'spec/migrations/20210910194952_update_report_type_for_existing_approval_project_rules_spec.rb'
|
||||
- 'spec/migrations/confirm_support_bot_user_spec.rb'
|
||||
- 'spec/migrations/reset_job_token_scope_enabled_again_spec.rb'
|
||||
- 'spec/migrations/reset_job_token_scope_enabled_spec.rb'
|
||||
- 'spec/migrations/reset_severity_levels_to_new_default_spec.rb'
|
||||
- 'spec/policies/clusters/agent_policy_spec.rb'
|
||||
- 'spec/policies/group_member_policy_spec.rb'
|
||||
- 'spec/policies/issue_policy_spec.rb'
|
||||
- 'spec/policies/project_policy_spec.rb'
|
||||
- 'spec/policies/terraform/state_policy_spec.rb'
|
||||
- 'spec/policies/terraform/state_version_policy_spec.rb'
|
||||
- 'spec/presenters/packages/composer/packages_presenter_spec.rb'
|
||||
- 'spec/presenters/packages/conan/package_presenter_spec.rb'
|
||||
- 'spec/presenters/packages/nuget/packages_metadata_presenter_spec.rb'
|
||||
- 'spec/presenters/project_presenter_spec.rb'
|
||||
- 'spec/rubocop/cop/migration/create_table_with_foreign_keys_spec.rb'
|
||||
- 'spec/serializers/cluster_entity_spec.rb'
|
||||
- 'spec/serializers/import/provider_repo_serializer_spec.rb'
|
||||
- 'spec/tasks/gitlab/snippets_rake_spec.rb'
|
||||
- 'spec/uploaders/packages/debian/distribution_release_file_uploader_spec.rb'
|
||||
- 'spec/validators/addressable_url_validator_spec.rb'
|
||||
- 'spec/views/help/instance_configuration.html.haml_spec.rb'
|
||||
- 'spec/views/layouts/_header_search.html.haml_spec.rb'
|
||||
- 'spec/views/layouts/_published_experiments.html.haml_spec.rb'
|
||||
- 'spec/views/shared/runners/_runner_details.html.haml_spec.rb'
|
||||
- 'spec/workers/bulk_imports/export_request_worker_spec.rb'
|
||||
- 'spec/workers/clusters/cleanup/project_namespace_worker_spec.rb'
|
||||
- 'spec/workers/packages/helm/extraction_worker_spec.rb'
|
||||
- 'spec/workers/pages_worker_spec.rb'
|
||||
- 'spec/workers/purge_dependency_proxy_cache_worker_spec.rb'
|
||||
- 'spec/workers/releases/manage_evidence_worker_spec.rb'
|
|
@ -12,8 +12,6 @@ export const FIELDS = [
|
|||
key: 'name',
|
||||
label: __('Token name'),
|
||||
sortable: true,
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
},
|
||||
{
|
||||
formatter(scopes) {
|
||||
|
@ -22,40 +20,30 @@ export const FIELDS = [
|
|||
key: 'scopes',
|
||||
label: __('Scopes'),
|
||||
sortable: true,
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
},
|
||||
{
|
||||
key: 'createdAt',
|
||||
label: s__('AccessTokens|Created'),
|
||||
sortable: true,
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
},
|
||||
{
|
||||
key: 'lastUsedAt',
|
||||
label: __('Last Used'),
|
||||
sortable: true,
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
},
|
||||
{
|
||||
key: 'expiresAt',
|
||||
label: __('Expires'),
|
||||
sortable: true,
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
},
|
||||
{
|
||||
key: 'role',
|
||||
label: __('Role'),
|
||||
tdClass: `gl-text-black-normal`,
|
||||
thClass: `gl-text-black-normal`,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
key: 'action',
|
||||
label: __('Action'),
|
||||
thClass: `gl-text-black-normal`,
|
||||
tdClass: 'gl-py-3!',
|
||||
},
|
||||
];
|
||||
|
|
|
@ -105,7 +105,11 @@ export default {
|
|||
<code-block-bubble-menu />
|
||||
<link-bubble-menu />
|
||||
<media-bubble-menu />
|
||||
<tiptap-editor-content class="md" :editor="contentEditor.tiptapEditor" />
|
||||
<tiptap-editor-content
|
||||
class="md"
|
||||
data-testid="content_editor_editablebox"
|
||||
:editor="contentEditor.tiptapEditor"
|
||||
/>
|
||||
<loading-indicator />
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -157,7 +157,7 @@ export const SCANNER_NAMES_MAP = {
|
|||
COVERAGE_FUZZING: COVERAGE_FUZZING_NAME,
|
||||
SECRET_DETECTION: SECRET_DETECTION_NAME,
|
||||
DEPENDENCY_SCANNING: DEPENDENCY_SCANNING_NAME,
|
||||
GENERIC: s__('ciReport|Manually Added'),
|
||||
GENERIC: s__('ciReport|Manually added'),
|
||||
};
|
||||
|
||||
export const securityFeatures = [
|
||||
|
|
|
@ -46,7 +46,7 @@ export const SortDirection = {
|
|||
export const FILTERED_SEARCH_LABELS = 'labels';
|
||||
export const FILTERED_SEARCH_TERM = 'filtered-search-term';
|
||||
|
||||
export const TOKEN_TITLE_ASSIGNEE = __('Assignee');
|
||||
export const TOKEN_TITLE_ASSIGNEE = s__('SearchToken|Assignee');
|
||||
export const TOKEN_TITLE_AUTHOR = __('Author');
|
||||
export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential');
|
||||
export const TOKEN_TITLE_CONTACT = s__('Crm|Contact');
|
||||
|
|
|
@ -149,7 +149,7 @@
|
|||
margin: $sidebar-top-item-tb-margin $sidebar-top-item-lr-margin;
|
||||
|
||||
&:hover {
|
||||
background-color: $indigo-900-alpha-008;
|
||||
background-color: $nav-active-bg;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,7 @@
|
|||
|
||||
&:not(.fly-out-top-item) {
|
||||
> a:not(.has-sub-items) {
|
||||
background-color: $indigo-900-alpha-008;
|
||||
background-color: $nav-active-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -560,7 +560,7 @@
|
|||
}
|
||||
|
||||
.frequent-items-list-item-container > a:hover {
|
||||
background-color: $nav-active-bg;
|
||||
background-color: $nav-active-bg !important;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -577,7 +577,7 @@
|
|||
.top-nav-menu-item {
|
||||
&.active,
|
||||
&:hover {
|
||||
background-color: $nav-active-bg;
|
||||
background-color: $nav-active-bg !important;
|
||||
}
|
||||
|
||||
.gl-icon {
|
||||
|
|
|
@ -364,7 +364,7 @@ $well-expand-item: #e8f2f7 !default;
|
|||
$well-inner-border: #eef0f2 !default;
|
||||
$well-light-border: #f1f1f1;
|
||||
$well-light-text-color: #5b6169;
|
||||
$nav-active-bg: var(--nav-active-bg, rgba($black, 0.08)) !important;
|
||||
$nav-active-bg: rgba($black, 0.08);
|
||||
|
||||
/*
|
||||
* Text
|
||||
|
|
|
@ -18,7 +18,6 @@ body.gl-dark {
|
|||
--gl-text-color: #fafafa;
|
||||
--border-color: #4f4f4f;
|
||||
--black: #fff;
|
||||
--nav-active-bg: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
:root {
|
||||
--white: #333;
|
||||
|
@ -1128,7 +1127,7 @@ kbd {
|
|||
font-weight: 600;
|
||||
}
|
||||
.nav-sidebar li.active:not(.fly-out-top-item) > a:not(.has-sub-items) {
|
||||
background-color: rgba(41, 41, 97, 0.08);
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.nav-sidebar ul {
|
||||
padding-left: 0;
|
||||
|
@ -1781,7 +1780,6 @@ body.gl-dark {
|
|||
--white: #333;
|
||||
--black: #fff;
|
||||
--svg-status-bg: #333;
|
||||
--nav-active-bg: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.nav-sidebar,
|
||||
.toggle-sidebar-button,
|
||||
|
@ -1796,12 +1794,6 @@ body.gl-dark {
|
|||
.nav-sidebar li a {
|
||||
color: var(--gray-600);
|
||||
}
|
||||
.nav-sidebar li.active {
|
||||
box-shadow: none;
|
||||
}
|
||||
.nav-sidebar li.active:not(.fly-out-top-item) > a:not(.has-sub-items) {
|
||||
background-color: var(--nav-active-bg);
|
||||
}
|
||||
body.gl-dark {
|
||||
--gl-theme-accent: #868686;
|
||||
}
|
||||
|
@ -2029,7 +2021,6 @@ body.gl-dark {
|
|||
--white: #333;
|
||||
--black: #fff;
|
||||
--svg-status-bg: #333;
|
||||
--nav-active-bg: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
.tab-width-8 {
|
||||
tab-size: 8;
|
||||
|
|
|
@ -1107,7 +1107,7 @@ kbd {
|
|||
font-weight: 600;
|
||||
}
|
||||
.nav-sidebar li.active:not(.fly-out-top-item) > a:not(.has-sub-items) {
|
||||
background-color: rgba(41, 41, 97, 0.08);
|
||||
background-color: rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
.nav-sidebar ul {
|
||||
padding-left: 0;
|
||||
|
|
|
@ -101,7 +101,6 @@ $white-dark: #444;
|
|||
$theme-indigo-50: #1a1a40;
|
||||
|
||||
$border-color: #4f4f4f;
|
||||
$nav-active-bg: rgba(255, 255, 255, 0.08);
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
|
@ -206,7 +205,6 @@ body.gl-dark {
|
|||
--black: #{$black};
|
||||
|
||||
--svg-status-bg: #{$white};
|
||||
--nav-active-bg: #{$nav-active-bg};
|
||||
|
||||
.gl-button.gl-button,
|
||||
.gl-button.gl-button.btn-block {
|
||||
|
|
|
@ -64,20 +64,6 @@
|
|||
a {
|
||||
color: var(--gray-600);
|
||||
}
|
||||
|
||||
> a:hover {
|
||||
background-color: var(--nav-active-bg);
|
||||
}
|
||||
|
||||
&.active {
|
||||
box-shadow: none;
|
||||
|
||||
&:not(.fly-out-top-item) {
|
||||
> a:not(.has-sub-items) {
|
||||
background-color: var(--nav-active-bg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-sub-level-items.fly-out-list {
|
||||
|
|
|
@ -473,7 +473,7 @@ module Ci
|
|||
end
|
||||
|
||||
def uses_needs?
|
||||
builds.where(scheduling_type: :dag).any?
|
||||
processables.where(scheduling_type: :dag).any?
|
||||
end
|
||||
|
||||
def stages_count
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
name: ci_forked_source_public_cost_factor
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94870
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/370147
|
||||
milestone: '15.4'
|
||||
type: development
|
||||
group: group::pipeline execution
|
||||
default_enabled: false
|
|
@ -16,17 +16,13 @@ options:
|
|||
events:
|
||||
- i_package_composer_deploy_token
|
||||
- i_package_conan_deploy_token
|
||||
- i_package_container_deploy_token
|
||||
- i_package_debian_deploy_token
|
||||
- i_package_generic_deploy_token
|
||||
- i_package_golang_deploy_token
|
||||
- i_package_helm_deploy_token
|
||||
- i_package_maven_deploy_token
|
||||
- i_package_npm_deploy_token
|
||||
- i_package_nuget_deploy_token
|
||||
- i_package_pypi_deploy_token
|
||||
- i_package_rubygems_deploy_token
|
||||
- i_package_tag_deploy_token
|
||||
- i_package_terraform_module_deploy_token
|
||||
distribution:
|
||||
- ee
|
||||
|
|
|
@ -15,17 +15,13 @@ options:
|
|||
events:
|
||||
- i_package_composer_deploy_token
|
||||
- i_package_conan_deploy_token
|
||||
- i_package_container_deploy_token
|
||||
- i_package_debian_deploy_token
|
||||
- i_package_generic_deploy_token
|
||||
- i_package_golang_deploy_token
|
||||
- i_package_helm_deploy_token
|
||||
- i_package_maven_deploy_token
|
||||
- i_package_npm_deploy_token
|
||||
- i_package_nuget_deploy_token
|
||||
- i_package_pypi_deploy_token
|
||||
- i_package_rubygems_deploy_token
|
||||
- i_package_tag_deploy_token
|
||||
- i_package_terraform_module_deploy_token
|
||||
distribution:
|
||||
- ee
|
||||
|
|
|
@ -201,9 +201,12 @@ can be higher than the end-to-end duration of a pipeline.
|
|||
|
||||
The cost factors for jobs running on shared runners on GitLab.com are:
|
||||
|
||||
- `0.008` for public projects, and projects in the [GitLab for Open Source program](../../subscriptions/index.md#gitlab-for-open-source).
|
||||
For every 125 minutes of job execution time, you use 1 CI/CD minute.
|
||||
- `1` for internal and private projects.
|
||||
- `0.5` for public projects in the [GitLab for Open Source program](../../subscriptions/index.md#gitlab-for-open-source).
|
||||
- `0.008` for public forks of public projects. For every 125 minutes of job execution time,
|
||||
you use 1 CI/CD minute.
|
||||
- `0.04` for other public projects, after September 1, 2022 (previously `0.008`).
|
||||
For every 25 minutes of job execution time, you use 1 CI/CD minute.
|
||||
- Calculated differently for [community contributions to GitLab projects](#cost-factor-for-community-contributions-to-gitlab-projects).
|
||||
|
||||
The cost factors on self-managed instances are:
|
||||
|
|
|
@ -10,7 +10,7 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo
|
|||
NOTE:
|
||||
The documentation below is the single source of truth for the merge request terminology and functionality.
|
||||
|
||||
The merge request is made up of several different key components and ideas that encompass the overall merge request experience. These concepts sometimes have competing and confusing terminology or overlap with other concepts. The concepts this will cover are:
|
||||
The merge request is made up of several different key components and ideas that encompass the overall merge request experience. These concepts sometimes have competing and confusing terminology or overlap with other concepts. This page covers the following concepts:
|
||||
|
||||
1. Merge widget
|
||||
1. Report widgets
|
||||
|
@ -40,15 +40,17 @@ Reports are widgets within the merge request that report information about chang
|
|||
|
||||
## Merge checks
|
||||
|
||||
Merge checks are statuses that can either pass or fail and conditionally control the availability of the merge button being available within a merge request. The key distinguishing factor in a merge check is that users **do not** interact with the merge checks inside of the merge request, but are able to influence whether or not the check passes or fails. Results from the check are processed as true/false to determine whether or not a merge request can be merged. Examples include:
|
||||
Merge checks are statuses that can either pass or fail and conditionally control the availability of the merge button being available within a merge request. The key distinguishing factor in a merge check is that users **do not** interact with the merge checks inside of the merge request, but are able to influence whether or not the check passes or fails. Results from the check are processed as true/false to determine whether or not a merge request can be merged.
|
||||
|
||||
- Merge conflicts.
|
||||
- Pipeline success.
|
||||
- Threads resolution.
|
||||
- [External status checks](../../user/project/merge_requests/status_checks.md).
|
||||
- Required approvals.
|
||||
Examples of merge checks include:
|
||||
|
||||
When all of the required merge checks are satisfied a merge request becomes mergeable.
|
||||
- Merge conflicts
|
||||
- Pipeline success
|
||||
- Threads resolution
|
||||
- [External status checks](../../user/project/merge_requests/status_checks.md)
|
||||
- Required approvals
|
||||
|
||||
A merge request can be merged only when all of the required merge checks are satisfied.
|
||||
|
||||
## Approvals
|
||||
|
||||
|
@ -58,8 +60,8 @@ Additionally, approval settings provide configuration options to define how thos
|
|||
|
||||
Examples of approval rules and settings include:
|
||||
|
||||
1. [merge request approval rules](../../user/project/merge_requests/approvals/rules.md)
|
||||
1. [code owner approvals](../../user/project/code_owners.md)
|
||||
1. [security approvals](../../user/application_security/index.md#security-approvals-in-merge-requests)
|
||||
1. [prevent editing approval rules](../../user/project/merge_requests/approvals/settings.md#prevent-editing-approval-rules-in-merge-requests)
|
||||
1. [remove all approvals when commits are added](../../user/project/merge_requests/approvals/settings.md#remove-all-approvals-when-commits-are-added-to-the-source-branch)
|
||||
- [Merge request approval rules](../../user/project/merge_requests/approvals/rules.md)
|
||||
- [Code owner approvals](../../user/project/code_owners.md)
|
||||
- [Security approvals](../../user/application_security/index.md#security-approvals-in-merge-requests)
|
||||
- [Prevent editing approval rules](../../user/project/merge_requests/approvals/settings.md#prevent-editing-approval-rules-in-merge-requests)
|
||||
- [Remove all approvals when commits are added](../../user/project/merge_requests/approvals/settings.md#remove-all-approvals-when-commits-are-added-to-the-source-branch)
|
||||
|
|
|
@ -127,7 +127,7 @@ Examples using `usage_data.rb` have been [deprecated](usage_data.md). We recomme
|
|||
|
||||
#### Grouping and batch operations
|
||||
|
||||
The `count`, `distinct_count`, `sum`, and `average` batch counters can accept an `ActiveRecord::Relation`
|
||||
The `count`, `distinct_count` and `sum` batch counters can accept an `ActiveRecord::Relation`
|
||||
object, which groups by a specified column. With a grouped relation, the methods do batch counting,
|
||||
handle errors, and returns a hash table of key-value pairs.
|
||||
|
||||
|
@ -142,9 +142,6 @@ distinct_count(Project.group(:visibility_level), :creator_id)
|
|||
|
||||
sum(Issue.group(:state_id), :weight))
|
||||
# returns => {1=>3542, 2=>6820}
|
||||
|
||||
average(Issue.group(:state_id), :weight))
|
||||
# returns => {1=>3.5, 2=>2.5}
|
||||
```
|
||||
|
||||
#### Add operation
|
||||
|
|
|
@ -337,7 +337,7 @@ To create a stub instrumentation for a Service Ping metric, you can use a dedica
|
|||
The generator takes the class name as an argument and the following options:
|
||||
|
||||
- `--type=TYPE` Required. Indicates the metric type. It must be one of: `database`, `generic`, `redis`, `numbers`.
|
||||
- `--operation` Required for `database` & `numebers` type.
|
||||
- `--operation` Required for `database` & `numbers` type.
|
||||
- For `database` it must be one of: `count`, `distinct_count`, `estimate_batch_distinct_count`, `sum`, `average`.
|
||||
- For `numbers` it must be: `add`.
|
||||
- `--ee` Indicates if the metric is for EE.
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 48 KiB |
Binary file not shown.
After Width: | Height: | Size: 60 KiB |
|
@ -56,12 +56,11 @@ displays next to your name.
|
|||
You can submit your completed review in multiple ways:
|
||||
|
||||
- Use the `/submit_review` [quick action](../../quick_actions.md) in the text of a non-review comment.
|
||||
- Select **Finish review** and then **Submit review** in the footer at the bottom of the screen.
|
||||
- Select **Finish review**, then select **Submit review** at the bottom of the modal window.
|
||||
In the modal window, you can supply a **Summary comment**, approve the merge request, and
|
||||
include quick actions:
|
||||
|
||||
Selecting **Finish review** opens a modal window to add an optional comment to summarize your review.
|
||||
You can also include quick actions:
|
||||
|
||||
![Finish review with comment](img/mr_summary_comment_v15_3.png)
|
||||
![Finish review with comment](img/mr_summary_comment_v15_4.png)
|
||||
|
||||
When you submit your review, GitLab:
|
||||
|
||||
|
@ -69,6 +68,7 @@ When you submit your review, GitLab:
|
|||
- Sends a single email to every notifiable user of the merge request, with your
|
||||
review comments attached. Replying to this email creates a new comment on the merge request.
|
||||
- Perform any quick actions you added to your review comments.
|
||||
- Optional. Approves the merge request.
|
||||
|
||||
### Resolve or unresolve thread with a comment
|
||||
|
||||
|
|
|
@ -10,16 +10,12 @@ module Gitlab
|
|||
vulnerability_reads.project_id = cluster_agents.project_id
|
||||
SQL
|
||||
|
||||
RELATION = ->(relation) do
|
||||
relation
|
||||
.where(report_type: 7)
|
||||
end
|
||||
CLUSTER_IMAGE_SCANNING_REPORT_TYPE = 7
|
||||
|
||||
scope_to ->(relation) { relation.where(report_type: CLUSTER_IMAGE_SCANNING_REPORT_TYPE) }
|
||||
|
||||
def perform
|
||||
each_sub_batch(
|
||||
operation_name: :update_all,
|
||||
batching_scope: RELATION
|
||||
) do |sub_batch|
|
||||
each_sub_batch(operation_name: :update_all) do |sub_batch|
|
||||
sub_batch
|
||||
.joins(CLUSTER_AGENTS_JOIN)
|
||||
.update_all('casted_cluster_agent_id = CAST(vulnerability_reads.cluster_agent_id AS bigint)')
|
||||
|
|
|
@ -3,18 +3,9 @@
|
|||
module Gitlab
|
||||
module BackgroundMigration
|
||||
module BatchingStrategies
|
||||
# Batching class to use for back-filling project_statistic's container_registry_size.
|
||||
# Batches will be scoped to records where the project_ids are migrated
|
||||
#
|
||||
# If no more batches exist in the table, returns nil.
|
||||
# Used to apply additional filters to the batching table, migrated to
|
||||
# use BatchedMigrationJob#filter_batch with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93771
|
||||
class BackfillProjectStatisticsWithContainerRegistrySizeBatchingStrategy < PrimaryKeyBatchingStrategy
|
||||
MIGRATION_PHASE_1_ENDED_AT = Date.new(2022, 01, 23).freeze
|
||||
|
||||
def apply_additional_filters(relation, job_arguments: [], job_class: nil)
|
||||
relation.where(created_at: MIGRATION_PHASE_1_ENDED_AT..).or(
|
||||
relation.where(migration_state: 'import_done')
|
||||
).select(:project_id).distinct
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,16 +3,9 @@
|
|||
module Gitlab
|
||||
module BackgroundMigration
|
||||
module BatchingStrategies
|
||||
# Batching class to use for back-filling vulnerability_read's casted_cluster_agent_id from cluster_agent_id.
|
||||
# Batches will be scoped to records where the report_type belongs to cluster_image_scanning.
|
||||
#
|
||||
# If no more batches exist in the table, returns nil.
|
||||
# Used to apply additional filters to the batching table, migrated to
|
||||
# use BatchedMigrationJob#filter_batch with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93771
|
||||
class BackfillVulnerabilityReadsClusterAgentBatchingStrategy < PrimaryKeyBatchingStrategy
|
||||
CLUSTER_IMAGE_SCANNING_REPORT_TYPE = 7
|
||||
|
||||
def apply_additional_filters(relation, job_arguments: [], job_class: nil)
|
||||
relation.where(report_type: CLUSTER_IMAGE_SCANNING_REPORT_TYPE)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,14 +3,9 @@
|
|||
module Gitlab
|
||||
module BackgroundMigration
|
||||
module BatchingStrategies
|
||||
# Batching class to use for setting state in vulnerabilitites table.
|
||||
# Batches will be scoped to records where the dismissed_at is set.
|
||||
#
|
||||
# If no more batches exist in the table, returns nil.
|
||||
# Used to apply additional filters to the batching table, migrated to
|
||||
# use BatchedMigrationJob#filter_batch with https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93771
|
||||
class DismissedVulnerabilitiesStrategy < PrimaryKeyBatchingStrategy
|
||||
def apply_additional_filters(relation, job_arguments: [], job_class: nil)
|
||||
relation.where.not(dismissed_at: nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -6,11 +6,10 @@ module Gitlab
|
|||
class SetCorrectVulnerabilityState < BatchedMigrationJob
|
||||
DISMISSED_STATE = 2
|
||||
|
||||
scope_to ->(relation) { relation.where.not(dismissed_at: nil) }
|
||||
|
||||
def perform
|
||||
each_sub_batch(
|
||||
operation_name: :update_vulnerabilities_state,
|
||||
batching_scope: -> (relation) { relation.where.not(dismissed_at: nil) }
|
||||
) do |sub_batch|
|
||||
each_sub_batch(operation_name: :update_vulnerabilities_state) do |sub_batch|
|
||||
sub_batch.update_all(state: DISMISSED_STATE)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,103 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module Database
|
||||
class BatchAverageCounter
|
||||
COLUMN_FALLBACK = 0
|
||||
DEFAULT_BATCH_SIZE = 1_000
|
||||
FALLBACK = -1
|
||||
MAX_ALLOWED_LOOPS = 10_000
|
||||
OFFSET_BY_ONE = 1
|
||||
SLEEP_TIME_IN_SECONDS = 0.01 # 10 msec sleep
|
||||
|
||||
attr_reader :relation, :column
|
||||
|
||||
def initialize(relation, column)
|
||||
@relation = relation
|
||||
@column = wrap_column(relation, column)
|
||||
end
|
||||
|
||||
def count(batch_size: nil)
|
||||
raise 'BatchAverageCounter can not be run inside a transaction' if transaction_open?
|
||||
|
||||
batch_size = batch_size.presence || DEFAULT_BATCH_SIZE
|
||||
|
||||
start = column_start
|
||||
finish = column_finish
|
||||
|
||||
total_sum = 0
|
||||
total_records = 0
|
||||
|
||||
batch_start = start
|
||||
|
||||
while batch_start < finish
|
||||
begin
|
||||
batch_end = [batch_start + batch_size, finish].min
|
||||
batch_relation = build_relation_batch(batch_start, batch_end)
|
||||
|
||||
# We use `sum` and `count` instead of `average` here to not run into an "average of averages"
|
||||
# problem as batches will have different sizes, so we are essentially summing up the values for
|
||||
# each batch separately, and then dividing that result on the total number of records.
|
||||
batch_sum, batch_count = batch_relation.pick(column.sum, column.count)
|
||||
|
||||
total_sum += batch_sum.to_i
|
||||
total_records += batch_count
|
||||
|
||||
batch_start = batch_end
|
||||
rescue ActiveRecord::QueryCanceled => error # rubocop:disable Database/RescueQueryCanceled
|
||||
# retry with a safe batch size & warmer cache
|
||||
if batch_size >= 2 * DEFAULT_BATCH_SIZE
|
||||
batch_size /= 2
|
||||
else
|
||||
log_canceled_batch_fetch(batch_start, batch_relation.to_sql, error)
|
||||
|
||||
return FALLBACK
|
||||
end
|
||||
end
|
||||
|
||||
sleep(SLEEP_TIME_IN_SECONDS)
|
||||
end
|
||||
|
||||
return FALLBACK if total_records == 0
|
||||
|
||||
total_sum.to_f / total_records
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def column_start
|
||||
relation.unscope(:group, :having).minimum(column) || COLUMN_FALLBACK
|
||||
end
|
||||
|
||||
def column_finish
|
||||
(relation.unscope(:group, :having).maximum(column) || COLUMN_FALLBACK) + OFFSET_BY_ONE
|
||||
end
|
||||
|
||||
def build_relation_batch(start, finish)
|
||||
relation.where(column.between(start...finish))
|
||||
end
|
||||
|
||||
def log_canceled_batch_fetch(batch_start, query, error)
|
||||
Gitlab::AppJsonLogger
|
||||
.error(
|
||||
event: 'batch_count',
|
||||
relation: relation.table_name,
|
||||
operation: 'average',
|
||||
start: batch_start,
|
||||
query: query,
|
||||
message: "Query has been canceled with message: #{error.message}"
|
||||
)
|
||||
end
|
||||
|
||||
def transaction_open?
|
||||
relation.connection.transaction_open?
|
||||
end
|
||||
|
||||
def wrap_column(relation, column)
|
||||
return column if column.is_a?(Arel::Attributes::Attribute)
|
||||
|
||||
relation.arel_table[column]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -48,7 +48,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def batch_average(relation, column, batch_size: nil, start: nil, finish: nil)
|
||||
BatchCounter.new(relation, column: nil, operation: :average, operation_args: [column]).count(batch_size: batch_size, start: start, finish: finish)
|
||||
BatchAverageCounter.new(relation, column).count(batch_size: batch_size)
|
||||
end
|
||||
|
||||
class << self
|
||||
|
|
|
@ -6,7 +6,6 @@ module Gitlab
|
|||
FALLBACK = -1
|
||||
MIN_REQUIRED_BATCH_SIZE = 1_250
|
||||
DEFAULT_SUM_BATCH_SIZE = 1_000
|
||||
DEFAULT_AVERAGE_BATCH_SIZE = 1_000
|
||||
MAX_ALLOWED_LOOPS = 10_000
|
||||
SLEEP_TIME_IN_SECONDS = 0.01 # 10 msec sleep
|
||||
ALLOWED_MODES = [:itself, :distinct].freeze
|
||||
|
@ -27,7 +26,6 @@ module Gitlab
|
|||
def unwanted_configuration?(finish, batch_size, start)
|
||||
(@operation == :count && batch_size <= MIN_REQUIRED_BATCH_SIZE) ||
|
||||
(@operation == :sum && batch_size < DEFAULT_SUM_BATCH_SIZE) ||
|
||||
(@operation == :average && batch_size < DEFAULT_AVERAGE_BATCH_SIZE) ||
|
||||
(finish - start) / batch_size >= MAX_ALLOWED_LOOPS ||
|
||||
start >= finish
|
||||
end
|
||||
|
@ -110,7 +108,6 @@ module Gitlab
|
|||
|
||||
def batch_size_for_mode_and_operation(mode, operation)
|
||||
return DEFAULT_SUM_BATCH_SIZE if operation == :sum
|
||||
return DEFAULT_AVERAGE_BATCH_SIZE if operation == :average
|
||||
|
||||
mode == :distinct ? DEFAULT_DISTINCT_BATCH_SIZE : DEFAULT_BATCH_SIZE
|
||||
end
|
||||
|
@ -148,10 +145,6 @@ module Gitlab
|
|||
message: "Query has been canceled with message: #{error.message}"
|
||||
)
|
||||
end
|
||||
|
||||
def not_group_by_query?
|
||||
!@relation.is_a?(ActiveRecord::Relation) || @relation.group_values.blank?
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -22,7 +22,6 @@ module Gitlab
|
|||
analytics
|
||||
code_review
|
||||
compliance
|
||||
deploy_token_packages
|
||||
ecosystem
|
||||
epic_boards_usage
|
||||
epics_usage
|
||||
|
@ -37,6 +36,7 @@ module Gitlab
|
|||
|
||||
CATEGORIES_COLLECTED_FROM_METRICS_DEFINITIONS = %w[
|
||||
ci_users
|
||||
deploy_token_packages
|
||||
error_tracking
|
||||
ide_edit
|
||||
importer
|
||||
|
|
|
@ -218,6 +218,11 @@ msgid_plural "%d contributions"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d contributor"
|
||||
msgid_plural "%d contributors"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d day"
|
||||
msgid_plural "%d days"
|
||||
msgstr[0] ""
|
||||
|
@ -368,6 +373,11 @@ msgid_plural "%d projects selected"
|
|||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d push"
|
||||
msgid_plural "%d pushes"
|
||||
msgstr[0] ""
|
||||
msgstr[1] ""
|
||||
|
||||
msgid "%d remaining"
|
||||
msgid_plural "%d remaining"
|
||||
msgstr[0] ""
|
||||
|
@ -10418,7 +10428,7 @@ msgstr ""
|
|||
msgid "ContributionAnalytics|%{created_count} created, %{merged_count} merged, %{closed_count} closed."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContributionAnalytics|%{pushes} pushes, more than %{commits} commits by %{people} contributors."
|
||||
msgid "ContributionAnalytics|%{pushes}, more than %{commits} by %{contributors}."
|
||||
msgstr ""
|
||||
|
||||
msgid "ContributionAnalytics|Contribution analytics for issues, merge requests and push events since %{start_date}"
|
||||
|
@ -13104,6 +13114,12 @@ msgstr ""
|
|||
msgid "DeploymentApproval|Manual job: %{jobName}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeploymentApproval|Rejected %{time}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeploymentApproval|Rejected by you %{time}"
|
||||
msgstr ""
|
||||
|
||||
msgid "DeploymentTarget|GitLab Pages"
|
||||
msgstr ""
|
||||
|
||||
|
@ -46175,7 +46191,7 @@ msgstr ""
|
|||
msgid "ciReport|Manage licenses"
|
||||
msgstr ""
|
||||
|
||||
msgid "ciReport|Manually Added"
|
||||
msgid "ciReport|Manually added"
|
||||
msgstr ""
|
||||
|
||||
msgid "ciReport|New"
|
||||
|
|
|
@ -116,7 +116,7 @@ RSpec.describe Settings do
|
|||
describe '.cron_for_service_ping' do
|
||||
it 'returns correct crontab for some manually calculated example' do
|
||||
allow(Gitlab::CurrentSettings)
|
||||
.to receive(:uuid) { 'd9e2f4e8-db1f-4e51-b03d-f427e1965c4a'}
|
||||
.to receive(:uuid) { 'd9e2f4e8-db1f-4e51-b03d-f427e1965c4a' }
|
||||
|
||||
expect(described_class.send(:cron_for_service_ping)).to eq('44 10 * * 4')
|
||||
end
|
||||
|
|
|
@ -9,7 +9,7 @@ RSpec.describe Admin::ApplicationSettingsController, :do_not_mock_admin_mode_set
|
|||
let(:group) { create(:group) }
|
||||
let(:project) { create(:project, namespace: group) }
|
||||
let(:admin) { create(:admin) }
|
||||
let(:user) { create(:user)}
|
||||
let(:user) { create(:user) }
|
||||
|
||||
before do
|
||||
stub_env('IN_MEMORY_APPLICATION_SETTINGS', 'false')
|
||||
|
|
|
@ -1006,7 +1006,7 @@ RSpec.describe ApplicationController do
|
|||
end
|
||||
|
||||
describe '.endpoint_id_for_action' do
|
||||
controller(described_class) { }
|
||||
controller(described_class) {}
|
||||
|
||||
it 'returns an expected endpoint id' do
|
||||
expect(controller.class.endpoint_id_for_action('hello')).to eq('AnonymousController#hello')
|
||||
|
|
|
@ -20,7 +20,7 @@ RSpec.describe Groups::LabelsController do
|
|||
it 'returns group and project labels by default' do
|
||||
get :index, params: { group_id: group }, format: :json
|
||||
|
||||
label_ids = json_response.map {|label| label['title']}
|
||||
label_ids = json_response.map { |label| label['title'] }
|
||||
expect(label_ids).to match_array([label_1.title, group_label_1.title])
|
||||
end
|
||||
|
||||
|
@ -36,7 +36,7 @@ RSpec.describe Groups::LabelsController do
|
|||
params = { group_id: subgroup, only_group_labels: true }
|
||||
get :index, params: params, format: :json
|
||||
|
||||
label_ids = json_response.map {|label| label['title']}
|
||||
label_ids = json_response.map { |label| label['title'] }
|
||||
expect(label_ids).to match_array([group_label_1.title, subgroup_label_1.title])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -42,7 +42,7 @@ RSpec.describe Groups::ReleasesController do
|
|||
end
|
||||
|
||||
it 'does not return any releases' do
|
||||
expect(json_response.map {|r| r['tag'] } ).to be_empty
|
||||
expect(json_response.map { |r| r['tag'] } ).to be_empty
|
||||
end
|
||||
|
||||
it 'returns OK' do
|
||||
|
@ -56,7 +56,7 @@ RSpec.describe Groups::ReleasesController do
|
|||
|
||||
index
|
||||
|
||||
expect(json_response.map {|r| r['tag'] } ).to match_array(%w(p2 p1 v2 v1))
|
||||
expect(json_response.map { |r| r['tag'] } ).to match_array(%w(p2 p1 v2 v1))
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ RSpec.describe Import::ManifestController, :clean_gitlab_redis_shared_state do
|
|||
include ImportSpecHelper
|
||||
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:group) { create(:group)}
|
||||
let_it_be(:group) { create(:group) }
|
||||
|
||||
before(:all) do
|
||||
group.add_maintainer(user)
|
||||
|
|
|
@ -41,7 +41,7 @@ RSpec.describe Projects::BlameController do
|
|||
end
|
||||
|
||||
context "invalid branch, valid file" do
|
||||
let(:id) { 'invalid-branch/files/ruby/missing_file.rb'}
|
||||
let(:id) { 'invalid-branch/files/ruby/missing_file.rb' }
|
||||
|
||||
it { is_expected.to respond_with(:not_found) }
|
||||
end
|
||||
|
|
|
@ -27,8 +27,8 @@ RSpec.describe Projects::DeployKeysController do
|
|||
end
|
||||
|
||||
context 'when json requested' do
|
||||
let(:project2) { create(:project, :internal)}
|
||||
let(:project_private) { create(:project, :private)}
|
||||
let(:project2) { create(:project, :internal) }
|
||||
let(:project_private) { create(:project, :private) }
|
||||
|
||||
let(:deploy_key_internal) { create(:deploy_key) }
|
||||
let(:deploy_key_actual) { create(:deploy_key) }
|
||||
|
|
|
@ -208,7 +208,7 @@ RSpec.describe Projects::FeatureFlagsController do
|
|||
end
|
||||
|
||||
context 'when feature flag is not found' do
|
||||
let!(:feature_flag) { }
|
||||
let!(:feature_flag) {}
|
||||
|
||||
let(:params) do
|
||||
{
|
||||
|
|
|
@ -700,7 +700,7 @@ RSpec.describe Projects::JobsController, :clean_gitlab_redis_shared_state do
|
|||
expect(response).to match_response_schema('job/build_trace')
|
||||
expect(json_response['id']).to eq job.id
|
||||
expect(json_response['status']).to eq job.status
|
||||
expect(json_response['lines'].flat_map {|l| l['content'].map { |c| c['text'] } }).to include("ヾ(´༎ຶД༎ຶ`)ノ")
|
||||
expect(json_response['lines'].flat_map { |l| l['content'].map { |c| c['text'] } }).to include("ヾ(´༎ຶД༎ຶ`)ノ")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -25,10 +25,10 @@ RSpec.describe Projects::LabelsController do
|
|||
let_it_be(:group_label_3) { create(:group_label, group: group, title: 'Group Label 3') }
|
||||
let_it_be(:group_label_4) { create(:group_label, group: group, title: 'Group Label 4') }
|
||||
|
||||
let_it_be(:group_labels) { [group_label_3, group_label_4]}
|
||||
let_it_be(:project_labels) { [label_4, label_5]}
|
||||
let_it_be(:group_priority_labels) { [group_label_1, group_label_2]}
|
||||
let_it_be(:project_priority_labels) { [label_1, label_2, label_3]}
|
||||
let_it_be(:group_labels) { [group_label_3, group_label_4] }
|
||||
let_it_be(:project_labels) { [label_4, label_5] }
|
||||
let_it_be(:group_priority_labels) { [group_label_1, group_label_2] }
|
||||
let_it_be(:project_priority_labels) { [label_1, label_2, label_3] }
|
||||
|
||||
before do
|
||||
create(:label_priority, project: project, label: group_label_1, priority: 3)
|
||||
|
|
|
@ -659,7 +659,7 @@ RSpec.describe Projects::NotesController do
|
|||
|
||||
context 'when target_id and noteable_id do not match' do
|
||||
let(:locked_issue) { create(:issue, :locked, project: project) }
|
||||
let(:issue) {create(:issue, project: project)}
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
|
||||
it 'uses target_id and ignores noteable_id' do
|
||||
request_params = {
|
||||
|
|
|
@ -312,7 +312,7 @@ RSpec.describe Projects::ReleasesController do
|
|||
end
|
||||
|
||||
context 'suffix path abuse' do
|
||||
let(:suffix_path) { 'downloads/zips/../../../../../../../robots.txt'}
|
||||
let(:suffix_path) { 'downloads/zips/../../../../../../../robots.txt' }
|
||||
|
||||
it 'raises attack error' do
|
||||
expect do
|
||||
|
|
|
@ -163,8 +163,8 @@ RSpec.describe Projects::TreeController do
|
|||
end
|
||||
|
||||
context 'successful creation' do
|
||||
let(:path) { 'files/new_dir'}
|
||||
let(:branch_name) { 'master-test'}
|
||||
let(:path) { 'files/new_dir' }
|
||||
let(:branch_name) { 'master-test' }
|
||||
|
||||
it 'redirects to the new directory' do
|
||||
expect(subject)
|
||||
|
@ -175,7 +175,7 @@ RSpec.describe Projects::TreeController do
|
|||
|
||||
context 'unsuccessful creation' do
|
||||
let(:path) { 'README.md' }
|
||||
let(:branch_name) { 'master'}
|
||||
let(:branch_name) { 'master' }
|
||||
|
||||
it 'does not allow overwriting of existing files' do
|
||||
expect(subject)
|
||||
|
|
|
@ -36,7 +36,7 @@ RSpec.describe Registrations::WelcomeController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to(dashboard_projects_path)}
|
||||
it { is_expected.to redirect_to(dashboard_projects_path) }
|
||||
end
|
||||
|
||||
context 'when role is set and setup_for_company is not set' do
|
||||
|
@ -78,7 +78,7 @@ RSpec.describe Registrations::WelcomeController do
|
|||
sign_in(user)
|
||||
end
|
||||
|
||||
it { is_expected.to redirect_to(dashboard_projects_path)}
|
||||
it { is_expected.to redirect_to(dashboard_projects_path) }
|
||||
|
||||
context 'when the new user already has any accepted group membership' do
|
||||
let!(:member1) { create(:group_member, user: user) }
|
||||
|
|
|
@ -312,7 +312,7 @@ RSpec.describe Snippets::NotesController do
|
|||
|
||||
describe 'POST toggle_award_emoji' do
|
||||
let(:note) { create(:note_on_personal_snippet, noteable: public_snippet) }
|
||||
let(:emoji_name) { 'thumbsup'}
|
||||
let(:emoji_name) { 'thumbsup' }
|
||||
|
||||
before do
|
||||
sign_in(user)
|
||||
|
|
|
@ -17,7 +17,7 @@ RSpec.describe 'processing of SAMLResponse in dependencies' do
|
|||
allow_next_instance_of(OneLogin::RubySaml::Response) do |instance|
|
||||
allow(instance).to receive(:is_valid?).and_return(true)
|
||||
end
|
||||
saml_strategy.send(:handle_response, mock_saml_response, {}, settings ) { }
|
||||
saml_strategy.send(:handle_response, mock_saml_response, {}, settings ) {}
|
||||
end
|
||||
|
||||
it 'can extract AuthnContextClassRef from SAMLResponse param' do
|
||||
|
|
|
@ -21,7 +21,7 @@ RSpec.describe ApplicationExperiment, :experiment do
|
|||
# them optional there.
|
||||
|
||||
expect(experiment(:example)).to register_behavior(:control).with(nil)
|
||||
expect { experiment(:example) { } }.not_to raise_error
|
||||
expect { experiment(:example) {} }.not_to raise_error
|
||||
end
|
||||
|
||||
describe "#publish" do
|
||||
|
@ -289,11 +289,11 @@ RSpec.describe ApplicationExperiment, :experiment do
|
|||
end
|
||||
|
||||
it "doesn't raise an exception" do
|
||||
expect { experiment(:top) { |e| e.control { experiment(:nested) { } } } }.not_to raise_error
|
||||
expect { experiment(:top) { |e| e.control { experiment(:nested) {} } } }.not_to raise_error
|
||||
end
|
||||
|
||||
it "tracks an event", :snowplow do
|
||||
experiment(:top) { |e| e.control { experiment(:nested) { } } }
|
||||
experiment(:top) { |e| e.control { experiment(:nested) {} } }
|
||||
|
||||
expect(Gitlab::Tracking).to have_received(:event).with( # rubocop:disable RSpec/ExpectGitlabTracking
|
||||
'top',
|
||||
|
@ -311,8 +311,8 @@ RSpec.describe ApplicationExperiment, :experiment do
|
|||
|
||||
cache.clear(key: application_experiment.name)
|
||||
|
||||
application_experiment.control { }
|
||||
application_experiment.candidate { }
|
||||
application_experiment.control {}
|
||||
application_experiment.candidate {}
|
||||
end
|
||||
|
||||
it "caches the variant determined by the variant resolver" do
|
||||
|
@ -378,7 +378,7 @@ RSpec.describe ApplicationExperiment, :experiment do
|
|||
it "doesn't warn on non dev/test environments" do
|
||||
allow(Gitlab).to receive(:dev_or_test_env?).and_return(false)
|
||||
|
||||
expect { experiment(:example) { |e| e.use { } } }.not_to raise_error
|
||||
expect { experiment(:example) { |e| e.use {} } }.not_to raise_error
|
||||
expect(ActiveSupport::Deprecation).not_to have_received(:new).with(anything, 'Gitlab::Experiment')
|
||||
end
|
||||
|
||||
|
@ -387,7 +387,7 @@ RSpec.describe ApplicationExperiment, :experiment do
|
|||
|
||||
# This will eventually raise an ActiveSupport::Deprecation exception,
|
||||
# it's ok to change it when that happens.
|
||||
expect { experiment(:example) { |e| e.use { } } }.not_to raise_error
|
||||
expect { experiment(:example) { |e| e.use {} } }.not_to raise_error
|
||||
|
||||
expect(ActiveSupport::Deprecation).to have_received(:new).with(anything, 'Gitlab::Experiment')
|
||||
end
|
||||
|
|
|
@ -56,7 +56,7 @@ RSpec.describe Ci::JobsFinder, '#execute' do
|
|||
|
||||
context 'scope is an array' do
|
||||
let(:jobs) { [pending_job, running_job, successful_job, canceled_job] }
|
||||
let(:params) {{ scope: %w'running success' }}
|
||||
let(:params) { { scope: %w'running success' } }
|
||||
|
||||
it 'filters by the job statuses in the scope' do
|
||||
expect(subject).to contain_exactly(running_job, successful_job)
|
||||
|
|
|
@ -260,13 +260,13 @@ RSpec.describe Ci::RunnersFinder do
|
|||
let_it_be(:runner_sub_group_2) { create(:ci_runner, :group, contacted_at: 10.minutes.ago) }
|
||||
let_it_be(:runner_sub_group_3) { create(:ci_runner, :group, contacted_at: 9.minutes.ago) }
|
||||
let_it_be(:runner_sub_group_4) { create(:ci_runner, :group, contacted_at: 8.minutes.ago) }
|
||||
let_it_be(:runner_project_1) { create(:ci_runner, :project, contacted_at: 7.minutes.ago, projects: [project])}
|
||||
let_it_be(:runner_project_2) { create(:ci_runner, :project, contacted_at: 6.minutes.ago, projects: [project_2])}
|
||||
let_it_be(:runner_project_3) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, description: 'runner_project_search', projects: [project, project_2])}
|
||||
let_it_be(:runner_project_4) { create(:ci_runner, :project, contacted_at: 4.minutes.ago, projects: [project_3])}
|
||||
let_it_be(:runner_project_5) { create(:ci_runner, :project, contacted_at: 3.minutes.ago, tag_list: %w[runner_tag], projects: [project_4])}
|
||||
let_it_be(:runner_project_6) { create(:ci_runner, :project, contacted_at: 2.minutes.ago, projects: [project_5])}
|
||||
let_it_be(:runner_project_7) { create(:ci_runner, :project, contacted_at: 1.minute.ago, projects: [project_6])}
|
||||
let_it_be(:runner_project_1) { create(:ci_runner, :project, contacted_at: 7.minutes.ago, projects: [project]) }
|
||||
let_it_be(:runner_project_2) { create(:ci_runner, :project, contacted_at: 6.minutes.ago, projects: [project_2]) }
|
||||
let_it_be(:runner_project_3) { create(:ci_runner, :project, contacted_at: 5.minutes.ago, description: 'runner_project_search', projects: [project, project_2]) }
|
||||
let_it_be(:runner_project_4) { create(:ci_runner, :project, contacted_at: 4.minutes.ago, projects: [project_3]) }
|
||||
let_it_be(:runner_project_5) { create(:ci_runner, :project, contacted_at: 3.minutes.ago, tag_list: %w[runner_tag], projects: [project_4]) }
|
||||
let_it_be(:runner_project_6) { create(:ci_runner, :project, contacted_at: 2.minutes.ago, projects: [project_5]) }
|
||||
let_it_be(:runner_project_7) { create(:ci_runner, :project, contacted_at: 1.minute.ago, projects: [project_6]) }
|
||||
|
||||
let(:target_group) { nil }
|
||||
let(:membership) { nil }
|
||||
|
|
|
@ -24,7 +24,7 @@ RSpec.describe ::Packages::FinderHelper do
|
|||
|
||||
subject { finder.execute(project1) }
|
||||
|
||||
it { is_expected.to eq [package1]}
|
||||
it { is_expected.to eq [package1] }
|
||||
end
|
||||
|
||||
describe '#packages_visible_to_user' do
|
||||
|
@ -61,7 +61,7 @@ RSpec.describe ::Packages::FinderHelper do
|
|||
end
|
||||
|
||||
shared_examples 'returning package1' do
|
||||
it { is_expected.to eq [package1]}
|
||||
it { is_expected.to eq [package1] }
|
||||
end
|
||||
|
||||
shared_examples 'returning no packages' do
|
||||
|
@ -165,7 +165,7 @@ RSpec.describe ::Packages::FinderHelper do
|
|||
end
|
||||
|
||||
shared_examples 'returning project1' do
|
||||
it { is_expected.to eq [project1]}
|
||||
it { is_expected.to eq [project1] }
|
||||
end
|
||||
|
||||
shared_examples 'returning no project' do
|
||||
|
|
|
@ -28,9 +28,9 @@ RSpec.describe ContainerRepositoriesFinder do
|
|||
context "with name set to #{name}" do
|
||||
let(:params) { { name: name } }
|
||||
|
||||
it { is_expected.to contain_exactly(project_repository)}
|
||||
it { is_expected.to contain_exactly(project_repository) }
|
||||
|
||||
it { is_expected.not_to include(not_searched_repository)}
|
||||
it { is_expected.not_to include(not_searched_repository) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -50,7 +50,7 @@ RSpec.describe ContainerRepositoriesFinder do
|
|||
context "with sort set to #{order}" do
|
||||
let(:params) { { sort: order } }
|
||||
|
||||
it { is_expected.to eq([sort_repository2, sort_repository])}
|
||||
it { is_expected.to eq([sort_repository2, sort_repository]) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -58,7 +58,7 @@ RSpec.describe ContainerRepositoriesFinder do
|
|||
context "with sort set to #{order}" do
|
||||
let(:params) { { sort: order } }
|
||||
|
||||
it { is_expected.to eq([sort_repository, sort_repository2])}
|
||||
it { is_expected.to eq([sort_repository, sort_repository2]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -71,13 +71,13 @@ RSpec.describe DesignManagement::VersionsFinder do
|
|||
|
||||
describe 'returning versions earlier or equal to a version' do
|
||||
context 'when argument is the first version' do
|
||||
let(:params) { { earlier_or_equal_to: version_1 }}
|
||||
let(:params) { { earlier_or_equal_to: version_1 } }
|
||||
|
||||
it { is_expected.to eq([version_1]) }
|
||||
end
|
||||
|
||||
context 'when argument is the second version' do
|
||||
let(:params) { { earlier_or_equal_to: version_2 }}
|
||||
let(:params) { { earlier_or_equal_to: version_2 } }
|
||||
|
||||
it { is_expected.to contain_exactly(version_1, version_2) }
|
||||
end
|
||||
|
|
|
@ -28,7 +28,7 @@ RSpec.describe MilestonesFinder do
|
|||
end
|
||||
|
||||
context 'milestones for groups and project' do
|
||||
let(:extra_params) {{}}
|
||||
let(:extra_params) { {} }
|
||||
let(:result) do
|
||||
described_class.new({ project_ids: [project_1.id, project_2.id], group_ids: group.id, state: 'all' }.merge(extra_params)).execute
|
||||
end
|
||||
|
|
|
@ -217,7 +217,7 @@ RSpec.describe Packages::GroupPackagesFinder do
|
|||
context 'group is nil' do
|
||||
subject { described_class.new(user, nil).execute }
|
||||
|
||||
it { is_expected.to be_empty}
|
||||
it { is_expected.to be_empty }
|
||||
end
|
||||
|
||||
context 'package type is nil' do
|
||||
|
@ -225,7 +225,7 @@ RSpec.describe Packages::GroupPackagesFinder do
|
|||
|
||||
subject { described_class.new(user, group, package_type: nil).execute }
|
||||
|
||||
it { is_expected.to match_array([package1])}
|
||||
it { is_expected.to match_array([package1]) }
|
||||
end
|
||||
|
||||
context 'with invalid package_type' do
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ::Packages::Npm::PackageFinder do
|
||||
let_it_be_with_reload(:project) { create(:project)}
|
||||
let_it_be_with_reload(:project) { create(:project) }
|
||||
let_it_be_with_refind(:package) { create(:npm_package, project: project) }
|
||||
|
||||
let(:project) { package.project }
|
||||
|
|
|
@ -62,7 +62,7 @@ RSpec.describe ProjectsFinder do
|
|||
|
||||
describe 'with id_after' do
|
||||
context 'only returns projects with a project id greater than given' do
|
||||
let(:params) { { id_after: internal_project.id }}
|
||||
let(:params) { { id_after: internal_project.id } }
|
||||
|
||||
it { is_expected.to eq([public_project]) }
|
||||
end
|
||||
|
@ -70,7 +70,7 @@ RSpec.describe ProjectsFinder do
|
|||
|
||||
describe 'with id_before' do
|
||||
context 'only returns projects with a project id less than given' do
|
||||
let(:params) { { id_before: public_project.id }}
|
||||
let(:params) { { id_before: public_project.id } }
|
||||
|
||||
it { is_expected.to eq([internal_project]) }
|
||||
end
|
||||
|
@ -79,7 +79,7 @@ RSpec.describe ProjectsFinder do
|
|||
describe 'with both id_before and id_after' do
|
||||
context 'only returns projects with a project id less than given' do
|
||||
let!(:projects) { create_list(:project, 5, :public) }
|
||||
let(:params) { { id_after: projects.first.id, id_before: projects.last.id }}
|
||||
let(:params) { { id_after: projects.first.id, id_before: projects.last.id } }
|
||||
|
||||
it { is_expected.to contain_exactly(*projects[1..-2]) }
|
||||
end
|
||||
|
@ -89,7 +89,7 @@ RSpec.describe ProjectsFinder do
|
|||
context 'only returns projects with a project id less than given and matching search' do
|
||||
subject { finder.execute.joins(:route) }
|
||||
|
||||
let(:params) { { id_before: public_project.id }}
|
||||
let(:params) { { id_before: public_project.id } }
|
||||
|
||||
it { is_expected.to eq([internal_project]) }
|
||||
end
|
||||
|
@ -97,7 +97,7 @@ RSpec.describe ProjectsFinder do
|
|||
context 'only returns projects with a project id greater than given and matching search' do
|
||||
subject { finder.execute.joins(:route) }
|
||||
|
||||
let(:params) { { id_after: internal_project.id }}
|
||||
let(:params) { { id_after: internal_project.id } }
|
||||
|
||||
it { is_expected.to eq([public_project]) }
|
||||
end
|
||||
|
|
|
@ -313,7 +313,7 @@ RSpec.describe ApplicationSettingsHelper do
|
|||
allow(helper).to receive(:can?).with(user, :read_cluster, instance_of(Clusters::Instance)).and_return(true)
|
||||
end
|
||||
|
||||
it { is_expected.to be_truthy}
|
||||
it { is_expected.to be_truthy }
|
||||
|
||||
context ':certificate_based_clusters feature flag is disabled' do
|
||||
before do
|
||||
|
|
|
@ -357,7 +357,7 @@ RSpec.describe BlobHelper do
|
|||
|
||||
describe '#ide_merge_request_path' do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project)}
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
|
||||
|
||||
it 'returns IDE path for the given MR if MR is not merged' do
|
||||
expect(helper.ide_merge_request_path(merge_request)).to eq("/-/ide/project/#{project.full_path}/merge_requests/#{merge_request.iid}")
|
||||
|
|
|
@ -27,8 +27,8 @@ RSpec.describe GitlabScriptTagHelper do
|
|||
end
|
||||
|
||||
describe 'inline script tag' do
|
||||
let(:tag_with_nonce) {"<script nonce=\"noncevalue\">\n//<![CDATA[\nalert(1)\n//]]>\n</script>"}
|
||||
let(:tag_with_nonce_and_type) {"<script type=\"application/javascript\" nonce=\"noncevalue\">\n//<![CDATA[\nalert(1)\n//]]>\n</script>"}
|
||||
let(:tag_with_nonce) { "<script nonce=\"noncevalue\">\n//<![CDATA[\nalert(1)\n//]]>\n</script>" }
|
||||
let(:tag_with_nonce_and_type) { "<script type=\"application/javascript\" nonce=\"noncevalue\">\n//<![CDATA[\nalert(1)\n//]]>\n</script>" }
|
||||
|
||||
it 'returns a script tag with a nonce using block syntax' do
|
||||
expect(helper.javascript_tag { 'alert(1)' }.to_s).to eq tag_with_nonce
|
||||
|
|
|
@ -448,7 +448,7 @@ RSpec.describe IssuablesHelper do
|
|||
allow(merge_request).to receive(:can_be_merged_by?).and_return(can_merge)
|
||||
end
|
||||
|
||||
it { is_expected.to include({ can_merge: can_merge })}
|
||||
it { is_expected.to include({ can_merge: can_merge }) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -480,7 +480,7 @@ RSpec.describe IssuablesHelper do
|
|||
allow(merge_request).to receive(:can_be_merged_by?).and_return(can_merge)
|
||||
end
|
||||
|
||||
it { is_expected.to include({ can_merge: can_merge })}
|
||||
it { is_expected.to include({ can_merge: can_merge }) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe Projects::PipelineHelper do
|
|||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:raw_pipeline) { create(:ci_pipeline, project: project, ref: 'master', sha: project.commit.id) }
|
||||
let_it_be(:pipeline) { Ci::PipelinePresenter.new(raw_pipeline, current_user: user)}
|
||||
let_it_be(:pipeline) { Ci::PipelinePresenter.new(raw_pipeline, current_user: user) }
|
||||
|
||||
describe '#js_pipeline_tabs_data' do
|
||||
before do
|
||||
|
|
|
@ -70,7 +70,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
|
|||
end
|
||||
|
||||
context 'with controller for groups with subgroups and project' do
|
||||
let(:masked_url) { "http://localhost/namespace#{subgroup.id}/project#{subproject.id}"}
|
||||
let(:masked_url) { "http://localhost/namespace#{subgroup.id}/project#{subproject.id}" }
|
||||
let(:group) { subgroup }
|
||||
let(:project) { subproject }
|
||||
let(:request) do
|
||||
|
@ -94,7 +94,7 @@ RSpec.describe ::Routing::PseudonymizationHelper do
|
|||
end
|
||||
|
||||
context 'with controller for groups and subgroups' do
|
||||
let(:masked_url) { "http://localhost/groups/namespace#{subgroup.id}/-/shared"}
|
||||
let(:masked_url) { "http://localhost/groups/namespace#{subgroup.id}/-/shared" }
|
||||
let(:group) { subgroup }
|
||||
let(:request) do
|
||||
double(:Request,
|
||||
|
|
|
@ -625,7 +625,7 @@ RSpec.describe SearchHelper do
|
|||
false | false
|
||||
end
|
||||
|
||||
let(:params) {{ confidential: confidential }}
|
||||
let(:params) { { confidential: confidential } }
|
||||
|
||||
with_them do
|
||||
it 'transforms confidentiality param' do
|
||||
|
|
|
@ -6,8 +6,8 @@ RSpec.describe WikiPageVersionHelper do
|
|||
let_it_be(:project) { create(:project, :public, :repository) }
|
||||
let_it_be(:user) { create(:user, username: 'foo') }
|
||||
|
||||
let(:commit_with_user) { create(:commit, project: project, author: user)}
|
||||
let(:commit_without_user) { create(:commit, project: project, author_name: 'Foo', author_email: 'foo@example.com')}
|
||||
let(:commit_with_user) { create(:commit, project: project, author: user) }
|
||||
let(:commit_without_user) { create(:commit, project: project, author_name: 'Foo', author_email: 'foo@example.com') }
|
||||
let(:wiki_page_version) { Gitlab::Git::WikiPageVersion.new(commit, nil) }
|
||||
|
||||
describe '#wiki_page_version_author_url' do
|
||||
|
|
|
@ -8,7 +8,7 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
|
|||
let(:storage) { CarrierWave::Storage::Fog.new(uploader) }
|
||||
let(:bucket_name) { 'some-bucket' }
|
||||
let(:connection) { ::Fog::Storage.new(connection_options) }
|
||||
let(:bucket) { connection.directories.new(key: bucket_name )}
|
||||
let(:bucket) { connection.directories.new(key: bucket_name ) }
|
||||
let(:test_filename) { 'test' }
|
||||
let(:test_data) { File.read(Rails.root.join('spec/support/gitlab_stubs/gitlab_ci.yml')) }
|
||||
|
||||
|
@ -33,7 +33,7 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
|
|||
end
|
||||
|
||||
describe '#copy_to' do
|
||||
let(:dest_filename) { 'copied.txt'}
|
||||
let(:dest_filename) { 'copied.txt' }
|
||||
|
||||
it 'copies the file' do
|
||||
fog_file = subject.send(:file)
|
||||
|
@ -67,7 +67,7 @@ RSpec.describe 'CarrierWave::Storage::Fog::File' do
|
|||
end
|
||||
|
||||
describe '#copy_to' do
|
||||
let(:dest_filename) { 'copied.txt'}
|
||||
let(:dest_filename) { 'copied.txt' }
|
||||
|
||||
it 'copies the file' do
|
||||
result = subject.copy_to(dest_filename)
|
||||
|
|
|
@ -58,7 +58,7 @@ RSpec.describe 'trusted_proxies' do
|
|||
end
|
||||
|
||||
def stub_request(headers = {})
|
||||
ActionDispatch::RemoteIp.new(proc { }, false, Rails.application.config.action_dispatch.trusted_proxies).call(headers)
|
||||
ActionDispatch::RemoteIp.new(proc {}, false, Rails.application.config.action_dispatch.trusted_proxies).call(headers)
|
||||
ActionDispatch::Request.new(headers)
|
||||
end
|
||||
|
||||
|
|
|
@ -23,8 +23,6 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityReadsClusterAge
|
|||
let(:sub_batch_size) { 1_000 }
|
||||
let(:pause_ms) { 0 }
|
||||
|
||||
subject(:perform_migration) { migration.perform }
|
||||
|
||||
before do
|
||||
users_table.create!(id: 1, name: 'John Doe', email: 'test@example.com', projects_limit: 5)
|
||||
|
||||
|
@ -49,6 +47,15 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityReadsClusterAge
|
|||
add_vulnerability_read!(11, project_id: 1, cluster_agent_id: 1, report_type: 7)
|
||||
end
|
||||
|
||||
describe '#filter_batch' do
|
||||
it 'pick only vulnerability reads where report_type = 7' do
|
||||
expect(migration.filter_batch(vulnerability_reads_table).pluck(:id)).to contain_exactly(1, 3, 7, 9, 10, 11)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
subject(:perform_migration) { migration.perform }
|
||||
|
||||
it 'backfills `casted_cluster_agent_id` for the selected records', :aggregate_failures do
|
||||
queries = ActiveRecord::QueryRecorder.new do
|
||||
perform_migration
|
||||
|
@ -64,6 +71,7 @@ RSpec.describe Gitlab::BackgroundMigration::BackfillVulnerabilityReadsClusterAge
|
|||
|
||||
expect { perform_migration }.to change { migration.batch_metrics.timings }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -2,137 +2,6 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillProjectStatisticsWithContainerRegistrySizeBatchingStrategy, '#next_batch' do # rubocop:disable Layout/LineLength
|
||||
let(:batching_strategy) { described_class.new(connection: ActiveRecord::Base.connection) }
|
||||
let(:namespace) { table(:namespaces) }
|
||||
let(:project) { table(:projects) }
|
||||
let(:container_repositories) { table(:container_repositories) }
|
||||
|
||||
let!(:group) do
|
||||
namespace.create!(
|
||||
name: 'namespace1', type: 'Group', path: 'space1'
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj_namespace1) do
|
||||
namespace.create!(
|
||||
name: 'proj1', path: 'proj1', type: 'Project', parent_id: group.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj_namespace2) do
|
||||
namespace.create!(
|
||||
name: 'proj2', path: 'proj2', type: 'Project', parent_id: group.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj_namespace3) do
|
||||
namespace.create!(
|
||||
name: 'proj3', path: 'proj3', type: 'Project', parent_id: group.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj1) do
|
||||
project.create!(
|
||||
name: 'proj1', path: 'proj1', namespace_id: group.id, project_namespace_id: proj_namespace1.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj2) do
|
||||
project.create!(
|
||||
name: 'proj2', path: 'proj2', namespace_id: group.id, project_namespace_id: proj_namespace2.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:proj3) do
|
||||
project.create!(
|
||||
name: 'proj3', path: 'proj3', namespace_id: group.id, project_namespace_id: proj_namespace3.id
|
||||
)
|
||||
end
|
||||
|
||||
let!(:con1) do
|
||||
container_repositories.create!(
|
||||
project_id: proj1.id,
|
||||
name: "ContReg_#{proj1.id}:1",
|
||||
migration_state: 'import_done',
|
||||
created_at: Date.new(2022, 01, 20)
|
||||
)
|
||||
end
|
||||
|
||||
let!(:con2) do
|
||||
container_repositories.create!(
|
||||
project_id: proj1.id,
|
||||
name: "ContReg_#{proj1.id}:2",
|
||||
migration_state: 'import_done',
|
||||
created_at: Date.new(2022, 01, 20)
|
||||
)
|
||||
end
|
||||
|
||||
let!(:con3) do
|
||||
container_repositories.create!(
|
||||
project_id: proj2.id,
|
||||
name: "ContReg_#{proj2.id}:1",
|
||||
migration_state: 'import_done',
|
||||
created_at: Date.new(2022, 01, 20)
|
||||
)
|
||||
end
|
||||
|
||||
let!(:con4) do
|
||||
container_repositories.create!(
|
||||
project_id: proj3.id,
|
||||
name: "ContReg_#{proj3.id}:1",
|
||||
migration_state: 'default',
|
||||
created_at: Date.new(2022, 02, 20)
|
||||
)
|
||||
end
|
||||
|
||||
let!(:con5) do
|
||||
container_repositories.create!(
|
||||
project_id: proj3.id,
|
||||
name: "ContReg_#{proj3.id}:2",
|
||||
migration_state: 'default',
|
||||
created_at: Date.new(2022, 02, 20)
|
||||
)
|
||||
end
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::BackfillProjectStatisticsWithContainerRegistrySizeBatchingStrategy do # rubocop:disable Layout/LineLength
|
||||
it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy }
|
||||
|
||||
context 'when starting on the first batch' do
|
||||
it 'returns the bounds of the next batch' do
|
||||
batch_bounds = batching_strategy.next_batch(
|
||||
:container_repositories,
|
||||
:project_id,
|
||||
batch_min_value: con1.project_id,
|
||||
batch_size: 3,
|
||||
job_arguments: []
|
||||
)
|
||||
expect(batch_bounds).to eq([con1.project_id, con4.project_id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when additional batches remain' do
|
||||
it 'returns the bounds of the next batch' do
|
||||
batch_bounds = batching_strategy.next_batch(
|
||||
:container_repositories,
|
||||
:project_id,
|
||||
batch_min_value: con3.project_id,
|
||||
batch_size: 3,
|
||||
job_arguments: []
|
||||
)
|
||||
|
||||
expect(batch_bounds).to eq([con3.project_id, con5.project_id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no additional batches remain' do
|
||||
it 'returns nil' do
|
||||
batch_bounds = batching_strategy.next_batch(:container_repositories,
|
||||
:project_id,
|
||||
batch_min_value: con5.project_id + 1,
|
||||
batch_size: 1, job_arguments: []
|
||||
)
|
||||
|
||||
expect(batch_bounds).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -3,117 +3,5 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BatchingStrategies::DismissedVulnerabilitiesStrategy, '#next_batch' do
|
||||
let(:batching_strategy) { described_class.new(connection: ActiveRecord::Base.connection) }
|
||||
let(:namespace) { table(:namespaces).create!(name: 'user', path: 'user') }
|
||||
let(:users) { table(:users) }
|
||||
let(:user) { create_user! }
|
||||
let(:project) do
|
||||
table(:projects).create!(
|
||||
namespace_id: namespace.id,
|
||||
project_namespace_id: namespace.id,
|
||||
packages_enabled: false)
|
||||
end
|
||||
|
||||
let(:vulnerabilities) { table(:vulnerabilities) }
|
||||
|
||||
let!(:vulnerability1) do
|
||||
create_vulnerability!(
|
||||
project_id: project.id,
|
||||
author_id: user.id,
|
||||
dismissed_at: Time.current
|
||||
)
|
||||
end
|
||||
|
||||
let!(:vulnerability2) do
|
||||
create_vulnerability!(
|
||||
project_id: project.id,
|
||||
author_id: user.id,
|
||||
dismissed_at: Time.current
|
||||
)
|
||||
end
|
||||
|
||||
let!(:vulnerability3) do
|
||||
create_vulnerability!(
|
||||
project_id: project.id,
|
||||
author_id: user.id,
|
||||
dismissed_at: Time.current
|
||||
)
|
||||
end
|
||||
|
||||
let!(:vulnerability4) do
|
||||
create_vulnerability!(
|
||||
project_id: project.id,
|
||||
author_id: user.id,
|
||||
dismissed_at: nil
|
||||
)
|
||||
end
|
||||
|
||||
it { expect(described_class).to be < Gitlab::BackgroundMigration::BatchingStrategies::PrimaryKeyBatchingStrategy }
|
||||
|
||||
context 'when starting on the first batch' do
|
||||
it 'returns the bounds of the next batch' do
|
||||
batch_bounds = batching_strategy.next_batch(
|
||||
:vulnerabilities,
|
||||
:id,
|
||||
batch_min_value: vulnerability1.id,
|
||||
batch_size: 2,
|
||||
job_arguments: []
|
||||
)
|
||||
expect(batch_bounds).to eq([vulnerability1.id, vulnerability2.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when additional batches remain' do
|
||||
it 'returns the bounds of the next batch and skips the records that do not have `dismissed_at` set' do
|
||||
batch_bounds = batching_strategy.next_batch(
|
||||
:vulnerabilities,
|
||||
:id,
|
||||
batch_min_value: vulnerability3.id,
|
||||
batch_size: 2,
|
||||
job_arguments: []
|
||||
)
|
||||
|
||||
expect(batch_bounds).to eq([vulnerability3.id, vulnerability3.id])
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no additional batches remain' do
|
||||
it 'returns nil' do
|
||||
batch_bounds = batching_strategy.next_batch(
|
||||
:vulnerabilities,
|
||||
:id,
|
||||
batch_min_value: vulnerability4.id + 1,
|
||||
batch_size: 1,
|
||||
job_arguments: []
|
||||
)
|
||||
|
||||
expect(batch_bounds).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def create_vulnerability!(
|
||||
project_id:, author_id:, title: 'test', severity: 7, confidence: 7, report_type: 0, state: 1, dismissed_at: nil
|
||||
)
|
||||
vulnerabilities.create!(
|
||||
project_id: project_id,
|
||||
author_id: author_id,
|
||||
title: title,
|
||||
severity: severity,
|
||||
confidence: confidence,
|
||||
report_type: report_type,
|
||||
state: state,
|
||||
dismissed_at: dismissed_at
|
||||
)
|
||||
end
|
||||
|
||||
def create_user!(name: "Example User", email: "user@example.com", user_type: nil)
|
||||
users.create!(
|
||||
name: name,
|
||||
email: email,
|
||||
username: name,
|
||||
projects_limit: 10
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -34,7 +34,7 @@ RSpec.describe Gitlab::BackgroundMigration::SetCorrectVulnerabilityState do
|
|||
let(:detected_state) { 1 }
|
||||
let(:dismissed_state) { 2 }
|
||||
|
||||
subject(:perform_migration) do
|
||||
let(:migration_job) do
|
||||
described_class.new(start_id: vulnerability_with_dismissed_at.id,
|
||||
end_id: vulnerability_without_dismissed_at.id,
|
||||
batch_table: :vulnerabilities,
|
||||
|
@ -42,9 +42,17 @@ RSpec.describe Gitlab::BackgroundMigration::SetCorrectVulnerabilityState do
|
|||
sub_batch_size: 1,
|
||||
pause_ms: 0,
|
||||
connection: ActiveRecord::Base.connection)
|
||||
.perform
|
||||
end
|
||||
|
||||
describe '#filter_batch' do
|
||||
it 'filters out vulnerabilities where dismissed_at is null' do
|
||||
expect(migration_job.filter_batch(vulnerabilities)).to contain_exactly(vulnerability_with_dismissed_at)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
subject(:perform_migration) { migration_job.perform }
|
||||
|
||||
it 'changes vulnerability state to `dismissed` when dismissed_at is not nil' do
|
||||
expect { perform_migration }.to change { vulnerability_with_dismissed_at.reload.state }.to(dismissed_state)
|
||||
end
|
||||
|
@ -52,6 +60,7 @@ RSpec.describe Gitlab::BackgroundMigration::SetCorrectVulnerabilityState do
|
|||
it 'does not change the state when dismissed_at is nil' do
|
||||
expect { perform_migration }.not_to change { vulnerability_without_dismissed_at.reload.state }
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
|
|
|
@ -0,0 +1,107 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::Database::BatchAverageCounter do
|
||||
let(:model) { Issue }
|
||||
let(:column) { :weight }
|
||||
|
||||
let(:in_transaction) { false }
|
||||
|
||||
before do
|
||||
allow(model.connection).to receive(:transaction_open?).and_return(in_transaction)
|
||||
end
|
||||
|
||||
describe '#count' do
|
||||
before do
|
||||
create_list(:issue, 2, weight: 4)
|
||||
create_list(:issue, 2, weight: 2)
|
||||
create_list(:issue, 2, weight: 3)
|
||||
end
|
||||
|
||||
subject(:batch_average_counter) { described_class.new(model, column) }
|
||||
|
||||
it 'returns correct average of weights' do
|
||||
expect(subject.count).to eq(3.0)
|
||||
end
|
||||
|
||||
it 'does no raise an exception if transaction is not open' do
|
||||
expect { subject.count }.not_to raise_error
|
||||
end
|
||||
|
||||
context 'when transaction is open' do
|
||||
let(:in_transaction) { true }
|
||||
|
||||
it 'raises an error' do
|
||||
expect { subject.count }.to raise_error('BatchAverageCounter can not be run inside a transaction')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when batch size is small' do
|
||||
let(:batch_size) { 2 }
|
||||
|
||||
it 'returns correct average of weights' do
|
||||
expect(subject.count(batch_size: batch_size)).to eq(3.0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when column passed is an Arel attribute' do
|
||||
let(:column) { model.arel_table[:weight] }
|
||||
|
||||
it 'returns correct average of weights' do
|
||||
expect(subject.count).to eq(3.0)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when column has total count of zero' do
|
||||
before do
|
||||
Issue.update_all(weight: nil)
|
||||
end
|
||||
|
||||
it 'returns the fallback value' do
|
||||
expect(subject.count).to eq(-1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when one batch has nil weights (no average)' do
|
||||
before do
|
||||
issues = Issue.where(weight: 4)
|
||||
issues.update_all(weight: nil)
|
||||
end
|
||||
|
||||
let(:batch_size) { 2 }
|
||||
|
||||
it 'calculates average of weights with no errors' do
|
||||
expect(subject.count(batch_size: batch_size)).to eq(2.5)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when batch fetch query is cancelled' do
|
||||
let(:batch_size) { 22_000 }
|
||||
let(:relation) { instance_double(ActiveRecord::Relation, to_sql: batch_average_query) }
|
||||
|
||||
context 'when all retries fail' do
|
||||
let(:batch_average_query) { 'SELECT AVG(weight) FROM issues WHERE weight BETWEEN 2 and 5' }
|
||||
let(:query_timed_out_exception) { ActiveRecord::QueryCanceled.new('query timed out') }
|
||||
|
||||
before do
|
||||
allow(model).to receive(:where).and_return(relation)
|
||||
allow(relation).to receive(:pick).and_raise(query_timed_out_exception)
|
||||
end
|
||||
|
||||
it 'logs failing query' do
|
||||
expect(Gitlab::AppJsonLogger).to receive(:error).with(
|
||||
event: 'batch_count',
|
||||
relation: model.table_name,
|
||||
operation: 'average',
|
||||
start: 2,
|
||||
query: batch_average_query,
|
||||
message: 'Query has been canceled with message: query timed out'
|
||||
)
|
||||
|
||||
expect(subject.count(batch_size: batch_size)).to eq(-1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -493,56 +493,18 @@ RSpec.describe Gitlab::Database::BatchCount do
|
|||
end
|
||||
|
||||
describe '#batch_average' do
|
||||
let(:model) { Issue }
|
||||
let(:column) { :weight }
|
||||
|
||||
before do
|
||||
Issue.update_all(weight: 2)
|
||||
allow_next_instance_of(Gitlab::Database::BatchAverageCounter) do |instance|
|
||||
allow(instance).to receive(:count).and_return
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns the average of values in the given column' do
|
||||
expect(described_class.batch_average(model, column)).to eq(2)
|
||||
end
|
||||
|
||||
it 'works when given an Arel column' do
|
||||
expect(described_class.batch_average(model, model.arel_table[column])).to eq(2)
|
||||
end
|
||||
|
||||
it 'works with a batch size of 50K' do
|
||||
expect(described_class.batch_average(model, column, batch_size: 50_000)).to eq(2)
|
||||
end
|
||||
|
||||
it 'works with start and finish provided' do
|
||||
expect(described_class.batch_average(model, column, start: model.minimum(:id), finish: model.maximum(:id))).to eq(2)
|
||||
end
|
||||
|
||||
it "defaults the batch size to #{Gitlab::Database::BatchCounter::DEFAULT_AVERAGE_BATCH_SIZE}" do
|
||||
min_id = model.minimum(:id)
|
||||
relation = instance_double(ActiveRecord::Relation)
|
||||
allow(model).to receive_message_chain(:select, public_send: relation)
|
||||
batch_end_id = min_id + calculate_batch_size(Gitlab::Database::BatchCounter::DEFAULT_AVERAGE_BATCH_SIZE)
|
||||
|
||||
expect(relation).to receive(:where).with("id" => min_id..batch_end_id).and_return(double(send: 1))
|
||||
it 'calls BatchAverageCounter' do
|
||||
expect(Gitlab::Database::BatchAverageCounter).to receive(:new).with(model, column).and_call_original
|
||||
|
||||
described_class.batch_average(model, column)
|
||||
end
|
||||
|
||||
it_behaves_like 'when a transaction is open' do
|
||||
subject { described_class.batch_average(model, column) }
|
||||
end
|
||||
|
||||
it_behaves_like 'disallowed configurations', :batch_average do
|
||||
let(:args) { [model, column] }
|
||||
let(:default_batch_size) { Gitlab::Database::BatchCounter::DEFAULT_AVERAGE_BATCH_SIZE }
|
||||
let(:small_batch_size) { Gitlab::Database::BatchCounter::DEFAULT_AVERAGE_BATCH_SIZE - 1 }
|
||||
end
|
||||
|
||||
it_behaves_like 'when batch fetch query is canceled' do
|
||||
let(:mode) { :itself }
|
||||
let(:operation) { :average }
|
||||
let(:operation_args) { [column] }
|
||||
|
||||
subject { described_class.method(:batch_average) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -16,6 +16,10 @@ RSpec.describe Gitlab::UsageDataMetrics do
|
|||
allow_next_instance_of(Gitlab::Database::BatchCounter) do |batch_counter|
|
||||
allow(batch_counter).to receive(:transaction_open?).and_return(false)
|
||||
end
|
||||
|
||||
allow_next_instance_of(Gitlab::Database::BatchAverageCounter) do |instance|
|
||||
allow(instance).to receive(:transaction_open?).and_return(false)
|
||||
end
|
||||
end
|
||||
|
||||
context 'with instrumentation_class' do
|
||||
|
|
|
@ -76,7 +76,7 @@ RSpec.describe Emails::ServiceDesk do
|
|||
|
||||
shared_examples 'read template from repository' do |template_key|
|
||||
let(:template_content) { 'custom text' }
|
||||
let(:issue) { create(:issue, project: project)}
|
||||
let(:issue) { create(:issue, project: project) }
|
||||
|
||||
before do
|
||||
issue.issue_email_participants.create!(email: email)
|
||||
|
|
|
@ -48,7 +48,7 @@ RSpec.describe RemoveDuplicateProjectAuthorizations, :migration do
|
|||
project_authorizations.create! project_id: project_1.id, user_id: user_1.id, access_level: Gitlab::Access::REPORTER
|
||||
end
|
||||
|
||||
it { expect { subject }.to change { ProjectAuthorization.count}.from(3).to(1) }
|
||||
it { expect { subject }.to change { ProjectAuthorization.count }.from(3).to(1) }
|
||||
|
||||
it 'retains the highest access level' do
|
||||
subject
|
||||
|
|
|
@ -39,7 +39,7 @@ RSpec.describe UpdateReportTypeForExistingApprovalProjectRules, :migration do
|
|||
end
|
||||
|
||||
context 'with the rule name set to another value (e.g., Test Rule)' do
|
||||
let(:rule_name) { 'Test Rule'}
|
||||
let(:rule_name) { 'Test Rule' }
|
||||
|
||||
it 'does not update report_type' do
|
||||
expect { migrate! }.not_to change { approval_project_rule.reload.report_type }
|
||||
|
|
|
@ -52,7 +52,7 @@ RSpec.describe ConfirmSupportBotUser, :migration do
|
|||
end
|
||||
|
||||
it 'does not change the `created_at` attribute' do
|
||||
expect { migrate!}.not_to change { support_bot.reload.created_at }.from(nil)
|
||||
expect { migrate! }.not_to change { support_bot.reload.created_at }.from(nil)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ RSpec.describe ResetJobTokenScopeEnabledAgain do
|
|||
let(:projects) { table(:projects) }
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
|
||||
let(:project_1) { projects.create!(name: 'proj-1', path: 'gitlab-org', namespace_id: namespace.id)}
|
||||
let(:project_2) { projects.create!(name: 'proj-2', path: 'gitlab-org', namespace_id: namespace.id)}
|
||||
let(:project_1) { projects.create!(name: 'proj-1', path: 'gitlab-org', namespace_id: namespace.id) }
|
||||
let(:project_2) { projects.create!(name: 'proj-2', path: 'gitlab-org', namespace_id: namespace.id) }
|
||||
|
||||
before do
|
||||
settings.create!(id: 1, project_id: project_1.id, job_token_scope_enabled: true)
|
||||
|
|
|
@ -9,8 +9,8 @@ RSpec.describe ResetJobTokenScopeEnabled do
|
|||
let(:projects) { table(:projects) }
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:namespace) { namespaces.create!(name: 'gitlab', path: 'gitlab-org') }
|
||||
let(:project_1) { projects.create!(name: 'proj-1', path: 'gitlab-org', namespace_id: namespace.id)}
|
||||
let(:project_2) { projects.create!(name: 'proj-2', path: 'gitlab-org', namespace_id: namespace.id)}
|
||||
let(:project_1) { projects.create!(name: 'proj-1', path: 'gitlab-org', namespace_id: namespace.id) }
|
||||
let(:project_2) { projects.create!(name: 'proj-2', path: 'gitlab-org', namespace_id: namespace.id) }
|
||||
|
||||
before do
|
||||
settings.create!(id: 1, project_id: project_1.id, job_token_scope_enabled: true)
|
||||
|
|
|
@ -6,10 +6,10 @@ require_migration!
|
|||
|
||||
RSpec.describe ResetSeverityLevelsToNewDefault do
|
||||
let(:approval_project_rules) { table(:approval_project_rules) }
|
||||
let(:projects) { table(:projects)}
|
||||
let(:namespaces) { table(:namespaces)}
|
||||
let(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace')}
|
||||
let(:project) { projects.create!(name: 'project', path: 'project', namespace_id: namespace.id)}
|
||||
let(:projects) { table(:projects) }
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:namespace) { namespaces.create!(name: 'namespace', path: 'namespace') }
|
||||
let(:project) { projects.create!(name: 'project', path: 'project', namespace_id: namespace.id) }
|
||||
let(:approval_project_rule) { approval_project_rules.create!(name: 'rule', project_id: project.id, severity_levels: severity_levels) }
|
||||
|
||||
context 'without having all severity levels selected' do
|
||||
|
@ -27,7 +27,7 @@ RSpec.describe ResetSeverityLevelsToNewDefault do
|
|||
|
||||
it 'changes severity_levels to the default value' do
|
||||
expect(approval_project_rule.severity_levels).to eq(severity_levels)
|
||||
expect { migrate! }.to change {approval_project_rule.reload.severity_levels}.from(severity_levels).to(default_levels)
|
||||
expect { migrate! }.to change { approval_project_rule.reload.severity_levels }.from(severity_levels).to(default_levels)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -4482,12 +4482,22 @@ RSpec.describe Ci::Pipeline, :mailer, factory_default: :keep do
|
|||
let_it_be(:pipeline) { create(:ci_pipeline) }
|
||||
|
||||
context 'when the scheduling type is `dag`' do
|
||||
context 'when the processable is a bridge' do
|
||||
it 'returns true' do
|
||||
create(:ci_bridge, pipeline: pipeline, scheduling_type: :dag)
|
||||
|
||||
expect(pipeline.uses_needs?).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the processable is a build' do
|
||||
it 'returns true' do
|
||||
create(:ci_build, pipeline: pipeline, scheduling_type: :dag)
|
||||
|
||||
expect(pipeline.uses_needs?).to eq(true)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the scheduling type is nil or stage' do
|
||||
it 'returns false' do
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Clusters::AgentPolicy do
|
||||
let(:cluster_agent) { create(:cluster_agent, name: 'agent' )}
|
||||
let(:cluster_agent) { create(:cluster_agent, name: 'agent' ) }
|
||||
let(:user) { create(:admin) }
|
||||
let(:policy) { described_class.new(user, cluster_agent) }
|
||||
let(:project) { cluster_agent.project }
|
||||
|
|
|
@ -128,7 +128,7 @@ RSpec.describe GroupMemberPolicy do
|
|||
|
||||
context 'with the group parent' do
|
||||
let(:current_user) { create :user }
|
||||
let(:subgroup) { create(:group, :private, parent: group)}
|
||||
let(:subgroup) { create(:group, :private, parent: group) }
|
||||
|
||||
before do
|
||||
group.add_owner(owner)
|
||||
|
@ -143,7 +143,7 @@ RSpec.describe GroupMemberPolicy do
|
|||
|
||||
context 'without group parent' do
|
||||
let(:current_user) { create :user }
|
||||
let(:subgroup) { create(:group, :private)}
|
||||
let(:subgroup) { create(:group, :private) }
|
||||
|
||||
before do
|
||||
subgroup.add_owner(current_user)
|
||||
|
@ -158,7 +158,7 @@ RSpec.describe GroupMemberPolicy do
|
|||
context 'without group parent with two owners' do
|
||||
let(:current_user) { create :user }
|
||||
let(:other_user) { create :user }
|
||||
let(:subgroup) { create(:group, :private)}
|
||||
let(:subgroup) { create(:group, :private) }
|
||||
|
||||
before do
|
||||
subgroup.add_owner(current_user)
|
||||
|
|
|
@ -398,7 +398,7 @@ RSpec.describe IssuePolicy do
|
|||
context 'with a hidden issue' do
|
||||
let(:user) { create(:user) }
|
||||
let(:banned_user) { create(:user, :banned) }
|
||||
let(:admin) { create(:user, :admin)}
|
||||
let(:admin) { create(:user, :admin) }
|
||||
let(:hidden_issue) { create(:issue, project: project, author: banned_user) }
|
||||
|
||||
it 'does not allow non-admin user to read the issue' do
|
||||
|
|
|
@ -777,13 +777,13 @@ RSpec.describe ProjectPolicy do
|
|||
project.add_developer(user)
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_allowed(:project_bot_access)}
|
||||
it { is_expected.not_to be_allowed(:project_bot_access) }
|
||||
end
|
||||
|
||||
context "when project bot and not part of the project" do
|
||||
let(:current_user) { project_bot }
|
||||
|
||||
it { is_expected.not_to be_allowed(:project_bot_access)}
|
||||
it { is_expected.not_to be_allowed(:project_bot_access) }
|
||||
end
|
||||
|
||||
context "when project bot and part of the project" do
|
||||
|
@ -793,7 +793,7 @@ RSpec.describe ProjectPolicy do
|
|||
project.add_developer(project_bot)
|
||||
end
|
||||
|
||||
it { is_expected.to be_allowed(:project_bot_access)}
|
||||
it { is_expected.to be_allowed(:project_bot_access) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -804,7 +804,7 @@ RSpec.describe ProjectPolicy do
|
|||
project.add_maintainer(project_bot)
|
||||
end
|
||||
|
||||
it { is_expected.not_to be_allowed(:create_resource_access_tokens)}
|
||||
it { is_expected.not_to be_allowed(:create_resource_access_tokens) }
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -946,7 +946,7 @@ RSpec.describe ProjectPolicy do
|
|||
context 'with anonymous' do
|
||||
let(:current_user) { anonymous }
|
||||
|
||||
it { is_expected.to be_disallowed(:metrics_dashboard)}
|
||||
it { is_expected.to be_disallowed(:metrics_dashboard) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Terraform::StatePolicy do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:terraform_state) { create(:terraform_state, project: project)}
|
||||
let_it_be(:terraform_state) { create(:terraform_state, project: project) }
|
||||
|
||||
subject { described_class.new(user, terraform_state) }
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Terraform::StateVersionPolicy do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project)}
|
||||
let_it_be(:terraform_state) { create(:terraform_state, :with_version, project: project) }
|
||||
|
||||
subject { described_class.new(user, terraform_state.latest_version) }
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ RSpec.describe ::Packages::Composer::PackagesPresenter do
|
|||
end
|
||||
|
||||
describe '#provider' do
|
||||
subject { presenter.provider}
|
||||
subject { presenter.provider }
|
||||
|
||||
let(:expected_json) do
|
||||
{
|
||||
|
|
|
@ -7,7 +7,7 @@ RSpec.describe ::Packages::Conan::PackagePresenter do
|
|||
let_it_be(:package) { create(:conan_package) }
|
||||
let_it_be(:project) { package.project }
|
||||
let_it_be(:package_file_pending_destruction) { create(:package_file, :pending_destruction, package: package) }
|
||||
let_it_be(:conan_package_reference) { '123456789'}
|
||||
let_it_be(:conan_package_reference) { '123456789' }
|
||||
|
||||
let(:params) { { package_scope: :instance } }
|
||||
let(:presenter) { described_class.new(package, user, project, params) }
|
||||
|
|
|
@ -12,7 +12,7 @@ RSpec.describe Packages::Nuget::PackagesMetadataPresenter do
|
|||
describe '#count' do
|
||||
subject { presenter.count }
|
||||
|
||||
it {is_expected.to eq 1}
|
||||
it { is_expected.to eq 1 }
|
||||
end
|
||||
|
||||
describe '#items' do
|
||||
|
|
|
@ -613,7 +613,7 @@ RSpec.describe ProjectPresenter do
|
|||
end
|
||||
|
||||
context 'empty repo' do
|
||||
let(:project) { create(:project, :stubbed_repository)}
|
||||
let(:project) { create(:project, :stubbed_repository) }
|
||||
|
||||
context 'for a guest user' do
|
||||
it 'orders the items correctly' do
|
||||
|
|
|
@ -192,7 +192,7 @@ RSpec.describe RuboCop::Cop::Migration::CreateTableWithForeignKeys do
|
|||
|
||||
include_context 'when there is a target to a high traffic table', :foreign_key do
|
||||
let(:explicit_target_opts) { ", to_table: :#{table_name}" }
|
||||
let(:implicit_target_opts) { }
|
||||
let(:implicit_target_opts) {}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue