NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Jira no fix version in ready for release // @namespace https://openuserjs.org/users/floodmeadows // @description Show list of Jira tickets with a state of Ready for Release without a value for fix_version // @copyright 2022, floodmeadows (https://openuserjs.org/users/floodmeadows) // @license MIT // @version 0.4 // @include https://jira.*.uk/secure/RapidBoard.jspa?rapidView=5483* // @grant none // @updateURL https://openuserjs.org/meta/floodmeadows/Jira_no_fix_version_in_ready_for_release.meta.js // @downloadURL https://openuserjs.org/install/floodmeadows/Jira_no_fix_version_in_ready_for_release.user.js // ==/UserScript== // ==OpenUserJS== // @authors floodmeadows // ==/OpenUserJS== /* jshint esversion: 6 */ //--- Enter your search query -----------// const jql = 'MY_JIRA_SEARCH_QUERY'; // e.g. 'project = MY-PROJECT AND status in (LIST_OF_STATUS_VALUES) ORDER BY key' //---------------------------------------// const currentUrl = new URL(document.URL); const myJiraBaseUrl = currentUrl.protocol + '//' + currentUrl.host; (function () { 'use strict'; addPossibleIssuesContainer(); checkForProblemIssues(); })(); function addPossibleIssuesContainer() { const parentElementId = 'ghx-modes-tools'; var subtasksToCheckContainer = document.createElement("div"); var t = "Possible issues: "; subtasksToCheckContainer.setAttribute('id','subtasks-to-check-container'); subtasksToCheckContainer.setAttribute('style','position:absolute; top:4em; right:1.5em; margin-top:0.5em; text-align:right;'); document.getElementById(parentElementId).appendChild(subtasksToCheckContainer); } function checkForProblemIssues() { var headers = new Headers(); headers.append("Content-Type", "application/json"); const baseApiUrl = myJiraBaseUrl + '/rest/api/latest/search'; const baseStoryUrl = myJiraBaseUrl + '/browse/'; const fields = 'key,summary,status'; const jiraApiSearchUrl = baseApiUrl + '?jql=' + encodeURI(jql) + '&fields=' + fields; const jiraWebSearchUrl = myJiraBaseUrl + '/issues/?jql=' + encodeURI(jql); console.log('api URL: ' + jiraApiSearchUrl); console.log('web URL: ' + jiraWebSearchUrl); var requestOptions = { method: 'GET', headers: headers }; fetch(jiraApiSearchUrl, requestOptions) .then(response => response.json()) .then( json => { var problemIssues = []; // console.log('json = ' + JSON.stringify(json)) for (const [_, issue] of Object.entries(json.issues)) { console.log("issue.fields.fixVersions = " + issue.fields.fixVersions); if (issue.fields.status.name == "Ready for Release" && typeof(issue.fields.fixVersions == 'undefined')) { problemIssues.push(" <a href='" + baseStoryUrl + issue.key + "' target='_blank' title='" + issue.fields.summary.replace(/'/g, "'") + "'>" + issue.key + "</a>"); console.log(baseStoryUrl + issue.key + " is in Ready for Release, but has no fixVersion."); } } var e = document.getElementById('subtasks-to-check-container'); if (problemIssues.length > 0) { console.log("R4R but no fix version: " + problemIssues); e.innerHTML = '<a href="' + jiraWebSearchUrl + '" target="_blank">' + problemIssues.length + ' items</a> Ready for Release but no fix version: ' + problemIssues; } else { e.innerHTML = "All good: Ready for Release tickets all have fixVersions."; } } ) .catch(error => console.log('error', error)); }