今更だけどGitHub Actionsに入門してみた

## 記事の目的

業務でCircleCIからGitHubActionsへのリプレイスを行った際に調べた事や記述などまとめておきます。（ほぼ自分用）

間違ってる箇所などあれば教えてください:robot:
## GitHub Actionsとは？
GitHubに組み込まれたCI/CD機能
2018年10月に開催された開発者のためのカンファレンス、GitHub Universeにて発表され、
2019年11月にリリースされた新しめの技術

## 特徴
### ○無料で使える！
正確にはPublicリポジトリであれば無料で、Privateリポジトリは有料ですが2000分/月まで無料で使えちゃいます。（うちのような小規模プロジェクトでは十分）
[料金詳細 →](https://docs.github.com/ja/github/setting-up-and-managing-billing-and-payments-on-github/about-billing-for-github-actions)

### ◯GitHubのイベントをトリガーに出来る！
branchにpushやissueの発行、pull requestなど様々なイベントをトリガーにすることができます。
[ワークフローをトリガーするイベント →](https://docs.github.com/ja/actions/reference/events-that-trigger-workflows)
### ◯豊富なアクション！
GitHub Actionsでは、実行する処理を定義したものを**Workflow（ワークフロー）**と呼びます。
ワークフロー内では、シェル経由で任意のコマンドを実行できるほか、**Action（アクション）**という、あらかじめ定義済みの処理が豊富に用意されています！
[Actions →](https://github.com/marketplace?type=actions)

### ○キックの単位をフィルタリング出来る！
特定のディレクトリ、ファイルでフィルタリングが出来る為、IaC系のコードの変更時のみなど特定のにキックされるワークフローを作る事ができます。
[フィルタパターンのチートシート →](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet)

他にもスケジューリングなどたくさんの機能があります。


## Secrets
シークレットは暗号化された環境変数で、Organization、リポジトリ、あるいはリポジトリ環境に作成でき、作成したシークレットは、GitHub Actionsワークフローで利用できる！
※設定はリポジトリオーナーのみ

```yaml
${{ secrets.DOCKERHUB_USERNAME }}
```
[暗号化されたシークレット →](https://docs.github.com/ja/actions/reference/encrypted-secrets)
## Workflow（ワークフロー
GitHub Actionsは、YAML 構文を使用して、イベント、ジョブ、およびステップを定義する。

```yaml
name: ci

on:
  push:
    branches: main

jobs:
  login:
    runs-on: ubuntu-latest
    steps:
      -
        name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}
```

### ■ name
好きなワークフロー名

```yaml
name: ci
```

### ■ on（必須）
#### ワークフローをトリガーするGitHubイベントを決めます

#### □ on.push

```yaml
# リポジトリ内のpushでキック
on: push
```
```yaml
# masterブランチのpushでキック
on:
  push:
    branches: master
```

#### □ on.pull_request

```yaml
# リポジトリ内のpush, PRでキック
on: [push, pull_request]
```
```yaml
# mainブランチのpush, PRでキック
on:
  push:
    branches:
      - main
  pull_request:
    branches:
      - main
```

#### □ on.paths

```yaml
# cloud_formation_templates/以下の変更があった場合のみキック
# IaC系とアプリコードを同一リポジトリで管理しやすくなりそう
on:
  push:
    paths:
    - 'cloud_formation_templates/**'
```

```yaml
# !否定
on:
  push:
    paths:
    - '!**.md'
```
[フィルタパターンのチートシート →](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#filter-pattern-cheat-sheet)

### ■ env
ワークフローで設定出来る環境変数
設定した箇所でスコープが異なる

```yaml
# 全てのjobから参照可
env:
  RAILS_ENV: production

jobs:
  job1:
    name: Greeting
    runs-on: ubuntu-latest
　　 # job1内から参照可
    env:
      GREET: Hello

    steps:
    - name: Print greeting
      # steps Print greeting内から参照可
      env:
        FIRST_NAME: Satoru
        LAST_NAME: Gojo
      run: |
        echo $GREET $LAST_NAME $FIRST_NAME.
　　　　　
　　　　　# => Hello Gojo Satoru
```

### ■ jobs
ワークフローには１つ以上のジョブからなり、 デフォルトでは、ジョブは**並行して実行**されます。後述する`needs`などを使いジョブを順番に実行するようにワークフローを設定することもできます。
各ジョブは仮想環境の**新しいインスタンス**で実行される為、
ジョブ間で環境変数やファイル、実行結果などは共有されないので注意！

#### □ jobs.< jobs_id >
ジョブ内でユニークな文字型で命名

```yaml
jobs:
  first_job_id:

  second_job_id:
```

#### □ jobs.< jobs_id >.runs-on（必須）
ジョブが実行される仮想環境を指定

```yaml
jobs:
  first_job_id:
    runs-on: ubuntu-latest

  second_job_id:
    runs-on: windows-latest
```
`Windows Server 2019`, `macOS Big Sur 11.0`などなどが使えます。
[jobs.< jobs_id >.runs-on →](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#)


#### □ jobs.< job_id>.steps
１つのジョブ内で順番に実行されるタスク

```yaml
jobs:
  first_job_id:
    runs-on: ubuntu-latest
    steps:
      - name: My first step
      run: echo First step.

      - name: My second step
      run: echo Second step.
```

#### □ jobs.< job_id>.needs
ジョブの実行前に正常完了する必要があるジョブを指定し依存関係を作る

1. `job1`実行
2. `job1`が正常終了されたら`job2`を実行
3. `job1`と`job2`が正常終了されたら`job３`を実行

```yaml
jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]
```

#### □ jobs.< job_id>.steps[*].run
コマンド実行！
[シェルのカスタマイズ](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#using-a-specific-shell)も出来る

```yaml
jobs:
  first_job_id:
    runs-on: ubuntu-latest
    steps:
      - name: My first step
      run: echo First step.

      # 複数コマンド実行
      - name: My second step
      run: |
        echo First line.
        echo Second line
        echo Third line
```


#### □ jobs.< job_id>.steps[*].uses
ステップの一部として実行される[アクション](#豊富なアクション)を選択できます！
AWSの初期セットアップもこれでオッケー

```yaml
steps:
  - name: checkout
    uses: actions/checkout@v2
  - name: configure AWS credentials
    uses: aws-actions/configure-aws-credentials@v1
    # with => 入力パラメータ
    with:
      aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
      aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
      aws-region: ap-northeast-1
```


## Tips

#### 指定ブランチにマージされたらキックする
```yaml

on:
  pull_request:
    branches:
      - main
    types: [closed]

jobs:
  test:
    runs-on: ubuntu-latest
    if: github.event.pull_request.merged == true
```

#### Slackへ実行結果の通知
```yaml
  slack-notify:
    if: always()
    needs: test
    name: workflow notification to slack
    runs-on: ubuntu-latest
    steps:
      - uses: Gamesight/slack-workflow-status@master
        with:
          repo_token: ${{ secrets.GITHUB_TOKEN }}
          slack_webhook_url: ${{ secrets.SLACK_WEBHOOK_URL }}

# ${{ secrets.GITHUB_TOKEN }} => デフォルトの環境変数
```

#### Docker Hub Build Push

```yaml
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Check Out Repo
        uses: actions/checkout@v2

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v1

      - name: Login to DockerHub
        uses: docker/login-action@v1
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}

      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v1

      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: ./Dockerfile
          push: true
          tags: ${{ secrets.DOCKER_IMAGE_REPO }}:latest

      - name: Image digest
        run: echo ${{ steps.docker_build.outputs.digest }}

```

## 参考
[GitHub Actionsのワークフロー構文](https://docs.github.com/ja/actions/reference/workflow-syntax-for-github-actions#)
[Configure GitHub Actions](https://docs.docker.com/ci-cd/github-actions/)
[Github Actionsの使い方メモ](https://qiita.com/HeRo/items/935d5e268208d411ab5a)
[GitHubの新機能「GitHub Actions」で試すCI/CD](https://knowledge.sakura.ad.jp/23478/)
[GitHub Actionsでworkflow全体の結果をSlackに通知する](https://swfz.hatenablog.com/entry/2020/10/21/091628)
[Github Actionsに入門してみた(CI編)](https://www.wantedly.com/companies/tutorial/post_articles/297967)