TL;DR
- CircleCIでビルド, テスト, デプロイを順序立てて実行するにはWorkflowsを使う
- Workflowsはローカル実行できないため、どうしてもローカルで確認したい場合は各ステップを
build
に切り出す - デプロイ先となるAWSのアクセスキーなどはCircleCIのEnvrionment Variablesに登録する
- CircleCI CLIのローカル実行ではEnvrionment Variablesを
-e
オプションで設定できる
サンプルプロジェクト
今回はNuxt.jsで作ったフロントエンドプロジェクトをビルド/テスト/デプロイします。
create-nuxt-app
は次の設定で作りました。
create-nuxt-app v3.4.0
✨ Generating Nuxt.js project in .
? Project name: map-sample
? Programming language: JavaScript
? Package manager: Yarn
? UI framework: Vuetify.js
? Nuxt.js modules: (Press <space> to select, <a> to toggle all, <i> to invert selection)
? Linting tools: ESLint, Prettier, StyleLint
? Testing framework: Jest
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/JAMStack hosting)
? Development tools: jsconfig.json (Recommended for VS Code if you're not using typescript)
? Continuous integration: None
? Version control system: Git
CircleCIのプロジェクト立ち上げ方
CircleCIのProjectsにはアカウント作成に使ったGitHub/Bitbucketのリポジトリが並んでいます。
このリポジトリの Set Up Project から設定できますが、リポジトリにあるCircleCIの設定ファイルを使用するUse Existing Configを選ぶと CIが即実行されます。 CircleCI側に環境変数の設定が必要でも即実行されます。
そのため、プロジェクトを新しく立ち上げる場合は次の手順がおすすめだと考えています。
- GitHub/Bitbucketにリポジトリを作成する
- CircleCIのSet Up ProjectからAdd Configをクリックして最低限動作する設定をリポジトリに追加する
- リポジトリをローカルにcloneして開発を始める
- 設定ファイル
.circleci/config.yml
を編集してCircleCI CLIで設定ファイルのバリデーションとローカル実行する。 - CircleCIのプロジェクト設定から必要な設定をする
- GitHub/BitbucketのリポジトリにpushしてCircleCIのサービスで実行する
すでにCircleCIの設定ファイルがある場合は、Use Existing Configをクリックして実行されたジョブを停止させるか失敗するまで待ちます。
複数のジョブに順序を設定する場合はWorkflowsを用いる
次の一連の作業をCircleCIに実行させます。
- Nuxtなどのプロジェクトから静的サイトを生成する
- プロジェクトのテストを実行する
- 生成された静的サイトをS3にデプロイする
この場合、Workflowsという機能を使います。 この機能を使わないと build
ジョブのみが実行されます。
設定ファイルの全体は次の通りです。
version: 2.1
orbs:
aws-s3: circleci/aws-s3@1.0.11
jobs:
build:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- checkout
- restore_cache:
name: Yarn パッケージのキャッシュの復元
keys:
- yarn-packages-{{ checksum "src/yarn.lock" }}
- run:
name: 依存関係のインストール
command: yarn install --frozen-lockfile
working_directory: src
- save_cache:
name: Yarn パッケージのキャッシュの保存
key: yarn-packages-{{ checksum "src/yarn.lock" }}
paths:
- ~/.cache/yarn
- run:
name: 静的サイトのビルド
command: yarn generate
working_directory: src
- persist_to_workspace:
root: .
paths:
- src
test:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- attach_workspace:
at: .
- run:
name: テスト(Jest)
command: yarn test
working_directory: src
- persist_to_workspace:
root: .
paths:
- src
deploy:
docker:
- image: circleci/python:3.7-stretch
working_directory: /tmp/work
steps:
- attach_workspace:
at: .
- aws-s3/sync:
from: src/dist
to: 's3://$AWS_TARGET_BUCKET'
arguments: |
--acl public-read \
--cache-control "max-age=86400"
overwrite: true
workflows:
build-deploy:
jobs:
- build
- test:
requires:
- build
- deploy:
requires:
- test
workflows
にWorkflowsで実行したいジョブを記述します。 requires
を指定することでジョブに順序を設定できます。
フロントエンドのビルドはcircleci/node
Node.jsを用いて開発しているため circleci/node
のイメージを使います。 yarn install
などYarnもこのイメージに入っています。
ステップ実行前の working_directory
はその通り checkout
などを実行する前に設定しようとするため、リポジトリ内のディレクトリは指定できません。
Monorepoなどの構成でステップに使うディレクトリを指定したい場合はステップ内で working_directory
を設定します。
jobs:
build:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- checkout
- run:
name: yarnパッケージの取得
command: yarn install
working_directory: src
- run:
name: 静的サイトのビルド
command: yarn generate
working_directory: src
- persist_to_workspace:
root: .
paths:
- src
環境変数を使う場合
process.env
など環境変数を使う場合はCircleCIのEnvironment Variablesで設定したものが使えます。
env: {
mapsKey: process.env.MAPS_KEY,
},
CircleCIのダッシュボードからプロジェクトを開き、Project SettingsのEnvironment Variablesをで設定できます。
CircleCI CLIでローカル実行する場合は -e
オプションを任意の数だけ追加して環境変数を渡すことができます。
circleci local execute -e KEY1=VALUE1 -e KEY2=VALUE2
Yarnパッケージのキャッシュ
また、Yarnパッケージは変更がなければ次回のビルドでキャッシュを使うことができます。これによりビルドが高速化します。
https://circleci.com/docs/ja/2.0/yarn/ をほぼそのまま使うと次の通りになります。
checksum
のコマンドだけステップで指定する working_directory
の影響を受けないため個別に設定する必要があります。
jobs:
build:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- checkout
- restore_cache:
name: Yarn パッケージのキャッシュの復元
keys:
- yarn-packages-{{ checksum "src/yarn.lock" }}
- run:
name: 依存関係のインストール
command: yarn install --frozen-lockfile
working_directory: src
- save_cache:
name: Yarn パッケージのキャッシュの保存
key: yarn-packages-{{ checksum "src/yarn.lock" }}
paths:
- ~/.cache/yarn
- run:
name: 静的サイトのビルド
command: yarn generate
working_directory: src
- persist_to_workspace:
root: .
paths:
- src
AWS S3のデプロイはcircleci/python + aws-s3 Orb
一方で、AWS S3にデプロイする場合はAWS CLIが動作するPythonの環境が必要です。イメージは circleci/python:3.7-stretch
を使っています。
CircleCIのEnvironment Variablesは次を設定します。
- AWS_REGION
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
AWS CLIをインストールするステップとデプロイに必要なコマンドを実行するステップをそのまま入れても対応できます。
aws-s3 Orbを使うとAWS CLIをインストールするステップを記述する必要がなくなり、コマンド実行も簡単な形で書くことができます。
aws-s3 Orbを使った場合もAWS CLIのインストールから始まるため実行時間はほぼ変わりません。
Orbを使う場合は、 versions: 2.1
と宣言してから 使用するOrbを定義します。次にstepsでOrbを指定して引数を渡すとつかうようになります。
version: 2.1
orbs:
aws-s3: circleci/aws-s3@1.0.11
...
deploy:
docker:
- image: circleci/python:3.7-stretch
working_directory: /tmp/work
steps:
...
- aws-s3/sync:
from: src/dist
to: 's3://$AWS_TARGET_BUCKET'
arguments: |
--acl public-read \
--cache-control "max-age=86400"
overwrite: true
--acl public-read
をつけないとバケットのWebホスティングを有効にしても403 Forbiddenになります。
ジョブで複数のimageを設定する方法は難しい
NodeでビルドしながらPython製のAWS CLIを使ったデプロイをしたい、を実現する方法としてジョブで使うイメージを複数指定する方法があります。
しかし、現在のバージョンで組み合わせられるイメージを見つけることができませんでした。
jobs:
build:
docker:
- image: circleci/node:14.15.0
- image: circleci/python:3.7
Error:
Unexpected environment preparation error: Error response from daemon: can't join IPC of container 53363ebc1e04ac6613b863d3fe80f6f28757182d7e725250c8981f55b8c4d3b2: non-shareable IPC (hint: use IpcMode:shareable for the donor container) > > > Step failed
Task failed
ジョブ間のデータはやり取りされない: persist_to_workspace
を使う
ジョブを続けて書いてWorkflowsで連結しても 前のジョブで生成したデータにはアクセスできません。
次のジョブに移る前に persist_to_workspace
と宣言してから、次のジョブで attach_workspace
を使ってデータを取り出します。
persist_to_workspace
のroot
はジョブの作業ディレクトリから相対/絶対パスで指定し、paths
はその中で次のジョブに残したいディレクトリを指定します。
attach_workspace
のat
は同様にジョブの作業ディレクトリから相対/絶対パスで指定します。
jobs:
build:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- run:
name: yarnパッケージの取得
command: yarn install
working_directory: src
- run:
name: 静的サイトのビルド
command: yarn generate
working_directory: src
- persist_to_workspace:
root: .
paths:
- src
test:
docker:
- image: circleci/node:lts
working_directory: /tmp/work
steps:
- attach_workspace:
at: .
- run:
name: テスト(Jest)
command: yarn test
working_directory: src
CircleCI CLIのローカル実行ではWorkflowsはサポートされない
Workflowsを指定しても build
ジョブだけが実行されます。Workflowを通して動作確認したい場合はローカルではなくCircleCIのサービスで実行する必要があります。
ジョブを選んで実行する方法が見つからなかったので、各ジョブを切り出して build
ジョブとして実行するようにしています。
もちろん「静的サイトのビルドをしないと deploy
ジョブで必要な dist
にファイルが生成されない」など前のジョブに依存する場合は前提となる状態を再現しています。
ローカル実行は persist_to_workspace
もサポートされない
persist_to_workspace
を使ったジョブで circleci local exec
を実行すると次のメッセージが表示されます。
こちらもCircleCIのサービス側で実行すると正しく処理されます。
Warning: skipping this step: Missing workflow workspace identifiers, this step must be run in the context of a workflow
参考
ワークフローを使用したジョブのスケジュール - CircleCI
https://circleci.com/docs/ja/2.0/workflows/
CircleCI2.0のWorkflowを試してみる - Qiita
https://qiita.com/sawadashota/items/ba89382d563bc90bb5cd
環境変数の使用 - CircleCI
https://circleci.com/docs/ja/2.0/env-vars/
CircleCI のローカル CLI の使用 - CircleCI
https://circleci.com/docs/ja/2.0/local-cli/#limitations-of-running-jobs-locally
デプロイの構成 - CircleCI
https://circleci.com/docs/ja/2.0/deployment-integrations/
Nuxt.js+CircleCIで静的ページをAWSのS3へデプロイする - Qiita
https://qiita.com/nishinoshake/items/21af46b4101392ffc666
CircleCI での Yarn (npm の代替) の使用 - CircleCI
https://circleci.com/docs/ja/2.0/yarn/
Configuring CircleCI - CircleCI
https://circleci.com/docs/2.0/configuration-reference/#persist_to_workspace