GitHub Actions で CI 回して README に build と coverage の badge を付けるまでのメモ
Jest のテストを GitHub Actions で実行する
- PR の最新のコミットでテストを実行する
- coverage をコメントに残す
環境
- jest
29.6.3
- eslint
8.47.0
- typescript
5.1.6
- ts-jest
29.1.1
- @types/jest
29.5.4
JEST config
jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
coverageDirectory: 'coverage',
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
roots: ['<rootDir>/tests/'],
transformIgnorePatterns: ['/node_modules/'],
};
npm script
package.json
"scripts": {
"test": "jest --runInBand",
"test:coverage": "jest test --coverage",
"lint": "eslint --ext .js,.ts src/",
}
1. PR の最新のコミットで Jest のテストを GitHub actions で実行する
.github/workflows/ci.yml
name: "CI"
on:
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ["lts/*"]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup
run: npm ci
- name: ESLint
run: npm run lint
- name: Run Jest
run: npm run test:coverage
2. coverage を PR のコメントに残す
Jest Coverage Comment を使ってみる
jest-junit をインストール
--reporters=jest-junit
のオプションが使われており、jest-junit が必要なようなのでインストールする
$ npm i -D jest-junit
JEST config の修正
jest.config.js
/** @type {import('ts-jest').JestConfigWithTsJest} */
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
coverageDirectory: 'coverage',
moduleFileExtensions: ['js', 'json', 'jsx', 'ts', 'tsx', 'node'],
roots: ['<rootDir>/tests/'],
transformIgnorePatterns: ['/node_modules/'],
+ reporters: [ 'default', 'jest-junit' ],
};
Summary Report を PR に追加する
サンプルを参考に GitHub actions に coverage を PR にコメントするアクションを追加する
.github/workflows/ci.yml
name: "CI"
on:
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ["lts/*"]
steps:
- uses: actions/checkout@v3
# …
- name: Run Jest
run: npm run test:coverage
+ - name: Jest Coverage Comment
+ uses: MishaKav/jest-coverage-comment@v1.0.23
+ with:
+ coverage-summary-path: ./coverage/coverage-summary.json
./coverage/coverage-summary.json
が存在しないエラー
🙅 Jest Coverage Comment
の箇所で ./coverage/coverage-summary.json
が存在しないとして CI が落ちてしまっていた
Jest Coverage Comment がいい感じに生成してくれる訳ではないらしい
Jest で summary レポートを出力する必要があった
Jest Coverage Comment の直前で実行される Jest コマンドで coverage-summary.json
が出力されてないのが原因だった
--coverageReporters="json-summary"
オプションで coverage-summary.json
が出力できる
通常のテストを残したいので別途 json-summary
を生成するための npm script を作成した
package.json
"scripts": {
"test": "jest --runInBand",
"test:coverage": "jest test --coverage",
+ "test:coverage:summary": "jest test --coverage --coverageReporters=\"json-summary\"",
"lint": "eslint --ext .js,.ts src/",
}
workflow を修正する
.github/workflows/ci.yml
name: "CI"
on:
pull_request:
branches: [main]
jobs:
ci:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ["lts/*"]
steps:
- uses: actions/checkout@v3
# …
- name: Run Jest
- run: npm run test:coverage
+ run: npm run test:coverage:summary
- name: Jest Coverage Comment
uses: MishaKav/jest-coverage-comment@v1.0.23
with:
coverage-summary-path: ./coverage/coverage-summary.json
これで PR を作ると coverage がコメントされるようになった
✅ Jest のテストを GitHub Actions で実行する
Build と Coverage の badge を README に表示する
- Build 成功の badge を README に貼る
- Coverage の badge を README に貼る
条件
- いずれも badge の画像が生成されて同じ URL でアクセスできる必要がある
- Build・Coverage の badge 生成は main のブランチに PR がマージ・更新された時に実行されれば良い
1. Build 成功の badge を README に貼る
https://github.com/<OWNER>/<REPOSITORY>/actions/workflows/<WORKFLOW_FILE>/badge.svg
で workflow status badge が取得できるっぽい
なので main ブランチが更新された時にビルドとテストを実行して通れば OK とする GitHub action を作成すれば良い
main ブランチが更新された時に実行される GitHub actions を作成する
.github/workflows/build.yml
name: Build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['lts/*']
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup
run: npm ci
# Test と build を実行
- run: npm run test:coverage
- run: npm run build
README に Build workflow の status badge を貼り付ける
README.md
![build workflow](https://github.com/<USER_NAME>/<REPOSITORY>/actions/workflows/build.yml/badge.svg)
name
に設定した名前で badge が表示されていれば OK
🎖️ workflow の ✅ Build の badge を README に表示する
2. Coverage の badge を README に貼る (GitHubで完結したい)
いくつか方法がありそう
Coverage Badge
📦- 比較した中でスター数は一番多かった
- gh-pages ブランチに badge の画像をコミットするっぽい
# .github/workflows/test.yml
name: Test
on: [push, pull_request, workflow_dispatch]
jobs:
test:
runs-on: ubuntu-latest
steps:
# Your original steps
- uses: actions/checkout@v3
- uses: actions/setup-node@v3
- name: Install
run: npm install
- name: Test and Coverage
run: npm run test:cov # or npm run coverage
# Add this
- name: Update Coverage Badge
# GitHub actions: default branch variable
# https://stackoverflow.com/questions/64781462/github-actions-default-branch-variable
if: github.ref == format('refs/heads/{0}', github.event.repository.default_branch)
uses: we-cli/coverage-badge-action@main
cf. https://github.com/we-cli/coverage-badge-action/blob/main/README.md
Create Coverage Badges
📦- TypeScript 製
- このライブラリはあくまで coverage の画像を生成するだけで、後は自分でGitHub page に badge をアップロードして使う方法っぽい
- name: Create Coverage Badges
uses: jaywcjlove/coverage-badges-cli@main
with:
style: flat
source: coverage/coverage-summary.json
output: coverage/badges.svg
- name: Deploy
uses: peaceiris/actions-gh-pages@v3
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_dir: ./build
cf. https://github.com/jaywcjlove/coverage-badges-cli/blob/main/README.md
CI Badges action
📦- Badge のカスタマイズが豊富
- Gist を使う方法っぽい
uses: gaelgirodon/ci-badges-action@v1
with:
gist-id: <gist-id>
token: ${{ secrets.GIST_TOKEN }}
cf. https://github.com/GaelGirodon/ci-badges-action/blob/main/README.md
Create Coverage Badges を選択した
- Gist を使う CI Badges action 設定が面倒なので除外
-
Coverage Badge はファイルの作成もなくいい感じだが、
gh-pages
ブランチが作られて勝手にコミットされるのが少し微妙に感じた-
gh-pages
を使わずに GitHub ページへのアップロードができそうだったので
-
- TypeScript 製
badges.svg
を作成する
2-1. coverage-summary.json
から生成できるようなので、coverage-summary.json
を生成できるテストを実行するようにする
.github/workflows/build.yml
name: Build
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['lts/*']
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup
run: npm ci
# Test と build を実行
- - run: npm run test:coverage
+ # npx jest test --coverage --coverageReporters="json-summary"
+ - npm run test:coverage:summary
- run: npm run build
+ - name: Create Coverage Badges
+ uses: jaywcjlove/coverage-badges-cli@main
+ with:
+ style: flat
+ source: coverage/coverage-summary.json
+ output: coverage/badges.svg
2-2. Coverge Badge を GitHub page にデプロイする
🥔 Tips
サンプルに載っていた peaceiris/actions-gh-pages は gh-pages
ブランチを使って GitHub page にデプロイするものだったが、GitHub 公式の actions/upload-pages-artifact, actions/deploy-pages を用いる事で gh-pages
を使うこと無く GitHub page にデプロイが可能になったらしい
サイトを公開するカスタム GitHub Actions ワークフローの作成
GitHub Actions で発行するようにサイトを構成する場合、GitHub により、一般的な公開シナリオのスターター ワークフローが提案されます。 ワークフローの一般的なフローは、次のとおりです。
- リポジトリの既定のブランチへのプッシュがあるたびに、またはワークフローが [Actions] タブから手動で実行されるたびに、トリガーされます。
actions/checkout
アクションを使用してリポジトリの内容をチェックアウトします。- サイトで必要な場合、静的サイト ファイルをビルドします。
actions/upload-pages-artifact
アクションを使用して静的ファイルを成果物としてアップロードします。- ワークフローが既定のブランチへのプッシュによってトリガーされた場合、
actions/deploy-pages
アクションを使用して成果物をデプロイします。 ワークフローが pull request によってトリガーされた場合、この手順はスキップされます。
cf.
- https://zenn.dev/jordan/articles/b6c1e905adab31
- https://docs.github.com/ja/pages/getting-started-with-github-pages/configuring-a-publishing-source-for-your-github-pages-site#サイトを公開するカスタム-github-actions-ワークフローの作成
2-2-1. GitHub page の準備
- ブランチの
Settings
メニューからPages
を選択 - Build and deployment の Source を
GitHub Actions
にしておく
2-2-2. badge を GitHub Page にアップロードする workflow を追加する
- actions/upload-pages-artifact で github storage にアップロードする
- アップロードされたファイルを actions/deploy-pages で GitHub page にデプロイする
cf. https://zenn.dev/jordan/articles/b6c1e905adab31
.github/workflows/build.yml
name: Build
on:
push:
branches: [main]
+ permissions:
+ contents: read
+ pages: write
+ id-token: write
+ concurrency:
+ group: 'pages'
+ cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['lts/*']
steps:
- uses: actions/checkout@v3
# 略
- npm run test:coverage:summary
- run: npm run build
- name: Create Coverage Badges
uses: jaywcjlove/coverage-badges-cli@main
with:
style: flat
source: coverage/coverage-summary.json
output: coverage/badges.svg
+ - name: Upload test coverage artifact
+ uses: actions/upload-pages-artifact@v2
+ with:
+ name: coverage
+ path: ./coverage
+
+ deploy:
+ needs: build
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ runs-on: ubuntu-latest
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v2
+ with:
+ artifact_name: coverage
ブランチの GitHub page 直下に ./coverage
の内容がデプロイされるので、badges.svg
のパスは http(s)://<username>.github.io/<repository>/badges.svg
となる
この URL にアクセスして Coverage の badge が表示されていれば OK
2-2-3. 🎖️ badge を README に追加する
badges.svg
を画像として表示する markdown を README に貼り付ければ OK
[![coverage](https://<username>.github.io/<repository>/badges.svg)](https://github.com/<username>/<repository>/actions)
✅ Coverage の badge を README に表示する
[参考]
最終的な CI workflow
.github/workflows/ci.yml
name: CI
on:
pull_request:
branches: [main]
jobs:
build:
name: Test on node ${{ matrix.node_version }} and ${{ matrix.os }}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [16.x, 18.x, 20.x]
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup
run: npm ci
- name: ESLint
run: npm run lint
- name: Run Jest
run: npm run test:coverage:summary
- name: Jest Coverage Comment
uses: MishaKav/jest-coverage-comment@v1.0.23
with:
coverage-summary-path: ./coverage/coverage-summary.json
最終的な Build workflow
.github/workflows/build.yml
name: Build
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: 'pages'
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: ['lts/*']
steps:
- uses: actions/checkout@v3
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v3
with:
node-version: ${{ matrix.node-version }}
- name: setup
run: npm ci
# Test と build を実行
- run: npm run test:coverage:summary
- run: npm run build
- name: Create Coverage Badges
uses: jaywcjlove/coverage-badges-cli@main
with:
style: flat
source: coverage/coverage-summary.json
output: coverage/badges.svg
- name: Upload test coverage artifact
uses: actions/upload-pages-artifact@v2
with:
name: coverage
path: ./coverage
deploy:
needs: build
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
with:
artifact_name: coverage
Badges
Build status
![build](https://github.com/<USER_NAME>/<REPOSITORY>/actions/workflows/build.yml/badge.svg)
Coverage
![coverage](https://<USER_NAME>.github.io/<REPOSITORY>/badges.svg)
🛑 actions/deploy-pages のエラー
coverage の badge を GitHub Page にデプロイする所でエラーが発生した
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v2
with:
artifact_name: coverage
Error: Artifact could not be deployed. Please ensure the content does not contain any hard links, symlinks and total size is less than 10GB.
/covarage
ディレクトリなので 10GB を超えているとは考えにくい
actions/upload-pages-artifact
ではなく actions/upload-artifact
を使っているとエラーになる
❇️ 名前が似ているが別物っぽい
actions/deploy-pages
を使うときは actions/upload-pages-artifact
を使う
🛑 GitHub Page にデプロイした Coverage の badge が 404 になる
coverage の badge をデプロイする workflow が完了しても https://<USER_NAME>.github.io/<REPOSITORY>/badges.svg
が 404 になってしまった
❇️ GitHub のリポジトリ名に大文字が含まれていると GitHub page が 404 になる
リポジトリ名に大文字が含まれている場合は変更する必要があった
リポジトリ名の変更は GitHub 上から Settings
→ General
→ Repository name
から変更できる
リポジトリ名変更後に local の remote ブランチの名前を変更する 👇
その他 README や package.json などに含まれているリポジトリ名を置換する
[参考]
📝
$default-branch
を使うと main
とか master
とかの違いを考えなくて良くなるらしい!
branches: [$default-branch]
$default-branch
が効かない
⚠ $default-branch
にしておくと main
/ master
どちらでものブランチでも OK になるように GitHub の記事 に書かれていたのですが、実際には動作しないようです…
The documentation on custom workflow templates linked in that changelog post says this:
If you need to refer to a repository’s default branch, you can use the $default-branch placeholder. When a workflow is created using your template, the placeholder will be automatically replaced with the name of the repository’s default branch.
So $default-branch doesn’t seem to be supported in the actual workflow file.
cf. $default-branch not working · community · Discussion #26597 · GitHub
つまり、GitHub上のテンプレートを使用して作成した場合は $default-branch
がデフォルトブランチ名に置き換えられるけど、local で $default-branch
としたファイルを作成しても置き換えられないので効かないということっぽい。
local で workflow のファイルを作成するときは自分のデフォルトブランチ名 (main
/ master
) を直接指定する必要があるようです