Я пытаюсь создать CI для кода Terraform.
Первое задание — это линтер, который должен запускаться только в том случае, если файлы Terraform были изменены.
test_lint:
stage: lint
script:
- |
cd xxx
terraform init
terraform fmt -check -recursive -diff
terraform validate
rules:
- if: '$CI_COMMIT_BRANCH'
changes:
compare_to: 'refs/heads/main'
paths:
- 'projects/xxx/*'
- 'xxx/*'
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
Если файлы не были изменены, мне не нужно запускать второе задание с помощью terraform plan
и третье задание с помощью terraform apply
.
test_plan:
stage: plan
script:
- |
cd xxx
terraform init
terraform plan -out=$PLAN -parallelism=30
terraform show --json $PLAN | convert_report > $PLAN_JSON
artifacts:
paths:
- xxx/$PLAN
reports:
terraform: xxx/$PLAN_JSON
resource_group: terraform-state
test_apply:
stage: apply
script:
- |
cd xxx
terraform apply $PLAN
rules:
- if: '$CI_COMMIT_REF_NAME == "main"' ### Apply only after merging
resource_group: terraform-state
Как я могу пропустить план и применить задания, если первое задание не было добавлено в конвейер? Мои настройки MR не позволяют выполнить слияние, если ни один конвейер не прошел, поэтому мне нужно дополнительное фиктивное задание, которое запускается только тогда, когда эти три задания пропускаются или вообще не добавляются в конвейер? после MR мне не нужно запускать пустую работу
Я пытался использовать правила, например, в планировании задания.
rules:
- if: '$CI_JOB_STATUS == "success" && $CI_JOB_STAGE == "lint"' # here i mean previous job
when: never
но это не работает
Может быть, мне просто нужно взять названия предыдущей работы и добавить их в правило для следующей работы с «когда: никогда»
Как
rules:
- if: $PREVIOUS JOB (or STAGE) = not created
when: never
Я думал, что есть еще какие-нибудь изящные методы, позволяющие сделать это без повторения кода в каждом задании. И еще проблема - как запустить (если пропускаются первые три задания) и не запускать (если будут применены первые три этапа) фиктивное успешное задание только для того, чтобы разрешить слияние (да, это похоже на другой вопрос ((
Основываясь на вашем комментарии и вашем запросе на решение, которое не дублирует код, я бы предложил вам использовать шаблон для необходимого правила:
.only_on_changes: &only_on_changes
if: '$CI_COMMIT_BRANCH'
changes:
compare_to: 'refs/heads/main'
paths:
- 'projects/xxx/*'
- 'xxx/*'
test_lint:
stage: lint
script:
- |
cd xxx
terraform init
terraform fmt -check -recursive -diff
terraform validate
rules:
- *only_on_changes
- if: $CI_PIPELINE_SOURCE != "merge_request_event"
when: never
test_plan:
stage: plan
script:
- |
cd xxx
terraform init
terraform plan -out=$PLAN -parallelism=30
terraform show --json $PLAN | convert_report > $PLAN_JSON
artifacts:
paths:
- xxx/$PLAN
reports:
terraform: xxx/$PLAN_JSON
rules:
- *only_on_changes
resource_group: terraform-state
test_apply:
stage: apply
script:
- |
cd xxx
terraform apply $PLAN
rules:
- *only_on_changes
- if: '$CI_COMMIT_REF_NAME == "main"' ### Apply only after merging
resource_group: terraform-state
Если вам нужно другое задание, которое будет выполняться только тогда, когда предыдущее правило не применяется, вы можете отменить его и добавить к своему фиктивному заданию:
.only_on_no_changes: &only_on_no_changes
if: '$CI_COMMIT_BRANCH'
changes:
compare_to: 'refs/heads/main'
paths:
- 'projects/xxx/*'
- 'xxx/*'
when: never
dummy_job:
stage: apply
script:
- echo "Dummy Job"
rules:
- *only_on_no_changes
- when: always
Спасибо! Это очень интересно, я никогда не использовал якоря. Но могу ли я параметризовать пути? Поскольку мне нужно выполнить terraform для 5 проектов в монорепо, у меня есть 5 каталогов, в которых я должен отслеживать изменения ``` Rules: - *only_on_changes[paths: yyy] Rules: - *only_on_changes[paths: zzz] ``` it будет очень хорошо, но я не уверен, как мне это сделать
Это невозможно, насколько я знаю
У вас уже есть рабочее правило для
lint
. Разве вы не можете использовать одно и то же правило дляplan
иapply
?