ci: migrate to GitHub Actions from CircleCI, allow running Browserstack on forked repo via label (#2417)

* Remove CircleCI and codecov

* Add GitHub Actions workflow

* Add Browserstack credentials

* Skip tests if ci skip or skip ci is in commit messages

* Update and rename test.yml to ci.yml

* Postfix artifacts name with browser

* Disable proxy on chrome

* Update dockers/screenshotter/screenshotter.js

* Add status badge

* Set directory option in codecov action

* Run Browserstack on forked repo via label

* Print Docker logs

* Disable GPU on ChromeDriver

* Add comments

* Add comments
This commit is contained in:
ylemkimon
2020-08-18 04:58:08 +09:00
committed by GitHub
parent b59ca67530
commit 221042be86
6 changed files with 191 additions and 264 deletions

View File

@@ -1,146 +0,0 @@
version: 2.1
executors:
node:
docker:
- image: circleci/node:10
firefox:
docker:
- image: circleci/node:10
- image: selenium/standalone-firefox:3.141.59-20200525
chrome:
docker:
- image: circleci/node:10
- image: selenium/standalone-chrome:3.141.59-20200525
commands:
checkout_repo:
steps:
- checkout
- run:
name: Checkout submodule
command: |
git submodule sync
git submodule update --init --recursive
skip_if_only_changed:
parameters:
filter:
type: string
steps:
- run:
name: Skip tests if only "<< parameters.filter >>" are changed
command: git diff --name-only << pipeline.git.base_revision >>... | grep -qvE '<< parameters.filter >>' || circleci step halt
install_dependencies:
steps:
- restore_cache:
keys:
- yarn-deps-v5-{{ checksum "yarn.lock" }}
- yarn-deps-v5-
- run:
name: Install dependencies
command: yarn --immutable
- save_cache:
key: yarn-deps-v5-{{ checksum "yarn.lock" }}
paths:
- .yarn
- .pnp.js
screenshot:
parameters:
flags:
type: string
default: ""
steps:
- run:
name: Verify screenshots and generate diffs and new screenshots
command: yarn node dockers/screenshotter/screenshotter.js -b $CIRCLE_JOB --verify --diff --new << parameters.flags >>
jobs:
test:
executor: node
steps:
- run:
name: Check whether the build is running on the main repository
command: |
if [[ $CIRCLE_PULL_REQUEST && $CIRCLE_PROJECT_USERNAME != "KaTeX" ]]; then
echo "Please disable CircleCI on your forked repository!"
exit 1
fi
- checkout_repo
- skip_if_only_changed:
filter: '^docs/|^LICENSE|\.md$'
- install_dependencies
- run:
name: Lint code
command: yarn test:lint
- skip_if_only_changed:
filter: '^static/|^website/'
- run:
name: Run Flow and Jest tests
command: |
yarn test:flow
yarn test:jest --coverage --runInBand
- run:
name: Upload code coverage reports to Codecov
command: yarn codecov
screenshotter:
parameters:
browser:
type: executor
browserstack:
type: string
default: ""
executor: << parameters.browser >>
steps:
- checkout_repo
- skip_if_only_changed:
filter: '^docs/|^static/|^website/|^LICENSE|\.md$'
- install_dependencies
- when:
condition: << parameters.browserstack >>
steps:
- screenshot:
flags: --browserstack --selenium-capabilities '<< parameters.browserstack >>'
- unless:
condition: << parameters.browserstack >>
steps:
- screenshot:
flags: --selenium-ip localhost
- store_artifacts:
path: test/screenshotter/new
destination: new
- store_artifacts:
path: test/screenshotter/diff
destination: diff
workflows:
test:
jobs:
- test
- screenshotter:
name: firefox
browser: firefox
- screenshotter:
name: chrome
browser: chrome
- screenshotter:
name: safari
browser: node
browserstack: |
{
"browserName": "Safari",
"browser_version": "13.1",
"os": "OS X",
"os_version": "Catalina"
}
filters:
branches:
# Forked pull requests don't have access to Browserstack credentials
ignore: /pull\/[0-9]+/

179
.github/workflows/ci.yml vendored Normal file
View File

@@ -0,0 +1,179 @@
name: CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
pull_request_target:
branches: [ master ]
types: [ labeled ] # 'test screenshots' label on PRs from fork
jobs:
test:
runs-on: ubuntu-latest
if: |
github.event_name != 'pull_request_target' &&
!contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
!contains(toJSON(github.event.commits.*.message), '[ci skip]')
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: '12'
- name: Cache dependencies
uses: actions/cache@v2
with:
path: |
.yarn/cache
.pnp.js
key: yarn-deps-v1-${{ hashFiles('yarn.lock') }}
restore-keys: |
yarn-deps-v1-
- name: Install dependencies
run: yarn --immutable
- name: Lint code
run: yarn test:lint
- name: Run Flow
run: yarn test:flow
if: always()
- name: Run Jest tests
run: yarn test:jest --coverage
if: always()
- uses: codecov/codecov-action@v1
with:
directory: ./coverage/
screenshotter_dispatcher:
runs-on: ubuntu-latest
if: |
(github.event_name != 'pull_request_target' ||
(github.event.pull_request.head.repo.full_name != 'KaTeX/KaTeX' &&
contains(github.event.pull_request.labels.*.name, 'test screenshots'))) &&
!contains(toJSON(github.event.commits.*.message), '[skip ci]') &&
!contains(toJSON(github.event.commits.*.message), '[ci skip]')
outputs:
matrix: ${{ steps.set-matrix.outputs.result }}
steps:
- id: set-matrix
uses: actions/github-script@v2
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const SELENIUM_BROWSERS = ["chrome", "firefox"];
const BROWSERSTACK_BROWSERS = [{
browserName: "safari",
browser_version: "13.1",
os: "OS X",
os_version: "Catalina",
}];
const include = [];
// running selenium doesn't require access to secrets
if (context.eventName !== "pull_request_target") {
include.push(...SELENIUM_BROWSERS.map(name => ({
browser: name,
services: {selenium: {
image: `selenium/standalone-${name}:3.141.59-20200525`,
ports: ["4444:4444"],
}},
})));
}
// check access to Browserstack crendential secrets
if (context.eventName !== "pull_request" ||
context.payload.pull_request.head.repo.full_name === "KaTeX/KaTeX") {
if (context.eventName === "pull_request_target") {
github.issues.removeLabel({
issue_number: context.issue.number,
owner: context.repo.owner,
repo: context.repo.repo,
name: "test screenshots",
});
}
include.push(...BROWSERSTACK_BROWSERS.map(capabilities => ({
browser: capabilities.browserName,
services: {},
browserstack: capabilities,
})));
}
return {browser: include.map(b => b.browser), include};
screenshotter:
runs-on: ubuntu-latest
needs: screenshotter_dispatcher
strategy:
matrix: ${{ fromJson(needs.screenshotter_dispatcher.outputs.matrix) }}
fail-fast: false
services: ${{ matrix.services }}
steps:
- uses: actions/checkout@v2
if: github.event_name != 'pull_request_target'
with:
submodules: recursive
- uses: actions/checkout@v2
if: github.event_name == 'pull_request_target'
with:
# pull_request_target is run in the context of the base repository
# of the pull request, so the default ref is master branch and
# ref should be manually set to the head of the PR
ref: refs/pull/${{ github.event.pull_request.number }}/head
submodules: recursive
- name: Use Node.js 12.x
uses: actions/setup-node@v1
with:
node-version: '12'
- name: Cache dependencies
uses: actions/cache@v2
with:
path: |
.yarn/cache
.pnp.js
key: yarn-deps-v1-${{ hashFiles('yarn.lock') }}
restore-keys: |
yarn-deps-v1-
- name: Install dependencies
run: yarn --immutable
- name: Verify screenshots and generate diffs and new screenshots
run: yarn node dockers/screenshotter/screenshotter.js -b ${{ matrix.browser }} --verify --diff --new -c ${{ job.services.selenium.id }}
if: matrix.services.selenium
- name: Verify screenshots and generate diffs and new screenshots
run: yarn node dockers/screenshotter/screenshotter.js -b ${{ matrix.browser }} --verify --diff --new --browserstack --selenium-capabilities '${{ toJson(matrix.browserstack) }}'
if: matrix.browserstack
env:
BROWSERSTACK_USER: ${{ secrets.BROWSERSTACK_USER }}
BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }}
- name: Print Docker logs
run: docker logs ${{ job.services.selenium.id }}
if: always() && matrix.services.selenium
- uses: actions/upload-artifact@v2
if: failure()
with:
name: new-${{ matrix.browser }}
path: test/screenshotter/new
- uses: actions/upload-artifact@v2
if: failure()
with:
name: diff-${{ matrix.browser }}
path: test/screenshotter/diff

View File

@@ -1,6 +1,6 @@
# [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/) # [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)
[![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex) [![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex)
[![CircleCI](https://circleci.com/gh/KaTeX/KaTeX.svg?style=shield)](https://circleci.com/gh/KaTeX/KaTeX) [![CI](https://github.com/KaTeX/KaTeX/workflows/CI/badge.svg?branch=master&event=push)](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX) [![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/master/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX)
[![Discussions](https://img.shields.io/badge/Discussions-join-brightgreen)](https://github.com/KaTeX/KaTeX/discussions) [![Discussions](https://img.shields.io/badge/Discussions-join-brightgreen)](https://github.com/KaTeX/KaTeX/discussions)
[![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com) [![Dependabot Status](https://api.dependabot.com/badges/status?host=github&repo=KaTeX/KaTeX)](https://dependabot.com)

View File

@@ -10,6 +10,7 @@ const pako = require("pako");
const path = require("path"); const path = require("path");
const selenium = require("selenium-webdriver"); const selenium = require("selenium-webdriver");
const firefox = require("selenium-webdriver/firefox"); const firefox = require("selenium-webdriver/firefox");
const chrome = require("selenium-webdriver/chrome");
const istanbulLibCoverage = require('istanbul-lib-coverage'); const istanbulLibCoverage = require('istanbul-lib-coverage');
const istanbulLibReport = require('istanbul-lib-report'); const istanbulLibReport = require('istanbul-lib-report');
@@ -152,8 +153,12 @@ function guessDockerIPs() {
return; return;
} }
// Native Docker on Linux or remote Docker daemon or similar // Native Docker on Linux or remote Docker daemon or similar
const gatewayIP = cmd("docker", "inspect", // https://docs.docker.com/engine/tutorials/networkingcontainers/
"-f", "{{.NetworkSettings.Gateway}}", opts.container); const gatewayIP = cmd("docker", "inspect", // using default bridge network
"-f", "{{.NetworkSettings.Gateway}}", opts.container)
|| cmd("docker", "inspect", // using own network
"-f", "{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}",
opts.container);
seleniumIP = seleniumIP || gatewayIP; seleniumIP = seleniumIP || gatewayIP;
katexIP = katexIP || gatewayIP; katexIP = katexIP || gatewayIP;
} }
@@ -277,6 +282,10 @@ function buildDriver() {
ffProfile.setPreference("browser.startup.page", 0); ffProfile.setPreference("browser.startup.page", 0);
const ffOptions = new firefox.Options().setProfile(ffProfile); const ffOptions = new firefox.Options().setProfile(ffProfile);
builder.setFirefoxOptions(ffOptions); builder.setFirefoxOptions(ffOptions);
} else if (opts.browser === "chrome") {
// https://stackoverflow.com/questions/48450594/selenium-timed-out-receiving-message-from-renderer
const chrOptions = new chrome.Options().addArguments("--disable-gpu");
builder.setChromeOptions(chrOptions);
} }
if (seleniumURL) { if (seleniumURL) {
builder.usingServer(seleniumURL); builder.usingServer(seleniumURL);

View File

@@ -36,7 +36,6 @@
"browserslist": "^4.13.0", "browserslist": "^4.13.0",
"browserstack-local": "^1.4.5", "browserstack-local": "^1.4.5",
"caniuse-lite": "^1.0.30001102", "caniuse-lite": "^1.0.30001102",
"codecov": "^3.7.1",
"css-loader": "^4.0.0", "css-loader": "^4.0.0",
"cssnano": "^4.1.10", "cssnano": "^4.1.10",
"eslint": "^7.4.0", "eslint": "^7.4.0",

114
yarn.lock
View File

@@ -1592,13 +1592,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@tootallnate/once@npm:1":
version: 1.1.2
resolution: "@tootallnate/once@npm:1.1.2"
checksum: d030f3fb14e0373dbf5005d8f696ff34fda87bf56744bea611fc737449bfc0687ebcb28ee8ba4c6624877f51b18d701c0d417d793f406006a192f4721911d048
languageName: node
linkType: hard
"@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.7": "@types/babel__core@npm:^7.0.0, @types/babel__core@npm:^7.1.7":
version: 7.1.9 version: 7.1.9
resolution: "@types/babel__core@npm:7.1.9" resolution: "@types/babel__core@npm:7.1.9"
@@ -2054,15 +2047,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"agent-base@npm:6":
version: 6.0.1
resolution: "agent-base@npm:6.0.1"
dependencies:
debug: 4
checksum: 5dbab2ce93cbf858c557c87a7401114ccf6afdd3d1c5c038831798de2be3873356bb1c09067a75e7e1f9a9ba84b4d979d3aec8cab3db87c776f05b5ae693323c
languageName: node
linkType: hard
"aggregate-error@npm:^3.0.0": "aggregate-error@npm:^3.0.0":
version: 3.0.1 version: 3.0.1
resolution: "aggregate-error@npm:3.0.1" resolution: "aggregate-error@npm:3.0.1"
@@ -2228,13 +2212,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"argv@npm:0.0.2":
version: 0.0.2
resolution: "argv@npm:0.0.2"
checksum: 09d26b0dc74bfdbc70feb354294d029e2e14cf274b404749b0369b917c0c993219f2b48285eb56b15441df1317b912a3ed09a82ae4f46bee640b68b769f01223
languageName: node
linkType: hard
"arr-diff@npm:^4.0.0": "arr-diff@npm:^4.0.0":
version: 4.0.0 version: 4.0.0
resolution: "arr-diff@npm:4.0.0" resolution: "arr-diff@npm:4.0.0"
@@ -3384,21 +3361,6 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"codecov@npm:^3.7.1":
version: 3.7.2
resolution: "codecov@npm:3.7.2"
dependencies:
argv: 0.0.2
ignore-walk: 3.0.3
js-yaml: 3.13.1
teeny-request: 6.0.1
urlgrey: 0.4.4
bin:
codecov: bin/codecov
checksum: ecddd837e3d7519f36aee902122d99cf6ba8bf07c6ffd2b5c8936193a9825d72e5699efd02b9ba87ae942cd14ee8b999034ad5cbfe85d8219387b775ce74d136
languageName: node
linkType: hard
"collapse-white-space@npm:^1.0.2": "collapse-white-space@npm:^1.0.2":
version: 1.0.6 version: 1.0.6
resolution: "collapse-white-space@npm:1.0.6" resolution: "collapse-white-space@npm:1.0.6"
@@ -6047,17 +6009,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"http-proxy-agent@npm:^4.0.0":
version: 4.0.1
resolution: "http-proxy-agent@npm:4.0.1"
dependencies:
"@tootallnate/once": 1
agent-base: 6
debug: 4
checksum: 6703aeb5c5d398d93757c38eb0d77df10239ff3fefee27614aad2831f06f9ca6c8b21c43e9ff02464b5284cba3c6cedefffd210750871277ebf652cbe3230566
languageName: node
linkType: hard
"http-proxy-middleware@npm:0.19.1": "http-proxy-middleware@npm:0.19.1":
version: 0.19.1 version: 0.19.1
resolution: "http-proxy-middleware@npm:0.19.1" resolution: "http-proxy-middleware@npm:0.19.1"
@@ -6169,15 +6120,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"ignore-walk@npm:3.0.3":
version: 3.0.3
resolution: "ignore-walk@npm:3.0.3"
dependencies:
minimatch: ^3.0.4
checksum: 08394ce8c47dc086d44ef65a1e1d30352ff3d6605bdec90f59e985b710cc660aafa7975cb30312891d21d826d10b3a8b3210c5d68251678e2dcd366362865170
languageName: node
linkType: hard
"ignore@npm:^4.0.6": "ignore@npm:^4.0.6":
version: 4.0.6 version: 4.0.6
resolution: "ignore@npm:4.0.6" resolution: "ignore@npm:4.0.6"
@@ -7422,18 +7364,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"js-yaml@npm:3.13.1":
version: 3.13.1
resolution: "js-yaml@npm:3.13.1"
dependencies:
argparse: ^1.0.7
esprima: ^4.0.0
bin:
js-yaml: bin/js-yaml.js
checksum: 277157fdf235757b71cfbf24f6bef57576a26d9b4cf89b63d89c9044da7b0f9d16c3629c8b5fd549ae343523727a0df1598794e9a4429763cee4e17056ff8523
languageName: node
linkType: hard
"js-yaml@npm:^3.12.1, js-yaml@npm:^3.13.1": "js-yaml@npm:^3.12.1, js-yaml@npm:^3.13.1":
version: 3.14.0 version: 3.14.0
resolution: "js-yaml@npm:3.14.0" resolution: "js-yaml@npm:3.14.0"
@@ -7671,7 +7601,6 @@ fsevents@^1.2.7:
browserslist: ^4.13.0 browserslist: ^4.13.0
browserstack-local: ^1.4.5 browserstack-local: ^1.4.5
caniuse-lite: ^1.0.30001102 caniuse-lite: ^1.0.30001102
codecov: ^3.7.1
commander: ^6.0.0 commander: ^6.0.0
css-loader: ^4.0.0 css-loader: ^4.0.0
cssnano: ^4.1.10 cssnano: ^4.1.10
@@ -8590,13 +8519,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"node-fetch@npm:^2.2.0":
version: 2.6.0
resolution: "node-fetch@npm:2.6.0"
checksum: dd9f586a9f7ddb7dd94d2aba9cb693d32f5001e9850098512fbc8a4cbdd56838afa08ed0a6725b9fce9b01ec12b713e622cbfc16d92762d8b937b238330a632a
languageName: node
linkType: hard
"node-forge@npm:0.9.0": "node-forge@npm:0.9.0":
version: 0.9.0 version: 0.9.0
resolution: "node-forge@npm:0.9.0" resolution: "node-forge@npm:0.9.0"
@@ -11901,15 +11823,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"stream-events@npm:^1.0.5":
version: 1.0.5
resolution: "stream-events@npm:1.0.5"
dependencies:
stubs: ^3.0.0
checksum: faa9a327e3f8ac366ec7365e6cded01c5de44b834b429d2c8eea8039839269f437c0dd8afb996353b4eed016803292bf490fda78b87fdd8ae1437cff6649bd00
languageName: node
linkType: hard
"stream-http@npm:^2.7.2": "stream-http@npm:^2.7.2":
version: 2.8.3 version: 2.8.3
resolution: "stream-http@npm:2.8.3" resolution: "stream-http@npm:2.8.3"
@@ -12123,13 +12036,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"stubs@npm:^3.0.0":
version: 3.0.0
resolution: "stubs@npm:3.0.0"
checksum: 5d58c7b76aa6ac62149166ae43a1fc257cc093fffc2b584cbc09a49c5feb951f4ba05c6832453fad392a3c7665bbe62167c116a17edc8520637d0d65706bef0d
languageName: node
linkType: hard
"style-loader@npm:^1.2.1": "style-loader@npm:^1.2.1":
version: 1.2.1 version: 1.2.1
resolution: "style-loader@npm:1.2.1" resolution: "style-loader@npm:1.2.1"
@@ -12354,19 +12260,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"teeny-request@npm:6.0.1":
version: 6.0.1
resolution: "teeny-request@npm:6.0.1"
dependencies:
http-proxy-agent: ^4.0.0
https-proxy-agent: ^4.0.0
node-fetch: ^2.2.0
stream-events: ^1.0.5
uuid: ^3.3.2
checksum: 8721d128d0ac98043c985f67cd5511fe59f4e31ba0d93512e187c9cf348a51a82722e8f8ed7e1a949a5667f7317ddb40f2f15d57ded193881b3a19e271db0f6e
languageName: node
linkType: hard
"temp-fs@npm:^0.9.9": "temp-fs@npm:^0.9.9":
version: 0.9.9 version: 0.9.9
resolution: "temp-fs@npm:0.9.9" resolution: "temp-fs@npm:0.9.9"
@@ -13006,13 +12899,6 @@ fsevents@^1.2.7:
languageName: node languageName: node
linkType: hard linkType: hard
"urlgrey@npm:0.4.4":
version: 0.4.4
resolution: "urlgrey@npm:0.4.4"
checksum: 9c124ff8c1d705e2606e665c9a5307d85b233f887429bd3398d9dc171d14679f469e274ab8632e976c6faf05c678c39209f3a328932839dfec1837b47bd29d55
languageName: node
linkType: hard
"use@npm:^3.1.0": "use@npm:^3.1.0":
version: 3.1.1 version: 3.1.1
resolution: "use@npm:3.1.1" resolution: "use@npm:3.1.1"