Cypressでe2eをCloudBuild上で実行する方法
Cloud Build: サーバーレス CI / CD プラットフォーム | Google Cloud
CI/CD で Github Actions
を使うことは多いですが、 GCP の Cloud Build
を使って Cypress
を実行する方法をメモしておきます。
今回の成果物リポジトリ: hisasann/nuxt-lint-ts-msw: ESlint、TypeScript、Mock Service Worker(msw)でのモックサーバーを使ったリポジトリです
Cloud SDK のインストール
圧縮ファイルをダウンロードしてきて sh ファイルを実行していきます。
$ ./google-cloud-sdk/install.sh
$ ./google-cloud-sdk/bin/gcloud init
サンプルコードの実行
$ git clone https://github.com/GoogleCloudBuild/cloud-console-sample-build && \
cd cloud-console-sample-build && \
gcloud builds submit --config cloudbuild.yaml
ローカルのプロジェクトを設定する
$ gcloud auth list
$ gcloud config set project プロジェクト名(aliasではない)
$ gcloud config configurations list
はじめ、これからを何もせずに gcloud builds submit
してみたらエラーで進みませんでした。
プロジェクトをブラウザの GCP の画面から作り、その名前を指定してから、
$ gcloud builds submit --config cloudbuild.yaml
をしたらうまくいきました。
調子に乗って、 今回使っている nuxt のリポジトリで hisasann/nuxt-lint-ts-msw 実行してみたら、
$ gcloud builds submit --config ./cloudbuild/lint_and_test.yaml
.eslintignoreを作るの巻
こんなエラーが出ました。
Step #1: Oops! Something went wrong! :(
Step #1:
Step #1: ESLint: 7.32.0
Step #1:
Step #1: Error: Cannot read .eslintignore file: /workspace/.gitignore
Step #1: Error: ENOENT: no such file or directory, open '/workspace/.gitignore'
Step #1: at Object.openSync (fs.js:497:3)
Step #1: at Object.readFileSync (fs.js:393:35)
Step #1: at readFile (/workspace/node_modules/@eslint/eslintrc/lib/config-array-factory.js:142:15)
Step #1: at loadESLintIgnoreFile (/workspace/node_modules/@eslint/eslintrc/lib/config-array-factory.js:270:16)
Step #1: at ConfigArrayFactory.loadESLintIgnore (/workspace/node_modules/@eslint/eslintrc/lib/config-array-factory.js:559:32)
Step #1: at createCLIConfigArray (/workspace/node_modules/@eslint/eslintrc/lib/cascading-config-array-factory.js:165:34)
Step #1: at new CascadingConfigArrayFactory (/workspace/node_modules/@eslint/eslintrc/lib/cascading-config-array-factory.js:243:29)
Step #1: at new CLIEngine (/workspace/node_modules/eslint/lib/cli-engine/cli-engine.js:569:36)
Step #1: at new ESLint (/workspace/node_modules/eslint/lib/eslint/eslint.js:432:27)
Step #1: at Object.execute (/workspace/node_modules/eslint/lib/cli.js:292:24)
Step #1: npm ERR! code ELIFECYCLE
Step #1: npm ERR! errno 2
Step #1: npm ERR! nuxt-lint-ts-msw@1.0.0 lint:js: `eslint --ext .js,.ts,.vue --ignore-path .gitignore .`
Step #1: npm ERR! Exit status 2
S
.eslintignore の配置場所は気をつけた方がいい - Qiita
eslint --ext .js,.ts,.vue --ignore-path .gitignore .
このあたりを読んで、 --ignore-path .gitignore
するのやめて .eslintignore を配置してみよう。
あんまり普段意識したことなかったが、 .gitignore
ファイルを eslint に食べさせる横着は良くなかったのだろう。
$ gcloud builds submit --config ./cloudbuild/lint_and_test.yaml
エラーが解消されました!
cloudbuild.yamlをはじめから作ればよかった
Cloud Build 上で yaml ファイルを 自動検出
ではなく指定で /cloudbuild
としていたらどうやらパス指定は Invalid Argument のようだ。
特にここが悪いという内容のエラーが一切出てくれなかったので、かなりハマってしまった。
なので cloudbuild.yaml
にリネームした。
こうしたらビルドが走るようになった。
Node.js アプリケーションのビルド | Cloud Build のドキュメント | Google Cloud
Server起動しつつe2eの実行をコマンド一発でやる
よくある需要だと思いますが、 e2e の場合は、
- ソースコードをビルドする
- サーバーを起動する
- サーバーが起動したままでe2eテストを実行する
- サーバーを停止する
とサーバーが起動したままテストを実行したいので、このモジュールを使わせていただきました。
cypress:run でコケた
> nuxt-lint-ts-msw@1.0.0 cypress:run /workspace
> cypress run
It looks like this is your first time using Cypress: 8.4.1
[STARTED] Task without title.
[FAILED] Your system is missing the dependency: Xvfb
[FAILED]
[FAILED] Install Xvfb and run Cypress again.
[FAILED]
[FAILED] Read our documentation on dependencies for more information:
[FAILED]
[FAILED] https://on.cypress.io/required-dependencies
[FAILED]
[FAILED] If you are using Docker, we provide containers with all required dependencies installed.
[FAILED]
[FAILED] ----------
[FAILED]
[FAILED] Error: spawn Xvfb ENOENT
[FAILED]
[FAILED] ----------
[FAILED]
[FAILED] Platform: linux (Debian - 9.13)
[FAILED] Cypress Version: 8.4.1
Your system is missing the dependency: Xvfb
Install Xvfb and run Cypress again.
Read our documentation on dependencies for more information:
https://on.cypress.io/required-dependencies
If you are using Docker, we provide containers with all required dependencies installed.
どうやら結構依存してるモジュールがあるようです。
Introduction | Cypress Documentation
cypress/included Tags | Docker Hub
$ docker pull cypress/included:8.5.0
bahmutov/demo-docker-cypress-included: Demo running the complete Docker image cypress/included
node:14イメージでは厳しかった
こんな感じで、 test までする cloudbuild.yaml があったとして、ここに cypress run
する script 実行を追加しましたが、 node:14
イメージだと Cypress で使う依存モジュールが入っていないのエラーになりました。
chore(cloudbuild): add cloudbuild/lint_and_test.yaml · hisasann/nuxt-lint-ts-msw@6fbcf10
steps:
- name: node:14
entrypoint: yarn
args: ['install']
- name: node:14
entrypoint: yarn
args: ['run', 'lint']
- name: node:14
entrypoint: yarn
args: ['test']
- name: node:14
entrypoint: yarn
args: ['cypress']
cypress/includedを使ってCypressを実行する
今の最終形態はこちらです。
nuxt-lint-ts-msw/cloudbuild.yaml at main · hisasann/nuxt-lint-ts-msw
steps:
# install dependencies
- id: install-dependencies
name: node:14
entrypoint: npm
args: ['install']
# lint and test
- name: node:14
entrypoint: npm
args: ['run', 'lint']
- name: node:14
entrypoint: npm
args: ['test']
# run cypress
- name: cypress/included:8.5.0
entrypoint: 'npm'
args: ['run', 'ci']
options:
machineType: 'E2_HIGHCPU_8'
npm install
を一番はじめに一回だけしていますが、これを Cypress を実行する前でもう一度実行してしまい、 Cypress の npm 環境が壊れて実行ができなくなりました。
また、 CYPRESS_CACHE_FOLDER
という環境変数を使う記事が多々ありましたが、今の Cloud Build 上だと逆にそれがあることで Cypress がうまく動きませんでした。
こちらのリポジトリには大変助けられました。
bahmutov/demo-docker-cypress-included: Demo running the complete Docker image cypress/included
via:
Running Cypress in Google Cloud Build - Stack Overflow
【Cypress】Cloud Buildでdocker runを使ってCypressを実行する - UGA Boxxx
【Cypress】ローカルのCloud BuildでCypressを実行する - UGA Boxxx
【Cypress】Cloud BuildでCypressを実行したら"out of memory" エラーが発生した - UGA Boxxx
Running Cypress in Google Cloud Build - Stack Overflow
Docker | Cypress Documentation
GithubActionsでCypressを実行するyaml
Github Actions のほうはサンプルも多いので簡単です。
nuxt-lint-ts-msw/e2e.yml at main · hisasann/nuxt-lint-ts-msw
name: Node.js E2E
on: push
jobs:
build:
name: Node.js ${{ matrix.os }} ${{ matrix.node }}
runs-on: ${{ matrix.os }}
strategy:
matrix:
os: [ubuntu-latest]
node: [ '14' ]
steps:
- uses: actions/checkout@v2
- name: Setup node
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node }}
- name: Display version of Node.js, npm, Yarn
run: |
node -v
npm -v
yarn --version
- name: Get yarn cache
id: yarn-cache
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
with:
path: ${{ steps.yarn-cache.outputs.dir }}
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
with:
path: node_modules
key: ${{ runner.os }}-yarn-${{ hashFiles('yarn.lock') }}
- run: yarn
- name: Cypress run
uses: cypress-io/github-action@v2
with:
build: yarn build
start: yarn start
今回の成果物リポジトリ: hisasann/nuxt-lint-ts-msw: ESlint、TypeScript、Mock Service Worker(msw)でのモックサーバーを使ったリポジトリです
記事を書いてる最中に動かなくなった
こんなエラーが出るようになって、どうやら cypress:8.6.0
のイメージが出ていて、 cypress:8.5.0
を使っているはずがなぜか 8.6.0 が使われてしまい、 cypress がインストールされていない的なエラーが出た。
Error: Command failed with exit code 1: npm run cypress:run
Step #3: at makeError (/workspace/node_modules/execa/lib/error.js:60:11)
Step #3: at handlePromise (/workspace/node_modules/execa/index.js:118:26)
Step #3: at processTicksAndRejections (internal/process/task_queues.js:95:5) {
Step #3: shortMessage: 'Command failed with exit code 1: npm run cypress:run',
Step #3: command: 'npm run cypress:run',
Step #3: escapedCommand: '"npm run cypress:run"',
Step #3: exitCode: 1,
Step #3: signal: undefined,
Step #3: signalDescription: undefined,
Step #3: stdout: undefined,
Step #3: stderr: undefined,
Step #3: failed: true,
Step #3: timedOut: false,
Step #3: isCanceled: false,
Step #3: killed: false
Step #3: }
とりあえず、 8.6.0 に cloudbuild.yaml を書き換えてみたら、 cypress が run できるようになった。
うーん、 latest みたいな感じで使われてしまっているのだろうか。
cypress/included
のバージョンを固定して使いたいがちょっとここはまた別のお話。
追記
普通に凡ミスしていることを教えていただいた。
yarn.lock
ファイルでバージョンを固定していたのに npm install
してしまっていた。
これにより、 Cypress がバージョンを指定しているはずなのに最新がインストールされてしまっていた。
chore(cloudbuild): change entrypoint from npm to yarn · hisasann/nuxt-lint-ts-msw@c78f433
エラーがでなくなり、しっかりと cypress/included
のバージョンを固定できた。
参考記事
ビルド構成ファイルのスキーマ | Cloud Build のドキュメント | Google Cloud
コンテナ イメージのビルド | Cloud Build のドキュメント | Google Cloud
cypress/included Tags | Docker Hub
Cloud Build を知ってみよう | フューチャー技術ブログ
Discussion