Categories
Tech

Auto generate merge requests for new branches on Gitlab

I want to have a new merge request (MR) created for every branch in the feature/* namespace. It is possible to use push options to automatically create the branch, but every developer has to remember to use those options. I found this post on the Gitlab blog from 2017, that describes another way: Using Gitlab CI to check if there is a MR for a given branch, and if not create it.

I have adopted that solution, replaced python with jq to parse the API responses and used some predefined environment variables here and there, that didn’t exist at the time the original script was written.

# automatically open a MR for every feature/* branch
open_mr:
  rules:
    - if: $CI_COMMIT_BRANCH =~ /^feature/
  before_script: []   # We do not need any setup work, let's remove the global one (if any)
  stage: build
  image: everpeace/curl-jq
  script:
    # The description of our new MR, we want to remove the branch after the MR has
    # been closed
    - |-
      BODY="{
        \"id\":${CI_PROJECT_ID},
        \"source_branch\":\"${CI_COMMIT_REF_NAME}\",
        \"target_branch\":\"${CI_DEFAULT_BRANCH}\",
        \"remove_source_branch\":true,
        \"title\":\"WIP: ${CI_COMMIT_REF_NAME}\",
        \"assignee_id\":\"${GITLAB_USER_ID}\"
      }"
    # Require a list of all the merge request and take a look if there is already
    # one with the same source branch
    - LISTMR=`curl --silent "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests?state=opened" --header "PRIVATE-TOKEN:${GITLAB_ACCESS_TOKEN}"`
    - HASBRANCHES=`echo ${LISTMR} | jq --raw-output 'any ( .source_branch =="'${CI_COMMIT_REF_NAME}'")'`

    # No MR found, let's create a new one
    - |-
      if [ ${HASBRANCHES} = "false" ]; then
        curl -X POST "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests" --header "PRIVATE-TOKEN:${GITLAB_ACCESS_TOKEN}" --header "Content-Type:application/json" --data "${BODY}";
        echo "Opened a new merge request: WIP: ${CI_COMMIT_REF_NAME} and assigned to you";
        exit;
      fi
    - echo "No new merge request opened"

You need to define a variable GITLAB_ACCESS_TOKEN with an access token with API scope for this to work. Also if you use workflow rules, to limit when a pipeline is created, it needs to be configured to create pipelines for feature/* branches. For reference, this is what I am using:

# Run for every tag, MR and master. Also for every feature/* branch
workflow:
  rules:
    - if: $CI_MERGE_REQUEST_IID
    - if: $CI_COMMIT_TAG
    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
    - if: $CI_COMMIT_BRANCH =~ /^feature/