The slippery slope of scripting
At Blended Perspectives, we frequently see scripting capabilities added to Jira, Confluence, and Bitbucket. While in Confluence and Bitbucket the extent of what is possible to do with scripting is limited, in the case of Jira, scripting provides administrators and Jira developers with unlimited access to their environment. Scripting in Jira enables direct access to the Jira Java API, releasing the potential to create complete business solutions inside Jira. Hence the sword of Damocles. Legend has it that Dionysius, a Greek King offered to switch places with Damocles, an obsequious courtier for one day so that Damocles could taste good fortune firsthand. Damocles quickly and eagerly accepted the king’s proposal. He sat down in the king’s throne surrounded by every luxury, but Dionysius arranged that a huge sword should hang above the throne, held by only by a single hair of a horse’s tail. Damocles realized that this was a responsibility he really didn’t want, understanding that with great fortune and power comes also great danger. So it is with scripting.
In the beginning, it was only the ScriptRunner add-on providing scripting features. Nowadays many other add-ons, such as Jira Misc Workflow Extensions, JSU – Suite Utilities for Jira, Jira Misc Custom Fields, and Insight Discovery, have jumped onto the scripting wagon. Since we’re an independent Atlassian partner, with no vested interests in selling add-ons, we take a purely independent view of the pros and cons of these products.
In most cases the features such add-ons provide are so extensive that even using the word “script” is misleading. It may give the impression of something enabling minor “scripts”, innocent pieces of code that perform simple automation actions, with no major consequences. The fact is, we can use scripting to access Jira’s internal structures, defining full new class hierarchies to develop complex implementations that fulfill any business requirements. Unfortunately, as is the case with any other powerful tool, incorrect usage can lead to dire consequences, as scripting also allows us to perform quite invasive and very damaging actions to the system. So, all the power released by those add-ons are way beyond the usual definition of what “script” suggests.
There may be moments in which scripting saves time, but we believe it should be used very judiciously. In this article, we discuss in detail the issues with scripting, alternative approaches and finally what to do about it if you are concerned about whether you have a ticking “script bomb”.
Extending Jira applications
As mentioned in the documentation, Jira is very flexible and has a number of extension points where Jira’s data can be queried or its functionality extended. Atlassian products are built on the premise that companies can extend them. The base platform is slim, which has the clear benefit in that you are not paying for things most people do not need.
The most basic way Jira extensions are implemented is by changes in the configuration, such as defining new workflows, custom fields, and screens. A powerful scheme system allows us to tweak Jira’s out of the box offering into a more customized environment.
Add-ons are one step up in the ladder of Jira customization. Buying add-ons in the marketplace is a straightforward way to add new functionalities. Some of them provide their own user interface, while others enable new features that can be incorporated in workflow transitions or provide new types of special custom fields. In-house add-on development is another way to extend Jira, with the added value that we do not need to pay for add-ons and we can even sell the add-ons we develop in the Atlassian Marketplace.
Scripting falls right in the middle of these two last options. The premise is we acquire an add-on that will allow us to use the full power of the Jira API while being free of the hassle of dealing with the add-on development process. As the potentialities of the Java API are infinite, they are usually sold with the promise of being the one tool to rule them all. However, building any functionality is a serious undertaking. It takes focused effort to put into code an idea, and it cannot be taken lightly either, as there are costs, skills, and dedication for maintenance required.
“Just one more thing”
Starting simple is straightforward, perhaps it is just to automatically add a task and a set of subtasks. Happy times, a bit of “code glue” … now you have eliminated a tiresome set of clicks. If you assess the possibilities of the Jira Java API you’ll realize it’s vast. Your possibilities are endless! Customers are typically immediately gratified and the service provider has delivered.
This can play out in a multitude of ways. In some organizations, business visionaries push for more. Sometime later, more scripts arrive. Months later, customers return, asking for more. Your code glue has expanded. It interfaces to other glue. You need to find a way to document. You are no longer an administrator, but a programmer, architect/designer and product manager as well.
Organize in Standard Ways
Extending a distributed system such as Jira requires sprinkling content across the various elements (workflows, behaviors, event listeners, escalation services, etc). Atlassian has been providing programmers with a structure for this for at least 10 years. In turn, the standards are built on Java, with solid guidelines that have been around another decade or so. Those standards and guidelines allow for Performance Testing, for Debugging, Documentation, and Automation. Aswell for rigor around builds.
The Jira user interface does not have a simple way to control all scripts currently in the system. ScriptRunner, it’s later versions provide a Script Registry feature that helps in locating the scripts. However, this feature may fail in large instances or when too many scripts are in use. Even using the Script Registry feature provided by ScriptRunner, the code is still dispersed across multiple structures, which makes it difficult to keep track of the script in production. Having multiple developers creating the scripts does not help in this direction. For the rest of the add-ons providing scripting features, the case is even worse. For example, when using Jira Misc Custom Fields the scripts are located in the description of custom fields, not at all an intuitive place to store a piece of code.
Once scripts are in production when they fail they do not usually show any warnings of something going wrong in the user interface. Most of the errors happen silently and are only detected in the logs or when inconsistencies in the data reveal the problem that the scripts are not working as expected. The Jira logs, being in a production server, are not easily accessible by non-administrator users.
In most organizations, the role of Jira Administrator does not necessarily include development skills. Jira Administrators are faced with evaluating scripts where they may not have a full understanding, even more, a problem when not only Java/Groovy skills are required but also a good understanding of the Jira Java API. It is not fair to expect a Jira Administrator to validate a piece of code that is meant for production. This should be the result of a peer review and approval process as in any other software development activity.
Potentially damaging actions
While using the Jira REST API is relatively safe, the Java API provides full access to many areas where an accidental or intentional wrongful use can cause considerable damage. Some of the actions that can cause damage are:
- Perform issue actions (create, update, delete) bypassing Jira permissions.
- Create and update issue links, breaking consistency.
- Execute JQL ignoring limits on the number of results (performance impact).
- Directly set custom field values breaking consistency, ignoring the issue history, and affecting the Jira index.
- Bulk create, update, and delete user accounts.
- Execute actions impersonating another user.
Any of those actions can be done in a large number of items, for instance deleting all issues at once by accident or deactivating all user accounts in a wrong bulk update.
Code maintenance problems
The use of the ScriptRunner puts Jira administrators in the same field of add-on developers, so they are forced to use the same procedures and safeguards used in any other software development project. Jira add-ons developers are supposed to update the code of their add-ons whenever a new version of Jira is released, following changes in the Java API. Atlassian annotates deprecated classes and methods to signal they are going away in future releases and to encourage developers to change to the newly available options. In case those deprecations are ignored, eventually, the code will fail with future Jira upgrades. Atlassian also announces upcoming changes at https://developer.atlassian.com/jiradev/latest-updates/jira-eap-releases, where multiple “Preparing for Jira 7.x” can be found with detailed information of those changes.
ScriptRunner developers take care of updating their code and releasing the new version compatible with the new Jira version, so any built-in action the ScriptRunner provides should be ok. The problems are in the custom code that may break in the new version of Jira due to changes in the Java API. It is very common to find code in production using deprecated classes, which is a risk for the stability of the system.
Considering most organizations have a strict procedure for review and approval before installing a new add-on; it makes sense to have a similar procedure in place for scripts added to the system. In the case of new add-ons, they are usually widely tested by the developers and issues reported by the Atlassian community, something that does not happen with custom scripts developed in-house, making it more important still to have a proper review and approval in place.
Code re-usability challenges
ScriptRunner incorporates script into Jira in two ways: inline script and filesystem references. Inline scripts are defined in the web GUI, pasting the code we hopefully developed and tested in a proper IDE or, unfortunately, a very frequent case, pasting the code we found on the internet.
When using inline scripts, we cannot import utility classes defined in other scripts. In this case, the code is stored in the Jira database, either in Active Object tables or inside the workflow definition. This is a major disadvantage of this method that causes a considerable amount of code duplication. The maintenance of the code is also affected because when a change in a duplicated utility class or function is required it needs to be changed in all the scripts where it was duplicated. This change is done using the Jira GUI, mostly in the workflow editor, which is time-consuming and prone to errors.
Using scripts in the file system allows us to define utility classes and import them into our code, with evident advantages for maintenance, reusability, and consistency of the code. However there is a downside on this method; it requires direct access to the filesystem, which may be a blocker in many organizations for security reasons. On the other hand, this may be an advantage from the point of view of security and governance, where only approved code gets into production following defined channels. The code in the file system is not visible from the Jira GUI, only a reference to the location of the script. Keeping the code in a git repository and implementing the procedures to have traceability of the changes can mitigate this problem. Jira access to the administration interface is not granular enough to prevent Jira administrator access to the scripts. Keeping the scripts in the file system allows the code to remain secure and permission to be set in the Bitbucket projects and repositories to allow only authorized access to the code.
Deployment and limitation of Jira UI for simultaneous changes
Scripts in multiple places may depend on each other. Using the GUI to insert the script online makes it difficult to update multiple scripts at once. The very process of updating the structures containing the workflows is different. Some changes can be deployed and applied later on, some other changes are immediate. Some examples of this problem are:
- Workflow changes are applied on publishing the workflow, in some cases, this requires the creation of a workflow copy and apply a new workflow scheme.
- Screen changes happen immediately (no save button!)
- Listeners are a global configuration, attached to projects by defining a scope, which can be dangerously broad and affect all projects at once.
- Scripts in behaviors can have a complex mapping of projects, issue types, fields and workflow transitions.
With workflows and screens, changes can be staged using schemes and re-applying the schemes to the associated projects. However, re-applying a scheme can take some time, depending on the number of issues, and during that time the project status is unstable. If one script is running while the change is already applied in some areas while not yet in other areas we can have unexpected results.
Using scripts in the file system mitigate these problems to some extent, as they allow the deployment of multiple scripts at once, ensuring they are consistent with each other and that no unstable window exists. But that consistency will be only among the scripts, it will not prevent inconsistencies with related Jira structures included in the solution being implemented. All this boils down to the need to have maintenance downtime once the complexity of the script based solution increases.
Add-on development vs ScriptRunner
A custom add-on is a more packaged product, that can be disabled at once if it causes problems. In that case, all workflow using the structures created by the add-on (conditions, validators, and workflows) will not work as expected, but that is also a problem when disabling a defective ScriptRunner script. A Jira add-on is not very different from any other Java development project. It can be properly documented and the long-standing best practices of software development applied, something hard to achieve using ScriptRunner, where a multitude of scripts are dispersed across many Jira configuration structures. And once you build one add-on the rest are similar, so the effort scales very well as features are added.
The debugging and troubleshooting are also improved when developing your own add-on. You will not be dealing with an intermediate party, figuring out why the code you are using is not translated by the scripting add-on into the expected result on the Jira Java API. When developing your own add-on you can use the well-documented class hierarchy of the Jira API and know exactly what to expect, with no black boxes in between. In short, you own the full process.
Java vs Groovy
Considering ScriptRunner and the rest of scripting add-ons as just groovy scripting tools is not completely accurate. When using Groovy to implement a solution we use objects and imported packages from the Jira Java API. The loose typing groovy provides and the flexibility in the syntax may be a double-edged sword, if not, of course, the sword of Damocles! Whilst it allows us to go faster and not worry about what types the objects need to have, it makes it harder to spot errors and mistakes that may be happening without warning. Once a solution becomes too complicated the complexity of management of all involved scripts increases.
In the end, we are supposedly using a scripting add-on to access the Jira Java API. But the Jira Java API is developed in Java, not in Groovy! Using Groovy will only prevent you from being able to package that code later on into a single add-on. After you have hundreds of thousands of scripts using Groovy syntax to formalize them into Java syntax is a cumbersome effort, probably bigger than the initial development. Using Groovy will only make you forever dependent of the scripting add-on. Using Java has the extra advantage that there are way more examples and documentation for Java than for Groovy all over the internet.
The lifecycle of scripting usage in many organizations shows that it starts simple, with basic scripts to fill the gaps in Jira out of the box features. However, as the possibilities of directly using the Jira java API are discovered, it becomes hard to resist the temptation to develop even more complex implementations using this approach.
Instead of developing a custom add-on from the outset, the same resources are invested in creating hundreds or thousands of scripts with the corresponding maintenance and administration ordeal. Very soon there are too many scripts to manage.
Based on the size of your organization the complexity of the solutions can be estimated. When we know from the beginning that a simple script will not be enough then an in-house add-on development makes more sense. If we are going to run into deep waters anyway then using a scripting add-on will probably cause more harm than benefits. Add-on development may seem complex, however, we won’t escape complexity by using scripting. On the contrary, we will create more complexity.
Finally, if we know the solution we need is fairly simple, then there may very well be a way to do such things without scripting. So if you are suspicious about the amount of code glue you may have or concerned about the impact on the stability of your system call us up for a no-cost assessment of your Jira installation. We can help, contact us today!
– – – Blended Perspectives is Canada’s largest Atlassian Solution Partner providing Consulting, Managed Hosting, Installation, Data Migration, Performance Tuning and Certified Atlassian training. We have deep expertise in all Atlassian products with certified experts covering the full lifecycle for SDLC, Service Desk and broader business application support. Founded in 2007 after years of experience serving clients in Canada, Europe, USA and Australia; Blended Perspectives’ mission is to enable Corporations to unleash the power of their teams and to leverage the true potential of their business via enhanced tools and processes.