CodePipeline よ Github や CodeCommit と連携出来るのはわかった

では、Backlog Git と連携はどげんすればよかとかね。
その答えにヒントを与えてくれたのは以下の記事。

Integrating Git with AWS CodePipeline | AWS DevOps Blog

なるほど…とにかく、何らかの方法で Codepipeline までソースコードをお届け出来れば…ということで、Backlog Git の Webhook と API Gateway + Lambda を組み合わせればいけそうな気がする!

ということで

ざっくり構成

以下のような構成を作ってみた。

Backlog Git の Webhook は…

以下のような JSON データを送信する。

{
  "before": push前のコミット,
  "after": push後のコミット,
  "ref": 参照
  "repository": {
    "url": リポジトリのURL,
    "name": リポジトリ名,
    "description": リポジトリの説明,
  },
  "revisions": [{
    "id": コミットのID,
    "url": コミットのURL,
    "author": {
      "email": コミットした人のメールアドレス,
      "name": コミットした人の名前
    },
    "message": コミットメッセージ,
    "timestamp": タイムスタンプ,
    "added": [ 追加されたファイル ],
    "removed": [ 削除されたファイル ],
    "modified": [ 修正されたファイル ],
  }]
}

詳細は以下のページに記載されている。

Git Webフックとは、Backlogが管理しているGitリポジトリにpushされた際に、指定されたURL(サーバ)へHTTP POSTする機能です。 Webフックは、例えば以下の用途に用いることができます。 CIビルドのトリガ バックアップの更新 ステージング環境への最新版コードの反...

www.backlog.jp

Lambda ファンクションは…

Python で書いてみた。

# -*- coding: utf-8 -*-

import os
import os.path
import sys
import urllib
import urlparse
import shutil
import json

sys.path.append(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'vendor'))

import boto3
import dulwich.client
from dulwich.repo import Repo
from dulwich import porcelain

target = os.environ['TARGET_DIR']
username = os.environ['USER_NAME']
password = os.environ['PASSWORD']
source_bucket = os.environ['BUCKET_NAME']

def git_clone(repo_url):
    print repo_url + ' からソースコードを取得します.'

    parsed_url = urlparse.urlparse(repo_url)
    src = parsed_url.scheme + '://' + username + ':' + password + '@' + parsed_url.netloc + parsed_url.path + '.git'

    if not os.path.isdir(target):
        os.mkdir(target)
    else:
        shutil.rmtree(target)

    try:
        porcelain.clone(src, target)
    except Exception as e:
        print(e)

    print(os.listdir(target))

def zip_files():
    print 'ソースコードを zip で圧縮します.'

    try:
        shutil.make_archive(target, 'zip', target)
    except Exception as e:
        print(e)

def upload_to_s3():
    print '圧縮したソースコードを s3 にアップロードします.'

    zip_file_name = target.split('/')[-1]

    s3 = boto3.client('s3')
    try:
        s3.upload_file(target + '.zip', source_bucket, zip_file_name + '.zip')
    except Exception as e:
        print(e)

def git(event, context):

    payload = json.loads(event['body']['payload'])
    repo_url = payload['repository']['url']

    git_clone(repo_url)
    zip_files()
    upload_to_s3()

    response = {
        'statusCode': 200
    }

    return response

以下の点を直したいけど取り急ぎ。

  • エラー処理
  • 環境変数で指定している各種値を KMS で暗号化

API Gateway と Lambda ファンクションのセットアップは…

Serverless Framework を使えば一瞬だった… serverless.yml は以下の通り。

service: slstest
provider:
  name: aws
  runtime: python2.7
  region: ap-northeast-1
  iamRoleStatements:
    - Effect: "Allow"
      Action:
        - "s3:PutObject"
      Resource: "arn:aws:s3:::demodemo-codepipeline/*"
functions:
  hello:
    handler: handler.git
    memorySize: 128
    timeout: 60
    events:
      - http:
          path: git/push
          method: post
          integration: lambda
          request:
            parameters:
              querystrings:
                payload: true
    environment:
        USER_NAME: kappa
        PASSWORD: xxxxxxxxxxxxxx
        TARGET_DIR: /tmp/oreno-repo
        BUCKET_NAME: demodemo-codepipeline

今まで何で Serverless Framework を使っていなかったんだろうと後悔。

CodePipeline と S3 バケットの連携は…

以前に書いた記事を参考にした。

はじめに CodeDeploy をオンプレミス環境で利用してみる - ようへいの日々精進XPinokara.hateblo.jp 上の記事で CodeDeploy を触っていてソースコードが更新されたら自動でデプロイする仕組みは無いものかなと調べていたら CodePipeline ですぐに出来そうだったので...

inokara.hateblo.jp

これはマネジメントコンソールから。
S3 バケットを作って、バージョニングを有効にして CodePipeline からソースプロバイダとして指定するだけ。

Codebuild では Ruby のテストを走らせてみる

以下のドキュメントを参考にして Codebuild で Ruby のテストを走らせてみた。

AWS CodeBuild で機能するよう設計された Ruby Hello World サンプルについて説明します。

docs.aws.amazon.com

ファイル構成は以下の通り。

$ tree oreno-repo/
oreno-repo/
├── HelloWorld.rb
├── HelloWorld_spec.rb
└── buildspec.yml

0 directories, 3 files

buildspec.yml は以下の通り。

version: 0.1

phases:
  install:
    commands:
      - echo Installing RSpec...
      - gem install rspec
  build:
    commands:
      - echo Build started on `date`
      - echo Compiling the Ruby code...
      - rspec HelloWorld_spec.rb
  post_build:
    commands:
      - echo Build completed on `date`
artifacts:
  files:
    - HelloWorld.rb

実際にビルドを走らせた図。

あえて Failed させている。

まとめ

課題

本構成には以下のような課題が残っている。

  • Webhook 用 URL のアクセス制限(API キーによる認証又は IP アドレス制限
  • Lambda ファンクションで利用する環境変数の暗号化(KMS と連携させる)
  • ブランチ毎に処理を変えられるようにする(master ブランチ以外のブランチだけでビルドが走るようにするとか)

Serverless Framework

API Gateway と Lambda のセットを丸っとサクッと作ってくれるのが気持ち良すぎた。

元記事はこちら

いろいろとツッコミどころはあるばってん、Backlog Git と AWS CodePipeline の連携について考察してみたくさ