From 73c70a718c4585d4196e2e83f4cd85f14e6544bf Mon Sep 17 00:00:00 2001 From: Eric Bidelman Date: Fri, 31 Mar 2017 15:09:52 -0700 Subject: [PATCH] Travis Lighthouse setup --- .gitignore | 1 + .travis.yml | 27 ++++++++ gcloud-client-secret.json.enc | Bin 0 -> 2352 bytes package.json | 3 +- travis/deploy_pr_gae.sh | 32 ++++++++++ travis/install_google_cloud_sdk.sh | 21 +++++++ travis/package.json | 11 ++++ travis/runLighthouse.js | 95 +++++++++++++++++++++++++++++ 8 files changed, 189 insertions(+), 1 deletion(-) create mode 100644 .travis.yml create mode 100644 gcloud-client-secret.json.enc create mode 100755 travis/deploy_pr_gae.sh create mode 100755 travis/install_google_cloud_sdk.sh create mode 100644 travis/package.json create mode 100755 travis/runLighthouse.js diff --git a/.gitignore b/.gitignore index 27345d74d4c..c7035b3ac44 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ .sass-cache *oauth2.data node_modules +travis/node_modules *bower_components *.vulcanize.html *.vulcanize.js diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000000..ef9dfa68c78 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,27 @@ +language: node_js +node_js: '7' +dist: trusty +sudo: false +git: + depth: 1 +env: + global: + - CLOUDSDK_CORE_DISABLE_PROMPTS=1 + - CLOUDSDK_PYTHON_SITEPACKAGES=1 + - GAE_APP_ID=cr-status +cache: + directories: + - node_modules + - travis/node_modules +install: +- npm install -g bower gulp +- npm install +- npm run install-travis +script: +- npm run lint +- npm run build +after_success: +- "./travis/deploy_pr_gae.sh" +- export LH_MIN_PASS_SCORE=96 +- export LH_TEST_URL=https://lighthouse-ci-staging-dot-cr-status.appspot.com/features +- node travis/runLighthouse.js $LH_TEST_URL $LH_MIN_PASS_SCORE diff --git a/gcloud-client-secret.json.enc b/gcloud-client-secret.json.enc new file mode 100644 index 0000000000000000000000000000000000000000..1a7f18e7b221c7fcbf9692a9988eba0e315f316b GIT binary patch literal 2352 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.0.0" }, "scripts": { - "postinstall": "npm run deps; npm run build", + "postinstall": "npm run deps && npm run build", + "install-travis": "npm --prefix ./travis install ./travis", "deps": "rm -rf static/bower_components; bower install", "lint": "gulp lint", "build": "gulp", diff --git a/travis/deploy_pr_gae.sh b/travis/deploy_pr_gae.sh new file mode 100755 index 00000000000..d9c2ee9950c --- /dev/null +++ b/travis/deploy_pr_gae.sh @@ -0,0 +1,32 @@ +#!/bin/bash +set -e + +# Auto-Deploy Pull Request + +# If this isn't a pull request, abort. +if [ "${TRAVIS_EVENT_TYPE}" != "pull_request" ]; then + echo "This only runs on pull_request events. Event was $TRAVIS_EVENT_TYPE." + exit +fi + +# If there were build failures, abort +if [ "${TRAVIS_TEST_RESULT}" = "1" ]; then + echo "Deploy aborted, there were build/test failures." + exit +fi + +./travis/install_google_cloud_sdk.sh + +# Set the AppEngine version for staging +# VERSION=pr-$TRAVIS_PULL_REQUEST +VERSION=lighthouse-ci-staging + +# Determine staging URL based on PR. +export LH_TEST_URL=https://$VERSION-dot-$GAE_APP_ID.appspot.com/features +echo "Pull Request: $TRAVIS_PULL_REQUEST will be staged at $LH_TEST_URL" + +# Deploy to AppEngine +$HOME/google-cloud-sdk/bin/gcloud app deploy app.yaml -q --no-promote --version $VERSION + +# Make sure an AppEngine instance has started. +curl $LH_TEST_URL diff --git a/travis/install_google_cloud_sdk.sh b/travis/install_google_cloud_sdk.sh new file mode 100755 index 00000000000..2533f6a9181 --- /dev/null +++ b/travis/install_google_cloud_sdk.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +# Installs the Google Cloud SDK + +# Decrypt the Service Account Key +openssl aes-256-cbc -K $encrypted_aee7e38c959c_key -iv $encrypted_aee7e38c959c_iv \ + -in gcloud-client-secret.json.enc -out gcloud-client-secret.json -d + +# Download & install the Google Cloud SDK +curl https://sdk.cloud.google.com | bash + +# Update any necessary components +$HOME/google-cloud-sdk/bin/gcloud components update -q + +# Set the AppEngine App ID to $GAE_APP_ID +$HOME/google-cloud-sdk/bin/gcloud config set project $GAE_APP_ID + +# Authenticate to AppEngine using the service account +$HOME/google-cloud-sdk/bin/gcloud auth activate-service-account \ + --key-file gcloud-client-secret.json diff --git a/travis/package.json b/travis/package.json new file mode 100644 index 00000000000..b4f87358deb --- /dev/null +++ b/travis/package.json @@ -0,0 +1,11 @@ +{ + "name": "chrome-status-ci", + "version": "0.0.1", + "main": "index.js", + "license": "Apache-2.0", + "dependencies": { + "chalk": "^1.1.3", + "github": "^9.2.0", + "node-fetch": "^1.6.3" + } +} diff --git a/travis/runLighthouse.js b/travis/runLighthouse.js new file mode 100755 index 00000000000..d0206a93e6c --- /dev/null +++ b/travis/runLighthouse.js @@ -0,0 +1,95 @@ +/** + * Copyright 2017 Google Inc. All rights reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +'use strict'; + +const chalk = require('chalk'); +const fetch = require('node-fetch'); // polyfill + +const args = process.argv.slice(2); +const LH_TEST_URL = args[0]; +const LH_MIN_PASS_SCORE = args[1]; +const PR_NUM = process.env.TRAVIS_PULL_REQUEST; +const PR_SHA = process.env.TRAVIS_PULL_REQUEST_SHA; +const REPO_SLUG = process.env.TRAVIS_PULL_REQUEST_SLUG; + +const CI_HOST = 'https://lighthouse-ci.appspot.com'; +const API_KEY = process.env.API_KEY; +const RUNNERS = {chrome: 'chrome', wpt: 'wpt'}; + +/** + * @param {!string} runner Where to run Lighthouse. + */ +function run(runner) { + const data = { + testUrl: LH_TEST_URL, + minPassScore: Number(LH_MIN_PASS_SCORE), + repo: { + owner: REPO_SLUG.split('/')[0], + name: REPO_SLUG.split('/')[1] + }, + pr: { + number: parseInt(PR_NUM, 10), + sha: PR_SHA + } + }; + + let endpoint; + let body = JSON.stringify(data); + + switch (runner) { + case RUNNERS.wpt: + endpoint = `${CI_HOST}/run_on_wpt`; + break; + case RUNNERS.chrome: // same as default + default: + endpoint = `${CI_HOST}/run_on_chrome`; + body = JSON.stringify(Object.assign({format: 'json'}, data)); + } + + fetch(endpoint, { + method: 'POST', + body, + headers: { + 'Content-Type': 'application/json', + 'X-API-KEY': API_KEY // Keep usage tight for now. + } + }) + .then(resp => resp.json()) + .then(json => { + if (runner === RUNNERS.wpt) { + console.log(chalk.green( + `Started Lighthouse run on WebPageTest: ${json.data.target_url}`)); + return; + } + + let colorize = chalk.green; + if (json.score < LH_MIN_PASS_SCORE) { + colorize = chalk.red; + } + console.log(colorize('Lighthouse CI score:'), json.score); + }) + .catch(err => { + console.log(chalk.red('Lighthouse CI failed'), err); + process.exit(1); + }); +} + +// Run LH if this is a PR. +if (process.env.TRAVIS_EVENT_TYPE === 'pull_request') { + run(RUNNERS.wpt); +} else { + console.log('Lighthouse not run for non-PR commits'); +}