Skip to content
Snippets Groups Projects
Unverified Commit cc000b48 authored by Timo Furrer's avatar Timo Furrer
Browse files

Support running pipeline templates directly in child pipeline with...

Support running pipeline templates directly in child pipeline with `trigger_in_child_pipeline` input

This change set allows a user of this component to directly execute a
pipeline template in its own child pipeline. This is useful to run
dedicated child pipeline for multiple environments.

Changelog: added
parent 3f22d1f6
No related branches found
No related tags found
No related merge requests found
......@@ -44,6 +44,17 @@ include:
opentofu_version: <OPENTOFU_VERSION>
stages: [validate, build, deploy]
# ... or in a child pipeline:
include:
- component: $CI_SERVER_FQDN/components/opentofu/validate-plan-apply@<VERSION>
inputs:
# The version must currently be specified explicitly as an input,
# to find the correctly associated images. # This can be removed
# once https://gitlab.com/gitlab-org/gitlab/-/issues/438275 is solved.
version: <VERSION> # component version
opentofu_version: <OPENTOFU_VERSION>
trigger_in_child_pipeline: true
```
A concrete example may look like this:
......@@ -158,6 +169,10 @@ but no destructive actions.
- [`validate-plan-apply`](templates/validate-plan-apply.yml)
- [`validate-plan-destroy`](templates/validate-plan-destroy.yml)
These templates support the `trigger_in_child_pipeline` input which will
include the component but run all its job in a child pipeline. This may be useful in cases
where you want to run dedicated child pipeline for each of your environments.
### Job Templates
Instead of including the `full-pipeline` or another opinionated template,
......
......@@ -46,6 +46,17 @@ include:
opentofu_version: <OPENTOFU_VERSION>
stages: [validate, build, deploy]
# ... or in a child pipeline:
include:
- component: $CI_SERVER_FQDN/components/opentofu/validate-plan-apply@<VERSION>
inputs:
# The version must currently be specified explicitly as an input,
# to find the correctly associated images. # This can be removed
# once https://gitlab.com/gitlab-org/gitlab/-/issues/438275 is solved.
version: <VERSION> # component version
opentofu_version: <OPENTOFU_VERSION>
trigger_in_child_pipeline: true
```
A concrete example may look like this:
......@@ -160,6 +171,10 @@ but no destructive actions.
- [`validate-plan-apply`](templates/validate-plan-apply.yml)
- [`validate-plan-destroy`](templates/validate-plan-destroy.yml)
These templates support the `trigger_in_child_pipeline` input which will
include the component but run all its job in a child pipeline. This may be useful in cases
where you want to run dedicated child pipeline for each of your environments.
### Job Templates
Instead of including the `full-pipeline` or another opinionated template,
......
......@@ -159,11 +159,25 @@ spec:
default: false
type: boolean
description: 'Whether to mark the job with a warning if the plan contains a diff.'
trigger_in_child_pipeline:
default: false
type: boolean
description: 'Whether to run all the jobs in a child pipeline.'
child_pipeline_name:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the name of the child pipeline bridge job.'
child_pipeline_stage:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the stage of the child pipeline bridge job.'
---
include:
- local: '/templates/fmt.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]fmt'
stage: $[[ inputs.stage_validate ]]
......@@ -177,6 +191,8 @@ include:
needs: []
rules: $[[ inputs.fmt_rules ]]
- local: '/templates/validate.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]validate'
stage: $[[ inputs.stage_validate ]]
......@@ -191,6 +207,11 @@ include:
var_file: $[[ inputs.var_file ]]
rules: $[[ inputs.validate_rules ]]
- local: '/templates/test.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
when: never
- exists:
- $[[ inputs.root_dir ]]/**/*.tftest.hcl
inputs:
as: '$[[ inputs.job_name_prefix ]]test'
stage: $[[ inputs.stage_test ]]
......@@ -205,10 +226,9 @@ include:
var_file: $[[ inputs.var_file ]]
needs: []
rules: $[[ inputs.test_rules ]]
rules:
- exists:
- $[[ inputs.root_dir ]]/**/*.tftest.hcl
- local: '/templates/plan.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]plan'
stage: $[[ inputs.stage_build ]]
......@@ -226,6 +246,8 @@ include:
rules: $[[ inputs.plan_rules ]]
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
- local: '/templates/apply.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]apply'
stage: $[[ inputs.stage_deploy ]]
......@@ -241,6 +263,8 @@ include:
var_file: $[[ inputs.var_file ]]
rules: $[[ inputs.apply_rules ]]
- local: '/templates/destroy.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]destroy'
stage: $[[ inputs.stage_cleanup ]]
......@@ -255,6 +279,8 @@ include:
var_file: $[[ inputs.var_file ]]
rules: $[[ inputs.destroy_rules ]]
- local: '/templates/delete-state.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]delete-state'
stage: $[[ inputs.stage_cleanup ]]
......@@ -267,3 +293,58 @@ include:
# https://gitlab.com/gitlab-org/gitlab/-/issues/440468
'$[[ inputs.job_name_prefix ]]delete-state':
needs: ['$[[ inputs.job_name_prefix ]]destroy']
# NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
stages:
- $[[ inputs.stage_validate ]]
- $[[ inputs.stage_build ]]
- $[[ inputs.stage_deploy ]]
- $[[ inputs.stage_cleanup ]]
- $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:true':
stage: $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:false':
# NOTE: this is a hack for the bridge job below to have a valid stage even if it isn't used.
# The thing is that the stage needs to be defined even if the job is "ruled" out and not created.
# The .pre stage always exists.
stage: .pre
'$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]':
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
extends: '.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:$[[ inputs.trigger_in_child_pipeline ]]'
trigger:
include:
- local: /templates/validate-plan-apply.yml
inputs:
stage_validate: $[[ inputs.stage_validate ]]
stage_build: $[[ inputs.stage_build ]]
stage_deploy: $[[ inputs.stage_deploy ]]
stage_cleanup: $[[ inputs.stage_cleanup ]]
version: $[[ inputs.version ]]
base_os: $[[ inputs.base_os ]]
opentofu_version: $[[ inputs.opentofu_version ]]
image_registry_base: $[[ inputs.image_registry_base ]]
image_name: $[[ inputs.image_name]]
image_digest: $[[ inputs.image_digest]]
job_name_prefix: $[[ inputs.job_name_prefix]]
root_dir: $[[ inputs.root_dir]]
state_name: $[[ inputs.state_name]]
plan_name: $[[ inputs.plan_name ]]
plan_artifacts_access: $[[ inputs.plan_artifacts_access ]]
var_file: $[[ inputs.var_file ]]
fmt_rules: $[[ inputs.fmt_rules ]]
validate_rules: $[[ inputs.validate_rules ]]
plan_rules: $[[ inputs.plan_rules ]]
apply_rules: $[[ inputs.apply_rules ]]
destroy_rules: $[[ inputs.destroy_rules ]]
delete_state_rules: $[[ inputs.delete_state_rules ]]
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
trigger_in_child_pipeline: false
forward:
yaml_variables: true
pipeline_variables: true
strategy: depend
......@@ -126,11 +126,25 @@ spec:
default: false
type: boolean
description: 'Whether to mark the job with a warning if the plan contains a diff.'
trigger_in_child_pipeline:
default: false
type: boolean
description: 'Whether to run all the jobs in a child pipeline.'
child_pipeline_name:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the name of the child pipeline bridge job.'
child_pipeline_stage:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the stage of the child pipeline bridge job.'
---
include:
- local: '/templates/fmt.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]fmt'
stage: $[[ inputs.stage_validate ]]
......@@ -144,6 +158,8 @@ include:
needs: []
rules: $[[ inputs.fmt_rules ]]
- local: '/templates/validate.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]validate'
stage: $[[ inputs.stage_validate ]]
......@@ -159,6 +175,8 @@ include:
rules: $[[ inputs.validate_rules ]]
cache_policy: pull-push
- local: '/templates/plan.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]plan'
stage: $[[ inputs.stage_build ]]
......@@ -177,6 +195,8 @@ include:
cache_policy: pull
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
- local: '/templates/apply.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]apply'
stage: $[[ inputs.stage_deploy ]]
......@@ -192,3 +212,54 @@ include:
var_file: $[[ inputs.var_file ]]
rules: $[[ inputs.apply_rules ]]
cache_policy: pull
# NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
stages:
- $[[ inputs.stage_validate ]]
- $[[ inputs.stage_build ]]
- $[[ inputs.stage_deploy ]]
- $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:true':
stage: $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:false':
# NOTE: this is a hack for the bridge job below to have a valid stage even if it isn't used.
# The thing is that the stage needs to be defined even if the job is "ruled" out and not created.
# The .pre stage always exists.
stage: .pre
'$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]':
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
extends: '.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:$[[ inputs.trigger_in_child_pipeline ]]'
trigger:
include:
- local: /templates/validate-plan-apply.yml
inputs:
stage_validate: $[[ inputs.stage_validate ]]
stage_build: $[[ inputs.stage_build ]]
stage_deploy: $[[ inputs.stage_deploy ]]
version: $[[ inputs.version ]]
base_os: $[[ inputs.base_os ]]
opentofu_version: $[[ inputs.opentofu_version ]]
image_registry_base: $[[ inputs.image_registry_base ]]
image_name: $[[ inputs.image_name]]
image_digest: $[[ inputs.image_digest]]
job_name_prefix: $[[ inputs.job_name_prefix]]
root_dir: $[[ inputs.root_dir]]
state_name: $[[ inputs.state_name]]
plan_name: $[[ inputs.plan_name ]]
plan_artifacts_access: $[[ inputs.plan_artifacts_access ]]
var_file: $[[ inputs.var_file ]]
fmt_rules: $[[ inputs.fmt_rules ]]
validate_rules: $[[ inputs.validate_rules ]]
plan_rules: $[[ inputs.plan_rules ]]
apply_rules: $[[ inputs.apply_rules ]]
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
trigger_in_child_pipeline: false
forward:
yaml_variables: true
pipeline_variables: true
strategy: depend
......@@ -132,11 +132,25 @@ spec:
default: false
type: boolean
description: 'Whether to mark the job with a warning if the plan contains a diff.'
trigger_in_child_pipeline:
default: false
type: boolean
description: 'Whether to run all the jobs in a child pipeline.'
child_pipeline_name:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the name of the child pipeline bridge job.'
child_pipeline_stage:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the stage of the child pipeline bridge job.'
---
include:
- local: '/templates/fmt.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]fmt'
stage: $[[ inputs.stage_validate ]]
......@@ -150,6 +164,8 @@ include:
needs: []
rules: $[[ inputs.fmt_rules ]]
- local: '/templates/validate.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]validate'
stage: $[[ inputs.stage_validate ]]
......@@ -165,6 +181,8 @@ include:
rules: $[[ inputs.validate_rules ]]
cache_policy: pull-push
- local: '/templates/plan.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]plan'
stage: $[[ inputs.stage_build ]]
......@@ -184,6 +202,8 @@ include:
cache_policy: pull
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
- local: '/templates/destroy.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]destroy'
stage: $[[ inputs.stage_cleanup ]]
......@@ -201,6 +221,8 @@ include:
rules: $[[ inputs.destroy_rules ]]
cache_policy: pull
- local: '/templates/delete-state.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]delete-state'
stage: $[[ inputs.stage_cleanup ]]
......@@ -213,3 +235,55 @@ include:
# https://gitlab.com/gitlab-org/gitlab/-/issues/440468
'$[[ inputs.job_name_prefix ]]delete-state':
needs: ['$[[ inputs.job_name_prefix ]]destroy']
# NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
stages:
- $[[ inputs.stage_validate ]]
- $[[ inputs.stage_build ]]
- $[[ inputs.stage_cleanup ]]
- $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:true':
stage: $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:false':
# NOTE: this is a hack for the bridge job below to have a valid stage even if it isn't used.
# The thing is that the stage needs to be defined even if the job is "ruled" out and not created.
# The .pre stage always exists.
stage: .pre
'$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]':
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
extends: '.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:$[[ inputs.trigger_in_child_pipeline ]]'
trigger:
include:
- local: /templates/validate-plan-destroy.yml
inputs:
stage_validate: $[[ inputs.stage_validate ]]
stage_build: $[[ inputs.stage_build ]]
stage_cleanup: $[[ inputs.stage_cleanup ]]
version: $[[ inputs.version ]]
base_os: $[[ inputs.base_os ]]
opentofu_version: $[[ inputs.opentofu_version ]]
image_registry_base: $[[ inputs.image_registry_base ]]
image_name: $[[ inputs.image_name]]
image_digest: $[[ inputs.image_digest]]
job_name_prefix: $[[ inputs.job_name_prefix]]
root_dir: $[[ inputs.root_dir]]
state_name: $[[ inputs.state_name]]
plan_name: $[[ inputs.plan_name ]]
plan_artifacts_access: $[[ inputs.plan_artifacts_access ]]
var_file: $[[ inputs.var_file ]]
fmt_rules: $[[ inputs.fmt_rules ]]
validate_rules: $[[ inputs.validate_rules ]]
plan_rules: $[[ inputs.plan_rules ]]
destroy_rules: $[[ inputs.destroy_rules ]]
delete_state_rules: $[[ inputs.delete_state_rules ]]
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
trigger_in_child_pipeline: false
forward:
yaml_variables: true
pipeline_variables: true
strategy: depend
......@@ -110,11 +110,25 @@ spec:
default: false
type: boolean
description: 'Whether to mark the job with a warning if the plan contains a diff.'
trigger_in_child_pipeline:
default: false
type: boolean
description: 'Whether to run all the jobs in a child pipeline.'
child_pipeline_name:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the name of the child pipeline bridge job.'
child_pipeline_stage:
default: opentofu
type: string
description: 'If `trigger_in_child_pipeline` is `true` then this defines the stage of the child pipeline bridge job.'
---
include:
- local: '/templates/fmt.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]fmt'
stage: $[[ inputs.stage_validate ]]
......@@ -128,6 +142,8 @@ include:
needs: []
rules: $[[ inputs.fmt_rules ]]
- local: '/templates/validate.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]validate'
stage: $[[ inputs.stage_validate ]]
......@@ -143,6 +159,8 @@ include:
rules: $[[ inputs.validate_rules ]]
cache_policy: pull-push
- local: '/templates/plan.yml'
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "false"'
inputs:
as: '$[[ inputs.job_name_prefix ]]plan'
stage: $[[ inputs.stage_build ]]
......@@ -160,3 +178,51 @@ include:
rules: $[[ inputs.plan_rules ]]
cache_policy: pull
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
# NOTE: the following configuration is only used if `trigger_in_child_pipeline` is enabled.
stages:
- $[[ inputs.stage_validate ]]
- $[[ inputs.stage_build ]]
- $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:true':
stage: $[[ inputs.child_pipeline_stage ]]
'.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:false':
# NOTE: this is a hack for the bridge job below to have a valid stage even if it isn't used.
# The thing is that the stage needs to be defined even if the job is "ruled" out and not created.
# The .pre stage always exists.
stage: .pre
'$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]':
rules:
- if: '"$[[ inputs.trigger_in_child_pipeline ]]" == "true"'
extends: '.$[[ inputs.job_name_prefix ]]$[[ inputs.child_pipeline_name ]]:bridge_job_stage:$[[ inputs.trigger_in_child_pipeline ]]'
trigger:
include:
- local: /templates/validate-plan.yml
inputs:
stage_validate: $[[ inputs.stage_validate ]]
stage_build: $[[ inputs.stage_build ]]
version: $[[ inputs.version ]]
base_os: $[[ inputs.base_os ]]
opentofu_version: $[[ inputs.opentofu_version ]]
image_registry_base: $[[ inputs.image_registry_base ]]
image_name: $[[ inputs.image_name]]
image_digest: $[[ inputs.image_digest]]
job_name_prefix: $[[ inputs.job_name_prefix]]
root_dir: $[[ inputs.root_dir]]
state_name: $[[ inputs.state_name]]
plan_name: $[[ inputs.plan_name ]]
artifacts_access: $[[ inputs.artifacts_access ]]
var_file: $[[ inputs.var_file ]]
fmt_rules: $[[ inputs.fmt_rules ]]
validate_rules: $[[ inputs.validate_rules ]]
plan_rules: $[[ inputs.plan_rules ]]
warning_on_non_empty_plan: $[[ inputs.warning_on_non_empty_plan ]]
trigger_in_child_pipeline: false
forward:
yaml_variables: true
pipeline_variables: true
strategy: depend
include:
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/validate-plan-apply@$CI_COMMIT_SHA
inputs:
image_registry_base: $GITLAB_OPENTOFU_IMAGE_BASE
version: $CI_COMMIT_SHA
base_os: $GITLAB_OPENTOFU_BASE_IMAGE_OS
opentofu_version: $OPENTOFU_VERSION
root_dir: $TEST_TF_ROOT
state_name: $TEST_TF_STATE_NAME
fmt_rules: [{when: on_success}]
validate_rules: [{when: on_success}]
plan_rules: [{when: on_success}]
apply_rules: [{when: on_success}]
trigger_in_child_pipeline: true
child_pipeline_name: test-pipeline
child_pipeline_stage: test
# For CI Terraform state cleanup
- component: $CI_SERVER_FQDN/$CI_PROJECT_PATH/delete-state@$CI_COMMIT_SHA
inputs:
stage: cleanup
state_name: $TEST_TF_STATE_NAME
rules: [{when: always}]
stages: [test, cleanup]
......@@ -17,6 +17,7 @@ component:
- Destroy
- VarFile
- WarningOnNonEmptyPlan
- TriggerInChildPipeline
GITLAB_OPENTOFU_BASE_IMAGE_OS:
- alpine
- debian
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment