Scheduled pipeline to run only after a new merge request is completed

Hi there!

Have a question regarding scheduling pipelines, the core functionality is that I only want to push a new build at a specific time weekly if we had a successful merge request during the week. If there are no merge requests done during the week, then the scheduled pipeline should not run.

Can that be achieved?

I see that CI_PIPELINE_SOURCE can be equal to a number of options including schedule or merge_request_event

Because I know people look at forums in the future because of web crawlers and wanting the same functionality, I was able to make something that does the logic I want. I do not know if it’s the most elegant and there are probably ways to reduce the size & make it more secure, not use just a template for the schedule, blah blah. I just wanted to get it out there for other people to see.

.gitlab-ci.yml:

stages:
  - schedule
  - build
  - push

.prod_variables: &prod_variables
  ENV: production

.template-schedule: &template-schedule
  stage: schedule
  image: ubuntu:22.04   # I want to reduce this image overhead, if replacing with busybox, I just need date command to give me ISO8601 from a week ago & curl 
  script:
    - apt update -y && apt upgrade -y
    - apt-get install -y curl
    # - printenv # just for debugging
    - ./linuxdeploy.sh
  environment:
    name: $ENV

check-schedule-prod:
  <<: *template-schedule
  variables:
   <<: *prod_variables
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

build-schedule-prod:
  stage: build
  variables:
   <<: *prod_variables
  script:
    - echo "Building" # just a placeholder for a docker build that then can be used in the next stage for a push
  environment:
    name: $ENV
  rules:
    - if: '$CI_PIPELINE_SOURCE == "api"'

push-schedule-prod:
  stage: push
  variables:
   <<: *prod_variables
  script:
    - echo "Pushing" # just a placeholder for like a docker push stage to a repo with the artifact from the previous stage
  environment:
    name: $ENV
  rules:
    - if: '$CI_PIPELINE_SOURCE == "api"'

linuxdeploy.sh

#!/bin/bash

set -e -o pipefail

main()
{
    get_mergerequests 0
}

get_mergerequests() {

  # 5 vars within the script
  gitlab_url=gitlab.example.com
  dateISO8601=$(date --date="7 day ago" +"%Y-%m-%dT%H:%M:%SZ") # 7 days ago in a format the gitlab API needs
  project_id=1 # Pipeline sample
  state=merged
  approved=yes

  # $GitlabPAT needs to be set in the schedule vars and be created by a user who allows it access to the API

  # Just to verify your system is displaying ISO8601
  echo $dateISO8601

  # Get a response back checking for MRs using a gitlab PAT ENV VAR on a specific project, approved, merged and within the past week

  MR_RESP=$(curl --request GET --silent --header "PRIVATE-TOKEN: $GitlabPAT" "$gitlab_url/api/v4/projects/$project_id/merge_requests?approved=$approved&created_after=$dateISO8601&state=$state")

  if [ "$MR_RESP" = [] ]; then
      echo "Detected No Merge Requests that were approved, merged and created within the last week, completed check"
  else
      echo "Detected a MR that was approved, merged and created with the last week, calling create pipeline to activate deployment, schedule will need GitlabPAT defined with a proper API key to work"
      NEWPIPELINE_RESP=$(curl --request POST --silent --header "PRIVATE-TOKEN: $GitlabPAT" "$gitlab_url/api/v4/projects/$project_id/pipeline?ref=main")
  fi

}

main
2 Likes