Skip to content

Commit

Permalink
feat(jira): improve setup UI for transition ids
Browse files Browse the repository at this point in the history
* Show user issue transitions before asking for the ids.
* Wait for an issue to ask for the id.
* Export some constants so status can be referenciated from outside.
  • Loading branch information
tagoro9 committed Feb 23, 2017
1 parent 2cddf0d commit 69576a0
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 62 deletions.
57 changes: 24 additions & 33 deletions lib/issue-tracker/jira/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,31 +26,18 @@ var _issue = require('./issue');

var _issue2 = _interopRequireDefault(_issue);

var _status = require('./status');

var _status2 = _interopRequireDefault(_status);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

exports['default'] = function (config) {
return function () {
(0, _util.debug)('jira', 'Initializing Jira api');
var root = config.get(['jira', 'root']) ? (0, _util.wrapInPromise)(config.get(['jira', 'root'])) : _ramda2['default'].composeP(config.update(['jira', 'root']), _reporter2['default'].question)({ question: 'What\'s your jira root?' });
var statusPromise = root.then(function () {
return _ramda2['default'].either(_ramda2['default'].isNil, _ramda2['default'].isEmpty)(config.get(['jira', 'status'])) ? _ramda2['default'].composeP(config.update(['jira', 'status']), _ramda2['default'].compose(_util.wrapInPromise, function (_ref) {
var _ref2 = _slicedToArray(_ref, 4),
BACKLOG = _ref2[0],
SELECTED_FOR_DEVELOPMENT = _ref2[1],
IN_PROGRESS = _ref2[2],
IN_REVIEW = _ref2[3];

return {
BACKLOG: BACKLOG, SELECTED_FOR_DEVELOPMENT: SELECTED_FOR_DEVELOPMENT, IN_PROGRESS: IN_PROGRESS, IN_REVIEW: IN_REVIEW
};
}), _ramda2['default'].compose(_util.wrapInPromise, JSON.parse), _ramda2['default'].compose(_util.wrapInPromise, _ramda2['default'].concat('['), _ramda2['default'].concat(_ramda2['default'].__, ']')), _reporter2['default'].question)({ question: 'What are your jira step ids (Backlog, to do, in progress, in review)? Enter a comma separated list' }) : (0, _util.wrapInPromise)(config.get(['jira', 'status']));
});

return Promise.all([root, statusPromise]).then(function (_ref3) {
var _ref4 = _slicedToArray(_ref3, 2),
jiraRoot = _ref4[0],
status = _ref4[1];

return root.then(function (jiraRoot) {
var _httpClient = (0, _httpClient3['default'])(jiraRoot),
get = _httpClient.get,
post = _httpClient.post,
Expand All @@ -63,10 +50,10 @@ exports['default'] = function (config) {
(0, _util.debug)('jira', 'Reading user login info');
var readUsernamePromise = _reporter2['default'].question({ question: 'What\'s your Jira username?' });
var readPasswordPromise = readUsernamePromise.then(_ramda2['default'].partial(_reporter2['default'].question, [{ question: 'What\'s your Jira password?', password: true }]));
return Promise.all([readUsernamePromise, readPasswordPromise]).then(function (_ref5) {
var _ref6 = _slicedToArray(_ref5, 2),
login = _ref6[0],
password = _ref6[1];
return Promise.all([readUsernamePromise, readPasswordPromise]).then(function (_ref) {
var _ref2 = _slicedToArray(_ref, 2),
login = _ref2[0],
password = _ref2[1];

return { login: login, password: password };
});
Expand Down Expand Up @@ -104,20 +91,24 @@ exports['default'] = function (config) {
issueRoot: issueRoot,
getCurrentUser: _ramda2['default'].always((0, _util.wrapInPromise)(user)),
getIssue: _ramda2['default'].composeP(parseIssue, _ramda2['default'].compose((0, _error.catchPromiseAndThrow)('jira', _error.errors.jira.issueNotFound), get, _ramda2['default'].concat(_ramda2['default'].__, '?expand=transitions'), _ramda2['default'].concat('/rest/api/2/issue/')), (0, _util.debugCurriedP)('jira', 'Getting issue from jira')),
setIssueStatus: _ramda2['default'].curryN(2, function (_ref7, issue) {
var issueStatus = _ref7.status,
comment = _ref7.comment;
setIssueStatus: _ramda2['default'].curryN(2, function (_ref3, issue) {
var issueStatus = _ref3.status,
comment = _ref3.comment;
return _ramda2['default'].composeP(_ramda2['default'].always(issue),
// Jira api for transition is not adding the comment so we need an extra api call
_ramda2['default'].partial(_ramda2['default'].unless(_ramda2['default'].isNil, addCommentToIssue(issue)), [comment]), post('/rest/api/2/issue/' + issue.key + '/transitions'), (0, _util.debugCurriedP)('jira', 'Updating issue status to ' + issueStatus))({
body: {
transition: _ramda2['default'].compose(_ramda2['default'].pick(['id']), _ramda2['default'].find(_ramda2['default'].compose(_ramda2['default'].equals(issueStatus), Number, _ramda2['default'].path(['to', 'id']))), _ramda2['default'].prop('transitions'))(issue),
fields: {}
}
});
_ramda2['default'].partial(_ramda2['default'].unless(_ramda2['default'].isNil, addCommentToIssue(issue)), [comment]), post('/rest/api/2/issue/' + issue.key + '/transitions'), (0, _util.debugCurriedP)('jira', 'Updating issue status to ' + issueStatus), function (statuses) {
return (0, _util.wrapInPromise)({
body: {
transition: _ramda2['default'].compose(_ramda2['default'].pick(['id']), _ramda2['default'].find(_ramda2['default'].compose(_ramda2['default'].equals(statuses[issueStatus]), Number, _ramda2['default'].path(['to', 'id']))), _ramda2['default'].prop('transitions'))(issue),
fields: {}
}
});
}, (0, _status2['default'])(config))(issue);
}),
canWorkOnIssue: (0, _issue2['default'])(status).canWorkOnIssue,
status: status
canWorkOnIssue: _ramda2['default'].curryN(2, _ramda2['default'].converge(function (canWonOnIssue, promise) {
return promise.then(canWonOnIssue);
}, [_ramda2['default'].curryN(2, _ramda2['default'].invoker(2, 'canWorkOnIssue')), _ramda2['default'].composeP(_ramda2['default'].compose(_util.wrapInPromise, _issue2['default']), _ramda2['default'].flip((0, _status2['default'])(config)))])),
status: _status.status
};
});
});
Expand Down
52 changes: 45 additions & 7 deletions lib/issue-tracker/jira/status.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,49 @@
"use strict";
'use strict';

Object.defineProperty(exports, "__esModule", {
value: true
});
exports["default"] = {
BACKLOG: 10000,
SELECTED_FOR_DEVELOPMENT: 10001,
IN_PROGRESS: 3,
CODE_REVIEW: 10005
};
exports.status = undefined;

var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }();

var _ramda = require('ramda');

var _ramda2 = _interopRequireDefault(_ramda);

var _util = require('../../util');

var _reporter = require('../../reporter');

var _reporter2 = _interopRequireDefault(_reporter);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; }

var status = exports.status = {
BACKLOG: 'BACKLOG',
IN_PROGRESS: 'IN_PROGRESS',
IN_REVIEW: 'IN_PREVIEW',
SELECTED_FOR_DEVELOPMENT: 'SELECTED_FOR_DEVELOPMENT'
};

exports['default'] = _ramda2['default'].curryN(2, function (config, issue) {
var askForStatus = _ramda2['default'].composeP(config.update(['jira', 'status']), _ramda2['default'].compose(_util.wrapInPromise, function (_ref) {
var _ref2 = _slicedToArray(_ref, 4),
BACKLOG = _ref2[0],
SELECTED_FOR_DEVELOPMENT = _ref2[1],
IN_PROGRESS = _ref2[2],
IN_REVIEW = _ref2[3];

return {
BACKLOG: BACKLOG, SELECTED_FOR_DEVELOPMENT: SELECTED_FOR_DEVELOPMENT, IN_PROGRESS: IN_PROGRESS, IN_REVIEW: IN_REVIEW
};
}), _ramda2['default'].compose(_util.wrapInPromise, JSON.parse), _ramda2['default'].compose(_util.wrapInPromise, _ramda2['default'].concat('['), _ramda2['default'].concat(_ramda2['default'].__, ']')), _ramda2['default'].compose(_reporter2['default'].question, _ramda2['default'].always({
question: 'What are the ids for the transitions that represent\n' + 'Backlog, to do, in progress, in review (enter a comma separated list)?'
}), _reporter2['default'].info, _ramda2['default'].concat('These are the possible transitions found for the issue:\n')));

return _ramda2['default'].ifElse(_ramda2['default'].compose(_ramda2['default'].either(_ramda2['default'].isNil, _ramda2['default'].isEmpty), _ramda2['default'].invoker(1, 'get')(['jira', 'status'])), _ramda2['default'].partial(_ramda2['default'].compose(askForStatus, _ramda2['default'].join('\n'), _ramda2['default'].map(function (_ref3) {
var name = _ref3.name,
id = _ref3.id;
return ' * ' + name + ': ' + id;
}), _ramda2['default'].map(_ramda2['default'].prop('to')), _ramda2['default'].prop('transitions')), [issue]), _ramda2['default'].compose(_util.wrapInPromise, _ramda2['default'].invoker(1, 'get')(['jira', 'status'])))(config);
});
7 changes: 7 additions & 0 deletions lib/reporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,13 @@ exports['default'] = {
}(),

log: log,
info: function () {
function info(msg) {
return log(_chalk2['default'].grey('info') + ' ' + msg);
}

return info;
}(),
error: function () {
function error(msg) {
log(_chalk2['default'].red('error') + ' ' + prependEmoji(msg, _nodeEmoji2['default'].get('boom')));
Expand Down
41 changes: 19 additions & 22 deletions src/issue-tracker/jira/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,30 +4,16 @@ import { debug, debugCurried, debugCurriedP, wrapInPromise } from '../../util';
import reporter from '../../reporter';
import { errors, catchPromiseAndThrow } from '../../error';
import issueUtil from './issue';
import readIssueStatus, { status } from './status';


export default config => () => {
debug('jira', 'Initializing Jira api');
const root = config.get(['jira', 'root'])
? wrapInPromise(config.get(['jira', 'root']))
: R.composeP(config.update(['jira', 'root']), reporter.question)({ question: 'What\'s your jira root?' });
const statusPromise = root.then(() =>
(R.either(R.isNil, R.isEmpty)(config.get(['jira', 'status']))
? R.composeP(
config.update(['jira', 'status']),
R.compose(
wrapInPromise,
([BACKLOG, SELECTED_FOR_DEVELOPMENT, IN_PROGRESS, IN_REVIEW]) => ({
BACKLOG, SELECTED_FOR_DEVELOPMENT, IN_PROGRESS, IN_REVIEW
})
),
R.compose(wrapInPromise, JSON.parse),
R.compose(wrapInPromise, R.concat('['), R.concat(R.__, ']')),
reporter.question
)({ question: 'What are your jira step ids (Backlog, to do, in progress, in review)? Enter a comma separated list' })
: wrapInPromise(config.get(['jira', 'status'])))
);

return Promise.all([root, statusPromise]).then(([jiraRoot, status]) => {
return root.then(jiraRoot => {
const { get, post, setAuth } = httpClient(jiraRoot);
const issueRoot = `${jiraRoot}/browse/`;
const readUserInfo = () => {
Expand Down Expand Up @@ -86,19 +72,30 @@ export default config => () => {
// Jira api for transition is not adding the comment so we need an extra api call
R.partial(R.unless(R.isNil, addCommentToIssue(issue)), [comment]),
post(`/rest/api/2/issue/${issue.key}/transitions`),
debugCurriedP('jira', `Updating issue status to ${issueStatus}`)
)({
debugCurriedP('jira', `Updating issue status to ${issueStatus}`),
statuses => wrapInPromise({
body: {
transition: R.compose(
R.pick(['id']),
R.find(R.compose(R.equals(issueStatus), Number, R.path(['to', 'id']))),
R.find(R.compose(R.equals(statuses[issueStatus]), Number, R.path(['to', 'id']))),
R.prop('transitions')
)(issue),
fields: {},
}
})
}),
readIssueStatus(config)
)(issue)
),
canWorkOnIssue: issueUtil(status).canWorkOnIssue,
canWorkOnIssue: R.curryN(2, R.converge(
(canWonOnIssue, promise) => promise.then(canWonOnIssue),
[
R.curryN(2, R.invoker(2, 'canWorkOnIssue')),
R.composeP(
R.compose(wrapInPromise, issueUtil),
R.flip(readIssueStatus(config))
)
]
)),
status
}));
});
Expand Down
48 changes: 48 additions & 0 deletions src/issue-tracker/jira/status.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import R from 'ramda';
import { wrapInPromise } from '../../util';
import reporter from '../../reporter';

export const status = {
BACKLOG: 'BACKLOG',
IN_PROGRESS: 'IN_PROGRESS',
IN_REVIEW: 'IN_PREVIEW',
SELECTED_FOR_DEVELOPMENT: 'SELECTED_FOR_DEVELOPMENT'
};

export default R.curryN(2, (config, issue) => {
const askForStatus = R.composeP(
config.update(['jira', 'status']),
R.compose(
wrapInPromise,
([BACKLOG, SELECTED_FOR_DEVELOPMENT, IN_PROGRESS, IN_REVIEW]) => ({
BACKLOG, SELECTED_FOR_DEVELOPMENT, IN_PROGRESS, IN_REVIEW
})
),
R.compose(wrapInPromise, JSON.parse),
R.compose(wrapInPromise, R.concat('['), R.concat(R.__, ']')),
R.compose(
reporter.question,
R.always({
question: 'What are the ids for the transitions that represent\n' +
'Backlog, to do, in progress, in review (enter a comma separated list)?'
}),
reporter.info,
R.concat('These are the possible transitions found for the issue:\n'),
)
);

return R.ifElse(
R.compose(
R.either(R.isNil, R.isEmpty), R.invoker(1, 'get')(['jira', 'status'])
),
R.partial(R.compose(
askForStatus,
R.join('\n'),
R.map(({ name, id }) => ` * ${name}: ${id}`),
R.map(R.prop('to')),
R.prop('transitions')
), [issue]),
R.compose(wrapInPromise, R.invoker(1, 'get')(['jira', 'status']))
)(config);
});

1 change: 1 addition & 0 deletions src/reporter/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default {
return { step: step(totalSteps), stepCurried: stepCurried(totalSteps) };
},
log,
info: (msg) => log(`${format.grey('info')} ${msg}`),
error(msg) {
log(`${format.red('error')} ${prependEmoji(msg, emojis.get('boom'))}`);
},
Expand Down

0 comments on commit 69576a0

Please sign in to comment.