Auto-Book Dependent Environments
When you book an environment, you may also want to book its dependencies to ensure that the necessary resources and configurations are available when needed. Thankfully, you can rely on the already defined environment dependencies to completely automate the booking of dependent environments.
In this step-by-step guide, you will learn how to create a ScriptRunner Listener to automatically set a read only Environment Custom Field with dependent environments
This page documents an advanced setup that requires knowledge in following areas:
Feel free to reach out if you need assistance.
Solution Overview
At the heart of the proposed solution, you will use two different environment custom fields:
"Environment(s) to book": The main editable custom field used to select the environments you want to book.
"Booked Dependencies": Another readonly custom field used to display the list of the dependencies of booked environments
When a user updates the list of environments to book in the "Environment(s) to book" field, the list of dependencies in the "Booked Dependencies" field is automatically populated by a ScriptRunner Listener:

Quick Demo
ScriptRunner Listener
Setup of the Listener
Code of the Listener
Do not forget to adapt the name of the custom fields used in this example script.
These both custom fields must be Environment Custom Fields.
package com.apwide.golive.example.listener
import com.apwide.env.api.Environment
import com.apwide.env.api.Golive
import com.onresolve.scriptrunner.runner.customisers.WithPlugin
import com.onresolve.scriptrunner.runner.customisers.PluginModule
import com.apwide.env.api.GoliveAccessor
import com.atlassian.jira.component.ComponentAccessor
import java.util.stream.Collectors
@WithPlugin("com.holydev.env.plugin.jira-holydev-env-plugin")
@PluginModule
GoliveAccessor goliveAccessor
Golive golive = goliveAccessor.golive()
final bookedEnvironmentsFieldName = 'Environment(s) to book'
final unbookedDependenciesFieldName = 'Booked Dependencies'
private static List<Environment> getDependencyIds(List<Integer> envIds, Golive golive) {
if (!envIds || envIds.isEmpty()) {
return []
}
return envIds.stream().flatMap({ envId ->
Environment env = golive.environments.getById(envId)
return env.outgoingDependencies.stream()
})
.map { it.id }
.distinct()
.filter { !envIds.contains(it) }
.collect(Collectors.toList())
}
final customFieldManager = ComponentAccessor.customFieldManager
final issue = event.issue
def triggerCustomField = customFieldManager.getCustomFieldObjects(issue).findByName(bookedEnvironmentsFieldName)
assert triggerCustomField: "Could not find custom field with name $bookedEnvironmentsFieldName"
def bookedEnvironments = issue.getCustomFieldValue(triggerCustomField) as List
def bookedEnvironmentIds = bookedEnvironments.collect { it.id }
def dependencyIds = getDependencyIds(bookedEnvironmentIds, golive)
def environmentField = golive.environmentFields.getByName(issue, unbookedDependenciesFieldName)
assert environmentField: "Could not find custom field with name $unbookedDependenciesFieldName"
environmentField.setValue(*dependencyIds)
In order to view conflicts and dependencies while creating or editing a booking request, check this page: Conflict Checker