Skip to content

Instantly share code, notes, and snippets.

@tyrcho
Last active March 28, 2023 16:16
Show Gist options
  • Select an option

  • Save tyrcho/3f15273497ff9d5b5a0b12c672094387 to your computer and use it in GitHub Desktop.

Select an option

Save tyrcho/3f15273497ff9d5b5a0b12c672094387 to your computer and use it in GitHub Desktop.
Script to accept Gitlab MRs when the pipeline has succeeded. Sample : https://gitlab.com/tyrcho/michel-steward/-/blob/master/.gitlab-ci.yml
#!/usr/bin/env bash
curl_gitlab() {
echo $* >&2
URL_SUFFIX=$1
shift
curl \
--silent \
--show-error \
--fail \
--header "PRIVATE-TOKEN: $GITLAB_PAT" \
"https://gitlab.com/api/v4/$URL_SUFFIX" $*
}
get_project_id() {
PROJECTS_FILTER=$1
NAME=$2
curl_gitlab "$PROJECTS_FILTER$NAME" \
| jq -r '.[] | select(.path == "'$NAME'") | "\(.id)"'
}
merge_mr() {
PROJECT_ID=$1
MR_ID=$2
MERGE_WHEN_PIPELINE_SUCCEEDS=${3:-false}
curl_gitlab "projects/$PROJECT_ID/merge_requests/$MR_ID/merge?should_remove_source_branch=true&merge_when_pipeline_succeeds=$MERGE_WHEN_PIPELINE_SUCCEEDS" -X PUT
ret=$?
echo
if [ $ret -eq 0 ] ; then
echo "MR $MR_ID was merged" >&2
else
echo "MR $MR_ID was not merged" >&2
fi
return $ret
}
# Rebase the MR then sets it to "merge when pipeline succeeds"
rebase_mr() {
PROJECT_ID=$1
MR_ID=$2
curl_gitlab "projects/$PROJECT_ID/merge_requests/$MR_ID/rebase" -X PUT
ret=$?
if [ $ret -eq 0 ] ; then
echo "MR $MR_ID was rebased"
sleep 10
merge_mr $PROJECT_ID $MR_ID true
else
echo "MR $MR_ID was not rebased"
fi
return $ret
}
get_pipeline_status() {
PROJECT_ID=$1
MR_IID=$2
curl_gitlab "projects/$PROJECT_ID/merge_requests/$MR_IID" \
| jq -r ' "\(.pipeline.status)"'
}
all_open_mrs() {
AUTHOR_ID=$1
PROJECT_ID=$2
curl_gitlab \
"projects/$PROJECT_ID/merge_requests?state=opened&scope=all&author_id=$AUTHOR_ID" \
| jq -r '.[] | "\(.iid)"' \
| tr '\r\n' ' '
}
nurture_mr() {
project_id=$1
mr_id=$2
echo "nurturing MR $mr_id" >&2
status=$(get_pipeline_status $project_id $mr_id)
echo "pipeline status is $status" >&2
if [ "$status" = "success" ] ; then
merge_mr $project_id $mr_id
else
rebase_mr $project_id $mr_id
fi
}
nurture_project() {
project_name=$1
project_id=$(get_project_id $PROJECTS_FILTER $project_name)
echo "nurturing project $project_name (id $project_id)" >&2
local nurtured_count=0
local mrs=$(all_open_mrs $AUTHOR_ID $project_id)
echo "MRs found : [$mrs]" >&2
for mr_id in $mrs ; do
((nurtured_count < MAX_MRS)) || return 0
if nurture_mr $project_id $mr_id; then
((nurtured_count++))
fi
done
# finish with a return code 0 even if some MRs could not be merged / rebased
echo "finished with project $project_name (id $project_id)" >&2
echo "" >&2
}
usage() {
echo "Usage:"
echo "$0 GITLAB_ACCESS_TOKEN AUTHOR_ID FILTER 'name1 name2 name3' MAX_MRS"
echo
echo "examples:"
echo "$0 df12fs1sdd 12345 'groups/789/search?scope=projects&search=' 'a b c' 3"
echo "$0 df12fs1sdd 12345 'users/123/projects?search=' 'a b c'"
exit 1
}
[ $# -eq 5 ] || usage
GITLAB_PAT=$1
AUTHOR_ID=$2
PROJECTS_FILTER=$3
PROJECT_NAMES="$4"
MAX_MRS=$5
for project_name in $PROJECT_NAMES ; do
nurture_project $project_name
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment