Or “I don’t have TIME to understand Maven; I’ve got work to do!”
A big part of developing a plugin is seeing it work inside the base product. For Jira plugins, this is accomplished using the maven-jira-plugin. There are two options for getting your plugin to run inside the host application: adding it as a bundledArtifact, or as a pluginArtifact. If you examine the configuration of an established plugin, like GreenHopper or any of Jira’s bundled plugins, you might see multiple plugins configured, using either method. For example, making use of the jira-func-test-plugin or the jira-testkit-plugin to assist with writing integration tests, or the atlassian-qunit-plugin to run QUnit tests.
Why are there two ways? I always get confused by this, so I looked up the documentation. It quite clearly states:
Specifies other Atlassian plugins that your plugin depends on to work properly. These plugin artifacts will be installed into the product along with your plugin.
Specifies other Atlassian plugins that your plugin depends on to work properly. These plugin artifacts will be treated as bundled by the product, meaning they can be disabled but not removed. The product will always make a bundled plugin available at startup, even if it was removed previously. By contrast, plugin artifacts can be removed after installation at any time, and they will stay gone until they are manually reinstalled.
Ask yourself this question — is the plugin you are developing always going to be a bundled plugin i.e. not removable by administrators? If so, add it as a bundledArtifact. Simple.
But does it really make a difference? This configuration is purely for development purposes. What does it matter if your plugin is treated as bundled? As I found out today, it matters if you plan on doing any sort of integration testing around your plugin’s interactions with Atlassian’s Universal Plugin Manager (UPM).
I wrote a WebDriver test that re-used UPM’s PageObject library to drive licensing changes. In my development environment, everything was working just fine. But when the test ran in Bamboo, it failed. Initially, I thought the failure was due to a “flaky” PageObject. We call PageObjects “flaky” if they bind correctly to the DOM in a low-latency environment, like your workstation, but fail to bind due to timeouts or StaleElementExceptions in an environment where there is more latency, such as a Remote Agent. However, I realised that UPM’s PageObjects weren’t flaky. When I re-ran my test locally in the IDE, with the Slo-mo Filter enabled (which you can get by using the jira-func-test-plugin, by the way), it still passed.
The golden rule of test failure debugging is “try it from the command line”. We introduced a profile in our integration test POM that allows us to run a single test via mvn verify. So I ran the command and eagerly awaited the failure to appear before me. And sure enough, it did. The problem arose when my test attempted to “expand” the plugin’s details on the UPM page, to extract some license information. The PageObject couldn’t perform the task, because there was nothing to expand – the plugin was hidden away in the “System Plugins” section of the page.
Flipping back to the POM file for our integration test module, I quickly realised why this was the case – we had declared that the plugin should be installed as a bundled artifact instead of a plugin artifact. Moving the configuration across to the other XML block fixed the problem instantly. But it’s easy to see how we got in the predicament in the first place – both ways of installing a plugin were being used for different artifacts, and we probably just added it to the one that had more blocks in it.
Now, I will never forget the difference between the two. And hopefully, you won’t either!