NestJS + TypeORMを使った新規開発で開発がちょっと進み、テストコマンドなどもできてきたのでCircleCIで自動実行できるようにしたのでメモ。
前提としてローカルではテストなどが動いていること。
実行したのは下記。まだデプロイなどは行っていない。
- lintの実行
- NestJSのbuild
- マイグレーション漏れが無いか確認
- 普通のテスト実行 (テスト用DB使用)
- E2Eテストの実行(テスト用DB使用)
NestJS系のバージョン
"dependencies": { "@nestjs/common": "^8.0.9", "@nestjs/config": "^1.0.1", "@nestjs/core": "^8.0.9", "@nestjs/platform-express": "^8.0.0", "@nestjs/typeorm": "^8.0.2",
CircleCIの設定ファイル(.circleci/config.yml)
いろいろなところからのコピペしたままもあり、ツギハギ感あるけど一旦動いたもの。
テスト用DBの接続情報、パスワードとかも直書きだけどCircleCI内部で使われるだけなので問題なさそうなのでそのまま。
version: 2.1 jobs: test-server: resource_class: medium docker: - image: circleci/node:14 environment: TEST_DB_HOST: localhost TEST_DB_PORT: 3306 TEST_DB_USERNAME: test_search_user TEST_DB_PASSWORD: test_search_password TEST_DB_DATABASE: test_search_db - image: mysql:8.0 command: - --sql-mode=NO_ENGINE_SUBSTITUTION environment: MYSQL_DATABASE: test_search_db MYSQL_USER: test_search_user MYSQL_PASSWORD: test_search_password MYSQL_ROOT_PASSWORD: test_search_root_password MYSQL_HOST: localhost steps: - checkout - restore_cache: name: Restore Yarn Package Cache keys: - yarn-packages-{{ checksum "./server/yarn.lock" }} - run: # フロント、サーバーを同一レポジトリでやる予定のため、./serverにNestJSを入れてあるので全体的にそのフォルダを指定してます。 working_directory: ./server name: Install Dependencies command: yarn install --immutable - save_cache: name: Save Yarn Package Cache key: yarn-packages-{{ checksum "./server/yarn.lock" }} paths: - ~/server/.cache/yarn - run: working_directory: ./server name: lint command: yarn lint:ci - run: working_directory: ./server name: nest build command: yarn nest build - run: name: dockerize のインストール command: wget https://github.com/jwilder/dockerize/releases/download/$DOCKERIZE_VERSION/dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && sudo tar -C /usr/local/bin -xzvf dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz && rm dockerize-linux-amd64-$DOCKERIZE_VERSION.tar.gz environment: DOCKERIZE_VERSION: v0.3.0 - run: name: db の待機 command: dockerize -wait tcp://localhost:3306 -timeout 1m - run: working_directory: ./server name: migration run command: yarn typeorm migration:run -c test no_output_timeout: 1m - run: working_directory: ./server name: Verifies that the current database is up to date. command: yarn typeorm migration:generate -c test --ch -n Test no_output_timeout: 1m - run: working_directory: ./server name: app test command: yarn test no_output_timeout: 1m - run: working_directory: ./server name: e2e test command: yarn test:e2e no_output_timeout: 3m workflows: server: jobs: - test-server
接続設定関係
接続情報にはormconfig.tsを用いておりこんな感じ。
default を環境変数で切り替えでもいいけど、もしもの事故を防ぐ意味も兼ねて明示的にbtestを使うようにしている。
マスタデータ系の投入にもmigrationを用いているため、synchronizeは使わず、migrationsRunでマイグレーションを実行している。
マイグレーションファイルも、DB名を変えたり、不要なデータを省いたり専用に用意している。
ormconfig.ts
// https://github.com/typeorm/typeorm/blob/master/docs/connection-options.md module.exports = [ { name: 'default', type: 'mysql', // 省略 }, { name: 'test', type: 'mysql', host: process.env.TEST_DB_HOST, port: process.env.TEST_DB_PORT, username: process.env.TEST_DB_USERNAME, password: process.env.TEST_DB_PASSWORD, database: process.env.TEST_DB_DATABASE, synchronize: false, dropSchema: true, entities: ['src/**/*.entity.ts'], migrationsRun: true, migrations: ['src/migration_test/*.ts'], logging: false, }, ]
circleci/mysqlイメージを使ったら固まったので普通のMySQLイメージを使った
CircleCIが用意したMySQLイメージがあり、インメモリ設定も簡単にできるので使っていたが、実行すると途中で固まってしまうため、通常のMySQLイメージを使用した。
https://hub.docker.com/r/circleci/mysql
こっち使ってる
https://hub.docker.com/_/mysql
接続もクエリ発行も問題ないけど下記の箇所で何も返さずに固まってタイムアウトするので困った。
yarn run v1.22.5 $ ts-node $(yarn bin typeorm) migration:show -c test query: SELECT * FROM `INFORMATION_SCHEMA`.`COLUMNS` WHERE `TABLE_SCHEMA` = 'test_search_db' AND `TABLE_NAME` = 'migrations' query: CREATE TABLE `test_search_db`.`migrations` (`id` int NOT NULL AUTO_INCREMENT, `timestamp` bigint NOT NULL, `name` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ENGINE=InnoDB query: SELECT * FROM `test_search_db`.`migrations` `migrations` ORDER BY `id` DESC # このまま音信不通となりタイムアウト・・・
Experimental の記載もあるし、実行速度も問題ないので一旦このまま。将来的にまた試して見ようと思う。
CI用のlintコマンドを追加する
レビューのときもちょくちょく忘れがあったので欲しかったやつ。
yarn lintで実行できるコマンドはあるが--fixが付いていて直せるところは直したあとの結果が返ってしまうので、fixなしのコマンドをつくって実行するようにした。
package.json
"scripts": { "lint": "eslint \"{src,apps,libs,test}/**/*.ts\" --fix", "lint:ci": "eslint \"{src,apps,libs,test}/**/*.ts\"",
テスト用DBを使ったテスト実行
AWS で専用に立てなきゃ・・・と思ってたら簡単にDockerで動かせるので超便利だった。時代に追いつけてない。
マイグレーション漏れが無いか確認
現状のマイグレーションを実行後のテーブルと、Entityに差異が無いかをチェックする。
これもレビュー時に手動で確認してて、ちょくちょく問題になったので欲しかった。
typeormのCLIで下記のように--ch をつければ確認できる。なければ0, あれば1でエラー。
- nは使われることはないが必要なので適当に。
事前にtypeorm migration:runが必要なのでCI側で直前に実行するようにしている。
typeorm migration:generate -c test --ch -n Test
できた!
プッシュすると一通りのテストがCIで動くやつ、5年以上前から憧れてた気がするけどようやく形にできた気がする。
新規のタイミングでないとなかなか難しい。
これを維持できるようにがんばりたい。