GitHub ActionsでNodeサーバーでbuildを走らせる


目的:

記事にヘッドレスCMS+SSGを導入することに当たってNodeサーバー構築し、
GitHubActionでpush時に自動でgitから最新ソースをpull後にnodeサーバーでbuildする仕組みを実装

前提:

下記のNodeサーバー構築完了
https://qiita.com/kerry/items/7a414f6fa2ca793c407e

必要な情報をGitHubに登録

下記の必要なサーバーへ接続情報(envに設定する)をGitHubに登録する。
GitHubのSettingsタブの一番下のSecretsメニューを選択して順番に登録する。

      AWS用のACCESS_KEY(secrets.AWS_ACCESS_KEY_ID)
      AWS用のSECRET_ACCESS_KEY(secrets.AWS_SECRET_ACCESS_KEY_ID)
      AWS用のSECURITY_GROUP_ID(secrets.AWS_SECURITY_GROUP_ID_STG)
      SSH用の鍵(secrets.PRIVATE_KEY_STG)
      SSH用のユーザー名(secrets.USER_NAME)
      SSH用のHost(secrets.HOST_NAME_STG)

GitHubActionsのworkflow作成

GitHubのActionsタブに入って新しくTempleteを利用して
.github/workflows/stag.ymlファイルを作成

処理の流れ:

・Github ActionsのイメージのIPを取得
・AWS CLIをインストール
・AWS CLIの設定
・EC2のセキュリティグループにルールを追加
・SSH接続する
・サーバーでGit pull処理
・nodeサーバーでbuild処理
・EC2のセキュリティグループからルールを削除

実装コート:

name: deploy stag

on:
  push:
    branches: [stag]

jobs:
  deploy:
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/stag'
    steps:
      - uses: actions/checkout@v2

      - name: deploy stag
        env:
          ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }}
          SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
          SECURITY_GROUP: ${{ secrets.AWS_SECURITY_GROUP_ID_STG }}
          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY_STG }}
          USER_NAME: ${{ secrets.USER_NAME }}
          HOST_NAME: ${{ secrets.HOST_NAME_STG }}
        run: |
          IP_ADDRESS=`curl https://api.ipify.org/ -s`

          # AWS CLIインストール
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip awscliv2.zip
          sudo ./aws/install
          aws --version

          # AWS CLI設定
          printf "${ACCESS_KEY}\n${SECRET_ACCESS_KEY}\nap-northeast-1\njson\n" | aws configure --profile blog-stag
          aws configure get aws_access_key_id --profile blog-stag

          # セキュリティグループにルールを追加
          aws --profile blog-stag ec2 authorize-security-group-ingress --group-id ${SECURITY_GROUP} --protocol tcp --port 22 --cidr "$IP_ADDRESS"/32

          # sshキーをコピー
          mkdir -p /home/runner/.ssh
          touch /home/runner/.ssh/private_key.pem
          echo "$PRIVATE_KEY" > /home/runner/.ssh/private_key.pem
          chmod 600 /home/runner/.ssh/private_key.pem

          # known_hostsに追加
          ssh-keyscan ${HOST_NAME} >> ~/.ssh/known_hosts

          # テスト環境にclone
          #cd ./deploy && git clone [email protected]:test/blog.git /home/ec2-user/deploy

          # SSH接続して、git pullする
          ssh -o StrictHostKeyChecking=no -i /home/runner/.ssh/private_key.pem ${USER_NAME}@${HOST_NAME} '
          source ~/.bash_profile &&
          cd /home/ec2-user/deploy/blog &&
          git checkout stag && git fetch --all &&
          git reset --hard origin/stag &&
          git pull origin stag &&
          chmod +x /home/ec2-user/deploy/deploy_node.sh &&
          sh /home/ec2-user/deploy/deploy_node.sh
          '

          # セキュリティグループからルールを削除
          aws --profile blog-stag ec2 revoke-security-group-ingress --group-id ${SECURITY_GROUP} --protocol tcp --port 22 --cidr "$IP_ADDRESS"/32

上記の実行しているシェルの中身
sh deploy_node.sh
```

!/bin/sh

nodenv local 14.15.1
npm ci
npm run build
```

今回はサーバー上に静的htmlを吐き出したがったので、pull後に直接nodeサーバー内でbuildする仕組みを実装したが、下記のようにS3に保存することも可能

S3にアップ

上記の情報以外に下記の情報が追加で必要

      AWS用のS3_BUCKET名(secrets.AWS_S3_BUCKET)

実装コート:

name: deploy stag

on:
  push:
    branches: [stag]

jobs:
  deploy:
    name: git pull origin
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/stag'
    steps:
      - uses: actions/checkout@v2

      - name: deploy stag
        env:
          ACCESS_KEY: ${{ secrets.AWS_ACCESS_KEY_ID }}
          SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
          SECURITY_GROUP: ${{ secrets.AWS_SECURITY_GROUP_ID_STG }}
          PRIVATE_KEY: ${{ secrets.PRIVATE_KEY_STG }}
          USER_NAME: ${{ secrets.USER_NAME }}
          HOST_NAME: ${{ secrets.HOST_NAME_STG }}
        run: |
          IP_ADDRESS=`curl https://api.ipify.org/ -s`

          # AWS CLIインストール
          curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
          unzip awscliv2.zip
          sudo ./aws/install
          aws --version

          # AWS CLI設定
          printf "${ACCESS_KEY}\n${SECRET_ACCESS_KEY}\nap-northeast-1\njson\n" | aws configure --profile blog-stag
          aws configure get aws_access_key_id --profile blog-stag

          # セキュリティグループにルールを追加
          aws --profile blog-stag ec2 authorize-security-group-ingress --group-id ${SECURITY_GROUP} --protocol tcp --port 22 --cidr "$IP_ADDRESS"/32

          # sshキーをコピー
          mkdir -p /home/runner/.ssh
          touch /home/runner/.ssh/private_key.pem
          echo "$PRIVATE_KEY" > /home/runner/.ssh/private_key.pem
          chmod 600 /home/runner/.ssh/private_key.pem

          # known_hostsに追加
          ssh-keyscan ${HOST_NAME} >> ~/.ssh/known_hosts

          # テスト環境にclone
          #cd ./deploy && git clone [email protected]:com:test/blog.git /home/ec2-user/deploy

          # SSH接続して、git pullする
          ssh -o StrictHostKeyChecking=no -i /home/runner/.ssh/private_key.pem ${USER_NAME}@${HOST_NAME} '
          cd /home/ec2-user/deploy/blog &&
          git checkout stg && git fetch --all &&
          git reset --hard origin/stg &&
          git pull origin stg
          '

          # セキュリティグループからルールを削除
          aws --profile blog-stag ec2 revoke-security-group-ingress --group-id ${SECURITY_GROUP} --protocol tcp --port 22 --cidr "$IP_ADDRESS"/32

  build:
    name: build and deploy to s3
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/stag'
    strategy:
      matrix:
        node-version: [14.15.1]
    steps:
      - uses: actions/checkout@v2

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v1
        with:
          node-version: ${{ matrix.node-version }}
      - run: npm ci
      - run: npm run build --if-present
      - run: npm test

      - name: s3 sync
        uses: jakejarvis/s3-sync-action@master
        with:
          args: --acl public-read --follow-symlinks --delete
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY_ID }}
          AWS_REGION: 'ap-northeast-1'
          AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
          SOURCE_DIR: 'out'

今回ハマったところ

nodenvコマンドのところで下記のエラーが発生。

bash: line 5: nodenv: command not found

直接サーバーでは問題なくbuildできたのに、、
ssh接続後下記を追加で解決

source ~/.bash_profile

https://superuser.com/questions/564926/profile-is-not-loaded-when-using-ssh-ubuntu