actを使ってGithub Actionsをローカルで実行する

[act](https://github.com/nektos/act)はGithub Actionsで実行される処理をローカルで行うことができるツールです。

Github ActionsはGithub上でしか動かないので、実行結果を確認するためには[on](https://docs.github.com/ja/actions/using-workflows/workflow-syntax-for-github-actions#on)の値に`pull_request`を指定してマージ前に動かしたり、`workflow_dispatch`を指定してマージ後に手動で動かしたり工夫をする必要があります。

ですが、[act](https://github.com/nektos/act)ならGithub Actionsのワークフローファイルをローカルで実行することができます。

actはDocker上で動作し、実行環境の提供は`ubuntu`のみです。（[Github Actionsでは対応](https://docs.github.com/ja/actions/using-github-hosted-runners/about-github-hosted-runners#github-%E3%83%9B%E3%82%B9%E3%83%86%E3%83%83%E3%83%89-%E3%83%A9%E3%83%B3%E3%83%8A%E3%83%BC%E3%81%AE%E4%BD%BF%E7%94%A8)しているmacOS,windowsの実行環境は試せない）

# 事前準備
Windows 10 上のWSL2(Ubuntu 20.04)で行っています。

1. Dockerを入れます。
    - https://github.com/nektos/act#installation を参照ください。
2. Homebrewを入れます。
    - https://brew.sh/ を参照ください。
        - Homebrew以外にも[様々なパッケージ管理ツールに対応](https://github.com/nektos/act#installation-through-package-managers)しています。
3. `brew install act`
4. `curl https://raw.githubusercontent.com/nektos/act/master/install.sh | sudo bash`


# 実行

[actお試し用のサンプルリポジトリ](https://github.com/cplee/github-actions-demo)の[main.yml](https://github.com/cplee/github-actions-demo/blob/master/.github/workflows/main.yml)とGithubのsecrets動作確認用のファイル(`test.yml`)を作って実行してみました。

```yml:main.yml
name: CI
on: push

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: actions/setup-node@v1
    - run: npm install
    - run: npm test
```

```yml:test.yml
name: Secretsテスト
on: 
  schedule:
    - cron: '00 02 * * *'

jobs:
  build:

    runs-on: ubuntu-20.04
    timeout-minutes: 15
    env:
      ACCESS_KEY: ${{ secrets.TEST_ACCESS_KEY }}
    
    steps:
      - uses: actions/checkout@v3
      - run: echo "ACCESS_KEY = ${{ env.ACCESS_KEY }}"
```

`act -l`で実行できるリストを表示します。

```shell
$ act -l
Stage  Job ID  Job name  Workflow name     Workflow file  Events  
0      test    test      CI                main.yml       push    
0      build   build     Secretsテスト        test.yml       schedule
```


`main.yml`を実行してみます。job名とディレクトリを記載して指定のjobを実行します。
初回は[どのコンテナで実行するかのパターンを選択](https://github.com/nektos/act#runners)する必要があります。

```shell
$ act -j test -W .github/workflows/main.yml
[CI/test] 🚀  Start image=catthehacker/ubuntu:act-latest
---------------------------------------- # 間のコードは省略
[CI/test]   ✅  Success - Main actions/checkout@v2
[CI/test]   ✅  Success - Main npm install
[CI/test]   ✅  Success - Main npm test
[CI/test] 🏁  Job succeeded
```
実行は成功しました。



次は`test.yml`を実行してみます。`act -s MY_SECRET=somevalue`とすることで[Secrets環境変数を入れた状態で実行](https://github.com/nektos/act#secrets)できます。
もしくは`my.secrets`ファイルを作成しそこに`.env`形式と同様に値をいれて`act --secret-file my.secrets`とします。

```shell
$ act -j build -W .github/workflows/test.yml -s TEST_ACCESS_KEY=abcdefg
[Secretsテスト/build      ] 🚀  Start image=catthehacker/ubuntu:act-20.04
----------------------------------------
[Secretsテスト/build      ]   ✅  Success - Main actions/checkout@v3
[Secretsテスト/build      ]   ✅  Success - Main echo "ACCESS_KEY = ***"
[Secretsテスト/build      ] 🏁  Job succeeded
```

こちらも実行は成功です。
`-s`の引数が無い状態で実行しても成功しますが、`ACCESS_KEY = `とブランクな値が返されますので、Secretsの`TEST_ACCESS_KEY`に値を入れる事にも成功しています。

## データマート作成用Github Actions実行ファイルの確認に用いる

AWSのアクセスキー、シークレットキーを用いてAthenaへクエリを実行し、BIツール用のテーブルを作成・更新するまでの動作をGithub Actionsで行いたいとします。
また、必要があればPythonのPandasライブラリを使ってデータを加工したい為、Poetryを用いてPythonのライブラリ環境を構築しているとします。
この時にactを用いてGithub Actions実行ファイルの動作をチェックします。

[こちらのリポジトリ](https://github.com/nijigen-plot/python_repository_template)をクローンしローカルで以下のファイルを追加して、actを使ってAthenaへクエリを叩く動作をローカルで実行してみました。

```python:get_current_timestamp.py
import os

import awswrangler as wr
import boto3

session = boto3.Session(
    aws_access_key_id=os.environ.get("ATHENA_ACCESS"),
    aws_secret_access_key=os.environ.get("ATHENA_SECRET"),
    region_name="ap-northeast-1",
)
WORKGROUP = "primary"
S3DIR = "s3://query-results-bucker/primary_folder/"

df = wr.athena.read_sql_query(
    "SELECT CURRENT_TIMESTAMP",
    database="*",
    boto3_session=session,
    workgroup=WORKGROUP,
    s3_output=S3DIR,
    ctas_approach=False,
)

print(df)

```


```yml:update_data.yml
name: データ更新
on: 
  schedule:
    - cron: '00 02 * * *'

jobs:
  build:

    runs-on: ubuntu-20.04
    timeout-minutes: 30
    env:
      ATHENA_ACCESS: ${{ secrets.AWS_ACCESS_KEY_ID }}
      ATHENA_SECRET: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
    
    steps:
      - uses: actions/checkout@v2
      - uses: actions/setup-python@v2
        with:
          python-version: '3.9.11'
        
      - run: pip install poetry==1.1.13
      - run: poetry install
      - run: |
          poetry run python get_current_timestamp.py
```


Secrets環境変数は、`my.secrets`ファイルを作成しそこに記載する形で実行してみました。

```my.secrets
AWS_ACCESS_KEY_ID=xxxxxxxxxx
AWS_SECRET_ACCESS_KEY=yyyyyyyyyy
```


`update_data`.ymlをローカル実行

```shell
$ act -j build --secret-file my.secrets -W .github/workflows/update_data.yml
[データ更新/build          ] 🚀  Start image=catthehacker/ubuntu:act-20.04
----------------------------------------
[データ更新/build          ]   ✅  Success - Main actions/checkout@v2
[データ更新/build          ]   ✅  Success - Main actions/setup-python@v2
[データ更新/build          ]   ✅  Success - Main pip install poetry==1.1.13
[データ更新/build          ]   ✅  Success - Main poetry install
|                              _col0
| 0 2022-12-24 08:09:58.175000+00:00
[データ更新/build          ]   ✅  Success - Main poetry run python get_current_timestamp.py
[データ更新/build          ]   ✅  Success - Post actions/setup-python@v2
[データ更新/build          ] 🏁  Job succeeded
```

無事に`SELECT CURRENT_TIMESTAMP`の結果が返ってきました。
実際はここでデータを取得したり、CREATE, INSERT, UNLOAD等DDL操作を行うクエリを書きます。


# まとめ
- GithubへGithub Actions ymlファイルをPushしなくても実行確認できるので便利
- [Github Actions環境を100%再現しているわけではない](https://github.com/nektos/act#default-runners-are-intentionally-incomplete)ので、そこは理解した上で使う必要がある