記事
チュートリアル
インタラクティブ ガイド
Concourse-CI と Atlassian Open DevOps の統合
ほとんどのチームが、自分たちのニーズを満たしてくれる独自のツールを導入しているか、長年使用している従来のツールを持っています。これらのツールは、チームの開発プロセスに不可欠ですが、Jira とすぐに統合できる機能がありません。幸い、Cloud 開発者向けドキュメンテーション - アトラシアン開発者に記載されている Atlassian REST API を使用すれば、カスタム統合を簡単に構築できます。Concourse-CI は CI/CD 製品であり、この記事の執筆時点では、Atlassian Marketplace に統合されていません。この記事では、Atlassian REST API を使用して Jira と Concourse-CI の基本的な統合を構築する方法を説明します。
前提条件
必要なドキュメントを利用して Docker、docker-compose、Concourse-CI をセットアップします。Concourse-CI は Docker 上で動作し、docker-compose スクリプトが提供されるため簡単に始められます。
アトラシアンの ImageLabeller デモ アプリについては、こちらをご覧ください。この記事では、Concourse-CI を使用して ImageLabeller の SubmitImage コンポーネントを AWS にデプロイする方法について説明します。
Docker
関連ドキュメントに従って Docker と docker-compose をセットアップします。
Docker: https://docs.docker.com/get-docker/
docker-compose: https://docs.docker.com/compose/install/
Concourse-CI
Docker と docker-compose をインストールすれば、提供された docker-compose.yml ファイルを使用して Concourse-CI を起動できます。
Concourse-CI のクイック スタート ガイドに従い、https://concourse-ci.org/quick-start.html#docker-compose-concourse から始めましょう。このガイドでは、認証情報の Concourse-CI への安全な提供が求められています。ガイドでは、この目的のために Concourse-CI AWS Secrets Manager 統合を使用しています。
Concourse-CI と AWS Secrets Manager の統合
Concourse-CI を AWS Secrets Manager と統合する方法に関するドキュメントはこちらをご覧ください。ドキュメントの指示に従って統合を有効にして始めましょう。
Concourse-CI の起動に使用される docker-compose.yml ファイルは、統合するためにわずかに修正が必要です。Concourse-CI が提供しているデフォルトの docker-compose.yml ファイルを取り出し、以下を追加します:
CONCOURSE_AWS_SECRETSMANAGER_ACCESS_KEY、CONCOURSE_AWS_SECRETSMANAGER_SECRET_KEY、CONCOURSE_AWS_SECRETSMANAGER_REGION
version: '3'
services:
concourse-db:
image: postgres
environment:
POSTGRES_DB: concourse
POSTGRES_PASSWORD: concourse_pass
POSTGRES_USER: concourse_user
PGDATA: /database
concourse:
image: concourse/concourse
command: quickstart
privileged: true
depends_on: [concourse-db]
ports: ["8080:8080"]
environment:
CONCOURSE_POSTGRES_HOST: concourse-db
CONCOURSE_POSTGRES_USER: concourse_user
CONCOURSE_POSTGRES_PASSWORD: concourse_pass
CONCOURSE_POSTGRES_DATABASE: concourse
CONCOURSE_EXTERNAL_URL: http://localhost:8080
CONCOURSE_ADD_LOCAL_USER: test:test
CONCOURSE_MAIN_TEAM_LOCAL_USER: test
# instead of relying on the default "detect"
CONCOURSE_WORKER_BAGGAGECLAIM_DRIVER: overlay
CONCOURSE_CLIENT_SECRET: Y29uY291cnNlLXdlYgo=
CONCOURSE_TSA_CLIENT_SECRET: Y29uY291cnNlLXdvcmtlcgo=
CONCOURSE_X_FRAME_OPTIONS: allow
CONCOURSE_CONTENT_SECURITY_POLICY: "*"
CONCOURSE_CLUSTER_NAME: tutorial
CONCOURSE_WORKER_CONTAINERD_DNS_SERVER: "8.8.8.8"
CONCOURSE_WORKER_RUNTIME: "containerd"
CONCOURSE_ENABLE_ACROSS_STEP: "true"
CONCOURSE_ENABLE_PIPELINE_INSTANCES: "true"
CONCOURSE_AWS_SECRETSMANAGER_ACCESS_KEY: <add access key>
CONCOURSE_AWS_SECRETSMANAGER_SECRET_KEY: <add secret key>
CONCOURSE_AWS_SECRETSMANAGER_REGION: <add a region>
統合のセットアップが完了し、Concourse-CI が稼働して統合が有効になったら、以下のシークレットを AWS Secrets Manager に追加します。
/concourse/main/bitbucket_username
/concourse/main/bitbucket_api_key
/concourse/main/bitbucket_ssh_key
/concourse/main/docker_username
/concourse/main/docker_api_key
/concourse/main/aws_access_key_ID
/concourse/main/aws_secret_access_key
/concourse/main/aws_default_Region
読者がコードに Bitbucket を使用せず、Docker リポジトリとして JFrog を使用していない場合は、Bitbucket と Docker のシークレットを置き換えなければなりません。読者の個々のツールに合わせた調整は、課題練習として残します。
Concourse-CI との連携
docker-compose up -d の実行前後に docker ps -a を実行して、Concourse-CI が正しく起動したことを確認します。
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
docker-compose up -d
Creating network "restapiproject_default" with the default driver
Creating restapiproject_concourse-db_1 ... done
Creating restapiproject_concourse_1 ... done
docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd2b5afd0ac7 concourse/concourse "dumb-init /usr/loca…" 3 seconds ago Up 2 seconds 0.0.0.0:8080->8080/tcp restapiproject_concourse_1
bd9005b45636 postgres "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 5432/tcp restapiproject_concourse-db_1
fly -t tutorial login -c http://localhost:8080 -u test -p test を実行したら、http://localhost:8080/ にアクセスします。
fly -t tutorial login -c http://localhost:8080 -u test -p test
logging in to team 'main'
target saved
この時点では定義されているパイプラインはありません。
Hello World のパイプライン
この Concourse-CI のドキュメント: https://concourse-ci.org/tutorial-hello-world.html に従って、Hello World のパイプラインをセットアップします。これは Fly cli を導入し、コマンドラインからの Concourse-CI の操作に慣れるために必要なものです。
次のセクションでは、Concourse-CI を使用し、Golang で記述されている AWS Lambda を単一の AWS リージョンにデプロイする方法と、そのプロセスの一環として Jira 課題のアップデートを記述する方法について説明します。
SubmitImage を Concourse-CI でデプロイする
Concourse-CI で SubmitImage Lambda をデプロイするには 3 つのステップがあります。最初のステップでは、Jira Cloud REST API を使用して Jira 課題にコメントを書く簡単な bash スクリプトを記述します。これは、自分で作成できる最も簡単な統合です。次のステップでは、Golang AWS Lambda を構築し、デプロイするために必要なツールを使った Docker イメージを作成します。最後のステップでは、Concourse-CI の設定ファイルを 2 つ記述します。最初の設定ファイル parent.yml は、SubmitImage リポジトリに新しいブランチがないかを監視し、新しいパイプラインをスプールしてそのブランチからのコミットをデプロイします。2 つ目の設定ファイル child.yml は、変更をデプロイするために必要な一連のステップを定義します。
ステップ 1 - REST API 経由で Jira 課題を更新する
この update スクリプトは、Jira Cloud プラットフォーム REST API を使用して、特定の Jira 課題にコメントを記述します。スクリプトの実行ごとに設定が必要な必須パラメーターは 5 つあります。jiraUserName、jiraApiToken、および workspace は通常、特定のパイプラインについては、毎回の実行で同じです。IssueKeyは、デプロイされる特定のブランチのブランチ名によって異なります。Jira のベスト プラクティスとしては、特定の課題に取り組むときには Jira 課題 ID をブランチ名に含め、メッセージをコミットすることが推奨されます。この記事ではベスト プラクティスに従っていること、およびブランチ名が Jira 課題 ID に等しいことを前提としています。
パラメーターを見つける方法
Jira ユーザー名
Jira ユーザー名は、Jira へのログインに使用されるメール アドレスです。
Jira API トークン
アカウント設定に進みます
[Security] をクリックします
[API トークンの作成と管理] をクリックします
ワークスペース
たとえば、https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203 などの Jira インスタンスの URL では、ワークスペースは pmmquickstartguide01 です。
課題キー
たとえば、https://pmmquickstartguides01.atlassian.net/jira/software/projects/IM/boards/1?selectedIssue=IM-203 などの Jira 課題の URL では、Jira 課題キーは IM-203 です。統合機能によって正しい場所にアップデートが書き込まれるように、Jira 課題 ID をコミット メッセージとブランチ名に含めます。
コメント
コメントはどのようなものでもかまいません。
update スクリプト
update スクリプトは、Jira 課題コメント REST API エンドポイントを使用するシンプルな bash シェル スクリプトです。この API 呼び出しのドキュメントはこちらをご覧ください。提供されたパターンに従って追加の API 呼び出しを行うことによって、さらに緊密に統合できるようにスクリプトを変更できます。このスクリプトを concourse-ci-integration.sh という名前のファイルにコピーして、Bitbucket または updateScript という名前の GitHub リポジトリに入れます。
#!/usr/bin/env bash
addCommentToIssue() {
printf "addCommentToIssue\n"
local jiraUsername=$1
shift
local jiraApiToken=$1
shift
local workspace=$1
shift
local issueKey=$1
shift
local comment=$1
shift
curl -s --request POST \
--url 'https://'"${workspace}"'.atlassian.net/rest/api/3/issue/'"${issueKey}"'/comment' \
--user "${jiraUsername}"':'"${jiraApiToken}" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"body": {
"type": "doc",
"version": 1,
"content": [{
"type": "paragraph",
"content": [{
"text": "'"${comment}"'",
"type": "text"
}]
}]
}
}' | jq
}
main() {
printf "main\n"
while getopts ":c:k:o:u:t:w:" opt; do
case $opt in
c)
local comment=$OPTARG
;;
k)
local issueKey=$OPTARG
;;
o)
local op=$OPTARG
;;
u)
local jiraUsername=$OPTARG
;;
t)
local jiraApiToken=$OPTARG
;;
w)
local workspace=$OPTARG
;;
*)
printf "invalid option: -${OPTARG}\n" >&2
exit 1
;;
esac
done
case $op in
ac)
addCommentToIssue ${jiraUsername} ${jiraApiToken} ${workspace} ${issueKey} "${comment}"
;;
*)
printf "invalid op: ${op}\n" >&2
exit 1
;;
esac
}
main "$@"
ステップ 2 - カスタムの Dockerfile
Golang で記述された AWS Lambda を構築し、デプロイするために必要なツールを使って、カスタムの Dockerfile を作成します。Dockerfile によっていくつかのユーティリティがインストールされ、AWS、SAM、Golang が追加されます。画像の Git はステップ 1 で Bitbucket リポジトリから作成した update スクリプトのクローンを作成します。この Bitbucket リポジトリは、update スクリプトを保存するために作成したリポジトリに置き換える必要があります。Docker がこの Dockerfile を構築し、それを Docker リポジトリにプッシュします。
Dockerfile
# syntax = docker/dockerfile:1.3
FROM ubuntu:20.04
MAINTAINER wmarusiak@atlassian.com
WORKDIR /workspace
RUN apt-get update \
&& apt-get -y upgrade \
&& apt-get -y install curl unzip tar openssh-client git jq
RUN curl https://github.com/aws/aws-sam-cli/releases/latest/download/aws-sam-cli-linux-x86_64.zip -L -o aws-sam-cli.zip \
&& mkdir sam-installation \
&& unzip aws-sam-cli.zip -d sam-installation \
&& ./sam-installation/install \
&& sam --version
RUN curl https://go.dev/dl/go1.18.2.linux-amd64.tar.gz -L -o go.tar.gz \
&& rm -rf /usr/local/go \
&& tar -C /usr/local -xzf go.tar.gz
RUN mkdir -p -m 0700 ~/.ssh && ssh-keyscan bitbucket.org >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone git@bitbucket.org:pmmquickstartguides01/updatescript.git
ENV PATH $PATH:/usr/local/go/bin
ステップ 3 - Concourse-CI デプロイ パイプライン yaml ファイル
concourse という新しいリポジトリを作成し、その中に 2 つのファイルを入れます。Parent.yml は正規表現と一致する新しいブランチがないかどうか、リポジトリを監視するパイプラインを作成するものです。branch_regex は IM- で始まるすべてのブランチと一致する IM-* です。Parent.yml は、正規表現の IM-* と一致する新しいブランチが作成されると、child.yml の設定を使用して新しいパイプラインを作成するものです。このファイルは、自分のバージョンの SubmitImage リポジトリを指し示すよう更新してください。SubmitImage コードについてはこちらを参照してください。このリポジトリのコードを書き込み権限のあるリポジトリにコピーします。
parent.yml
resource_types:
- name: git-branches
type: registry-image
source:
repository: aoldershaw/git-branches-resource
resources:
- name: feature-branches
type: git-branches
source:
uri: git@bitbucket.org:pmmquickstartguides01/submitimage.git
branch_regex: IM-*
private_key: ((bitbucket_ssh_key))
- name: examples
type: git
source:
uri: git@bitbucket.org:pmmquickstartguides01/concourse.git
private_key: ((bitbucket_ssh_key))
jobs:
- name: set-feature-pipelines
plan:
- in_parallel:
- get: feature-branches
trigger: true
- get: examples
- load_var: branches
file: feature-branches/branches.json
- across:
- var: branch
values: ((.:branches))
set_pipeline: dev
file: examples/child.yml
vars: {branch: ((.:branch.name))}
Child.yml は 4 つのステップからなるパイプラインを定義しています。まず、sam validate を実行し、AWS CloudFormation template.yml ファイルが有効であることを検証します。次に sam build を実行し、SubmitImage パッケージをデプロイ可能なアーティファクトにビルドします。3 番目に sam deploy を実行して、更新された SubmitImage コードを AWS にデプロイします。最後に、パイプラインがステップ 1 で作成した update スクリプトを呼び出し、一致する Jira 課題にコメントを書いて戻します。
child.yml
resources:
- name: repo
type: git
source:
uri: git@bitbucket.org:pmmquickstartguides01/submitimage.git
branch: ((branch))
private_key: ((bitbucket_ssh_key))
jobs:
- name: deploy-submit-image
plan:
- get: repo
trigger: true
- task: run-sam-validate
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["validate", "-t", "repo/template.yml"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-sam-build
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["build", "-t", "repo/template.yml"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-sam-deploy
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
inputs: # add the get step as an input to this task
- name: repo
run:
path: sam
args: ["deploy", "-t", "repo/template.yml", "--stack-name", "OpenDevOpsSubmitImage", "--s3-bucket", "open-devops-code-us-west-1-756685045356", "--capabilities", "CAPABILITY_IAM", "CAPABILITY_NAMED_IAM"]
params:
AWS_ACCESS_KEY_ID: ((AWS_ACCESS_KEY_ID))
AWS_SECRET_ACCESS_KEY: ((AWS_SECRET_ACCESS_KEY))
AWS_DEFAULT_REGION: ((AWS_DEFAULT_REGION))
- task: run-update-script
config:
platform: linux
image_resource:
type: registry-image
source:
repository: docker.atl-paas.net/wmarusiak/ubuntuawssam
username: ((docker_username))
password: ((docker_api_key))
input:
-name: repo
run:
path: /workspace/updatescript/concourse-ci-integration.sh
args: ["-c", "successfully deployed submitImage via concourse-ci", "-k", "((branch))", "-o", "ac", "-u", "((bitbucket_username))", "-t", "((bitbucket_api_key))", "-w", "pmmquickstartguides01"]
親パイプラインを開始する方法
parent.yml のディレクトリから次の 3 つのコマンドを実行します。最初のコマンドは、ローカルで実行されている Concourse-CI インスタンスにログインします。2 つ目のコマンドは、parent.yml の設定に基づき、wm というパイプラインを作成します。3 つ目のコマンドは、wm パイプラインの一時停止を解除します。
fly -t tutorial login -c http://localhost:8080 -u test -p test
fly -t tutorial set-pipeline -p wm -c parent.yml
fly -t tutorial unpause-pipeline -p wm
この 3 つのコマンドを実行したら、Concourse-CI の Web クライアントにアクセスして、wm パイプラインが稼働していることを確認します。
parent.yml で fly set-pipeline を実行すると、wm パイプラインが現れます。このパイプラインは、新しい機能ブランチがないか SubmitImage を監視し、parent.yml の正規表現と一致するパイプラインをフィーチャー ブランチごとに作成します。
wm パイプラインをクリックして、実行されるステップを確認します。feature-branches のステップには IM-61 ブランチが表示されています。これは、SubmitImage に存在する、現時点で parent.yml の正規表現と一致する唯一のブランチです。自動的に起動した開発パイプラインをクリックし、実行されるステップを確認してください。
SubmitImage リポジトリを取得するステップがありますが、そのブランチは IM-61 です。また、run-sam-validate、run-sam-build、run-sam-deploy、および run-update-script のステップがあることにも注意してください。
開発パイプラインの実行後は IM-61 の Jira 課題に戻り、1 分前に記録された新しいコメントが child.yml のコメント文字列と一致することに注目してください。
結論
このガイドは、Concourse-CI を使用して Golang AWS Lambda を単一の AWS リージョンに自動的にデプロイできるパイプラインを設定する方法について説明するものです。このガイドでは、bash シェル スクリプトを使用して Jira との簡単な統合を作成する方法も説明しています。統合スクリプトは、こちらから入手可能な Atlassian REST API を深く掘り下げることによって、大幅に拡張することができます。
この記事を共有する
次のトピック
おすすめコンテンツ
次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。