0

Hey I am using conduit curl method to create tasks from post. It work fine when I run from terminal with hardcoded values. But when I try to execute it with variables it throws an error:

Script:

#!/bin/bash
echo "$1"
echo "$2"
echo "$3"
echo "$4"
echo "$5"
echo '{
  "transactions": [
    {
      "type": "title",
      "value": "$1"
    },
    {
      "type": "description",
      "value": "$2"
    },
    {
      "type": "status",
      "value": "$3"
    },
    {
      "type": "priority",
      "value": "$4"
    },
    {
       "type": "owner",
       "value": "$5"
    }
  ]
}' | arc call-conduit --conduit-uri https://mydomain.phacility.com/ --conduit-token mytoken maniphest.edit

execution:

./test.sh "test003 ticket from api post" "for testing" "open" "high" "ahsan"

Output:

test003 ticket from api post
for testing
open
high
ahsan
{"error":"ERR-CONDUIT-CORE","errorMessage":"ERR-CONDUIT-CORE: Validation errors:\n  - User \"$5\" is not a valid user.\n  - Task priority \"$4\" is not a valid task priority. Use a priority keyword to choose a task priority: unbreak, very, high, kinda, triage, normal, low, wish.","response":null}

As you can see in error its reading $4 and $5 as values not variables. And I am failing to understand how to use $variables as input in these arguments.

Kusalananda
  • 333,661

2 Answers2

1

The issue here is that you're using single quotes. It prevents shell from variable expansion. Use double quotes instead (and escape internal double quotes) or put additional single quotes around variable $X.

E.g. compare this command:

$ test_var="wiii" && echo '"$test_var"'
"$test_var"

and this:

$ test_var="wiiii" && echo "\"$test_var\""
"wiiii"

and this one:

$ test_var="wiiii" && echo '"'$test_var'"'
"wiiii"

Additional information to read:

rush
  • 27,403
1

Your main issue is that the shell won't expand variables within single quotes. You also have an issue with injecting unsanitized user-supplied data directly into the JSON document without encoding it.

We can solve these issues by letting jq encode the data provided by the user:

#!/bin/sh

if [ "$#" -ne 5 ]; then printf 'Expected 5 arguments, got %d\n' "$#" >&2 exit 1 fi

for type in title description status priority owner do jq -n --arg type "$type" --arg value "$1" '{ type: $type, value: $value }' shift done | jq -c -s '{ transactions: . }' | arc call-conduit
--conduit-uri 'https://mydomain.phacility.com/'
--conduit-token 'mytoken'
maniphest.edit

This script takes the command line arguments and creates the transactions array elements by letting jq create objects containing a type and a value key with the appropriate content.

The generated objects are then inserted into the transactions array by means of another jq call, reading from the loop. This creates your final JSON document which is then passed to the arc command.

Instead of the slightly long and complicated-looking

jq -n --arg type "$type" --arg value "$1" '{ type: $type, value: $value }'

in the body of the loop, you may use the jo tool like so:

jo type="$type" value="$1"

Both this jo invocation and the original jq invocation would make sure that both $type (our loop variable) and $1 (the user-supplied command line argument) are properly JSON encoded.

Given the five arguments "test003" ticket from api post, for "testing", open, high, and ahsan, this code would generate a JSON document equivalent to the document below, and pass it on to arc.

{
  "transaction": [
    {
      "type": "title",
      "value": "\"test003\" ticket from api post"
    },
    {
      "type": "description",
      "value": "for \"testing\""
    },
    {
      "type": "status",
      "value": "open"
    },
    {
      "type": "priority",
      "value": "high"
    },
    {
      "type": "owner",
      "value": "ahsan"
    }
  ]
}

Notice that the double quotes have all been properly handled.

Kusalananda
  • 333,661