Slack message layout templates#

Example templates are provided that helps you to create message layout to use with Slack integration.

The message layout is available for the following events:

Note: You can customize these available message layout as per your team requirement. Refer to Slack documentation for more information.

Parent topic: How-to: Integrate Slack

Application Deployment Failure JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
#macro (addLimitReached)
        ## show limit message & link
    ,{
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request For More>"
        }
    }
        #set ($blockCount = $blockCount + 1)
#end
#macro (showFailure $analysis $indent)
    #if ($blockCount == 50)
        #addLimitReached()
    #elseif ($blockCount > 50)
        ##ignore no room left
    #else
        ## add section and recurse down
    ,{
        "type": "section",
        "text": {
            "type": "plain_text",
            "text": "$indent$fn.escapeJson($analysis.getTrace().getName())"
        }
    }
        #set ($blockCount = $blockCount + 1)
        #set ($analysisChildren = $analysis.getChildren())
        #if ($analysisChildren && $analysisChildren.size() > 0)
            #set ($newindent = $indent+"--")
            #foreach ($child in $analysisChildren)
                #showFailure($child, $newindent)
            #end
        #end
    #end
#end

#macro (showVersion $version)
    #if ($blockCount == 50)
        #addLimitReached()
    #elseif ($blockCount > 50)
        ##ignore no room left
    #else
        ## add section
    ,{
        "type": "section",
        "fields": [{
             "type": "mrkdwn",
             "text": "*Component*: $fn.escapeJson($version.getComponent().getName())"
         },{
             "type": "mrkdwn",
             "text": "*Version*: $fn.escapeJson($version.getName())"
         #if ($version.getDescription() and !$version.getDescription().trim().isEmpty())
         },{
             "type": "plain_text",
             "text": "$fn.escapeJson($version.getDescription())"
         #end
         }]
    }
        #set ($blockCount = $blockCount + 1)
    #end
#end

{
    "blocks": [
        ## block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process on $fn.escapeJson($application.getName()) failed"
            }
        },
        ## block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($applicationProcess.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Requested On*: $fn.formatDate($request.getSubmittedDate())"
                }
                ,{
                    "type": "mrkdwn",
                    "text": "*Duration in Milliseconds*: $request.getDurationInMillis()"
                }
                #if ($request.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Description*: $fn.escapeJson($request.getDescription())"
                }
                #end
                #set ($warningCount = $workflowTrace.getWarningCount())
                #if ($warningCount > 0)
                ,{
                    "type": "mrkdwn",
                    "text": "*Warning Count*: $warningCount"
                }
                #end
            ]
        },
        ## block 3
        {
            "type":"section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request>"
            }
        },
        ## block 4
        {
            "type":"divider"
        },
        ## block 5
        #set ($warnMessList = $workflowTrace.getChildWarningMessages())
        #if ($warnMessList && $warnMessList.size() > 0)
        {
            "type": "section",
            "fields": [{
                "type": "mrkdwn",
                "text": "*Warnings*"
            #foreach ($mess in $warnMessList)
                #if($velocityCount == 9)
                    ## add link
            },{
                "type": "mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|See process request for more>"
                #elseif ($velocityCount > 9)
                    ## ignore
                #else
            },{
                "type": "plain_text",
                "text": "$fn.escapeJson($mess)"
                #end
            #end
            }]
        },
        #end
        ## block 6
        {
            "type":"divider"
        }
        ## Show as many of the failure analysis and versions as we can.
        ## If we run out of blocks(slack limits to 50), make the last block
        ## a link to the process request
        ## for brevity we don't show summary of other steps as we do in emails
        ##block 7 - 50
        #set ($blockCount = 7)
        #set ($rootAnalyses = $failureAnalysis.getRootAnalyses())
        #if ($rootAnalyses && $rootAnalyses.size() > 0)
            ## block 7
            ,{
                "type": "section",
                "text": {
                    "type": "mrkdwn",
                    "text": "*Failures*"
                }
            }
            #set ($blockCount = $blockCount + 1)
            #foreach ($failure in $rootAnalyses)
                #showFailure ($failure "")
            #end
        #end
        ##Show as many versions as we have space for
        #if ($versions && $versions.size() > 0)
            #if ($blockCount == 50)
                #addLimitReached()
            #elseif ($blockCount > 50)
                ## do nothing
            #else
                ,{
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": "*Versions*"
                    }
                }
                #set ($blockCount = $blockCount + 1)
                #foreach($version in $versions)
                    #showVersion ($version)
                #end
            #end
        #end
    ]
}
## END SECTION Body

Application Deployment Success JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
#macro (addLimitReached)
        ## show limit message & link
    ,{
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request For More>"
        }
    }
        #set ($blockCount = $blockCount + 1)
#end

#macro (showVersion $version)
    #if ($blockCount == 50)
        #addLimitReached()
    #elseif ($blockCount > 50)
        ##ignore no room left
    #else
        ## add section
    ,{
        "type": "section",
        "fields": [{
             "type": "mrkdwn",
             "text": "*Component*: $fn.escapeJson($version.getComponent().getName())"
         },{
             "type": "mrkdwn",
             "text": "*Version*: $version.getName()"
         #if ($version.getDescription() and !$version.getDescription().trim().isEmpty())
         },{
             "type": "plain_text",
             "text": "$fn.escapeJson($version.getDescription())"
         #end
         }]
    }
        #set ($blockCount = $blockCount + 1)
    #end
#end

{
    "blocks": [
        ## block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process on $fn.escapeJson($application.getName()) completed successfully"
            }
        },
        ## block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($applicationProcess.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Requested On*: $fn.formatDate($request.getSubmittedDate())"
                }
                ,{
                    "type": "mrkdwn",
                    "text": "*Duration in Milliseconds*: $request.getDurationInMillis()"
                }
                #if ($request.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Description*: $fn.escapeJson($request.getDescription())"
                }
                #end
                #set ($warningCount = $workflowTrace.getWarningCount())
                #if ($warningCount > 0)
                ,{
                    "type": "mrkdwn",
                    "text": "*Warning Count*: $warningCount"
                }
                #end
            ]
        },
        ## block 3
        {
            "type":"section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request>"
            }
        },
        ## block 4
        {
            "type":"divider"
        },
        ## block 5
        #set ($warnMessList = $workflowTrace.getChildWarningMessages())
        #if ($warnMessList && $warnMessList.size() > 0)
        {
            "type": "section",
            "fields": [{
                "type": "mrkdwn",
                "text": "*Warnings*"
            #foreach ($mess in $warnMessList)
                #if($velocityCount == 9)
                    ## add link
            },{
                "type": "mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|See process request for more>"
                #elseif ($velocityCount > 9)
                    ## ignore
                #else
            },{
                "type": "plain_text",
                "text": "$fn.escapeJson($mess)"
                #end
            #end
            }]
        },
        #end
        ## block 6
        {
            "type":"divider"
        }
        ##block 7 - 50
        #set ($blockCount = 7)
        ## show as many versions as possible
        ## in the email template we show step summaries as well.
        ## this is omitted here due to slack limits on sections and
        ## my personal believe version list is more valuable than a bunch
        ## of successful steps
        ##Show as many versions as we have space for
        #if ($versions && $versions.size() > 0)
            #if ($blockCount == 50)
                #addLimitReached()
            #elseif ($blockCount > 50)
                ## do nothing
            #else
                ,{
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": "*Versions*"
                    }
                }
                #set ($blockCount = $blockCount + 1)
                #foreach($version in $versions)
                    #showVersion ($version)
                #end
            #end
        #end
    ]
}
## END SECTION Body

Approval Completed JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "Approval Completed"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($requester.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Scheduled for*: $scheduledDate"
                }
                #if ($appRequest.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($appRequest.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        },
        ## Block 4
        {
            "type": "divider"
        }
        ## Block 5
        #if ($tasks && $tasks.size() > 0)
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Tasks*"
            }
        }
        #end
        #set ($blockCount = 6)

        #foreach ($task in $tasks)
            #if ($blockCount == 50)
        ,{
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request for more information.>"
            }
        }
            #set ($blockCount = $blockCount + 1)
            #elseif ($blockCount > 50)
                ## no more room
            #else
        ,{
            "type": "context",
            "elements": [{
                "type": "mrkdwn",
                "text": "*Name*: $fn.escapeJson($task.getName())"
            },{
                "type": "mrkdwn",
                "text": "*Type*: $fn.escapeJson($task.getTaskType())"
            },{
                "type": "mrkdwn",
                "text": "*Status*: $fn.escapeJson($task.getStatus().name())"
            },{
                "type": "mrkdwn",
                "text": "*User*: $fn.escapeJson($task.getUser().getDisplayName())"
            },{
                "type": "mrkdwn",
                "text": "*Comment*: $fn.escapeJson($task.getComment())"
            },{
                "type": "mrkdwn",
                "text": "*Date*: $fn.formatUnixTime($task.getDateEnded())"
            }]
        }
            #set ($blockCount = $blockCount + 1)
            #end
        #end
    ]
}
## END SECTION Body

Approval Created JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "Approval Pending"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                #if ($component)
                {
                    "type": "mrkdwn",
                    "text": "*Component*: $fn.escapeJson($component.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($processName)"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Scheduled for*: $scheduledDate"
                }
                #if ($appRequest.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($appRequest.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        },
        ## Block 4
        #if ($respondUrl)
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($respondUrl)|Respond>"
            }
        },
        #end
        ## Block 5
        {
            "type": "divider"
        }
        ## Block 6
        #if ($roles)
        ,{
            "type": "section",
            "fields": [
                {
                    "type": "mrkdwn",
                    "text": "*Roles*:"
                }
                ## This breaks at > 9 roles. Check for version handling to modify to handle more
                #foreach ( $role in $roles )
                ,{
                     "type": "mrkdwn",
                     "text": "$fn.escapeJson($role.getName())"
                }
                #end
            ]
        },{
            "type": "divider"
        }
        #end
        ## Block 7-50
        #if ($versionMap)
            #set ( $compSet = $versionMap.getComponents())
            #foreach ( $comp in $compSet)
                ## velocityCount is the default iterator velocity uses
                #if ($velocityCount == 42)
                    ## add placeholder
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|Refer to request for more components.>"
            }
        }
                #elseif ($velocityCount > 42)
                     ## do nothing
                     ## anymore and slack will reject the message
                ## velocityCount starts at 1
                #elseif ($velocityCount == 1)
                    ## add label and thing
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Versions by Component*:"
            }
        }
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*$fn.escapeJson($comp)*: $fn.escapeJson($versionMap.getVersionsForComp($comp))"
            }
        }
                #else
                     ## addthing
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*$fn.escapeJson($comp)*: $fn.escapeJson($versionMap.getVersionsForComp($comp))"
            }
        }
                #end
            #end
        #end
    ]
}
## END SECTION Body

Approval Failed JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "Approval Failed"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($requester.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Scheduled for*: $scheduledDate"
                }
                #if ($appRequest.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($appRequest.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        },
        ## Block 4
        {
            "type": "divider"
        }
        ## Block 5
        #if ($tasks && $tasks.size() > 0)
        ,{
            "type": "section",
            "text": {
                "type": "mrkdwn",
                "text": "*Tasks*"
            }
        }
        #end
        #set ($blockCount = 6)

        #foreach ($task in $tasks)
            #if ($blockCount == 50)
        ,{
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request for more information.>"
            }
        }
            #set ($blockCount = $blockCount + 1)
            #elseif ($blockCount > 50)
                ## no more room
            #else
        ,{
            "type": "context",
            "elements": [{
                "type": "mrkdwn",
                "text": "*Name*: $fn.escapeJson($task.getName())"
            },{
                "type": "mrkdwn",
                "text": "*Type*: $fn.escapeJson($task.getTaskType())"
            },{
                "type": "mrkdwn",
                "text": "*Status*: $$fn.escapeJson(task.getStatus().name())"
            },{
                "type": "mrkdwn",
                "text": "*User*: $fn.escapeJson($task.getUser().getDisplayName())"
            },{
                "type": "mrkdwn",
                "text": "*Comment*: $fn.escapeJson($task.getComment())"
            },{
                "type": "mrkdwn",
                "text": "*Date*: $fn.formatUnixTime($task.getDateEnded())"
            }]
        }
            #set ($blockCount = $blockCount + 1)
            #end
        #end
    ]
}
## END SECTION Body

External Approval Completed JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "An external approval process was successful"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($requester.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Scheduled for*: $scheduledDate"
                }
                #if ($request.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($request.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

External Approval Failed JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "An application process was rejected during its external approval process"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                },
                #if ($snapshot)
                {
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },
                #end
                {
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($requester.getDisplayName())"
                },
                {
                    "type": "mrkdwn",
                    "text": "*Scheduled for*: $scheduledDate"
                }
                #if ($request.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($request.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

Generic Process Failure JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process failed"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($process.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $scheduledDate"
                }
                #if ($resourceName)
                ,{
                    "type": "mrkdwn",
                    "text": "*Resource*: $fn.escapeJson($resourceName)"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

Generic Process Request Started JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process started"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($process.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $scheduledDate"
                }
                #if ($resourceName)
                ,{
                    "type": "mrkdwn",
                    "text": "*Resource*: $fn.escapeJson($resourceName)"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

Generic Process Success JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process succeeded"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($process.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $scheduledDate"
                }
                #if ($resourceName)
                ,{
                    "type": "mrkdwn",
                    "text": "*Resource*: $fn.escapeJson($resourceName)"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

Process Not Started JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A process failed to start (server in maintenance mode)"
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($process.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $scheduledDate"
                }
                #if ($resourceName)
                ,{
                    "type": "mrkdwn",
                    "text": "*Resource*: $fn.escapeJson($resourceName)"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type": "plain_text",
                "text": "The process failed to start because the server is in maintenance mode. You can request the process again when maintenance is complete."
            }
        },
        ## Block 4
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
            }
        }
    ]
}
## END SECTION Body

Process Request Started JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
#macro (addLimitReached)
        ## show limit message & link
    ,{
        "type": "section",
        "text": {
            "type": "mrkdwn",
            "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request For More>"
        }
    }
        #set ($blockCount = $blockCount + 1)
#end

#macro (showVersion $version)
    #if ($blockCount == 50)
        #addLimitReached()
    #elseif ($blockCount > 50)
        ##ignore no room left
    #else
        ## add section
    ,{
        "type": "section",
        "fields": [{
             "type": "mrkdwn",
             "text": "*Component*: $fn.escapeJson($version.getComponent().getName())"
         },{
             "type": "mrkdwn",
             "text": "*Version*: $fn.escapeJson($version.getName())"
         #if ($version.getDescription() and !$version.getDescription().trim().isEmpty())
         },{
             "type": "plain_text",
             "text": "$fn.escapeJson($version.getDescription())"
         #end
         }]
    }
        #set ($blockCount = $blockCount + 1)
    #end
#end
#macro (showChanges $compName)
    #if ($blockCount == 50)
        #addLimitReached()
        #set ($blockCount = $blockCount + 1)
    #elseif ($blockCount > 50)
        ## do nothing
    #else
        ,{
            "type":"section",
            "fields": [
                {
                    "type":"mrkdwn",
                    "text": "*$fn.escapeJson($compName)*:"
                }
                #set ($changes = $changesByComponent.get($compName))
                #foreach ($change in $changes)
                    #if ($velocityCount < 9)
                ,{
                    "type": "mrkdwn",
                    "text": "$fn.escapeJson($fn.getChangeTypeDisplayName($change)) $fn.escapeJson($fn.getChangeVersionDisplayName($change)) to <$fn.escapeJson($externalUrl)#resource/$change.getResource().getId().toString()|$fn.escapeJson($change.getResource().getName())>"
                }
                    #elseif ($velocityCount == 9)
                ,{
                    "type": "mrkdwn",
                    "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request For More>"
                }
                    #end
                #end
            ]
        }
        #set ($blockCount = $blockCount + 1)
    #end
#end

{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "An application process started."
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($applicationProcess.getName())"
                },{
                #if ($snapshot)
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                },{
                #end
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $fn.formatDate($request.getSubmittedDate())"
                }
                #if ($request.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Description*: $fn.escapeJson($request.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "text": {
                "type":"mrkdwn",
                "text": "<$fn.escapeJson($externalUrl)#applicationProcessRequest/$request.getId().toString()|View Process Request For More>"
            }
        }
        #set ($blockCount = 4)
        ##Show as many versions as we have space for
        #if ($versions && $versions.size() > 0)
            #if ($blockCount == 50)
                #addLimitReached()
            #elseif ($blockCount > 50)
                ## do nothing
            #else
                ,{
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": "*Versions*"
                    }
                }
                #set ($blockCount = $blockCount + 1)
                #foreach($version in $versions)
                    #showVersion ($version)
                #end
            #end
        #end
        ## show as many Components as possible
        #if ($uniqueComponentNames && $uniqueComponentNames.size() > 0)
            #if ($blockCount == 50)
                #addLimitReached()
            #elseif ($blockCount > 50)
                ## do nothing
            #else
                ,{
                    "type": "section",
                    "text": {
                        "type": "mrkdwn",
                        "text": "*Pending Changes*"
                    }
                }
                #set ($blockCount = $blockCount + 1)
                #foreach($compName in $uniqueComponentNames)
                    #showChanges ($compName)
                #end
            #end
        #end
    ]
}
## END SECTION Body

Task Created JSON body#

## BEGIN SECTION Body
## PROPERTY Content-Type: application/json
{
    "blocks": [
        ## Block 1
        {
            "type": "header",
            "text": {
                "type": "plain_text",
                "text": "A task is eligible to be completed. Please review the request and approve or reject this task."
            }
        },
        ## Block 2
        {
            "type": "context",
            "elements": [
                {
                    "type": "mrkdwn",
                    "text": "*Process*: $fn.escapeJson($process.getName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Requested by*: $fn.escapeJson($user.getDisplayName())"
                },{
                    "type": "mrkdwn",
                    "text": "*Request on*: $scheduledDate"
                }
                #if ($application)
                ,{
                    "type": "mrkdwn",
                    "text": "*Application*: $fn.escapeJson($application.getName())"
                }
                #end
                #if ($enviornment)
                ,{
                    "type": "mrkdwn",
                    "text": "*Environment*: $fn.escapeJson($environment.getName())"
                }
                #end
                #if ($snapshot)
                ,{
                    "type": "mrkdwn",
                    "text": "*Snapshot*: $fn.escapeJson($snapshot.getName())"
                }
                #end
                #if ($component)
                ,{
                    "type": "mrkdwn",
                    "text": "*Component*: $fn.escapeJson($component.getName())"
                }
                #end
                #if ($resourceName)
                ,{
                    "type": "mrkdwn",
                    "text": "*Resource*: $fn.escapeJson($resourceName)"
                }
                #end
                #if ($appRequest && $appRequest.getDescription())
                ,{
                    "type": "mrkdwn",
                    "text": "*Request Description*: $fn.escapeJson($appRequest.getDescription())"
                }
                #end
            ]
        },
        ## Block 3
        {
            "type": "section",
            "fields": [
                {
                    "type":"mrkdwn",
                    "text": "<$fn.escapeJson($externalUrl)/#$requestType/$processId|View Request>"
                }
                #if ($respondUrl)
                ,{
                    "type":"mrkdwn",
                    "text": "<$fn.escapeJson($respondUrl)|Respond>"
                }
                #end
            ]
        }
        #if ($roles)
        ,{
            "type": "section",
            "fields": [
                {
                    "type": "mrkdwn",
                    "text": "*Roles*:"
                }
                ## This breaks at > 9 roles. Check for other templates handling to modify to handle more
                #for each ( $role in $roles )
                ,{
                     "type": "mrkdwn",
                     "text": "$fn.escapeJson($role.getName())"
                }
                #end
            ]
        }
        #end
    ]
}
## END SECTION Body