diff --git a/app/models/ci/pipeline.rb b/app/models/ci/pipeline.rb
index fdef3f3e55e6d218da9a1a341adc3a090d173316..f37fa2edcf81c3fb92f5913ddf2fea111e48474f 100644
--- a/app/models/ci/pipeline.rb
+++ b/app/models/ci/pipeline.rb
@@ -4,6 +4,7 @@ module Ci
   class Pipeline < Ci::ApplicationRecord
     include Ci::Partitionable
     include Ci::HasStatus
+    include Ci::HasCompletionReason
     include Importable
     include AfterCommitQueue
     include Presentable
diff --git a/app/models/concerns/ci/has_completion_reason.rb b/app/models/concerns/ci/has_completion_reason.rb
new file mode 100644
index 0000000000000000000000000000000000000000..b725d900f88de18294b0e770192688b6eb493f3e
--- /dev/null
+++ b/app/models/concerns/ci/has_completion_reason.rb
@@ -0,0 +1,22 @@
+# frozen_string_literal: true
+
+module Ci
+  module HasCompletionReason
+    extend ActiveSupport::Concern
+
+    class_methods do
+      def rules_failure_message
+        "the resulting pipeline would have been empty. Review the " \
+          "[rules](#{Rails.application.routes.url_helpers.help_page_url('ci/yaml/index', anchor: 'rules')}) " \
+          "configuration for the relevant jobs."
+      end
+
+      def workflow_rules_failure_message
+        "the pipeline did not run. Review the " \
+          "[workflow:rules](#{Rails.application.routes.url_helpers.help_page_url('ci/yaml/index',
+            anchor: 'workflowrules')}) " \
+        "configuration for the pipeline."
+      end
+    end
+  end
+end
diff --git a/app/presenters/ci/pipeline_presenter.rb b/app/presenters/ci/pipeline_presenter.rb
index 6c7608b8067dc7bc57a00714444b6c528b9a0062..c609cb35d9d6fd4135de8be3f148c8944c919c66 100644
--- a/app/presenters/ci/pipeline_presenter.rb
+++ b/app/presenters/ci/pipeline_presenter.rb
@@ -12,14 +12,13 @@ def self.failure_reasons
       { unknown_failure: 'The reason for the pipeline failure is unknown.',
         config_error: 'The pipeline failed due to an error on the CI/CD configuration file.',
         external_validation_failure: 'The external pipeline validation failed.',
-        user_not_verified: 'The pipeline failed due to the user not being verified',
+        user_not_verified: 'The pipeline failed due to the user not being verified.',
         size_limit_exceeded: 'The pipeline size limit was exceeded.',
         job_activity_limit_exceeded: 'The pipeline job activity limit was exceeded.',
         deployments_limit_exceeded: 'The pipeline deployments limit was exceeded.',
         project_deleted: 'The project associated with this pipeline was deleted.',
-        filtered_by_rules: 'Pipeline will not run for the selected trigger. ' \
-                           'The rules configuration prevented any jobs from being added to the pipeline.',
-        filtered_by_workflow_rules: 'Pipeline filtered out by workflow rules.' }
+        filtered_by_rules: Ci::Pipeline.rules_failure_message,
+        filtered_by_workflow_rules: Ci::Pipeline.workflow_rules_failure_message }
     end
 
     presents ::Ci::Pipeline, as: :pipeline
diff --git a/app/services/merge_requests/refresh_service.rb b/app/services/merge_requests/refresh_service.rb
index fbf3a48ac12c4cadb791a9739acc40392992e7e6..8f6979460a9c4a757d32e5d9665a1c22d4c7b0de 100644
--- a/app/services/merge_requests/refresh_service.rb
+++ b/app/services/merge_requests/refresh_service.rb
@@ -193,7 +193,12 @@ def abort_auto_merges?(merge_request)
     def abort_auto_merges(merge_request)
       return unless abort_auto_merges?(merge_request)
 
-      abort_auto_merge(merge_request, 'source branch was updated')
+      learn_more_url = Rails.application.routes.url_helpers.help_page_url(
+        'ci/pipelines/merge_trains',
+        anchor: 'merge-request-dropped-from-the-merge-train'
+      )
+
+      abort_auto_merge(merge_request, "the source branch was updated. [Learn more](#{learn_more_url}).")
     end
 
     def abort_ff_merge_requests_with_auto_merges
diff --git a/doc/ci/pipelines/downstream_pipelines_troubleshooting.md b/doc/ci/pipelines/downstream_pipelines_troubleshooting.md
index fc5477074a0d907ffac1992f2b44ec41e55b8b81..12f160cc53a4ac03c972320d02d2bfb08e3b1789 100644
--- a/doc/ci/pipelines/downstream_pipelines_troubleshooting.md
+++ b/doc/ci/pipelines/downstream_pipelines_troubleshooting.md
@@ -31,7 +31,7 @@ the child pipeline must [use `workflow:rules` or `rules` to ensure the jobs run]
 If no jobs in the child pipeline can run due to missing or incorrect `rules` configuration:
 
 - The child pipeline fails to start.
-- The parent pipeline's trigger job fails with: `downstream pipeline can not be created, Pipeline will not run for the selected trigger. The rules configuration prevented any jobs from being added to the pipeline.`
+- The parent pipeline's trigger job fails with: `downstream pipeline can not be created, the resulting pipeline would have been empty. Review the`[`rules`](../yaml/index.md#rules)`configuration for the relevant jobs.`
 
 ## Variable with `$` character does not get passed to a downstream pipeline properly
 
diff --git a/ee/app/services/merge_trains/refresh_merge_request_service.rb b/ee/app/services/merge_trains/refresh_merge_request_service.rb
index d361b2b3018a1e32965e2195883f19526ca7d0bb..1e3eeeb92963b93ffde8f040d7cc637110644175 100644
--- a/ee/app/services/merge_trains/refresh_merge_request_service.rb
+++ b/ee/app/services/merge_trains/refresh_merge_request_service.rb
@@ -35,18 +35,25 @@ def validate!
       end
 
       if !merge_request.open? || merge_request.broken? || merge_request.draft?
-        raise ProcessError, 'merge request is not mergeable'
+        raise ProcessError, "the merge request is not mergeable. [Learn more](#{learn_more_url})."
       end
 
       unless merge_train_car.previous_ref_sha.present?
-        raise ProcessError, 'previous ref does not exist'
+        raise ProcessError, "the previous ref does not exist. [Learn more](#{learn_more_url})."
       end
 
       if merge_train_car.pipeline_not_succeeded?
-        raise ProcessError, 'pipeline did not succeed'
+        raise ProcessError, "the pipeline did not succeed. [Learn more](#{learn_more_url})."
       end
     end
 
+    def learn_more_url
+      Rails.application.routes.url_helpers.help_page_url(
+        'ci/pipelines/merge_trains',
+        anchor: 'merge-request-dropped-from-the-merge-train'
+      )
+    end
+
     def merge_from_train_ref?
       # Although it should be technically safe to merge from any mergeable train
       # ref, do so for fast-forward and semi-linear merge trains to avoid
diff --git a/ee/app/services/system_notes/merge_train_service.rb b/ee/app/services/system_notes/merge_train_service.rb
index 7a02f75f8ab0e45e2f5c1412cc3ac6d190a4b34b..34f9060280b76e51646df51f6218408084ee2082 100644
--- a/ee/app/services/system_notes/merge_train_service.rb
+++ b/ee/app/services/system_notes/merge_train_service.rb
@@ -29,11 +29,8 @@ def abort(reason)
       ##
       # TODO: Abort message should be sent by the system, not a particular user.
       # See https://gitlab.com/gitlab-org/gitlab/issues/29467.
-      url = Rails.application.routes.url_helpers.help_page_url(
-        'ci/pipelines/merge_trains',
-        anchor: 'merge-request-dropped-from-the-merge-train'
-      )
-      body = "removed this merge request from the merge train because #{reason}. [Learn more](#{url})."
+
+      body = "removed this merge request from the merge train because #{reason}"
 
       create_note(NoteSummary.new(noteable, project, author, body, action: 'merge'))
     end
diff --git a/ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb b/ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb
index cfb768d738abfb664f9fe0fe550383b6092306cb..a240e8614f453355c6f2599d74140dba676264f4 100644
--- a/ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb
+++ b/ee/spec/features/merge_trains/two_merge_requests_on_train_spec.rb
@@ -147,7 +147,8 @@
 
     it_behaves_like 'drops merge request 1 from the merge train' do
       let(:system_note) do
-        'removed this merge request from the merge train because pipeline did not succeed. [Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        'removed this merge request from the merge train because the pipeline did not succeed. ' \
+          '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
       end
     end
 
@@ -189,7 +190,8 @@
 
     it_behaves_like 'drops merge request 1 from the merge train' do
       let(:system_note) do
-        'removed this merge request from the merge train because source branch was updated. [Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        'removed this merge request from the merge train because the source branch was updated. ' \
+          '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
       end
     end
 
@@ -209,7 +211,8 @@
 
     it_behaves_like 'drops merge request 1 from the merge train' do
       let(:system_note) do
-        'removed this merge request from the merge train because merge request is not mergeable. [Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        'removed this merge request from the merge train because the merge request is not mergeable. ' \
+          '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
       end
     end
 
diff --git a/ee/spec/lib/ee/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb b/ee/spec/lib/ee/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
index fb2490547d165d5c724bc9a50d14ab26863931c1..07056754f25e4aa794cabea5481071648b41e6fd 100644
--- a/ee/spec/lib/ee/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
+++ b/ee/spec/lib/ee/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
@@ -88,7 +88,7 @@
         end
 
         it 'attaches an error to the pipeline' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
         end
 
         it 'saves workflow_rules_result' do
diff --git a/ee/spec/lib/gitlab/ci/templates/Security/bas_latest_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/Security/bas_latest_ci_yaml_spec.rb
index dc7a1e45a84eb29e736e0822c8c0dac4348986de..93b832db173694ccaa268b50e985a24930f5bc6e 100644
--- a/ee/spec/lib/gitlab/ci/templates/Security/bas_latest_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/Security/bas_latest_ci_yaml_spec.rb
@@ -56,9 +56,7 @@
 
       it 'skips branch pipelines when an open MR exists' do
         expect(build_names).to be_empty
-        expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                                                              'The rules configuration prevented any jobs from ' \
-                                                              'being added to the pipeline.'])
+        expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
   end
diff --git a/ee/spec/lib/gitlab/ci/templates/api_discovery_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/api_discovery_gitlab_ci_yaml_spec.rb
index a84ac48bd0904a386d8aa78efc478e12abd3210f..e4542b83cecc1f85085d7f587755c4c84406fd5c 100644
--- a/ee/spec/lib/gitlab/ci/templates/api_discovery_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/api_discovery_gitlab_ci_yaml_spec.rb
@@ -89,8 +89,7 @@
           it 'includes no jobs' do
             expect(build_names).to be_empty
             expect(pipeline.errors.full_messages).to match_array([
-              'Pipeline will not run for the selected trigger. ' \
-              'The rules configuration prevented any jobs from being added to the pipeline.'
+              Ci::Pipeline.rules_failure_message
             ])
           end
         end
diff --git a/ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb
index 1199e6d6dee04a558e2c1d1959a914d75eca5963..26f1f5d8803590ce59dcb4167ab5cf9f6a714e21 100644
--- a/ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/api_fuzzing_gitlab_ci_yaml_spec.rb
@@ -134,8 +134,7 @@
           it 'includes no jobs' do
             expect(build_names).to be_empty
             expect(pipeline.errors.full_messages).to match_array([
-              'Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'
+              Ci::Pipeline.rules_failure_message
             ])
           end
         end
diff --git a/ee/spec/lib/gitlab/ci/templates/api_fuzzing_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/api_fuzzing_latest_gitlab_ci_yaml_spec.rb
index 9b8c6a1eab1623a16c347e7f49e3022fa1f3ec81..1b4122b9db392aa1b423afdda8d17209db203fda 100644
--- a/ee/spec/lib/gitlab/ci/templates/api_fuzzing_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/api_fuzzing_latest_gitlab_ci_yaml_spec.rb
@@ -136,8 +136,7 @@
             it 'includes no jobs' do
               expect(build_names).to be_empty
               expect(pipeline.errors.full_messages).to match_array([
-                'Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.'
+                Ci::Pipeline.rules_failure_message
               ])
             end
           end
@@ -150,8 +149,7 @@
             it 'includes no jobs' do
               expect(build_names).to be_empty
               expect(pipeline.errors.full_messages).to match_array([
-                'Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.'
+                Ci::Pipeline.rules_failure_message
               ])
             end
           end
diff --git a/ee/spec/lib/gitlab/ci/templates/api_security_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/api_security_gitlab_ci_yaml_spec.rb
index 5ed62c4c52a275875bbaf0087e9d8e5b4ecdeee8..7a46d908b57519ef5cb468408c493c74020fca68 100644
--- a/ee/spec/lib/gitlab/ci/templates/api_security_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/api_security_gitlab_ci_yaml_spec.rb
@@ -96,8 +96,7 @@
 
           it 'includes no jobs' do
             expect(build_names).to be_empty
-            expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-              'The rules configuration prevented any jobs from being added to the pipeline.'])
+            expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
           end
         end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/api_security_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/api_security_latest_gitlab_ci_yaml_spec.rb
index 2f1a284ea2530ea02a42e1b12ce409d4cdb01922..18a83fb09068928a685032088288495d2688df06 100644
--- a/ee/spec/lib/gitlab/ci/templates/api_security_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/api_security_latest_gitlab_ci_yaml_spec.rb
@@ -98,8 +98,7 @@
 
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
 
@@ -110,8 +109,7 @@
 
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb
index 989b9077bd3b4c4e27b553560089df616687ab84..0411f5d59a3b469f7b003d7bc372f3b7ca44a8f9 100644
--- a/ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/container_scanning_gitlab_ci_yaml_spec.rb
@@ -46,8 +46,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/ee/spec/lib/gitlab/ci/templates/container_scanning_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/container_scanning_latest_gitlab_ci_yaml_spec.rb
index c266541fd1d471201493ffd4b17f8af51a62896c..8f9ede2abbfed3f84b57a1f0c347a11fe02782d4 100644
--- a/ee/spec/lib/gitlab/ci/templates/container_scanning_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/container_scanning_latest_gitlab_ci_yaml_spec.rb
@@ -80,8 +80,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -92,8 +91,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb
index 949002a5f986da0d1d1845e72ffbed1a7ad1dadb..24df5a2d3577f940f0e744dd1a629ecd4c4ceac6 100644
--- a/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_gitlab_ci_yaml_spec.rb
@@ -47,8 +47,7 @@
 
         it 'includes no job' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -61,8 +60,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_latest_gitlab_ci_yaml_spec.rb
index bcbcefd62dcad1b43cd67b7e906033c59f798d30..228945973868c199cc1e6371ee5b3e243966131d 100644
--- a/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/coverage_fuzzing_latest_gitlab_ci_yaml_spec.rb
@@ -47,8 +47,7 @@
 
         it 'includes no job' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -63,8 +62,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -75,8 +73,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb
index 33766acd3050bdd2ff4b175effe3d7e774c1081c..bcd5014e307572c151e5c08cdc02265c8b924497 100644
--- a/ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dast_api_gitlab_ci_yaml_spec.rb
@@ -96,8 +96,7 @@
 
           it 'includes no jobs' do
             expect(build_names).to be_empty
-            expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-              'The rules configuration prevented any jobs from being added to the pipeline.'])
+            expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
           end
         end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb
index 43d9d5bade548d96c7987dae2af3a733abeed596..5261e8368bfee04cc38b3700872df6253943a13c 100644
--- a/ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dast_api_latest_gitlab_ci_yaml_spec.rb
@@ -98,8 +98,7 @@
 
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
 
@@ -110,8 +109,7 @@
 
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb
index 182fc45b3b1b13c5b42f97a59aebc94fb569600d..d421034571838efcfe65b8268cc6d2761c5b7dd4 100644
--- a/ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dast_gitlab_ci_yaml_spec.rb
@@ -49,8 +49,7 @@
       context 'when project has no license' do
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -72,8 +71,7 @@
 
           it 'includes no jobs' do
             expect(build_names).to be_empty
-            expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-              'The rules configuration prevented any jobs from being added to the pipeline.'])
+            expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
           end
         end
 
@@ -107,8 +105,7 @@
           context 'when on default branch' do
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
 
@@ -145,8 +142,7 @@
 
             it 'includes no jobs' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
         end
diff --git a/ee/spec/lib/gitlab/ci/templates/dast_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dast_latest_gitlab_ci_yaml_spec.rb
index 88384db4bbece60ccb0a3b8db772f323ea5cfe23..338b4c5312975f656482523eecaf9cac20ec0df5 100644
--- a/ee/spec/lib/gitlab/ci/templates/dast_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dast_latest_gitlab_ci_yaml_spec.rb
@@ -5,8 +5,7 @@
 RSpec.shared_examples 'includes no jobs' do
   it 'includes no jobs' do
     expect(build_names).to be_empty
-    expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-      'The rules configuration prevented any jobs from being added to the pipeline.'])
+    expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
   end
 end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb
index e8b89f5d4163b9b7f1f0695df4f304084202ea1a..bf3dc07fa9dcecd65f6adef677db26877890a4f0 100644
--- a/ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dependency_scanning_gitlab_ci_yaml_spec.rb
@@ -132,8 +132,7 @@
     context 'when project has no license' do
       it 'includes no jobs' do
         expect(build_names).to be_empty
-        expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
 
@@ -151,8 +150,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -189,8 +187,7 @@
 
             it 'creates a pipeline excluding jobs from specified analyzers' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
         end
diff --git a/ee/spec/lib/gitlab/ci/templates/dependency_scanning_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/dependency_scanning_latest_gitlab_ci_yaml_spec.rb
index 3bdc09727c581abe82073710b9867feb0830bf90..25d86b0c6e673cbff9df85948a6d21eaf9b69174 100644
--- a/ee/spec/lib/gitlab/ci/templates/dependency_scanning_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/dependency_scanning_latest_gitlab_ci_yaml_spec.rb
@@ -171,8 +171,7 @@
     context 'when project has no license' do
       it 'includes no jobs' do
         expect(build_names).to be_empty
-        expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
 
@@ -191,8 +190,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -203,8 +201,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -250,8 +247,7 @@
 
             it 'creates a pipeline excluding jobs from specified analyzers' do
               expect(build_names).to be_empty
-              expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.'])
+              expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
             end
           end
         end
diff --git a/ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb
index 554f554528891487c05b6a756b7714bdb856a3e6..b6c8ab5f397db8cd9780a3f0c5030deb2ba26e40 100644
--- a/ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/sast_gitlab_ci_yaml_spec.rb
@@ -30,8 +30,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -44,8 +43,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb
index ab16efccd0fbee459d9d9359ff0f0b501c312d49..f446551cdd12ef05bb82e86a4069a56693686700 100644
--- a/ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/sast_iac_gitlab_ci_yaml_spec.rb
@@ -30,8 +30,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb
index 5ce72ca563825aacf722be7f2d6ccade3335c87d..b5626648ea516921bccb31f0efc7eecfbf0a18af 100644
--- a/ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/sast_latest_gitlab_ci_yaml_spec.rb
@@ -37,8 +37,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -49,8 +48,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -73,8 +71,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb
index 389fb233503870e27288a64a9b83dbfdc8998087..fff42b20fa9d886c6d0501f2bf0aa33ac7d39035 100644
--- a/ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/secret_detection_gitlab_ci_yaml_spec.rb
@@ -30,8 +30,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/lib/gitlab/ci/templates/secret_detection_latest_gitlab_ci_yaml_spec.rb b/ee/spec/lib/gitlab/ci/templates/secret_detection_latest_gitlab_ci_yaml_spec.rb
index baa8fe8d13f16a046fd16af5e1955a1edcc70471..755bc34cfbedcd917111eb09ab473b09f24bde33 100644
--- a/ee/spec/lib/gitlab/ci/templates/secret_detection_latest_gitlab_ci_yaml_spec.rb
+++ b/ee/spec/lib/gitlab/ci/templates/secret_detection_latest_gitlab_ci_yaml_spec.rb
@@ -35,8 +35,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -47,8 +46,7 @@
 
         it 'includes no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
diff --git a/ee/spec/services/merge_trains/create_pipeline_service_spec.rb b/ee/spec/services/merge_trains/create_pipeline_service_spec.rb
index fff9ff7f60e90d5ad67bd72b16a375b5812b40f5..5fc2e9fef50a168777b6eb995fa11a59be25a1e3 100644
--- a/ee/spec/services/merge_trains/create_pipeline_service_spec.rb
+++ b/ee/spec/services/merge_trains/create_pipeline_service_spec.rb
@@ -35,7 +35,7 @@
 
         specify do
           expect(subject[:status]).to eq(:error)
-          expect(subject[:message]).to match(/^#{expected_reason}/)
+          expect(subject[:message]).to match expected_reason
         end
       end
 
@@ -146,10 +146,7 @@
 
         context 'when .gitlab-ci.yml does not have only: [merge_requests] specification' do
           it_behaves_like 'returns an error' do
-            let(:expected_reason) do
-              'Pipeline will not run for the selected trigger. ' \
-              'The rules configuration prevented any jobs from being added to the pipeline.'
-            end
+            let(:expected_reason) { ::Ci::Pipeline.rules_failure_message }
           end
         end
       end
diff --git a/ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb b/ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb
index 868bc1c661799fb42efa0791b8839e6400098548..e9c87842b20d3f5d7612319fb2030f65224d2025 100644
--- a/ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb
+++ b/ee/spec/services/merge_trains/refresh_merge_request_service_spec.rb
@@ -124,7 +124,10 @@
       end
 
       it_behaves_like 'drops the merge request from the merge train' do
-        let(:expected_reason) { 'merge request is not mergeable' }
+        let(:expected_reason) do
+          'the merge request is not mergeable. ' \
+            '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        end
       end
     end
 
@@ -136,7 +139,10 @@
       end
 
       it_behaves_like 'drops the merge request from the merge train' do
-        let(:expected_reason) { 'pipeline did not succeed' }
+        let(:expected_reason) do
+          'the pipeline did not succeed. ' \
+            '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        end
       end
     end
 
@@ -158,7 +164,10 @@
       end
 
       it_behaves_like 'drops the merge request from the merge train' do
-        let(:expected_reason) { 'previous ref does not exist' }
+        let(:expected_reason) do
+          'the previous ref does not exist. ' \
+            '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+        end
       end
     end
 
diff --git a/ee/spec/services/system_notes/merge_train_service_spec.rb b/ee/spec/services/system_notes/merge_train_service_spec.rb
index cf29802210177d4131fff0933838296fb88a449b..b9198cc0a3b1ae7860b99bb2d6c2787fe893a29c 100644
--- a/ee/spec/services/system_notes/merge_train_service_spec.rb
+++ b/ee/spec/services/system_notes/merge_train_service_spec.rb
@@ -55,7 +55,11 @@
   end
 
   describe '#abort' do
-    subject { described_class.new(noteable: noteable, project: project, author: author).abort('source branch was updated') }
+    subject do
+      described_class.new(noteable: noteable, project: project, author: author)
+                     .abort('the source branch was updated. ' \
+                       '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).')
+    end
 
     let(:noteable) { create(:merge_request, :on_train, source_project: project, target_project: project) }
 
@@ -64,7 +68,10 @@
     end
 
     it "posts the 'merge train' system note" do
-      expect(subject.note).to eq('removed this merge request from the merge train because source branch was updated. [Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).')
+      expect(subject.note).to eq(
+        'removed this merge request from the merge train because the source branch was updated. ' \
+          '[Learn more](http://localhost/help/ci/pipelines/merge_trains#merge-request-dropped-from-the-merge-train).'
+      )
     end
 
     it_behaves_like 'creates a removed merge train TODO'
diff --git a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
index 04195e4f8480707685995bd1d518134de38f965b..fca7bf1ab084f1bd8deecaead2cef84b56bee4e1 100644
--- a/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
+++ b/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules.rb
@@ -28,7 +28,7 @@ def perform!
             end
 
             error(
-              'Pipeline filtered out by workflow rules.',
+              ::Ci::Pipeline.workflow_rules_failure_message,
               failure_reason: :filtered_by_workflow_rules
             )
           end
diff --git a/lib/gitlab/ci/pipeline/chain/populate.rb b/lib/gitlab/ci/pipeline/chain/populate.rb
index 5b2cb7f759dcb5e194e67e4bfb77e78d0e5f1633..e5a2be755d85e0089ad929797861192f70ef844c 100644
--- a/lib/gitlab/ci/pipeline/chain/populate.rb
+++ b/lib/gitlab/ci/pipeline/chain/populate.rb
@@ -19,8 +19,7 @@ def perform!
 
             if no_pipeline_to_create?
               return error(
-                'Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.',
+                ::Ci::Pipeline.rules_failure_message,
                 failure_reason: :filtered_by_rules
               )
             end
diff --git a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
index bf14679165932728d3a7f774f563ebfef086718d..761dccf3d4261a21eaea15154beeba953cd64432 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/evaluate_workflow_rules_spec.rb
@@ -33,7 +33,7 @@
       end
 
       it 'attaches an error to the pipeline' do
-        expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+        expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
       end
 
       it 'saves workflow_rules_result' do
diff --git a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
index 85b0abb554839f604ac583965da84dc3f0a308df..544650da18d37c2b1a9a8e9621f8a44e118f0df3 100644
--- a/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
+++ b/spec/lib/gitlab/ci/pipeline/chain/populate_spec.rb
@@ -90,8 +90,7 @@ def run_chain
 
     it 'appends an error about missing stages' do
       expect(pipeline.errors.to_a)
-        .to include 'Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'
+        .to include ::Ci::Pipeline.rules_failure_message
     end
 
     it 'wastes pipeline iid' do
diff --git a/spec/lib/gitlab/ci/status/bridge/factory_spec.rb b/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
index 6c8daf4bfb1bfda760aac65ee2d51da9df4beb9c..3e584e972f56e42a1c6fde56aafb3aa4a19380af 100644
--- a/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
+++ b/spec/lib/gitlab/ci/status/bridge/factory_spec.rb
@@ -60,15 +60,13 @@
 
     context 'failed with downstream_pipeline_creation_failed' do
       before do
-        bridge.options = { downstream_errors: ['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.', 'other error'] }
+        bridge.options = { downstream_errors: [Ci::Pipeline.rules_failure_message, 'other error'] }
         bridge.failure_reason = 'downstream_pipeline_creation_failed'
       end
 
       it 'fabricates correct status_tooltip' do
         expect(status.status_tooltip).to eq(
-          "#{s_('CiStatusLabel|Failed')} - (downstream pipeline can not be created, Pipeline will not run for the selected trigger. " \
-          "The rules configuration prevented any jobs from being added to the pipeline., other error)"
+          "#{s_('CiStatusLabel|Failed')} - (downstream pipeline can not be created, #{Ci::Pipeline.rules_failure_message}, other error)"
         )
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
index 286f3d10b7fa3a07aad8ea7a522fa85289a3944d..a729a95b8ac118cbd43d4820c7d510a243f037d7 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/code_quality_gitlab_ci_yaml_spec.rb
@@ -63,8 +63,7 @@
       context 'on master' do
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -73,8 +72,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -83,8 +81,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
index 68d249e31f93442d3ceeb18a917d0413a081d4a7..19dc8292c540448dd57ba19f6e419d2e19d7ae0e 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_gitlab_ci_yaml_spec.rb
@@ -50,8 +50,7 @@
       context 'on default branch' do
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -60,8 +59,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
index 86bc92597898b6646ed35b729fe011f3420a0a15..514b3dd8bab5f21a085c6f73c734b7d753289c31 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/sast_iac_latest_gitlab_ci_yaml_spec.rb
@@ -57,8 +57,7 @@
       context 'on default branch' do
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -67,8 +66,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
index d73d8a15feb8539108593738632617c1baa752b3..a5bae3e5a0be4c9d9add9899258941753c2aba6b 100644
--- a/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/Jobs/test_gitlab_ci_yaml_spec.rb
@@ -63,8 +63,7 @@
       context 'on master' do
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -73,8 +72,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
 
@@ -83,8 +81,7 @@
 
         it 'has no jobs' do
           expect(build_names).to be_empty
-          expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'])
+          expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
         end
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/npm_spec.rb b/spec/lib/gitlab/ci/templates/npm_spec.rb
index a949a7ccfb1a2f03cb6ecc95d3cc40b214c25be8..834b8daacd5cfc45db176d50d667ecc4ddae7474 100644
--- a/spec/lib/gitlab/ci/templates/npm_spec.rb
+++ b/spec/lib/gitlab/ci/templates/npm_spec.rb
@@ -43,8 +43,7 @@ def create_tag(name:)
     shared_examples 'no pipeline created' do
       it 'does not create a pipeline because the only job (publish) is not created' do
         expect(build_names).to be_empty
-        expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
 
diff --git a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
index f84826efc49c3c32ebc327263cb2ac04fe9b6465..dd9fe01ba7a8f922a4fd93c10426b442476ac560 100644
--- a/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/terraform_latest_gitlab_ci_yaml_spec.rb
@@ -79,10 +79,7 @@
       it 'does not create a branch pipeline', :aggregate_failures do
         expect(branch_build_names).to be_empty
         expect(branch_pipeline.errors.full_messages).to match_array(
-          [
-            'Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.'
-          ]
+          [Ci::Pipeline.rules_failure_message]
         )
       end
     end
diff --git a/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb b/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
index 607db33f61a0d32a85d04cba62e77a6436143b6c..1021da5ce5ca7a1c520928caa5c92d7eac1008c1 100644
--- a/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
+++ b/spec/lib/gitlab/ci/templates/themekit_gitlab_ci_yaml_spec.rb
@@ -52,8 +52,7 @@
 
       it 'has no jobs' do
         expect(build_names).to be_empty
-        expect(pipeline.errors.full_messages).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(pipeline.errors.full_messages).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
   end
diff --git a/spec/services/ci/create_downstream_pipeline_service_spec.rb b/spec/services/ci/create_downstream_pipeline_service_spec.rb
index 4eb6962cf47d80de698615fe8d8f20618890c58b..c3e6876b57dfff1ae24b0864c6bb7fc34112e21f 100644
--- a/spec/services/ci/create_downstream_pipeline_service_spec.rb
+++ b/spec/services/ci/create_downstream_pipeline_service_spec.rb
@@ -777,13 +777,11 @@
       it 'does not create a pipeline and drops the bridge' do
         expect { subject }.not_to change(downstream_project.ci_pipelines, :count)
         expect(subject).to be_error
-        expect(subject.message).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(subject.message).to match_array([Ci::Pipeline.rules_failure_message])
 
         expect(bridge.reload).to be_failed
         expect(bridge.failure_reason).to eq('downstream_pipeline_creation_failed')
-        expect(bridge.options[:downstream_errors]).to match_array(['Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.'])
+        expect(bridge.options[:downstream_errors]).to match_array([Ci::Pipeline.rules_failure_message])
       end
     end
 
diff --git a/spec/services/ci/create_pipeline_service/rules_spec.rb b/spec/services/ci/create_pipeline_service/rules_spec.rb
index ee9031cd7d17d32efa8ba93c0f99941b9a38e265..c5a0907f490d0ed5268b19189a574096e562df65 100644
--- a/spec/services/ci/create_pipeline_service/rules_spec.rb
+++ b/spec/services/ci/create_pipeline_service/rules_spec.rb
@@ -1309,7 +1309,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/wip' }
 
         it 'invalidates the pipeline with a workflow rules error' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1318,7 +1318,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/fix' }
 
         it 'invalidates the pipeline with a workflow rules error' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1375,7 +1375,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/feature_conflict' }
 
         it 'invalidates the pipeline with a workflow rules error' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1401,8 +1401,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/master' }
 
         it 'invalidates the pipeline with an empty jobs error' do
-          expect(pipeline.errors[:base]).to include('Pipeline will not run for the selected trigger. ' \
-            'The rules configuration prevented any jobs from being added to the pipeline.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1420,7 +1419,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/fix' }
 
         it 'invalidates the pipeline with a workflow rules error' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1429,7 +1428,7 @@ def find_job(name)
         let(:ref) { 'refs/heads/wip' }
 
         it 'invalidates the pipeline with a workflow rules error' do
-          expect(pipeline.errors[:base]).to include('Pipeline filtered out by workflow rules.')
+          expect(pipeline.errors[:base]).to include(Ci::Pipeline.workflow_rules_failure_message)
           expect(pipeline).not_to be_persisted
         end
       end
@@ -1621,7 +1620,7 @@ def find_job(name)
           end
 
           it 'creates the pipeline with a job' do
-            expect(pipeline.errors.full_messages).to eq(['Pipeline filtered out by workflow rules.'])
+            expect(pipeline.errors.full_messages).to eq([Ci::Pipeline.workflow_rules_failure_message])
             expect(response).to be_error
             expect(pipeline).not_to be_persisted
           end
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index b5280c9c5fdbf9f0dc8ba89a2c93e6c2f48c9633..ce02bfea7f11ef0aa38940c2cc4d8dc0553d7565 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -694,8 +694,7 @@ def previous_commit_sha_from_ref(ref)
         result = execute_service
 
         expect(result).to be_error
-        expect(result.message).to eq('Pipeline will not run for the selected trigger. ' \
-          'The rules configuration prevented any jobs from being added to the pipeline.')
+        expect(result.message).to eq(Ci::Pipeline.rules_failure_message)
         expect(result.payload).not_to be_persisted
         expect(Ci::Build.all).to be_empty
         expect(Ci::Pipeline.count).to eq(0)
@@ -1265,11 +1264,9 @@ def previous_commit_sha_from_ref(ref)
 
               it 'does not create a detached merge request pipeline', :aggregate_failures do
                 expect(response).to be_error
-                expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.')
+                expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
                 expect(pipeline).not_to be_persisted
-                expect(pipeline.errors[:base]).to eq(['Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.'])
+                expect(pipeline.errors[:base]).to eq([Ci::Pipeline.rules_failure_message])
               end
             end
           end
@@ -1479,8 +1476,7 @@ def previous_commit_sha_from_ref(ref)
 
               it 'does not create a detached merge request pipeline', :aggregate_failures do
                 expect(response).to be_error
-                expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                  'The rules configuration prevented any jobs from being added to the pipeline.')
+                expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
                 expect(pipeline).not_to be_persisted
               end
             end
@@ -1516,8 +1512,7 @@ def previous_commit_sha_from_ref(ref)
 
             it 'does not create a detached merge request pipeline', :aggregate_failures do
               expect(response).to be_error
-              expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.')
+              expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
               expect(pipeline).not_to be_persisted
             end
           end
@@ -1545,8 +1540,7 @@ def previous_commit_sha_from_ref(ref)
 
             it 'does not create a detached merge request pipeline', :aggregate_failures do
               expect(response).to be_error
-              expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.')
+              expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
               expect(pipeline).not_to be_persisted
             end
           end
@@ -1576,8 +1570,7 @@ def previous_commit_sha_from_ref(ref)
 
             it 'does not create a detached merge request pipeline', :aggregate_failures do
               expect(response).to be_error
-              expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.')
+              expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
               expect(pipeline).not_to be_persisted
             end
           end
@@ -1605,8 +1598,7 @@ def previous_commit_sha_from_ref(ref)
 
             it 'does not create a detached merge request pipeline', :aggregate_failures do
               expect(response).to be_error
-              expect(response.message).to eq('Pipeline will not run for the selected trigger. ' \
-                'The rules configuration prevented any jobs from being added to the pipeline.')
+              expect(response.message).to eq(Ci::Pipeline.rules_failure_message)
               expect(pipeline).not_to be_persisted
             end
           end