Page Approvals - Let's Make It Complicated (Part 2)

OK! So... yesterday I published a user's guide to my Page Approvals implementation.

But let's get into the fun stuff. What's under the hood?

matrix.gif

 

Smart Buttons

Smart Buttons are a nifty, but limited feature that allow users to trigger a pre-defined Automation rules that can be chosen from a stock set of simple templates. The rules can only be modified within the Smart Button templates, and only settings for the pre-defined actions can be modified, ex: Page Status to change to, Labels to add, hard-coded address to email.

BUT! Thanks to the handy Allow rule trigger option, we can use Labels to trigger more advanced rules.

So in our case, we created a Request Approval Smart Button that changes the Page Status to [IN REVIEW] and adds a label approval-started.

image.png

Per a user suggestion, I’ve put the button in an Expand macro as a “safety” of sorts. In truth, anyone can click a Smart Button, but the page restriction added upon publishing should prevent it from working for anyone but the page author.


Automation Rules

Approval Page Restricted to Author

image.png

  • When page published:

  • If Page Condition where page was created from the template we use for approvals

  • Then: Restrict page to only be edited by the “Rule initiator” (which is the page author in this case).


Approval Started

image.png

  • When Page status changes to In Review (triggered by the Smart Button, because we have enabled the Allow rule trigger option):

  • Web request to the get page API just to get the current version of the page (minus the version that gets created when the Page Status changes, sigh).

  • Create variable {{approvalVersion}} - used to hold version for use in Comment.

  • Web request to the get tasks API to get all the tasks for the page.

  • Create variable {{approversIdArray}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.

    • Smart Value:
      {{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}"{{assignedTo}}"{{^last}}, {{/}}{{/}}{{/}}

  • Web request to the Add restrictions API (using POST method) with {{approversIdArray}} to allow the Approvers to edit this page (which the previous automation restricted to the author) so that they can actually check the Tasks off.

  • Web request to the bulk user lookup API to query {{approversIdArray}} and to get email and displayName for each Approvers.

  • Add comment to the page logging that the approval has been requested, including the {{webResponse.body.results.displayName}} and {{approvalVersion}}.

  • Send email to the Approvers giving them instructions to approve the page, using {{webResponse.body.results.emailAddress}}.

  • Add label approvalversion-{{approvalVersion}}so that we can later reference this version.

  • Remove label approval-started because we really only need it for the Smart Button trigger.


Approvals Checked - Task Status Changed

image.png

  • When Task status changes:

  • If: Page status is In Review and if the Task body {{task.body}} includes the word “Approve” (to allow for the possibility of non-Approval tasks to be used on these pages.)

  • Add comment that an Approval Task was APPROVED or (if unchecked) UNAPPROVED, and who carried initiated the change, as well as the assignee of the task. Unfortunately we cannot restrict assignees to only checking their own tasks, but through the comment log we have an audit trail of mistaken clicks OR (in theory) approvals made on behalf of somebody else.

  • Web request to the get tasks API to get all the incomplete tasks for the page.

  • Create variable {{incompleteApprovalsList}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.

    • Smart Value:
      {{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}{{id}}{{^last}}~~{{/}}{{/}}{{/}}

  • If: Compare two values - if the list of approvers {{incompleteApprovalsList}} is Empty …

  • Change page status to Approved


Approval Cancelled - Page Changed

image.png

  • When: Page edited

  • If: Page Status is In Review or Approved, we cancel/invalidate the Request/Approval, because the page under review (or approved) is no longer the same.

  • Change the page status to IN PROGRESS (as there is no automation action to remove a page status).

  • Add label: approval-cancelled

  • Add comment indicating Approval request was cancelled. Include version.

  • Remove approvalversion-VERSIONlabel.

  • Web request to the get tasks API to get all the tasks for the page.

  • Create variable {{approversIdArray}} to filter out only tasks that include “Approve”, and store the IDs of the assignee (Approver) of each task.

    • Smart Value:
      {{#webResponse.body.results}}{{#if(body.storage.value.match(".(Approve).").isNotEmpty())}}"{{assignedTo}}"{{^last}}, {{/}}{{/}}{{/}}

  • Web request to the Delete restrictions API (using DELETE method) to remove page edit permissions for approvers.

  • Web request to the Add restrictions API (using POST method) add edit permission back for Page Author, in case they were an Approver.

  • Send email to Approvers indicating Approval Cancelled.

  • Web request to the get page API just to get the version, title, and body (content) of the page.

  • Web request to the update page API (using PUT method) replace the body of the page where the replaceAll text function has been used to find all completed tasks that include “Approve” in their description and set their status to incomplete.

  •  

    • Full Payload:
    • {
      "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>\\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}}"
      },
      "version": {
      "number": {{webResponse.body.version.number.plus(1)}},
      "message": "Approval Cancelled - Clearing Approvals"
      }
      }


Whew. That's a lot.

Documentation can be a lot of work.

Hopefully this helps somebody in the future. Please let me know if you have questions.

Happy to provide text of various calls/custom data if that helps, as I know the images can be hard to read.

4 comments

Darryl Lee
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 20, 2025

I have to thank @Matthew Ogrady for asking Is there a way to uncheck all action items on a page? and the esteemed @Bill Sheboy for providing the right answer:

  • load the page contents using the REST API and the Send Web Request action
  • find / replace the task-status values of "complete" with "incomplete"
  • use the REST API again to update the page content

When I was first working on this project a few months ago, I discovered the Tasks API and fixated on using it to uncheck items.

Bill's elegantly simple answer actually worked, unlike the buggy API (AHEM), but of course Bill pointed me to a slightly more complex method (recursive rules? Yikes) that also worked.

https://community.atlassian.com/t5/Automation-questions/Re-Re-Is-there-a-way-to-uncheck-all-action-items-on-a-p/qaq-p/2947597/comment-id/13441#M13441

Bill Sheboy
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 20, 2025

Hi @Darryl Lee 

Just "wow" on this one!  Well done following through and adding the content details needed for people to try it.

One question...

I observe many moving parts and Send Web Request actions in these rules, which I assume are configured to halt on first failure.  What are your thoughts on having an additional "cleanup / reset rule" to help if a page's approval data gets glitched due to a rule failure, service limit problem, or Atlassian outage...leaving it midway through the changes for an approval step?

Kind regards,
Bill

Darryl Lee
Community Leader
Community Leader
Community Leaders are connectors, ambassadors, and mentors. On the online community, they serve as thought leaders, product experts, and moderators.
February 20, 2025

Thanks, and great question Bill! Yes, data integrity (or at least some kind of traceability/audit trail) was something I thought about, but mainly as it pertained to "logging" (comments) or "approval state".

One tricky thing I learned is that while checking a box is not considered a "Page edited" trigger, it DOES increment the page version.

This is why I add a label with containing the "In Review" version, and add it to every comment:

Page Approval process STARTED [v.15]

Approvers: *Naga Raju Adapa, Inayat Nahvi, Darryl Lee, Andrey Khessin

I suppose I could pose it as ...


Exercises for the reader

Error checks

Sometimes calls to the REST API fail, or you might run into rule limits, or Atlassian outages happen.

Can find some way to alert about when these cases happen, and possibly clean them up?

  • Maybe a rule that could be run from a schedule to find and flag pages that are in an "Approved" status but ALSO have approval-cancelled. (I guess it should send a report?)
  • Look at pages are are "Approved" whose restrictions are not limited to the page owner? Again, a report seems like it might be helpful.

Email reminders

Commercial page approval tools (I think) probably let you send reminders about pending approvals. You can probably do this with a scheduled rule, looking for pages that are "In Review" and have unchecked tasks.


There's probably other features I forgot.

Also, it's important to consider your use case:

  • How much risk/failure you can tolerate?
  • How much time/expertise do you have to maintain a home-grown solution?

Because there's no shortage of vendors out there ready to take your money provide a robust solution for you:

... and that's just the first page...

Ooof, that's a lot of apps. Please please vendors I missed, feel free to plug away. :-P

Matt Doar _Adaptavist_
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
February 21, 2025

This is clever. 

"How much time/expertise do you have to maintain a home-grown solution?" - yes, that's what I was thinking. I looked at the price for some of the apps and the numbers were actually less than I expected. I'd be interested to see an estimate of the effort involved in coming up with this approach and the estimated maintenance costs over the next few years.

Comment

Log in or Sign up to comment
TAGS
AUG Leaders

Atlassian Community Events