[!NOTE|label:reference:]

jira

$ jiraName='jira.sample.com'
$ jiraID='STORY-1'

[!NOTE]

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=marslo
  • get 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-output

check attachment

  • check attachment ID

    $ curl -s \
           -k \
           -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
           jq --raw-output .fields.attachment[].id
    
  • get attachments download url

    $ curl -s \
           -k \
           -X GET https://${jiraName}/rest/api/2/issue/${jiraID}?fields=attachment |
           jq --raw-output .fields.attachment[].content
    
    • download 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 '|' -t

search issue by JQL

[!TIP]

  • format JQL

    [!TIP]

    $ jql='project = abc AND issuetype = release order by updated desc'
    $ jql=$(printf %s "${jql}" | jq -sRr @uri)
    
    legacy version
    $ 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%3Drelease
    
  • api

    [!NOTE]

    • * iMarslo : bin/jira
    • query parameters:
      • maxResults: integer
      • startAt: integer
      • validateQuery: string
      • fields: array<string>
      • expand: string
      • properties: array<string>
      • fieldsByKeys: boolean
      • sample: 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
    
    legacy version
    $ 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

$ curl GET https://jira.sample.com/rest/api/2/user?key=JIRAUSER10100 |
  jq -r

api token

[!NOTE|label:references:]

  • list all tokens

    [!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 -r
      
    • to 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 -r
    
    • get 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.000PDT
      
      • or

        $ 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
        
  • create token

    [!TIP]

    • expiration keywords
      • tokenValidityTimeInMonths
      • tokenExpirationDateTime
      • tokenExpirationDateTimeMillis
    $ 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/token
    
    • create 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/token
        
      • with 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
      NdxEToKfDsjUE7tct1ePP6erE1xdDsEAa64BOT
      
    • create 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
      
  • update token description

    $ 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>
    
  • delete token

    [!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
    
  • filter

PARAMETER VALUE COMMENT
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&notValidAfter=1688918956972" |
      jq -r
    

generate OAuth consumer

[!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.pem

icons 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}
  done

confluence

$ confluenceName='confluence.domain.com'
$ pageID='143765713'

get page id: confluence page id

myself

$ curl -s https://${confluenceName}/rest/api/user/current | jq -r

get info

$ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq --raw-output
  • get space

    $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .space.key
    
  • get title

    $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .title
    
  • get page history

    $ curl -s -X GET https://${confluenceName}/rest/api/content/${pageID} | jq .version.number
    
    • get 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 publish via api

plugins

Multiexcerpt

  • create excerpt create multiexcerpt

  • include excerpt include excerpt

  • result include excerpt

ACLI

[!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

create .acli.keystore

$ 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.

acli.properties

Copyright © marslo 2020-2023 all right reserved,powered by GitbookLast Modified: 2024-05-16 01:41:36

results matching ""

    No results matching ""