@@ -328,20 +328,25 @@ class Jira {
328
328
}
329
329
330
330
/**
331
- * Find the shortest path between two statuses using BFS
332
- * @param {Object } stateMachine - The workflow state machine
333
- * @param {string } fromStatusName - Starting status name
334
- * @param {string } toStatusName - Target status name
335
- * @returns {Array } Shortest path of transitions
336
- */
337
- findShortestTransitionPath ( stateMachine , fromStatusName , toStatusName ) {
331
+ * Find the shortest path between two statuses using BFS, excluding paths through certain states
332
+ * @param {Object } stateMachine - The workflow state machine
333
+ * @param {string } fromStatusName - Starting status name
334
+ * @param {string } toStatusName - Target status name
335
+ * @param {Array<string> } excludeStates - Array of state names to exclude from paths (optional)
336
+ * @returns {Array } Shortest path of transitions
337
+ */
338
+ findShortestTransitionPath ( stateMachine , fromStatusName , toStatusName , excludeStates = [ ] ) {
338
339
// Convert names to IDs
339
340
let fromStatusId = null
340
341
let toStatusId = null
342
+ const excludeStatusIds = new Set ( )
341
343
342
344
for ( const [ statusId , status ] of Object . entries ( stateMachine . states ) ) {
343
345
if ( status . name === fromStatusName ) fromStatusId = statusId
344
346
if ( status . name === toStatusName ) toStatusId = statusId
347
+ if ( excludeStates . includes ( status . name ) ) {
348
+ excludeStatusIds . add ( statusId )
349
+ }
345
350
}
346
351
347
352
if ( ! fromStatusId || ! toStatusId ) {
@@ -352,6 +357,12 @@ class Jira {
352
357
return [ ] // Already at destination
353
358
}
354
359
360
+ // Check if target status is in excluded states
361
+ if ( excludeStatusIds . has ( toStatusId ) ) {
362
+ console . warn ( `Target status "${ toStatusName } " is in the excluded states list` )
363
+ return null
364
+ }
365
+
355
366
// BFS to find shortest path
356
367
const queue = [ { statusId : fromStatusId , path : [ ] } ]
357
368
const visited = new Set ( [ fromStatusId ] )
@@ -362,6 +373,11 @@ class Jira {
362
373
const transitions = stateMachine . transitionMap . get ( currentId )
363
374
if ( transitions ) {
364
375
for ( const [ nextStatusId , transition ] of transitions ) {
376
+ // Skip if the next status is in the excluded list (unless it's the target)
377
+ if ( excludeStatusIds . has ( nextStatusId ) && nextStatusId !== toStatusId ) {
378
+ continue
379
+ }
380
+
365
381
if ( nextStatusId === toStatusId ) {
366
382
// Found the target
367
383
return [ ...path , {
@@ -392,16 +408,16 @@ class Jira {
392
408
}
393
409
}
394
410
395
- return null // No path found
411
+ return null
396
412
}
397
413
398
414
/**
399
415
* Transition an issue through multiple states to reach target
400
416
* @param {string } issueKey - Jira issue key
401
- * @param {string } targetStatus - Target status
402
- * @param {Map } transitionGraph - Pre-built transition graph (optional)
417
+ * @param {string } targetStatus - Target status name
418
+ * @param {Array<string> } excludeStates - Array of state names to exclude from paths (optional)
403
419
*/
404
- async transitionIssue ( issueKey , targetStatusName ) {
420
+ async transitionIssue ( issueKey , targetStatusName , excludeStates = [ 'Blocked' , 'Rejected' ] ) {
405
421
try {
406
422
// Get current issue status
407
423
const issueResponse = await this . request ( `/issue/${ issueKey } ?fields=status` )
@@ -413,15 +429,20 @@ class Jira {
413
429
return true
414
430
}
415
431
416
- const [ projectKey ] = issueKey . split ( '-' )
432
+ const [ projectKey ] = issueKey . split ( '-' )
417
433
const workflowName = await this . getProjectWorkflowName ( projectKey )
418
434
const stateMachine = await this . getWorkflowStateMachine ( workflowName )
419
435
420
- // Find shortest path using BFS
421
- const shortestPath = this . findShortestTransitionPath ( stateMachine , currentStatusName , targetStatusName )
436
+ // Find shortest path using BFS, excluding specified states
437
+ const shortestPath = this . findShortestTransitionPath (
438
+ stateMachine ,
439
+ currentStatusName ,
440
+ targetStatusName ,
441
+ excludeStates
442
+ )
422
443
423
444
if ( ! shortestPath ) {
424
- console . error ( `No transition path found from ${ currentStatusName } to ${ targetStatusName } ` )
445
+ console . error ( `No transition path found from ${ currentStatusName } to ${ targetStatusName } that avoids ${ excludeStates . join ( ', ' ) } ` )
425
446
return false
426
447
}
427
448
0 commit comments