これまで適当に作っていたGitHub Actionsを再構成した

# えっ…わたしのGitHub Actions、汚すぎ！？
GitHubActionsを、主に社内ドキュメント管理のリポジトリに対して活用しています。
リポジトリにcommitされたmarkdownファイルをHugoでbuildしてS3にdeployする、という工程をすべて自動でやっている感じです。
ブランチを分けて、作成中のドキュメントと完成したドキュメントがそれぞれdeployされる状態にしてみたり、場合によってはdeploy結果をSlackに通知してみたりしています。

ちょっと試してみよう～♪というノリから、だいぶガッツリ使ってしまっているため、
ファイル数も増えてきていたり、似たような処理の記述を複数ファイルで繰り返していたり…。
さすがにまずいかなと思い、リファクタリングを検討してみます。

# ついでにtokenの個人依存をやめる
これまで、これまた適当に、個人依存のpersonalAccessTokenで回していました。
せっかくの機会なので、これもやめます。

代替となるのは、GitAppsTokenです。

## 1. GitHub Appを作成する
面倒そうだなと思って敬遠していましたが、tokenが欲しいだけなら非常にカンタンに作れました。

公式ドキュメントに従って作業します。
https://docs.github.com/en/developers/apps/building-github-apps/creating-a-github-app

`Organization>Settings>Developers settings>GitHub Apps>New GitHub App`を選択します。

![GitHubApps01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/666457/c46f52f4-095b-8215-a646-a5bf8b175bf2.png)

- 名前やdescriptionを適当に付けます。
- HomepageURLはorganizationのURLを付けておきました。
- チェックボックスは全部外しました。
- 権限は「Actions」、「Checks」、「Contents」「Deployments」「Commit statuses」に付けておきました。 
 - どういうGitHubActionsを組んでいるかによってつけるべき権限が変わると思いますが、後からでも付け替えられるので、よく分からない場合は、とりあえずそれらしい権限を付けて作成しちゃっても良いと思います。
- アプリをインストールできる場所は、このアカウントでのみ、にしておくのが良い。

## 2. 秘密鍵を作成する
無事にGitHub Appが作成できたら、Private keyを作成しましょう。
「Generate a private key」を押すだけで作成できます。

これで得たpemファイルの中身を利用して、GitHub Actions起動時にGitAppsTokenを作成することができます。
そういったアクションはいくつかありましたが、今回は↓を使いました。

https://github.com/tibdex/github-app-token


# ついでのついでに、SecretsをOrganizationで共有・設定した

これは2020年のアップデートでできるようになっていたみたいです。

https://github.blog/changelog/2020-05-14-organization-secrets/

`Organization>Settings>Secrets`で、ポチポチ設定するだけ！

今まで、同じSecretsを色んなリポジトリで1つ1つ設定していたので、
新しいリポジトリを作成したときやキーローテーションの時など、非常に手間でした。。。
これからはリポジトリ一括で変更できます！

リポジトリ側で同じKeyのSecretsが設定されていると、そちらを優先して採用して実行してくれるみたいです。

# ようやく本題：workflowの整理整頓

https://docs.github.com/ja/actions/creating-actions/creating-a-composite-action

Composite Action（複合ステップアクション）、以前に見たときは、外部のActionsを使うことができない等の制約が多くて、イマイチ使い勝手が悪いなと思ってスルーしていました。しかし、そのあたりがアップデートされてだいぶ実用性が出てきています。

今回は、これを使って、これまで場当たり的に作っていたGitHub Actionsをいいかんじに整理整頓してみようと思います。

## 1. ブランチ別にファイルを分けていたのをまとめる
mainブランチ・developブランチなど複数ブランチでそれぞれ同じような処理を行っているのに、ファイルを分けてしまっている状態でした。

トリガーをまとめて、ブランチ名によって処理が変わる部分は変数で置き換えてあげました。

```yml
on:
  push:
    branches: [main,release,develop]
workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-18.04
    steps:
######## 省略 ########
      - name: Upload file to S3
        env:
          S3_UPLOAD_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
        run: |
          aws s3 sync --exact-timestamps --delete public s3://$S3_UPLOAD_BUCKET/}/${GITHUB_REF#refs/heads/}
```

## 2. compositeを利用して、処理を切り出す
色々調べてみた結果、元々のファイルはメインファイルとして使用しながら、複数ファイルで使用している共通処理をcompositeとして切り出すのがよさそうです。

これがメインのファイル。

```yml:.github/workflows/main.yml
on:
  push:
    branches: [main,release,develop]
workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-18.04
    steps:
# Checkoutするためにtokenを作成
      - name: Generate token
        id: generate_token
        uses: tibdex/github-app-token@v1
        with:
            app_id: ${{ secrets.APP_ID }}
            private_key: ${{ secrets.APP_PRIVATE_KEY }}

      - uses: actions/checkout@v2
        with:
          submodules: true  # Fetch Hugo themes
          token: ${{ steps.generate_token.outputs.token }}
          fetch-depth: 0    # Fetch all history for .GitInfo and .Lastmod

######## 省略 ########

      - id: deploy
        uses: ./.github/workflows/deploy/
        with: 
          github-token: ${{ secrets.GITHUB_TOKEN }}
          aws-access-key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          s3-bucket: ${{ secrets.AWS_S3_BUCKET }}
```

これがcompositeとして切り出したファイル。
compositeのファイルでは、runのときに`shell: bash`を明示してあげないといけません。

```yml:.github/workflows/deploy/action.yml
name: "Deploy"
description: "deploy to s3"
inputs:
  github-token:
    required: true
  aws-access-key:
    required: true
  aws-secret-key:
    required: true
  s3-bucket:
    required: true
  deploy-path:
    required: true
runs:
  using: "composite"
  steps:
   - name: githubpages
     uses: peaceiris/actions-gh-pages@v3
     with:
       github_token: ${{ inputs.github-token }}
       publish_dir: ./public

   - name: Configure AWS credentials
     uses: aws-actions/configure-aws-credentials@v1
     with:
        aws-access-key-id: ${{ inputs.aws-access-key }}
        aws-secret-access-key: ${{ inputs.aws-secret-key }}
        aws-region: ap-northeast-1

   - name: Upload file to S3
     env:
         S3_UPLOAD_BUCKET: ${{ inputs.s3-bucket }}
     shell: bash
     run: |
         aws s3 sync --exact-timestamps --delete public s3://$S3_UPLOAD_BUCKET//${GITHUB_REF#refs/heads/}
```

# おわりに
走らせてみると、これまでと同様に動いてくれました！
ちょっとまだ汚いですが、以前に比べると圧倒的にメンテナンス性が上がってよかったです:relaxed:
まだ発展途上の機能だと思うので、これからもっと使いやすくなりそうな予感。

とりあえず、GitHubActionsも組織で管理できるようになるともっと楽だな…。