There are many questions on how to post JSON via curl
. And I am able to send one word as json but not the whole text.
My requirement is to comment a merge request when one job fail in our GitLab CI.
# From .gitlab-ci.yaml
after_script:
- report=$(find services/ -name '*_latest_failure.md')
- comment="Job failed.nn$(cat "$report")"
- if [[ "${CI_JOB_STATUS}" == "failed" ]] ; then bash -c "source .gitlab-ci/gitlab.sh; gitlab-comment_merge_request "$comment"" ; fi
# From .gitlab-ci/gitlab.sh
function gitlab-comment_merge_request() {
url="https://$CI_SERVER_HOST/api/v4/projects/$CI_MERGE_REQUEST_PROJECT_ID/merge_requests/$CI_MERGE_REQUEST_IID/notes"
comment="$1"
curl -v --location -X POST "$url"
--header "PRIVATE-TOKEN: $GITLAB_CI_TOKEN"
--header "Content-Type: application/json"
--data '{"body": "'"$comment"'"}'
}
Unfortunately, the comment that is created contains only the first word, Job.
I have tried many techniques to build and send the JSON payload. But all give the same result.
So I thought it could be a mistake when creating the $comment
variable in my .gitlab-ci.yaml
. However, echo $comment
in the same file give the right content.
Now, I’m lost. Do you know why the $comment
variable that should contain a large text (a markdown text with title, subtitles, and lists) is not sent ?
Thanks
2
Answers
A simplified version of this would look like:
Note:
find
before passing it tocat
,cat
was looking for a single file with all the filenames concatenated together as its name. Don’t do that. Usingfind ... -exec cat -- {} +
correctly handles names with spaces without creating new bugs.==
to=
,[[
to[
.bash -c
and the exec boundary between parent and child processes it implied. If we hadn’t done this we would need toexport comment
.source
keyword to its POSIX-compliant synonym,.
A POSIX-compliant version of your function might look like:
If you don’t have
jq
installed, it’s straightforward to write a shell wrapper for Python’sjson
module for the same purpose.It is possible to minimize all the logic and JSON formatting into a single shell script:
gitlab-ci.yaml
:failed-reports.sh
:In case the JSON data payload is very large, it is a safer option to stream it to curl with
--data @-
rather than passing it as an argument which turns out to be rather limited by the system’s maximum allowed argument length.