Skip to content
代码片段 群组 项目
代码所有者
将用户和群组指定为特定文件更改的核准人。 了解更多。
rules.gitlab-ci.yml 108.77 KiB
##############
# Conditions #
##############
.if-not-canonical-namespace: &if-not-canonical-namespace
  if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org|-cn)?($|\/)/'

.if-not-ee: &if-not-ee
  # Only consider FOSS not EE
  if: '$CI_PROJECT_NAME !~ /^gitlab(-ee)?$/ && $CI_PROJECT_NAME !~ /^gitlab-jh/'

.if-not-foss: &if-not-foss
  if: '$CI_PROJECT_NAME != "gitlab-foss" && $CI_PROJECT_NAME != "gitlab-ce" && $CI_PROJECT_NAME != "gitlabhq"'

.if-jh: &if-jh
  # Matches these two projects:
  # https://jihulab.com/gitlab-cn/gitlab
  # https://gitlab.com/gitlab-org-sandbox/gitlab-jh-validation
  if: '$CI_PROJECT_PATH == "gitlab-cn/gitlab" || $CI_PROJECT_PATH == "gitlab-org-sandbox/gitlab-jh-validation"'

.if-force-ci: &if-force-ci
  if: '$FORCE_GITLAB_CI'

.if-default-refs: &if-default-refs
  if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\// || $CI_COMMIT_REF_NAME =~ /^ruby\d+(_\d)*$/ || ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") || $CI_COMMIT_TAG || $FORCE_GITLAB_CI'

.if-default-branch-refs: &if-default-branch-refs
  if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null'

.if-auto-deploy-branches: &if-auto-deploy-branches
  if: '$CI_COMMIT_BRANCH =~ /^\d+-\d+-auto-deploy-\d+$/'

.if-default-branch-or-tag: &if-default-branch-or-tag
  if: '($CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH && $CI_MERGE_REQUEST_IID == null) || $CI_COMMIT_TAG'

.if-tag: &if-tag
  if: '$CI_COMMIT_TAG'

.if-merge-request: &if-merge-request
  if: '$CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached"'

.if-not-merge-request: &if-not-merge-request
  if: '$CI_MERGE_REQUEST_EVENT_TYPE == null'

# Once https://gitlab.com/gitlab-org/gitlab/-/issues/373904 is implemented, we should be able to change this back to
# if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_APPROVALS_COUNT > 0'
# or any similar condition to check that the MR has *any* approval (not just required approval).
.if-merge-request-approved: &if-merge-request-approved
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /pipeline:mr-approved/'

.if-merge-request-approved-and-specific-devops-stage: &if-merge-request-approved-and-specific-devops-stage
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && ($CI_MERGE_REQUEST_LABELS =~ /pipeline:mr-approved/ && $CI_MERGE_REQUEST_LABELS =~ /devops::(create|govern|manage|plan|verify|package|monitor|data stores|fulfillment|systems)/)'

.if-merge-request-and-specific-devops-stage: &if-merge-request-and-specific-devops-stage
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /devops::(create|govern|manage|plan|verify|package|monitor|data stores|fulfillment|systems)/'

.if-merge-request-and-devops-fulfillment: &if-merge-request-and-devops-fulfillment
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS =~ /devops::fulfillment/'

.if-merge-request-not-approved: &if-merge-request-not-approved
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS !~ /pipeline:mr-approved/'

.if-automated-merge-request: &if-automated-merge-request
  if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME == "release-tools/update-gitaly" || $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /stable-(ee|jh)$/'

.if-merge-request-targeting-stable-branch: &if-merge-request-targeting-stable-branch
  if: '($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^[\d-]+-stable(-ee|-jh)?$/'

.if-merge-request-labels-run-in-ruby: &if-merge-request-labels-run-in-ruby
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby\d+(_\d)*/'
.if-merge-request-labels-as-if-foss: &if-merge-request-labels-as-if-foss
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-as-if-foss/'

.if-merge-request-labels-as-if-jh: &if-merge-request-labels-as-if-jh
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-as-if-jh/'

.if-merge-request-labels-update-caches: &if-merge-request-labels-update-caches
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:update-cache/'

.if-merge-request-labels-run-all-rspec: &if-merge-request-labels-run-all-rspec
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-rspec/'

.if-merge-request-labels-run-all-jest: &if-merge-request-labels-run-all-jest
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-jest/'

.if-merge-request-labels-run-all-e2e: &if-merge-request-labels-run-all-e2e
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-all-e2e/'

.if-merge-request-labels-run-single-db: &if-merge-request-labels-run-single-db
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-single-db/'

.if-merge-request-labels-run-clusterwide-db: &if-merge-request-labels-run-clusterwide-db
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-clusterwide-db/'

.if-merge-request-labels-run-review-app: &if-merge-request-labels-run-review-app
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-review-app/'

.if-merge-request-labels-run-cs-evaluation: &if-merge-request-labels-run-cs-evaluation
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-CS-evaluation/'

.if-merge-request-labels-skip-undercoverage: &if-merge-request-labels-skip-undercoverage
  if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:skip-undercoverage/'

.if-merge-request-labels-jh-contribution: &if-merge-request-labels-jh-contribution
  if: '$CI_MERGE_REQUEST_LABELS =~ /JiHu contribution/'

.if-merge-request-labels-group-global-search: &if-merge-request-labels-group-global-search
  if: '$CI_MERGE_REQUEST_LABELS =~ /group::global search/'

.if-merge-request-labels-pipeline-expedite: &if-merge-request-labels-pipeline-expedite
  if: '($CI_MERGE_REQUEST_LABELS =~ /master:(foss-)?broken/ || $CI_MERGE_REQUEST_LABELS =~ /quarantine/) && $CI_MERGE_REQUEST_LABELS =~ /pipeline:expedite/'

.if-merge-request-labels-frontend-and-feature-flag: &if-merge-request-labels-frontend-and-feature-flag
  if: '$CI_MERGE_REQUEST_LABELS =~ /frontend/ && $CI_MERGE_REQUEST_LABELS =~ /feature flag/'

.if-security-merge-request: &if-security-merge-request
  if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")'

.if-fork-merge-request: &if-fork-merge-request
  if: '$CI_PROJECT_NAMESPACE !~ /^gitlab(-org)?($|\/)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_LABELS !~ /pipeline:run-all-rspec/'

.if-schedule-pipeline: &if-schedule-pipeline
  if: '$CI_PIPELINE_SOURCE == "schedule"'

.if-schedule-maintenance: &if-schedule-maintenance
  if: '$CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "maintenance"'

.if-default-branch-schedule-nightly: &if-default-branch-schedule-nightly
  if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "nightly"'

.if-ruby-branch-schedule-nightly: &if-ruby-branch-schedule-nightly
  if: '$CI_COMMIT_BRANCH =~ /^ruby\d+(_\d)*$/ && $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "nightly"'

.if-security-schedule: &if-security-schedule
  if: '$CI_PROJECT_NAMESPACE == "gitlab-org/security" && $CI_PIPELINE_SOURCE == "schedule"'

.if-foss-schedule: &if-foss-schedule
  if: '$CI_PROJECT_PATH == "gitlab-org/gitlab-foss" && $CI_PIPELINE_SOURCE == "schedule"'

.if-foss-default-branch: &if-foss-default-branch
  if: '$CI_PROJECT_PATH == "gitlab-org/gitlab-foss" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'

.if-dot-com-gitlab-org-schedule: &if-dot-com-gitlab-org-schedule
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_PIPELINE_SOURCE == "schedule"'

.if-dot-com-ee-schedule-default-branch-maintenance: &if-dot-com-ee-schedule-default-branch-maintenance
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE == "schedule" && $SCHEDULE_TYPE == "maintenance"'

.if-dot-com-gitlab-org-default-branch: &if-dot-com-gitlab-org-default-branch
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && $CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH'

.if-dot-com-gitlab-org-merge-request: &if-dot-com-gitlab-org-merge-request
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE == "gitlab-org" && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")'

.if-dot-com-gitlab-org-and-security-merge-request: &if-dot-com-gitlab-org-and-security-merge-request
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached")'

.if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified: &if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $QA_TESTS'

.if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e: &if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $QA_MANUAL_FF_PACKAGE_AND_QA'

.if-dot-com-gitlab-org-and-security-tag: &if-dot-com-gitlab-org-and-security-tag
  if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_NAMESPACE =~ /^gitlab-org($|\/security$)/ && $CI_COMMIT_TAG'

.if-ruby-branch: &if-ruby-branch
  if: '$CI_COMMIT_BRANCH =~ /^ruby\d+(_\d)*$/ || $CI_MERGE_REQUEST_LABELS =~ /pipeline:run-in-ruby\d+(_\d)*/'

####################
# Changes patterns #
####################
.ci-patterns: &ci-patterns
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  - "scripts/rspec_helpers.sh"

.ci-build-images-patterns: &ci-build-images-patterns
  - ".gitlab-ci.yml"
  - ".gitlab/ci/build-images.gitlab-ci.yml"

.ci-review-patterns: &ci-review-patterns
  - ".gitlab-ci.yml"
  - ".gitlab/ci/frontend.gitlab-ci.yml"
  - ".gitlab/ci/build-images.gitlab-ci.yml"
  - ".gitlab/ci/review.gitlab-ci.yml"
  - ".gitlab/ci/cng/**/*"
  - ".gitlab/ci/review-apps/**/*"
  - "scripts/review_apps/**/*"
  - "scripts/trigger-build.rb"
  - "{,ee/,jh/}{bin,config}/**/*.rb"

.ci-templates-patterns: &ci-templates-patterns
  - "lib/gitlab/ci/templates/**/*.gitlab-ci.yml"

.ci-qa-patterns: &ci-qa-patterns
  - ".gitlab-ci.yml"
  - ".gitlab/ci/frontend.gitlab-ci.yml"
  - ".gitlab/ci/build-images.gitlab-ci.yml"
  - ".gitlab/ci/qa.gitlab-ci.yml"
  - ".gitlab/ci/package-and-test/*.yml"
  - ".gitlab/ci/review-apps/qa.gitlab-ci.yml"
  - ".gitlab/ci/review-apps/rules.gitlab-ci.yml"
  - ".gitlab/ci/test-on-gdk/*.yml"

.gitaly-patterns: &gitaly-patterns
  - "GITALY_SERVER_VERSION"
  - "lib/gitlab/setup_helper.rb"

.workhorse-patterns: &workhorse-patterns
  - ".gitlab/ci/workhorse.gitlab-ci.yml"
  - "GITLAB_WORKHORSE_VERSION"
  - "workhorse/**/*"
  - "scripts/gitaly-test-build"
  - "scripts/gitaly-test-spawn"
  - "spec/support/gitlab-git-test.git/**/*"
  - "spec/support/helpers/gitaly_setup.rb"

.yaml-lint-patterns: &yaml-lint-patterns
  - "**/*.{yml,yaml}{,.*}"

.lint-pipeline-yaml-patterns: &lint-pipeline-yaml-patterns
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*.yml"
  - "lib/gitlab/ci/templates/**/*.yml"
  - "data/deprecations/**/*.yml"
  - "data/whats_new/**/*.yml"

.lint-metrics-yaml-patterns: &lint-metrics-yaml-patterns
  - "config/metrics/**/*.yml"

.docs-patterns: &docs-patterns
  - ".gitlab/route-map.yml"
  - "doc/**/*"
  - ".markdownlint.yml"
  - "scripts/lint-doc.sh"
  - ".gitlab/ci/docs.gitlab-ci.yml"

.docs-blueprints-patterns: &docs-blueprints-patterns
  - "doc/architecture/blueprints/**/*"
  - "scripts/lint-docs-blueprints.rb"
  - ".gitlab/ci/docs.gitlab-ci.yml"

.docs-deprecations-and-removals-patterns: &docs-deprecations-and-removals-patterns
  - "doc/update/deprecations.md"
  - "data/deprecations/**/*"
  - "tooling/docs/**/*"
  - "lib/tasks/gitlab/docs/compile_deprecations.rake"

.bundler-patterns: &bundler-patterns
  - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'

.nodejs-patterns: &nodejs-patterns
  - '{package.json,*/package.json,*/*/package.json}'
  - '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'

.python-patterns: &python-patterns
  - '{Pipfile,*/Pipfile,*/*/Pipfile}'

.dependency-patterns: &dependency-patterns
  - '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
  - '{go.sum,*/go.sum,*/*/go.sum}'
  - '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'

.frontend-dependency-patterns: &frontend-dependency-patterns
  - "{package.json,yarn.lock}"
  - "config/webpack.config.js"
  - "config/helpers/*.js"

.frontend-build-patterns: &frontend-build-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "config/webpack.config.js"
  - "config/**/*.js"
  - "{,ee/,jh/}app/assets/**/*"
  - "vendor/assets/**/*"

# This list should match the list in Tasks::Gitlab::Assets.assets_impacting_compilation
.assets-compilation-patterns: &assets-compilation-patterns
  - "{package.json,yarn.lock}"
  - "{Gemfile,Gemfile.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "config/webpack.config.js"
  - "*.js"
  - "config/**/*.js"
  - "locale/**/gitlab.po"
  - "{,ee/,jh/}app/assets/**/*"
  - "fixtures/emojis/**/*"
  - "vendor/assets/**/*"

.frontend-patterns-for-as-if-foss: &frontend-patterns-for-as-if-foss
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "config/**/*.js"
  - "vendor/assets/**/*"
  - "{app/assets,app/components,app/helpers,app/presenters,app/views,locale,public,spec/frontend,storybook,symbol}/**/*"

.initializers-patterns: &initializers-patterns
  - "{,ee/,jh/}config/initializers/**/*"

.controllers-patterns: &controllers-patterns
  - "{,ee/,jh/}{app/controllers}/**/*"

.models-patterns: &models-patterns
  - "{,ee/,jh/}{app/models}/**/*"

.decomposed-db-models-patterns: &decomposed-db-models-patterns
  - "{,ee/,jh/}app/models/{ci,geo}/**/*"

.lib-gitlab-patterns: &lib-gitlab-patterns
  - "{,ee/,jh/}lib/{,ee/,jh/}gitlab/**/*"

# Patterns to match pure Ruby code
.ruby-patterns: &ruby-patterns
  - "**/Rakefile"
  - "**/Dangerfile"
  - "**/Gemfile"
  - "**/Guardfile"
  - "**/*.rake"
  - "**/*.rb"
  - "**/*.ru"

# Backend patterns + .ci-patterns
.backend-patterns: &backend-patterns
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "config.ru"
  # List explicitly all the app/ dirs that are backend (i.e. all except app/assets).
  - "{,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,elastic,gems,generator_templates,lib}/**/*"
  - "{,ee/,jh/}spec/**/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  - "*_VERSION"
  - "scripts/rspec_helpers.sh"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"

.search-backend-patterns: &search-backend-patterns
  - "{,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/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,elastic,gems,generator_templates,lib}/**/*"
  - "{,ee/,jh/}spec/**/*"

# Redis patterns + feature flags
.redis-patterns: &redis-patterns
  - "{,ee/,jh/}{,spec/}app/models/concerns/redis_cacheable{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}app/models/ci/build_trace_chunks/redis{,_base,_trace_chunks}{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/usage_data_counters/{hll_redis_counter,redis_counter}{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/usage/metrics/instrumentations/redis{_metric,hll_metric}{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/usage/metrics/aggregates/sources/redis_hll{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/merge_requests/mergeability/redis_interface{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/markdown_cache/redis/*.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/redis/**/*.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/instrumentation/*.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/redis.rb"
  - "{,ee/,jh/}config/initializers/7_redis.rb"
  # Feature flag changes
  - "{,ee/,jh/}{,spec/}lib/feature.rb"
  - "config/feature_flags/**/*"

# AI patterns:
.ai-patterns: &ai-patterns
  - "{ee/,jh/}lib/gitlab/llm/**/*"
  - "{ee/,jh/}{,spec/}lib/gitlab/llm/**/*"
  - "{ee/,jh/}lib/gitlab/duo/**/*"

# DB patterns + .ci-patterns
.db-patterns: &db-patterns
  - "{,ee/,jh/}{,spec/}{db,migrations}/**/*"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/background_migration{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/background_migration/**/*"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database{,_spec}.rb"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database/**/*"
  - "{,ee/,jh/}spec/support/db_cleaner.rb"
  - "{,ee/,jh/}spec/support/helpers/database/**/*"
  - "{,ee/,jh/}spec/support/helpers/migrations_helpers/**/*"
  - "lib/api/admin/batched_background_migrations.rb"
  - "lib/gitlab/markdown_cache/active_record/**/*"
  - "spec/requests/api/admin/batched_background_migrations_spec.rb"
  - "spec/support/database_cleaner.rb"
  - "config/prometheus/common_metrics.yml"  # Used by Gitlab::DatabaseImporters::CommonMetrics::Importer
  - "{,ee/,jh/}app/models/project_statistics.rb"  # Used to calculate sizes in migration specs
  - "{,ee/,jh/}app/{,models/,services/,workers/}loose_foreign_keys/**/*"
  # Gitaly has interactions with background migrations: https://gitlab.com/gitlab-org/gitlab/-/issues/336538
  - "GITALY_SERVER_VERSION"
  - "lib/gitlab/setup_helper.rb"
  # Test-gap from https://gitlab.com/gitlab-org/quality/engineering-productivity/team/-/issues/275
  - "{,ee/,jh/}lib/tasks/gitlab/seed/*.rake"

# DB backup patterns
.db-backup-patterns: &db-backup-patterns
  - "lib/backup/**/*"
  - "lib/tasks/gitlab/backup.rake"

.db-library-patterns: &db-library-patterns
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database/**/*"
  - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/database{,_spec}.rb"
  - "{,ee/,jh/}spec/support/helpers/database/**/*"

.backstage-patterns: &backstage-patterns
  - "Dangerfile"
  - "danger/**/*"
  - "{,ee/,jh/}fixtures/**/*"
  - "{,ee/,jh/}rubocop/**/*"
  - "{,ee/,jh/}spec/**/*"
  - "{,spec/}tooling/**/*"

.qa-patterns: &qa-patterns
  - ".dockerignore"
  - "{,jh/}qa/**/*"

# Frontend view patterns + .qa-patterns
.frontend-qa-patterns: &frontend-qa-patterns
  - "{,ee/,jh/}{app/assets,app/components,app/helpers,app/presenters,app/views}/**/*"
  # QA changes
  - "{,jh/}qa/**/*"

# Code patterns + .ci-patterns
.code-patterns: &code-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "vendor/assets/**/*"
  - ".{eslintrc.yml,eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
  - "*_VERSION"
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "tests.yml"
  - "config.ru"
  - "{,ee/,jh/}{app,bin,config,db,elastic,generator_templates,gems,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*"
  # Auto-generated files
  - "doc/api/graphql/reference/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"

# .code-patterns + .backstage-patterns
.code-backstage-patterns: &code-backstage-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "vendor/assets/**/*"
  - ".{eslintrc.yml,eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
  - "*_VERSION"
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "tests.yml"
  - "config.ru"
  - "{,ee/,jh/}{app,bin,config,db,elastic,generator_templates,gems,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*"
  # Auto-generated files
  - "doc/api/graphql/reference/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"
  # Backstage changes
  - "Dangerfile"
  - "danger/**/*"
  - "{,ee/,jh/}fixtures/**/*"
  - "{,ee/,jh/}rubocop/**/*"
  - "{,ee/,jh/}spec/**/*"
  - "{,spec/}tooling/**/*"

# .code-patterns + .qa-patterns
.code-qa-patterns: &code-qa-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "vendor/assets/**/*"
  - ".{eslintrc.yml,eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
  - "*_VERSION"
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "tests.yml"
  - "config.ru"
  - "{,ee/,jh/}{app,bin,config,db,elastic,generator_templates,gems,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*"
  # Auto-generated files
  - "doc/api/graphql/reference/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  # QA changes
  - ".dockerignore"
  - "{,jh/}qa/**/*"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"

# .code-patterns + .backstage-patterns + .qa-patterns
.code-backstage-qa-patterns: &code-backstage-qa-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "vendor/assets/**/*"
  - ".{eslintrc.yml,eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
  - ".gitlab-ci.yml"
  - "*_VERSION"
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "tests.yml"
  - "config.ru"
  - "{,ee/,jh/}{app,bin,config,db,elastic,generator_templates,gems,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*"
  # Auto-generated files
  - "doc/api/graphql/reference/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  # Backstage changes
  - "Dangerfile"
  - "danger/**/*"
  - "{,ee/,jh/}fixtures/**/*"
  - "{,ee/,jh/}rubocop/**/*"
  - "{,ee/,jh/}spec/**/*"
  - "{,spec/}tooling/**/*"
  # QA changes
  - ".dockerignore"
  - "{,jh/}qa/**/*"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"

# .code-backstage-qa-patterns + .workhorse-patterns
# NOTE: `setup-test-env-patterns` intentionally does not include docs files, because this would
#       result in docs-only pipelines having failures of jobs which use `setup-test-env-patterns`
#       in their rules and thus require `setup-test-env`, which isn't present in docs-only pipelines.
.setup-test-env-patterns: &setup-test-env-patterns
  - "{package.json,yarn.lock}"
  - ".browserslistrc"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - ".stylelintrc"
  - "Dockerfile.assets"
  - "vendor/assets/**/*"
  - ".{eslintrc.yml,eslintignore,gitattributes,nvmrc,prettierrc,stylelintrc,yamllint}"
  - "*_VERSION"
  - "{,jh/}Gemfile{,.lock}"
  - "Rakefile"
  - "tests.yml"
  - "config.ru"
  - "{,ee/,jh/}{app,bin,config,db,elastic,generator_templates,gems,haml_lint,lib,locale,public,scripts,storybook,symbol,vendor}/**/*"
  # Auto-generated files
  - "doc/api/graphql/reference/*"
  # CI changes
  - ".gitlab-ci.yml"
  - ".gitlab/ci/**/*"
  # Mapped patterns (see tests.yml)
  - "data/whats_new/*.yml"
  - "doc/index.md"
  # Backstage changes
  - "Dangerfile"
  - "danger/**/*"
  - "{,ee/,jh/}fixtures/**/*"
  - "{,ee/,jh/}rubocop/**/*"
  - "{,ee/,jh/}spec/**/*"
  - "{,spec/}tooling/**/*"
  # QA changes
  - ".dockerignore"
  - "{,jh/}qa/**/*"
  # Workhorse changes
  - "GITLAB_WORKHORSE_VERSION"
  - "workhorse/**/*"
  - ".gitlab/ci/workhorse.gitlab-ci.yml"
  # CI Templates changes
  - "scripts/lint_templates_bash.rb"
  - "lib/gitlab/ci/templates/**/*.gitlab-ci.yml"
  # GLFM specification changes
  - "glfm_specification/**/*"

.static-analysis-patterns: &static-analysis-patterns
  - ".{codeclimate,eslintrc,haml-lint,haml-lint_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"
  - "config/feature_categories.yml"  # Used by RSpec/FeatureCategory

.danger-patterns: &danger-patterns
  - "Dangerfile"
  - "danger/**/*"
  - "tooling/danger/**/*"

.core-backend-patterns: &core-backend-patterns
  - "{,jh/}Gemfile{,.lock}"
  - "{,ee/,jh/}config/**/*.rb"

.core-frontend-patterns: &core-frontend-patterns
  - "{package.json,yarn.lock}"
  - "babel.config.js"
  - "jest.config.{base,integration,unit}.js"
  - "config/helpers/**/*.js"
  - "vendor/assets/javascripts/**/*"

.feature-flag-development-config-patterns: &feature-flag-development-config-patterns
  - "{,ee/,jh/}config/feature_flags/**/*.yml"

.glfm-patterns: &glfm-patterns
  - ".gitlab/ci/rules.gitlab-ci.yml"
  - "glfm_specification/**/*"
  - "scripts/glfm/**/*"
  - "scripts/lib/glfm/**/*"

# Certain components require the base e2e GDK image to be rebuilt if they change
.gdk-component-patterns: &gdk-component-patterns
  - qa/gdk/**/*
  - Gemfile.lock
  - yarn.lock
  - scripts/build_gdk_image
  - scripts/frontend/postinstall.js
  - workhorse/**/*
  - vendor/gems/**/*
  - gems/**/*
  - VERSION
  - GITLAB_WORKHORSE_VERSION
  - GITLAB_SHELL_VERSION
  - GITALY_SERVER_VERSION

.audit-events-patterns: &audit-events-patterns
  - "{,ee/}config/audit_events/types/*.yml"
  - "doc/administration/audit_event_types.md"
  - "tooling/audit_events/docs/templates/audit_event_types.md.erb"
  - "lib/tasks/gitlab/audit_event_types/audit_event_types.rake"
  - "lib/tasks/gitlab/audit_event_types/check_docs_task.rb"
  - "lib/gitlab/audit/type/definition.rb"
  - "ee/lib/ee/gitlab/audit/type/definition.rb"

##################
# Conditions set #
##################
.strict-ee-only-rules:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-jh
      when: never

.rails:rules:run-search-tests:
  rules:
    - !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-ee-only", rules]
    - <<: *if-merge-request-labels-group-global-search
      changes: *search-backend-patterns
    - <<: *if-merge-request-labels-group-global-search
      changes: *ci-patterns

.rails:rules:ee-and-foss-default-rules:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *core-backend-patterns
    - <<: *if-automated-merge-request
      changes: *backend-patterns
    - <<: *if-security-merge-request
      changes: *backend-patterns
    - <<: *if-merge-request-not-approved
      when: never

.rails:rules:system-default-rules:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *core-backend-patterns
    - <<: *if-merge-request
      changes: *workhorse-patterns
    - <<: *if-automated-merge-request
      changes: *code-backstage-patterns
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
    - <<: *if-merge-request-not-approved
      when: never

.rails:rules:previous-failed-tests-default-rules:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-security-merge-request
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *code-backstage-patterns

###########################
# Conditions set for JiHu #
###########################
.rails:rules:predictive-default-rules:
  rules:
    - <<: *if-merge-request-approved
      when: never
    - <<: *if-automated-merge-request
      when: never
    - <<: *if-security-merge-request
      when: never

.rails:rules:as-if-foss-migration-unit-integration:predictive-default-rules:
  rules:
    - <<: *if-merge-request
      changes: *core-backend-patterns
      when: never
    - <<: *if-merge-request
      changes: *ci-patterns
      when: never

.rails:rules:unit-integration:predictive-default-rules:
  rules:
    - <<: *if-merge-request-labels-run-all-rspec
      when: never
    - !reference [".rails:rules:as-if-foss-migration-unit-integration:predictive-default-rules", rules]

.rails:rules:system:predictive-default-rules:
  rules:
    - <<: *if-merge-request-labels-run-all-rspec
      when: never
    - <<: *if-merge-request
      changes: *core-backend-patterns
      when: never
    - <<: *if-merge-request
      changes: *workhorse-patterns
      when: never
    - <<: *if-merge-request
      changes: *ci-patterns
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-patterns

.rails:rules:ee-and-foss-migration:predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *db-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
    # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
    - <<: *if-merge-request
      changes: *db-patterns
      when: never
.rails:rules:ee-and-foss-background-migration:predictive:
  rules:
    - !reference [".rails:rules:ee-and-foss-migration:predictive", rules]
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:ee-and-foss-unit:predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *backend-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    - <<: *if-merge-request
      changes: *backend-patterns
    - <<: *if-merge-request
      changes: *backstage-patterns

.rails:rules:ee-and-foss-integration:predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *backend-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:ee-and-foss-system:predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *code-backstage-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:system:predictive-default-rules", rules]

.rails:rules:ee-only-migration:predictive:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
    # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
    - <<: *if-merge-request
      changes: *db-patterns
      when: never

.rails:rules:ee-only-background-migration:predictive:
  rules:
    - !reference [".rails:rules:ee-only-migration:predictive", rules]
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:ee-only-unit:predictive:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      changes: *backend-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:ee-only-integration:predictive:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      changes: *backend-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:unit-integration:predictive-default-rules", rules]
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:ee-only-system:predictive:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      changes: *code-backstage-patterns
    - !reference [".rails:rules:predictive-default-rules", rules]
    - !reference [".rails:rules:system:predictive-default-rules", rules]

################
# Shared rules #
################
.shared:rules:update-cache:
  rules:
    - <<: *if-schedule-maintenance
    - <<: *if-security-schedule
    - <<: *if-foss-schedule
    - <<: *if-merge-request-labels-update-caches

.shared:rules:update-gitaly-binaries-cache:
  rules:
    - <<: *if-merge-request-labels-update-caches
    - <<: *if-default-refs
      changes: *gitaly-patterns

######################
# Build images rules #
######################
.build-images:rules:build-qa-image-merge-requests:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_BUILD_QA_IMAGE == "true"'
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-merge-request-labels-run-review-app
    - <<: *if-merge-request
      changes: *ci-build-images-patterns
    - <<: *if-merge-request
      changes: *code-qa-patterns
    # Rules to support .qa:rules:package-and-test-ee
    - <<: *if-merge-request
      changes: *dependency-patterns
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-merge-request
      changes: *ci-qa-patterns
    - <<: *if-force-ci

.build-images:rules:build-qa-image:
  rules:
    - !reference [".build-images:rules:build-qa-image-merge-requests", "rules"]
    - <<: *if-auto-deploy-branches
      variables:
        ARCH: amd64,arm64
    - <<: *if-default-branch-refs
      variables:
        ARCH: amd64,arm64
    - <<: *if-tag
      variables:
        ARCH: amd64,arm64
      # TODO: Remove once confirmed on a tag pipeline
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-schedule
      variables:
        ARCH: amd64,arm64
    - <<: *if-ruby-branch
    - !reference [".releases:rules:canonical-dot-com-gitlab-stable-branch-only-setup-test-env", rules]

.build-images:rules:build-qa-image-as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - !reference [".build-images:rules:build-qa-image-merge-requests", "rules"]
    - <<: *if-default-branch-schedule-nightly
      variables:
        ARCH: amd64,arm64

# We use a multi-stage image to:
# - (re)build the first stage in master pipelines (including scheduled pipelines), and
# - build the final stage in code-change pipelines (including MRs), and scheduled pipelines
# This has to match ".qa:rules:e2e:test-on-gdk" otherwise there won't be an image available to run GDK in the test jobs.
# Unfortunately, we can't just include ".qa:rules:e2e:test-on-gdk" because some of the conditions are manual
# Since the smoke test job is not allowed to fail, the `build-gdk-image` job is also not allowed to fail.
# It's better to fail early and avoid wasting resources running test jobs that would just fail anyway.
.build-images:rules:build-gdk-image:
  rules:
    # Allows to force rebuild base image in case something goes wrong and this had to be disabled
    - if: '$QA_RUN_TESTS_ON_GDK !~ /true|yes|1/i'
      when: manual
      allow_failure: true
      variables:
        BUILD_GDK_BASE: "true"
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-default-branch-schedule-nightly  # already executed in the 2-hourly schedule
      when: never
    - <<: *if-default-branch-refs
    - <<: *if-merge-request
      changes: *gdk-component-patterns
    # The rest are included to be consistent with .qa:rules:e2e:test-on-gdk
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-ruby-branch
    # We include the job under the matching conditions below, but unlike in .qa:rules:e2e:test-on-gdk we don't need to
    # set OMNIBUS_GITLAB_BUILD_ON_ALL_OS when testing against GDK
    - <<: *if-merge-request
      changes: *dependency-patterns
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-merge-request-labels-run-cs-evaluation
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *initializers-patterns
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-merge-request
      changes: *ci-qa-patterns
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      when: manual
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
    - <<: *if-merge-request
      changes: *code-qa-patterns
    - <<: *if-force-ci
      when: manual

.build-images:rules:build-assets-image:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_BUILD_ASSETS_IMAGE == "true"'
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-ruby-branch
    - <<: *if-merge-request-labels-run-review-app
    - <<: *if-auto-deploy-branches
    - <<: *if-default-refs
      changes: *ci-build-images-patterns
    - <<: *if-default-refs
      changes: *code-qa-patterns
    # Rules to support .qa:rules:package-and-test
    - <<: *if-default-branch-schedule-nightly
    - <<: *if-merge-request
      changes: *dependency-patterns
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-merge-request
      changes: *ci-qa-patterns
    - <<: *if-force-ci

.build-images:rules:build-assets-image-as-if-foss:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".build-images:rules:build-assets-image", "rules"]

#################
# Caching rules #
#################
.caching:rules:cache-workhorse:
  rules:
    - <<: *if-not-ee
      when: never
    # That would run for any project that has a "maintenance" pipeline schedule
    # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
    - <<: *if-schedule-maintenance
    - <<: *if-dot-com-gitlab-org-default-branch
      changes: ["workhorse/**/*"]
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - ".gitlab/ci/caching.gitlab-ci.yml"
        - "scripts/gitlab_component_helpers.sh"
      when: manual
      allow_failure: true

.caching:rules:cache-assets:
  rules:
    # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
    - if: '$CACHE_ASSETS_AS_PACKAGE != "true"'
      when: never
    - <<: *if-not-ee
      when: never
    # That would run for any project that has a "maintenance" pipeline schedule
    # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
    - <<: *if-schedule-maintenance
    - <<: *if-dot-com-gitlab-org-default-branch
      changes: *assets-compilation-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - ".gitlab/ci/caching.gitlab-ci.yml"
        - "scripts/gitlab_component_helpers.sh"
        - "lib/tasks/gitlab/assets.rake"
      when: manual
      allow_failure: true

.caching:rules:cache-assets-as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - !reference [".caching:rules:cache-assets", "rules"]

.caching:rules:packages-cleanup:
  rules:
    # The new strategy to cache assets as generic packages is experimental and can be disabled by removing the `CACHE_ASSETS_AS_PACKAGE` variable
    - if: '$CACHE_ASSETS_AS_PACKAGE != "true"'
      when: never
    - <<: *if-not-ee
      when: never
    # That would run for any project that has a "maintenance" pipeline schedule
    # but in fact, the cache package is only uploaded for gitlab.com/gitlab-org/gitlab and jihulab.com/gitlab-cn/gitlab
    - <<: *if-schedule-maintenance
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - ".gitlab/ci/caching.gitlab-ci.yml"
        - "scripts/packages/automated_cleanup.rb"
      when: manual
      allow_failure: true

######################
# CI Templates Rules #
######################
.ci-templates:rules:shellcheck:
  rules:
    - <<: *if-default-refs
      changes: *ci-templates-patterns
    - <<: *if-default-refs
      changes:
        - scripts/lint_templates_bash.rb

######################
# Dev fixtures rules #
######################
.dev-fixtures:rules:ee-and-foss:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.dev-fixtures:rules:ee-only:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

##############
# Docs rules #
##############
.docs:rules:review-docs:
  rules:
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *docs-patterns
      when: manual
      allow_failure: true

.docs:rules:redirect-check:
  rules:
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *docs-patterns

.docs:rules:docs-lint:
  rules:
    - <<: *if-default-refs
      changes: *docs-patterns

.docs:rules:docs-blueprints-lint:
  rules:
    - <<: *if-default-refs
      changes: *docs-blueprints-patterns

.docs:rules:deprecations-and-removals:
  rules:
    - <<: *if-default-refs
      changes: *docs-deprecations-and-removals-patterns

##################
# GLFM rules     #
##################
.glfm:rules:glfm-verify:
  # NOTES ON RULES:
  # 1. We only run this job in EE because some of the markdown examples in the generated files depend
  #    on EE-only features. This means that it may fail when it is first run in a full EE pipeline.
  # 2. We run this job for the `.setup-test-env-patterns` subset of file changes because:
  #    A. There are potentially many different source files within the codebase which could
  #       change the contents of the generated GLFM files, and it is therefore safer to always
  #       run this job to ensure that no changes are missed.
  #    B. The `.setup-test-env-patterns` restriction is needed because the job `needs` the
  #       `setup-test-env` job.
  # See more context on each rule in the inline comments below:
  rules:
    # The `glfm-verify` job has dependencies on EE, so only run it for EE
    - !reference [".strict-ee-only-rules", rules]
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    # If any of the files that are DIRECTLY related to generating or managing the GLFM specification change,
    # run `glfm-verify` to get quick feedback on any needed updates, even if the MR is not yet approved
    - <<: *if-default-refs
      changes: *glfm-patterns
    # Otherwise do not run `glfm-verify` if the MR is not approved
    - <<: *if-merge-request-not-approved
      when: never
    # If we passed all the previous rules, run `glfm-verify` if there are any changes that could impact `glfm-verify`.
    # This could potentially be a wide range of files, so we reuse `setup-test-env-patterns`, which includes
    # almost all app files except docs files.
    - <<: *if-default-refs
      changes: *setup-test-env-patterns
    # If we are forcing all rspec to run, run this job too.
    - <<: *if-merge-request-labels-run-all-rspec

##################
# GraphQL rules  #
##################
.graphql:rules:graphql-verify:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

############################
# Audit event types rules  #
############################
.audit-event-types:rules:audit-event-types-verify:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-default-refs
      changes: *audit-events-patterns

##################
# Frontend rules #
##################
.frontend:rules:predictive-default-rules:
  rules:
    - <<: *if-merge-request-approved
      when: never
    - <<: *if-automated-merge-request
      when: never
    - <<: *if-security-merge-request
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never

.frontend:rules:compile-production-assets:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_COMPILE_PRODUCTION_ASSETS == "true"'
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-merge-request-labels-run-review-app
    - <<: *if-auto-deploy-branches
    - <<: *if-ruby-branch
    - <<: *if-default-refs
      changes: *ci-build-images-patterns
    - <<: *if-default-refs
      changes: *code-qa-patterns
    - <<: *if-default-refs
      changes: *workhorse-patterns
    # Rules to support .qa:rules:package-and-test
    - <<: *if-default-branch-schedule-nightly
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *dependency-patterns
    - <<: *if-force-ci

.frontend:rules:compile-production-assets-as-if-foss:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - !reference [".strict-ee-only-rules", rules]
    - !reference [.frontend:rules:compile-production-assets, rules]

.frontend:rules:compile-test-assets:
  rules:
    - if: '$ENABLE_COMPILE_TEST_ASSETS == "true"'
    - if: '$ENABLE_RSPEC == "true"'
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *backend-patterns
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns
    - <<: *if-default-refs
      changes: *workhorse-patterns

.frontend:rules:compile-test-assets-as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - <<: *if-merge-request-labels-as-if-foss
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns
    - <<: *if-default-refs
      changes: *workhorse-patterns

.frontend:rules:default-frontend-jobs:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_JEST_INTEGRATION == "true"'
    - if: '$ENABLE_RSPEC_FRONTEND_FIXTURE == "true"'
    - if: '$ENABLE_ESLINT == "true"'
    - if: '$ENABLE_COMPILE_STORYBOOK == "true"'
    - if: '$ENABLE_GRAPHQL_SCHEMA_DUMP == "true"'
    - if: '$ENABLE_GENERATE_APOLLO_GRAPHQL_SCHEMA == "true"'
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.frontend:rules:default-frontend-jobs-as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
    - <<: *if-merge-request-labels-as-if-foss
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *frontend-patterns-for-as-if-foss

.frontend:rules:frontend_fixture-as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - !reference [".frontend:rules:default-frontend-jobs-as-if-foss", rules]
    - <<: *if-merge-request-labels-run-all-jest
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-merge-request
      changes: *frontend-patterns-for-as-if-foss

.frontend:rules:upload-frontend-fixtures:
  rules:
    # The new strategy to upload fixtures as generic packages is experimental and can be disabled by removing the `REUSE_FRONTEND_FIXTURES_ENABLED` variable
    - if: '$REUSE_FRONTEND_FIXTURES_ENABLED != "true"'
      when: never
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-dot-com-gitlab-org-default-branch
      changes: *code-backstage-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - ".gitlab/ci/frontend.gitlab-ci.yml"
        - "scripts/gitlab_component_helpers.sh"
      when: manual
      allow_failure: true

.frontend:rules:jest:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-fork-merge-request
      when: never
    - if: '$ENABLE_JEST == "true"'
    - <<: *if-merge-request-labels-run-all-jest
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-merge-request
      changes: *frontend-dependency-patterns
    - <<: *if-merge-request
      changes: [".gitlab/ci/rules.gitlab-ci.yml", ".gitlab/ci/frontend.gitlab-ci.yml"]
    - <<: *if-automated-merge-request
      changes: *code-backstage-patterns
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.frontend:rules:jest:predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *code-backstage-patterns
    - !reference [".frontend:rules:predictive-default-rules", rules]
    - <<: *if-merge-request-labels-run-all-jest
      when: never
    - <<: *if-merge-request-labels-frontend-and-feature-flag
      when: never
    - <<: *if-merge-request
      changes: *frontend-dependency-patterns
      when: never
    - <<: *if-merge-request
      changes: [".gitlab/ci/rules.gitlab-ci.yml", ".gitlab/ci/frontend.gitlab-ci.yml"]
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-patterns

.frontend:rules:jest:predictive:as-if-foss:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - !reference [".frontend:rules:predictive-default-rules", rules]
    - <<: *if-merge-request-labels-as-if-foss
      when: never
    - <<: *if-merge-request-labels-run-all-jest
      when: never
    - <<: *if-merge-request
      changes: *frontend-dependency-patterns
      when: never
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-merge-request
      changes: *frontend-patterns-for-as-if-foss

.frontend:rules:coverage-frontend:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-patterns
    - <<: *if-default-branch-refs
      changes: *code-backstage-patterns

.frontend:rules:bundle-size-review:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-branch-refs
      changes: *frontend-build-patterns
      allow_failure: true
    - if: '$DANGER_GITLAB_API_TOKEN && ($CI_MERGE_REQUEST_EVENT_TYPE == "merged_result" || $CI_MERGE_REQUEST_EVENT_TYPE == "detached") && $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH'
      changes: *frontend-build-patterns
      allow_failure: true

.frontend:rules:jest-snapshot:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-merge-request-labels-run-all-jest
      when: manual
      allow_failure: true
    - <<: *if-merge-request-labels-frontend-and-feature-flag
      when: manual
      allow_failure: true
    - <<: *if-merge-request
      changes: *frontend-dependency-patterns
      when: manual
      allow_failure: true
    - <<: *if-merge-request
      changes: [".gitlab/ci/rules.gitlab-ci.yml", ".gitlab/ci/frontend.gitlab-ci.yml"]
      allow_failure: true

################
# Memory rules #
################
.memory:rules:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-patterns

##########
# Notify #
##########
.notify:rules:notify-package-and-test-failure:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-security-merge-request
      when: never
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      when: always

###############
# Pages rules #
###############
.pages:rules:
  rules:
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance

############
# QA rules #
############
.qa:rules:update-gem-cache:
  rules:
    - if: '$CI_COMMIT_REF_NAME == $CI_DEFAULT_BRANCH || $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable(-ee)?$/ || $CI_COMMIT_REF_NAME =~ /^\d+-\d+-auto-deploy-\d+$/ || $CI_COMMIT_REF_NAME =~ /^security\//'
      changes:
        - qa/Gemfile.lock
    - <<: *if-schedule-maintenance
    - <<: *if-security-schedule
    - <<: *if-foss-schedule
    - <<: *if-merge-request-labels-update-caches

.qa:rules:code-merge-request-manual:
  rules:
    - <<: *if-merge-request
      changes: *code-patterns
      when: manual
      allow_failure: true

.qa:rules:code-merge-request:
  rules:
    - <<: *if-merge-request
      changes: *code-patterns

.qa:rules:internal:
  rules:
    - if: '$ENABLE_QA_INTERNAL == "true"'
    - <<: *if-default-refs
      changes: *qa-patterns

.qa:rules:selectors:
  rules:
    - if: '$ENABLE_QA_SELECTORS == "true"'
    - <<: *if-default-refs
      changes: *code-qa-patterns

.qa:rules:determine-e2e-tests:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      allow_failure: true
    - <<: *if-merge-request
      # Certain components trigger a rebuild of the e2e GDK image so we want to test it too
      changes: *gdk-component-patterns
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-schedule
      allow_failure: true
    - <<: *if-ruby-branch
    # Rules to support .qa:rules:package-and-test-ee
    - <<: *if-merge-request
      changes: *dependency-patterns
      allow_failure: true
    - <<: *if-merge-request-labels-run-all-e2e
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *nodejs-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *ci-qa-patterns
      allow_failure: true
    - <<: *if-force-ci
      allow_failure: true

# All rules copied from qa:rules:package-and-test-ee but jobs are automatic and not allowed to fail
.qa:rules:trigger-omnibus-env:
  rules:
    # From .qa:rules:package-and-test-common
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-ruby-branch
    - <<: *if-merge-request
      changes: *dependency-patterns
      variables:
        OMNIBUS_GITLAB_BUILD_ON_ALL_OS: 'true'
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request
      changes: *initializers-patterns
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-merge-request
      changes: *ci-qa-patterns
    - <<: *if-merge-request
      changes: *qa-patterns
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
    - <<: *if-force-ci
    # From .qa:rules:package-and-test-schedule
    - <<: *if-dot-com-gitlab-org-schedule
    # From .qa:rules:code-merge-request-manual
    - <<: *if-merge-request
      changes: *code-patterns

.qa:rules:package-and-test-never-run:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never

.qa:rules:package-and-test-common:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      allow_failure: true
    - <<: *if-ruby-branch
      allow_failure: true
    - <<: *if-merge-request
      changes: *dependency-patterns
      variables:
        OMNIBUS_GITLAB_BUILD_ON_ALL_OS: 'true'
    - <<: *if-merge-request-labels-run-all-e2e
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      when: manual
      allow_failure: true
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *initializers-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *nodejs-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *ci-qa-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *qa-patterns
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
      allow_failure: true
    - <<: *if-force-ci
      when: manual
      allow_failure: true
    - <<: *if-merge-request-approved-and-specific-devops-stage
      changes: *code-patterns
      allow_failure: true
      # We used to have a rule at the end here that would catch any remaining code MRs and allow the job to be run
      # manually. That rule is now in ".qa:rules:code-merge-request-manual" so it can be included when needed and we can
      # still use ".qa:rules:package-and-test-common" in jobs we don't want to be manual.

# Like .qa:rules:package-and-test-common but not allowed to fail.
# It's named `e2e` instead of `package-and-test` because it's used for e2e tests on GDK (and could be used
# for other e2e tests)
.qa:rules:e2e-blocking:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-ruby-branch
    - <<: *if-merge-request
      # Certain components trigger a rebuild of the e2e GDK image so we want to test it too
      changes: *gdk-component-patterns
    - <<: *if-merge-request
      changes: *dependency-patterns
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      when: manual
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
    - <<: *if-merge-request
      changes: *code-patterns
      variables:
        MR_CODE_PATTERNS: "true"
    - <<: *if-merge-request
      changes: *code-qa-patterns  # Includes all CI changes
    - <<: *if-force-ci
      when: manual

.qa:e2e-test-schedule-variables: &qa-e2e-test-schedule-variables
  variables:
    CREATE_TEST_FAILURE_ISSUES: "true"
    PROCESS_TEST_RESULTS: "true"
    KNAPSACK_GENERATE_REPORT: "true"
    QA_SAVE_TEST_METRICS: "true"
    QA_EXPORT_TEST_METRICS: "false"  # on main runs, metrics are exported to separate bucket via rake task for better consistency

.qa:rules:package-and-test-schedule:
  rules:
    - <<: [*if-dot-com-gitlab-org-schedule, *qa-e2e-test-schedule-variables]
      allow_failure: true

.qa:rules:e2e-schedule-blocking:
  rules:
    - <<: [*if-dot-com-gitlab-org-schedule, *qa-e2e-test-schedule-variables]

.qa:rules:code-suggestions-eval-base:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-merge-request-labels-run-cs-evaluation

.qa:rules:code-suggestions-eval:
  rules:
    - !reference [".qa:rules:code-suggestions-eval-base", rules]
    - <<: *if-merge-request
      changes: *code-patterns
      when: manual
      allow_failure: true

.qa:rules:code-suggestions-eval-results:
  rules:
    - !reference [".qa:rules:code-suggestions-eval-base", rules]
    - <<: *if-merge-request
      changes: *code-patterns

# Note: If any changes are made to this rule, the following should also be updated:
# 1) .qa:rules:manual-omnibus-and-follow-up-e2e
# 2) .qa:rules:follow-up-e2e
# 3) .qa:rules:trigger-omnibus-env
# 4) .qa:rules:post-run-e2e-message
.qa:rules:package-and-test-ee:
  rules:
    - !reference [".qa:rules:package-and-test-common", rules]
    - !reference [".qa:rules:package-and-test-schedule", rules]
    - !reference [".qa:rules:code-merge-request-manual", rules]

.qa:rules:package-and-test-ce:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-dot-com-gitlab-org-and-security-merge-request
      changes: *ci-build-images-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-and-security-merge-request
      changes: *code-qa-patterns
      when: manual
      allow_failure: true
    - <<: *if-default-branch-schedule-nightly
      allow_failure: true
      variables:
        CREATE_TEST_FAILURE_ISSUES: "true"
        PROCESS_TEST_RESULTS: "true"
        QA_SAVE_TEST_METRICS: "true"
        QA_EXPORT_TEST_METRICS: "false"

.qa:rules:e2e:test-on-gdk:
  rules:
    - if: '$QA_RUN_TESTS_ON_GDK !~ /true|yes|1/i'
      when: never
    - <<: *if-default-branch-schedule-nightly  # already executed in the 2-hourly schedule
      when: never
    - !reference [".qa:rules:e2e-blocking", rules]
    - !reference [".qa:rules:e2e-schedule-blocking", rules]

.qa:rules:package-and-test-nightly:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-default-branch-schedule-nightly
      allow_failure: true
      variables:
        KNAPSACK_GENERATE_REPORT: "true"
        PROCESS_TEST_RESULTS: "true"
        CREATE_TEST_FAILURE_ISSUES: "true"
        QA_SAVE_TEST_METRICS: "true"
        QA_EXPORT_TEST_METRICS: "false"

.qa:rules:trigger-omnibus:
  rules:
    - !reference [".qa:rules:package-and-test-nightly", rules]
    - !reference [".qa:rules:package-and-test-ee", rules]

.qa:rules:trigger-omnibus-ce:
  rules:
    - !reference [".qa:rules:package-and-test-nightly", rules]
    - !reference [".qa:rules:package-and-test-ce", rules]

# These are based on `.qa:rules:trigger-omnibus` except:
# 1. Automatic jobs changed to `when: never.`
# 2. For specific devops stage, do not run for code-patterns
# If any changes are made to this rule, `.qa:rules:follow-up-e2e` should also be updated.
.qa:rules:manual-omnibus-and-follow-up-e2e:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-and-specific-devops-stage
      when: never
    - !reference [".qa:rules:code-merge-request-manual", rules]
    - <<: *if-dot-com-gitlab-org-schedule
      when: never
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      when: never
    - <<: *if-ruby-branch
      when: never
    - <<: *if-merge-request
      changes: *dependency-patterns
      when: never
    - <<: *if-merge-request-labels-run-all-e2e
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      when: manual
      allow_failure: true
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      when: never
    - <<: *if-merge-request
      changes: *initializers-patterns
      when: never
    - <<: *if-merge-request
      changes: *nodejs-patterns
      when: never
    - <<: *if-merge-request
      changes: *ci-qa-patterns
      when: never
    - <<: *if-merge-request
      changes: *qa-patterns
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
      when: never
    - <<: *if-force-ci
      when: manual
      allow_failure: true

# These are based on `.qa:rules:manual-omnibus-and-follow-up-e2e` but with manual jobs changed to automatic
.qa:rules:follow-up-e2e:
  rules:
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-and-specific-devops-stage
      when: never
    - <<: *if-merge-request
      changes: *code-patterns
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-schedule
      when: never
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      when: never
    - <<: *if-ruby-branch
      when: never
    - <<: *if-merge-request
      changes: *dependency-patterns
      when: never
    - <<: *if-merge-request-labels-run-all-e2e
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      when: never
    - <<: *if-merge-request
      changes: *initializers-patterns
      when: never
    - <<: *if-merge-request
      changes: *nodejs-patterns
      when: never
    - <<: *if-merge-request
      changes: *ci-qa-patterns
      when: never
    - <<: *if-merge-request
      changes: *qa-patterns
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
      when: never
    - <<: *if-force-ci
      allow_failure: true

# These are based on `qa:rules:package-and-test-ee` but with when:never in all except for code-patterns in merge requests
.qa:rules:post-run-e2e-message:
  rules:
    # From .qa:rules:package-and-test-common
    - !reference [".qa:rules:package-and-test-never-run", rules]
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      when: never
    - <<: *if-ruby-branch
      when: never
    - <<: *if-merge-request
      changes: *dependency-patterns
      when: never
    - <<: *if-merge-request-labels-run-all-e2e
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      when: never
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      when: never
    - <<: *if-merge-request
      changes: *initializers-patterns
      when: never
    - <<: *if-merge-request
      changes: *nodejs-patterns
      when: never
    - <<: *if-merge-request
      changes: *ci-qa-patterns
      when: never
    - <<: *if-merge-request
      changes: *qa-patterns
      when: never
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-and-qa-tests-specified
      changes: *code-patterns
      when: never
    - <<: *if-force-ci
      when: never
    - <<: *if-merge-request-and-specific-devops-stage
      when: never
    # From .qa:rules:package-and-test-schedule
    - <<: *if-dot-com-gitlab-org-schedule
      when: never
    # Do not run on unapproved MR
    - <<: *if-merge-request-not-approved
      when: never
    # From .qa:rules:code-merge-request-manual
    - <<: *if-merge-request
      changes: *code-patterns
      allow_failure: true

.qa:rules:fulfillment-e2e-quarantine-report:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-and-devops-fulfillment
      changes: *code-patterns
      allow_failure: true

###############
# Rails rules #
###############
.rails:rules:setup-test-env:
  rules:
    - if: '$ENABLE_RSPEC == "true"'
    - <<: *if-default-refs
      changes: *setup-test-env-patterns
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:clusterwide-db:
  rules:
    - <<: *if-merge-request-labels-run-clusterwide-db

.rails:rules:single-redis:
  rules:
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_RSPEC_SINGLE_REDIS == "true"'
    - <<: *if-merge-request
      changes: *redis-patterns
    - <<: *if-default-branch-schedule-nightly

.rails:rules:single-redis-ee:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:single-redis", "rules"]

.rails:rules:single-db:
  rules:
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_RSPEC_SINGLE_DB == "true"'
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns
    - <<: *if-default-branch-schedule-nightly

.rails:rules:single-db-ee:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:single-db", "rules"]

.rails:rules:db:check-migrations-single-db:
  rules:
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns

.rails:rules:single-db-ci-connection:
  rules:
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_RSPEC_SINGLE_DB_CI_CONNECTION == "true"'
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns
    - <<: *if-default-branch-schedule-nightly

.rails:rules:single-db-ci-connection-ee:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:single-db-ci-connection", "rules"]

.rails:rules:db:check-migrations-single-db-ci-connection:
  rules:
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns

.rails:rules:db-backup:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-default-refs
      changes: *db-backup-patterns
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-default-refs
      changes: *db-patterns

.rails:rules:db-rollback:
  rules:
    - !reference [".rails:rules:ee-and-foss-migration", rules]
    - <<: *if-default-refs
      changes: *initializers-patterns
    - <<: *if-default-refs
      changes:
        - "{,ee/,jh/}{,spec/}lib/{,ee/,jh/}gitlab/content_security_policy/config_loader{,_spec}.rb"

.rails:rules:praefect-with-db:
  rules:
    - if: '$ENABLE_RSPEC_PRAEFECT == "true"'
      allow_failure: true
    - if: '$CI_MERGE_REQUEST_LABELS =~ /pipeline:run-praefect-with-db/'
      allow_failure: true

.rails:rules:ee-and-foss-migration:
  rules:
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$ENABLE_RSPEC_MIGRATION == "true"'
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *core-backend-patterns
    # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
    # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-default-refs
      changes: *db-patterns

.rails:rules:rspec-predictive:
  rules:
    - <<: *if-fork-merge-request
      changes: *code-backstage-patterns
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-approved
      when: never
    - <<: *if-automated-merge-request
      when: never
    - <<: *if-security-merge-request
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-patterns

.rails:rules:ee-and-foss-background-migration:
  rules:
    - if: '$ENABLE_RSPEC_BACKGROUND_MIGRATION == "true"'
    - !reference [".rails:rules:ee-and-foss-migration", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-and-foss-mr-with-migration:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request-labels-run-all-rspec

.rails:rules:db:gitlabcom-database-testing:
  rules:
    - if: '$GITLABCOM_DATABASE_TESTING_TRIGGER_TOKEN == null'
      when: never
    - <<: *if-merge-request
      changes: *db-patterns
      when: manual

.rails:rules:ee-and-foss-unit:
  rules:
    - <<: *if-fork-merge-request
      when: never
    - if: '$ENABLE_RSPEC_UNIT == "true"'
    - !reference [".rails:rules:ee-and-foss-default-rules", rules]
    - <<: *if-default-refs
      changes: *backend-patterns
    - <<: *if-default-refs
      changes: *backstage-patterns

.rails:rules:clickhouse-changes:
  rules:
    - <<: *if-fork-merge-request
      when: never
    - if: '$ENABLE_RSPEC_UNIT == "true"'
    - !reference [".rails:rules:ee-and-foss-default-rules", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-only-clickhouse-changes:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:clickhouse-changes", rules]

.rails:rules:ee-and-foss-integration:
  rules:
    - <<: *if-fork-merge-request
      when: never
    - if: '$ENABLE_RSPEC_INTEGRATION == "true"'
    - !reference [".rails:rules:ee-and-foss-default-rules", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-and-foss-system:
  rules:
    - <<: *if-fork-merge-request
      when: never
    - if: '$ENABLE_RSPEC_SYSTEM == "true"'
    - !reference [".rails:rules:system-default-rules", rules]
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.rails:rules:ee-and-foss-fast_spec_helper:
  rules:
    - if: '$ENABLE_RSPEC_FAST_SPEC_HELPER == "true"'
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *backend-patterns
    - <<: *if-default-refs
      changes: *core-backend-patterns

.rails:rules:code-backstage-qa:
  rules:
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns
    - <<: *if-merge-request-labels-run-all-rspec

.rails:rules:ee-only-migration:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *core-backend-patterns
    # When DB schema changes, many migrations spec may be affected. However, the test mapping from Crystalball does not map db change to a specific migration spec well.
    # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/68840.
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-automated-merge-request
      changes: *db-patterns
    - <<: *if-security-merge-request
      changes: *db-patterns
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-default-refs
      changes: *db-patterns

.rails:rules:ee-only-background-migration:
  rules:
    - !reference [".rails:rules:ee-only-migration", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-only-unit:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      when: never
    - !reference [".rails:rules:ee-and-foss-default-rules", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-only-integration:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      when: never
    - !reference [".rails:rules:ee-and-foss-default-rules", rules]
    - <<: *if-default-refs
      changes: *backend-patterns

.rails:rules:ee-only-system:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-fork-merge-request
      when: never
    - !reference [".rails:rules:system-default-rules", rules]
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.rails:rules:ee-gitlab-duo-chat-base:
  rules:
    - !reference [".strict-ee-only-rules", rules]
    - if: '$REAL_AI_REQUEST == null'
      when: never
    - if: '$ANTHROPIC_API_KEY == null'
      when: never
    - if: '$VERTEX_AI_PROJECT == null'
      when: never
    - if: '$VERTEX_AI_CREDENTIALS == null'
      when: never
    - <<: *if-fork-merge-request
      when: never

.rails:rules:ee-gitlab-duo-chat-optional:
  rules:
    - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
    - <<: *if-merge-request
      changes: *backend-patterns
      when: manual
      allow_failure: true

.rails:rules:ee-gitlab-duo-chat-always:
  rules:
    - !reference [".rails:rules:ee-gitlab-duo-chat-base", rules]
    - <<: *if-merge-request
      changes: *ai-patterns

.rails:rules:ee-gitlab-duo-chat-qa-full:
  rules:
    - !reference [".rails:rules:ee-gitlab-duo-chat-optional", rules]
    - <<: *if-default-branch-refs
      changes: *setup-test-env-patterns
      when: manual
      allow_failure: true

.rails:rules:ee-and-foss-db-library-code:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *db-library-patterns
    - <<: *if-merge-request-labels-run-all-rspec

.rails:rules:ee-mr-and-default-branch-only:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *code-backstage-patterns
    - <<: *if-default-branch-refs
      changes: *code-backstage-patterns

.rails:rules:artifact-collector-unit:
  rules:
    # Always run for as-if-foss to work around not having needs.optional for
    # cross project pipeline. See .gitlab/ci/artifact-collector/as-if-foss.gitlab-ci.yml
    - if: '$START_AS_IF_FOSS == "true"'
    - !reference [".rails:rules:ee-and-foss-unit", rules]

.rails:rules:artifact-collector-system:
  rules:
    - if: '$START_AS_IF_FOSS == "true"'
    - !reference [".rails:rules:ee-and-foss-system", rules]

.rails:rules:artifact-collector-remainder:
  rules:
    - if: '$START_AS_IF_FOSS == "true"'
    - !reference ['.rails:rules:ee-and-foss-integration', rules]
    - !reference ['.rails:rules:ee-and-foss-migration', rules]
    - !reference ['.rails:rules:ee-and-foss-background-migration', rules]

.rails:rules:detect-tests:
  rules:
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns
    - <<: *if-merge-request
      changes: *workhorse-patterns

.rails:rules:detect-previous-failed-tests:
  rules:
    - !reference [".rails:rules:previous-failed-tests-default-rules", rules]

.rails:rules:rerun-previous-failed-tests:
  rules:
    - !reference [".rails:rules:previous-failed-tests-default-rules", rules]

.rails:rules:rspec-foss-impact:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-as-if-foss
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *code-backstage-patterns

.rails:rules:rspec fail-fast:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *code-backstage-patterns

.rails:rules:fail-pipeline-early:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-security-merge-request
      changes: *code-backstage-patterns
      when: on_failure
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *code-backstage-patterns
      when: on_failure

.rails:rules:rspec-coverage:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-patterns
    - <<: *if-schedule-maintenance
    - <<: *if-merge-request-labels-run-all-rspec

.rails:rules:rspec-undercoverage:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-skip-undercoverage
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    # We cannot get the coverage data from child pipeline so we only run undercoverage on full pipelines for now
    # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113410#note_1335422806
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-merge-request
      changes: *backend-patterns

.rails:rules:rspec-merge-auto-explain-logs:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request
      changes: *code-backstage-patterns
    - <<: *if-default-branch-refs
      changes: *code-patterns

.rails:rules:default-branch-schedule-nightly--code-backstage-default-rules:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-branch-schedule-nightly

.rails:rules:default-branch-schedule-nightly--code-backstage:
  rules:
    - !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-default-rules", rules]

.rails:rules:default-branch-schedule-nightly--code-backstage-ee-only:
  rules:
    - <<: *if-not-ee
      when: never
    - !reference [".rails:rules:default-branch-schedule-nightly--code-backstage-default-rules", rules]

.rails:rules:rspec-feature-flags:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.rails:rules:flaky-tests-report:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request
      when: never
    - if: '$FAST_QUARANTINE == "false" && $RETRY_FAILED_TESTS_IN_NEW_PROCESS != "true"'
      when: never
    - <<: *if-default-branch-refs
      changes: *code-backstage-patterns
      when: always

#########################
# Static analysis rules #
#########################

.static-analysis:rules:static-analysis:
  rules:
    - if: '$ENABLE_STATIC_ANALYSIS == "true"'
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns
    - <<: *if-default-refs
      changes: *static-analysis-patterns

.static-analysis:rules:static-verification-with-database:
  rules:
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

.static-analysis:rules:rubocop:
  rules:
    - <<: *if-default-refs
      changes: *rubocop-patterns
      variables:
        RUN_ALL_RUBOCOP: "true"
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

.static-analysis:rules:qa:metadata-lint:
  rules:
    - <<: *if-default-refs
      changes: *qa-patterns
    - <<: *if-default-refs
      changes: [".gitlab/ci/static-analysis.gitlab-ci.yml"]

.static-analysis:rules:haml-lint:
  rules:
    - <<: *if-default-refs
      changes: *rubocop-patterns
    - <<: *if-default-refs
      changes: *static-analysis-patterns
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

.static-analysis:rules:haml-lint-ee:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-default-refs
      changes: *rubocop-patterns
    - <<: *if-default-refs
      changes: *static-analysis-patterns
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

.static-analysis:rules:trigger-depsaster:
  rules:
    - if: "$ENABLE_DEPSASTER != 'true'"
      when: never
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request
      changes: ["**/Gemfile.checksum"]

.semgrep-appsec-custom-rules:rules:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns

.ping-appsec-for-sast-findings:rules:
  rules:
    # Requiring $CUSTOM_SAST_RULES_BOT_PAT prevents the bot from running on forks or CE
    # Without it the script would fail too.
    - if: "$CUSTOM_SAST_RULES_BOT_PAT == null"
      when: never
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns

.ping-appsec-for-dependency-review:rules:
  rules:
    # Requiring $DEPENDENCY_REVIEW_PAT prevents the bot from running on forks or CE
    # Without it the script would fail too.
    - if: "$ENABLE_DEPSCORE != 'true'"
      when: never
    - if: "$DEPENDENCY_REVIEW_PAT == null"
      when: never
    - <<: *if-fork-merge-request
      when: never
    - <<: *if-not-ee
      when: never
    # Run only when the merge request have dependency file modifications
    - <<: *if-merge-request
      changes: *dependency-patterns

##################
# Releases rules #
##################
.releases:rules:canonical-dot-com-gitlab-stable-branch-only:
  rules:
    - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
      when: never
    - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'

.releases:rules:canonical-dot-com-gitlab-stable-branch-only-setup-test-env:
  rules:
    - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
      when: never
    - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'
      changes: *setup-test-env-patterns

.releases:rules:canonical-dot-com-security-gitlab-stable-branch-only:
  rules:
    - if: '$CI_COMMIT_MESSAGE =~ /\[merge-train skip\]/'
      when: never
    - if: '$CI_SERVER_HOST == "gitlab.com" && $CI_PROJECT_PATH == "gitlab-org/security/gitlab" && $CI_COMMIT_REF_NAME =~ /^[\d-]+-stable-ee$/'

#################
# Reports rules #
#################
.reports:rules:code_quality:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$CODE_QUALITY_DISABLED'
      when: never
    # Run code_quality on master until https://gitlab.com/gitlab-org/gitlab/-/issues/363747 is resolved
    - <<: *if-default-branch-refs
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns
    - <<: *if-default-refs
      changes: *docs-patterns

.reports:rules:brakeman-sast:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: $SAST_DISABLED
      when: never
    - if: $SAST_EXCLUDED_ANALYZERS =~ /brakeman/
      when: never
    - <<: *if-default-refs
      changes:
        - '**/*.rb'
        - '**/Gemfile'

.reports:rules:semgrep-sast:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: $SAST_DISABLED
      when: never
    - if: $SAST_EXCLUDED_ANALYZERS =~ /semgrep/
      when: never
    - <<: *if-default-refs
      changes:
        - '**/*.py'
        - '**/*.js'
        - '**/*.jsx'
        - '**/*.ts'
        - '**/*.tsx'
        - '**/*.c'
        - '**/*.go'
        - '**/*.rb'

.reports:rules:secret_detection:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$SECRET_DETECTION_DISABLED'
      when: never
    # Scan each commit on master to feed the Vulnerability Reports with detected secrets
    - <<: *if-default-branch-refs
    - <<: *if-default-refs
      changes: *code-backstage-qa-patterns

.reports:rules:gemnasium-dependency_scanning:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/'
      when: never
    # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
    - <<: *if-default-branch-refs
    - <<: *if-default-refs
      changes: *dependency-patterns

.reports:rules:gemnasium-python-dependency_scanning:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$DEPENDENCY_SCANNING_DISABLED || $GITLAB_FEATURES !~ /\bdependency_scanning\b/ || $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/'
      when: never
    # Run Dependency Scanning on master until https://gitlab.com/gitlab-org/gitlab/-/issues/361657 is resolved
    - <<: *if-default-branch-refs
    - <<: *if-default-refs
      changes: *python-patterns

.reports:rules:test-dast:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - if: '$DAST_DISABLED || $GITLAB_FEATURES !~ /\bdast\b/'
      when: never
    - <<: *if-merge-request

.reports:rules:package_hunter-yarn:
  rules:
    - if: "$PACKAGE_HUNTER_USER == null || $PACKAGE_HUNTER_USER == ''"
      when: never
    - <<: *if-schedule-maintenance
    - <<: *if-merge-request
      changes: ["yarn.lock"]

.reports:rules:package_hunter-bundler:
  rules:
    - if: "$PACKAGE_HUNTER_USER == null || $PACKAGE_HUNTER_USER == ''"
      when: never
    - <<: *if-schedule-maintenance
    - <<: *if-merge-request
      changes: ["Gemfile.lock"]

.reports:rules:x-ray:
  rules:
    - <<: *if-default-branch-refs
      changes: *dependency-patterns
    - <<: *if-merge-request
      changes: *dependency-patterns
      when: never
    - <<: *if-merge-request
      changes: [".gitlab/ci/reports.gitlab-ci.yml"]
      when: manual
    - when: never

.reports:rules:pajamas_adoption:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-jh
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request
      changes:
        - '{,ee/}app/**/*.{js,vue,rb,haml}'
    - <<: *if-default-branch-refs
      allow_failure: true

################
# Review rules #
################
.review-change-pattern: &review-change-pattern
  APP_CHANGE_TRIGGER: "true"

# The following rules needs to be the same as the one for .review:rules:review-cleanup
# except that:
# - most rules re automatic here (i.e. no `when: manual`) and not allowed to fail (i.e. no `allow_failure: true`) here
# - several rules have `variables: *review-change-pattern` here
.review:rules:start-review-app-pipeline:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-review-app
    - if: '$CI_REVIEW_APPS_ENABLED != "true"'
      when: never
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *ci-review-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *frontend-build-patterns
      variables: *review-change-pattern
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *controllers-patterns
      variables: *review-change-pattern
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *models-patterns
      variables: *review-change-pattern
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *lib-gitlab-patterns
      variables: *review-change-pattern
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *qa-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *code-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-schedule
      allow_failure: true
      variables:
        QA_SAVE_TEST_METRICS: "true"
        QA_EXPORT_TEST_METRICS: "false"  # on main runs, metrics are exported to separate bucket via rake task for better consistency

# The following rules needs to be the same as the one for .review:rules:start-review-app-pipeline
# except that:
# - all rules have `when: manual` and `allow_failure: true` here
.review:rules:review-stop-merge-requests:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-labels-run-review-app
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *ci-review-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *frontend-build-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *controllers-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *models-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *lib-gitlab-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *qa-patterns
      when: manual
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: *code-patterns
      when: manual
      allow_failure: true
.review:rules:review-cleanup:
  rules:
    - !reference [".review:rules:review-stop-merge-requests", rules]
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance
      allow_failure: true

.review:rules:review-stop:
  rules:
    - !reference [".review:rules:review-stop-merge-requests", rules]
    - <<: *if-dot-com-gitlab-org-schedule
      when: manual
      allow_failure: true

.review:rules:review-k8s-resources-count-checks:
  rules:
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - "scripts/review_apps/k8s-resources-count-checks.sh"
      allow_failure: true

.review:rules:review-gcp-quotas-checks:
  rules:
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-merge-request
      changes:
        - "scripts/review_apps/gcp-quotas-checks.rb"
      allow_failure: true

.review:rules:danger:
  rules:
    - <<: *if-merge-request

.review:rules:danger-local:
  rules:
    - <<: *if-merge-request
      changes: *danger-patterns

###############
# Setup rules #
###############
.setup:rules:cache-gems:
  rules:
    - <<: *if-not-canonical-namespace
      when: never
    - <<: *if-default-branch-or-tag
      changes: *code-backstage-qa-patterns
    - <<: *if-dot-com-gitlab-org-merge-request
      changes: [".gitlab/ci/setup.gitlab-ci.yml"]
      when: manual
      allow_failure: true

.setup:rules:dont-interrupt-me:
  rules:
    - <<: *if-default-branch-or-tag
      allow_failure: true
    - <<: *if-schedule-pipeline
      allow_failure: true
    - <<: *if-auto-deploy-branches
      allow_failure: true
    - when: manual
      allow_failure: true

.setup:rules:clone-gitlab-repo:
  rules:
    - if: '$CI_FETCH_REPO_GIT_STRATEGY == "none"'

.setup:rules:gitlab_git_test:
  rules:
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.setup:rules:verify-default-ruby:
  rules:
    - <<: *if-merge-request-labels-run-in-ruby

.setup:rules:verify-tests-yml:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.setup:rules:jh-contribution:
  rules:
    - <<: *if-jh
      when: never
    - <<: *if-merge-request-labels-jh-contribution

.setup:rules:generate-frontend-fixtures-mapping:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance
    - <<: *if-default-branch-refs
      changes:
        - ".gitlab/ci/setup.gitlab-ci.yml"
        - ".gitlab/ci/test-metadata.gitlab-ci.yml"
        - "scripts/rspec_helpers.sh"

###################
# Preflight rules #
###################

.preflight:rules:rails-production-server-boot:
  rules:
    - <<: *if-default-refs
      changes: *code-patterns

.preflight:rules:ruby_syntax:
  rules:
    - <<: *if-default-refs
      changes: *ruby-patterns

.preflight:rules:no-ee-check:
  rules:
    - <<: *if-not-foss
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

.preflight:rules:no-jh-check:
  rules:
    - <<: *if-jh
      when: never
    - <<: *if-default-refs
      changes: *code-backstage-patterns

#######################
# Test metadata rules #
#######################
.test-metadata:rules:retrieve-tests-metadata:
  rules:
    - if: '$ENABLE_RSPEC == "true"'
    - <<: *if-default-refs
      changes: *code-backstage-patterns
    - <<: *if-default-refs
      changes: *workhorse-patterns
    - <<: *if-default-branch-refs
      changes: *setup-test-env-patterns
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-merge-request
      changes: *backend-patterns

.test-metadata:rules:update-tests-metadata:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-dot-com-ee-schedule-default-branch-maintenance
      when: always
    - <<: *if-default-branch-refs
      changes:
        - ".gitlab/ci/test-metadata.gitlab-ci.yml"
        - "scripts/rspec_helpers.sh"
    - <<: *if-merge-request
      changes:
        - "scripts/flaky_examples/prune-old-flaky-examples"

###################
# workhorse rules #
###################
.workhorse:rules:workhorse:
  rules:
    - <<: *if-default-refs
      changes: *workhorse-patterns

###################
# yaml-lint rules #
###################
.yaml-lint:rules:
  rules:
    - <<: *if-default-refs
      changes: *yaml-lint-patterns

.lint-pipeline-yaml:rules:
  rules:
    - <<: *if-default-refs
      changes: *lint-pipeline-yaml-patterns

.lint-metrics-yaml:rules:
  rules:
    - <<: *if-default-refs
      changes: *lint-metrics-yaml-patterns

####################
# as-if-foss rules #
####################

# This is a very big rules set because it's the union of all as-if-foss jobs.
# We want to start this for any FOSS jobs we want to run. For example:
# (This is not an exhaustive list and can be outdated!)
# .build-images:rules:build-qa-image-merge-requests
# .build-images:rules:build-assets-image
# .frontend:rules:compile-production-assets
# .frontend:rules:default-frontend-jobs-as-if-foss
# .rails:rules:single-db
# .rails:rules:single-db-ci-connection
# .rails:rules:single-redis
# .rails:rules:ee-and-foss-default-rules
# .rails:rules:system-default-rules
.as-if-foss:rules:start-as-if-foss:
  rules:
    - if: '$AS_IF_FOSS_TOKEN == null'
      when: never
    - <<: *if-not-merge-request  # This is only designed to run in a merge request
      when: never
    - !reference [".strict-ee-only-rules", rules]
    - <<: *if-merge-request-labels-as-if-foss
    - <<: *if-merge-request-labels-run-all-rspec
    - <<: *if-merge-request-labels-run-all-jest
    - <<: *if-merge-request-labels-run-clusterwide-db
    - <<: *if-merge-request-labels-run-single-db
    - <<: *if-merge-request-labels-run-review-app
    - <<: *if-merge-request-labels-run-all-e2e
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-merge-request-labels-frontend-and-feature-flag
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns
    - <<: *if-merge-request
      changes: *nodejs-patterns
    - <<: *if-merge-request
      changes: *static-analysis-patterns
    - <<: *if-merge-request
      changes: *db-patterns
    - <<: *if-merge-request
      changes: *workhorse-patterns
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns
    - <<: *if-merge-request
      changes: *redis-patterns
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
    - <<: *if-automated-merge-request
      changes: *db-patterns
    - <<: *if-automated-merge-request
      changes: *backend-patterns
    - <<: *if-automated-merge-request
      changes: *code-backstage-patterns
    - <<: *if-security-merge-request
      changes: *backend-patterns
    - <<: *if-security-merge-request
      changes: *code-backstage-qa-patterns
    - <<: *if-security-merge-request
      changes: *db-patterns
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns

.as-if-foss:rules:start-as-if-foss:allow-failure:manual:
  rules:
    - if: '$AS_IF_FOSS_TOKEN == null'
      when: never
    - <<: *if-not-merge-request
      when: never
    - !reference [".strict-ee-only-rules", rules]
    # Copy everything from .as-if-foss:rules:start-as-if-foss
    # and add `allow_failure: true` and `when: manual` to all
    - <<: *if-merge-request-labels-as-if-foss
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-all-rspec
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-all-jest
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-clusterwide-db
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-single-db
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-review-app
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-run-all-e2e
      allow_failure: true
      when: manual
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-merge-request-labels-frontend-and-feature-flag
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *nodejs-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *static-analysis-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *db-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *workhorse-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *redis-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      allow_failure: true
      when: manual
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      allow_failure: true
      when: manual
    - <<: *if-automated-merge-request
      changes: *db-patterns
      allow_failure: true
      when: manual
    - <<: *if-automated-merge-request
      changes: *backend-patterns
      allow_failure: true
      when: manual
    - <<: *if-automated-merge-request
      changes: *code-backstage-patterns
      allow_failure: true
      when: manual
    - <<: *if-security-merge-request
      changes: *backend-patterns
      allow_failure: true
      when: manual
    - <<: *if-security-merge-request
      changes: *code-backstage-qa-patterns
      allow_failure: true
      when: manual
    - <<: *if-security-merge-request
      changes: *db-patterns
      allow_failure: true
      when: manual
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      allow_failure: true
      when: manual

.as-if-foss:rules:start-as-if-foss:allow-failure:
  rules:
    - if: '$AS_IF_FOSS_TOKEN == null'
      when: never
    - <<: *if-not-merge-request
      when: never
    - !reference [".strict-ee-only-rules", rules]
    # Copy everything from .as-if-foss:rules:start-as-if-foss
    # and add `allow_failure: true` to all
    - <<: *if-merge-request-labels-as-if-foss
      allow_failure: true
    - <<: *if-merge-request-labels-run-all-rspec
      allow_failure: true
    - <<: *if-merge-request-labels-run-all-jest
      allow_failure: true
    - <<: *if-merge-request-labels-run-clusterwide-db
      allow_failure: true
    - <<: *if-merge-request-labels-run-single-db
      allow_failure: true
    - <<: *if-merge-request-labels-run-review-app
      allow_failure: true
    - <<: *if-merge-request-labels-run-all-e2e
      allow_failure: true
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - <<: *if-merge-request-not-approved
      when: never
    - <<: *if-merge-request-labels-frontend-and-feature-flag
      allow_failure: true
    - <<: *if-merge-request
      changes: *code-backstage-qa-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *nodejs-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *static-analysis-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *db-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *workhorse-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *decomposed-db-models-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *redis-patterns
      allow_failure: true
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      allow_failure: true
    - <<: *if-merge-request-targeting-stable-branch
      changes: *setup-test-env-patterns
      allow_failure: true
    - <<: *if-automated-merge-request
      changes: *db-patterns
      allow_failure: true
    - <<: *if-automated-merge-request
      changes: *backend-patterns
      allow_failure: true
    - <<: *if-automated-merge-request
      changes: *code-backstage-patterns
      allow_failure: true
    - <<: *if-security-merge-request
      changes: *backend-patterns
      allow_failure: true
    - <<: *if-security-merge-request
      changes: *code-backstage-qa-patterns
      allow_failure: true
    - <<: *if-security-merge-request
      changes: *db-patterns
      allow_failure: true
    - <<: *if-dot-com-gitlab-org-and-security-merge-request-manual-ff-package-and-e2e
      changes: *feature-flag-development-config-patterns
      allow_failure: true

##################
# as-if-jh rules #
##################
.as-if-jh:rules:prepare-as-if-jh:
  rules:
    - <<: *if-merge-request-labels-as-if-jh
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns

# This rule should share the same logic with .as-if-jh:rules:prepare-as-if-jh
# in additionally that there are changes in dependency-patterns
# Unfortunately, we can't say it has changes in
#     feature-flag-development-config-patterns
# And in
#     dependency-patterns
# At the same time. Note that this can't be using OR so using a union pattern
# doesn't work either. Given that we cannot specify this, there's a gap can
# happen when:
#     * The merge request does not have ~"pipeline:run-as-if-jh"
#     * The merge request changes a feature flag
#     * The merge request also changes dependencies
# In this case, we expect that we do run `sync-as-if-jh-branch` but it won't,
# meaning that dependencies in the JH validation pipeline will be outdated.
# To work around this issue, apply ~"pipeline:run-as-if-jh" to the merge
# request so we can force it to run `sync-as-if-jh-branch` when there are
# dependencies changes.
.as-if-jh:rules:sync-as-if-jh:
  rules:
    - <<: *if-merge-request-labels-as-if-jh
      changes: *dependency-patterns
      # Ideally, we should be able to do this:
      # - <<: *if-dot-com-gitlab-org-merge-request
      #   changes: *feature-flag-development-config-patterns && *dependency-patterns

# This rule should share the same logic with .as-if-jh:rules:prepare-as-if-jh
# Because the jobs using this need jobs using the preparation rules
.as-if-jh:rules:start-as-if-jh:
  rules:
    - <<: *if-merge-request-labels-as-if-jh
      allow_failure: true  # See https://gitlab.com/gitlab-org/gitlab/-/issues/351136
    - <<: *if-merge-request
      changes: *feature-flag-development-config-patterns
      allow_failure: true  # See https://gitlab.com/gitlab-org/gitlab/-/issues/351136

##############################
# release-environments rules #
##############################
.release-environments:rules:start-release-environments-pipeline:
  rules:
    - <<: *if-not-ee
      when: never
    - <<: *if-merge-request-labels-pipeline-expedite
      when: never
    - !reference [".releases:rules:canonical-dot-com-gitlab-stable-branch-only-setup-test-env", rules]

###################
# Benchmark rules #
###################
.benchmark:rules:benchmark-markdown:
  rules:
    - <<: *if-default-refs
      changes: *setup-test-env-patterns
      when: manual
    - <<: *if-merge-request-labels-run-all-rspec
      when: manual

###############################
# Observability Backend rules #
###############################
.observability-backend:rules:
  rules:
    - <<: *if-merge-request
      changes: *code-patterns
      when: manual
      allow_failure: true
    - <<: *if-merge-request
      changes: *ci-patterns
      when: manual
      allow_failure: true