Forums

Articles
Create
cancel
Showing results for 
Search instead for 
Did you mean: 

JIRA Create an issue using Powershell (without using curl)

ArtemT August 24, 2014

Hi all.

Does anyone ever used powershell scripts for creating JIRA issues? Could you provide an example please?

4 answers

1 accepted

1 vote
Answer accepted
ArtemT September 2, 2014

Finally i did it. Here is my script:

[String] $target = "http://jirahost:2990";
[String] $username = "username"
[String] $password = "password"
[String] $projectKey = "TP";
[String] $issueType = "Task";
[String] $summary = "summary";
[String] $description = "description"
[String] $priority = "2"
 
[String] $body = '{"fields":{"project":{"key":"'+$projectKey+'"},"issuetype":{"name": "'+$issueType+'"},"summary":"'+$summary+'","description":"'+$description+'", "priority":{"id":"'+$priority+'"}}}';
 
function ConvertTo-Base64($string) {
$bytes = [System.Text.Encoding]::UTF8.GetBytes($string);
$encoded = [System.Convert]::ToBase64String($bytes);
return $encoded;
}
 
try {
 
$b64 = ConvertTo-Base64($username + ":" + $password);
$auth = "Basic " + $b64;
 
$webRequest = [System.Net.WebRequest]::Create($target+"/jira/rest/api/2/issue/")
$webRequest.ContentType = "application/json"
$BodyStr = [System.Text.Encoding]::UTF8.GetBytes($body)
$webrequest.ContentLength = $BodyStr.Length
$webRequest.ServicePoint.Expect100Continue = $false
$webRequest.Headers.Add("Authorization", $auth);
$webRequest.PreAuthenticate = $true
$webRequest.Method = "POST"
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($BodyStr, 0, $BodyStr.length)
$requestStream.Close()
[System.Net.WebResponse] $resp = $webRequest.GetResponse()
 
$rs = $resp.GetResponseStream()
[System.IO.StreamReader] $sr = New-Object System.IO.StreamReader -argumentList $rs
[string] $results = $sr.ReadToEnd()
Write-Output $results
 
}
 
catch [System.Net.WebException]{
        if ($_.Exception -ne $null -and $_.Exception.Response -ne $null) {
            $errorResult = $_.Exception.Response.GetResponseStream()
            $errorText = (New-Object System.IO.StreamReader($errorResult)).ReadToEnd()
            Write-Warning "The remote server response: $errorText"
            Write-Output $_.Exception.Response.StatusCode
        } else {
            throw $_
        }
    }

0 votes
Dakota Zinn December 1, 2017

You don't have to use headers when authenticating on JIRA. 

You can use JSON formatted bodies and save the session authentication to a variable to call later

 

This code will create a session in JIRA, then create a subtask for an issue. if you don't want it as a subtask, change issue type, and remove issue parent. 

 

$global:Summary = "This is the Summary"
$global:URI = "https://localhost:8080"
$global:IssueParent = "Parent"
$global:ProjectKey = "ProjectKey"
$global:description = "This is the Issue Description"


$body1 = @{
username = $username
password = $password
} | ConvertTo-Json -Depth 10
#Try/catches are use so that if there is an error, it doesn't continue


#create a session in JIRA in order to stay logged in and make changes
try
{
Invoke-RestMethod -uri "$uri/rest/auth/latest/session" -ContentType "application/json" -Method post -body $body1 -SessionVariable mysession
}
catch
{
$fullerror = $_.Exception
[void][System.Windows.Forms.MessageBox]::Show("Failed to log in with error:`r$fullerror", 'Error') # Casting the method to [void] suppresses the output.
$global:StopIssueCreation = $true
}





#this is a properly formed powershell JSON string
#documentation on conversion can be found at
#<http://wahlnetwork.com/2016/02/18/using-powershell-arrays-and-hashtables-with-json-formatting/>

$global:IssueCreationBody =
@{
fields = @{
project = @{
key = $projectKey
}
parent = @{
key = $issueParent
}
summary = $summary
description = $description
issuetype = @{
id = '5' #this is a sub-task issuetype
}
assignee = @{
name = $username
}
priority = @{
id = '5' #no priority
}
}
} | ConvertTo-Json -Depth 100


if ($StopIssueCreation -ne $true) #if the login didn't fail
{
try
{
$IssueCreation = Invoke-WebRequest -uri "$uri/rest/api/latest/issue" `
-ContentType "application/json" -Method post -Body $IssueCreationBody -WebSession $mysession | ConvertFrom-Json
}

catch
{
$fullerror = $_.Exception
[void][System.Windows.Forms.MessageBox]::Show("Failed to create Issue in JIRA with error:`r$fullerror", 'Error') # Casting the method to [void] suppresses the output.
$global:StopIssueCreation = $true
}
}



<#Use this if you want to add a description Post-Creation
#and change the description above to ''

if ($StopIssueCreation -ne $true)
{

$global:descriptionBody = @{
fields = @{ description = $description }
} | ConvertTo-Json -Depth 100

try
{
Invoke-WebRequest -uri "$uri/rest/api/latest/issue/$issueNumber" -ContentType "application/json" -Method put -websession $mysession -Body $descriptionBody | ConvertFrom-Json
$global:StopIssueCreation = $true
}
catch
{
$fullerror = $_.Exception
[void][System.Windows.Forms.MessageBox]::Show("Failed to add Description with error:`r$fullerror", 'Error') # Casting the method to [void] suppresses the output.
$global:StopIssueCreation = $true
}
}
#>
if ($StopIssueCreation -ne $true)
{
$global:repairCompleted = $true
$global:StopIssueCreation = $false
}
if ($repairCompleted -ne $true)
{} #If the repair didn't complete correctly, maybe tell them something

 

 

This one is a little better looking:

$global:Summary = "This is the Summary"
$global:URI = "https://localhost:8080"
$global:IssueParent = "Project Parent"
$global:ProjectKey = "ProjectKey"
$global:description = "This is the Issue Description"


$body1 = @{
username = $username
password = $password
} | ConvertTo-Json -Depth 10

#create a session in JIRA in order to stay logged in and make changes
Invoke-RestMethod -uri "$uri/rest/auth/latest/session" -ContentType "application/json" -Method post -body $body1 -SessionVariable mysession


#this is a properly formed powershell JSON string
#documentation on conversion can be found at
#<http://wahlnetwork.com/2016/02/18/using-powershell-arrays-and-hashtables-with-json-formatting/>

$global:IssueCreationBody =
@{
fields = @{
project = @{ key = $projectKey }
parent = @{ key = $issueParent }
summary = $summary
description = $description
issuetype = @{ id = '5' #this is a sub-task issuetype }
assignee = @{ name = $username }
priority = @{ id = '5' #no priority }
}
} | ConvertTo-Json -Depth 100



$IssueCreation = Invoke-WebRequest -uri "$uri/rest/api/latest/issue" `
-ContentType "application/json" -Method post -Body $IssueCreationBody -WebSession $mysession | ConvertFrom-Json
$issueNumber = $IssueCreation.id


<#
#Use this if you want to add a description Post-Creation
#and change the description above to ''

$global:descriptionBody = @{
fields = @{ description = $description }
} | ConvertTo-Json -Depth 100

Invoke-WebRequest -uri "$uri/rest/api/latest/issue/$issueNumber" -ContentType "application/json" -Method put -websession $mysession -Body $descriptionBody | ConvertFrom-Json
#>
mike p
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
October 8, 2018

Invoke-WebRequest : The remote server returned an error: (400) Bad Request.
At line:1 char:23
+ ... eCreation = Invoke-WebRequest -uri "$uri/rest/api/latest/issue" -Cont ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebException
+ FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

-----

Please provide your suggestions.

Dakota Zinn October 8, 2018

Looking back at this , issue type and priority need to have the comment removed. 

The end } on them

0 votes
James Coryat
I'm New Here
I'm New Here
Those new to the Atlassian Community have posted less than three times. Give them a warm welcome!
February 3, 2017

The example is 8 years old and was built using the SOAP interface.  If that doesn't matter to you, it will be fine.  The code example provided above looks to be a C# implementation ported to PowerShell.  Works but is not very PowerShelly...

Fortunately it can be boiled down to a few lines of powershell (3.0+) now...

[string] $target = "http://jirahost:2990"
[string] $username = "username"
[string] $password = "password"
[string] $projectKey = "TP";
[string] $issueType = "Task"
[string] $summary = "summary"
[string] $description = "description"
[string] $priority = "2"
  
[string] $body = "{`"fields`":{`"project`":{`"key`":`"$projectKey`"},`"issuetype`":{`"name`":`"$issueType`"},`"summary`":`"$summary`",`"description`":`"$description`",`"priority`":{`"id`":`"$priority`"}}}"
  
try {
    $basicAuth = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($Username):$Password"))
    $headers = @{
        "Authorization" = $basicAuth
        "Content-Type"="application/json"
    }
    $requestUri = "$target/jira/rest/api/latest/issue"
    $response = Invoke-RestMethod -Uri $requestUri -Method POST -Headers $headers -Body $body -UseBasicParsing
    Write-Output "ID: $($response.id)"
    Write-Output "Key: $($response.key)"
    Write-Output "Self: $($response.self)"    
}
catch {
    Write-Warning "Remote Server Response: $($_.Exception.Message)"
    Write-Output "Status Code: $($_.Exception.Response.StatusCode)"
}
Chris
Contributor
August 16, 2019

With this I'm getting a

WARNING: Remote Server Response: The remote server returned an error: (400) Bad Request.
Status Code: BadRequest

 

I know that -UseBasicParsing is no longer a thing (per M$ anyway), so that's been taken out, and I know it's authenticating properly.  I feel like this should work, but just isn't for me. I think that the $body variable must have some kind of syntax issue, or maybe because we're on JIRA cloud, it behaves a little differently?

I was able to get this working in Python really easily, but I'm trying to make something a little more self-contained for ActiveBatch.

This is what I'm working with at the moment

[string] $target = "https://DOMAIN.atlassian.net"
[string] $username = 'USERNAME'
[string] $password = 'API-KEY'
[string] $projectKey = "PROJECT ID"
[string] $issueType = "Incident"
[string] $summary = "Testing This"
[string] $description = "Testing that"


[string] $body = "{`"fields`":{`"project`":{`"key`":`"$projectKey`"},`"issuetype`":{`"name`":`"$issueType`"},`"summary`":`"$summary`",`"description`":`"$description`"}}";

try {
$basicAuth = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($Username):$Password"))
$headers = @{
"Authorization" = $basicAuth
"Content-Type" = "application/json"
"verify" = "false"
}
$requestUri = "$target/rest/api/3/issue"
$response = Invoke-RestMethod -Uri $requestUri -Method POST -Headers $headers -Body $body
Write-Output "ID: $($response.id)"
Write-Output "Key: $($response.key)"
Write-Output "Self: $($response.self)"
}
catch {
Write-Warning "Remote Server Response: $($_.Exception.Message)"
Write-Output "Status Code: $($_.Exception.Response.StatusCode)"
}

You may also note that Priority isn't included, that's because our Incident priorities are default to "High" and cannot be adjusted.

Dakota Zinn August 16, 2019

Try using [pscustomobject]@{} to create your body, then use | convertto-json on it to get the JSON string. 

 

You write it the same way you would a hashtable, but it can have more depth to it

[pscustomobject]@{

Fields = [pscustomobject]@{

    Project = @{ key = $projectkey}

    IssueType = @{name = $issuetype}

    }

} | convertto-json -depth 5

(For simplicity, pscustomobject creates the object as an ordered list, and will not change its order like a hashtable can)

Chris
Contributor
August 19, 2019

I can't even begin to experiment with this this morning yet, for some reason it's giving me 407 proxy errors now, where when I left friday, it was just the error indicated above.

I was curious, however, could you include your solution in the rest of the code? Or an example on where I'd be calling it? I've mostly performed more complex operations in Batch or Python script and I'm not completely familiar with PowerShell yet. I imagine that what you're advising would replace the top section of the script, and then this line

[string] $body = "{`"fields`":{`"project`":{`"key`":`"$projectKey`"},`"issuetype`":{`"name`":`"$issueType`"},`"summary`":`"$summary`",`"description`":`"$description`"}}";

would be calling from the pscustomobject. But I wanted to be sure I had syntax correct for referring to the pscustomobject. 

Dakota Zinn August 19, 2019

it would be implemented like this:

 

[string] $target = "https://DOMAIN.atlassian.net"
[string] $username = 'USERNAME'
[string] $password = 'API-KEY'
[string] $projectKey = "PROJECT ID"
[string] $issueType = "Incident"
[string] $summary = "Testing This"
[string] $description = "Testing that"


$body = [pscustomobject]@{
fields = @{
project= @{ key = $projectKey}
issuetype = @{ name = $issueType }
summary = $summary
description = $description
}
} | ConvertTo-Json


try {
$basicAuth = "Basic " + [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes("$($Username):$Password"))
$headers = @{
"Authorization" = $basicAuth
"verify" = "false"
}
$requestUri = "$target/rest/api/3/issue"
$response = Invoke-RestMethod -Uri $requestUri -Method POST -Headers $headers -Body $body -ContentType "application/json"
Write-Output "ID: $($response.id)"
Write-Output "Key: $($response.key)"
Write-Output "Self: $($response.self)"
}
catch {
Write-Warning "Remote Server Response: $($_.Exception.Message)"
Write-Output "Status Code: $($_.Exception.Response.StatusCode)"
}

Chris
Contributor
August 19, 2019

Okay, I just resolved the proxy issue (temporarily at least), evidently I need to open JIRA up in a web browser, then the script runs without error 407. I'll eventually need to figure out a permanent fix for that.

I attempted your implementation code, and it's returning the same 400 (Bad Request) error. I'm not sure what I'm doing wrong here. It shouldn't matter that I'm using JIRA cloud, correct? This should still work since it works in my Python script, I would imagine. 

 

UPDATE:

I found a workaround ActiveBatch's bug, where it doesn't execute .py scripts properly, it's not the most graceful workaround, but the script works in Python and doesn't in PowerShell, so I just went with Python instead. However, if anyone else has suggestions for a PowerShell fix, I'm all ears. 

0 votes
Diego Zarpelon
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
August 25, 2014

Hey Artem.

I think you should take a look here. As it have some explanation on powershell/jira use.

B. Normann P. Nielsen
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
September 2, 2014

I tend to use the Atlassian CLI, then it is just calling the jira.bat at the command line, plain and simple. And the CLI is quite useable from powershell, VB, VBS, Bach, etc etc - pure KISS :-)

Main challenge can be that using the CLI is relatively slow....

BR,

Normann

Suggest an answer

Log in or Sign up to answer