by @nyarla

GitLab Webhook → AWS Lambda → AWS CodeBuild → Hugo → Deploy を出来る様にした

このブログを含むカラクリスタ全体では Hugo でページ類を生成していて、 つい先日までは Gitlab CI で Hugo → Deploy を回す様にしてたんですが、この Gitlab CI 、 どうも時々キューを実行する Runner の空きが無くなって詰まる時が有ることが分かったので、 これを タイトルにも有る通り、

GitLab Webhook → AWS Lambda → AWS CodeBuild → Hugo → Deploy

という感じでサクっと出来る様にしました。

なんで今回はその辺りを話をサクっと書きたいと思います。

現在の CI/CD の概要

基本的にこのブログも含めた記事の類いは netlify-cms で書いていて、 netlify-cms は GitLab へのリポジトリへ API 経由でダイレクトにコミット出来る様にしています。

そのため GitLab へ記事などを Commit した際には通常の git push 時と同じく、 git push をトリガーに Webhook を起動できるのですが、この Webhook に、

AWS Lambda → AWS CodeBuild → Hugo → Deploy

を行なう Amazon API Gateway の HTTPS Endpoint を指定して、

GitLab への Commit 時に色々やって AWS CodeBuild を起動する

と言う様なコトを実際にやっています。

実際に使っているファイル定義

下記のサンプルコードは一部プロジェクト名などは伏せてますが、次の様なファイルをほぼそのまま用意し、 AWS CodeBuild や AWS Lambda を実行できる Role を Attach した上で実際の環境は動いています:

index.js (AWS Lambda)

"use strict";

const AWS = require("aws-sdk");

exports.handler = async (event) => {
  const token = event.headers["X-Gitlab-Token"] || "";

  if (token !== process.env.token) {
    return Promise.reject({ statusCode: 403 });
  }

  return new Promise((resolve, reject) => {
    var codeBuild = new AWS.CodeBuild();
    codeBuild.startBuild({ projectName: "XXXXXXXXXXX" }, (err, data) => {
      if (err !== null) {
        return reject({ statusCode: 500 });
      }

      resolve({
        statusCode: 200,
      });
    });
  });
};

buildspec.yml (AWS CodeBuild)

version: 0.2
phases:
  install:
    runtime-versions:
      nodejs: 10
    commands:
      - apt-get install -qq curl locales
      - curl -sL https://github.com/gohugoio/hugo/releases/download/v0.55.6/hugo_extended_0.55.6_Linux-64bit.deb -o hugo.deb
      - dpkg -i hugo.deb
  pre_build:
    commands:
      - export LC_ALL="en_US.UTF-8"
      - locale-gen en_US en_US.UTF-8
      - dpkg-reconfigure locales
      - test -d $HOME/repo || mkdir -p $HOME/repo
      - cd $HOME/repo
      - test -d .git || (git init && git remote add upstream https://oauth2:${gitlabToken}@gitlab.com/nyarla/${gitlabRepo})
      - git pull upstream master
  build:
    commands:
      - cd $HOME/repo
      - /usr/local/bin/hugo --minify
      - rm -rf public/pages
      - rm -rf public/search/search.js
      - rm -rf public/search/pages
      - rm -rf public/search/atom.xml
  post_build:
    commands:
      - aws s3 sync --exact-timestamps --delete public/ s3://the.kalaclista.com
      - aws cloudfront create-invalidation --distribution-id XXXXXXXXXXXX --paths "/*"
cache:
  paths:
    - $HOME/repo

以上

ちなみにこれ個人用途だしめっちゃ雑に構築したんでダイレクトに AWS のコンパネから設定していますが、 実際に業務などで使う場合には terraform なり pulumi.io なりを使った方が良いと思ってます。

あと動作検証もザックリと実際に動かして動けば良いやーという感じでテストしてたんで、色々試してた途中、一時的にこの WebSite 全体の CSS が吹っ飛んだ状態にもなっていたのはここだけの話です。

まぁでもこれで CI/CD に掛かる時間も短くなったし、良い感じに生成出来てるので、 個人的には満足しています。はい。