見出し画像

CircleCIとserverless-frameworkで自動デプロイするまでの初期設定方法

スクリーンショット 2020-12-02 4.03.50

この記事を読むと、以下についての説明をする。

新規リポジトリに対してCircleCIを設定し、リモートへプッシュしたら、serverless-frameworkによってGolangで書かれたAWS LambdaやAPI Gatewayが自動更新されるまでの設定方法。

なお、Githubアカウントの作成及びserverless-frameworkの初期設定は済んでいるものとする。serverless-frameworkが未設定の方及び基本的な使い方を知りたい方は下記記事をご参考に。

設定手順

1. GitHubで新規リポジトリを作成する。

右上の+ボタンから、New repositoryを選択。

画像1

Repository nameの欄にリポジトリ名を記入。今回はわかりやすくcircleci-testとしている。その後左下緑ボタンCreate repositoryで新規作成完了。

画像2

その後、出てきたコマンドにしたがって最初のコミットを行う。(2020/12/02現在新規リポジトリを作るとメインブランチ名はmainで作る事例が出てくるが、今回は筆者が慣れているmasterの名称でセットしている)

$ git clone git@github.com:mu-editech/circleci-test.git
$ echo "# circle-ci-test" >> README.md
$ git init
$ git add README.md
$ git commit -m "first commit"
$ git branch -M master # <= mainからmasterに変わってる
$ git remote add origin git@github.com:mu-editech/circle-ci-test.git
$ git push -u origin master # <= mainからmasterに変わってる

2. Serveless-frameworkでデプロイフローを作成

必要ファイル(serverless.yml + main.go)を作成し、記述する。2ファイルの書き方例はコマンド例以下。

$ touch serverless.yml

# golangのバイナリファイルを置いておく場所を作成。
$ mkdir bin
$ touch bin/.gitkeep

$ touch main.go

$ go mod init notification-sender # go.modの生成
$ go build main.go # go.modに書き込みが走り、go.sumが生成される

$ rm -rf ./bin # <= 2回目以降のデプロイに掃除用として必要なコマンド
$ env GOOS=linux go build -o ./bin/circleci-deploy-test main.go
$ serverless deploy --verbose # ローカルからデプロイ
•
•
•
endpoints:
 POST - ~~~~~~~~~~~ <= ここに出てくるURLがhostURL
•
•

# リソースが生成されたことを確認する。Succeededが返り値で帰ってくればおk。
$ curl -X POST hostURL

serverless.yml(API GatewayとLambdaの最小構成)

service: circleci-test

provider:
 name: aws
 runtime: go1.x
 stage: dev
 region: ap-northeast-1

package:
 exclude:
   - ./**
 include:
   - ./bin/**

functions:
 circleci-deploy-test:
   handler: bin/circleci-deploy-test
   timeout: 300
   events:
     - http:
         path: eventtest
         method: POST

main.go(何を投げても「Suceeded」と文字を返す)

package main

import (
	"github.com/aws/aws-lambda-go/events"
	"github.com/aws/aws-lambda-go/lambda"
)

func handler(request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {
	return events.APIGatewayProxyResponse{
		Body:       "Suceeded",
		StatusCode: 200,
	}, nil
}

func main() {
	lambda.Start(handler)
}

ここまででserverlessコマンドでローカルからデプロイできることが確認できたら、serverless.ymlmain.gogo.modgo.sumbin/.gitkeepをコミット+プッシュする。

3. リポジトリとCircleCIを紐付ける

GitHubにログインした状態でCircleCIのサイトに行き、「Sign up with GitHub」ボタンを押してアクセス認証を行う。(Authorize circleciボタンを選択)

すると、下記のようなプロジェクト一覧画面が表示される。自身のGitHubアカウントにあるリポジトリが一覧になっているはずなので、この中から先ほど追加したリポジトリを選択する。

スクリーンショット 2020-12-02 2.16.05

するとCircleCIの初期設定を行う画面に飛ぶので、そのまま赤枠Add Configを選択する。これにより自動でcircleci-project-setupという名称のブランチが作成され、/circleci-test/.circleci/config.ymlというファイルが作成され、CircleCIがプッシュするたびに実行される設定が完了する。CircleCIはこの.circleci/config.ymlというファイルにCircleCIの設定やフローを書き込んでいく仕様になっている。(青枠のところを選択すると、各言語のテストとデプロイを行うが、どうせconfig.ymlは書き換えることになるのでどちらでも良い)

スクリーンショット 2020-12-02 2.17.11

4. CircleCI専用ユーザーを作成+設定する。

CircleCIはAWSアカウントに向かってリソースをいじるため、アクセスキーとシークレットアクセスキーによるアクセスが必要になる。ここではユーザー名をcircle-ciとし、管理者の権限をつけている。

$ aws iam create-user --user-name circle-ci
$ aws iam attach-user-policy --user-name circle-ci --policy-arn "arn:aws:iam::aws:policy/AdministratorAccess"
$ aws iam create-access-key --user-name circle-ci 
{
  "AccessKey": {
      "UserName": "circle-ci",
      "AccessKeyId": "XXXXXXXXXXXXXXXXXXXX",
      "Status": "Active",
      "SecretAccessKey": "YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY",
      "CreateDate": "2020-07-04T04:10:00Z"
  }
}

XXXX...とYYYYY....の部分をどこかに保存しておき、CircleCIのコンソール画面からProject Settings => Environment Variables => Add Environment Variableへと選択していく。

スクリーンショット 2020-12-02 3.20.14

スクリーンショット 2020-12-02 3.21.36

AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYセットする。(下図はAWS_ACCESS_KEYの例)

画像7

5. CircleCIのデプロイフローを記述する。

git  pullし、circleci-project-setupブランチにcheckoutしたら、config.ymlを以下のように書き換える。コミット+プッシュすれば、CircleCIが作動し、自動デプロイが完了する。

.circleci/config.yml

version: 2

references:
 install_serverless: &install_serverless
   run:
     name: Install serverless command
     command: |
       sudo apt-get update
       sudo apt-get install gcc g++ make
       curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
       sudo apt-get install -y nodejs
       mkdir ~/.npm-global
       npm config set prefix '~/.npm-global'
       echo ' export PATH=~/.npm-global/bin:$PATH' >> $BASH_ENV
       npm install -g serverless
 build: &build
   run:
     name: Build go files
     command: |
       env GOOS=linux go build -o ./bin/circleci-deploy-test main.go
jobs:
 build:
   docker:
     - image: circleci/golang:1.13.4
       environment:
         AWS_DEFAULT_REGION: ap-northeast-1
   steps:
     - checkout
     - *install_serverless
     - *build
     - run:
         name: Deploy to dev
         command: serverless deploy --stage=dev

workflows:
 version: 2
 workflow:
   jobs:
     - build

Column1:.circleci/config.ymlファイルの解説

circleciのファイルの最小構成は以下のようになっている。

version: 2

jobs:
  build:
    docker:
      - image: circleci/golang:1.13.4
    steps:
      - checkout
      - run: echo "Hello, World"

workflows:
  version: 2
  workflow:
    jobs:
      - build      

小さな手続きをまとめたものをjob、そしてjobをまとめたものをworkflowと呼んでいる。workflowsを見てみると、jobsのbuildが実施されることとなっており、buildを見てみれば、CIの実行環境にcircleci/golang:1.13.4というコンテナイメージを使ってcheckout=>echo "Hello World"をするという手続きが書かれている。そう、CircleCIはDockerコンテナ上で動かすのである(他にも複数の実行環境の選択肢があるが、主流はDockerコンテナ)

改めて二つ上の.circleci/config.ymlを眺めてみると、
1. install_serverlessでnode、npm、serverless-frameworkをインストール
2. buildでビルド
3. Deploy to devのところでデプロイ
の三ステップを踏んでいるのがわかる。

Column2:死ぬほどハマりポイント=環境変数

半日溶かして悔しかったので共有。CircleCIには環境変数の挙動に特殊なルールがある。下記をみると$BASH_ENVと書かれている部分がある。

install_serverless: &install_serverless
  run:
    name: Install serverless command
    command: |
      sudo apt-get update
      sudo apt-get install gcc g++ make
      curl -sL https://deb.nodesource.com/setup_12.x | sudo bash -
      sudo apt-get install -y nodejs
      mkdir ~/.npm-global
      npm config set prefix '~/.npm-global'
      echo ' export PATH=~/.npm-global/bin:$PATH' >> $BASH_ENV # <= ココ!!!!!!!!
      npm install -g serverless

もし普通にUbuntuを使うなら、npmをインストールした後パスを通すため以下のようなコマンドを打つだろう。

$ echo ' export PATH=~/.npm-global/bin:$PATH' >> ~/.bash_profile
$ source ~/.bash_profile

しかし、これではデプロイする時にserverless: not foundなどとエラーで怒られてしまう。パスが通ってないのだ。なぜならexportで通したパスはそのシェルの中では有効だが、CircleCIは各ステップごとに新しいシェルを立てる仕様になっている。なので解決方法として$BASH_ENVを使う。これはそのジョブ内で有効な一時ファイルであり、新しいシェルが呼ばれてもBASH_ENVのファイルをsourceで読み込んでから起動してくれる。

Column3:ローカルテストの方法

プッシュしていちいち画面を確認するのが面倒な方はcirlceci-cliを使ってローカルでテストを行うことができる。circle-ciのインストールは公式がコマンドつきで説明してくれている。

.circleciディレクトリがある場所で以下のコマンドを打てばローカルでテストができる。

$ circleci local execute

おしまい。

この記事が気に入ったらサポートをしてみませんか?