概要
既にある程度の開発が進んでいるBitbucket上のプロジェクトにPipelinesを使って継続的あれこれする機能を追加しようという、解説というよりも私の挑戦の記録です。
前回は初のPipelinesの利用として「手動でテストを実行」しました。
その2では「オープンソースの開発で、生成されたテスト結果を開発リソースとして共有する」シーンをを想定して、テスト結果をAWS S3にアップロードするまでを扱います。記事の分量から、CloudFrontでの配信やビルドステータスへのアーティファクトの公開URLの追加は次回以降に扱います。
記事内で使用している環境
- Java17
- Gradle7.6
- JUnit,JaCoCoでテストのレポートを作成
- BitbucketのリポジトリでPipelinesを有効化している(その1を読んでいる)
- AWSの管理者アカウントを持っている
Pipelinesと生成物
Pipelines上で実行されたビルドも、ビルドツールの指定通りに成果物を生成します。生成場所はGradleの標準的な設定であればbuild
ディレクトリ内となります。
この生成物をダウンロードしたり、Pipelinesの別ステップで利用できるようにするためには、yml内で「アーティファクト」として指定する必要があります。
アーティファクトの指定には、step
プロパティ内でartifacts
を使用して生成物が配置されるディレクトリを指定します。
この指定はリポジトリのルートからの相対指定となります。また、globパターンを使用して複数のファイル、ディレクトリに一致させることが出来ますが、.
や..
は使用できません。つい./build/**
などとしたくなりますが、この制約のために機能しません。
Gradleでの標準的な設定での指定の例は下記のようになります。
#前略 stepのみ抜粋
- step
scripts:
- ./gradlew test
artifacts:
- build/reports/tests/** #JUnitのテストレポートすべて
- build/libs/** #Jar
正しく指定できていれば、アーティファクトを含むステップの終了時にそれが保存され、パイプラインのログ画面のArtifacts
タブから確認とダウンロードができます。
個人のリポジトリであればこれだけでも十分ともいえるのですが、アーティファクトの保存期間は14日間、1容量GB以下という制限もありますので、過去のバージョンを保存しておく必要がある、などの場合には別のストレージにアップロードするなどの手段が必要になります。
ファイル展開用にS3をセットアップする
そこでこの記事ではS3にテストレポートをアップロードして、後にブラウザから閲覧できるようにしてみます。
ここからはしばらく、AWSコンソールでの作業になります。
採用する構成
ストレージにはS3を使用しますが、Jarなど比較的大きなバイナリを含み、プロジェクトが人気になると膨大なアクセスが発生することも想定して、CloudFrontからファイルを配信します。
検索するとS3にhtmlを配置する場合の様々な記事が出てきますが、現在1はこの組み合わせを利用するのが一番シンプルに実現できるようです。
PipelinesからS3にアップロードする処理にはAtlassian公式からaws-s3-deployパイプが用意されていますので、これを使用します。
そしてこのパイプの使用法にBitbucket Pipelines OpenID Connect を使用して AWS にデプロイするが紹介されていますので、これを組み合わせて使用します。
この組み合わせにすることでアクセスキーとシークレットの脆弱性を避けることが出来る上、AWS側ではBitbucketPipelinesとCloudFrontに対してそれぞれロールを割り当てるだけでアクセス管理をできるようになりますので、煩雑な設定がほとんどなくなります。
S3バケットを作成する
それではまず、AWSでS3のバケットを作成します。
S3のコンソールから、「バケットを作成」をクリックします。
名前、リージョン等、多数の設定項目が表示されますが、ここでは名前とリージョン以外のバケットの設定はすべてデフォルトで問題ありません。
記事のタイトルにもあるようにCloudFrontから配信するため、「静的ウェブサイトホスティング」や「パブリックアクセスの設定」は変更しません。
Pipelinesからのアップロードを行うための権限は、IAMで設定します。
IAMでIDプロバイダにBitbuketPipelineを登録する
Bitbucket Pipelines OpenID Connect を使用して AWS にデプロイするの手順に従って、リポジトリのPipelinesがS3を利用できるようにしていきます。
IAMのサイドメニューから「IDプロバイダ」開きます。プロバイダのタイプで「OpenID Connect」を選択すると下図のような画面になります。
この画面に設定する内容は、Bitbucketのリポジトリ設定>OpenID Connectから確認できます。ここで表示されるIdentity provider URL
とAudience
がIAM側のプロバイダのURL
と対象者
に相当します。
プロバイダのURLを張り付けたあと、「サムプリントを取得」で表示されるサムプリントはa031c46782e6e6c662c2c87c76da9aa62ccabd8e
となります。確認出来たら対象者も張り付け、「プロバイダを追加」で登録完了です。
作成したプロバイダにロールを作成して割り当てる
引き続き、作成したプロバイダ情報とS3へのアクセス許可を持ったロールを紐づけます。
作成されたプロバイダを選択するとプロバイダの詳細画面へ移動します。
プロバイダ名の下に「ロールの割り当て」ボタンが表示されていますので、それをクリックします。
ダイアログが表示され「新しいロール作成」を選択すると、プロバイダを選択する画面に移動します。
先ほど作成したPipelinesのプロバイダとAudience
(なぜかここは翻訳されてない)を選択して、「次のステップ」へ進みます。
上図のようにフィルタにS3
と入力し、AmazonS3FullAccess
にチェックを入れ「次のステップ」に進みます。
タグの付与は任意ですが、プロジェクト名などをタグとして追加しておくことをお勧めします。
最後にロールの名前と説明を入力しますが、説明にも一部の記号と英数字しか入力できないことに注意してください。「信頼されたエンティティー」が設定するリポジトリのパイプラインであること、ポリシーがS3FullAccessであることを確認して、「ロールの作成」で完了です。
これでS3にファイルをアップロードするためのAWS側の作業は完了しました。
Pipelinesにパイプを追加する
Bitbucketのリポジトリに戻って、S3へのアップロードを行うようにパイプラインを編集します。
こちらにもいくつかの準備が必要となり、また、今後を見据えてymlの構造の変更も行います。
Pipelinesの変数、リポジトリ変数
パイプの使用には、パイプが指定する変数に値を設定する必要があります。
この変数はyml内部で直接指定することも可能ですが、リポジトリやワークスペースに変数を登録することが可能です。
これらの変数はパイプラインを実行するコンテナの環境変数として読み込まれ、値だけを変更するような場合にコミットを行う必要がなくなります。また、この変数に「Secured」を指定することで、ログや画面上に値が表示されないようにできます。他システムとの連携時には特に重宝する機能です。
このほか、変数とシークレットには、デフォルトで使用できる変数のリストが掲載されています。ビルド番号やパイプラインが起動されたブランチなどを識別することが可能なため、積極的に利用していきましょう。
aws-s3-deployパイプで使用される変数
aws-s3-deployパイプから、必要な変数を確認します。*
のついた変数は「パイプを使用する際に常に指定する変数」**
のついた変数は「必須だが、アカウント、リポジトリ、環境変数に指定されていれば自動的に読み取られる変数。実行時に上書き可能」となっています。つまり、*
はymlに直接記入、**
はリポジトリ変数に登録する変数とするとよいでしょう。
aws-s3-deployパイプのAdvanced example:に、OpenID Connectを使用する例もありますので、これを参考にします。
まず、リポジトリ変数にAWS_DEFAULT_REGION
とAWS_OIDC_ROLE_ARN
を登録します。
リポジトリ設定の下部に「PIPELINES」のセクションがあり、その中に「Repository variables」のページがあります。
変数の追加は名前と値を入力して「add」を押すだけです。アクセスキーなど値が見えてはいけない変数にはSecuredのチェックを入れてから「add」します。
AWS_DEFAULT_REGION
の値はS3バケットを作成したリージョン名、AWS_OIDC_ROLE_ARN
の値は作成したプロバイダにロールを作成して割り当てるで作成したロールのARNとなります。
また、これ自体は必須の変数ではありませんが、S3で作成したバケット名をBUCKET_NAME
として登録しておきます。これは、このリポジトリに設定された他のパイプラインでS3を利用するときに、パイプの必須変数であるS3_BUCKET
に指定するパス(正確にはプレフィックス)の生成に利用する目的と、以降にバケット自体が変更になる可能性もあるためです。
これらを利用してaws-s3-deployパイプをパイプラインに追加していきます。
bitbucket-pipelines.ymlの編集
例によってバリデーターを開いてそこで編集していきます。2
バリデーターに前回のymlをコピペします。
image: eclipse-temurin:17
definitions:
caches:
gradlewrapper: ~/.gradle/wrapper
pipelines:
custom:
manualTest:
- step:
caches:
- gradle
- gradlewrapper
script:
- ./gradlew test
テスト結果をアーティファクトに指定する
前述のように、stepの終了時に生成物は破棄されてしまいますので、testタスクを実行しているstep
にartifacts
を追加します。
このとき、あくまでもパイプラインの動作確認であればbuild/**
という指定もあり得ますが、ここでアーティファクトに指定したディレクトリは以降のすべてのstepで読み込まれるため、少しでも処理を軽くしたいのであれば必要なディレクトリのみを指定した方が効率的です。ここではJUnitの標準であるbuild/reports/tests/test/**
3とします。
build.gradleで別の場所を指定している場合は、当然それに合わせて変更が必要です。また、私の環境ではJaCoCoでカバレッジのレポートも生成していますが、それもtestタスクに組み込んでいるため、同じディレクトリ内にcoverage
ディレクトリを指定して出力させています。
アーティファクトを指定したymlは下記のようになります。
image: eclipse-temurin:17
definitions:
caches:
gradlewrapper: ~/.gradle/wrapper
pipelines:
custom:
manualTest:
- step:
caches:
- gradle
- gradlewrapper
script:
- ./gradlew test
artifacts:
- build/reports/tests/test/** #JUnitの出力先ディレクトリ内をアーティファクトに指定
アップロードするstepの作成
まず簡単な変更ですが、ステップが増えたので各step
にname
プロパティを追加して名前を付けます。ステップの名前はパイプラインの実行時のログや結果表示に使用されます。
ここでは、先に作成済みのtestタスク実行部分はTest
、パイプの実行部分はUpload Reports
とします。
パイプの実行にはパイプの使用法の通り、必要な変数を宣言してパイプに渡します。
また、OpenID Connectを利用したaws-s3-deployパイプの使用では、使用するstep
にoidc
プロパティを追加し、true
を設定する必要があります。
必須の変数のうち、AWS_DEFAULT_REGION
はパイプの必須変数でリポジトリ変数に登録してあるため、記述を省略できます。
AWS_OIDC_ROLE_ARN
もリポジトリ変数に登録していますが、こちらはパイプの必須の変数ではないため宣言が必要です。少し不思議な感じがしますが、パイプの変数にリポジトリ変数を展開させます。
S3_BUCKET
には、どのビルドのテスト結果がわかるようなパスを指定します。ここでは、テスト結果はビルドの番号に依存するため、ビルドごとにバケット内にbuild_<ビルド番号>
のフォルダを作ってアップロードするようにします。。リポジトリ変数に登録したバケット名と、ビルド番号を表すBITBUCKET_BUILD_NUMBER
を組み合わせて、$BUCKET_NAME/build_$BITBUCKET_BUILD_NUMBER
と指定しました。
LOCAL_PATH
はアーティファクトに指定したフォルダを指定します。ここではbuild/reports/tests/test
です。
image: eclipse-temurin:17
definitions:
caches:
gradlewrapper: ~/.gradle/wrapper
pipelines:
custom:
manualTest:
- step:
name: Test #ステップが増えるので名前を付けて区別
caches:
- gradle
- gradlewrapper
script:
- ./gradlew test
artifacts:
- build/reports/tests/test/** #JUnitの出力先ディレクトリをアーティファクトに指定
- step:
name: Upload Reports #作業内容がわかる名前を
deployment: test
oidc: true
script:
- pipe: atlassian/aws-s3-deploy:1.1.0 #パイプの実行
variables: #パイプに渡す変数
AWS_OIDC_ROLE_ARN: $AWS_OIDC_ROLE_ARN #必須ではないため宣言が必要
S3_BUCKET: $BUCKET_NAME/build_$BITBUCKET_BUILD_NUMBER #例えばbucket/build_10などに展開される
LOCAL_PATH: build/reports/tests/test #アーティファクトの存在するディレクトリ
deployment
プロパティ
このプロパティはBitbucketに生成物のデプロイを追跡させます。デフォルトで指定可能な値はtest
,staging
,production
です。デプロイの性質によって分けて追跡できるようになっています。
ここではテストのレポートですのでtest
を指定していますが、リポジトリ設定から別のデプロイを設定することもできます。
この指定が存在することで、リポジトリのサイドメニュー「Deployments」から、デプロイを行ったコミット・ビルドの情報や、デプロイの履歴を確認できます。
デプロイの詳細はデプロイを設定、監視するを参照してください。
ymlの変更をコミットして実行してみる
バリデーター上でエラーがなければ、リポジトリの「ソース」からymlを表示し、「編集」ボタンからエディタを有効にしてバリデーターの内容をコピーして、コミットします。2
手動でのパイプラインの実行はサイドメニュー「パイプライン」でパイプラインの履歴を表示し、「Run pipeline」からブランチと実行するパイプライン(ここではmanualTest)を選択して「Run」です。
前回と同様、コンソール風の画面にログを表示しながらパイプラインが実行されます。今回はステップがふたつあるため、左側のステータス表示が2段になり、「Test」と「Upload Reports」になっているはずです。
ふたつとも無事に緑になったら、S3のコンソールからバケットのオブジェクトを確認してください。S3_BUCKET
に指定した名前のフォルダが生成されていれば、アップロードは成功です。
次の記事
ここまでご閲覧いただきありがとうございます。
次の記事ではCloudFrontを通じてレポートをブラウザに表示する、ビルドステータスにレポートへのリンクを追加する、など、今回の処理に付随する機能の設定を行います。