search
LoginSignup
1

More than 1 year has passed since last update.

posted at

updated at

Organization

GitHub Actionsを使ってServerless Frameworkチーム開発効率化

はじめに

この記事は2020年のRevCommアドベントカレンダー10日目の記事です。9日目は @sukekd さんの Google Workspace(旧称G Suite) アカウントのSAML認証を使ってAWS CLIの認証を行う でした。

こんにちは。
RevCommでエンジニアリングマネージャーを担当している@series7です。
エンジニアリングマネージャーということで最近は組織づくりや採用を主に担当していますが、まだまだエンジニアの人数が少ないので日々プログラミングも行っています。

ちょっとしたLambdaを作ってデプロイしたいときにServerless Framework便利ですよね。
ただチームで開発をしていてるとプルリクエストレビュー時の実機確認をローカルで行うか、自分でデプロイするかなど悩みもあると思います。
そんなときに便利なのがGitHub Actions。
数行のコードで、

  • プルリクエスト単位にPR単位の独自環境を作成
  • チェックしてマージ完了した段階で削除

ということが全自動でできちゃいます。
それでは、そんな素敵な環境作りの第一歩ということで簡単な環境を構築してみましょう。

今回作成するもの

  • 簡単なServerless Frameworkアプリ
  • GitHub Actions

前提

PCにnpmがインストールされていること

Serverless Frameworkアプリの準備

今回はあくまでもPull Request単位に環境の自動作成を試すだけなので簡潔にすませます。

まずはServerlessコマンドのインストール

npm install -g serverless

インストールが完了したら適当なディレクトリーで

sls create -t aws-nodejs-typescript --path advent2020

これでファイル一式が入ったディレクトリーが作成されたと思います。
handlers.tsを覗いてみるとこんな状況になっているはずです。

handlers.ts
import { APIGatewayProxyHandler } from 'aws-lambda';
import 'source-map-support/register';

export const hello: APIGatewayProxyHandler = async (event, _context) => {
  return {
    statusCode: 200,
    body: JSON.stringify({
      message: 'Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!',
      input: event,
    }, null, 2),
  };
}

このままdeployを行うとデフォルトの米国東部(バージニア北部)リージョン us-east-1 に環境構築が行われるので、フォルダー内の serverless.ts にリージョン指定を設定します。

serverless.ts
provider: {
    name: 'aws',
    runtime: 'nodejs12.x',
    region: 'ap-northeast-1', //この行を追加してリージョンを指定。
    apiGateway: {
      minimumCompressionSize: 1024,
    },
    environment: {
      AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
    },
  },

GitHubに保存

保存しましょう。
適当にGitHubのレポジトリを作成して、ひとまずdefaultブランチにドーーン。

git init
git add .
git commit -m "first commit"
git branch -M main
git remote add origin {リモートレポジトリ名}
git push -u origin main

AWSにデプロイするための準備

Deploy用のAWS IAMユーザーを作成する

AWSに環境構築をする上でユーザーが必要となるのでAWS IAMユーザーを作成します。

まずはAWSマネージメントコンソールにログインしてプログラムアクセスのみのユーザーを作成します。
advent-aws-console.png

今回はあくまでもサンプルなので全権限移譲したユーザーを作成します。
実際の開発では権限をちゃんとしぼったユーザーにしましょうね。
advent-aws-console2.png

ユーザーを作成したらアクセスキーとシークレットアクセスキーをメモっときます。
advent-aws-console3.png

これで準備は完了です。
ここからは実際にGitHub Actionsの設定をしていきます。

Github Actionsの準備

GitHub Secretesの登録

さきほど作成したAWS IAMユーザーのアクセスキーとシークレットアクセスキーをGitHubレポジトリのシークレットに登録します。
[設定場所]
Settings -> Secrets
Secrets.png

AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEY の2つを設定します。

デフォルトブランチ用のGitHub Actionsの設定

デフォルトブランチに変更が入った場合にAWSの環境をアップデートするようなActionsを設定していきます。

.githubというフォルダーをプロジェクトルート直下に作成し、その中に workflowsというフォルダーを作成します。
このフォルダーに実行したいGitHub Actionsのコードをいれていくことになります。

デフォルトブランチ用ということで、 main.yml というファイルを作成します。

.github/workflows/main.yml
name: Main CI/CD

on:
  push:
    branches:
      - main

jobs:
  primary:
    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
      with:
        node-version: '12'
    - name: install dependencies
      run: yarn install
    - name: serverless config
      run: npx serverless config credentials --provider aws --key ${{ secrets.AWS_ACCESS_KEY_ID }} --secret ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    - name: serverless deploy
      run: npx serverless deploy --stage prod

GitHub Actionsの記法自体はGitHub Docsを参照して頂くとして、重要点だけ。

on:
  push:
    branches:
      - main

これでmainブランチにpushされたときに記載されたコードが動くようになります。

    - name: serverless config
      run: npx serverless config credentials --provider aws --key ${{ secrets.AWS_ACCESS_KEY_ID }} --secret ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    - name: serverless deploy
      run: npx serverless deploy --stage prod

この部分が実際のServerless FrameworkのDeployコードとなります。
今回はmainブランチのstageをprodという名称でデプロイしています。

実際にこの .github/workflows/main.yml をレポジトリーにプッシュしてみましょう。

プッシュが終わったらブラウザでGitHubのレポジトリーサイトを開いてみます。
Actionsページをみると稼働しているActionのJobの状態が確認できるはずです。
githubaction-result.png

完了したら、AWSマネージメントコンソールのAPI Gatewayページを見てみます。
api-geteway1.png

無事 prod-advent2020というAPIが作成されていますね。
実際に動いている状況をみてみたいので、API名をクリックしてダッシュボードメニューへ遷移します。

apigateway2.png

右上にAPIのURLが記載されていると思うので末尾に /hello/ を付け足してブラウザで見てます。
実際のURLはこのような形になるはずです。
https://{生成されたURL}.execute-api.ap-northeast-1.amazonaws.com/prod/hello/

ブラウザに下のような画面がでれば成功です。
apigateway-result.png

handers.ts内に記載されてた Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!という文言が表示されていますね。

プルリクエスト作成時用のAction

それでは本題であるプルリクエストが作成されたときにPR単位の独自環境を作成するコードを追記していきましょう。
先程と同じく .github -> workflows フォルダー内に pr-open.ymlというファイルを作成します。

.github/workflows/pr-open.yml
name: Pull Request CI/CD

on: pull_request

jobs:
  primary:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
      with:
        node-version: '12'
    - name: install dependencies
      run: yarn install
    - name: serverless config
      run: npx serverless config credentials --provider aws --key ${{ secrets.AWS_ACCESS_KEY_ID }} --secret ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    - name: serverless deploy
      run: npx serverless deploy --stage pr$(jq --raw-output .number "$GITHUB_EVENT_PATH")

ほぼデフォルトブランチ用のActionを同じなのですが、
重要となる変更点は2箇所。

プルリクエストが作成されたときに動くことを宣言している部分と

on: pull_request

デプロイする環境名(stage)をプルリクエストの番号をもとに自動生成しているところです。

- name: serverless deploy
      run: npx serverless deploy --stage pr$(jq --raw-output .number "$GITHUB_EVENT_PATH")

プルリクエストマージ時用のAction

レビュー後、マージ時(またはキャンセルのタイミング)に実行するGitHub Actionsのコードはこちら。

.github/workflows/pr-close.yml
name: Pull Request Close CI/CD

on:
  pull_request:
    types: [closed]

jobs:
  primary:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
      with:
        node-version: '12'
    - name: install dependencies
      run: yarn install
    - name: serverless config
      run: npx serverless config credentials --provider aws --key ${{ secrets.AWS_ACCESS_KEY_ID }} --secret ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    - name: serverless remove
      run: npx serverless remove --stage pr$(jq --raw-output .number "$GITHUB_EVENT_PATH")

プルリクエストオープン時との違いは2箇所。

on:
  pull_request:
    types: [closed]

この部分でpull_requestがcloseされた時にのみ動くよう指定しています。

- name: serverless remove
      run: npx serverless remove --stage pr$(jq --raw-output .number "$GITHUB_EVENT_PATH")

作成時には serverlss のあとが deploy となっていたのに対してcloseされた際には環境を削除したいので remove となっています。

プルリクエスト動作の実行確認

準備が終わったので実行してみましょう。

GitHub Actionsコードのプッシュ

さきほど追加で作成したプルリクエスト オープン用とクローズ用のコードもmainブランチにpushしておきます。
GitHub Actionsはデフォルトブランチのコードのみが動作対象となるのが注意点です。

新規ブランチの作成

適当にブランチを作成してマスターブランチに対してPRを作成しましょう。

testというブランチを作成してチェックアウトします。

git checkout -b test

表示されるメッセージだけ変更します。

handlers.ts
import { APIGatewayProxyHandler } from 'aws-lambda';
import 'source-map-support/register';

export const hello: APIGatewayProxyHandler = async (event, _context) => {
  return {
    statusCode: 200,
-    body: JSON.stringify({
-      message: 'Go Serverless Webpack (Typescript) v1.0! Your function -executed successfully!',
-      input: event,
-    }, null, 2),
+    body: JSON.stringify({
+      message: 'GO! GitHub Actions!!',
+    }, null, 2),
  };
}

変更したファイルをリモートのtestブランチにpushします。
プッシュ後にプルリクエストを作成。

pr_open.png

PRを作成した段階でGitHub のActionsページをみると処理がはしっているはずです。
エラーが出ないことを確認したあとにAWSのコンソールをみてみると

apigete3.png

PR番号がついたAPI Gatewayがありますね!
実際に表示されたURLを確認してみます。

api-result3.png

変更されたメッセージが画面に表示されましたね。

確認できたのでマージします。

再びGitHub Actionsのページをみると処理が行われていることがわかります。
この段階ではPRのクローズ用のActionとmainブランチのdeploy用のActionの2つが走っています。
prcloseaction.png

AWSコンソールの画面をみると、先程作成されたapi gatewayが削除されていることが確認できますね。
final.png

もとのブランチもアップデートされているので残っているAPI Gatewayのレスポンスも変更されているかと思います。

おわりに

最後まで読んでいただきありがとうございます。
GitHub Actionsを使うと簡単に確認のための環境を構築できましたね!
これでプルリクエストのレビュー時にローカル環境で構築してみる or 手動でデプロイしてみる、という手間が不要になるのでチーム開発がスムーズになる・・・かもしれません。

実務ではDynamoDBやS3など各種リソースの記載と合わせて使うことが多いかと思いますが、その際にもリソース名にコマンドラインから渡されたstage名を含めると完全に分離された環境が作成可能です。
GitHub ActionsからSeed Dataの登録なども行うとテストデータも用意された環境構築もできます。
需要があれば別の機会にでも書きたいと思います。

RevCommではサーバーサイド、フロントエンド、モバイルアプリ、インフラを問わずエンジニア絶賛募集中です。
興味ある方はぜひまずはおしゃべりしましょう。
エントリーはこちらから。
https://hrmos.co/pages/revcomm/jobs

明日は@hiratake55さんの記事になります。

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
1