Hey there,
i am importing workflows via my own scriptrunner restendpoints (including xml-parsing, statusmapping etc.) programatically into an jira instance.
So far works like a charm. Problem is the visual workflow designer displays all the status and transitions nearly unreadable under each other.
I was wondering if i could somehow programatically format them.
I came across the fact that the jira default workflow (atlassian-jira/WEB-INF/classes/jira-workflow.xml) is formatted well, but that there are no styling information in the xml file. Because of that i searched the whole atlassian-jira sources, but could not find anything that does that formatting.
If anyone knows how-/where it´s done, please share.
If you have the JIRA Sources (I'm currently working with atlassian-jira-software-7.6.1-source), have a look at the following files:
They are mapping a JSON layout file on a XML workflow file...
If I will manage to get the JSON for an existing workflow, I will let you know.
So, here we go:
/**
* Create a workflow based on an exported workflow XML file.
*
* You can provide a layout file in layout format v5 with the following pattern:
* - my-workflow.xml (workflow XML file)
* - my-workflow-format.json (workflow JSON format file)
*
* @param name the workflow name
* @param description the workflow description
* @param pathXml the path to the workflow xml file
* @return the created workflow
*/
@Nullable
public JiraWorkflow createWorkflowFromXML(
@Nonnull final String name,
@Nonnull final String description,
@Nullable final String pathXml) {
if (pathXml == null || pathXml.isEmpty() || !pathXml.endsWith(".xml")) {
return null;
}
final String xml = readFile(pathXml);
if (xml == null) {
return null;
}
final String layoutKey = DigestUtils.md5Hex(name);
final String pathFormatJson = pathXml.replace(".xml", "-format.json");
final String formatJson = readFile(pathFormatJson);
try {
final WorkflowDescriptor descriptor = WorkflowUtil.convertXMLtoWorkflowDescriptor(xml);
final ConfigurableJiraWorkflow workflow = new ConfigurableJiraWorkflow(name, descriptor, workflowManager);
workflow.setDescription(description);
workflowManager.createWorkflow(authenticationContext.getLoggedInUser(), workflow);
eventPublisher.publish(new WorkflowImportedFromXmlEvent(workflow));
if (formatJson != null) {
final Map<String, Object> entryFields = ImmutableMap.of(
"entityName", "com.atlassian.jira.plugins.jira-workflow-designer",
"entityId", 1,
"propertyKey", "jira.workflow.layout.v5:" + layoutKey,
"type", 6);
final Long layoutId = ofBizDelegator.createValue("OSPropertyEntry", entryFields).getLong("id");
final Map<String, Object> textFields = ImmutableMap.of(
"id", layoutId,
"value", formatJson);
ofBizDelegator.createValue("OSPropertyText", textFields);
}
return workflow;
} catch (FactoryException e) {
String message = "Error parsing workflow XML: " + e.getMessage();
log.error(message, e);
} catch (WorkflowException e) {
String message = "Error saving workflow: " + e.getMessage();
log.error(message, e);
}
return null;
}
/**
* Find the layout for a designed workflow.
*
* This json layout file can be used to format a workflow that is exported as XML
*
* @param name the workflow name
* @return the json layout
*/
@Nullable
public String getWorkflowFormatJson(
@Nonnull final String name) {
String layoutKey = DigestUtils.md5Hex(name);
Map<String, String> filter = ImmutableMap.of(
"entityName", "com.atlassian.jira.plugins.jira-workflow-designer",
"propertyKey", "jira.workflow.layout.v5:" + layoutKey);
Optional<Long> layoutId = ofBizDelegator.findByLike("OSPropertyEntry", filter).stream()
.map(gv -> gv.getLong("id"))
.findFirst();
if (layoutId.isPresent()) {
GenericValue osPropertyText = ofBizDelegator.findById("OSPropertyText", layoutId.get());
if (osPropertyText != null) {
return (String) osPropertyText.get("value");
}
}
return null;
}
@Nullable
private String readFile(String filename) {
InputStream stream = getClass().getClassLoader().getResourceAsStream(filename);
try {
return IOUtils.toString(stream, "utf-8");
} catch (IOException e) {
log.error("Could not read file" + filename, e);
} finally {
IOUtils.closeQuietly(stream);
}
return null;
}
Note that replaced some custom stuff and did not test the code again. Also note that there are different format versions for the workflows and this code currently only works with version v5.
Cheers
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
That's handy!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
What is the eventPublisher variable that you are using?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I was able to get an event publisher by doing the following
import com.atlassian.sal.api.component.ComponentLocator
import com.atlassian.event.api.EventPublisher
EventPublisher eventPublisher = ComponentLocator.getComponent(EventPublisher)
eventPublisher.publish(new WorkflowImportedFromXmlEvent(workflow))
Using that I was able to create the workflow successfully with the formatting applied
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
I've never seen a way to format the workflow diagram programmatically
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.