エンジニア同士で話していると、CIどうしよう、今何がいいかなぁという話にたびたびなります。
CIサービスは複数ありますが、サーバーサイドビルドでSaaS型CIならCircleCIが今のところいいい感じです。(2.1を前提とする)
あるいはGitHub Actionsもとてもいい感触です。 現状Betaでpushイベント駆動なのでlintやビルドにはいい感じで利用できます。他のTagなどのイベントを利用できるようになるのが楽しみです。
今回は、CircleCI 2.1で利用できるOrbについてPR送ることを通して学んでみます。
概要
PRを出したくて仕組みを理解していくと何かと捗るのでいいですよ。 実情は、適切に動かすためにコンセプトと仕様を理解することに徹するだけです。 モチベーションだいじ。
Orbとは
CircleCI 2.1から利用できる機能で、JobsやCommandに定義していた処理を公開し、それを利用できる機能です。
利用方法はいたって簡単です。
YAMLでversion: 2.1を宣言し、orbsで利用するorbを定義、command/jobs/workflowのいずれかでOrbに定義されたcommandやjobをnamespace/コマンドのような記述で利用するだけです。
ドキュメントにあるミニマムな例が分かりやすいでしょう。
version: 2.1
orbs:
hello: circleci/hello-build@0.0.5
workflows:
"Hello Workflow":
jobs:
- hello/hello-build
Orbや使い方は、Orb Explorerを使うことで探すことができます。

Orbを利用するにあたり困らない例と困る例
さて公開されているOrbですが、いい感じで使える一方、あと一歩これが足りない、というケースがあります。
例えば、circleci/aws-s3@1.0.6を見てみましょう。
このOrbがよく考えられているのが、argumentsパラメーターを公開しておりOrbに定義がないパラメーターを受付可能にしていることです。 このパラメーターがあるおかげで、aws cliにOrbが想定していないパラメーターを渡すことができます。
version: 2.1 orbs: aws-s3: circleci/aws-s3@1.0.0 jobs: build: docker: - image: 'circleci/python:2.7' steps: - checkout - run: mkdir bucket && echo "lorum ipsum" > bucket/build_asset.txt - aws-s3/sync: from: bucket to: 's3://my-s3-bucket-name/prefix' arguments: | --acl public-read \ --cache-control "max-age=86400" overwrite: true - aws-s3/copy: from: bucket/build_asset.txt to: 's3://my-s3-bucket-name' arguments: '--dryrun'
一方で、circleci/aws-code-deploy@0.0.7を見るとこのargumentsパラメーターがないために、ごにょごにょできません。
version: 2.1 orbs: aws-code-deploy: circleci/aws-code-deploy@1.0.0 workflows: deploy_application: jobs: - aws-code-deploy/deploy: application-name: myApplication deployment-group: myDeploymentGroup service-role-arn: myDeploymentGroupRoleARN bundle-bucket: myApplicationS3Bucket bundle-key: myS3BucketKey
AWS CLIをCircle CIで使うときの注意
aws関連のOrbにargumentsを渡す口がなくて困る例として、aws cliの処理をassume roleによる認証で行いたい場合があります。
https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/cli-configure-role.html
assume roleを使うことで、認証は1つで、assume先のrole定義でアクセス先を切り替えることができます。
また、アクセス先の認証もassume roleのpolicyで縛ることができるため、AWSのアクセス制御的にも相性が良くなっています。
assume roleを利用するには、そのプロファイル定義とrole_arnとsource_profileを定義します。
```~/.aws/credentials [profile marketingadmin] role_arn = arn:aws:iam::123456789012:role/marketingadmin source_profile = user1
あとは、環境変数で`AWS_DEFAULT_PROFILE`を定義するか`AWS_PROFILE`で暗黙的に解決させる、あるいはコマンド実行時に`--profile プロファイル名`が必要です。
aws s3 cp .... s3://.... --marketingadmin
CircleCIの事情を考えると、circleciのaws系のOrbは`circleci/aws-cli`を必ず利用しています。 > [https://circleci.com/orbs/registry/orb/circleci/aws-cli] このOrbは非常に使い勝手が良く、`AWS_ACCESS_KEY`、`AWS_SECRET_ACCESS_KEY`、`AWS_DEFAULT_REGION`をCircle CIのProjectにあるEnvironment Variableを定義しておくだけでaws configureします。 一方で、このOrbはdefault profileを使う前提であるため任意のProfileを追加で生成できません。そのためassume roleを使うときには別途プロファイルを追加します。
- run:
command: |
mkdir -p ~/.aws
echo "[assume_role]" >> ~/.aws/credentials
echo "source_profile = default" >> ~/.aws/credentials
echo "role_arn = << parameters.role_arn >>" >> ~/.aws/credentials
circleci/aws-cliを自分で実行しない場合は、事前に`~/.aws`を作ってあげましょう。もし`circleci/aws-cli/install`と`circleci/aws-cli/configure`を自分で実行するなら不要です。 あとはコマンドにProfileを渡せばいいです。 で、前節の`circleci/aws-s3`の場合は、`arguments: '--profile assume_role'`とOrb実行時に渡せばいいのでok、となります。 余談ですがcircle ciの`aws-cli/configure`を使うなら、`AWS_DEFAULT_PROFILE`と`AWS_PROFILE`は使えません。 これらを定義していると`aws-cli/configure`でコケます、`AWS_DEFAULT_PROFILE`は`aws configure`が終わっている前提なのでまぁシカタナイ。
Traceback (most recent call last):
File "/usr/local/bin/aws", line 27, in
## circleci/aws-code-deployでarguments対応をPRする このあたりを理解した上で、一時対処として自分のCommandsで対応していたのですが、公式にあった方がいいので対応しました。 `circleci/aws-code-deploy@0.0.9`からargumentsが利用できます。 > https://github.com/CircleCI-Public/circleci-orbs/pull/140 なお、#140で対応漏れがあったので #144をすぐに出しましたが... はずかしい、Orbのテストがないと厳しいですね。 > https://github.com/CircleCI-Public/circleci-orbs/pull/144 対応は単純でargumentsパラメーターをつけて回るだけです。この時、whenがstring型に対しては`''`をfalseと認識することを利用しています。 > Empty strings are treated as a falsy value in evaluation of when clauses, and all other strings are treated as truthy. Using an unquoted string value that YAML interprets as a boolean will result in a type error. > https://circleci.com/docs/2.0/reusing-config/#parameter-types 加えて、`<<# parameters.xxxxx >> <</parameters.xxxxx>>`によってパラメーターがtrueの場合にのみ埋め込まれるのを使うとこう書けばいいことが分かります。
<<# parameters.arguments >> << parameters.arguments >><</parameters.arguments >>
これで、argumentを使って`--profile`を指定可能になりましたとさ、めでたしめでたし。
version: 2.1 orbs: aws-code-deploy: circleci/aws-code-deploy@1.0.0 workflows: deploy_application: jobs: - aws-code-deploy/deploy: application-name: myApplication deployment-group: myDeploymentGroup service-role-arn: myDeploymentGroupRoleARN bundle-bucket: myApplicationS3Bucket bundle-key: myS3BucketKey arguments: '--profile assume_role'