<p>This is because despite looking like a conditional with an <code>if:</code> statement,</p>
<pre class="lang-yaml prettyprint-override"><code>rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
</code></pre>
<p>This <strong>actually does change the behavior</strong>, <a href="https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html" rel="nofollow noreferrer">it enables &quot;Merge Request Pipelines&quot; by satisfying the criteria,</a>.</p>
<blockquote>
<p>Your project’s .gitlab-ci.yml file must be configured with jobs that run in merge request pipelines. To do this, you can use:</p>
<ul>
<li>rules.</li>
<li>only/except.</li>
</ul>
</blockquote>
<p>Assume we have a repo <code>foo</code> and we fork it into <code>bar</code>. If we open a merge request (adding a new file) from <code>bar</code> to <code>foo</code>, you'll see the same high level overview,</p>
<p><a href="https://i.sstatic.net/FHjeOl.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/FHjeOl.png" alt="New merge request" /></a></p>
<p>But adding the rule <code>$CI_PIPELINE_SOURCE == 'merge_request_event'</code> causes a few different things to happen,</p>
<ul>
<li>The pipeline is no longer a &quot;Push Pipeline&quot; it's a <a href="https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html" rel="nofollow noreferrer">&quot;Merge Request Pipeline&quot;</a> and it has a different tag.</li>
<li>The pipeline is no longer run on the fork, but from the &quot;base&quot; project</li>
<li>The commit the pipeline runs on is no longer run on the fork, but from <code>refs/merge_requests</code> in the &quot;base&quot; project.</li>
</ul>
<p>I believe this gives a better idea of how this process works, but you should read the full official documentation page on <a href="https://docs.gitlab.com/ee/ci/pipelines/merge_request_pipelines.html" rel="nofollow noreferrer">&quot;Merge Request Pipelines&quot;</a> to compliment any understanding this gives.</p>
<h1>Without <em>&quot;Merge Request Pipelines&quot;</em></h1>
<p>However, everything is different from this point on. When you're <strong>NOT</strong> using &quot;Merged Request Pipelines&quot;, the merge request page will link to the pipeline like this,</p>
<p><a href="https://i.sstatic.net/5duoGm.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/5duoGm.png" alt="link to pipeline" /></a></p>
<p>Note <em>&quot;Pipeline&quot;</em> here is more correctly &quot;Push Pipeline&quot;. If you click on that number, the pipeline itself will show under <code>bar</code> <strong>the fork</strong> for example under this path <code>bar/-/pipelines/455884</code></p>
<p><a href="https://i.sstatic.net/JkYPDl.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/JkYPDl.png" alt="Pipelines in bar" /></a></p>
<p>And it will show the job,</p>
<p><a href="https://i.sstatic.net/QXlzKm.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/QXlzKm.png" alt="Job detail from bar" /></a></p>
<p>If you dump the environment from that job you'll see</p>
<pre><code>CI_PIPELINE_SOURCE=push
</code></pre>
<p>And this is true. The pipeline <strong>is running on the branch</strong> (in this case <code>foobar</code>), and that can be seen on <code>bar/-/tree/foobar</code>,</p>
<p><a href="https://i.sstatic.net/8CiY1l.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/8CiY1l.png" alt="foobar branch" /></a></p>
<h1>With <em>&quot;Merge Request Pipelines&quot;</em></h1>
<p>Now let's add the configuration and rerun,</p>
<pre class="lang-yaml prettyprint-override"><code>rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
</code></pre>
<p>Now you'll see this on the merge request sitting on <code>foo</code>,</p>
<p><a href="https://i.sstatic.net/Pb5kQm.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/Pb5kQm.png" alt="Foo's merge request" /></a></p>
<p>Immediately take note to it saying <em>&quot;Merge request pipeline&quot;</em> rather than <em>&quot;Pipeline&quot;</em>. When you click on that pipeline number #455999 you'll be taken <strong>NOT</strong> to bar's pipelines, as you were above, but instead to foo's pipelines, <code>foo/-/pipelines/455999</code> and here you'll see this summary which has the tag <code>merge_request</code>.</p>
<p><a href="https://i.sstatic.net/nBchkl.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/nBchkl.png" alt="Merge Request Pipeline summary" /></a></p>
<p>Clicking on the job's tab, you'll be taken to foo's jobs, <code>foo/-/pipelines/455999/builds</code> and you'll see this,</p>
<p><a href="https://i.sstatic.net/UkMge.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/UkMge.png" alt="Merged Request Pipeline Job" /></a></p>
<p>And that's showing you that the merge request no longer comes from the branch <code>foobar</code> in reality, it's pulled foobar down to the git merge request directory <code>foo/-/commits/refs/merge-requests/1/head</code> and the merge request now points to that, which resembles the commit <strong>AFTER</strong> it has merged.</p>
<hr />
<p><a href="https://gitlab.com/groups/gitlab-org/-/epics/2783#note_1826457181" rel="nofollow noreferrer">I posted this comment on the GitLab Rule Epic to let them know my thoughts on this</a></p>

CC BY-SA 4.0
2024-03-21T22:57:04.363Z
2024-06-18T14:45:56.240Z
2024-06-18T14:45:56.240Z
Evan Carroll
<p>I have in my gitlab.yml file,</p>
<pre class="lang-yaml prettyprint-override"><code>rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
</code></pre>
<p>Before adding that my pipeline was working fine. I just wanted to make it such that the job above was <em>only</em> run on <code>merge_request_event</code>. Now that I added that, the <em>behavior</em> seems to change. How is this rule implemented?</p>

<gitlab><gitlab-ci>
How does $CI_PIPELINE_SOURCE == 'merge_request_event' work?
Evan Carroll
# How does $CI_PIPELINE_SOURCE == 'merge_request_event' work?

(Asked by: username_0 on 2024-03-21)

I have in my gitlab.yml file,
rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

Before adding that my pipeline was working fine. I just wanted to make it such that the job above was only run on merge_request_event. Now that I added that, the behavior seems to change. How is this rule implemented?

**Tags:** gitlab, gitlab-ci


---

## 1 answers

### Answer by username_0 on 2024-03-21. Score: 0 | Accepted answer

This is because despite looking like a conditional with an if: statement,
rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

This actually does change the behavior, it enables "Merge Request Pipelines" by satisfying the criteria,.

Your project’s .gitlab-ci.yml file must be configured with jobs that run in merge request pipelines. To do this, you can use:

rules.
only/except.


Assume we have a repo foo and we fork it into bar. If we open a merge request (adding a new file) from bar to foo, you'll see the same high level overview,

But adding the rule $CI_PIPELINE_SOURCE == 'merge_request_event' causes a few different things to happen,

The pipeline is no longer a "Push Pipeline" it's a "Merge Request Pipeline" and it has a different tag.
The pipeline is no longer run on the fork, but from the "base" project
The commit the pipeline runs on is no longer run on the fork, but from refs/merge_requests in the "base" project.

I believe this gives a better idea of how this process works, but you should read the full official documentation page on "Merge Request Pipelines" to compliment any understanding this gives.
Without "Merge Request Pipelines"
However, everything is different from this point on. When you're NOT using "Merged Request Pipelines", the merge request page will link to the pipeline like this,

Note "Pipeline" here is more correctly "Push Pipeline". If you click on that number, the pipeline itself will show under bar the fork for example under this path bar/-/pipelines/455884

And it will show the job,

If you dump the environment from that job you'll see
CI_PIPELINE_SOURCE=push

And this is true. The pipeline is running on the branch (in this case foobar), and that can be seen on bar/-/tree/foobar,

With "Merge Request Pipelines"
Now let's add the configuration and rerun,
rules:
  - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

Now you'll see this on the merge request sitting on foo,

Immediately take note to it saying "Merge request pipeline" rather than "Pipeline". When you click on that pipeline number #455999 you'll be taken NOT to bar's pipelines, as you were above, but instead to foo's pipelines, foo/-/pipelines/455999 and here you'll see this summary which has the tag merge_request.

Clicking on the job's tab, you'll be taken to foo's jobs, foo/-/pipelines/455999/builds and you'll see this,

And that's showing you that the merge request no longer comes from the branch foobar in reality, it's pulled foobar down to the git merge request directory foo/-/commits/refs/merge-requests/1/head and the merge request now points to that, which resembles the commit AFTER it has merged.

I posted this comment on the GitLab Rule Epic to let them know my thoughts on this


---

