Repository: GoogleChrome/lighthouse
Pull request #10256 (2020-01-23 22:39:29)

misc(git3po): land-when-green


Patch:
diff --git a/.appveyor.yml b/.appveyor.yml
index 2e2804816..ecd6cde77 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -40,7 +40,6 @@ test_script:
   # run smoke tests serially, trying up to three times to prevent flakes.
   # FIXME: Exclude Appveyor from running `lantern` smoketest until we fix the flake.
   - yarn smoke -j=1 --retries=2 a11y errors oopif pwa pwa2 pwa3 dbw redirects seo offline byte perf metrics
-  - yarn test-docs
 
 cache:
   #- chrome-win32 -> appveyor.yml,package.json
diff --git a/.npmignore b/.npmignore
index 7c42d9dc7..3228964db 100644
--- a/.npmignore
+++ b/.npmignore
@@ -24,10 +24,12 @@ lighthouse-logger/
 # keep smokehouse tests, etc
 !lighthouse-cli/test
 
-node_modules/
 results/
 lantern-data/
-latest-run/
+
+# ignore all folders named as such
+node_modules
+latest-run
 
 # generated files
 **/pages/scripts/lighthouse-report.js
@@ -50,3 +52,4 @@ results.html
 .eslintignore
 .eslintrc.js
 .travis.yml
+*.tgz
\ No newline at end of file
diff --git a/build/build-pack.sh b/build/build-pack.sh
new file mode 100644
index 000000000..2877f33a9
--- /dev/null
+++ b/build/build-pack.sh
@@ -0,0 +1,12 @@
+#!/usr/bin/env bash
+
+DIRNAME="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+LH_ROOT="$DIRNAME/.."
+
+tmp_dir=$(mktemp -d -t lh-XXXXXXXXXX)
+
+cd "$tmp_dir"
+npm pack "$LH_ROOT"
+mv *.tgz "$LH_ROOT/dist/lighthouse.tgz"
+
+rmdir "$tmp_dir"
diff --git a/docs/recipes/auth/package.json b/docs/recipes/auth/package.json
index b632de6bb..d05fcb742 100644
--- a/docs/recipes/auth/package.json
+++ b/docs/recipes/auth/package.json
@@ -5,7 +5,7 @@
   "dependencies": {
     "express": "^4.17.1",
     "express-session": "^1.16.2",
-    "lighthouse": "file:../../..",
+    "lighthouse": "file:../../../dist/lighthouse.tgz",
     "morgan": "^1.9.1"
   }
 }
diff --git a/docs/recipes/custom-gatherer-puppeteer/custom-audit.js b/docs/recipes/custom-gatherer-puppeteer/custom-audit.js
new file mode 100644
index 000000000..1a640cbcf
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/custom-audit.js
@@ -0,0 +1,34 @@
+/**
+ * @license Copyright 2020 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 Audit = require('lighthouse').Audit;
+
+class CustomAudit extends Audit {
+  static get meta() {
+    return {
+      id: 'custom-audit',
+      title: 'First text input field accepts `123` as input',
+      failureTitle: 'First text input field doesn\'t accept `123` as input',
+      description: 'Example custom audit which relies on a fancy gatherer.',
+
+      // The name of the custom gatherer class that provides input to this audit.
+      requiredArtifacts: ['CustomGatherer'],
+    };
+  }
+
+  static audit(artifacts) {
+    const value = artifacts.CustomGatherer.value;
+    const success = value === '123';
+
+    return {
+      // Cast true/false to 1/0
+      score: Number(success),
+    };
+  }
+}
+
+module.exports = CustomAudit;
diff --git a/docs/recipes/custom-gatherer-puppeteer/custom-config.js b/docs/recipes/custom-gatherer-puppeteer/custom-config.js
new file mode 100644
index 000000000..47fbc0527
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/custom-config.js
@@ -0,0 +1,29 @@
+/**
+ * @license Copyright 2020 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';
+
+module.exports = {
+  passes: [{
+    passName: 'defaultPass',
+    gatherers: [
+      'custom-gatherer',
+    ],
+  }],
+
+  audits: [
+    'custom-audit',
+  ],
+
+  categories: {
+    mysite: {
+      title: 'My custom audit',
+      description: 'Super awesome, strings included',
+      auditRefs: [
+        {id: 'custom-audit', weight: 1},
+      ],
+    },
+  },
+};
diff --git a/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js b/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js
new file mode 100644
index 000000000..41373da8b
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/custom-gatherer.js
@@ -0,0 +1,51 @@
+/**
+ * @license Copyright 2020 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';
+
+/* global document */
+
+const Gatherer = require('lighthouse').Gatherer;
+const Puppeteer = require('puppeteer-core');
+
+async function connect(driver) {
+  const browser = await Puppeteer.connect({
+    browserWSEndpoint: await driver.wsEndpoint(),
+    defaultViewport: null,
+  });
+  const {targetInfo} = await driver.sendCommand('Target.getTargetInfo');
+  const puppeteerTarget = (await browser.targets())
+    .find(target => target._targetId === targetInfo.targetId);
+  const page = await puppeteerTarget.page();
+  return {browser, page};
+}
+
+class CustomGatherer extends Gatherer {
+  async afterPass(options) {
+    const {driver} = options;
+    const {page} = await connect(driver);
+
+    // Inject an input field for our debugging pleasure.
+    function makeInput() {
+      const el = document.createElement('input');
+      el.type = 'number';
+      document.body.append(el);
+    }
+    await driver.evaluateAsync(`(${makeInput})()`);
+    await new Promise(resolve => setTimeout(resolve, 100));
+
+    // Prove that `driver` (Lighthouse) and `page` (Puppeteer) are talking to the same page.
+    await driver.evaluateAsync(`document.querySelector('input').value = '1'`);
+    await page.type('input', '23', {delay: 300});
+    const value = await driver.evaluateAsync(`document.querySelector('input').value`);
+    if (value !== '123') throw new Error('huh?');
+
+    // No need to close the browser or page. Puppeteer doesn't own either of them.
+
+    return {value};
+  }
+}
+
+module.exports = CustomGatherer;
diff --git a/docs/recipes/custom-gatherer-puppeteer/package.json b/docs/recipes/custom-gatherer-puppeteer/package.json
new file mode 100644
index 000000000..f708a69fb
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/package.json
@@ -0,0 +1,13 @@
+{
+  "name": "custom-lighthouse-recipe",
+  "private": true,
+  "scripts": {
+    "test": "sh test.sh"
+  },
+  "devDependencies": {
+    "lighthouse": "file:../../../dist/lighthouse.tgz"
+  },
+  "dependencies": {
+    "puppeteer-core": "^2.0.0"
+  }
+}
diff --git a/docs/recipes/custom-gatherer-puppeteer/readme.md b/docs/recipes/custom-gatherer-puppeteer/readme.md
new file mode 100644
index 000000000..337953939
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/readme.md
@@ -0,0 +1,7 @@
+# Using Puppeteer in a Gatherer
+
+> **Tip**: see [Basic Custom Audit Recipe](../custom-audit) for basic information about custom audits.
+
+```sh
+lighthouse --config-path=custom-config.js https://www.example.com
+```
diff --git a/lighthouse-core/scripts/git3po-rules/land-when-green.yaml b/lighthouse-core/scripts/git3po-rules/land-when-green.yaml
new file mode 100644
index 000000000..0a210e259
--- /dev/null
+++ b/lighthouse-core/scripts/git3po-rules/land-when-green.yaml
@@ -0,0 +1,20 @@
+repo: GoogleChrome/lighthouse
+pullRequests: true
+filters:
+  - type: issue
+    criteria:
+      state: open
+      mergeable: true
+      mergeableState: clean
+  - type: label
+    label: land-when-ci-is-green
+actions:
+  - type: merge
+    # Squash all commits, leave commit message blank.
+    # The commit title (AKA first line of commit message) defaults to the PR title.
+    mergeMethod: squash
+    # Note: no `title`, so the default (PR title) is used.
+    # Disable the default squash message.
+    message: ''
+  - type: remove_label
+    label: land-when-ci-is-green
diff --git a/package.json b/package.json
index 8d23aafbe..e04d4906d 100644
--- a/package.json
+++ b/package.json
@@ -12,11 +12,12 @@
   },
   "scripts": {
     "build-all": "npm-run-posix-or-windows build-all:task",
-    "build-all:task": "yarn build-extension & yarn build-devtools & yarn build-lr & yarn build-viewer & wait",
+    "build-all:task": "(yarn build-extension & yarn build-devtools & yarn build-lr & yarn build-viewer & wait) && yarn build-pack",
     "build-all:task:windows": "yarn build-extension && yarn build-devtools && yarn build-lr && yarn build-viewer",
     "build-extension": "node ./build/build-extension.js",
     "build-devtools": "node ./build/build-bundle.js clients/devtools-entry.js dist/lighthouse-dt-bundle.js && node ./build/build-dt-report-resources.js",
     "build-lr": "node ./build/build-lightrider-bundles.js",
+    "build-pack": "bash build/build-pack.sh",
     "build-viewer": "node ./build/build-viewer.js",
     "clean": "rimraf dist proto/scripts/*.json proto/scripts/*_pb2.* proto/scripts/*_pb.* proto/scripts/__pycache__ proto/scripts/*.pyc *.report.html *.report.dom.html *.report.json *.devtoolslog.json *.trace.json lighthouse-core/lib/i18n/locales/*.ctc.json || true",
     "lint": "[ \"$CI\" = true ] && eslint --quiet -f codeframe . || eslint .",
@@ -28,7 +29,7 @@
     "test-clients": "jest \"clients/\"",
     "test-viewer": "yarn unit-viewer && jest lighthouse-viewer/test/viewer-test-pptr.js",
     "test-lantern": "bash lighthouse-core/scripts/test-lantern.sh",
-    "test-docs": "yarn --cwd docs/recipes/auth && jest docs/recipes/integration-test",
+    "test-docs": "yarn --cwd docs/recipes/auth && jest docs/recipes/integration-test && yarn --cwd docs/recipes/custom-gatherer-puppeteer test",
     "unit-core": "jest \"lighthouse-core/\"",
     "unit-cli": "jest \"lighthouse-cli/\"",
     "unit-viewer": "jest \"lighthouse-viewer/.*-test.js\"",
diff --git a/readme.md b/readme.md
index 91145b02e..65666229a 100644
--- a/readme.md
+++ b/readme.md
@@ -278,6 +278,13 @@ yarn smoke
 yarn type-check
 ```
 
+### Docs
+
+Some of our docs have tests that run only in CI by default. If you end up needing to modify our documentation, you'll need to run `yarn test-docs` locally to make sure they pass.
+
+**Additional Dependencies**
+- `brew install jq`
+
 ## Lighthouse Integrations
 This section details services that have integrated Lighthouse data. If you're working on a cool project integrating Lighthouse and would like to be featured here, file an issue to this repo or tweet at us [@_____lighthouse](https://twitter.com/____lighthouse?lang=en)!
 


Test patch:
diff --git a/docs/recipes/custom-gatherer-puppeteer/test.sh b/docs/recipes/custom-gatherer-puppeteer/test.sh
new file mode 100644
index 000000000..674135bb5
--- /dev/null
+++ b/docs/recipes/custom-gatherer-puppeteer/test.sh
@@ -0,0 +1,9 @@
+#!/usr/bin/env bash
+
+# Make sure we're in this `docs/recipes/customer-gatherer-puppeteer` directory
+cd "$(dirname "$0")"
+
+yarn
+node node_modules/.bin/lighthouse --config-path=custom-config.js https://www.example.com --output=json |
+  jq '.audits["custom-audit"].score' |
+  grep -q 1
diff --git a/docs/recipes/integration-test/package.json b/docs/recipes/integration-test/package.json
index bdcf37287..720f9cefd 100644
--- a/docs/recipes/integration-test/package.json
+++ b/docs/recipes/integration-test/package.json
@@ -4,6 +4,6 @@
   },
   "dependencies": {
     "jest": "^24.9.0",
-    "lighthouse": "file:../../.."
+    "lighthouse": "file:../../../dist/lighthouse.tgz"
   }
 }