From c0622300a9608fdaac9e3fd87f1a26b64e43f036 Mon Sep 17 00:00:00 2001
From: Teake Nutma <t.a.nutma@rug.nl>
Date: Fri, 10 Jun 2022 11:32:47 +0200
Subject: [PATCH] Add shared rules

---
 .gitlab-ci.yml                          | 36 ++++++++++++-------------
 dockerfiles/ci-tools/Dockerfile         |  1 -
 templates/changedfiles/_shared.yml      |  9 ++-----
 templates/changedfiles/mergerequest.yml |  6 ++++-
 templates/changedfiles/push.yml         |  6 +++--
 templates/monthlymerge.yml              |  2 +-
 templates/shared/rules.yml              | 34 +++++++++++++++++++++++
 7 files changed, 64 insertions(+), 30 deletions(-)
 create mode 100644 templates/shared/rules.yml

diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index b2ae923..bef45d9 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,30 +1,30 @@
+# Note: there's no job to lint the .yml files, because:
+#
+# - The GitLab API for linting does not support local includes
+#   and .extends is not fully supported [1].
+# - Local linting with e.g. check-jsonschema [2]
+#   does not support GitLab's custom !reference tag [3] [4].
+#
+# [1] https://docs.gitlab.com/ee/api/lint.html#yaml-expansion
+# [2] https://github.com/python-jsonschema/check-jsonschema
+# [3] https://gitlab.com/gitlab-org/gitlab/-/issues/348666#note_804097628
+# [4] https://github.com/SchemaStore/schemastore/issues/1476
+
 include:
+  - local: '/templates/shared/rules.yml'
   - local: '/templates/shared/stages.yml'
   - local: '/templates/changedfiles/all.yml'
 
-workflow:
-  rules:
-    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
-    - if: $CI_COMMIT_REF_PROTECTED == 'true'
-    - if: $CI_MERGE_REQUEST_ID
-
-lint:
-  stage: lint
-  # Note: the ci-tools image has to be build and pushed manually once to bootstrap this job
-  # since this job comes before the build_containers job.
-  image: ${CI_REGISTRY_IMAGE}/ci-tools:master
-  script:
-    # Note: we cannot use the GitLab API https://docs.gitlab.com/ee/api/lint.html
-    # for this since that does not support local includes.
-    - shopt -s globstar dotglob
-    - check-jsonschema --builtin-schema vendor.gitlab-ci **/*.yml
-
 build_containers:
   stage: build
   # Note: the docker-builder image has to be build and pushed manually once to bootstrap this job.
   image: ${CI_REGISTRY_IMAGE}/docker-builder:master
+  rules:
+    - !reference [.primary_ref_jobs, rules]
+    - !reference [.merge_request_jobs, rules]
   script:
-    # Find the directories that contain a file named 'Dockerfile'
+    # Find the directories that contain a file named 'Dockerfile', and (re)build the ones
+    # that contain changed files.
     - |
       find . -name Dockerfile -type f | while read FILE;
       do
diff --git a/dockerfiles/ci-tools/Dockerfile b/dockerfiles/ci-tools/Dockerfile
index 3003d8a..36d557a 100644
--- a/dockerfiles/ci-tools/Dockerfile
+++ b/dockerfiles/ci-tools/Dockerfile
@@ -11,7 +11,6 @@ RUN apt-get update && apt-get -y install \
     && apt-get clean
 # Install via pip
 RUN pip install \
-    check-jsonschema \
     black==22.3.0 \
     autopep8 \
     python-gitlab \
diff --git a/templates/changedfiles/_shared.yml b/templates/changedfiles/_shared.yml
index 0e1c5ea..b182a28 100644
--- a/templates/changedfiles/_shared.yml
+++ b/templates/changedfiles/_shared.yml
@@ -6,14 +6,9 @@
 # Storing the list of changed files in a dotenv file (and subsequently exposing
 # it as an environment variable) would have been nicer. But we cannot store the
 # list of changed files in dotenv file because at the time
-# of writing GitLab does not support multiline dotenv variables. This is not
-# explicitly stated in the docs [1], but is apparent from this discussion [2]
-# and from the actual source code [3]. MR to fix docs is [4].
+# of writing GitLab does not support multiline dotenv variables [1].
 #
-# [1] https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsdotenv,
-# [2] https://gitlab.com/gitlab-org/gitlab/-/issues/227320#note_389543891
-# [3] https://gitlab.com/gitlab-org/gitlab/-/blob/23932c45096d93832189838a32b06fb3e0ff3e4e/app/services/ci/parse_dotenv_artifact_service.rb#L40
-# [4] https://gitlab.com/gitlab-org/gitlab/-/merge_requests/89403
+# [1] https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportsdotenv
 
 include:
   - local: '/templates/shared/stages.yml'
diff --git a/templates/changedfiles/mergerequest.yml b/templates/changedfiles/mergerequest.yml
index 67c81e1..dc6bb44 100644
--- a/templates/changedfiles/mergerequest.yml
+++ b/templates/changedfiles/mergerequest.yml
@@ -1,9 +1,13 @@
 include:
+  - local: '/templates/shared/rules.yml'
   - local: '/templates/changedfiles/_shared.yml'
 
 changed_files_mr:
   extends: .changed_files
   rules:
-    - if: $CI_MERGE_REQUEST_ID
+    - if: $CI_AWE_SKIP_CHANGED_FILES
+      when: never
+    - !reference [.merge_request_jobs, rules]
+    - if: $CI_AWE_RUN_CHANGED_FILES
   before_script:
     - COMPARE_REF="origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}"
diff --git a/templates/changedfiles/push.yml b/templates/changedfiles/push.yml
index 926e24e..9de86f8 100644
--- a/templates/changedfiles/push.yml
+++ b/templates/changedfiles/push.yml
@@ -1,11 +1,13 @@
 include:
+  - local: '/templates/shared/rules.yml'
   - local: '/templates/changedfiles/_shared.yml'
 
 changed_files_push:
   extends: .changed_files
   rules:
-    - if: $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+    - if: $CI_AWE_SKIP_CHANGED_FILES || $CI_PIPELINE_SOURCE != 'push'
       when: never
-    - if: $CI_PIPELINE_SOURCE == 'push'
+    - !reference [.primary_ref_jobs, rules]
+    - if: $CI_AWE_RUN_CHANGED_FILES
   before_script:
     - COMPARE_REF=${CI_COMMIT_BEFORE_SHA}
diff --git a/templates/monthlymerge.yml b/templates/monthlymerge.yml
index 9f4fca0..367d702 100644
--- a/templates/monthlymerge.yml
+++ b/templates/monthlymerge.yml
@@ -49,7 +49,7 @@ release_merge_and_tag:on-schedule:
         fi
       done
     - git commit -m "Bump version to ${version}" ${MM_BUMP_FILES}
-    - git push origin
+    - git push origin -o ci.variable="CI_AWE_SKIP_ALL=1"
     # 5. Tag this version.
     - git tag -a "${version}" -m "Automated tag of ${version}."
     - git push origin ${version}
diff --git a/templates/shared/rules.yml b/templates/shared/rules.yml
new file mode 100644
index 0000000..e4e12b9
--- /dev/null
+++ b/templates/shared/rules.yml
@@ -0,0 +1,34 @@
+.primary_ref_jobs:
+  rules:
+    - if: $CI_AWE_SKIP_ALL
+      when: never
+    - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS
+      when: never
+    - if: $CI_COMMIT_TAG
+    - if: $CI_COMMIT_REF_PROTECTED == 'true'
+    - if: $CI_COMMIT_BRANCH == 'master'
+    - if: $CI_COMMIT_BRANCH == 'main'
+    - if: $CI_COMMIT_BRANCH == 'develop'
+    - if: $CI_COMMIT_BRANCH =~ /^release\/.*$/
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+    - if: $CI_AWE_RUN_ALL
+
+.merge_request_jobs:
+  rules:
+    - if: $CI_AWE_SKIP_ALL
+      when: never
+    - if: $CI_MERGE_REQUEST_ID &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME !~ /^assist\/autoformat\/.*$/ &&
+          (
+             $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'master' ||
+             $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'main' ||
+             $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == 'develop' ||
+             $CI_MERGE_REQUEST_TARGET_BRANCH_NAME =~ /^release\/.*$/
+             $CI_MERGE_REQUEST_TARGET_BRANCH_NAME == $CI_DEFAULT_BRANCH
+          ) &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME != 'master' &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME != 'main' &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME != 'develop' &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME !~ /^release\/.*$/ &&
+          $CI_MERGE_REQUEST_SOURCE_BRANCH_NAME != $CI_DEFAULT_BRANCH
+    - if: $CI_AWE_RUN_ALL
-- 
GitLab