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年以上前から憧れてた気がするけどようやく形にできた気がする。
新規のタイミングでないとなかなか難しい。
これを維持できるようにがんばりたい。
