Search code examples
gitlabcontinuous-integrationgitlab-cigitlab-ci-runnercontinuous-delivery

Run Gitlab CI job only once when MR open


I have a scenario in Gitlab where I would like to ping a particular Slack channel when an MR is opened up for the first time in Gitlab. I've attempted to use rules for triggering when the source is merge_request_event but, unfortunately, this also triggers my job when a new commit is pushed to the open MR.

Is it possible to run a Gitlab CI job once when the MR is initially opened, and never again after that point, even when new commits are added to the MR?

ping:
  stage: .pre
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
  script:
    - 'curl to slack url'

Solution

  • For your use case, you wouldn't be able to use GitLab CI/CD because a Merge Request Pipeline is started when a Merge Request is opened, a commit is pushed to the source branch of the Merge Request, or if someone hits the Run Pipeline button from the Pipelines tab on a Merge Request.

    Those are the only ways to start a Merge Request pipeline, but any of those will always start a pipeline.

    Instead of doing this in CI/CD, your best bet is to create a small application that can listen for GitLab Webhooks, and specifically react to Merge Request events where the action field is open. Here's an example Merge Request Open event from the docs.

    {
      "object_kind": "merge_request",
      "user": {
        "id": 1,
        "name": "Administrator",
        "username": "root",
        "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon",
        "email": "admin@example.com"
      },
      "project": {
        "id": 1,
        "name":"Gitlab Test",
        "description":"Aut reprehenderit ut est.",
        "web_url":"http://example.com/gitlabhq/gitlab-test",
        "avatar_url":null,
        "git_ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
        "git_http_url":"http://example.com/gitlabhq/gitlab-test.git",
        "namespace":"GitlabHQ",
        "visibility_level":20,
        "path_with_namespace":"gitlabhq/gitlab-test",
        "default_branch":"master",
        "homepage":"http://example.com/gitlabhq/gitlab-test",
        "url":"http://example.com/gitlabhq/gitlab-test.git",
        "ssh_url":"git@example.com:gitlabhq/gitlab-test.git",
        "http_url":"http://example.com/gitlabhq/gitlab-test.git"
      },
      "repository": {
        "name": "Gitlab Test",
        "url": "http://example.com/gitlabhq/gitlab-test.git",
        "description": "Aut reprehenderit ut est.",
        "homepage": "http://example.com/gitlabhq/gitlab-test"
      },
      "object_attributes": {
        "id": 99,
        "target_branch": "master",
        "source_branch": "ms-viewport",
        "source_project_id": 14,
        "author_id": 51,
        "assignee_id": 6,
        "title": "MS-Viewport",
        "created_at": "2013-12-03T17:23:34Z",
        "updated_at": "2013-12-03T17:23:34Z",
        "milestone_id": null,
        "state": "opened",
        "merge_status": "unchecked",
        "target_project_id": 14,
        "iid": 1,
        "description": "",
        "source": {
          "name":"Awesome Project",
          "description":"Aut reprehenderit ut est.",
          "web_url":"http://example.com/awesome_space/awesome_project",
          "avatar_url":null,
          "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
          "git_http_url":"http://example.com/awesome_space/awesome_project.git",
          "namespace":"Awesome Space",
          "visibility_level":20,
          "path_with_namespace":"awesome_space/awesome_project",
          "default_branch":"master",
          "homepage":"http://example.com/awesome_space/awesome_project",
          "url":"http://example.com/awesome_space/awesome_project.git",
          "ssh_url":"git@example.com:awesome_space/awesome_project.git",
          "http_url":"http://example.com/awesome_space/awesome_project.git"
        },
        "target": {
          "name":"Awesome Project",
          "description":"Aut reprehenderit ut est.",
          "web_url":"http://example.com/awesome_space/awesome_project",
          "avatar_url":null,
          "git_ssh_url":"git@example.com:awesome_space/awesome_project.git",
          "git_http_url":"http://example.com/awesome_space/awesome_project.git",
          "namespace":"Awesome Space",
          "visibility_level":20,
          "path_with_namespace":"awesome_space/awesome_project",
          "default_branch":"master",
          "homepage":"http://example.com/awesome_space/awesome_project",
          "url":"http://example.com/awesome_space/awesome_project.git",
          "ssh_url":"git@example.com:awesome_space/awesome_project.git",
          "http_url":"http://example.com/awesome_space/awesome_project.git"
        },
        "last_commit": {
          "id": "da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
          "message": "fixed readme",
          "timestamp": "2012-01-03T23:36:29+02:00",
          "url": "http://example.com/awesome_space/awesome_project/commits/da1560886d4f094c3e6c9ef40349f7d38b5d27d7",
          "author": {
            "name": "GitLab dev user",
            "email": "gitlabdev@dv6700.(none)"
          }
        },
        "work_in_progress": false,
        "url": "http://example.com/diaspora/merge_requests/1",
        "action": "open",
        "assignee": {
          "name": "User1",
          "username": "user1",
          "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon"
        }
      },
      "labels": [{
        "id": 206,
        "title": "API",
        "color": "#ffffff",
        "project_id": 14,
        "created_at": "2013-12-03T17:15:43Z",
        "updated_at": "2013-12-03T17:15:43Z",
        "template": false,
        "description": "API related issues",
        "type": "ProjectLabel",
        "group_id": 41
      }],
      "changes": {
        "updated_by_id": {
          "previous": null,
          "current": 1
        },
        "updated_at": {
          "previous": "2017-09-15 16:50:55 UTC",
          "current":"2017-09-15 16:52:00 UTC"
        },
        "labels": {
          "previous": [{
            "id": 206,
            "title": "API",
            "color": "#ffffff",
            "project_id": 14,
            "created_at": "2013-12-03T17:15:43Z",
            "updated_at": "2013-12-03T17:15:43Z",
            "template": false,
            "description": "API related issues",
            "type": "ProjectLabel",
            "group_id": 41
          }],
          "current": [{
            "id": 205,
            "title": "Platform",
            "color": "#123123",
            "project_id": 14,
            "created_at": "2013-12-03T17:15:43Z",
            "updated_at": "2013-12-03T17:15:43Z",
            "template": false,
            "description": "Platform related issues",
            "type": "ProjectLabel",
            "group_id": 41
          }]
        }
      }
    }
    

    The key things here for you are the object_kind field at the top since this will be issue, merge_request, push, tag_push, etc. and we can filter on merge_request. Next, the action field will tell us what happened with the Merge Request. In this example the value is open which means the Merge Request was opened. Other values are close, reopen, update, approved, unapproved, and merge.

    Currently, this is the only way to find out if a Merge Request was opened without the other events that start a Merge Request Pipeline.