Leveraging Slack Attachments via Webhooks with PHP

The year of 2016 is a year of continuous integration. At Facet, we have some initiatives in order to drive more visibility with our development team, surface sales pipelines, and also gain timely insights to our client's marketing campaigns. Webhooks are quickly becoming pervasive throughout many platforms online, and finally this week I had the opportunity to take a look at one of our targeted Webhooks in Pantheon's Quicksilver platform hook system. 

While first learning how to set up Pantheon webhooks this week, I decided to dig in for a bit to Slack's Webhooks and learn a little more about Slack Attachments. Pantheon's Quicksilver examples repo had an @TODO, and I aimed to do it.

(If you want to skip past some of the learnings I'll walk through, you can simply check out the Pull Request or Commit.)

Anatomy of Slack Attachments

{
    "attachments": [
        {
            "fallback": "Required plain-text summary of the attachment.",

            "color": "#36a64f",

            "pretext": "Optional text that appears above the attachment block",

            "author_name": "Bobby Tables",
            "author_link": "http://flickr.com/bobby/",
            "author_icon": "http://flickr.com/icons/bobby.jpg",

            "title": "Slack API Documentation",
            "title_link": "https://api.slack.com/",

            "text": "Optional text that appears within the attachment",

            "fields": [
                {
                    "title": "Priority",
                    "value": "High",
                    "short": false
                }
            ],

            "image_url": "http://my-website.com/path/to/image.jpg",
            "thumb_url": "http://example.com/path/to/thumb.png"
        }
    ]
}

The slack attachments are fairly robust in terms of delivering rich and robust information in a succinct manner. In my particular implementation, I focused on leveraging the field array in order to build out discreet information about each deployment or code push.

Building the Array of Fields

The array of fields is a mapping for the table of rich information that is displayed within Slack. Each field can either display as a full row when "short": false, and when "short": true, you are telling Slack that two fields can be stacked side by side. 

In the following example, a table is constructed so that deployment about the Site, Environment, and Commit information are displayed.

$fields = array(
  array(
    'title' => 'Site',
    'value' => $_ENV['PANTHEON_SITE_NAME'],
    'short' => 'true'
  ),
  array( // Render Environment name with link to site, <http://{ENV}-{SITENAME}.pantheon.io|{ENV}>
    'title' => 'Environment',
    'value' => '<http://' . $_ENV['PANTHEON_ENVIRONMENT'] . '-' . $_ENV['PANTHEON_SITE_NAME'] . '.pantheon.io|' . $_ENV['PANTHEON_ENVIRONMENT'] . '>',
    'short' => 'true'
  ),
  array( // Render Name with link to Email from Commit message
    'title' => 'By',
    'value' => $_POST['user_email'],
    'short' => 'true'
  ),
  array(
    'title' => 'View Dashboard', // Render link to Dashboard, <http://dashboard.pantheon.io/sites/{SITENAME}#{ENV}/deploys|View Dashboard>
    'value' => '<https://dashboard.pantheon.io/sites/'. PANTHEON_SITE .'#'. PANTHEON_ENVIRONMENT .'/deploys|View Dashboard>',
    'short' => 'true'
  ),
  array(
    'title' => 'Deploy Message',
    'value' => $annotation,
    'short' => 'false' // Expand this deploy message to the full width
  )
);

Create the Attachment 

Once you've constructed the array of fields, you can insert this into the $attachment, which will later be converted to JSON with json_encode().

$attachment = array(
  'fallback' => $text, // A required markdown textfield that is displayed on devices that can't display Attachments
  'pretext' => 'Deploying :rocket:',
  'color' => '#EFD01B', // Can either be one of 'good', 'warning', 'danger', or any hex color code, but this is Pantheon Yellow
  'fields' => $fields
);

Create the Post

Finally, now you have all of the pieces to build the first tier of the payload you'll be posting to Slack. $channel is consumed from the Slack Webhook URL, which you should've already set up and stored in a secret file. Look to the quicksilver examples for slack notifications in full here if you're looking for more information.

$post = array(
  'username' => 'Pantheon-Quicksilver',
  // 'text' => $text, // Uncomment if you always want to send a text message, otherwise display attachment->fallback when needed
  'channel' => $channel,
  'icon_emoji' => ':lightning_cloud:',
  'attachments' => array($attachment)
);
$payload = json_encode($post);

Debugging Posts

If you want to be sure you're constructing the JSON in the correct way, setting the JSON_PRETTY_PRINT flag and printing to a log will help you get insights into issues with formatting, or errors.

$payload_pretty = json_encode($post,JSON_PRETTY_PRINT); 
print("JSON: $payload_pretty"); 

In the quicksilver-example, this was added so that you can view the constructed webhooks via 

`terminus workflows watch --site=SITENAME`

What's Next

Now that our Pantheon commits and deploys are keeping our clients and remote team members informed, we're looking forward to our next webhooks project.

Next, we'll be looking to developing a Mautic webhook plugin in order to share qualified lead opportunities to our #sales channel. 

----

Jordan RyanJordan Ryan (@jordan_ryan) is President and Solutions Architect-for-hire at Facet Interactive (@FacetLA). When Jordan isn't hustling through his most recent discovery engagement, you can find him enjoying the finer grinds of fresh ground coffee in Santa Monica or fiending for a foodie fix wherever Yelp may take him. Follow him on Instagram if you like to feast with your eyes.

 

Need Help? Tell Us About your Project