会社でGitlab CIはいじっていたのだが、Circle CIに初めて手をつけてみた。
で、基本のサンプルなど読みながら勉強していたのだが、
タギングとパッケージ公開それぞれのサンプルは多々あったものの、
タギングとパッケージ公開を一緒に行っている簡単なサンプルが見つからなかったので落ち着いた方法を載せておく。
調べ方が悪かっただけな気もする。
やりたいこと
- github上にあるnpmプロジェクトをCircleCIでCIしたい
- masterにマージされたときだけタギングしたい
- タギングされたらnpmにパッケージを公開したい
方法1: タギングとパッケージ公開を一連で行う。
一番素直に書くとこうなる。シンプルでわかりやすい。
- タギングしたときにワークフローが無限ループしてしまうのを防ぐのに、
npm version
するときのメッセージに[ci skip]
を入れてやる。 -
${github_email}
と${npm_token}
は環境変数から渡してやる。
必ずpatchリリースになってしまう点に目を瞑ればこの方法が一番シンプル。
version: 2.1
executors:
default:
docker:
- image: circleci/node:10.15
commands:
restore_modules:
steps:
- restore_cache:
keys:
- v1-npm-deps-{{ checksum "package-lock.json" }}
- v1-npm-deps-
save_modules:
steps:
- save_cache:
key: v1-npm-deps-{{ checksum "package-lock.json" }}
paths:
- node_modules
jobs:
setup:
executor: default
steps:
- checkout
- restore_modules
- run: npm install
- save_modules
test:
executor: default
steps:
- checkout
- restore_modules
- run:
name: Test
command: npm test
- store_artifacts:
path: coverage
tag_and_publish:
executor: default
steps:
- checkout
- restore_modules
- run:
name: Push a new tag
command: |
git config --global user.name "EnKen"
git config --global user.email "${github_email}"
npm version patch -m "v%s tagged [ci skip]"
git push --tags origin master
- run:
name: Publish to npm
command: |
echo "//registry.npmjs.org/:_authToken=${npm_token}" > ~/project/.npmrc
npm publish
workflows:
main:
jobs:
- setup
- test:
requires:
- setup
- tag_and_publish:
requires:
- test
filters:
branches:
only: master #masterブランチでだけ実行
方法2: タギングとパッケージ公開を別々のワークフローで行う。
基本的なやることは変わらないが、
「masterにマージ -> テスト -> タギング」までを一連のワークフローで実施し、
パッケージ公開はタギングをトリガーに別のワークフローで実施する方法。
version: 2.1
executors:
default:
docker:
- image: circleci/node:10.15
commands:
restore_modules:
steps:
- restore_cache:
keys:
- v1-npm-deps-{{ checksum "package-lock.json" }}
- v1-npm-deps-
save_modules:
steps:
- save_cache:
key: v1-npm-deps-{{ checksum "package-lock.json" }}
paths:
- node_modules
jobs:
setup:
executor: default
steps:
- checkout
- restore_modules
- run: npm install
- save_modules
test:
executor: default
steps:
- checkout
- restore_modules
- run:
name: Test
command: npm test
- store_artifacts:
path: coverage
push_tag:
executor: default
steps:
- checkout
- restore_modules
- run:
name: Push a new tag
command: |
git config --global user.name "EnKen"
git config --global user.email "${github_email}"
npm version patch -m "v%s tagged [ci skip]"
git push --tags origin master
publish_package:
executor: default
steps:
- checkout
- restore_modules
- run:
name: Publish to npm
command: |
echo "//registry.npmjs.org/:_authToken=${npm_token}" > ~/project/.npmrc
npm publish
workflows:
main:
jobs:
- setup
- test:
requires:
- setup
- push_tag:
requires:
- test
filters:
branches:
only: master
publish:
jobs:
- setup:
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- publish_package:
requires:
- setup
filters:
tags:
only: /^v.*/
branches:
ignore: /.*/
- publishのワークフローでは
filters
記述でbranches
のトリガーをすべて無視し、
tags
(vで始まるやつだけ)のトリガーでのみ動作するように記述する。 - publish_packageのジョブだけでなくsetupのジョブにも同じtagsの記述が条件を記述しないとトリガーが作動してくれない点に注意。
若干面倒くさいが、この方法であればminorやmajorバージョンを上げたい場合、
ローカルで手動タギングする運用が可能である。
npm version minor -m "%s tagged [ci skip]"
という感じで[skip ci]
をメッセージに入れてバージョンを上げれば、
pushした際にmainのワークフローを実行せず、publishだけ行うことができる。
結論
ということで、今回はパッケージ公開の柔軟さから方法2の方法を選択した。
ワークフローがループする問題の対処法が[ci skip]
しか思いつかなかったのだが、
もうちょっとスマートな方法あったりするんだろうか。