Skip to main content
How to create a Confluence page from a Jira post function
Share on socials
A lightbulb
Tiffany Wortham
Tiffany Wortham
17th November, 2020
Data center icon
Server icon

How to create a Confluence page from a Jira post function

Want to learn how to create a Confluence page from a Jira workflow post function? Check out this walkthrough and free script.
During a recent webinar, a ScriptRunner user asked us this question:
How do I create a Confluence page from a Jira workflow post function with many multiline text Jira fields which have HTML and XML tags in their content? 
Below you will find guidance on how to achieve this, including the video demo and the Groovy code I used in the demo. Feel free to download it and use it for your own needs.
To illustrate the example, I created a Jira issue which has a custom field “Ideas to Increase Sales” which contains HTML, and a custom field “Store Locations” which contains XML.
A screenshot of a Jira ticket about pizza sales
I want to display HTML and data extracted from the XML in a Confluence page whenever the workflow transition to “Done” occurs. In order to achieve this, I’ll create a Custom Script Post Function on the “Done” workflow transition with the following script.
1package examples
3import com.atlassian.applinks.api.ApplicationLink
4import com.atlassian.applinks.api.ApplicationLinkService
5import com.atlassian.applinks.api.application.confluence.ConfluenceApplicationType
6import com.atlassian.jira.component.ComponentAccessor
7import com.atlassian.jira.issue.Issue
8import com.atlassian.sal.api.component.ComponentLocator
13import groovy.json.JsonBuilder
14import groovy.json.JsonSlurper
15import org.jsoup.Jsoup
18 * Retrieve the primary confluence application link
19 * @return confluence app link
20 */
21def getPrimaryConfluenceLink() {
22    def applicationLinkService = ComponentLocator.getComponent(ApplicationLinkService.class)
23    final ApplicationLink conflLink = applicationLinkService.getPrimaryApplicationLink(ConfluenceApplicationType.class)
24    conflLink
27// the issue provided to us in the binding
28Issue issue = issue
30def confluenceLink = getPrimaryConfluenceLink()
31assert confluenceLink // must have a working app link set up
33def authenticatedRequestFactory = confluenceLink.createImpersonatingAuthenticatedRequestFactory()
35// set the page title - this should be unique in the space or page creation will fail
36def pageTitle = issue.key + " Sales Improvement Plan"
37def htmlCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_10201")
38def xmlCustomField = ComponentAccessor.getCustomFieldManager().getCustomFieldObject("customfield_10202")
39def xml = Jsoup.parse(issue.getCustomFieldValue(xmlCustomField).toString())
40def locations = xml.getElementsByTag("locations").collect {
41    it.text()
42}.join(" ")
43// since my field renders html with the html macro, I need to strip it out before adding my html to the page
44def parsedHtmlFieldValue = issue.getCustomFieldValue(htmlCustomField).toString().replaceAll("\\{html}", '')
46def pageBody = """<p> ${issue.description} </p>
49<p> Locations: ${locations} </p>
51<p> Use this page to discuss our sales improvement plan </p>
54def params = [
55    type : "page",
56    title: pageTitle,
57    space: [
58        key: "SAL" // set the space key - or calculate it from the project or something
59    ],
60    body : [
61        storage: [
62            value         : pageBody,
63            representation: "storage"
64        ],
65    ],
69    .createRequest(Request.MethodType.POST, "rest/api/content")
70    .addHeader("Content-Type", "application/json")
71    .setRequestBody(new JsonBuilder(params).toString())
72    .execute(new ResponseHandler<Response>() {
73        @Override
74        void handle(Response response) throws ResponseException {
75            if (response.statusCode != HttpURLConnection.HTTP_OK) {
76                throw new Exception(response.getResponseBodyAsString())
77            } else {
78                def webUrl = new JsonSlurper().parseText(response.responseBodyAsString)["_links"]["webui"]
79            }
80        }
81    })
Please note that in this example I’m using app links, as this is the most universal way to achieve something like this. However, the more complex your use case is, you may want to consider using ScriptRunner’s remote control feature. Hope that helps!

Step-by-step guide

If you would like to watch a step-by-step video demo of what I described above, check out this video.

Get a 30 day free trial

ScriptRunner for Confluence is an amazingly versatile tool that lets you customise, extend and automate Confluence as much as you need. Explore what you can achieve!