diff --git a/Dockerfile b/Dockerfile index fd53295..3bb0e96 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,6 @@ -FROM concourse/buildroot:git +FROM alpine/git + +RUN apk add --no-cache curl curl-dev bash jq COPY scripts/ /opt/resource/ RUN chmod +x /opt/resource/* diff --git a/README.md b/README.md index a24e01c..b79eb6e 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,10 @@ Updates the merge request's `merge_status` which displays nicely in the GitLab U * `repository`: The path of the repository of the merge request's source branch (required) * `status`: The new status of the merge request (required, can be either `pending`, `running`, `success`, `failed`, or `canceled`) * `build_label`: The label of the build in GitLab (optional, defaults to `"Concourse"`) +* `comment`: Add a comment to the MRs open on the branch that is being target by concourse. Could be an object with `text/file(s)` fields. +If just the `file(s)` or `text` is specified it is used to populate the field, if both file and text are specified then the file(s) is substituted in to the text comment. +If only one file is specified (field `file`) then it replace `$FILE_CONTENT` in the text. +If multiple files are specified (field `files`) then it replace a variable with the key of the file (look the example for a better clarification) ## Example @@ -88,4 +92,14 @@ jobs: params: repository: repo status: success + comment: + files: + original: in/comment.txt + updated: out/comment.txt + text: | + Original comment: + $original + + new comment: + $updated ``` diff --git a/scripts/in b/scripts/in index 8fe0fd6..4744f06 100755 --- a/scripts/in +++ b/scripts/in @@ -12,7 +12,7 @@ source "$(dirname "$0")/common.sh" destination="$1" -if [ -z "${destination}" ]; then +if [[ -z "${destination}" ]]; then echo "Usage: $0 " >&2 exit 1 fi diff --git a/scripts/out b/scripts/out index 227ec5f..2e74f1c 100755 --- a/scripts/out +++ b/scripts/out @@ -12,7 +12,7 @@ source "$(dirname "$0")/common.sh" destination="$1" -if [ -z "${destination}" ]; then +if [[ -z "${destination}" ]]; then echo "Usage: $0 " >&2 exit 1 fi @@ -27,16 +27,19 @@ uri="$(jq -r '.source.uri // ""' < "${payload}")" private_token="$(jq -r '.source.private_token // ""' < "${payload}")" private_key="$(jq -r '.source.private_key // ""' < "${payload}")" no_ssl="$(jq -r '.source.no_ssl // ""' < "${payload}")" -params="$(jq -r '.params // ""' < "${payload}")" -path_to_repo="$(echo "${params}" | jq -r '.repository // ""')" -new_status="$(echo "${params}" | jq -r '.status // ""')" -build_label="$(echo "${params}" | jq -r '.build_label // "Concourse"')" - -if [ -z "${path_to_repo}" ]; then +path_to_repo="$(jq -c -r '.params.repository // ""' < "${payload}")" +new_status="$(jq -c -r '.params.status // ""' < "${payload}")" +build_label="$(jq -c -r '.params.build_label // "Concourse"' < "${payload}")" +comment_text="$(jq -c -r '.params.comment.text // ""' < "${payload}")" +comment_file="$(jq -c -r '.params.comment.file // ""' < "${payload}")" +comment_files="$(jq -c -r '.params.comment.files // ""' < "${payload}")" +comment="" + +if [[ -z "${path_to_repo}" ]]; then echo "please specify a repository" >&2 exit 1 fi -if [ -z "${new_status}" ]; then +if [[ -z "${new_status}" ]]; then echo "please specify a status" >&2 exit 1 fi @@ -54,13 +57,39 @@ else project_path="$(echo "${uri}" | sed -rn 's/(https?):\/\/([^\/]*)\/(.*)\.git/\3/p')" protocol="$(echo "${uri}" | sed -rn 's/(https?):\/\/([^\/]*)\/(.*)\.git/\1/p')" fi -if [ "${no_ssl}" == 'true' ]; then +if [[ "${no_ssl}" == 'true' ]]; then protocol='http' fi target_url="${ATC_EXTERNAL_URL}/teams/$(urlencode "${BUILD_TEAM_NAME}")/pipelines/$(urlencode "${BUILD_PIPELINE_NAME}")/jobs/$(urlencode "${BUILD_JOB_NAME}")/builds/$(urlencode "${BUILD_NAME}")" cd "${destination}" + +if [[ (-z "${comment_files}") && (! -z "${comment_file}") ]]; then + comment_files=$(echo "${comment_file}" | jq -c --raw-input '{ "FILE_CONTENT": . }') +fi + +if [[ (! -z "${comment_text}") ]]; then + comment=$(echo "${comment_text}" | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n//g') + + if [[ ! -z "${comment_files}" ]]; then + for row in $(echo "${comment_files}" | jq -c -r 'to_entries[] | @base64'); do + _jq() { + echo ${row} | base64 -d | jq -r ${1} + } + + file_key=$(echo "\$$(_jq '.key')" | sed -e 's/[]\/$*.^[]/\\&/g') + file_name=$(_jq '.value') + if [ -f "${file_name}" ]; then + file_content=$(cat | sed -e ':a' -e 'N' -e '$!ba' -e 's/\n//g' -e 's/[\/&]/\\&/g' "${file_name}") + comment=$(echo "${comment}" | sed "s/${file_key}/${file_content}/g") + fi + done + fi +elif [[ (! -z "${comment_file}") ]]; then + comment=$(cat "${comment_file}") +fi + cd "${path_to_repo}" commit_sha="$(git rev-parse HEAD)" @@ -72,6 +101,24 @@ curl \ --data "{\"state\":\"${new_status}\",\"name\":\"${build_label}\",\"target_url\":\"${target_url}\"}" \ "${protocol}://${gitlab_host}/api/v4/projects/$(urlencode "${project_path}")/statuses/${commit_sha}" +if [[ (! -z "${private_key}") && (! -z "${comment}") ]]; then + git_branch=$(git show-ref --heads | sed -n "s/^$(git rev-parse HEAD) refs\/heads\/\(.*\)/\1/p") + merge_requests=$(curl \ + --request GET \ + --header "PRIVATE-TOKEN: ${private_token}" \ + "${protocol}://${gitlab_host}/api/v4/projects/$(urlencode "${project_path}")/merge_requests?source_branch=${git_branch}") + + for merge_request_id in $(echo "${merge_requests}" | jq -r '.[].iid'); do + # Post comment to each merge request + curl \ + --request POST \ + --data "$(echo "${comment}" | jq -c -R '{ "body": . }')" \ + --header "Content-Type: application/json" \ + --header "PRIVATE-TOKEN: ${private_token}" \ + "${protocol}://${gitlab_host}/api/v4/projects/$(urlencode "${project_path}")/merge_requests/$(urlencode "${merge_request_id}")/notes" + done +fi + version="{\"sha\":\"${commit_sha}\"}" jq -n "{