GitHub ActionsでECSにデプロイ

# やりたいこと
masterにpushしたらデプロイする

- アプリのビルド
    - ビルドキャッシュしてほしい
- アプリのテスト
    - 全てのブランチでテストしたい
- dockerのビルド
    - デプロイ関連はmasterだけでいい
- ECRへpush
- ECSタスク定義の更新
    - masterがデプロイされるようにさしかわってほしい
- ECSデプロイ！

# ディレクトリ構成

```
repository
├── .github
│   └── workflows
│       └── build_and_deploy.yml
├── ops
│   ├── ECS
│   │   └── task-definition.json
│   └── app
│       ├── Dockerfile
│       └── app.jar
└── src
```

大切な要素は３つです

- /.github/workflows/build_and_deploy.yml
Github Actionsが参照するファイル
ファイル名はなんでもいいです

- /ops/ECS/task-definition.json
ECSタスク定義を更新する元になるTaskDefinitionを置いてます
通常のTaskDefinitionなので、省略します
ファイル名とフォルダはどこでもいいです

- secretsの登録
Settings > Secretsから、AWSのアクセスキーなどを登録します
大切ですが、画面からポチポチするので省略します

## /.github/workflows/build_and_deploy.yml
全体像をのせながら、コメントで細かく注釈していきます

レファレンスはこちら、かなり頻繁に修正されています
https://help.github.com/ja/actions/reference/workflow-syntax-for-github-actions

```/.github/workflows/build_and_deploy.yml
# nameはなんでもいいが、フロー名として一覧に出る
name: build_and_deploy

# 全てのブランチでpushされた時に起動する
on:
  push:
    branches:
      - '**'

jobs:
  # アプリのビルドとテストのjob、名前はなんでもいい
  app_build_and_test:
    # docker imageを指定するやり方と比べると、選択肢はほとんどないが、winやmacも選べる
    runs-on: ubuntu-latest

    # stepという区切りでひとつひとつ実行し、失敗した場合、残りのstepが全てスキップされる
    # 個別にスキップされないstepを作ることもできる
    steps:
      # actionsという仕組みをとにかく多用する
      # リポジトリチェックアウト
      # https://github.com/actions/checkout
      - uses: actions/checkout@v2

      # javaの準備
      # https://github.com/actions/setup-java
      - uses: actions/setup-java@v1
        with:
          java-version: 11

      # アプリビルドのキャッシュ
      # リストアしたいタイミングで書くが、キャッシュ作成は書く必要がなく、jobが成功で終わった際にキャッシュ作成される
      # https://help.github.com/ja/actions/configuring-and-managing-workflows/caching-dependencies-to-speed-up-workflows
      # https://github.com/actions/cache
      - uses: actions/cache@v1
        with:
          path: ~/.gradle
          # ${{ ... }} はGithub Actionsの評価式
          # 用意されたオブジェクトと関数を使えるだけで、できることは意外と少ない
          key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}

      # アプリのビルド、テスト
      - name: app build
        run: ./gradlew build -x test
      - name: app test
        run: ./gradlew test

      # 作ったjarを別のjobに渡して、それを元にdockerのビルドをしたい
      # https://help.github.com/ja/actions/configuring-and-managing-workflows/persisting-workflow-data-using-artifacts
      # https://github.com/actions/upload-artifact
      - uses: actions/upload-artifact@v1
        with:
          name: appjar
          path: ops/app/app.jar

  # dockerのビルドとECSデプロイのjob
  docker_build_and_deploy:
    # 他のjobをwaitさせることで、直列なフローを作る
    needs: app_build_and_test

    # dockerまわりの処理はmasterしか動かさない
    # 関数とかもちょっと使える
    # https://help.github.com/ja/actions/reference/context-and-expression-syntax-for-github-actions
    if: contains(github.ref, '/heads/master')

    runs-on: ubuntu-latest

    # 環境変数はstep別に書くことも、共通で書くこともできる
    env:
      DOCKER_BUILDKIT: 1

    steps:
      # チェックアウト
      # https://github.com/actions/checkout
      - uses: actions/checkout@v2

      # 別jobで作ったファイルをダウンロードする
      # https://github.com/actions/download-artifact
      - uses: actions/download-artifact@v1
        with:
          name: appjar
          path: ops/app

      # awsの認証をする
      # https://github.com/aws-actions/configure-aws-credentials
      - uses: aws-actions/configure-aws-credentials@v1
        with:
          # secretsはWEBのgithubのrepositoryのsettingsから登録
          # ログ含め綺麗にマスクされる
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ap-northeast-1

      # ECRログイン
      # https://github.com/aws-actions/amazon-ecr-login
      - uses: aws-actions/amazon-ecr-login@v1
        # あとで結果を参照するのでidをつけておく
        id: login-ecr

      # dockerビルドとECRpush
      - name: docker build, ECR push
        # このstepだけで使える環境変数
        env:
          # ECRログインstepの結果を使う
          ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
          # secretsはWEBのgithubのrepositoryのsettingsから登録
          ECR_REPOSITORY: ${{ secrets.ECR_REPOSITORY }}
        run: |
          # GITHUB_SHAなど、最初から使える環境変数もある
          docker build -t ${ECR_REGISTRY}/${ECR_REPOSITORY}:${GITHUB_SHA} ./ops/app/
          docker push ${ECR_REGISTRY}/${ECR_REPOSITORY}:${GITHUB_SHA}

      # サンプルで書いてあってのでなんとなくログアウト...
      - name: ECR logout
        # alwaysを指定することで、どこかで失敗していてもこのstepに関しては動く
        if: always()
        # Github Actionsの評価式、実はrun内でも使える
        run: docker logout ${{ steps.login-ecr.outputs.registry }}

      # TaskDefinitionのimageとtagを差し替えした、新しいTaskDefinitionを作る
      # https://github.com/aws-actions/amazon-ecs-render-task-definition
      - uses: aws-actions/amazon-ecs-render-task-definition@v1
        with:
          # 元になるTaskDefinitionファイルのパス
          task-definition: ./ops/ECS/task-definition.json
          # コンテナ名
          container-name: ${{ secrets.ECS_CONTAINER_NAME }}
          # 新しいイメージ名とタグ
          image: ${{ steps.login-ecr.outputs.registry }}/${{ secrets.ECR_REPOSITORY }}:${{ github.sha }}
        # あとで参照するのでid
        id: render-web-container

      # ECSサービスの更新とデプロイ
      # https://github.com/aws-actions/amazon-ecs-deploy-task-definition
      - uses: aws-actions/amazon-ecs-deploy-task-definition@v1
        with:
          # 新しく作ったTaskDefinitionファイルのパスを指定
          task-definition: ${{ steps.render-web-container.outputs.task-definition }}
          # ECSサービス名
          service: ${{ secrets.ECS_SERVICE_NAME }}
          # ECSクラスタ名
          cluster: ${{ secrets.ECS_CLUSTER_NAME }}
```

# actionsについて
マーケットプレイスが用意されているのでそこから探す
https://github.com/marketplace?type=actions
作ることもできますが、だいたいのユースケースにおいては使うだけだとおもいます

Microsoftが管理してるactionsだけじゃなく、誰でもactionsを上げられる(はず)なので、そういう状況であることを認識して選びましょう
今回使ったのはMicrosoftとAWSが管理してるactionsです

## actionsの引数と戻り値どこ見るの
リポジトリのルートのactions.ymlを見るのがシンプルです
READMEに書かれていることも多いです

amazon-ecs-render-task-definitionを例にして、上のjobと見比べるとわかりやすいと思います
https://github.com/aws-actions/amazon-ecs-render-task-definition/blob/master/action.yml

## (2020/5) AWS関連のactions、まだあんまりない
一覧はここから見れます
https://github.com/aws-actions

しかしデプロイ関連は、まだあまりないです、2020/1に確認した時は4つだけだったので、ここもすごい勢いで増えています

- https://github.com/aws-actions/configure-aws-credentials
- https://github.com/aws-actions/amazon-ecr-login
- https://github.com/aws-actions/amazon-ecs-render-task-definition
- https://github.com/aws-actions/amazon-ecs-deploy-task-definition
- https://github.com/aws-actions/aws-cloudformation-github-deploy
- https://github.com/aws-actions/aws-codebuild-run-build

といっても、awsコマンドやjqは、ubuntu-latestなどのホストランナーに入っているのであまり困りません
https://help.github.com/ja/actions/reference/software-installed-on-github-hosted-runners

## CodeDeploy（Blue/Green）は？
**amazon-ecs-deploy-task-definitionが対応したもよう**
試せてないです、