Как объединить несколько правил GitLab с And?

Согласно документации, с операцией OR сочетаются несколько правил, и она действительно ведет себя именно так. Но у меня конкретная ситуация.

Итак, у меня есть набор заданий, которые используются для PCF платформы, и еще один набор для Kubernetes платформы. Они управляются просто путем установки переменных. И возможно, что нам может понадобиться, чтобы оба были активны:

.pcf-platform:
  rules:
    - if: $PLATFORM_PCF == "true"

.k8s-platform:
  rules:
    - if: $PLATFORM_K8S == "true"

.manual-feature-branch-optional:
  rules:
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "schedule" && $CI_PIPELINE_SOURCE != "merge_request_event"
      when: manual
      allow_failure: true

.manual-default-branch-optional:
  rules:
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "schedule"
      when: manual
      allow_failure: true

Теперь представьте, что у нас есть эти рабочие места:


deploy-dev-pcf:
  extends:
    - .manual-feature-branch-optional
    - .pcf-platform
  script:
    - do deploy

deploy-dev-k8s:
  extends:
    - .manual-feature-branch-optional
    - .k8s-platform
  script:
    - do deploy

deploy-prod-pcf:
  extends:
    - .manual-default-branch-optional
    - .pcf-platform
  script:
    - do deploy
  

Теперь представьте, что и PLATFORM_K8S, и PLATFORM_PCF установлены на true, а текущая ветвь является функциональной ветвью (не по умолчанию); как и ожидалось, оба deploy-dev-pcf и deploy-dev-k8s добавляются в конвейер, но так, как deploy-prod-pcf.

Кажется, что первое правило, которое проверяет if the current branch is default branch, разрешается в false, но затем оно оценивает следующее правило, которое проверяет PLATFORM_PCF equals to true, и, поскольку оно верно, оно добавляет задание, пока мы все еще находимся в функциональной ветке.

Мне нужно каким-то образом сделать эти два отдельных правила And-ed, чтобы я мог включать/выключать задания в зависимости от желаемой платформы, а также типа ветки.

Я мог бы создать один набор правил для Kubernetes и один набор для PCF, но это необоснованно увеличивает количество правил, и я против такого подхода.

В документации говорится, что предложения only оцениваются с помощью And, но, похоже, only устаревает в пользу rules.

Как я могу этого добиться?

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
0
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы понять это правильно, вам нужно понять:

  • Как рабочие места объединяются вместе; и
  • Как оцениваются правила

Или вы можете просто перейти к последнему заголовку вашего ответа :-)

Как рабочие места объединяются вместе

Часть вашей проблемы здесь, похоже, заключается в ваших ожиданиях того, что extends: делает в этом случае. Когда значения массива встречаются через extends:, они перекрывают друг друга и не объединяются. См. сведения о слиянии для дополнительного контекста.

Например, при такой конфигурации:

.foo:
  rules:
    - if: $FOO == "foo"

.bar:
  rules:
    - if: $BAR == "bar"
job:
  extends:
    - foo
    - bar  # array of rules here will override the previous declarations
  

Другими словами, в результирующей конфигурации в этом случае будет действовать только один набор этих правил, как если бы они были написаны так:

job:
  rules:
    - if: $BAR == "bar"

Итак, в вашем примере применяется только правило платформы, что приводит к поведению, которое вы наблюдаете.

Один из способов обойти это — использовать !reference вместо создания массива правил:

rules:
  - !reference [.foo, rules]
  - !reference [.bar, rules]

Как оцениваются правила

Еще один аспект, требующий понимания, — это то, как оцениваются правила. GitLab будет оценивать каждое правило по порядку и остановится на первом правиле, которое оценивается как истинное. Может быть максимум одно правило, которое вступит в силу! Если никакие правила не совпадают, задание исключается из конвейера.

Итак, есть несколько способов получить эффект оценки AND.

Вы можете объединить его в одно правило и комбинировать с операторами &&:

rules:
  - if: $FOO == "foo" && $BAR == "bar"

Вы также можете получить желаемый эффект, расположив различные правила в определенном порядке и используя обратную логику в сочетании с when: never. Например, эти правила имеют тот же эффект, что и выше:

rules:
  - if: $FOO != "foo"
    when: never
  - if: $BAR != "bar"
    when: never
  - when: on_success  # base case is important!

Инвертируя логику здесь (проверяя != вместо ==), мы позволяем оценке продолжаться по последующим правилам. Это важно, если вы хотите определить и повторно использовать правила по отдельности.

На практике

Применяя понимание, объясненное выше, используя ваш пример, вы можете сделать что-то вроде этого, что позволит вам определить каждое правило только один раз:


# define different sets of rules
.rules:
  pcf-only:
    - if: $PCF_PLATFORM != "true"
      when: never
  k8s-only:
    - if: $K8S_PLATFORM != "true"
      when: never
  manual-feature-branch-optional:
    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH && $CI_PIPELINE_SOURCE != "schedule" && $CI_PIPELINE_SOURCE != "merge_request_event"
      when: manual
      allow_failure: true

# Combine these rules in different ways that can be reused
.k8s-deploy:
  rules: # Order matters!
    - !reference [.rules, k8s-only]
    - !reference [.rules, manual-feature-branch-optional]

.pcf-deploy:
  rules:
    - !reference [.rules, pcf-only]
    - !reference [.rules, manual-feature-branch-optional]

# Use `extends:` for each combination of rules as-needed
deploy-dev-pcf:
  extends:
    - .pcf-deploy  
  script:
    - do deploy

# alternatively, you can define rules directly instead of using `extends:`
deploy-dev-k8s:
  rules:
    - !reference [.rules, k8s-only]
    - !reference [.rules, manual-feature-branch-optional]
  script:
    - do deploy

# ... and so on

Здесь, вероятно, есть и другие возможности рефакторинга для вас, но это, возможно, не по существу вопроса :)

Огромное спасибо! Я реализую это и посмотрю, как оно пойдет, но мне также интересно узнать, какой другой рефакторинг вы предлагаете.

xbmono 21.04.2023 02:11

Отлично ... протестировал и сработало. Ваше объяснение того, как работает оценка, очень помогло, так как мне нужно было внести дополнительные коррективы. Я просматривал документацию GitLab, они очень краткие и не объясняют, что именно происходит. Еще раз спасибо, и я признателен, если у вас есть еще какие-либо точки рефакторинга для моего подхода.

xbmono 21.04.2023 06:32

@xbmono, что касается других возможностей для рефакторинга, в основном я думал, что вы сможете сориентировать все в матрицу с двумя измерениями: платформа и среда (например, pcf/k8s и dev/production). Но я полагаю, это зависит от деталей ваших сценариев и от того, что именно вы хотите. Возможно, вы также могли бы избежать повторения одного и того же script: (при условии, что это на самом деле одно и то же или может быть одинаковым для каждой работы).

sytech 22.04.2023 03:06

Другие вопросы по теме