diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 1bafcfc26ab26d66332d6750859dabb3fc64ee35..3b46a9f043742778c4f70520b986569c408ab553 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -22,12 +22,28 @@ stages:
   - report
   - deploy
 
+workflow:
+  rules:
+    - if: '$CI_COMMIT_TAG'
+    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
+    - if: '$CI_PIPELINE_SOURCE == "schedule"'
+    - if: '$CI_MERGE_REQUEST_IID'
+
 include:
  - local: '/.oniro-ci/build-generic.yaml'
  - local: '/.oniro-ci/test-generic.yaml'
  - local: '/.oniro-ci/machines-and-flavours.yaml'
  - local: '/.oniro-ci/dco.yaml'
- - template: 'Workflows/MergeRequest-Pipelines.gitlab-ci.yml'
+
+# Customize the .workspace job to set the path of the git repository to deviate
+# from what the git-repo prepares. This effectively allows testing incoming
+# changes that match the repository holding this CI pipeline.
+.workspace:
+  variables:
+    CI_ONIRO_GIT_REPO_PATH: "oniro"
+    CI_ONIRO_MANIFEST_URL: "$CI_PROJECT_URL"
+    CI_ONIRO_MANIFEST_BRANCH: "$CI_COMMIT_REF_NAME"
+    CI_ONIRO_MAGIC: ".gitlab-ci.yml:46:.workspace"
 
 dco:
   extends: .dco
@@ -39,81 +55,6 @@ aggregate-docs:
   extends: .aggregate-docs
   needs: [build-docs]
 
-# Customize the .workspace job to set the path of the git repository to deviate
-# from what the git-repo prepares. This effectively allows testing incoming
-# changes that match the repository holding this CI pipeline.
-.workspace:
-  variables:
-    CI_ONIRO_GIT_REPO_PATH: oniro
-
-# Anchor job rules, which govern if a job is instantiated in a given pipeline.
-# This job is then used as another base to several different jobs, including
-# .bitbake-workspace, .build-rauc-bundle and the
-# .publish-rauc-bundle-to-hawkbit jobs.
-#
-# The rules are: modifications (changes) to the pipeline, meta-layers, flavours
-# and assets OR to placement of a tag on a commit OR when a job is scheduled.
-# In addition, draft merge requests will no longer start the heavy build jobs
-# automatically, giving an option to the developer, to start the desired jobs
-# manually.
-.workspace-rules:
-  variables:
-    CI_ONIRO_MAGIC: ".gitlab-ci.yml:61:.workspace-rules"
-  rules:
-    - if: '$CI_PIPELINE_SOURCE == "schedule"'
-      variables:
-        CI_ONIRO_MANIFEST_URL: "$CI_PROJECT_URL"
-        CI_ONIRO_MANIFEST_BRANCH: "$CI_COMMIT_REF_NAME"
-        CI_ONIRO_MAGIC: ".gitlab-ci.yml:67:.workspace-rules"
-    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TITLE =~ /^(wip|draft):.*/i'
-      when: manual
-      variables:
-        # See below for rationale.
-        CI_ONIRO_MANIFEST_URL: "$CI_MERGE_REQUEST_SOURCE_PROJECT_URL"
-        CI_ONIRO_MANIFEST_BRANCH: "$CI_COMMIT_REF_NAME"
-        CI_ONIRO_MAGIC: ".gitlab-ci.yml:74:.workspace-rules"
-    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
-      changes:
-        - assets/**/*
-        - flavours/**/*
-        - manifests/*.xml
-        - meta-*/**/*
-        - .oniro-ci/*
-        - .gitlab-ci.yml
-      # When building a merge request substitute the CI_ONIRO_MANIFEST_URL to point
-      # to the incoming repository, and CI_ONIRO_MANIFEST_BRANCH, to the right
-      # branch name. This allows testing the changes coming into project. This
-      # is done here, so that it does not clobber scheduled pipelines.
-      variables:
-        CI_ONIRO_MANIFEST_URL: "$CI_MERGE_REQUEST_SOURCE_PROJECT_URL"
-        CI_ONIRO_MANIFEST_BRANCH: "$CI_COMMIT_REF_NAME"
-        CI_ONIRO_MAGIC: ".gitlab-ci.yml:90:.workspace-rules"
-    - if: '$CI_COMMIT_TAG'
-      # XXX: This needs CI_ONIRO_MANIFEST_BRANCH as well, most likely.
-
-
-# The three jobs defined below override the definitions from build-generic.yaml
-# to inject .workspace-rules and the rules defined therein. It is important to
-# understand that this is based on several separate systems: parsing and
-# loading yaml, processing the include rules, and processing extends rules.
-#
-# This specific trick (ab)uses the fact that yaml-top-level is one big map of
-# entities, and we can define an entity multiple times to effectively extend or
-# replace specific elements.
-#
-# The following three jobs are equivalent to copy-pasting the modified extends
-# line into the jobs in .oniro-ci/build-generic.yaml, because map/dictionary
-# entries compute the union of the defined keys, unlike list entries or scalars
-# that replace the previous value.
-
-.bitbake-workspace:
-  extends: [.workspace-rules, .workspace]
-
-.build-rauc-bundle:
-  extends: [.workspace-rules, .build-image]
-
-.publish-rauc-bundle-to-hawkbit:
-  extends: [.workspace-rules]
 
 # Build a RAUC update bundle for Raspberry Pi 4
 bundle-raspberrypi4-64:
diff --git a/.oniro-ci/build-generic.yaml b/.oniro-ci/build-generic.yaml
index 7149b47f89dfcf3556fd4cac2d725b3d19b9354d..2e58c2099f8ad6d1c6e22c69fce2d0d61c171625 100644
--- a/.oniro-ci/build-generic.yaml
+++ b/.oniro-ci/build-generic.yaml
@@ -75,6 +75,20 @@
     # Clean up after ourselves.
     - rm -f "$CI_PROJECT_DIR"/.scratch-dir-name
     - rm -rf "$SCRATCH_DIR"
+  rules:
+    - if: '$CI_PIPELINE_SOURCE == "merge_request_event" && $CI_MERGE_REQUEST_TITLE =~ /^(wip|draft):.*/i'
+      when: manual
+      variables:
+        CI_ONIRO_MANIFEST_URL: "$CI_MERGE_REQUEST_SOURCE_PROJECT_URL"
+        CI_ONIRO_MAGIC: ".oniro-ci/build-generic.yml:83:.workspace"
+    - if: '$CI_MERGE_REQUEST_IID'
+      # When building a merge request substitute the CI_ONIRO_MANIFEST_URL to point
+      # to the incoming repository, and CI_ONIRO_MANIFEST_BRANCH, to the right
+      # branch name. This allows testing the changes coming into project. This
+      # is done here, so that it does not clobber scheduled pipelines.
+      variables:
+        CI_ONIRO_MANIFEST_URL: "$CI_MERGE_REQUEST_SOURCE_PROJECT_URL"
+        CI_ONIRO_MAGIC: ".oniro-ci/build-generic.yml:91:.workspace"
 
 # This job is documented in docs/ci/hidden-jobs/bitbake-workspace.rst
 .bitbake-workspace: