Jira & Confluence
[!NOTE|label:reference:]
jira
[!NOTE]
X-Atlassian-Token
X-Force-Accept-Language
X-AAccountId
myself
[!NOTE|label:references:]
$ curl -s https://jira.sample.com/rest/api/2/myself
# or via `user?username=<id>`
$ curl -s https://jira.sample.com/rest/api/2/user?username=marsloget info
# get timezone $ curl -s https://jira.sample.com/rest/api/2/mypreferences?key=jira.user.timezone Asia/Shanghai # get locale $ curl --request GET \ --url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \ --header 'Accept: application/json'set info
# set timezone $ curl --request PUT \ --url 'https://jira.sample.com/rest/api/2/mypreferences?key={key}' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '"<string>"' # set local $ curl --request PUT \ --url 'https://jira.sample.com/rest/api/2/mypreferences/locale' \ --user 'email@example.com:<api_token>' \ --header 'Accept: application/json' \ --header 'Content-Type: application/json' \ --data '{ "locale": "en_US" }'
check fields
$ curl -s \
-k \
-X GET https://${jiraName}/rest/api/2/issue/${jiraID} |
jq --raw-outputcheck attachment
check attachment ID
$ curl -s \ -k \ -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment | jq --raw-output .fields.attachment[].idget attachments download url
$ curl -s \ -k \ -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment | jq --raw-output .fields.attachment[].contentdownload all attachments in Jira
-I replace-str Replace occurrences of replace-str in the initial-arguments with names read from standard in- put. Also, unquoted blanks do not terminate input items; instead the separator is the new- line character. Implies -x and -L 1.
$ curl -s \ -k \ -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment | jq --raw-output .fields.attachment[].content | xargs -I '{}' curl -sgOJL '{}'
list all projects
$ curl -fsSL -XGET https://jira.sample.com/rest/api/2/project |
jq -r '.[] | [.key, .name] | join(" | ")' |
column -s '|' -tsearch issue by JQL
[!TIP]
JQL pattern rule:
remove all space
%3Dinstead of=
project=abc->project%3Dabc
%20CONDITION%20instead ofCONDITION
AND->%20AND%20
OR->%20OR%20
format JQL
[!TIP]
$ jql='project = abc AND issuetype = release order by updated desc' $ jql=$(printf %s "${jql}" | jq -sRr @uri)$ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")" $ jql="$(printf %s "${jql}" | jq -sRr @uri)" # i.e.: $ jql='project = abc AND issuetype = release' $ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")" $ echo $jql project=abc AND issuetype=release $ jql="$(printf %s "${jql}" | jq -sRr @uri)" $ echo $jql project%3Dabc%20AND%20issuetype%3Dreleaseapi
[!NOTE]
maxResults:integerstartAt:integervalidateQuery:stringfields:array<string>expand:stringproperties:array<string>fieldsByKeys:booleansample:
search?jql=${jql}&maxResults=100&startAt=0
$ curl --silent \ --insecure \ --globoff \ --netrc-file ~/.netrc \ -XGET \ "https://jira.sample.com/rest/api/2/search?jql=${jql}" | jq -r ${jqOpt} # i.e.: $ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc' $ url='https://jira.sample.com/rest/api/2' $ queryParams="startAt=0&maxResults=10" $ jql='project = ABC AND issuetype = Release ORDER BY updated ASC' # copy from Jira website $ jql="$(printf %s "${jql}" | jq -sRr @uri)" $ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" | jq -r '.issues[]' | jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' | while IFS='|' read -r _key _summary _status _issuetype _updated _created; do echo "- [${_key}] - ${_summary}" echo " - status : ${_status}" echo " - issuetype : ${_issuetype}" echo " - created : ${_created}" echo " - updated : ${_updated}" done$ curl --silent \ --insecure \ --globoff \ --netrc-file ~/.netrc \ -XGET \ "https://jira.sample.com/rest/api/2/search?jql=${jql}" | jq -r ${jqOpt} # i.e.: $ curlOpt='--silent --insecure --globoff --netrc-file ~/.netrc' $ url='https://jira.sample.com/rest/api/2' $ queryParams="startAt=0&maxResults=10" $ jql='project = abc AND issuetype = release' # copy from Jira website $ jql="$(sed 's/ //g;s/AND/ AND /g;s/OR/ OR /g;s/IN/ IN /g;s/IS/ IS /g' <<< "${jql}")" $ jql="$(printf %s "${jql}" | jq -sRr @uri)" $ curl "${curlOpt}" "${url}/search?jql=${jql}&${queryParams}" | jq -r '.issues[]' | jq -r '. | [.key, .fields.summary, .fields.status.name, .fields.issuetype.name, .fields.updated, .fields.created] | join("|")' | while IFS='|' read -r _key _summary _status _issuetype _updated _created; do echo "- [${_key}] - ${_summary}" echo " - status : ${_status}" echo " - issuetype : ${_issuetype}" echo " - created : ${_created}" echo " - updated : ${_updated}" done
[get email address](Get Email Addresses For Users)
$ curl GET https://jira.sample.com/rest/api/2/user?key=JIRAUSER10100 |
jq -rapi token
[!NOTE|label:references:]
[!NOTE]
to list all tokens for single user:
$ curl -v -XGET \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/ | jq -rto list tokens for all users:
$ curl -v \ -X GET \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter | jq -r
$ curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -rget id, created, last access, and valid timestamp
function epoch2timestamp() { [[ 0 != $1 ]] && echo $(date -d @$(( $1/1000 )) +%FT%T.%3N%Z) || echo "0"; } $ while read -r _id _created _lastAccess _validUntil; do echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})"; done < <( curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )' ) | column -t 537 2024-01-31T21:32:51.000PST 2024-03-26T23:30:30.000PDT 2024-07-31T21:32:51.000PDT 579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT # with header $ ( echo "ID CREATED LASTACCESS VALIDUNTIL"; while read -r _id _created _lastAccess _validUntil; do echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})"; done < <( curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )' ) ) | column -t ID CREATED LASTACCESS VALIDUNTIL 537 2024-01-31T21:32:51.000PST 2024-03-26T23:33:33.000PDT 2024-07-31T21:32:51.000PDT 579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDTor
$ curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")' | xargs -r -I{} bash -c "et=\"{}\"; date -d @\$(( \${et}/1000 )) +%c" Mon 18 Dec 2023 10:25:58 AM PST Tue 26 Mar 2024 10:21:30 PM PDT Tue 18 Jun 2024 10:25:58 AM PDT # or $ while read -r _d; do date -d @$(( ${_d}/1000 )) +%c; done < <( curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .created, .lastAccessed, .validUntil ] | join("\n")' ) Mon 18 Dec 2023 10:25:58 AM PST Tue 26 Mar 2024 10:14:58 PM PDT Tue 18 Jun 2024 10:25:58 AM PDT
[!TIP]
expiration keywords
tokenValidityTimeInMonthstokenExpirationDateTimetokenExpirationDateTimeMillis
$ curl -v -d '{"tokenDescription":"<token-description>"}' \ -X POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokencreate new token with expiration time
[!NOTE|label:references:]
with
tokenValidityTimeInMonths$ curl -v \ -d '{"tokenDescription":"<token-description>", "tokenValidityTimeInMonths" : 1}' \ -X POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokenwith
tokenExpirationDateTime$ curl -v \ -d '{"tokenDescription":"Custom expiration", "tokenExpirationDateTime" : "2020-10-19T10:29:00.000+02:00"}' \ -X POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
$ curl -s \ -d '{"tokenDescription":"marslo-token-api-test", "tokenValidityTimeInMonths" : 6}' \ -X POST \ --header "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | jq -r .plainTextToken NdxEToKfDsjUE7tct1ePP6erE1xdDsEAa64BOTcreate token for another users
$ curl -v \ -d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105"}' \ POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token # or with token validity time $ curl -v \ -d '{"tokenDescription":"token for another user", "tokenForUserKey":"JIRAUSER10105","tokenValidityTimeInMonths":12}' \ POST \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token
$ curl -v \ -d '{"tokenDescription":"Updated token description"}' \ -X PATCH \ --header "Content-Type: application/json" \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id>[!NOTE|label:references:]
$ curl -v \ -X DELETE \ https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/token/<token-id># list before token deleted $ ( echo "ID CREATED LASTACCESS VALIDUNTIL"; while read -r _id _created _lastAccess _validUntil; do echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})"; done < <( curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )' ) ) | column -t ID CREATED LASTACCESS VALIDUNTIL 537 2024-01-31T21:32:51.000PST 2024-03-26T23:40:02.000PDT 2024-07-31T21:32:51.000PDT 579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT 580 2024-03-26T23:36:02.000PDT 0 2024-09-26T23:36:02.000PDT 581 2024-03-26T23:36:11.000PDT 0 2024-09-26T23:36:11.000PDT # delete $ curl -s -D- \ -X DELETE \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/581 HTTP/2 200 date: Wed, 27 Mar 2024 06:41:06 GMT content-type: application/json;charset=UTF-8 x-arequestid: 1421x248002x2 x-anodeid: jiraprod5 referrer-policy: strict-origin-when-cross-origin x-xss-protection: 1; mode=block x-content-type-options: nosniff x-frame-options: SAMEORIGIN content-security-policy: sandbox strict-transport-security: max-age=31536000 set-cookie: JSESSIONID=731380C1F17B2F9A59E211B0442AAFFB; Path=/; Secure; HttpOnly x-seraph-loginreason: OK set-cookie: atlassian.xsrf.token=A8KN-1NAU-M55V-EQSR_1811ae8601112c05430589e686032924599718c9_lin; Path=/; Secure; SameSite=None x-asessionid: k5q153 x-ausername: marslo cache-control: no-cache, no-store, no-transform true # curl without header $ curl -s \ -X DELETE \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token/580 true # verify $ ( echo "ID CREATED LASTACCESS VALIDUNTIL"; while read -r _id _created _lastAccess _validUntil; do echo "${_id} $(epoch2timestamp ${_created}) $(epoch2timestamp ${_lastAccess}) $(epoch2timestamp ${_validUntil})"; done < <( curl -s -D- \ -XGET \ -H "Content-Type: application/json" \ https://jira.sample.com/rest/de.resolution.apitokenauth/latest/user/token | sed '/^\s*$/,$!d;//d' | jq -r '.content[] | [ .id, .created, .lastAccessed, .validUntil ] | join( "\t" )' ) ) | column -t ID CREATED LASTACCESS VALIDUNTIL 537 2024-01-31T21:32:51.000PST 2024-03-26T23:44:32.000PDT 2024-07-31T21:32:51.000PDT 579 2024-03-26T23:19:16.000PDT 0 2024-09-26T23:19:16.000PDT$ curl GET \ https://jira.sample.com/rest/api/2/user?username=some.username | jq -r
userFilter
valid user key
read above how to get a user key for a name or by email address; if you want to filter for more than one user, repeat that parameter for as many users you want to filter for
descriptionFilter
search term
string to search for in all token descriptions
notValidAfter
epoch Unix timestamp
tokens not valid anymore after that date/ time in milliseconds
tokenScope
integer
0 = no scope (all pre 1.5.0 tokens), 1 = read-only, 2 = read/ write
fromCreated
epoch Unix timestamp
-
untilCreated
epoch Unix timestamp
-
fromLastUsed
epoch Unix timestamp
-
untilLastUsed
epoch Unix timestamp
-
fromExpiresDuring
epoch Unix timestamp
-
untilExpiresDuring
epoch Unix timestamp
-
list token expired after certain time
$ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?notValidAfter=1688918956972" | jq -r # with limit and page $ curl "https://jira-or-confluence.sample.com/rest/de.resolution.apitokenauth/latest/user/tokensByFilter?page=0&limit=1¬ValidAfter=1688918956972" | jq -r
[!NOTE|label:references:]
$ openssl genrsa -out jira_privatekey.pem 1024
$ openssl req -newkey rsa:1024 -x509 -key jira_privatekey.pem -out jira_publickey.cer -days 365
$ openssl pkcs8 -topk8 -nocrypt -in jira_privatekey.pem -out jira_privatekey.pcks8
$ openssl x509 -pubkey -noout -in jira_publickey.cer > jira_publickey.pemicons and priority
priority
[!NOTE|label:references:]
$ for _i in "blocker.png" "blocker.svg" "critical.png" "critical.svg" "high.png" "high.svg" "highest.png" "highest.svg" "low.png" "low.svg" "lowest.png" "lowest.svg" "major.png" "major.svg" "medium.png" "medium.svg" "minor.png" "minor.svg" "trivial.png" "trivial.svg"; do
echo "--> ${_i}"
curl -O https://jira-trigger-plugin.atlassian.net/images/icons/priorities/${_i}
doneconfluence
$ confluenceName='confluence.domain.com'
$ pageID='143765713'get page id:
$ curl -s https://${confluenceName}/rest/api/user/current | jq -rget info
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq --raw-outputget space
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .space.keyget title
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .titleget page history
$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.numberget next version
currentVer=$(curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number) newVer=$((currentVer+1))
publish to confluence
[!NOTE|label:references:]
$ url="https://${confluenceName}/rest/api/content/${pageID}"
$ page=$(curl -s ${url})
$ space=$(echo "${page}" | jq .space.key)
$ title=$(echo "${page}" | jq .title)
$ currentVer=$(echo "${page}" | jq .version.number)
$ newVer=$((currentVer+1))
$ cat > a.json << EOF
{
"id": "${pageID}",
"type": "page",
"title": ${title},
"space": {"key": ${space}},
"body": {
"storage": {
"value": "<h1>Hi confluence</h1>",
"representation": "storage"
}
},
"version": {"number":${newVer}}
}
EOF
$ curl -s \
-i \
-X PUT \
-H 'Content-Type: application/json' \
--data "$(cat a.json)" \
https://${confluenceName}/rest/api/content/${pageID}result

plugins
create excerpt

include excerpt

result

insert svg
insert svg image
[!TIP|label:get svg image:]
...->Attachmentspreview the image and get info from URL :
...&preview=/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg
<img width="800" src="https://ewiki.sample.com/download/attachments/506105287/513281481/k8s-ha-cluster-stacked-etcd.v3.svg">
edit source via
[!TIP|label:references:]
<p><ac:image ac:width="301"><ri:attachment ri:filename="SVG_logo.svg" /></ac:image></p>CLI
[!NOTE|label:references:]
running with docker images
$ $ docker run -ti bobswiftapps/acli:latest acli -a getClientInfo
# or
$ docker run -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli -a getClientInfo
# with env
$ cat .env
examplegear=jira -s https://examplegear.atlassian.net -u anonymous
examplegear_confluence=confluence -s https://examplegear.atlassian.net/wiki -u anonymous
$ docker run --env-file=.env -ti bobswiftapps/acli:latest /bin/bash
bash-5.0# acli $examplegear -a getServerInfo
# or
docker run -e examplegear='jira -s https://examplegear.atlassian.net -u anonymous' -ti bobswiftapps/acli:latest /bin/bash
bash-4.4# acli ${examplegear} -a getServerInfo
# with acli.properties
$ docker run -v ${PWD}/acli.properties:/opt/acli/acli.properties \
-ti bobswiftapps/acli:latest
# or prior to version 11.0.0, use:
$ docker run -v ${PWD}/acli.properties:/opt/atlassian-cli/acli.properties \
-ti bobswiftapps/acli:latest
# or with `ACLI_CONFIG` env
$ docker run -v ${PWD}/acli.properties:/tmp/acli.properties \
-e ACLI_CONFIG=/tmp/acli.properties \
-ti bobswiftapps/acli:latest \
acli -a getServerInfo --outputFormat 2$ acli system setSecureProperty --name my.secret --secret -
Enter secure value: <secret value prompt>
Secure properties file does not yet exist. Creating...
Enter new secure properties password: <new password prompt>
Confirm secure properties password: <new password prompt>
Secure properties file created.
Value for key 'foo' set in secure properties file.Last updated
Was this helpful?
