何で?
通常web系のビルドタスクとかminify化は作業環境上で行ってpushすることが多いんで、こういったサイクルは自分ではあまりやらないです。
だけど、チームにデザイナーさんとか非エンジニア職の人がいる場合、作業環境を無理に揃えるよりもハードルが低くて良い選択肢になるんじゃないかと。
CircleCI側の設定
CircleCIは使い始めた時点でGitHubと連携してるので、設定なしでGitHubにpush出来る予感がしたんですが気のせいでした。
CircleCI側の秘密鍵はリポジトリに対してread権限しか持ってないのでpushできません。
なのでwrite権限を持った秘密鍵を用意して別途登録する必要があります。
https://circleci.com/gh/<ユーザor組織名>/<リポジトリ名>/edit#ssh
用意した秘密鍵は上記から追加できます。
今回の場合はHostname
にgithub.com
を設定しPrivate Key
に秘密鍵の内容をコピペして登録すれば完了です。
circle.ymlのサンプル
circle.yml
の内容はプロジェクト毎に違うので、あくまでサンプルです。
machine:
timezone: Asia/Tokyo
node:
version: 0.12.0
dependencies:
cache_directories:
- node_modules
override:
- npm install
test:
pre:
- npm run build
override:
- npm test
deployment:
github:
branch: develop
commands:
- ./scripts/release_push.sh
上記ではdevelop
ブランチにpushされた時に./scripts/release_push.sh
が実行される内容になってます。
./scripts/release_push.sh
の中身は単純なgitコマンドの集合です。(後述)
今回のストーリーとしてはnpm run build
で諸々生成されたファイルをrelease
ブランチにコミットしてgithubにpushするという感じです。
CircleCIビルド実行時の振り分け
ちょっと寄り道ですが、develop
ブランチにpushするたびに毎回release
ブランチが切られるのは嫌だという場合はCircleCI REST APIを使って、明示的に実行させる方法もあります。
curl \
--header "Content-Type: application/json" \
--data '{"build_parameters": {"USE_RELEASE_PUSH": 1}}' \
--request POST \
https://circleci.com/api/v1/project/<ユーザor組織名>/<リポジトリ名>/tree/develop?circle-token=<circleci_api_token>
上記のようにbuild_parameters
に設定した値を、CircleCIの実行コンテナ内で環境変数として利用することが出来ます。
なので./scripts/release_push.sh
内で$USE_RELEASE_PUSH
をチェックして、処理を実行するかしないか判断させれば目的は達成されるはずです。
さらに、このAPIをSlackなどのツールと連携させれば簡単なChatOpsが出来て便利です。
release_push.sh
のサンプル
最後に./scripts/release_push.sh
のサンプルです。
#!/bin/bash
# gitユーザ設定
git config --global user.email "foo@bar.baz" #コミットユーザの有効なメールアドレス
git config --global user.name "hoge" #コミットユーザの名前
# リリースバージョン名
CI_RELEASE_VERSION=`date +"v%Y%m%d%H%M%S"`
# リリースブランチ名
CI_RELEASE_BRANCH="release/${CI_RELEASE_VERSION}"
# リモートリポジトリ
CI_REMOTE_REPOSITORY="git@github.com:${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}.git"
# リリースブランチ作成
git checkout -b ${CI_RELEASE_BRANCH}
#変更ファイルををすべて追加
git add --all :/
#コミット
git commit -m "[auto] release branch (${CI_RELEASE_VERSION})"
#リモートにプッシュ
git push ${CI_REMOTE_REPOSITORY} ${CI_RELEASE_BRANCH}
突然出てきたCIRCLE_PROJECT_USERNAME
とCIRCLE_PROJECT_REPONAME
は、元々CircleCIにある環境変数になります。
前述した、実行の振り分けを利用する場合はif
文などで実行判定処理を入れるだけです。
また、GitHub側のREST APIを使えばPull Request
まで含めて自動化出来ます。
curl \
--header "Accept: application/vnd.github.v3+json" \
--data "{\"title\": \"[auto] ${CI_RELEASE_BRANCH}\", \"head\":\"${CI_RELEASE_BRANCH}\", \"base\":\"master\" }" \
https://api.github.com/repos/${CIRCLE_PROJECT_USERNAME}/${CIRCLE_PROJECT_REPONAME}/pulls?access_token=<github_api_token>
※APIトークンはソースに記述せず、CircleCIの設定画面から環境変数などに登録して利用します。
まとめ
GitHubとCircleCI、あと今回は触れてませんがHubot/Slackの相互連携は、それぞれの目的に合わせて柔軟に自動化が行える反面、こだわり過ぎると無限に時間を吸われそうな印象です。
自動化環境作るの楽しい。