0

I want to send a notification to our mattermost channel, if my build script fails:

test.sh

#!/bin/bash
set -eEx

projectName="$(grep '<name>' config.xml | sed "s@.*<name>\(.*\)</name>.*@\1@" | xargs)"
payload="payload={\"text\":\"${projectName}\"}\""

echo $payload

# notify mattermost channel "Jenkins Failures" in case this script fails
function notifyMattermostOnError() {
curl -i -X POST -d \
${payload} \
https://mattermost.company.com/hooks/<key>
}

notifyMattermostOnError

I'm extracting the the Project Name from a XML file, then putting it into the message. The extraction of the Project Name with grep/sed/xargs is working and is not my issue here.

projectName can be a string with whitespaces, f.ex. the value could be Company App. Running the When running the test.sh it will insert backticks:

mles:project mles$ ./test.sh 
++ grep '<name>' config.xml
++ sed 's@.*<name>\(.*\)</name>.*@\1@'
+ projectName='Company App'
+ payload='payload={"text":"Company App"}"'
+ echo 'payload={"text":"Company' 'App"}"'
payload={"text":"Company App"}"
+ notifyMattermostOnError
+ curl -i -X POST -d 'payload={"text":"Company' 'App"}"' https://mattermost.company.com/hooks/<key>
curl: (3) [globbing] unmatched close brace/bracket in column 8

The Problem is the payload json is being split into 'payload={"text":"Company' and 'App"}"'. How can I prevent this from happening? I'm already setting quotemarks around my strings.

mles
  • 4,534
  • 10
  • 54
  • 94
  • Not sure why you are piping to xargs? – Raman Sailopal May 17 '17 at 11:22
  • For removing whitespaces, but that's not the issue here – mles May 17 '17 at 12:10
  • Use `jq` (or something similar) to generate the JSON instead of trying to create it manually. Use something like `xmlstarlet` to extract the name. – chepner May 17 '17 at 12:29
  • As an aside -- `set -e` is by no means universally considered a good idea; see [BashFAQ #105](http://mywiki.wooledge.org/BashFAQ/105). And your code is missing a significant amount of quoting -- consider running it through http://shellcheck.net/ and fixing what that finds. – Charles Duffy May 17 '17 at 17:49

1 Answers1

3

At the very least, you need to quote the parameter expansion:

curl -i -X POST -d "$payload" https://mattermost.company.com/hooks/<key>

You should also use a tool that knows how to properly escape a string for use in JSON:

payload="payload=$(jq -n --arg pn "$projectName" '{text :$pn}')"

Finally, you should use a tool that knows XML to extract the project name, rather than hoping the XML is formatted in such a way that grep might work.

projectName=$(xmlstarlet sel -t -v name config.xml)
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Thanks for the advise with the tools, but I'd like to keep my dependencies to a minimum. This script should also run on my colleagues machines. I don't want them to have the extra hassle with installing tools first. – mles May 17 '17 at 17:42
  • 1
    @mles, if your priority is ease-of-installation, I'd choose a different language to avoid compromising correctness. Python ships with both JSON generation *and* XML-parsing libraries, for example. – Charles Duffy May 17 '17 at 17:48