Automatically Setting Version Based on Component

In this scenario tester is setting bundle version on the issue. He doesn't have knowledge to determine which component issue belongs to, but he knows which higher level version (bundle version) he is testing. Assignee analyses the issue and assigns a component to issue. We want affects version to be automatically set based on bundle version and component. From the bundle version we can automatically detect which component versions are there in the bundle and as soon as a component is set on the bundle we should be automatically set affect version by searching the component inside the bundle.


For this we will create a "Custom Listener" using "Script Runner" add-on. We will listen for "Issue Created" and "Issue Updated" events and using the "Affects Version" information on the issue, we will fetch corresponding bundle. Than using the component of the issue we will find which component version it should contain and set this component version on the "Affects Version" field of the issue. Here is the script:

import com.deniz.jira.versioning.subcomponents.SubcomponentsService;
import com.deniz.jira.versioning.subcomponents.ComponentHierarchy;
import com.onresolve.scriptrunner.runner.customisers.PluginModule;
import com.onresolve.scriptrunner.runner.customisers.WithPlugin;
import com.atlassian.jira.issue.IssueManager;
import com.atlassian.jira.component.ComponentAccessor;
import com.deniz.jira.versioning.bundles.BundleService;
import com.deniz.jira.versioning.CmpVersionMappingService;
import com.deniz.jira.versioning.bundles.BundleNameFormatter;
import com.atlassian.jira.bc.issue.comment.CommentService;
import com.atlassian.jira.issue.IssueInputParametersImpl;
 
@WithPlugin("com.deniz.jira.versioning")
@PluginModule
BundleService bundleService;
@WithPlugin("com.deniz.jira.versioning")
@PluginModule
CmpVersionMappingService cmpVersionMappingService;

def versionManager = ComponentAccessor.getVersionManager();
def issueService = ComponentAccessor.getIssueService();
def user = ComponentAccessor.getJiraAuthenticationContext().getLoggedInUser();

//issue object is build in and com.atlassian.jira.issue.IssueImp
def versions = issue.getAffectedVersions();  
def components = issue.getComponents();
if (components.size() == 0 || versions.size() == 0) {
    return; //if no component or version is selected we can exit the script
}

//for simplicity of script, I'm assuming user is only selecting a single component and version
def component = components[0]; 
def version = versions[0];  //version class is: com.atlassian.jira.project.version.VersionImpl

def bundlesForVersion = bundleService.getBundlesForVersion(version.getId());
if (bundlesForVersion.size() == 0) {
    return; //this version doesn't belong to any bundle
}

for (bundle in bundlesForVersion) { //bundle is:com.deniz.jira.versioning.BundleImp
    System.out.println("Found bundle for issue:" + bundle.getBundleName());
    //def bundleContent = cmpVersionMappingService.getComponentsOfBundle(bundle.getId()); //FOR VERSIONS BEFORE 1.12.0
    def bundleContent = bundleService.getComponentsOfBundle(bundle.getId());  //FOR VERSION 1.12.0+
    for (componentVersion in bundleContent) {  // componentVersion is com.deniz.jira.bundle.BundleContentImp
        if (componentVersion.getComponentId() == component.getId())  {
            def pVersion = versionManager.getVersion(componentVersion.getVersionId());
            System.out.println("pVersion:" + pVersion.getName());
            def issueInputParameters = new IssueInputParametersImpl();
            issueInputParameters.setAffectedVersionIds(pVersion.getId());
            def validationResult = issueService.validateUpdate(user, issue.id, issueInputParameters)

            if (validationResult.isValid()) {
			    issueService.update(user, validationResult)
			} else {
			    log.warn validationResult.errorCollection.errors
			}
            break;
        }
    }

}