この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
PrettierとESLintは、JavaScript系のプロジェクトでよく使われる構文チェックツールです。
Prettierは主にコードのスタイルを整形するフォーマッターです。ESLintはコード内の不要な記述の削除を促すリンターです。両者は役割が異なる(重複する部分もありますが)ため一緒に使われることが多いです。
今回は、PrettierおよびESLintをCI上で実行して、違反時にWorkflowを失敗させる方法を確認してみました。
環境準備
今回はAWS CDKプロジェクト(TypeScript)で試してみます。
プロジェクトを作成します。
$ npx cdk init --language typescript
PrettierとESLintおよび周辺ライブラリをインストールします。
$ npm install -D \
prettier \
eslint \
eslint-config-prettier \
eslint-config-standard \
@typescript-eslint/eslint-plugin
PrettierとESLintがインストールできました。
$ npm ls --depth=0
├── eslint@8.13.0
├── prettier@2.6.2
その他ライブラリは次のような用途で入れています。
- eslint-config-prettierはPrettierとConflictするESLintのルールを無効にします。
- eslint-config-standardはShareable Config(.eslintrc)が使用可能になります。
- @typescript-eslint/eslint-pluginはESLintのTypeScript Pluginです。
.eslintrc.json
ファイルを作成して、ESLintのPrettierとの併用およびTypeScriptで利用するための設定を記述します。
.eslintrc.json
{
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"project": "./tsconfig.json"
},
"plugins": [
"@typescript-eslint"
]
}
また.prettierrc.json
ファイルを作成して、Prettierのフォーマッティングルールを定義します。
.prettierrc.json
{
"singleQuote": true,
"trailingComma": "all",
"tabWidth": 2
}
周辺ライブラリとしては他にもeslint-plugin-import
やeslint-plugin-node
、eslint-plugin-promise
などをよく導入しますが、今回は一旦ここまでとします。
CLI実行時のExit code
CI/CDツールではExit codeが0
以外の時にWorkflowの実行が失敗となります。まずはPrettierおよびESLintのCLI実行時のExit codeの仕様について確認してみます。
Prettier
Prettierでは--check
フラグを使用すれば、CLIコマンドの実行でファイルのフォーマットチェックができます。
フォーマットの違反が無ければExit codeは0
となります。
$ npx prettier --check lib
Checking formatting...
All matched files use Prettier code style!
$ echo $?
0
違反があれば1
となります。
$ npx prettier --check lib
Checking formatting...
[warn] lib/aws-cdk-v2-project-stack.ts
[warn] Code style issues found in the above file(s). Forgot to run Prettier?
$ echo $?
1
ESLint
ESLintが検知する違反にはerrors
とwarning
の2種類があり、warning
のみ検知時にExit codeを0
とするには--max-warnings
の設定が必要です。
違反が無ければExit codeは0
となります。
$ npx eslint src --max-warnings=0
$ echo $?
0
違反があれば1
となります。warning
が一つ検知されています。
$ npx eslint lib --max-warnings=0
/Users/wakatsuki.ryuta/projects/cm-rwakatsuki/aws-cdk-v2-project/lib/aws-cdk-v2-project-stack.ts
87:7 warning 'aaa' is assigned a value but never used @typescript-eslint/no-unused-vars
✖ 1 problem (0 errors, 1 warning)
ESLint found too many warnings (maximum: 0).
$ echo $?
1
CI上で実行してみる
prettier
とeslint
の実行コマンドをpackage.json
のscriptsに設定してプロジェクト上でコマンド実行できるようにします。
package.json
{
"scripts": {
"format": "prettier --check './{bin,lib,src,tests}/**/*.{ts,tsx}'",
"lint": "eslint './{bin,lib,src,tests}/**/*.{ts,tsx}' --max-warnings=0"
}
}
上述のコマンドをCI/CDツール(今回はGitHub Actions)のWorkflow fileに記述して実行されるようにします。
.github/workflows/cicd.yaml
on:
push:
paths-ignore:
- '**/*.md'
jobs:
integrate:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Cache CDK Dependency
uses: actions/cache@v3
id: cache_cdk_dependency_id
env:
cache-name: cache-cdk-dependency
with:
path: node_modules
key: ${{ runner.os }}-build-${{ env.cache-name }}-${{ hashFiles('package-lock.json') }}
restore-keys: ${{ runner.os }}-build-${{ env.cache-name }}-
- name: Install Dependency
if: ${{ steps.cache_cdk_dependency_id.outputs.cache-hit != 'true' }}
run: npm ci --no-audit --progress=false --silent
- name: Lint & Format
run: |
npm run lint
npm run format
Workflowを実行します。ESLintでリント違反となり、Workflowが失敗しました。
リント違反部分を修正し再度Workflowを実行します。次はPrettierでフォーマット違反となり、Workflowが失敗しました。
フォーマット違反を修正します。
$ npx prettier --write './{bin,lib,src,tests}/**/*.{ts,tsx}'
bin/aws-cdk-v2-project.ts 294ms
lib/aws-cdk-v2-project-stack.ts 31ms
再度Workflowを実行すると、今度はリントもフォーマットも違反無くパスし、Workflowが成功しました!
おわりに
PrettierおよびESLintをCI上で実行して、違反時にWorkflowを失敗させる方法を確認してみました。
huskyを使用してpre-commit時にフォーマット/リントを強制する宗派もありますが、私は今回のようなCI/CDツール上にオフロードする方が好みです。
参考
以上