We have a release checklist containing a number of action items to check off. We use this page every two weeks and instead of us having to manually uncheck the items I would like to automate it so when we come upon release week we have a fresh checklist to run through.
How can I make that possible via automation?
Hey @Matthew Ogrady and @Bill Sheboy - I actually recently attempted to do exactly what Matthew is asking as part of my attempt to implement Page Approvals in Confluence (sorry my Appfire friends) using Automation.
I was using action items (in Confluence they're actually called Tasks) for these approvals, and in the case where a previously approved page is edited, I wanted to clear the prior approvals.
Anyways, it turns out there is a Tasks API!
So was super-excited that I could Get tasks for the page with a Web Request like:
https://MYSITE.atlassian.net/wiki/api/v2/tasks?body-format=storage&page-id={{page.id}}
So with the unique task IDs, I figured it would be a slam dunk to simply use the Update task call for each ID, setting the status to incomplete.
UNFORTUNATELY I ran into a bug.
Even though I'm updating completely different tasks, Atlassian apparently really really doesn't like you to make Update task calls at the same time. And Automation actions annoyingly run in parallel.
So I got this error for every task except one:
{"errors":[{"status":409,"code":"CONFLICT","title":"Encountered conflict updating task with global id [979962]","detail":null}]}, {"errors":[{"status":409,"code":"CONFLICT","title":"Encountered conflict updating task with global id [979960]","detail":null}]}
I opened a support ticket for this, and it resulted in this bug being created:
CONFCLOUD-80654 - Improve Conflict Resolution for Task API in Confluence
I'd love for it to get more votes so we could do more cool stuff with Tasks like this.
Here's the portion of the rule that SHOULD clear the completed tasks (REMINDER THIS DOES NOT WORK DUE TO CONFCLOUD-80654):
I made things more complicated by myself by using Bill's trick to add an additional "filter" so that I'm only touching Tasks that contain the word "Approve".
So in "Create variable", completedApprovalsList is set to:
{{#webResponse.body.results}}{{#if(body.storage.value.match(".*(Approve).*").isNotEmpty())}}{{id}}{{^last}},{{/}}{{/}}{{/}}
And then in "For each: Smart value" the completedApproval variable is generated from this Smart value:
{{completedApprovalsList.split(",")}}
If you didn't care about that, you would simply use something like this in "For each":
{{webResponse.body.results.id}}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Darryl Lee
Did you find information if there is actually additional information stored for the tasks (necessitating use of the endpoint), or if that is all automagically based on the Confluence page contents?
Kind regards,
Bill
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey @Bill Sheboy - so this endpoint:
https://MYSITE.atlassian.net/wiki/api/v2/tasks?body-format=storage&page-id={{page.id}}
Is this API:
https://developer.atlassian.com/cloud/confluence/rest/v2/api-group-task/#api-group-task
And it returns a lot of information, but the only thing I'm concerned about is the id and status for each task in results. (Well, I'm lying, because I also look at body to see if it contains the word "Approve")
At any rate, in my particular use case, there should only be 4 tasks (approvals) per page, and so, unless other tasks were created on the page, sure, I have less than 10 tasks.
Can you send me a link to the recursive, incoming webhook trigger rule trick you're talking about? I don't have that one bookmarked. :-}
Sure, body storage could be updated, but ugh, I spent a few hours this week messing with replace to try and get an AI summary of a Jira ticket into Confluence, and it was NOT FUN.
Ah, in this case it might not be as painful because after you GET the page content, you'd put it back with the value:
{{webResponse.body.body.storage.value.replaceAll("<ac:task-status>complete<\/ac:task-status>", "<ac:task-status>incomplete<\/ac:task-status>").jsonEncode}}
HUH, that might even work in my case IF the pages that need approvals cleared don't have any other tasks. NICE!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Darryl, here is an example from Atlassian on dynamic looping for issue creation:
For the scenario you describe, there would be two rules:
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Huh. So I'm trying to wrap my head around this.
My primary "Clear Approved Tasks" rule would be able to generate a list of task IDs on a page that are complete that need to be cleared.
(Search by page-id, status=complete, and optionally filter if body contains "Approve")
So I send this data to the looping rule:
{
"value": 3,
"todelete": ["12345", "23456", "34567"]
}
So yes, I could "run" the looping rule 3 times. But what's the trick for selecting the right element? Like, would I be able to use webhookData.value as an index value for {{todelete.get(index)}}?
I keep feeling like I need a shift or pop function to grab the top or bottom of the stack of ids each iteration, and then run again. But no such function exists.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
When the rule triggers, it could parse the list and get the first item.
And when there are more to process, iterate the list to create the remainder by dropping the first one using {{^first}}{{.}}{{/}} with the iterator.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Neat! I got the recursive secondary rule working, but for some really annoying reason I can't seem to trigger the webhook from another rule. I can kick it off from a curl command just fine.
When I manually trigger my primary rule, the part where I lookup the tasks and generate the payload for the webhook call works great, but then it just fails to make the call, at least as far as the audit log for the secondary rule shows.
I've of course triple-checked the URL, secret, and headers, but am still getting this very odd error:
That Dynamic Looping article is from 2023. I wonder if it's possible that Atlassian is blocking the ability to trigger a webhook from an Automation?
Are you doing anything like this this in your production instance, @Bill Sheboy ?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
(Also in my testing, I'm only looping through THREE times, and audit logs are not showing anything about LOOP detection.)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Huh, in their Update on Incoming Webhooks Trigger for Atlassian Automation Rules they mention:
I use webhooks to chain my automation rules. Do I need to make changes to those too?
Yes. If you use the “Send web request” action in a rule, which triggers another rule containing the incoming webhook trigger, you'll need to update the endpoint used in the “Send web request” action.
So I GUESS we could infer that this is supported usage.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You have been busy trying this one! ;^)
I have not used this recursive technique in over two years (and I am not currently in a "production position" whereby to check the rule I did use).
When that update about webhooks came out, I recall I carefully read it to check for this scenario. My take: someone will need to contact Atlassian Support to ask them the specific question as to whether this incoming webhook change does / does not support triggering another (or same) webhook rule.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hah yeah, got it stuck in my head over the long weekend.
Ah, ok so Support very kindly pointed out that I had... bad JSON (extra left-brace)!
So it is working as expected now!!
It turns out that Incoming Webooks FAIL SILENTLY with a 200 OK status code even if your JSON is bad. This is a known issue:
However I am still getting this weird "Oops we ran into a problem" error with ANY of my manually triggered rules, including one I just created that does NOTHING except add "DO NOTHING" to the audit log.
Very very strange.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
That sounds like a different problem perhaps...
For about 2 weeks, I have noted latency on the site for the automation rule editor updates on publish, audit log refresh, and even the execution of rules (on a free license).
I even noted a new behavior: rules can now spontaneously halt executing, showing the "abort" message when one tries to execute / trigger a rule and then makes an update too soon afterwards.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yeah, "Oops we ran into a problem" seems to be unrelated. Support tells me:
I was able to reproduce this behavior with the Manual trigger on my own test site too.
I'm reporting this issue to our Confluence Automation Team for them to verify its root cause.
We will keep you posted.
Ugh, I wonder if their Automation infra is running into capacity issues.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hi @Matthew Ogrady -- Welcome to the Atlassian Community!
Do you mean an action item list on a Confluence page?
If so, I do not think there is a built-in rule action to edit a page that way. As a workaround, I hypothesize a rule could:
Kind regards,
Bill
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Yup. Once again, @Bill Sheboy is right. "This is the way."
https://YOURSITE.atlassian.net/wiki/api/v2/pages/{{page.id}}?body-format=storage
https://YOURSITE.atlassian.net/wiki/api/v2/pages/{{page.id}}
(Although it turns out Atlassian will ignore if you have "?body-format=storage" in the PUT)
{
"id": "{{page.id}}",
"status": "current",
"title": "{{webResponse.body.title}}",
"body": {
"representation": "storage",
"value": "{{webResponse.body.body.storage.value.replaceAll("<ac:task-status>complete<\/ac:task-status>", "<ac:task-status>incomplete<\/ac:task-status>").jsonEncode}}"
},
"version": {
"number": {{webResponse.body.version.number.plus(1)}},
"message": "Clearing Tasks"
}
}
If you're unfamiliar with using Atlassian's REST API from within Automation, here's a good explainer: https://community.atlassian.com/t5/Jira-articles/Automation-for-Jira-Send-web-request-using-Jira-REST-API/ba-p/1443828
You can pretty much use my Rule as-is, but you'll need to follow those instructions to generate the Authorization header for both Web Requests.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Thanks for creating the example, @Darryl Lee !
Did you try replace() rather than replaceAll() to avoid the need for escaping the characters?
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Hey @Bill Sheboy ah, that's a good point. However, for my use case, I needed regular expressions so I could get a little fancier (*sigh*) and search for "Approve" in the body of each task, so I'm ONLY clearing "Approval" tasks.
I end up having to include that text back in the replacement text, so regular expression is required. (It also lets me get fancy with where Approve appears in the task body, and whether it's capitalized.)
So here's what the value looked like in my final rule:
{{webResponse.body.body.storage.value.replaceAll("<ac:task-status>complete</ac:task-status>\\n<ac:task-body>(.*?[Aa]pprove.*?)</ac:task-body>", "<ac:task-status>incomplete</ac:task-status>\\n<ac:task-body>$1</ac:task-body>").jsonEncode}}
Sidenote: It is pretty annoying that the / character does not need to be escaped (Which was screwing up my regex. *Sigh* ruined by too many years with ex/sed/perl. :-)
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
Please try the approach @Darryl Lee and I suggested with this answer above to uncheck all of the actions / tasks on the page.
The other answer thread is just exploring another approach which may not work, possibly due to some recent automation changes to webhooks.
Please let us know how this one works for you. Thanks!
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.