@@ -6,36 +6,43 @@ const Jira = require('./../utils/jira')
66const statusMap = {
77 'master' : {
88 status : 'Done' ,
9- fields : {
10- resolution : 'Done' ,
9+ transitionFields : {
10+ resolution : 'Done'
11+ } ,
12+ customFields : {
1113 // prod release timestamp
1214 customfield_11475 : new Date ( ) ,
13- customfield_11473 : 'Production' ,
15+ customfield_11473 : 'Production'
1416 }
1517 } ,
1618 'main' : {
1719 status : 'Done' ,
18- fields : {
19- resolution : 'Done' ,
20+ transitionFields : {
21+ resolution : 'Done'
22+ } ,
23+ customFields : {
2024 // prod release timestamp
2125 customfield_11475 : new Date ( ) ,
22- customfield_11473 : 'Production' ,
26+ customfield_11473 : 'Production'
2327 }
2428 } ,
2529 'staging' : {
2630 status : 'Deployed to Staging' ,
27- fields : {
28- resolution : 'Done' ,
31+ transitionFields : {
32+ resolution : 'Done'
33+ } ,
34+ customFields : {
2935 // staging release timestamp
3036 customfield_11474 : new Date ( ) ,
31- customfield_11473 : 'Staging' ,
37+ customfield_11473 : 'Staging'
3238 }
3339 } ,
3440 'dev' : {
3541 status : 'Deployed to Dev' ,
36- fields : {
37- resolution : 'Done' ,
38- }
42+ transitionFields : {
43+ resolution : 'Done'
44+ } ,
45+ customFields : { }
3946 }
4047}
4148
@@ -119,6 +126,27 @@ async function prepareFields(fields, jiraUtil) {
119126 return preparedFields
120127}
121128
129+ /**
130+ * Update issue with transition and then update custom fields separately
131+ */
132+ async function updateIssueWithCustomFields ( jiraUtil , issueKey , targetStatus , excludeStates , transitionFields , customFields ) {
133+ try {
134+ // First, transition the issue with only transition-allowed fields
135+ const preparedTransitionFields = await prepareFields ( transitionFields , jiraUtil )
136+ await jiraUtil . transitionIssue ( issueKey , targetStatus , excludeStates , preparedTransitionFields )
137+
138+ // Then, if there are custom fields to update, update them separately
139+ if ( customFields && Object . keys ( customFields ) . length > 0 ) {
140+ await jiraUtil . updateCustomFields ( issueKey , customFields )
141+ }
142+
143+ return true
144+ } catch ( error ) {
145+ console . error ( `Failed to update ${ issueKey } :` , error . message )
146+ throw error
147+ }
148+ }
149+
122150/**
123151 * Handle pull request events (open, close, etc)
124152 */
@@ -134,6 +162,7 @@ async function handlePullRequestEvent(eventData, jiraUtil) {
134162 console . log ( `Found Jira issues: ${ issueKeys . join ( ', ' ) } ` )
135163
136164 let targetStatus = null
165+ let transitionFields = { }
137166 let customFields = { }
138167 const targetBranch = pull_request . base . ref
139168
@@ -156,10 +185,11 @@ async function handlePullRequestEvent(eventData, jiraUtil) {
156185 const branchConfig = statusMap [ targetBranch ]
157186 if ( branchConfig ) {
158187 targetStatus = branchConfig . status
159- customFields = branchConfig . fields || { }
188+ transitionFields = branchConfig . transitionFields || { }
189+ customFields = branchConfig . customFields || { }
160190 } else {
161191 targetStatus = 'Done'
162- customFields = { resolution : 'Done' }
192+ transitionFields = { resolution : 'Done' }
163193 }
164194 } else {
165195 console . log ( 'PR closed without merging, skipping status update' )
@@ -172,11 +202,16 @@ async function handlePullRequestEvent(eventData, jiraUtil) {
172202 }
173203
174204 if ( targetStatus ) {
175- const preparedFields = await prepareFields ( customFields , jiraUtil )
176-
177205 for ( const issueKey of issueKeys ) {
178206 try {
179- await jiraUtil . transitionIssue ( issueKey , targetStatus , [ 'Blocked' , 'Rejected' ] , preparedFields )
207+ await updateIssueWithCustomFields (
208+ jiraUtil ,
209+ issueKey ,
210+ targetStatus ,
211+ [ 'Blocked' , 'Rejected' ] ,
212+ transitionFields ,
213+ customFields
214+ )
180215 } catch ( error ) {
181216 console . error ( `Failed to update ${ issueKey } :` , error . message )
182217 }
@@ -209,8 +244,8 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
209244 }
210245
211246 const newStatus = branchConfig . status
212- const customFields = branchConfig . fields || { }
213- const preparedFields = await prepareFields ( customFields , jiraUtil )
247+ const transitionFields = branchConfig . transitionFields || { }
248+ const customFields = branchConfig . customFields || { }
214249
215250 const shouldCheckCommitHistory = [ 'master' , 'main' , 'staging' ] . includes ( branch )
216251
@@ -225,11 +260,13 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
225260 if ( commitHistoryIssues . length > 0 ) {
226261 console . log ( `Found ${ commitHistoryIssues . length } issues in production commit history` )
227262
228- const updateResults = await jiraUtil . updateIssuesFromCommitHistory (
263+ const updateResults = await updateIssuesFromCommitHistoryWithCustomFields (
264+ jiraUtil ,
229265 commitHistoryIssues ,
230266 newStatus ,
231267 [ 'Blocked' , 'Rejected' ] ,
232- preparedFields
268+ transitionFields ,
269+ customFields
233270 )
234271
235272 console . log ( `Production deployment results: ${ updateResults . successful } successful, ${ updateResults . failed } failed` )
@@ -246,7 +283,7 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
246283 const prUrl = `${ repositoryName } /pull/${ prNumber } `
247284 if ( prNumber ) {
248285 console . log ( `Also updating issues from PR ${ prUrl } to production status` )
249- await jiraUtil . updateByPR ( prUrl , newStatus , preparedFields )
286+ await updateByPRWithCustomFields ( jiraUtil , prUrl , newStatus , transitionFields , customFields )
250287 }
251288 }
252289 return
@@ -263,11 +300,13 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
263300 console . log ( `Found ${ commitHistoryIssues . length } issues in staging commit history` )
264301
265302 // Update issues found in commit history
266- const updateResults = await jiraUtil . updateIssuesFromCommitHistory (
303+ const updateResults = await updateIssuesFromCommitHistoryWithCustomFields (
304+ jiraUtil ,
267305 commitHistoryIssues ,
268306 newStatus ,
269307 [ 'Blocked' , 'Rejected' ] ,
270- preparedFields
308+ transitionFields ,
309+ customFields
271310 )
272311
273312 console . log ( `Staging deployment results: ${ updateResults . successful } successful, ${ updateResults . failed } failed` )
@@ -285,7 +324,7 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
285324 const prNumber = prMatch [ 1 ]
286325 const prUrl = `${ repositoryName } /pull/${ prNumber } `
287326 console . log ( `Also updating issues from PR ${ prUrl } to staging status` )
288- await jiraUtil . updateByPR ( prUrl , newStatus , preparedFields )
327+ await updateByPRWithCustomFields ( jiraUtil , prUrl , newStatus , transitionFields , customFields )
289328 }
290329 return
291330 }
@@ -295,7 +334,7 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
295334 const prNumber = prMatch [ 1 ]
296335 const prUrl = `${ repositoryName } /pull/${ prNumber } `
297336 console . log ( `Updating issues mentioning PR ${ prUrl } to status: ${ newStatus } ` )
298- await jiraUtil . updateByPR ( prUrl , newStatus , preparedFields )
337+ await updateByPRWithCustomFields ( jiraUtil , prUrl , newStatus , transitionFields , customFields )
299338 }
300339
301340 // Additionally, for important branches, check commit history for issue keys
@@ -308,11 +347,13 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
308347 console . log ( `Found ${ commitHistoryIssues . length } additional issues in commit history for ${ branch } branch` )
309348
310349 // Update issues found in commit history
311- const updateResults = await jiraUtil . updateIssuesFromCommitHistory (
350+ const updateResults = await updateIssuesFromCommitHistoryWithCustomFields (
351+ jiraUtil ,
312352 commitHistoryIssues ,
313353 newStatus ,
314354 [ 'Blocked' , 'Rejected' ] ,
315- preparedFields
355+ transitionFields ,
356+ customFields
316357 )
317358
318359 console . log ( `Commit history update results: ${ updateResults . successful } successful, ${ updateResults . failed } failed` )
@@ -324,6 +365,76 @@ async function handlePushEvent(branch, jiraUtil, githubRepository, githubToken)
324365 }
325366}
326367
368+ /**
369+ * Update issues from commit history with separate custom field updates
370+ */
371+ async function updateIssuesFromCommitHistoryWithCustomFields ( jiraUtil , issueKeys , targetStatus , excludeStates , transitionFields , customFields ) {
372+ if ( ! issueKeys || issueKeys . length === 0 ) {
373+ console . log ( 'No issue keys provided for update' )
374+ return { successful : 0 , failed : 0 , errors : [ ] }
375+ }
376+
377+ console . log ( `Updating ${ issueKeys . length } issues to status: ${ targetStatus } ` )
378+
379+ const results = await Promise . allSettled (
380+ issueKeys . map ( issueKey =>
381+ updateIssueWithCustomFields ( jiraUtil , issueKey , targetStatus , excludeStates , transitionFields , customFields )
382+ )
383+ )
384+
385+ const successful = results . filter ( result => result . status === 'fulfilled' ) . length
386+ const failed = results . filter ( result => result . status === 'rejected' )
387+ const errors = failed . map ( result => result . reason ?. message || 'Unknown error' )
388+
389+ console . log ( `Update summary: ${ successful } successful, ${ failed . length } failed` )
390+ if ( failed . length > 0 ) {
391+ console . log ( 'Failed updates:' , errors )
392+ }
393+
394+ return {
395+ successful,
396+ failed : failed . length ,
397+ errors
398+ }
399+ }
400+
401+ /**
402+ * Update issues by PR with separate custom field updates
403+ */
404+ async function updateByPRWithCustomFields ( jiraUtil , prUrl , newStatus , transitionFields , customFields ) {
405+ try {
406+ let jql = `text ~ "${ prUrl } "`
407+ const response = await jiraUtil . request ( '/search/jql' , {
408+ method : 'POST' ,
409+ body : JSON . stringify ( {
410+ jql,
411+ fields : [ 'key' , 'summary' , 'status' , 'description' ] ,
412+ maxResults : 50
413+ } )
414+ } )
415+
416+ const data = await response . json ( )
417+ const issues = data . issues
418+ console . log ( `Found ${ issues . length } issues mentioning PR ${ prUrl } ` )
419+
420+ for ( const issue of issues ) {
421+ await updateIssueWithCustomFields (
422+ jiraUtil ,
423+ issue . key ,
424+ newStatus ,
425+ [ 'Blocked' , 'Rejected' ] ,
426+ transitionFields ,
427+ customFields
428+ )
429+ }
430+
431+ return issues . length
432+ } catch ( error ) {
433+ console . error ( `Error updating issues by PR:` , error . message )
434+ throw error
435+ }
436+ }
437+
327438/**
328439 * Extract Jira issue keys from PR title or body
329440 * @param {Object } pullRequest - GitHub PR object
0 commit comments