From 88a512c68550e90d89cf3e76b12cac2e86e6a1f9 Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:12:20 -0700 Subject: [PATCH 01/27] 'Title' uses better formatting than pretext in Slack Attachments. Emojis display as well. --- slack_notification/slack_notification.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 3c6fcf1..c0053b3 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -104,7 +104,7 @@ $attachment = array( 'fallback' => $text, - 'pretext' => 'Deploying :rocket:', + 'title' => 'Deploying :rocket:', 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code 'fields' => $fields ); From 618acfd51c31ec11a3b388c17f845afb76a833c2 Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:19:55 -0700 Subject: [PATCH 02/27] Slack Attachments Title should really be set per-case --- slack_notification/slack_notification.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index c0053b3..b124f38 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -53,6 +53,9 @@ $deploy_tag = `git describe --tags`; $deploy_message = $_POST['deploy_message']; + // Set a Slack Attachments title + $title = 'Deploying :rocket:'; + // Prepare the slack payload as per: // https://api.slack.com/incoming-webhooks $text = 'Deploy to the '. $_ENV['PANTHEON_ENVIRONMENT']; @@ -76,6 +79,9 @@ $message = `git log -1 --pretty=%B`; $hash = `git log -1 --pretty=%h`; + // Set a Slack Attachments title + $title = 'Syncing code :fax:'; + // Prepare the slack payload as per: // https://api.slack.com/incoming-webhooks $text = 'Code sync to the ' . $_ENV['PANTHEON_ENVIRONMENT'] . ' environment of ' . $_ENV['PANTHEON_SITE_NAME'] . ' by ' . $_POST['user_email'] . "!\n"; @@ -104,7 +110,7 @@ $attachment = array( 'fallback' => $text, - 'title' => 'Deploying :rocket:', + 'title' => $title, 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code 'fields' => $fields ); From 3f2b0ba39f8fc6ee3837fb72902442b81d17f28c Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:53:11 -0700 Subject: [PATCH 03/27] Drush Site Audit on deploy. * @TODO: Duplicate to HipChat * This is implemented as a separate script, didn't want to assume everyone would ALWAYS want to run the site audit. Also this report is quite verbose, so I think people should opt-in if they want to pollute their Slack channel. * This is grouped under /slack_notification example, but could be arguably moved to it's own example as drush_site_audit or something similar. Concern there is duplicating Slack notification markup further. Makes me think a slack_helper.php would be easier to include basic functionality across multiple scripts/quicksilver workflow tasks. --- .../slack_notify_drush_site_audit.php | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 slack_notification/slack_notify_drush_site_audit.php diff --git a/slack_notification/slack_notify_drush_site_audit.php b/slack_notification/slack_notify_drush_site_audit.php new file mode 100644 index 0000000..8f386e3 --- /dev/null +++ b/slack_notification/slack_notify_drush_site_audit.php @@ -0,0 +1,133 @@ + '#quicksilver', + 'slack_username' => 'Pantheon-Quicksilver', + 'always_show_text' => false, +); + +// Load our hidden credentials. +// See the README.md for instructions on storing secrets. +$secrets = _get_secrets(array('slack_url'), $defaults); + +// Build an array of fields to be rendered with Slack Attachments as a table +// attachment-style formatting: +// https://api.slack.com/docs/attachments +$fields = array( + array( + 'title' => 'Site', + 'value' => $_ENV['PANTHEON_SITE_NAME'], + 'short' => 'true' + ), + array( // Render Environment name with link to site, + 'title' => 'Environment', + 'value' => '', + 'short' => 'true' + ), + array( // Render Name with link to Email from Commit message + 'title' => 'By', + 'value' => $_POST['user_email'], + 'short' => 'true' + ), + array( // Render workflow phase that the message was sent + 'title' => 'Workflow', + 'value' => ucfirst($_POST['stage']) . ' ' . str_replace('_', ' ', $_POST['wf_type']), + 'short' => 'true' + ), + array( + 'title' => 'View Dashboard', + 'value' => '', + 'short' => 'true' + ), +); + +// Set a Slack Attachments title +$title = 'Post-Deploy Site Audit :helmet_with_white_cross:'; + +// Prepare the slack payload as per: +// https://api.slack.com/incoming-webhooks +$text = 'Site Audit Report after deployment to the *'. $_ENV['PANTHEON_ENVIRONMENT']; +$text .= ' environment of '. $_ENV['PANTHEON_SITE_NAME'] .' by '. $_POST['user_email'] .' complete!'; +$text .= ' '; +$text .= "\n\n*SITE AUDIT REPORT*: \n\n$site_audit_all"; +// No need to render Site Audit All as a slack attachment, +// full report is cut off due to character limit + +$attachment = array( + 'fallback' => $text, + 'title' => $title, + 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code + 'fields' => $fields, + 'text' => $site_audit_all +); + +_slack_notification($secrets['slack_url'], $secrets['slack_channel'], $secrets['slack_username'], $text, $attachment, $secrets['always_show_text']); + + +/** + * Get secrets from secrets file. + * + * @param array $requiredKeys List of keys in secrets file that must exist. + */ +function _get_secrets($requiredKeys, $defaults) +{ + $secretsFile = $_SERVER['HOME'] . '/files/private/secrets.json'; + if (!file_exists($secretsFile)) { + die('No secrets file found. Aborting!'); + } + $secretsContents = file_get_contents($secretsFile); + $secrets = json_decode($secretsContents, 1); + if ($secrets == FALSE) { + die('Could not parse json in secrets file. Aborting!'); + } + $secrets += $defaults; + $missing = array_diff($requiredKeys, array_keys($secrets)); + if (!empty($missing)) { + die('Missing required keys in json secrets file: ' . implode(',', $missing) . '. Aborting!'); + } + return $secrets; +} + +/** + * Send a notification to slack + */ +function _slack_notification($slack_url, $channel, $username, $text, $attachment, $alwaysShowText = false) +{ + $attachment['fallback'] = $text; + $post = array( + 'username' => $username, + 'channel' => $channel, + 'icon_emoji' => ':lightning_cloud:', + 'attachments' => array($attachment) + ); + if ($alwaysShowText) { + $post['text'] = $text; + } + $payload = json_encode($post); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $slack_url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + // Watch for messages with `terminus workflows watch --site=SITENAME` + print("\n==== Posting to Slack ====\n"); + $result = curl_exec($ch); + print("RESULT: $result"); + // $payload_pretty = json_encode($post,JSON_PRETTY_PRINT); // Uncomment to debug JSON + // print("JSON: $payload_pretty"); // Uncomment to Debug JSON + print("\n===== Post Complete! =====\n"); + curl_close($ch); +} From c9ad888dc3aa11e7db4f94cb94bd9006fc2246d0 Mon Sep 17 00:00:00 2001 From: Rachel Date: Mon, 27 Jun 2016 13:26:26 -0500 Subject: [PATCH 04/27] Align with New Relic Pro product release --- new_relic_deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/new_relic_deploy/README.md b/new_relic_deploy/README.md index f7abfc0..b5075a2 100644 --- a/new_relic_deploy/README.md +++ b/new_relic_deploy/README.md @@ -4,13 +4,13 @@ This example will show you how you can automatically log changes to your site in This script uses a couple clever tricks to get data about the platform. First of all it uses the `pantheon_curl()` command to fetch the extended metadata information for the site/environment, which includes the New Relic API key. It also uses data within the git repository on the platform to pull out deploy tag numbers and log messages. -> **Note:** New Relic's Deployments feature is not available for sites using the APM Lite plan. This example will only work for sites with New Relic APM Professional. It will work with all Pantheon sites during the two-week free trial of New Relic Pro that begins after you enable the add-on. +> **Note:** This example will work for all Pantheon sites once the bundled [New Relic APM Pro feature](https://pantheon.io/features/new-relic) is activated, regardless of service level. ## Instructions ## Setting up this example is easy: -1. [Enable New Relic](https://pantheon.io/docs/articles/sites/newrelic/) for your site. +1. [Activate New Relic Pro](https://pantheon.io/docs/new-relic/#activate-new-relic-pro) within your site Dashboard. 2. Add the example `new_relic_deploy.php` script to the `private` directory of your code repository. 3. Add a Quicksilver operation to your `pantheon.yml` to fire the script after a deploy. 4. Test a deploy out! From e970d2fc76237c0da21b3dcf09b9d303870d1d2e Mon Sep 17 00:00:00 2001 From: Josh Koenig Date: Tue, 28 Jun 2016 15:31:15 -0700 Subject: [PATCH 05/27] Update to handle commit/push use-case Also pretty things up a little bit. --- new_relic_deploy/new_relic_deploy.php | 71 +++++++++++++++++++-------- 1 file changed, 51 insertions(+), 20 deletions(-) diff --git a/new_relic_deploy/new_relic_deploy.php b/new_relic_deploy/new_relic_deploy.php index a829265..503b859 100644 --- a/new_relic_deploy/new_relic_deploy.php +++ b/new_relic_deploy/new_relic_deploy.php @@ -4,8 +4,7 @@ $meta = json_decode($req['body'], true); // Get the right binding for the current ENV. -// TODO: scope down the pantheon_curl() more. -// It should be possible to just fetch the one for the current env. +// It should be possible to just fetch the one for the current env. $nr = FALSE; foreach($meta as $data) { if ($data['environment'] === PANTHEON_ENVIRONMENT) { @@ -13,25 +12,57 @@ break; } } +// Fail fast if we're not going to be able to call New Relic. +if ($nr == FALSE) { + echo "\n\nALERT! No New Relic metadata could be found.\n\n"; + exit(); +} -// Find out what tag we are on -$deploy_tag = `git describe --tags`; -// Get the annotation -$annotation = `git tag -l -n99 $deploy_tag`; +// This is one example that handles code pushes, dashboard +// commits, and deploys between environments. To make sure we +// have good deploy markers, we gather data differently depending +// on the context. -// Use New Relic's own example curl for ease of use. -if ($nr) { - $curl = 'curl -H "x-api-key:'. $data['api_key'] .'"'; - $curl .= ' -d "deployment[application_id]=' . $data['app_name'] .'"'; - $curl .= ' -d "deployment[description]=This deploy log was sent using Quicksilver"'; - $curl .= ' -d "deployment[revision]='. $deploy_tag .'"'; - $curl .= ' -d "deployment[changelog]='. $annotation .'"'; - $curl .= ' -d "deployment[user]='. $_POST['user_email'] .'"'; - $curl .= ' https://api.newrelic.com/deployments.xml'; - // The below can be helpful debugging. - // echo "\n\nCURLing... \n\n$curl\n\n"; - passthru($curl); +if ($_POST['wf_type'] == 'sync_code') { + // commit 'subject' + $description = trim(`git log --pretty=format:"%s" -1`); + $revision = trim(`git log --pretty=format:"%h" -1`); + if ($_POST['user_role'] == 'super') { + // This indicates an in-dashboard SFTP commit. + $user = trim(`git log --pretty=format:"%ae" -1`); + $changelog = trim(`git log --pretty=format:"%b" -1`); + $changelog .= "\n\n" . '(Commit made via Pantheon dashbaord.)'; + } + else { + $user = $_POST['user_email']; + $changelog = trim(`git log --pretty=format:"%b" -1`); + $changelog .= "\n\n" . '(Triggered by remote git push.)'; + } } -else { - echo "\n\nALERT! No New Relic metadata could be found.\n\n"; +elseif ($_POST['wf_type'] == 'deploy') { + // Topline description: + $description = 'Deploy to environment triggered via Pantheon'; + // Find out if there's a deploy tag: + $revision = `git describe --tags`; + // Get the annotation: + $changelog = `git tag -l -n99 $deploy_tag`; + $user = $_POST['user_email']; } + + +// Use New Relic's v1 curl command-line example. +// TODO: update to use v2 API with JSON, plus curl() in PHP. +// Blocked by needing the app_id to use v2 API +$curl = 'curl -H "x-api-key:'. $data['api_key'] .'"'; +$curl .= ' -d "deployment[application_id]=' . $data['app_name'] .'"'; +$curl .= ' -d "deployment[description]= '. $description .'"'; +$curl .= ' -d "deployment[revision]='. $revision .'"'; +$curl .= ' -d "deployment[changelog]='. $changelog .'"'; +$curl .= ' -d "deployment[user]='. $user .'"'; +$curl .= ' https://api.newrelic.com/deployments.xml'; +// The below can be helpful debugging. +// echo "\n\nCURLing... \n\n$curl\n\n"; + +echo "Logging deployment in New Relic...\n"; +passthru($curl); +echo "Done!"; From abd074867cd676457607245622218ad43051e2a2 Mon Sep 17 00:00:00 2001 From: Ariel Gold Date: Thu, 11 Aug 2016 09:54:46 -0700 Subject: [PATCH 06/27] Add new hooks to Slack example README Site and Multidev Creation --- slack_notification/README.md | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/slack_notification/README.md b/slack_notification/README.md index ffa7f55..cdc224e 100644 --- a/slack_notification/README.md +++ b/slack_notification/README.md @@ -16,6 +16,7 @@ This script shows how easy it is to integrate Slack notifications from your Pant sftp> mkdir private sftp> cd private sftp> put secrets.json + sftp> quit ``` 3. Add the example `slack_notification.php` script to the `private` directory in the root of your site's codebase, that is under version control. Note this is a different `private` directory than where the secrets.json is stored. @@ -32,15 +33,25 @@ Here's an example of what your `pantheon.yml` would look like if this were the o api_version: 1 workflows: + deploy_product: + after: + - type: webphp + description: Post to Slack after site creation + script: private/scripts/slack_notification.php + create_cloud_development_environment: + after: + - type: webphp + description: Post to Slack after Multidev creation + script: private/scripts/slack_notification.php deploy: after: - type: webphp - description: Post to Slack on deploy + description: Post to Slack after deploy script: private/scripts/slack_notification.php sync_code: after: - type: webphp - description: Post to Slack on sync code + description: Post to Slack after code commit script: private/scripts/slack_notification.php clear_cache: after: From 9c5b0c4b848bb204c305776d1ad7ed6ba978e6bc Mon Sep 17 00:00:00 2001 From: Ariel Gold Date: Wed, 10 Aug 2016 09:56:51 -0700 Subject: [PATCH 07/27] Add new features to example.pantheon.yml - Nested DOCROOT (web_root) - protected_web_paths - php_version New Quicksilver Hooks: * Site creation (deploy_product) * Multidev creation (create_cloud_development_environment) Hold for release --- example.pantheon.yml | 56 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/example.pantheon.yml b/example.pantheon.yml index 6430992..c1a3d8a 100644 --- a/example.pantheon.yml +++ b/example.pantheon.yml @@ -1,20 +1,52 @@ --- api_version: 1 +# PHP Version: +# https://pantheon.io/docs/pantheon-yml#php-version +# Set site's PHP version to 7.0 +php_version: 7.0 + +# Protected Web Paths +# https://pantheon.io/docs/pantheon-yml#protected-web-paths +protected_web_paths: + - /example.txt + - /example_directory + + +# Nested Docroot +# https://pantheon.io/docs/pantheon-yml#nested-docroot +web_docroot: true + +# Quicksilver Platform Integration Hooks +# https://pantheon.io/docs/pantheon-yml#quicksilver workflows: - # Commits: Notify team of new commit to master (dev) + # Site Creation + deploy_product: + after: + - type: webphp + description: Post to Slack after site creation + script: private/scripts/slack_after_site_creation.php + + # Multidev Creation + create_cloud_development_environment: + after: + - type: webphp + description: Post to Slack after Multidev creation + script: private/scripts/slack_after_multidev_creation.php + + # Commits sync_code: after: - type: webphp - description: post to slack after each code pushed + description: Post to Slack after each code pushed script: private/scripts/slack_after_code_push.php - # Database Clones: Notify, sanitize, generate content, and notify on db clone + # Database Clones clone_database: before: - type: webphp - description: post to slack before cloning the database + description: Post to Slack before cloning the database script: private/scripts/slack_before_db_clone.php after: - type: webphp @@ -24,19 +56,19 @@ workflows: description: generate development article content after the database clones script: private/scripts/generate_dev_content.php - type: webphp - description: post to slack after the database clones + description: Post to Slack after the database clones script: private/scripts/slack_after_db_clone.php - # Code Deploys: Notify, Sanitize (if on test), post to new relic, update db, and notify completion + # Code Deploys: Notify, Sanitize (if on test), Post to new relic, update db, and notify completion deploy: before: - type: webphp - description: post to slack before cloning the database + description: Post to Slack before cloning the database script: private/scripts/slack_before_deploy.php after: - type: webphp - description: post to new relic always - script: private/scripts/post_new_relic.php + description: Post to new relic always + script: private/scripts/Post_new_relic.php - type: webphp description: sanitize the db after deploy to test script: private/scripts/sanitize_after_db_clone.php @@ -50,12 +82,12 @@ workflows: description: do a visual regression test with Backtrac.io script: private/scripts/backtrac_visualregression.php - type: webphp - description: post to slack after each deploy + description: Post to Slack after each deploy script: private/scripts/slack_after_deploy.php - # Cache Clears: Post to slack after clearing cache + # Cache Clears: Post to Slack after clearing cache clear_cache: after: - type: webphp - description: post to slack after cache clear + description: Post to Slack after cache clear script: private/scripts/slack_after_clear_cache.php From 2f36d22aa7d7c008a1e9ba7a20fc4e2139003763 Mon Sep 17 00:00:00 2001 From: ataylorme Date: Thu, 18 Aug 2016 09:21:34 -0500 Subject: [PATCH 08/27] Add Solr Power indexing on multidev creation example --- solr_index/README.md | 29 +++++++++++++++++++++++++++++ solr_index/solr_power_index.php | 9 +++++++++ 2 files changed, 38 insertions(+) create mode 100644 solr_index/README.md create mode 100644 solr_index/solr_power_index.php diff --git a/solr_index/README.md b/solr_index/README.md new file mode 100644 index 0000000..b789394 --- /dev/null +++ b/solr_index/README.md @@ -0,0 +1,29 @@ +# Solr Power Indexing on Multidev Creation # + +When you create a new multidev environment the code, files and database are cloned but not the Solr instance. This script will re-index Solr using WP-CLI and the [Solr Power WordPress](https://github.com/pantheon-systems/solr-power) plugin. + +## Instructions ## + +1. Install and activate the Solr Power WordPress plugin in the dev environment. +2. Add the example `solr_power_index.php` script to the `private/scripts` directory in the root of your site's codebase, that is under version control. +3. Add the Quicksilver operations to your `pantheon.yml`. +4. Deploy `pantheon.yml` to the dev environment. +5. Create a new multidev instance + * Optionally run `terminus workflows watch` locally to get feedback from the Quicksilver script. +6. After indexing completes, test out search or other items using Solr. + +### Example `pantheon.yml` ### + +Here's an example of what your `pantheon.yml` would look like if this were the only Quicksilver operation you wanted to use. + +```yaml +api_version: 1 + +workflows: + create_cloud_development_environment: + after: + - type: webphp + description: Index Solr Power items after multidev creation + script: private/scripts/solr_power_index.php +``` + diff --git a/solr_index/solr_power_index.php b/solr_index/solr_power_index.php new file mode 100644 index 0000000..8e72ab4 --- /dev/null +++ b/solr_index/solr_power_index.php @@ -0,0 +1,9 @@ + Date: Fri, 19 Aug 2016 16:13:38 -0500 Subject: [PATCH 09/27] Adding new_relic_apdex_t typo fix Updating yml example title fix --- new_relic_apdex_t/README.md | 67 +++++++++++++ new_relic_apdex_t/new_relic_apdex_t.php | 119 ++++++++++++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 new_relic_apdex_t/README.md create mode 100644 new_relic_apdex_t/new_relic_apdex_t.php diff --git a/new_relic_apdex_t/README.md b/new_relic_apdex_t/README.md new file mode 100644 index 0000000..a45a668 --- /dev/null +++ b/new_relic_apdex_t/README.md @@ -0,0 +1,67 @@ +# Set New Relic Apdex T values on Multidev Creation # + + +[All sites on Pantheon include access to New Relic APM Pro](https://pantheon.io/features/new-relic). This application performance monitoring relies on the site owners setting time benchmark to measure against. Ideally, your Drupal or WordPress responds quickly to requests. And if the site is not responding quickly, New Relic can alert you. + +The question is, where do you want to set the bar? By default, New Relic uses 0.5 as the target number of seconds. This value is called "T" in the [Apdex (Application Performance Index) formula](https://docs.newrelic.com/docs/apm/new-relic-apm/apdex/apdex-measuring-user-satisfaction). + +In addition to monitoring how fast the server (Drupal or WordPress) respond, New Relic can monitor how fast real world browsers render your site. Browser performance is measured with the same Apdex formula. By default, New Relic uses a much more generous 7 seconds as the T value in browser Apdex. + +We recommend that any team working on a site discuss expectations for server-side and client-side performance and set T values accordingly. As you are developing new features with [Pantheon Multidev,](https://pantheon.io/features/multidev-cloud-environments) you might even want the Multidev environments to have more stringent T values than Test or Live environments. + +This Quicksilver example shows how you can set custom T values for Multidev environments when they are created. Otherwise each environment will use the default values of 0.5 and 7 for server and browser respectively. + +To do the actual setting of default values this script first gets an API key and then uses that key to interact with New Relic's REST API to set a T values. The main section of code you need to worry about though is just the variables at the top of the file. + +## Instructions ## + +To use this example: + +1. [Activate New Relic Pro](https://pantheon.io/docs/new-relic/#activate-new-relic-pro) within your site dashboard. +2. Add the example `new_relic_apdex_t.php` script to the `private` directory of your code repository. +3. Modify the variables at the top of the file to be the threshold T values you want for your site. + +```php + +/** + * CHANGE THESE VARIABLES FOR YOUR OWN SITE. + */ +// The "t" value (number of seconds) for your server-side apdex. +// https://docs.newrelic.com/docs/apm/new-relic-apm/apdex/apdex-measuring-user-satisfaction +$app_apdex_threshold = 0.4; +// Do you want New Relic to add JavaScript to pages to analyze rendering time? +// https://newrelic.com/browser-monitoring +$enable_real_user_monitoring = TRUE; +// The "t" value (number of seconds) for browser apdex. (The "real user +// monitoring turned off or on with $enable_real_user_monitoring") +$end_user_apdex_threshold = 6; + + +``` + + +4. Add a Quicksilver operation to your `pantheon.yml` to fire the script after a deploy. (One gotcha is that this script cannot be the first or only script called as part of Multidev creation. Before the New Relic API recognizes the the Multidev environment, that environment needs to have received at least one previous request.) + + +### Example `pantheon.yml` ### + +Here's an example of what your `pantheon.yml` would look like if this were the only Quicksilver operation you wanted to use: + +```yaml +api_version: 1 + +workflows: + create_cloud_development_environment: + after: + # The setting of Apdex cannot be the first traffic the new Multidev environment + # receives. A New Relic application ID is not available until after the + # environment receives some traffic. So run another script prior to calling + # new_relic_apdex_t.php. In this case drush_config_import.php is an + # arbitrary example. + - type: webphp + description: Drush Config Import + script: private/scripts/drush_config_import.php + - type: webphp + description: Set Apdex T values + script: private/scripts/new_relic_apdex_t.php +``` diff --git a/new_relic_apdex_t/new_relic_apdex_t.php b/new_relic_apdex_t/new_relic_apdex_t.php new file mode 100644 index 0000000..a5bb812 --- /dev/null +++ b/new_relic_apdex_t/new_relic_apdex_t.php @@ -0,0 +1,119 @@ + [ + 'name' => $app_name, + 'settings' => [ + 'app_apdex_threshold' => $app_apdex_threshold, + 'end_user_apdex_threshold' => $end_user_apdex_threshold, + 'enable_real_user_monitoring' => $enable_real_user_monitoring, + ], + ], + ]; + + $data_json = json_encode($settings); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); + $headers = [ + 'X-API-KEY:' . $api_key, + 'Content-Type: application/json' + ]; + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + $result = curl_exec($ch); + if (curl_errno($ch)) { + echo 'Error:' . curl_error($ch); + } + curl_close ($ch); +} + +?> From 32f89df1c6f7893a6f02c5aeea793fe8d8b0d666 Mon Sep 17 00:00:00 2001 From: Steve Persch Date: Fri, 19 Aug 2016 16:45:31 -0500 Subject: [PATCH 10/27] Whitespace fix --- new_relic_apdex_t/README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/new_relic_apdex_t/README.md b/new_relic_apdex_t/README.md index a45a668..0658f1a 100644 --- a/new_relic_apdex_t/README.md +++ b/new_relic_apdex_t/README.md @@ -22,7 +22,6 @@ To use this example: 3. Modify the variables at the top of the file to be the threshold T values you want for your site. ```php - /** * CHANGE THESE VARIABLES FOR YOUR OWN SITE. */ @@ -36,7 +35,6 @@ $enable_real_user_monitoring = TRUE; // monitoring turned off or on with $enable_real_user_monitoring") $end_user_apdex_threshold = 6; - ``` From a68b6080196b6d8be253d8c4a1fa6c968741e609 Mon Sep 17 00:00:00 2001 From: ataylorme Date: Mon, 22 Aug 2016 15:04:20 -0500 Subject: [PATCH 11/27] Fetch app name from Pantheon; Pull apdex_t from existing New Relic settings --- new_relic_apdex_t/new_relic_apdex_t.php | 180 +++++++++++++++--------- 1 file changed, 115 insertions(+), 65 deletions(-) diff --git a/new_relic_apdex_t/new_relic_apdex_t.php b/new_relic_apdex_t/new_relic_apdex_t.php index a5bb812..31f526e 100644 --- a/new_relic_apdex_t/new_relic_apdex_t.php +++ b/new_relic_apdex_t/new_relic_apdex_t.php @@ -5,115 +5,165 @@ * Sets New Relic Apdex T values for newly created multidev environments. */ -/** - * CHANGE THESE VARIABLES FOR YOUR OWN SITE. - */ +// get New Relic info from the dev environment +// Change to test or live as you wish +$app_info = get_app_info( 'dev' ); + +$settings = $app_info['settings']; + // The "t" value (number of seconds) for your server-side apdex. // https://docs.newrelic.com/docs/apm/new-relic-apm/apdex/apdex-measuring-user-satisfaction -$app_apdex_threshold = 0.4; +$app_apdex_threshold = $app_info['settings']['app_apdex_threshold']; // Do you want New Relic to add JavaScript to pages to analyze rendering time? // https://newrelic.com/browser-monitoring -$enable_real_user_monitoring = TRUE; +$enable_real_user_monitoring = $app_info['settings']['enable_real_user_monitoring']; // The "t" value (number of seconds) for browser apdex. (The "real user // monitoring turned off or on with $enable_real_user_monitoring") -$end_user_apdex_threshold = 6; - - -// Do not change these variables. -$site_name = $_SERVER['PANTHEON_SITE_NAME']; -$env = $_SERVER['PANTHEON_ENVIRONMENT']; -$app_name = $site_name . " ($env)"; - -set_thresholds($app_apdex_threshold, $end_user_apdex_threshold, $enable_real_user_monitoring, $app_name); +$end_user_apdex_threshold = $app_info['settings']['end_user_apdex_threshold']; +set_thresholds( $app_apdex_threshold, $end_user_apdex_threshold, $enable_real_user_monitoring ); /** * Gets the New Relic API Key so that further requests can be made. */ -function get_api_key() { - $return = ''; - $req = pantheon_curl('https://api.live.getpantheon.com/sites/self/bindings?type=newrelic', NULL, 8443); - $meta = json_decode($req['body'], true); - - foreach($meta as $data) { - if ($data['environment'] === PANTHEON_ENVIRONMENT && !empty($data['api_key'])) { - $return = $data['api_key']; - break; +function get_nr_connection_info() { + $output = array(); + $req = pantheon_curl( 'https://api.live.getpantheon.com/sites/self/bindings?type=newrelic', null, 8443 ); + $meta = json_decode( $req['body'], true ); + + foreach ( $meta as $data ) { + if ( $data['environment'] === PANTHEON_ENVIRONMENT ) { + if ( empty( $data['api_key'] ) ) { + echo "Failed to get API Key\n"; + + return; + } + $output['api_key'] = $data['api_key']; + + if ( empty( $data['app_name'] ) ) { + echo "Failed to get app name\n"; + + return; + } + $output['app_name'] = $data['app_name']; } } - return $return; -}; + + return $output; +} /** * Get the id of the current multidev environment. */ -function get_app_id($api_key, $app_name) { +function get_app_id( $api_key, $app_name ) { $return = ''; - $s = curl_init(); - curl_setopt($s,CURLOPT_URL,'https://api.newrelic.com/v2/applications.json'); - curl_setopt($s,CURLOPT_HTTPHEADER,array('X-API-KEY:' . $api_key)); - curl_setopt($s,CURLOPT_RETURNTRANSFER,1); - $result = curl_exec($s); - curl_close($s); + $s = curl_init(); + curl_setopt( $s, CURLOPT_URL, 'https://api.newrelic.com/v2/applications.json' ); + curl_setopt( $s, CURLOPT_HTTPHEADER, array( 'X-API-KEY:' . $api_key ) ); + curl_setopt( $s, CURLOPT_RETURNTRANSFER, 1 ); + $result = curl_exec( $s ); + curl_close( $s ); - $result = json_decode($result, true); + $result = json_decode( $result, true ); - foreach ($result['applications'] as $application) { - if ($application['name'] === $app_name ) { + foreach ( $result['applications'] as $application ) { + if ( $application['name'] === $app_name ) { $return = $application['id']; break; } } + return $return; } +function get_app_info( $env = 'dev' ) { + $nr_connection_info = get_nr_connection_info(); + if ( empty( $nr_connection_info ) ) { + echo "Unable to get New Relic connection info\n"; + + return; + } + + $api_key = $nr_connection_info['api_key']; + $app_name = $nr_connection_info['app_name']; + + $app_id = get_app_id( $api_key, $app_name ); + + $url = "https://api.newrelic.com/v2/applications/$app_id.json"; + + $ch = curl_init(); + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + $headers = [ + 'X-API-KEY:' . $api_key + ]; + curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers ); + + $response = curl_exec( $ch ); + + if ( curl_errno( $ch ) ) { + echo 'Error:' . curl_error( $ch ); + } + + curl_close( $ch ); + + $output = json_decode( $response, true ); + + return $output['application']; +} + /** * Sets the apdex thresholds. */ -function set_thresholds($app_apdex_threshold, $end_user_apdex_threshold, $enable_real_user_monitoring, $app_name) { +function set_thresholds( $app_apdex_threshold, $end_user_apdex_threshold, $enable_real_user_monitoring ) { - $api_key = get_api_key(); - if (empty($api_key)) { - echo "Failed to get API Key"; - return; - } + $nr_connection_info = get_nr_connection_info(); + if ( empty( $nr_connection_info ) ) { + echo "Unable to get New Relic connection info\n"; - $app_id = get_app_id($api_key, $app_name); - if (empty($app_id)) { - echo "Failed to get app id"; return; } + $api_key = $nr_connection_info['api_key']; + $app_name = $nr_connection_info['app_name']; + + $app_id = get_app_id( $api_key, $app_name ); + + echo "===== Setting New Relic Values for the App '$app_name' =====\n"; + echo "Application Apdex Threshold: $app_apdex_threshold\n"; + echo "End User Apdex Threshold: $end_user_apdex_threshold\n"; + echo "Enable Real User Monitoring: $enable_real_user_monitoring\n"; + $url = 'https://api.newrelic.com/v2/applications/' . $app_id . '.json'; $settings = [ - 'application' => [ - 'name' => $app_name, - 'settings' => [ - 'app_apdex_threshold' => $app_apdex_threshold, - 'end_user_apdex_threshold' => $end_user_apdex_threshold, - 'enable_real_user_monitoring' => $enable_real_user_monitoring, + 'application' => [ + 'name' => $app_name, + 'settings' => [ + 'app_apdex_threshold' => $app_apdex_threshold, + 'end_user_apdex_threshold' => $end_user_apdex_threshold, + 'enable_real_user_monitoring' => $enable_real_user_monitoring, + ], ], - ], ]; - $data_json = json_encode($settings); + $data_json = json_encode( $settings ); $ch = curl_init(); - curl_setopt($ch, CURLOPT_URL, $url); - curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($ch, CURLOPT_POSTFIELDS, $data_json); - curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); + curl_setopt( $ch, CURLOPT_URL, $url ); + curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); + curl_setopt( $ch, CURLOPT_POSTFIELDS, $data_json ); + curl_setopt( $ch, CURLOPT_CUSTOMREQUEST, "PUT" ); $headers = [ - 'X-API-KEY:' . $api_key, - 'Content-Type: application/json' + 'X-API-KEY:' . $api_key, + 'Content-Type: application/json' ]; - curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); - $result = curl_exec($ch); - if (curl_errno($ch)) { - echo 'Error:' . curl_error($ch); + curl_setopt( $ch, CURLOPT_HTTPHEADER, $headers ); + $result = curl_exec( $ch ); + if ( curl_errno( $ch ) ) { + echo 'Error:' . curl_error( $ch ); } - curl_close ($ch); -} + curl_close( $ch ); -?> + echo "===== Finished Setting New Relic Values =====\n"; +} From 1abc75db1906b9bea742921d0ac4f4e69aa2ef3a Mon Sep 17 00:00:00 2001 From: ataylorme Date: Mon, 22 Aug 2016 15:09:07 -0500 Subject: [PATCH 12/27] Update README as hard-coded values for T score or no longer needed --- new_relic_apdex_t/README.md | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/new_relic_apdex_t/README.md b/new_relic_apdex_t/README.md index 0658f1a..6424da7 100644 --- a/new_relic_apdex_t/README.md +++ b/new_relic_apdex_t/README.md @@ -11,33 +11,23 @@ We recommend that any team working on a site discuss expectations for server-sid This Quicksilver example shows how you can set custom T values for Multidev environments when they are created. Otherwise each environment will use the default values of 0.5 and 7 for server and browser respectively. -To do the actual setting of default values this script first gets an API key and then uses that key to interact with New Relic's REST API to set a T values. The main section of code you need to worry about though is just the variables at the top of the file. +To do the actual setting of default values this script first gets an API key and then uses that key to interact with New Relic's REST API to set a T values based on the existing values from the dev (or test/live) environment. ## Instructions ## To use this example: 1. [Activate New Relic Pro](https://pantheon.io/docs/new-relic/#activate-new-relic-pro) within your site dashboard. -2. Add the example `new_relic_apdex_t.php` script to the `private` directory of your code repository. -3. Modify the variables at the top of the file to be the threshold T values you want for your site. +2. Add the example `new_relic_apdex_t.php` script to the `private/scripts` directory of your code repository. +3. Optionally, modify the environment to pull existing threshold T values from at the top of the file. This defaults to `dev` but can also be `test` or `live`. ```php -/** - * CHANGE THESE VARIABLES FOR YOUR OWN SITE. - */ -// The "t" value (number of seconds) for your server-side apdex. -// https://docs.newrelic.com/docs/apm/new-relic-apm/apdex/apdex-measuring-user-satisfaction -$app_apdex_threshold = 0.4; -// Do you want New Relic to add JavaScript to pages to analyze rendering time? -// https://newrelic.com/browser-monitoring -$enable_real_user_monitoring = TRUE; -// The "t" value (number of seconds) for browser apdex. (The "real user -// monitoring turned off or on with $enable_real_user_monitoring") -$end_user_apdex_threshold = 6; +// get New Relic info from the dev environment +// Change to test or live as you wish +$app_info = get_app_info( 'dev' ); ``` - 4. Add a Quicksilver operation to your `pantheon.yml` to fire the script after a deploy. (One gotcha is that this script cannot be the first or only script called as part of Multidev creation. Before the New Relic API recognizes the the Multidev environment, that environment needs to have received at least one previous request.) From 2c7a28ec24d78a239ecf58e35c065d80b604efcc Mon Sep 17 00:00:00 2001 From: Steve Persch Date: Tue, 23 Aug 2016 10:27:47 -0500 Subject: [PATCH 13/27] Update new_relic_apdex_t.php --- new_relic_apdex_t/new_relic_apdex_t.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/new_relic_apdex_t/new_relic_apdex_t.php b/new_relic_apdex_t/new_relic_apdex_t.php index 31f526e..c3dc824 100644 --- a/new_relic_apdex_t/new_relic_apdex_t.php +++ b/new_relic_apdex_t/new_relic_apdex_t.php @@ -76,6 +76,11 @@ function get_app_id( $api_key, $app_name ) { return $return; } +/** + * Get New Relic information about a given environment. + * + * Used to retrive T values for a pre-existing environment. + */ function get_app_info( $env = 'dev' ) { $nr_connection_info = get_nr_connection_info(); if ( empty( $nr_connection_info ) ) { From 2dcaad02828ced796f4bd8f44439d9c091ce06f9 Mon Sep 17 00:00:00 2001 From: Steve Persch Date: Tue, 23 Aug 2016 11:01:48 -0500 Subject: [PATCH 14/27] Bug fix in new_relic_apdex_t --- new_relic_apdex_t/new_relic_apdex_t.php | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/new_relic_apdex_t/new_relic_apdex_t.php b/new_relic_apdex_t/new_relic_apdex_t.php index c3dc824..43a4590 100644 --- a/new_relic_apdex_t/new_relic_apdex_t.php +++ b/new_relic_apdex_t/new_relic_apdex_t.php @@ -25,14 +25,16 @@ /** * Gets the New Relic API Key so that further requests can be made. + * + * Also gets New Relic's name for the given environment. */ -function get_nr_connection_info() { +function get_nr_connection_info( $env = 'dev' ) { $output = array(); $req = pantheon_curl( 'https://api.live.getpantheon.com/sites/self/bindings?type=newrelic', null, 8443 ); $meta = json_decode( $req['body'], true ); foreach ( $meta as $data ) { - if ( $data['environment'] === PANTHEON_ENVIRONMENT ) { + if ( $data['environment'] === $env ) { if ( empty( $data['api_key'] ) ) { echo "Failed to get API Key\n"; @@ -78,9 +80,9 @@ function get_app_id( $api_key, $app_name ) { /** * Get New Relic information about a given environment. - * + * * Used to retrive T values for a pre-existing environment. - */ + */ function get_app_info( $env = 'dev' ) { $nr_connection_info = get_nr_connection_info(); if ( empty( $nr_connection_info ) ) { @@ -122,7 +124,7 @@ function get_app_info( $env = 'dev' ) { */ function set_thresholds( $app_apdex_threshold, $end_user_apdex_threshold, $enable_real_user_monitoring ) { - $nr_connection_info = get_nr_connection_info(); + $nr_connection_info = get_nr_connection_info( PANTHEON_ENVIRONMENT ); if ( empty( $nr_connection_info ) ) { echo "Unable to get New Relic connection info\n"; From 7aaffef45ce01803cd1df3cf66799ae1173d9a80 Mon Sep 17 00:00:00 2001 From: ataylorme Date: Tue, 30 Aug 2016 15:50:49 -0500 Subject: [PATCH 15/27] Repost schema before indexing --- solr_index/solr_power_index.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/solr_index/solr_power_index.php b/solr_index/solr_power_index.php index 8e72ab4..91beb4d 100644 --- a/solr_index/solr_power_index.php +++ b/solr_index/solr_power_index.php @@ -1,4 +1,8 @@ Date: Tue, 30 Aug 2016 17:09:26 -0500 Subject: [PATCH 16/27] Clarify WordPress for this example --- wp_solr_index/README.md | 29 +++++++++++++++++++++++++++ wp_solr_index/wp_solr_power_index.php | 13 ++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 wp_solr_index/README.md create mode 100644 wp_solr_index/wp_solr_power_index.php diff --git a/wp_solr_index/README.md b/wp_solr_index/README.md new file mode 100644 index 0000000..a0f64af --- /dev/null +++ b/wp_solr_index/README.md @@ -0,0 +1,29 @@ +# Solr Power Indexing on Multidev Creation for WordPress # + +When you create a new multidev environment the code, files and database are cloned but not the Solr instance. This script will re-index Solr using WP-CLI and the [Solr Power WordPress](https://github.com/pantheon-systems/solr-power) plugin. + +## Instructions ## + +1. Install and activate the Solr Power WordPress plugin in the dev environment. +2. Add the example `solr_power_index.php` script to the `private/scripts` directory in the root of your site's codebase, that is under version control. +3. Add the Quicksilver operations to your `pantheon.yml`. +4. Deploy `pantheon.yml` to the dev environment. +5. Create a new multidev instance + * Optionally run `terminus workflows watch` locally to get feedback from the Quicksilver script. +6. After indexing completes, test out search or other items using Solr. + +### Example `pantheon.yml` ### + +Here's an example of what your `pantheon.yml` would look like if this were the only Quicksilver operation you wanted to use. + +```yaml +api_version: 1 + +workflows: + create_cloud_development_environment: + after: + - type: webphp + description: Index Solr Power items after multidev creation + script: private/scripts/wp_solr_power_index.php +``` + diff --git a/wp_solr_index/wp_solr_power_index.php b/wp_solr_index/wp_solr_power_index.php new file mode 100644 index 0000000..91beb4d --- /dev/null +++ b/wp_solr_index/wp_solr_power_index.php @@ -0,0 +1,13 @@ + Date: Tue, 30 Aug 2016 18:45:34 -0500 Subject: [PATCH 17/27] Remove duplicate directory --- solr_index/README.md | 29 ----------------------------- solr_index/solr_power_index.php | 13 ------------- 2 files changed, 42 deletions(-) delete mode 100644 solr_index/README.md delete mode 100644 solr_index/solr_power_index.php diff --git a/solr_index/README.md b/solr_index/README.md deleted file mode 100644 index b789394..0000000 --- a/solr_index/README.md +++ /dev/null @@ -1,29 +0,0 @@ -# Solr Power Indexing on Multidev Creation # - -When you create a new multidev environment the code, files and database are cloned but not the Solr instance. This script will re-index Solr using WP-CLI and the [Solr Power WordPress](https://github.com/pantheon-systems/solr-power) plugin. - -## Instructions ## - -1. Install and activate the Solr Power WordPress plugin in the dev environment. -2. Add the example `solr_power_index.php` script to the `private/scripts` directory in the root of your site's codebase, that is under version control. -3. Add the Quicksilver operations to your `pantheon.yml`. -4. Deploy `pantheon.yml` to the dev environment. -5. Create a new multidev instance - * Optionally run `terminus workflows watch` locally to get feedback from the Quicksilver script. -6. After indexing completes, test out search or other items using Solr. - -### Example `pantheon.yml` ### - -Here's an example of what your `pantheon.yml` would look like if this were the only Quicksilver operation you wanted to use. - -```yaml -api_version: 1 - -workflows: - create_cloud_development_environment: - after: - - type: webphp - description: Index Solr Power items after multidev creation - script: private/scripts/solr_power_index.php -``` - diff --git a/solr_index/solr_power_index.php b/solr_index/solr_power_index.php deleted file mode 100644 index 91beb4d..0000000 --- a/solr_index/solr_power_index.php +++ /dev/null @@ -1,13 +0,0 @@ - Date: Wed, 7 Sep 2016 19:43:37 -0400 Subject: [PATCH 18/27] Update slack_notification.php --- slack_notification/slack_notification.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 3c6fcf1..69fba37 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -3,7 +3,7 @@ // Important constants :) $pantheon_yellow = '#EFD01B'; -// Default values for parameters +// Default values for parameters - Be sure to update the channel to an active channel in your Slack! $defaults = array( 'slack_channel' => '#quicksilver', 'slack_username' => 'Pantheon-Quicksilver', From b062424c2f9642fe82588da71a95484b51d5d693 Mon Sep 17 00:00:00 2001 From: Ariel Gold Date: Fri, 16 Sep 2016 15:54:43 -0700 Subject: [PATCH 19/27] Add drush_version to example.pantheon.yml --- example.pantheon.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/example.pantheon.yml b/example.pantheon.yml index c1a3d8a..59f36b5 100644 --- a/example.pantheon.yml +++ b/example.pantheon.yml @@ -6,13 +6,16 @@ api_version: 1 # Set site's PHP version to 7.0 php_version: 7.0 +# Drush Version +# https://pantheon.io/docs/pantheon-yml/#drush-version +drush_version: 8 + # Protected Web Paths # https://pantheon.io/docs/pantheon-yml#protected-web-paths protected_web_paths: - /example.txt - /example_directory - # Nested Docroot # https://pantheon.io/docs/pantheon-yml#nested-docroot web_docroot: true From c17051c02bfa61a344abbfb03e267e1389b3d83f Mon Sep 17 00:00:00 2001 From: Josh Koenig Date: Thu, 29 Sep 2016 12:37:40 -0700 Subject: [PATCH 20/27] Update README.md --- new_relic_deploy/README.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/new_relic_deploy/README.md b/new_relic_deploy/README.md index b5075a2..cdeaefb 100644 --- a/new_relic_deploy/README.md +++ b/new_relic_deploy/README.md @@ -22,12 +22,25 @@ Optionally, you may want to use the `terminus workflows watch` command to get im Here's an example of what your `pantheon.yml` would look like if this were the only Quicksilver operation you wanted to use: ```yaml +# Always need to specify the pantheon.yml API version. api_version: 1 +# You might also want some of the following here: +# php_version: 7.0 +# drush_version: 8 + workflows: + # Log to New Relic when deploying to test or live. deploy: after: - type: webphp description: Log to New Relic script: private/scripts/new_relic_deploy.php + # Also log sync_code so you can track new code going into dev/multidev. + sync_code: + after: + - type: webphp + description: Log to New Relic + script: private/scripts/new_relic_deploy.php + ``` From a3700b329f9e97ad8fd8f2bf5c99214136c3f2b2 Mon Sep 17 00:00:00 2001 From: Josh Koenig Date: Thu, 29 Sep 2016 12:40:40 -0700 Subject: [PATCH 21/27] Add newrelic_ignore_transaction() --- new_relic_deploy/new_relic_deploy.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/new_relic_deploy/new_relic_deploy.php b/new_relic_deploy/new_relic_deploy.php index 503b859..b06b936 100644 --- a/new_relic_deploy/new_relic_deploy.php +++ b/new_relic_deploy/new_relic_deploy.php @@ -1,4 +1,11 @@ Date: Tue, 18 Oct 2016 14:41:14 -0400 Subject: [PATCH 22/27] Fix spelling of "snippet" in new_relic_deploy --- new_relic_deploy/new_relic_deploy.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/new_relic_deploy/new_relic_deploy.php b/new_relic_deploy/new_relic_deploy.php index b06b936..843c98f 100644 --- a/new_relic_deploy/new_relic_deploy.php +++ b/new_relic_deploy/new_relic_deploy.php @@ -1,6 +1,6 @@ Date: Sun, 23 Oct 2016 09:56:59 -0700 Subject: [PATCH 23/27] fixing a minor typo in description --- generate_dev_content/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_dev_content/README.md b/generate_dev_content/README.md index c7ac7d6..1c4691b 100644 --- a/generate_dev_content/README.md +++ b/generate_dev_content/README.md @@ -23,7 +23,7 @@ workflows: clone_database: after: - type: webphp - description: enerate development article content after the database clones + description: Generate development article content after the database clones script: private/scripts/generate_dev_content.php ``` From 27a3251eb68462e484b30a240dca00ba2f23a92c Mon Sep 17 00:00:00 2001 From: Josh Koenig Date: Wed, 16 Nov 2016 09:46:30 -0800 Subject: [PATCH 24/27] Improve message format so default Specifying a channel can mean the default one from the webhook isn't used. Also link to some spiffy new docs they have. --- slack_notification/slack_notification.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 69fba37..31bd4bd 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -3,9 +3,10 @@ // Important constants :) $pantheon_yellow = '#EFD01B'; -// Default values for parameters - Be sure to update the channel to an active channel in your Slack! +// Default values for parameters - this will assume the channel you define the webhook for. +// The full Slack Message API allows you to specify other channels and enhance the messagge further +// if you like: https://api.slack.com/docs/messages/builder $defaults = array( - 'slack_channel' => '#quicksilver', 'slack_username' => 'Pantheon-Quicksilver', 'always_show_text' => false, ); From 6bb4a3b01b15dda41789db0517684857abe4b3d0 Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:12:20 -0700 Subject: [PATCH 25/27] 'Title' uses better formatting than pretext in Slack Attachments. Emojis display as well. --- slack_notification/slack_notification.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 31bd4bd..01b48d4 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -105,7 +105,7 @@ $attachment = array( 'fallback' => $text, - 'pretext' => 'Deploying :rocket:', + 'title' => 'Deploying :rocket:', 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code 'fields' => $fields ); From 0a4cf3daae51b63de4f9e8e30bfe04812106c4a2 Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:19:55 -0700 Subject: [PATCH 26/27] Slack Attachments Title should really be set per-case --- slack_notification/slack_notification.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 01b48d4..4fc9244 100644 --- a/slack_notification/slack_notification.php +++ b/slack_notification/slack_notification.php @@ -54,6 +54,9 @@ $deploy_tag = `git describe --tags`; $deploy_message = $_POST['deploy_message']; + // Set a Slack Attachments title + $title = 'Deploying :rocket:'; + // Prepare the slack payload as per: // https://api.slack.com/incoming-webhooks $text = 'Deploy to the '. $_ENV['PANTHEON_ENVIRONMENT']; @@ -77,6 +80,9 @@ $message = `git log -1 --pretty=%B`; $hash = `git log -1 --pretty=%h`; + // Set a Slack Attachments title + $title = 'Syncing code :fax:'; + // Prepare the slack payload as per: // https://api.slack.com/incoming-webhooks $text = 'Code sync to the ' . $_ENV['PANTHEON_ENVIRONMENT'] . ' environment of ' . $_ENV['PANTHEON_SITE_NAME'] . ' by ' . $_POST['user_email'] . "!\n"; @@ -105,7 +111,7 @@ $attachment = array( 'fallback' => $text, - 'title' => 'Deploying :rocket:', + 'title' => $title, 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code 'fields' => $fields ); From 3592e4d0c0d8a84bf1f2ff5fc292142ce7da538d Mon Sep 17 00:00:00 2001 From: Jordan Ryan Date: Thu, 12 May 2016 22:53:11 -0700 Subject: [PATCH 27/27] Drush Site Audit on deploy. * @TODO: Duplicate to HipChat * This is implemented as a separate script, didn't want to assume everyone would ALWAYS want to run the site audit. Also this report is quite verbose, so I think people should opt-in if they want to pollute their Slack channel. * This is grouped under /slack_notification example, but could be arguably moved to it's own example as drush_site_audit or something similar. Concern there is duplicating Slack notification markup further. Makes me think a slack_helper.php would be easier to include basic functionality across multiple scripts/quicksilver workflow tasks. --- .../slack_notify_drush_site_audit.php | 133 ++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 slack_notification/slack_notify_drush_site_audit.php diff --git a/slack_notification/slack_notify_drush_site_audit.php b/slack_notification/slack_notify_drush_site_audit.php new file mode 100644 index 0000000..8f386e3 --- /dev/null +++ b/slack_notification/slack_notify_drush_site_audit.php @@ -0,0 +1,133 @@ + '#quicksilver', + 'slack_username' => 'Pantheon-Quicksilver', + 'always_show_text' => false, +); + +// Load our hidden credentials. +// See the README.md for instructions on storing secrets. +$secrets = _get_secrets(array('slack_url'), $defaults); + +// Build an array of fields to be rendered with Slack Attachments as a table +// attachment-style formatting: +// https://api.slack.com/docs/attachments +$fields = array( + array( + 'title' => 'Site', + 'value' => $_ENV['PANTHEON_SITE_NAME'], + 'short' => 'true' + ), + array( // Render Environment name with link to site, + 'title' => 'Environment', + 'value' => '', + 'short' => 'true' + ), + array( // Render Name with link to Email from Commit message + 'title' => 'By', + 'value' => $_POST['user_email'], + 'short' => 'true' + ), + array( // Render workflow phase that the message was sent + 'title' => 'Workflow', + 'value' => ucfirst($_POST['stage']) . ' ' . str_replace('_', ' ', $_POST['wf_type']), + 'short' => 'true' + ), + array( + 'title' => 'View Dashboard', + 'value' => '', + 'short' => 'true' + ), +); + +// Set a Slack Attachments title +$title = 'Post-Deploy Site Audit :helmet_with_white_cross:'; + +// Prepare the slack payload as per: +// https://api.slack.com/incoming-webhooks +$text = 'Site Audit Report after deployment to the *'. $_ENV['PANTHEON_ENVIRONMENT']; +$text .= ' environment of '. $_ENV['PANTHEON_SITE_NAME'] .' by '. $_POST['user_email'] .' complete!'; +$text .= ' '; +$text .= "\n\n*SITE AUDIT REPORT*: \n\n$site_audit_all"; +// No need to render Site Audit All as a slack attachment, +// full report is cut off due to character limit + +$attachment = array( + 'fallback' => $text, + 'title' => $title, + 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code + 'fields' => $fields, + 'text' => $site_audit_all +); + +_slack_notification($secrets['slack_url'], $secrets['slack_channel'], $secrets['slack_username'], $text, $attachment, $secrets['always_show_text']); + + +/** + * Get secrets from secrets file. + * + * @param array $requiredKeys List of keys in secrets file that must exist. + */ +function _get_secrets($requiredKeys, $defaults) +{ + $secretsFile = $_SERVER['HOME'] . '/files/private/secrets.json'; + if (!file_exists($secretsFile)) { + die('No secrets file found. Aborting!'); + } + $secretsContents = file_get_contents($secretsFile); + $secrets = json_decode($secretsContents, 1); + if ($secrets == FALSE) { + die('Could not parse json in secrets file. Aborting!'); + } + $secrets += $defaults; + $missing = array_diff($requiredKeys, array_keys($secrets)); + if (!empty($missing)) { + die('Missing required keys in json secrets file: ' . implode(',', $missing) . '. Aborting!'); + } + return $secrets; +} + +/** + * Send a notification to slack + */ +function _slack_notification($slack_url, $channel, $username, $text, $attachment, $alwaysShowText = false) +{ + $attachment['fallback'] = $text; + $post = array( + 'username' => $username, + 'channel' => $channel, + 'icon_emoji' => ':lightning_cloud:', + 'attachments' => array($attachment) + ); + if ($alwaysShowText) { + $post['text'] = $text; + } + $payload = json_encode($post); + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $slack_url); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($ch, CURLOPT_TIMEOUT, 5); + curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + curl_setopt($ch, CURLOPT_POSTFIELDS, $payload); + // Watch for messages with `terminus workflows watch --site=SITENAME` + print("\n==== Posting to Slack ====\n"); + $result = curl_exec($ch); + print("RESULT: $result"); + // $payload_pretty = json_encode($post,JSON_PRETTY_PRINT); // Uncomment to debug JSON + // print("JSON: $payload_pretty"); // Uncomment to Debug JSON + print("\n===== Post Complete! =====\n"); + curl_close($ch); +}