diff --git a/example.pantheon.yml b/example.pantheon.yml index 6430992..59f36b5 100644 --- a/example.pantheon.yml +++ b/example.pantheon.yml @@ -1,20 +1,55 @@ --- 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 + +# 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 + +# 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 +59,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 +85,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 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 ``` diff --git a/new_relic_apdex_t/README.md b/new_relic_apdex_t/README.md new file mode 100644 index 0000000..6424da7 --- /dev/null +++ b/new_relic_apdex_t/README.md @@ -0,0 +1,55 @@ +# 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 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/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 +// 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.) + + +### 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..43a4590 --- /dev/null +++ b/new_relic_apdex_t/new_relic_apdex_t.php @@ -0,0 +1,176 @@ + [ + '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 ); + + echo "===== Finished Setting New Relic Values =====\n"; +} diff --git a/new_relic_deploy/README.md b/new_relic_deploy/README.md index f7abfc0..cdeaefb 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! @@ -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 + ``` diff --git a/new_relic_deploy/new_relic_deploy.php b/new_relic_deploy/new_relic_deploy.php index a829265..843c98f 100644 --- a/new_relic_deploy/new_relic_deploy.php +++ b/new_relic_deploy/new_relic_deploy.php @@ -1,11 +1,17 @@ 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: diff --git a/slack_notification/slack_notification.php b/slack_notification/slack_notification.php index 3c6fcf1..4fc9244 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 +// 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, ); @@ -53,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']; @@ -76,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"; @@ -104,7 +111,7 @@ $attachment = array( 'fallback' => $text, - 'pretext' => 'Deploying :rocket:', + 'title' => $title, 'color' => $pantheon_yellow, // Can either be one of 'good', 'warning', 'danger', or any hex color code 'fields' => $fields ); 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); +} 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 @@ +