Close

Atlassian TEAM TOUR Tokyo 2022 の全セッションをアーカイブ配信中!会場実施のセッションもご覧いただけます。期間限定、2023年2月末まで。視聴はこちら >

Concourse-CI と Atlassian Open DevOps の統合

ほとんどのチームが、自分たちのニーズを満たしてくれる独自のツールを導入しているか、長年使用している従来のツールを持っています。これらのツールは、チームの開発プロセスに不可欠ですが、Jira Software とすぐに統合できる機能がありません。幸い、Cloud 開発者向けドキュメント ~ アトラシアン開発者 に記載されている Atlassian REST API を使用すれば、カスタム統合を簡単に構築できます。Concourse-CI は CI/CD 製品であり、この記事の執筆時点では、Atlassian Marketplace に統合されていません。この記事では、Atlassian REST API を使用して Jira Software と 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_KEYCONCOURSE_AWS_SECRETSMANAGER_SECRET_KEYCONCOURSE_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 のシークレットを置き換えなければなりません。読者の個々のツールに合わせた調整は、課題練習として残します。

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 トークン
アカウント設定に進みます

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 パイプラインが稼働していることを確認します。

Concourse-CI Web クライアントの画像

parent.yml で fly set-pipeline を実行すると、wm パイプラインが現れます。このパイプラインは、新しい機能ブランチがないか SubmitImage を監視し、parent.yml の正規表現と一致するパイプラインをフィーチャー ブランチごとに作成します。

fly set パイプライン

wm パイプラインをクリックして、実行されるステップを確認します。feature-branches のステップには IM-61 ブランチが表示されています。これは、SubmitImage に存在する、現時点で parent.yml の正規表現と一致する唯一のブランチです。自動的に起動した開発パイプラインをクリックし、実行されるステップを確認してください。

fly set パイプライン後の WM パイプライン

SubmitImage リポジトリを取得するステップがありますが、そのブランチは IM-61 です。また、run-sam-validate、run-sam-build、run-sam-deploy、および run-update-script のステップがあることにも注意してください。

IM 61 の Jira 課題の要約

開発パイプラインの実行後は IM-61 の Jira 課題に戻り、1 分前に記録された新しいコメントが child.yml のコメント文字列と一致することに注目してください。

結論

このガイドは、Concourse-CI を使用して Golang AWS Lambda を単一の AWS リージョンに自動的にデプロイできるパイプラインを設定する方法について説明するものです。このガイドでは、bash シェル スクリプトを使用して Jira との簡単な統合を作成する方法も説明しています。統合スクリプトは、こちらから入手可能な Atlassian REST API を深く掘り下げることによって、大幅に拡張することができます。

Warren Marusiak
Warren Marusiak

Warren is a Canadian developer from Vancouver, BC with over 10 years of experience. He came to Atlassian from AWS in January of 2021.

この記事を共有する

おすすめコンテンツ

次のリソースをブックマークして、DevOps チームのタイプに関する詳細や、アトラシアンの DevOps についての継続的な更新をご覧ください。

DevOps のイラスト

DevOps コミュニティ

DevOps のイラスト

DevOps ラーニング パス

マップのイラスト

無料で始める

DevOps ニュースレター購読

Thank you for signing up