見出し画像

Bitbucket Pipelinesの逆引きレシピ

この記事は、NAVITIME JAPAN Advent Calendar 2020の 22日目の記事です。

こんにちは、みみぞうです。
ナビタイムジャパンで『システムや開発環境、チームの改善』を担当しています。

本記事ではAtlassianが提供しているBitbucket Cloudという製品向けのCI/CDツール『Bitbucket Pipelines』の逆引きレシピを紹介します。具体的にはユースケースを集めたサンプルリポジトリ集です。

読んで欲しい方

以下のような方を対象としています。

❶ Bitbucketを使ったことがある、または使おうと思っている
❷ GitHub ActionsやCircle CIのようなことをBitbucketでしたいと思っている
❸ Bitbucket Pipelinesを使っているが書き方に迷うことが多い

逆引きレシピを作ろうと思ったわけ

以前ご紹介しましたとおり、ナビタイムジャパンでは現在Atlassian製品のクラウド移行を進めています。

クラウド移行実施前、社内のCIはほぼJenkinsでした。また、業務外でエンジニアリングする際に使うCIもGitHub Actions, Circle CIが多かったため、Bitbucket Pipelinesの使い方や魅力を伝える必要がありました。

もちろんBitbucket Pipelinesには公式ドキュメントがあります。

紹介されている例やBitbucket PipelinesのGUIから利用できるテンプレートはとてもCOOLなものです。一方、実際の業務で使う場合は社内のルール、チームの方針などを考えてカスタマイズが必要になることも多いでしょう。CIの経験が浅く、英語が苦手な方にとってはハードルも上がります。

そのような理由から、社内の文化やルールを理解しているエンジニアが、サンプルのリポジトリ日本語でつくることにしました。

次の章から、その中から厳選した6つのレシピを紹介していきます。

Recipe 1: ShellでHello Worldを出力する

お約束のHello Worldですが、基礎を学ぶには欠かせません。

構成
----

 .
├──  bitbucket-pipelines.yml
└──  hello.sh

bitbucket-pipelines.yml の中身です。

image: amazonlinux:latest
  
pipelines:
  default:
    - step:
        name: "pushされたら実行する (ブランチに関係なく)"
        script:
          - ./hello.sh

stepには名前がついており、scriptで指定した1つ以上のコマンドが実行されることが分かります。

画像4

Recipe 2: パラメータを指定して手動実行する

Jenkinsでジョブを実行するときによく使うパターンですね。

構成
----

 .
└──  bitbucket-pipelines.yml

variablesでパラメータ変数を定義し、${変数名}という形で使用します。

image: amazonlinux:latest
  
pipelines:
  custom:
    hello:
      - variables:
          - name: target
          - name: message
      - step:
          name: "Helloと挨拶して一言喋る"
          script:
            - echo "Hello, ${target}!  ${message}"
    sorry:
      - variables:
          - name: target
          - name: message
      - step:
          name: "Sorryと謝罪して一言喋る"
          script:
            - echo "Sorry, ${target}..  ${message}"

ブラウザから以下のように実行できます。

画像1

Recipe 3: Slackに通知する

ナビタイムジャパンのコミュニケーションは基本Slackです。CI完了時の通知は書かせません。

構成
----

 .
└──  bitbucket-pipelines.yml

このレシピには2つポイントがあります。

image: amazonlinux:latest
  
pipelines:
  default:
    - step:
        name: "pushされたら#test_bitbucket-pipelineに通知します"
        script:
          # https://bitbucket.org/atlassian/slack-notify/src/master/
          - pipe: atlassian/slack-notify:1.0.0
            variables:
              WEBHOOK_URL: $WEBHOOK_URL
              MESSAGE: 'てすとです'

1つ目は Bitbucket Pipelines Pipes という概念です。プラグインのようなもので、必要な情報を設定するだけで簡単に実行できます。

ここではSlack NotifyというPipeを使いました。

2つ目は秘密情報 $WEBHOOK_URL の指定方法です。秘密情報の管理をするにはリポジトリ変数を使います。

リポジトリ設定の Repository variables から設定します。Securedのチェックを忘れないようにしましょう。

画像2

Recipe 4: 簡単なドキュメントをデプロイする

『READMEでは物足りない.. けど本格的なドキュメンテーションビルダーを使うほどでもない..。 ただMarkdownで書きたいなあ..。』
という場合にオススメのレシピです。

構成
----

 .
├──  bitbucket-pipelines.yml
└──  docs
   ├──  _sidebar.md
   ├──  faq.md
   ├──  favicon.ico
   ├──  image.png
   ├──  index.html
   └──  index.md

docsディレクトリ配下がデプロイするドキュメントです。Markdownで書けるのにビルドが不要な魔法のサイトジェネレーターdocsifyを使っています。

デプロイ先はAWS S3です。秘密情報の管理には先ほどのリポジトリ変数を使います。

image: amazon/aws-cli:latest

pipelines:
  branches:
    master:
      - step:
          name: 'masterにpushされたらdocs配下のドキュメントをS3にデプロイする'
          script:
            - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
            - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
            - export AWS_DEFAULT_REGION=ap-northeast-1
            - aws s3 cp --recursive ./docs/ s3://your-favorite-bucket-name/$BITBUCKET_REPO_SLUG/

$BITBUCKET_REPO_SLUG はURLでそのリポジトリを示すslugが入ります。GitHub Pagesとは異なり、Bitbucketにはリポジトリごとにサイトを管理する機構がありません。しかし、これは必要な要件であったため、AWS S3で専用のBucketを構築し、リポジトリslugをprefixにすることで実現しました。

Recipe 5: 本格的なドキュメントをビルドデプロイする

数十ページに及ぶような本格的なドキュメントを管理したい場合にオススメのレシピです。

構成
----

 .
├──  bitbucket-pipelines.yml
├──  docs
│  ├──  faq.md
│  ├──  favicon.ico
│  ├──  image.png
│  ├──  index.md
│  └──  logo.png
├──  mkdocs.yml
├──  README.md
└──  requirements.txt

ドキュメーテーションビルダーとしてMkdocsを使います。テーマはMaterial for MkDocsを選びました。

PythonやMkDocsの話をすると長くなるため、このディレクトリ構成になった経緯やmkdocs.ymlの中身は割愛させてください。

pipelines:
  branches:
    master:
      - step:
          name: 'masterにpushされたらサイトをビルドする'
          image: python:latest
          script:
            - pip install --no-cache-dir -r requirements.txt
            - mkdocs build
          artifacts:
            - site/**
      - step:
          name: 'ビルドが終わったらS3にデプロイする'
          image: amazon/aws-cli:latest
          script:
            - export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY
            - export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
            - export AWS_DEFAULT_REGION=ap-northeast-1
            - aws s3 cp --recursive ./site/ s3://your-favorite-bucket-name/$BITBUCKET_REPO_SLUG/

stepが2つあり、それぞれ異なるimageが指定されているのがポイントです。

1つ目のstepではPythonを使ってドキュメントのビルドをするため、pythonのDockerイメージを使っています。2つ目のstepはawsへのデプロイにAWS CLIが必要なのでaws-cliのDockerイメージを使っています。

step全体で1つのDockerイメージしか使わない場合は、今までのレシピみたくTOP階層に1度指定するだけで問題ありません。

また、artifactsにも注意しましょう。stepを跨ぐとディレクトリは共有されないため、前stepの成果物を次stepで使うにはartifactsの指定が必要です。

Recipe 6: テストが通るまでプルリクエストをマージさせない

最後に、よくあるこのシチュエーションについてのレシピを紹介します。

構成
----

 .
├──  bitbucket-pipelines.yml
├──  requirements.txt
├──  src
│  ├──  __init__.py
│  ├──  math.py
│  └──  nest
│     └──  str.py
└──  tests
  ├──  __init__.py
  ├──  nest
  │  └──  test_str.py
  └──  test_math.py

ここではPythonを使っています。先ほどと同じ理由でPythonやPytestの話については割愛させてください。

image: python:3.8

pipelines:
  pull-requests:
    '**': # すべてのbranchでプルリクをマージしたコードに対して実行
      - step:
          name: pytestでテスト実行
          caches:
            - pip
          script:
            - pip install -r requirements.txt
            - pytest -v tests --junitxml=test-reports/report.xml

cachesはパッケージのキャッシュをするために指定しています。Bitbucket PipelinesのPythonテンプレートを参考にしました。

プルリクエストをトリガーにするためpull-requestsを指定しています。もし特定のブランチだけで発動させたい場合は '**' のパターンを変更します。

ただ、これだけではテストに失敗してもマージできてしまいます。それを防止するためリポジトリの設定変更が必要です。

画像3

上のチェックでビルド(テスト)が成功していなければマージチェックをNGにします。そして、下のチェックでマージチェックがNGならマージができないようにしています。後者はBitbucketのプレミアムプランユーザーのみ利用できる機能です。

それとは別に、書き込み権限が付与されていたら直接コミット/プッシュできてしまいますので注意してください。

さいごに

Bitbucket Pipelinesの逆引きレシピを6つ紹介しました。

Bitbucket PipelinesはDockerイメージをベースに処理を定義できます。そのため、Dockerを使える方にとってはかなり色々なことができると思います。

一方、DockerやCIに慣れていない方にとってはハードルを感じることもあるでしょう。逆引きレシピがそのような方にとっての道導になれたら...と願っております。

最後までご覧いただきありがとうございました!! 😄