diff --git a/.gitlab/README.md.template b/.gitlab/README.md.template
index d48a45ed6c3d34848156d0cdf54f763bb1372191..1930a95804013198858b1b159fafddd224b71fad 100644
--- a/.gitlab/README.md.template
+++ b/.gitlab/README.md.template
@@ -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,
diff --git a/README.md b/README.md
index 11e74bb8dd06b5ad5dffc2f99f7ac5941eaca90b..9a43bc784e874322ccbd70efdb262b186c0eaaaa 100644
--- a/README.md
+++ b/README.md
@@ -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,
diff --git a/templates/full-pipeline.yml b/templates/full-pipeline.yml
index 314697194497cff351f5ea1c4a8b0af9abfef01f..3baa72fd4438fc6103bf37a1d41f1327ddb4c610 100644
--- a/templates/full-pipeline.yml
+++ b/templates/full-pipeline.yml
@@ -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
diff --git a/templates/validate-plan-apply.yml b/templates/validate-plan-apply.yml
index 555574ecff6b6ce6f3e0eef6700b94274f0bab2e..05dfc7a60b7a4b9e2cd438bc60992dc0767c8ede 100644
--- a/templates/validate-plan-apply.yml
+++ b/templates/validate-plan-apply.yml
@@ -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
diff --git a/templates/validate-plan-destroy.yml b/templates/validate-plan-destroy.yml
index 40cde9ba70ef2f88a2d172bdee45906c3a6c6a47..1c9281a2daf22766d1f9e7818b867bcbdcd3ccc6 100644
--- a/templates/validate-plan-destroy.yml
+++ b/templates/validate-plan-destroy.yml
@@ -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
diff --git a/templates/validate-plan.yml b/templates/validate-plan.yml
index ecf271a83523fc936318721223bc63ba23a7b6ed..238fa182e28570c385e2a1c04c3a648d7cea72f3 100644
--- a/templates/validate-plan.yml
+++ b/templates/validate-plan.yml
@@ -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
diff --git a/tests/integration-tests/TriggerInChildPipeline.gitlab-ci.yml b/tests/integration-tests/TriggerInChildPipeline.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d1fd3cf410b40189a8d5d9431e0c6743490d8671
--- /dev/null
+++ b/tests/integration-tests/TriggerInChildPipeline.gitlab-ci.yml
@@ -0,0 +1,25 @@
+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]
diff --git a/tests/integration.gitlab-ci.yml b/tests/integration.gitlab-ci.yml
index 0ab3012b403e9fd5da57ceb087ccbf99259aded1..83ee35c5ea39cbdaa64eb8c469108020eac580db 100644
--- a/tests/integration.gitlab-ci.yml
+++ b/tests/integration.gitlab-ci.yml
@@ -17,6 +17,7 @@ component:
           - Destroy
           - VarFile
           - WarningOnNonEmptyPlan
+          - TriggerInChildPipeline
         GITLAB_OPENTOFU_BASE_IMAGE_OS:
           - alpine
           - debian