jira.js | |
---|---|
JavaScript JIRA API for node.jsA node.js module, which provides an object oriented wrapper for the JIRA REST API. This library is built to support version JIRA REST API documentation can be found here InstallationInstall with the node package manager npm:
or Install via git clone:
ExampleFind the status of an issue.
Currently there is no explicit login call necessary as each API call uses Basic Authentication to authenticate. OptionsJiraApi options:
* Implemented APIs
TODO
Changelog
| var url = require('url'),
logger = console;
var JiraApi = exports.JiraApi = function(protocol, host, port, username, password, apiVersion, verbose, strictSSL) {
this.protocol = protocol;
this.host = host;
this.port = port;
this.username = username;
this.password = password;
this.apiVersion = apiVersion; |
Default strictSSL to true (previous behavior) but now allow it to be modified | if (strictSSL == null) {
strictSSL = true;
}
this.strictSSL = strictSSL; |
This is so we can fake during unit tests | this.request = require('request');
if (verbose !== true) { logger = { log: function() {} }; } |
This is the same almost every time, refactored to make changing it later, easier | this.makeUri = function(pathname, altBase) {
var basePath = 'rest/api/';
if (altBase != null) {
basePath = altBase;
}
var uri = url.format({
protocol: this.protocol,
hostname: this.host,
auth: this.username + ':' + this.password,
port: this.port,
pathname: basePath + this.apiVersion + pathname
});
return uri;
};
};
(function() { |
Find an issue in jiraTakes
Returns
| this.findIssue = function(issueNumber, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueNumber),
method: 'GET'
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid issue number.');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during findIssueStatus.');
return;
}
callback(null, JSON.parse(body));
});
}; |
Get the unresolved issue countTakes
Returns
|
this.getUnresolvedIssueCount = function(version, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/version/' + version + '/unresolvedIssueCount'),
method: 'GET'
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid version.');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during findIssueStatus.');
return;
}
body = JSON.parse(body);
callback(null, body.issuesUnresolvedCount);
});
}; |
Get the Project by project keyTakes
Returns
| this.getProject = function(project, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/project/' + project),
method: 'GET'
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid project.');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during getProject.');
return;
}
body = JSON.parse(body);
callback(null, body);
});
}; |
Find the Rapid View for a specified projectTakes
Returns
|
/**
* Finds the Rapid View that belongs to a specified project.
*
* @param projectName
* @param callback
*/
this.findRapidView = function(projectName, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/rapidviews/list', 'rest/greenhopper/'),
method: 'GET',
json: true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid URL');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during rapidView search.');
return;
}
if (response.body !== null) {
var rapidViews = response.body.views;
for (var i = 0; i < rapidViews.length; i++) {
if(rapidViews[i].name.toLowerCase() === projectName.toLowerCase()) {
callback(null, rapidViews[i]);
return;
}
}
}
});
}; |
Get a list of Sprints belonging to a Rapid ViewTakes
Returns
| /**
* Returns a list of sprints belonging to a Rapid View.
*
* @param rapidView ID
* @param callback
*/
this.getLastSprintForRapidView = function(rapidViewId, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/sprints/' + rapidViewId, 'rest/greenhopper/'),
method: 'GET',
json:true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid URL');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during sprints search.');
return;
}
if (response.body !== null) {
var sprints = response.body.sprints;
callback(null, sprints.pop());
return;
}
});
}; |
Get the issues for a rapidView / sprintTakes
Returns
| /**
* Returns sprint and issues information
*
* @param rapidView ID
* @param sprint ID
* @param callback
*/
this.getSprintIssues = function getSprintIssues(rapidViewId, sprintId, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/rapid/charts/sprintreport?rapidViewId=' + rapidViewId + '&sprintId=' + sprintId, 'rest/greenhopper/'),
method: 'GET',
json: true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if( response.statusCode === 404 ) {
callback('Invalid URL');
return;
}
if( response.statusCode !== 200 ) {
callback(response.statusCode + ': Unable to connect to JIRA during sprints search');
return;
}
if(response.body !== null) {
callback(null, response.body);
} else {
callback('No body');
}
});
}; |
Add an issue to the project's current sprintTakes
Returns
does this callback if there's success? | /**
* Adds a given issue to a project's current sprint
*
* @param issueId
* @param sprintId
* @param callback
*/
this.addIssueToSprint = function(issueId, sprintId, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/sprint/' + sprintId + '/issues/add', 'rest/greenhopper/'),
method: 'PUT',
followAllRedirects: true,
json:true,
body: {
issueKeys: [issueId]
}
};
logger.log(options.uri);
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid URL');
return;
}
if (response.statusCode !== 204) {
callback(response.statusCode + ': Unable to connect to JIRA to add to sprint.');
return;
}
});
}; |
Create an issue link between two issuesTakes
Returns
| /**
* Creates an issue link between two issues. Link should follow the below format:
*
* {
* 'linkType': 'Duplicate',
* 'fromIssueKey': 'HSP-1',
* 'toIssueKey': 'MKY-1',
* 'comment': {
* 'body': 'Linked related issue!',
* 'visibility': {
* 'type': 'GROUP',
* 'value': 'jira-users'
* }
* }
* }
*
* @param link
* @param errorCallback
* @param successCallback
*/
this.issueLink = function(link, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issueLink'),
method: 'POST',
followAllRedirects: true,
json: true,
body: link
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid project.');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during issueLink.');
return;
}
callback(null);
});
}; |
Get Versions for a projectTakes
Returns
| this.getVersions = function(project, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/project/' + project + '/versions'),
method: 'GET'
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Invalid project.');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during getVersions.');
return;
}
body = JSON.parse(body);
callback(null, body);
});
}; |
Create a versionTakes
Returns
| /* {
* "description": "An excellent version",
* "name": "New Version 1",
* "archived": false,
* "released": true,
* "releaseDate": "2010-07-05",
* "userReleaseDate": "5/Jul/2010",
* "project": "PXA"
* }
*/
this.createVersion = function(version, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/version'),
method: 'POST',
followAllRedirects: true,
json: true,
body: version
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 404) {
callback('Version does not exist or the currently authenticated user does not have permission to view it');
return;
}
if (response.statusCode === 403) {
callback('The currently authenticated user does not have permission to edit the version');
return;
}
if (response.statusCode !== 201) {
callback(response.statusCode + ': Unable to connect to JIRA during createVersion.');
return;
}
callback(null, body);
});
};
|
Pass a search query to JiraTakes
Returns
| this.searchJira = function(searchString, optional, callback) { |
backwards compatibility | optional = optional || {};
if (Array.isArray(optional)) {
optional = { fields: optional };
}
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/search'),
method: 'POST',
json: true,
followAllRedirects: true,
body: {
jql: searchString,
startAt: optional.startAt || 0,
maxResults: optional.maxResults || 50,
fields: optional.fields || ["summary", "status", "assignee", "description"]
}
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 400) {
callback('Problem with the JQL query');
return;
}
if (response.statusCode !== 200) {
callback(response.statusCode + ': Unable to connect to JIRA during search.');
return;
}
callback(null, body);
});
};
|
Get issues related to a userTakes
Returns
| this.getUsersIssues = function(username, open, callback) {
var jql = "assignee = " + username;
var openText = ' AND status in (Open, "In Progress", Reopened)';
if (open) { jql += openText; }
this.searchJira(jql, {}, callback);
}; |
Add issue to JiraTakes
Returns
| this.addNewIssue = function(issue, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue'),
method: 'POST',
followAllRedirects: true,
json: true,
body: issue
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 400) {
callback(body);
return;
}
if ((response.statusCode !== 200) && (response.statusCode !== 201)) {
callback(response.statusCode + ': Unable to connect to JIRA during search.');
return;
}
callback(null, body);
});
}; |
Delete issue to JiraTakes
Returns
| this.deleteIssue = function(issueNum, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueNum),
method: 'DELETE',
followAllRedirects: true,
json: true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 204) {
callback(null, "Success");
return;
}
callback(response.statusCode + ': Error while deleting');
});
}; |
Update issue in JiraTakes
Returns
| this.updateIssue = function(issueNum, issueUpdate, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueNum),
body: issueUpdate,
method: 'PUT',
followAllRedirects: true,
json: true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 200) {
callback(null, "Success");
return;
}
callback(response.statusCode + ': Error while updating');
});
}; |
List TransitionsTakes
Returns
| /*
* {
* "expand": "transitions",
* "transitions": [
* {
* "id": "2",
* "name": "Close Issue",
* "to": {
* "self": "http://localhostname:8090/jira/rest/api/2.0/status/10000",
* "description": "The issue is currently being worked on.",
* "iconUrl": "http://localhostname:8090/jira/images/icons/progress.gif",
* "name": "In Progress",
* "id": "10000"
* },
* "fields": {
* "summary": {
* "required": false,
* "schema": {
* "type": "array",
* "items": "option",
* "custom": "com.atlassian.jira.plugin.system.customfieldtypes:multiselect",
* "customId": 10001
* },
* "name": "My Multi Select",
* "operations": [
* "set",
* "add"
* ],
* "allowedValues": [
* "red",
* "blue"
* ]
* }
* }
* }
* ]}
*/
this.listTransitions = function(issueId, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueId + '/transitions'),
method: 'GET',
json: true
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 200) {
callback(null, body.transitions);
return;
}
if (response.statusCode === 404) {
callback("Issue not found");
return;
}
callback(response.statusCode + ': Error while updating');
});
}; |
Transition issue in JiraTakes
Returns
| this.transitionIssue = function(issueNum, issueTransition, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueNum + '/transitions'),
body: issueTransition,
method: 'POST',
followAllRedirects: true,
json: true
};
this.request(options, function(error, response) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 204) {
callback(null, "Success");
return;
}
callback(response.statusCode + ': Error while updating');
});
};
|
List all Viewable ProjectsTakes
Returns
| /*
* Result items are in the format:
* {
* "self": "http://www.example.com/jira/rest/api/2/project/ABC",
* "id": "10001",
* "key": "ABC",
* "name": "Alphabetical",
* "avatarUrls": {
* "16x16": "http://www.example.com/jira/secure/projectavatar?size=small&pid=10001",
* "48x48": "http://www.example.com/jira/secure/projectavatar?size=large&pid=10001"
* }
* }
*/
this.listProjects = function(callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/project'),
method: 'GET',
json: true
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 200) {
callback(null, body);
return;
}
if (response.statusCode === 500) {
callback(response.statusCode + ': Error while retrieving list.');
return;
}
callback(response.statusCode + ': Error while updating');
});
}; |
Add a worklog to a projectTakes
Returns
| /*
* Worklog item is in the format:
* {
* "self": "http://www.example.com/jira/rest/api/2.0/issue/10010/worklog/10000",
* "author": {
* "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
* "name": "fred",
* "displayName": "Fred F. User",
* "active": false
* },
* "updateAuthor": {
* "self": "http://www.example.com/jira/rest/api/2.0/user?username=fred",
* "name": "fred",
* "displayName": "Fred F. User",
* "active": false
* },
* "comment": "I did some work here.",
* "visibility": {
* "type": "group",
* "value": "jira-developers"
* },
* "started": "2012-11-22T04:19:46.736-0600",
* "timeSpent": "3h 20m",
* "timeSpentSeconds": 12000,
* "id": "100028"
* }
*/
this.addWorklog = function(issueId, worklog, callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issue/' + issueId + '/worklog'),
body: worklog,
method: 'POST',
followAllRedirects: true,
json: true
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 201) {
callback(null, "Success");
return;
}
if (response.statusCode === 400) {
callback("Invalid Fields: " + JSON.stringify(body));
return;
}
if (response.statusCode === 403) {
callback("Insufficient Permissions");
return;
}
callback(response.statusCode + ': Error while updating');
});
}; |
List all Issue TypesTakes
Returns
| /*
* Result items are in the format:
* {
* "self": "http://localhostname:8090/jira/rest/api/2.0/issueType/3",
* "id": "3",
* "description": "A task that needs to be done.",
* "iconUrl": "http://localhostname:8090/jira/images/icons/task.gif",
* "name": "Task",
* "subtask": false
* }
*/
this.listIssueTypes = function(callback) {
var options = {
rejectUnauthorized: this.strictSSL,
uri: this.makeUri('/issuetype'),
method: 'GET',
json: true
};
this.request(options, function(error, response, body) {
if (error) {
callback(error, null);
return;
}
if (response.statusCode === 200) {
callback(null, body);
return;
}
callback(response.statusCode + ': Error while retrieving issue types');
});
};
}).call(JiraApi.prototype);
|