Project automation for Confluence plugins

A while ago our team was working at customizing Confluence for one of our customers. I’d like to share a few tips on how to automate Confluence plugin deployments.

(It should not be necessary to point out that all repetitive operations should be automated. Read all about it in The Pragmatic Programmer and Pragmatic Project Automation.)

Our automation was mostly Bash-based. I think it’s important to write expressive code in any language. When you’re scripting with Bash, the main way to be expressive is to use functions. We keep our scripts in a $(project)/script directory, so that you can invoke them with a minimum of keystrokes. The script we use for installing our plugin on localhost is:

 1  confluence_url=http://localhost:8080        
 2  confluence_install=~/confluence-2.9.2-std
 3  admin_password=admin
 5  source src/main/bash/ || exit 1
 7  quietmvn package || exit 1
 8  plugin_jar=$(ls target/ourplugin-*.jar)
 9  [ -f "$plugin_jar" ] || (echo "no plugin generated"; exit 1)
10  confluence_login 
11  confluence_uninstall_plugin
12  confluence_install_plugin

Lines 1-3 set up some variables for future use.

Line 5 loads our library of functions in the current shell process. The “|| exit 1” bit means “if this command fails, then quit immediately”.

The “quietmvn” in line 7 invokes maven with a filter that hides useless warnings. We found that Confluence plugin builds generate a lot of warnings due to dependencies on Atlassian packages that have poorly written “pom.xml” files. This (according to Atlassian) is harmless; but then again, useless warnings are harmful, so we filter them out.

Getting back to line 7, this builds the jar package of our Confluence plugin.

Line 8 defines a $plugin_jar variable with the relative pathname of the plugin jar. The $(foobar) bit is a Bash command that executes the foobar command and returns the text output generated by the command.

Line 9 says “if the plugin file does not exist, then exit with a meaningful error message.” In Bash, the command [ -f foobar ] tests if file “foobar” exists.

Line 10 to 12 are the interesting bit. They invoke three Bash functions that do what their name implies. They depend on the variables we set up in lines 1-3. This allows us to use the same functions for both local and production deployments. And here is our precious Bash library:

 1  cookie_jar=/tmp/confluence-cookies.txt
 2  curl="curl --cookie-jar $cookie_jar --cookie $cookie_jar --output /tmp/curl-output.html"
 4  function confluence_login() {
 5    echo "login to confluence"
 6    $curl -s -S -d os_username=admin -d os_password=$admin_password "$confluence_url/login.action"
 7  }
 9  function confluence_uninstall_plugin() {
10    echo "uninstall plugin"
11    $curl -s -S $confluence_url'/admin/plugins.action?mode=uninstall&pluginKey=ourpluginkey'
12  }
14  function confluence_install_plugin() {
15    echo "reinstall plugin ($plugin_jar)"
16    if [ \! -f $plugin_jar ]; then
17      echo "ERROR: $plugin_jar not found"
18      exit 1
19    fi
20    $curl -F file_0=@$plugin_jar\;type=application/octet-stream $confluence_url/admin/uploadplugin.action
21  }
23  function quietmvn() { 
24      mvn $* | grep -v '\[WARNING\] POM.*Not a v4.0.0 POM' 
25  }

The three functions I was talking about use Curl to interact with Confluence as if our script was a web browser. This is not the way to automate installs that Atlassian recommends, which is to use Maven with some Atlassian plugins. We found that the Maven way was not as reliable as using Curl.

And this is all there is to it. It took some time to find the right way to invoke Confluence with Curl, but every minute spent was worth it. This small library of Bash commands allows you to perform installs and uninstalls of any plugin with maximum reliability. It takes away a lot of pain from Confluence plugin development.

Leave a Reply