From 3981652611bf1d9672deff2f7f3c9848d49dd32d Mon Sep 17 00:00:00 2001
From: Timo Furrer <tfurrer@gitlab.com>
Date: Fri, 12 Jul 2024 13:27:38 +0200
Subject: [PATCH] Refactor rules in all jobs

---
 templates/apply.yml                 | 11 +++++++----
 templates/custom-command.yml        |  6 ++++++
 templates/delete-state.yml          |  8 +++++---
 templates/destroy.yml               |  8 +++++---
 templates/fmt.yml                   | 11 +++++------
 templates/full-pipeline.yml         | 29 +++++++++++++++++++++++++++++
 templates/module-release.yml        |  6 ++++++
 templates/plan.yml                  | 10 +++++-----
 templates/test.yml                  | 10 +++++-----
 templates/validate-plan-apply.yml   | 18 ++++++++++++++++++
 templates/validate-plan-destroy.yml | 21 +++++++++++++++++++++
 templates/validate-plan.yml         | 15 +++++++++++++++
 templates/validate.yml              | 10 +++++-----
 13 files changed, 132 insertions(+), 31 deletions(-)

diff --git a/templates/apply.yml b/templates/apply.yml
index 882a907..7753179 100644
--- a/templates/apply.yml
+++ b/templates/apply.yml
@@ -62,7 +62,11 @@ spec:
     auto_apply:
       default: false
       type: boolean
-      description: 'Whether the apply job is manual or automatically run.'
+      description: 'Whether the apply job is manual or automatically run. Prepend to the `rules` input array.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
@@ -73,9 +77,8 @@ spec:
     action: start
   resource_group: $TF_STATE_NAME
   rules:
-    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && "$[[ inputs.auto_apply ]]" == "true"'
-    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-      when: manual
+    - if: '"[[ inputs.auto_apply ]]" == "true"'
+    - $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
diff --git a/templates/custom-command.yml b/templates/custom-command.yml
index 5ab2f61..11e2a3e 100644
--- a/templates/custom-command.yml
+++ b/templates/custom-command.yml
@@ -53,11 +53,17 @@ spec:
     command:
       description: 'The gitlab-tofu command to run.'
 
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
+
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
   needs: []
+  rules: $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
diff --git a/templates/delete-state.yml b/templates/delete-state.yml
index 9a499ea..a586a5a 100644
--- a/templates/delete-state.yml
+++ b/templates/delete-state.yml
@@ -15,17 +15,19 @@ spec:
     create_delete_state_job:
       default: 'true'
       description: 'Wheather the delete-state job should be created or not.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
+  rules: $[[ inputs.rules ]]
   resource_group: $TF_STATE_NAME
   image: curlimages/curl:latest
   variables:
     TF_STATE_NAME: $[[ inputs.state_name ]]
   script:
     - curl --request DELETE -u "gitlab-ci-token:$CI_JOB_TOKEN" "$CI_API_V4_URL/projects/$CI_PROJECT_ID/terraform/state/$TF_STATE_NAME"
-  rules:
-    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
-    - when: manual
diff --git a/templates/destroy.yml b/templates/destroy.yml
index a7b4ac9..9726501 100644
--- a/templates/destroy.yml
+++ b/templates/destroy.yml
@@ -63,6 +63,10 @@ spec:
       default: false
       type: boolean
       description: 'Whether the destroy job is manual or automatically run.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
@@ -72,9 +76,7 @@ spec:
     name: $TF_STATE_NAME
     action: stop
   resource_group: $TF_STATE_NAME
-  rules:
-    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && "$[[ inputs.auto_destroy ]]" == "true"'
-    - when: manual
+  rules: $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
diff --git a/templates/fmt.yml b/templates/fmt.yml
index b8c53e7..4a9ab10 100644
--- a/templates/fmt.yml
+++ b/templates/fmt.yml
@@ -49,22 +49,21 @@ spec:
     root_dir:
       default: ${CI_PROJECT_DIR}
       description: 'Root directory for the OpenTofu project.'
-
     allow_failure:
       default: true
       type: boolean
       description: 'If the job is allowed to fail or not.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
   needs: []
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-    - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
-      when: never
-    - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
+  rules: $[[ inputs.rules ]]
   allow_failure: $[[ inputs.allow_failure ]]
   cache:
     key: "$__CACHE_KEY_HACK"
diff --git a/templates/full-pipeline.yml b/templates/full-pipeline.yml
index f6f88ea..0edaa76 100644
--- a/templates/full-pipeline.yml
+++ b/templates/full-pipeline.yml
@@ -85,6 +85,11 @@ include:
       image_registry_base: $[[ inputs.image_registry_base ]]
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/validate.yml'
     inputs:
       as: 'validate'
@@ -95,6 +100,11 @@ include:
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/test.yml'
     inputs:
       as: 'test'
@@ -105,6 +115,11 @@ include:
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
     rules:
       - exists:
           - $[[ inputs.root_dir ]]/**/*.tftest.hcl
@@ -119,6 +134,11 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       artifacts_access: $[[ inputs.plan_artifacts_access ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/apply.yml'
     inputs:
       as: 'apply'
@@ -130,6 +150,9 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       auto_apply: $[[ inputs.auto_apply ]]
+      rules:
+        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+          when: manual
   - local: '/templates/destroy.yml'
     inputs:
       as: 'destroy'
@@ -141,11 +164,17 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       auto_destroy: $[[ inputs.auto_destroy ]]
+      rules:
+        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && "$[[ inputs.auto_destroy ]]" == "true"'
+        - when: manual
   - local: '/templates/delete-state.yml'
     inputs:
       as: 'delete-state'
       stage: $[[ inputs.stage_cleanup ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+        - when: manual
 
 # NOTE: we have to define this `needs` here, because inputs don't support arrays, yet.
 delete-state:
diff --git a/templates/module-release.yml b/templates/module-release.yml
index 2d28d39..49037dc 100644
--- a/templates/module-release.yml
+++ b/templates/module-release.yml
@@ -30,10 +30,16 @@ spec:
         e.g. '0.1.0'
       default: ${CI_COMMIT_TAG}
 
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
+
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
+  rules: $[[ inputs.rules ]]
   image: curlimages/curl:8.8.0
   variables:
     TAR_FILENAME: /tmp/${CI_PROJECT_NAME}-${CI_COMMIT_SHA}.tgz
diff --git a/templates/plan.yml b/templates/plan.yml
index a8fedbc..095c9bb 100644
--- a/templates/plan.yml
+++ b/templates/plan.yml
@@ -62,6 +62,10 @@ spec:
     artifacts_access:
       default: 'none'
       description: 'Access level for the plan artifact. See https://docs.gitlab.com/ee/ci/yaml/#artifactsaccess for possible values.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
@@ -81,11 +85,7 @@ spec:
       - $TF_ROOT/$[[ inputs.plan_name ]].cache
     reports:
       terraform: $TF_ROOT/$[[ inputs.plan_name]].json
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-    - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
-      when: never
-    - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
+  rules: $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
diff --git a/templates/test.yml b/templates/test.yml
index dd9e5e7..7d78b4f 100644
--- a/templates/test.yml
+++ b/templates/test.yml
@@ -52,17 +52,17 @@ spec:
     state_name:
       default: default
       description: 'Remote OpenTofu state name.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
   needs: []
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-    - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
-      when: never
-    - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
+  rules: $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
diff --git a/templates/validate-plan-apply.yml b/templates/validate-plan-apply.yml
index ef3ca06..fa9702c 100644
--- a/templates/validate-plan-apply.yml
+++ b/templates/validate-plan-apply.yml
@@ -75,6 +75,11 @@ include:
       image_registry_base: $[[ inputs.image_registry_base ]]
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/validate.yml'
     inputs:
       as: 'validate'
@@ -85,6 +90,11 @@ include:
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/plan.yml'
     inputs:
       as: 'plan'
@@ -96,6 +106,11 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       artifacts_access: $[[ inputs.plan_artifacts_access ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/apply.yml'
     inputs:
       as: 'apply'
@@ -107,3 +122,6 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       auto_apply: $[[ inputs.auto_apply ]]
+      rules:
+        - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+          when: manual
diff --git a/templates/validate-plan-destroy.yml b/templates/validate-plan-destroy.yml
index ab85b5a..14016f2 100644
--- a/templates/validate-plan-destroy.yml
+++ b/templates/validate-plan-destroy.yml
@@ -78,6 +78,11 @@ include:
       image_registry_base: $[[ inputs.image_registry_base ]]
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/validate.yml'
     inputs:
       as: 'validate'
@@ -88,6 +93,11 @@ include:
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/plan.yml'
     inputs:
       as: 'plan'
@@ -101,6 +111,11 @@ include:
       plan_name: $[[ inputs.plan_name ]]
       artifacts_access: $[[ inputs.plan_artifacts_access ]]
       destroy: true
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/destroy.yml'
     inputs:
       as: 'destroy'
@@ -114,11 +129,17 @@ include:
       no_plan: false
       plan_name: $[[ inputs.plan_name ]]
       auto_destroy: $[[ inputs.auto_destroy ]]
+      rules:
+        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && "$[[ inputs.auto_destroy ]]" == "true"'
+        - when: manual
   - local: '/templates/delete-state.yml'
     inputs:
       as: 'delete-state'
       stage: $[[ inputs.stage_cleanup ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+        - when: manual
 
 # NOTE: we have to define this `needs` here, because inputs don't support arrays, yet.
 delete-state:
diff --git a/templates/validate-plan.yml b/templates/validate-plan.yml
index 6f7b3fe..052757a 100644
--- a/templates/validate-plan.yml
+++ b/templates/validate-plan.yml
@@ -68,6 +68,11 @@ include:
       image_registry_base: $[[ inputs.image_registry_base ]]
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/validate.yml'
     inputs:
       as: 'validate'
@@ -78,6 +83,11 @@ include:
       image_name: $[[ inputs.image_name ]]
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
   - local: '/templates/plan.yml'
     inputs:
       as: 'plan'
@@ -89,3 +99,8 @@ include:
       root_dir: $[[ inputs.root_dir ]]
       state_name: $[[ inputs.state_name ]]
       artifacts_access: $[[ inputs.artifacts_access ]]
+      rules:
+        - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+        - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
+          when: never
+        - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
diff --git a/templates/validate.yml b/templates/validate.yml
index 69634ce..874f6c2 100644
--- a/templates/validate.yml
+++ b/templates/validate.yml
@@ -52,16 +52,16 @@ spec:
     state_name:
       default: default
       description: 'Remote OpenTofu state name.'
+    rules:
+      type: array
+      default: []
+      description: 'An array of rules for the conditional creation of the apply job.'
 
 ---
 
 '$[[ inputs.as ]]':
   stage: $[[ inputs.stage ]]
-  rules:
-    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
-    - if: $CI_OPEN_MERGE_REQUESTS  # Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
-      when: never
-    - if: $CI_COMMIT_BRANCH        # If there's no open merge request, add it to a *branch* pipeline instead.
+  rules: $[[ inputs.rules ]]
   cache:
     key: "$__CACHE_KEY_HACK"
     paths:
-- 
GitLab