Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify successor management since now issue links are no longer inherited #1116

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

### Changed
* Enhance SSDS Document Generation Performance using New Atlassian APIs ([#1084](https://github.com/opendevstack/ods-jenkins-shared-library/issues/1084))
* Simplify successor management since now issue links are no longer inherited ([#1116](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1116))

### Fixed
* Fix Tailor deployment drifts for D, Q envs ([#1055](https://github.com/opendevstack/ods-jenkins-shared-library/pull/1055))
Expand Down
71 changes: 71 additions & 0 deletions src/org/ods/orchestration/util/Project.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -1288,6 +1288,8 @@ class Project {
logger.info("loadJiraData: Found a predecessor project version with ID '${previousVersionId}'. Loading its data.")
def savedDataFromOldVersion = this.loadSavedJiraData(previousVersionId)
def mergedData = this.mergeJiraData(savedDataFromOldVersion, newData)
mergedData = this.overrideDeltaDocgenDataLinks(mergedData, newData)
mergedData = this.removeObsoleteIssuesFromComponents(mergedData)
result << this.addKeyAndVersionToComponentsWithout(mergedData)
result.previousVersion = previousVersionId
} else {
Expand All @@ -1301,6 +1303,75 @@ class Project {
return result
}

/**
* It uses the data from the deltadocgen of the latest version as a source of truth in terms of links.
* If an issue appears in the deltadocgen report, we use all its data adding the expanded predecessors.
* If an issue appears as a link in the old data but in the deltadocgen report doesn't show the same link in the other
* direction, then we remove that link.
*
* @param mergedData resulting data of merging last release json report and deltadocgen
* @param deltaDocgenData result of deltadocgen endpoint for the latest version
* @return the merged data with the proper links
*/
protected Map overrideDeltaDocgenDataLinks(Map<String,Map> mergedData, Map<String,Map> deltaDocgenData) {
mergedData.findAll { JiraDataItem.REGULAR_ISSUE_TYPES.contains(it.key) }.each { issueType, issues ->
issues.values().each { Map issueToUpdate ->
if(deltaDocgenData[issueType] && deltaDocgenData[issueType][issueToUpdate.key]) {
def resultData = deltaDocgenData[issueType][issueToUpdate.key]
resultData << [expandedPredecessors: mergedData[issueType][issueToUpdate.key]['expandedPredecessors']]
mergedData[issueType][issueToUpdate.key] = resultData
} else {
mergedData[issueType][issueToUpdate.key].findAll { JiraDataItem.REGULAR_ISSUE_TYPES.contains(it.key) }.each { relatedIssueType, relatedIssues ->
def relatedIssuesToRemove = findRelatedIssuesToRemove(relatedIssues, deltaDocgenData, relatedIssueType, issueType, issueToUpdate)
mergedData[issueType][issueToUpdate.key][relatedIssueType].removeAll { relatedIssuesToRemove.contains(it) }
}
}
}
}
return mergedData
}

/**
* The method checks each issue in the 'relatedIssues' list against the related issues in the 'deltaDocgenData'.
* If the issueToUpdate key does not appear in the deltaDocgenData as a related issue but the deltaDocGen has some
* issues related for that issue type, the issue is added to the list of issues to be removed.
*
* @param relatedIssues A list of related issues to be examined.
* @param deltaDocgenData A map containing data from the deltaDocGen
* @param relatedIssueType The type of the related issue.
* @param issueType The type of the issue.
* @param issueToUpdate A map containing the issue to be updated.
*
* @return A list of related issues that need to be removed.
*/
protected static List findRelatedIssuesToRemove(List<String> relatedIssues, Map deltaDocgenData, String relatedIssueType, String issueType, Map issueToUpdate) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add Javadoc to this method. Why this is static?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added Javadoc. The method is static since it doesn't depend on any instance variables or methods of the class it's defined in.

def relatedIssuesToRemove = []
relatedIssues.each {
if (deltaDocgenData[relatedIssueType][it] && deltaDocgenData[relatedIssueType][it][issueType] && !deltaDocgenData[relatedIssueType][it][issueType].contains(issueToUpdate.key)) {
relatedIssuesToRemove.add(it)
}
}
return relatedIssuesToRemove
}

/**
* It removes any issue in the components map that does not appear under the technology map it should belong
*
* @param mergedData resulting data of merging last release json report and deltadocgen
* @return the merged data with the proper issues in the components map
*/
protected Map removeObsoleteIssuesFromComponents(Map<String,Map> mergedData) {
mergedData[JiraDataItem.TYPE_COMPONENTS].collectEntries { component, componentIssues ->
JiraDataItem.REGULAR_ISSUE_TYPES.each { issueType ->
if(componentIssues[issueType]) {
componentIssues[issueType].removeAll { !mergedData[issueType].keySet().contains(it) }
}
}
[(component): componentIssues]
}
return mergedData
}

protected Map loadJiraDataBugs(Map tests, String versionName = null) {
if (!this.jiraUseCase) return [:]
if (!this.jiraUseCase.jira) return [:]
Expand Down
23 changes: 11 additions & 12 deletions test/groovy/org/ods/orchestration/util/ProjectSpec.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -2246,7 +2246,6 @@ class ProjectSpec extends SpecHelper {
def firstVersion = '1.0'
def secondVersion = '2.0'

def cmp ={ name -> [key: "CMP-${name}" as String, name: "Component 1"]}
def req = { name, String version = null -> [key: "REQ-${name}" as String, description:name, versions:[version]] }
def ts = { name, String version = null -> [key: "TS-${name}" as String, description:name, versions:[version]] }
def rsk = { name, String version = null -> [key: "RSK-${name}" as String, description:name, versions:[version]] }
Expand All @@ -2272,23 +2271,23 @@ class ProjectSpec extends SpecHelper {
ts1 << [requirements: [req1.key], tests: [tst1.key, tst2.key]]
rsk1 << [requirements: [req1.key], mitigations: [mit1.key]]
mit1 << [requirements: [req1.key], risks: [rsk1.key]]
req2 << [predecessors: [req1.key], tests: [tst4.key]]
tst3 << [predecessors: [tst1.key]]
req2 << [predecessors: [req1.key], tests: [tst2.key,tst3.key,tst4.key], techSpecs: [ts2.key], risks: [rsk2.key], mitigations: [mit2.key]]
tst3 << [predecessors: [tst1.key], requirements: [req2.key], techSpecs: [ts2.key]]
tst4 << [requirements: [req2.key]]
rsk2 << [predecessors: [rsk1.key], requirements: [req1.key]]
mit2 << [predecessors: [mit1.key], requirements: [req1.key], risks: [rsk1.key]]
ts2 << [predecessors: [ts1.key]]
rsk2 << [predecessors: [rsk1.key], requirements: [req2.key], mitigations: [mit2.key]]
mit2 << [predecessors: [mit1.key], requirements: [req2.key], risks: [rsk2.key]]
ts2 << [predecessors: [ts1.key], requirements: [req2.key], tests: [tst2.key, tst3.key]]

def req2Updated = req2.clone() + [tests: [tst4.key, tst3.key, tst2.key], techSpecs: [ts2.key], risks: [rsk2.key], mitigations: [mit2.key]]
def req2Updated = req2.clone()
req2Updated << [expandedPredecessors: [[key: req1.key, versions: req1.versions]]]
def tst2Updated = tst2.clone() + [requirements: [req2.key], techSpecs: [ts2.key]]
def tst3Updated = tst3.clone() + [requirements: [req2.key], techSpecs: [ts2.key]]
def tst2Updated = tst2.clone()
def tst3Updated = tst3.clone()
tst3Updated << [expandedPredecessors: [[key: tst1.key, versions: tst1.versions]]]
def rsk2Updated = rsk2.clone() + [requirements: [req2.key], mitigations: [mit2.key]]
def rsk2Updated = rsk2.clone()
rsk2Updated << [expandedPredecessors: [[key: rsk1.key, versions: rsk1.versions]]]
def mit2Updated = mit2.clone() + [requirements: [req2.key], risks: [rsk2.key]]
def mit2Updated = mit2.clone()
mit2Updated << [expandedPredecessors: [[key: mit1.key, versions: mit1.versions]]]
def ts2Updated = ts2.clone() + [requirements: [req2.key], tests: [tst3.key, tst2.key]]
def ts2Updated = ts2.clone()
ts2Updated << [expandedPredecessors: [[key: ts1.key, versions: ts1.versions]]]

def storedData = [
Expand Down