Blog Archives

Confluence CLI for bulk actions like deleting or publishing pages

Today I needed to remove a number of pages from our Confluence documentation site. To do it via the web interface would have taken a long time. Instead, I used Bob Swift’s Confluence CLI tool. It is simple to use and powerful in capability, and you can run it from your own computer. Ideal for bulk deletion of pages and other mass documentation admin tasks!

The pages that I wanted to remove were a set of transcripts from our developer IRC chat. We had an automated process that generated the transcripts and added them to Confluence regularly for a certain period. There was therefore quite a large number of them. Then we stopped generating the transcripts, and those that were on the wiki became out of date and irrelevant. I needed to remove the parent page that introduced the transcripts, and all the child pages that represented individual IRC sessions. Enter the CLI.

My environment

I’m using the following setup:

  • My desktop PC is running Windows 7, and I executed the CLI commands from a command window on this machine.
  • The Confluence server is running Confluence 3.5.
  • I used version 2.2.0 of the CLI.

Note that you need Confluence administrator permissions to use the CLI.

Using the Confluence CLI

1. Make sure that the remote API is enabled on your Confluence site. Go to Confluence admin > General Configuration and make sure the following option is enabled: Remote API (XML-RPC & SOAP).

2. At this point, I recommend that you change your password on Confluence, because soon you will enter the password to a text file on your computer, where it will be visible for anyone to see unless you encrypt the file.

3. Download the CLI distribution from the Atlassian Plugin Exchange: https://plugins.atlassian.com/plugin/details/284.

4. Unzip the distribution into a directory on your computer. This will give you a directory called confluence-cli-x.x.x, where “x.x.x” is the version of the CLI that you downloaded. For example, mine is called confluence-cli-2.2.0.

5. Open a text editor and edit the batch file called confluence.bat (on Windows) or confluence.sh (on a Mac) which you will find in the above directory. Now you will specify the address of your Confluence server, and the username and password that the CLI will use to access that server.

My computer is running Windows 7. This is the content of the confluence.bat file before I did anything to it:

@echo off

rem remember the directory path to this bat file

set dirPath=%~dp0

rem need to reverse windows names to posix names by changing \ to /

set dirPath=%dirPath:\=/%

rem remove blank at end of string

set dirPath=%dirPath:~0,-1%

rem – Customize for your installation, for instance you might want to add default parameters like the following:

rem java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar –server http://my-server –user automation –password automation %*

java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar %*

rem Exit with the correct error level.

EXIT /B %ERRORLEVEL%

I commented out this line:

rem java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar %*

And added this line:

java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar –server https://my.confluence.com –user myname –password secret %*

Hehe, my password isn’t actually “secret”. You will need to substitute the correct values for https://my.confluence.com and myname too.

This is the content after I have added the details of the server and user:

@echo off

rem remember the directory path to this bat file

set dirPath=%~dp0

rem need to reverse windows names to posix names by changing \ to /

set dirPath=%dirPath:\=/%

rem remove blank at end of string

set dirPath=%dirPath:~0,-1%

rem – Customize for your installation, for instance you might want to add default parameters like the following:

rem java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar –server http://my-server –user automation –password automation %*

rem java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar %*

java -jar “%dirPath%”/lib/confluence-cli-2.2.0.jar –server https://my.confluence.com –user myname –password secret %*

rem Exit with the correct error level.

EXIT /B %ERRORLEVEL%

6. Save the batch file.

7. Open a command window and go to the directory (cd) where you unzipped the CLI distribution. For example: C:\>cd confluence-cli-2.2.0

8. Execute the batch file (see examples below), passing the relevant parameters to perform the action you need done. The CLI documentation lists all the parameters available and gives examples of the actions you can perform.

As mentioned at the beginning of this post, I wanted to delete a specific page and all its child pages. The pages were on our production documentation site. But first, being a cautious soul, I tested the CLI on a staging server, and instructed it to delete just one page. The page name is “atlassiandev_log-2010-03-15”.

This is the command I ran. (Remember that my batch file is configured to address the correct server with a valid username and password.)

confluence –action removePage –space “DOCS” –title “atlassiandev_log-2010-03-15”

This was the result:

C:\Atlassian\confluence-cli-2.2.0>confluence –action removePage –space “DOCS” –title “atlassiandev_log-2010-03-15”

Removed page ‘atlassiandev_log-2010-03-15’ from space ‘DOCS’.

C:\Atlassian\confluence-cli-2.2.0>

To make ultra sure, I went to my Confluence site and had a look at the trash bin for the space. (Go to Space Admin > Trash.) Yep, just the one page, and it was the one I expected. (I had craftily purged the trash bin before running the CLI command, so that I knew exactly what should be in there.)

Next I was ready to delete the parent page and all its child pages. In fact, this command will remove all descendents of the parent page, including its children and their children, and so on. The parent page is “IRC Chat Transcripts”.

confluence –action removePage –space “DOCS” –title “IRC Chat Transcripts” –descendents

This was the result:

C:\Atlassian\confluence-cli-2.2.0>confluence –action removePage –space “DOCS” –title “IRC Chat Transcripts” –descendents

Removed page ‘IRC Chat Transcripts’ from space ‘DOCS’.

C:\Atlassian\confluence-cli-2.2.0>

Hmm. Interesting. The message mentioned only the title of the parent page. I hopped back to my online view of the space’s trash bin, and all the expected pages had been deleted. Excellent!

Now I was ready to try it on the production server. I adjusted the server URL and my password in the batch file, then ran the same command as above. Yaayyy! It worked.

9. When all is done, change your password on Confluence again.

10. Have a chocolate.

Other scenarios

My requirement was fairly simple, but typical of the mass-processing a document administrator may need to do. The CLI documentation includes some useful examples and a list of all the available actions and parameters.

A scenario that springs to mind is publishing and removing pages on release date. In the scenario that I described above, all I needed was one line to remove a page and its descendents. To perform a series of actions, you can set up a number of lines in the batch file and then run it to do all the processing at one time. This may be very useful on release date. For example, you may want to delete a number of individual pages and publish other pages by removing page restrictions (permissions). Add the commands to the batch file during the documentation development cycle, then run the file on release date.

Thank you Bob

Thank you to Bob Swift for the awesome Confluence CLI! And thanks to Scott for pointing it out to me.

Making the include macro’s content appear in the Confluence search results

Confluence wiki provides two macros that you can use to embed content from one page onto another page: {include} and {excerpt-include}. Technical writers find these macros very handy for content reuse. Write the words once, put them somewhere sensible, and then reuse them in a number of different places. Confluence will dynamically copying the content into the page at display time. The trouble is that the Confluence search results pick up the content where it’s originally written, but not where it’s displayed. Or that’s what I thought until now!

Today I learned that you can make the content of the {include} and {excerpt-include} macros appear in the search results for the page where that content is displayed. Magic!

It would be nice if Confluence itself would offer the option to include the macro contents in the search results. If you agree, please comment on or vote for the improvement request: CONF-19054

In the meantime, there’s a workaround. A big thank you to Emily Johnson and David Peterson for finding and sharing this solution, and to Bob Swift for the Cache plugin for Confluence!

The solution in a nutshell

Install the Cache plugin for Confluence. Then wrap your include macros with the {cache} macro, using the “index=true” parameter to make the content of the include macros searchable.

{cache:index=true}
{include:mySPACEKEY:My page name}
{cache}

More about the Cache plugin

Bob Swift develops and maintains the Cache plugin for Confluence. He also provides the support for the plugin.

What does the plugin do? It’s principal function is to allow you to cache part of the page, especially if the content is derived from an external source. This could significantly improve the loading time of the page. You can configure the length of time that Confluence waits before updating the cached content.

For our purposes, one particular option in the Cache plugin is useful: the “index=true” parameter. There are many macros that you can use to display external content on a Confluence page. The {include} and {excerpt-include} macros are two examples. Even though the content appears on a Confluence page, the content will not be included in the Confluence search results, since it is not included in the wiki markup of the page and is therefore not included in the search index. The {cache} macro with parameter “index=true” will ensure that the content is indexed and therefore appears in the search results. See the plugin documentation.

Installing the Cache plugin

The easiest way to install the plugin is using the Confluence plugin manager:

  1. Go to your Confluence Administration Console by clicking “Browse” > “Confluence Admin”.
  2. Click “Plugins” in the left-hand menu.
  3. Click the “Install” tab.
  4. Select “All Available” in the “Plugins to show” dropdown list.
  5. Find the “Cache Plugin” in the list of plugins and click the plugin name. A panel will open up, showing the plugin description.
  6. Click “Install Now”.

If for some reason you can’t use the Confluence plugin manager, then you can download the plugin and install it manually:

  1. Go to the Cache plugin’s page on the Atlassian Plugin Exchange.
  2. Download the plugin JAR file. It has a name something like “cache-plugin-4.1.0.jar”. (The version number will probably change over time.) Save the JAR file on your local computer.
  3. Go to your Confluence Administration Console.
  4. Click “Plugins” in the left-hand menu.
  5. Click the “Install” tab.
  6. Click “Upload Plugin”.
  7. Browse to find the JAR file that you saved, and then click “Upload” to upload it into Confluence.

Let’s try it out

Let’s see what happens when we search for the terms “chocolate” and “cheese”, where those terms are included via the include macros. First we’ll do it without the {cache} macro, then we’ll add the {cache} macro and try the search again.

Example of search results without the Cache macro

First I created some pages.

1. A page called “Favourite food”

This page is in the “CHUNKS” space. The entire content of this page will be embedded into another page later.

Wiki markup:

{cheese}
I like chocolate too.

Displayed content:

I like cheese!

I like chocolate too.

The {cheese} macro is a bit of fun. It’s a real macro, shipped with Confluence. All it does is generate the words “I like cheese!” 🙂

2. A page called “Partial content reuse”:

This page is in the “Demonstration (DS)” space.  The excerpt defined on this page will be embedded into another page later.

Wiki markup:

This page has an excerpt defined on it.
{excerpt}I'm partial to chocolate.{excerpt}

Displayed content:

This page has an excerpt defined on it.

I’m partial to chocolate.

3. A page called “Include food page from another space”:

This page is in the “Demonstration (DS)” space.  This page will include the entire content from the “Favourite food” page (page 1).

Wiki markup:

*Tell me about your favourite foods.*
{include:CHUNKS:Favourite food}

Displayed content:

Tell me about your favourite foods.

I like cheese!

I like chocolate too.

4. A page called “Include excerpt from another page”:

This page is in the “Demonstration (DS)” space.  This page will include just the excerpt defined on another page (page 2).

Wiki markup:

*What do you really really like?*
{excerpt-include:Partial content reuse|nopanel=true}

Displayed content:

What do you really really like?

I’m partial to chocolate.

5. A page called “This page has chocolate in the title”:

I created this page just to test that the search is working.

Searching for “chocolate”:

I’ve restricted the search to the “Demonstration Space”. We have not yet added the {cache} macro to any of our pages. As expected, the Confluence search shows only those pages that include the word “chocolate” in the title, page content, attachments or labels. It does not pick up any pages where the word “chocolate” is displayed as a result of an include macro.

Making the include macro's content appear the Confluence search results

Search showing "chocolate" only when on page

Searching for “cheese”:

Similarly, the search does not pick up the word “cheese” at all.

Making the include macro's content appear the Confluence search results

Search does not pick up the word "cheese" at all

Example of search results after adding the Cache macro

Next I added the {cache} macro to the two pages that contain include macros. Let the magic begin.

Adding the {cache} macro to the page called “Include food page from another space”:

Wiki markup:

*Tell me about your favourite foods.*
{cache:index=true}
{include:CHUNKS:Favourite food}
{cache}

The displayed content of the page remains the same as before.

Adding the {cache} macro to the page called “Include excerpt from another page”:

Wiki markup:

*What do you really really like?*
{cache:index=true}
{excerpt-include:Partial content reuse|nopanel=true}
{cache}

Again, the displayed content of the page is unchanged.

Now let’s try searching for “chocolate”:

The Confluence search results now show the pages where the word “chocolate” is displayed as a result of an include macro.

Making the include macro's content appear the Confluence search results

The Confluence search picks up "chocolate" from the content of the include macros

Searching for “cheese”:

Yaayyy, the search picks up the word “cheese” too.

Making the include macro's content appear the Confluence search results

The Confluence search picks up "cheese" from the {cheese} macro inside an {include} macro

Doubly magic

That’s right! The Confluence search picks up the word “cheese” that was generated by the {cheese} macro embedded inside an {include} macro!

Update on 18 May 2011: I’ve just heard that the use of the {cache} macro means that the inclusion will ignore any page restrictions that you may have added to the included page. I haven’t tested this myself, and it’s unlikely that you’d want to include a page that has restrictions. But there are some applicable use cases, so please be aware of this possibility.

%d bloggers like this: