Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Gitlab job to run ONLY ONCE when Merge Request is created

Tags:

gitlab-ci

I want some specific jobs in my pipeline run only one time when I create a Merge Request. For example to assign reviewer for the MR, or to migrate data from QA environment.

Is there a way to achieve this in Gitlab?

like image 400
TomNg Avatar asked Dec 06 '25 06:12

TomNg


1 Answers

This is currently (Jul 2024) impossible just by using rules / only / etc.

You can use a label to track which MRs have been "processed" already:

  1. Inside the job, use GitLab API to tag the current MR with a label.
  2. Skip the job if the label is already present.

Sample implementation of a job posting a checklist to each newly created MR:

stages:
  - mr_only_once
  - ...

# This job will run only once when a MR is created
checklist:
  stage: mr_only_once

  rules:
    - if: $CI_PIPELINE_SOURCE == 'merge_request_event'

  variables:
    MESSAGE: |
      ## PR checklist

      - [ ] I updated the changelog
      - [ ] I updated documentation
  
  script:
    # Create a bot user and a personal access token; in this case I have put
    # this token into GitLab variables and named "BOT_TOKEN"
    - TOKEN="$BOT_TOKEN"

    # We will be using this GitLab endpoint to interact with the MR;
    # the $CI_... variables are provided by GitLab while the job is running
    - MERGE_REQUEST_API="$CI_SERVER_URL/api/v4/projects/$CI_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID"

    # Get PR labels
    - |
      LABELS=$(curl -sSf --header "PRIVATE-TOKEN: $TOKEN" "$MERGE_REQUEST_API" | jq -c '.labels')

    # Post a comment and assign the ~checklist_done label
    - |
      if [[ "$LABELS" != *'"~checklist_done"'* ]]; then
        # Construct the JSON body with proper escaping
        POST_JSON=$(jq -n --arg body "$MESSAGE" --argjson resolved false '{body: $body, resolved: $resolved}')

        # Post a comment on the merge request
        curl -sSf --request POST \
          --header "PRIVATE-TOKEN: $TOKEN" \
          --header "Content-Type: application/json" \
          --data "$POST_JSON" \
          "$MERGE_REQUEST_API/discussions"
          
        # Add a label so that we know not to post the same comment again
        curl -sSf --request PUT \
          --header "PRIVATE-TOKEN: $TOKEN" \
          --header "Content-Type: application/json" \
          --data '{"add_labels": "~checklist_done"}' \
          "$MERGE_REQUEST_API"
      fi
like image 194
Emily Kazak Avatar answered Dec 08 '25 23:12

Emily Kazak



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!