GithubActionsを使って、pushをトリガーにファイルをS3やサーバに同期する方法

Githubのレポジトリに上げたhtmlファイルをpushをトリガーに自動的にS3やサーバに同期する方法は何通りかあると思います(CIを何か使ったりAWS側の設定でやったり)が、手軽にできるGithubActionsを使ってやる方法を紹介したいと思います。

GithubActionsとは

対象のgithubレポジトリの

.github/workflows/

配下に指定の形式でymlファイルを設置すると、そこに書いてある内容を読み取って、Githubが自動的に何か動作をしてくれる仕組みです(CIツールが担っていた機能をGithub自体が持ってくれた感じですね)。
手軽に書ける上に、GithubActionで利用できるpluginがマーケットプレイスというところで大量に配布されているので、自分がやりたいなぁと思っているようなことは大体pluginを入れると瞬殺できます(便利な世の中ですね)。

GithubActionsの料金体系

Githubのdocumentによると2021-09月時点で、Freeプランでも結構な無料枠があります(サイズが全てのrepositoryの合計サイズなことに注意)。

前段はこのくらいにして、実際の例を見てみましょう。

Githubにあげたファイルを自動でS3に上げる方法

こちらはpluginを使うことで簡単にできます。htmlファイルを上げる場合、CloudFrontでキャッシュしている事が多いかと思うので、キャッシュを無効化(invalidation)するpluginもセットで書き方を紹介します。

on:
 push:
   branches:
   - main

jobs:
 deploy:
   runs-on: ubuntu-latest
   steps:
   - uses: actions/checkout@master
   - name: sync s3-bucket
     uses: jakejarvis/s3-sync-action@master
     with:
       args: --acl public-read --follow-symlinks --delete
     env:
       AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
       AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
       AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
       AWS_REGION: 'ap-northeast-1'   # optional: defaults to us-east-1
       SOURCE_DIR: 'lp'      # optional: defaults to entire repository
       DEST_DIR: 'lp'      # optional: defaults to entire repository
   - name: invalidate
     uses: chetan/invalidate-cloudfront-action@master
     env:
       DISTRIBUTION: ${{ secrets.DISTRIBUTION }}
       PATHS: '/lp/*'
       AWS_REGION: 'ap-northeast-1'
       AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
       AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      

使うpluginは

jakejarvis/s3-sync-action

chetan/invalidate-cloudfront-action

の2つです。githubレポジトリのlp/配下のファイルをS3上の指定のbucketのlp/配下に同期させ、cloudfrontのlp/配下のキャッシュを削除する形です。
上のPluginの説明にほぼ上記と同様のymlが載っています。

自動で物理サーバにsftpで上げる方法

今度はこちらの方法です。これについても同様にpluginが色々あるのですが、うちの設定の場合、パスワード認証がはいっているため、marketplaceのpluginが思ったように使えず、自分でlftpコマンドをコンパイルして実行する、という方法を取らざるを得ませんでした。


name: CI

on:
 push:
   branches:
     - main

# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
 # This workflow contains a single job called "build"
 build:
   # The type of runner that the job will run on
   runs-on: ubuntu-latest

   # Steps represent a sequence of tasks that will be executed as part of the job
   steps:
     # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
     - uses: actions/checkout@v2

     - name: install gnutls
       run: sudo apt-get update && sudo apt-get install libneon27-gnutls-dev
     # apt-getではいるlftpが4.8.4で、このユースケースでの不具合があるため4.9.2を落としてcompileしたものを使う。
     - name: compile lftp
       run: tar zxvf lftp-4.9.2.tar.gz && cd lftp-4.9.2 && ./configure && sudo make install

     # syncする。
     - name: execute lftp for for_producer
       run: lftp -c "set sftp:auto-confirm true; set ssl:verify-certificate no; set net:max-retries 1; set cmd:default-protocol sftp; connect ${{ secrets.SFTP_USER }}:${{ secrets.SFTP_PW }}@${{ secrets.SFTP_IP }}; mirror -Rv --delete --ignore-time --parallel=2 ./for_producer/ ~/public/for_producer/; quit"

コメントで記載しているように、apt-getで入るlftpが4.9.0未満だとコマンドプロンプトの応答がうまく処理できずfailします。こちらの記事に詳しいです(これに気づくのに非常に時間がかかりました...)。そのため、github上に

lftp-4.9.2.tar.gz

を予め公式から落としておいておき、それを毎回compileして実行するというなんとも面倒な方法をとっています。面倒でしたが、自動化できたのは大きいです(上げ漏れとかもなくなったので)。

lftpのコマンドの書き方もたくさんありなかなかどれが正解かわからなかったのですが上記の方法でgithub上のfor_producer/配下のファイルをリモートサーバのpublic/for_producerに同期させることができました。

物理サーバを使われている方は最近少なくなっているかとは思いますが、もし使われていて困っている方のお役に立てば幸いです。

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