Github Actions で Renovate を実行する


## 背景

別プロジェクトで [Renovate](https://docs.renovatebot.com/) の [Github Apps](https://github.com/apps/renovate) を使ってライブラリの自動更新をしていました。
諸々の事情で、新しいプロジェクトでは Github Apps の Renovate は使えなかったため、セルフホストで Renovate を動かす必要が出てきました。

今回は Github Actions であれば OK だったので Github Actions で Renovate を動かす方法を記載します。

## 設定方法
### 対象のプロジェクトに renovate.json を追加し、設定を行う
Github に関連するファイルなので、 対象のプロジェクトに `.github/renovate.json` のように Renovate の設定ファイルを作ってあげます。

設定は今回は以下のようにしていますが、他にも様々な設定ができるため、詳細は[公式](https://docs.renovatebot.com/configuration-options/)を参照してください。
（実際には、 `packageRules` の設定は「例」以外にも色々やっていますが、とりあえず一つだけ載せています。）

#### `renovate.json` の設定例
- [Renovate が用意しているプリセット設定](https://docs.renovatebot.com/presets-config/)を使用
- [merge-confidence を使ってプルリクを見やすくする](https://docs.renovatebot.com/merge-confidence/)
  - ※Github Apps の場合はデフォで入っているが、Github Actions の場合はデフォルトでこれが入っていないので追加する必要あり。
- プリセットのうち、以下を除外する
  - 1時間あたりのプルリク上限を2とする
  - プルリクの件数が10件以内に収まるようにプルリクを作る
- aws-sdk は頻度が高すぎるので「月の最初の土曜日」のみ更新
- 待機期間設定(ライブラリが更新されてからX日後はマージせずに待機期間とするという設定)
  - メジャーバージョンアップ：更新7日後
  - マイナーバージョンアップ：更新3日後
  - パッチ：更新2日後

なお、待機期間を設定すると、以下のようにプルリクで待機時間が経過しているかどうかをチェックしてくれます。

![check-before-merge.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877519/9c7c82ee-4a46-02a1-8c0b-f57b13fafc38.jpeg)


この状態での設定ファイルは以下のようになります。

```json:.github/renovate.json
{
  "extends": ["config:base","github>whitesource/merge-confidence:beta"],
  "ignorePresets": [":prHourlyLimit2", ":prConcurrentLimit10"],
  "packageRules": [
    {
      "groupName": "aws-sdk",
      "description": ["frequently updated package schedule"],
      "matchPackageNames": ["aws-sdk"],
      "schedule": ["on Saturday on the 1st through 7th day of the month"]
    },
  ],
  "major": {
    "stabilityDays": 7
  },
  "minor": {
    "stabilityDays": 3
  },
  "patch": {
    "stabilityDays": 2
  }
}

```

### Renovate を動かすための bot 用 Github Apps を作る
[Renovate の Github Actions の Readme](https://github.com/renovatebot/github-action#github-action-renovate) にも記載の通り、実行時に Token を渡す必要があります。
Token の発行は、 Personal Access Token (PAT) でも Github Apps でもどちらでもできます。

ただ、権限の調整が細かくできる Github Apps のほうが望ましいので、 Renovate を動かすための bot 用 Github Apps を作ります。

GitHub Apps を使って Github Actions を動かす方法は [GitHub Apps + GitHub Actionsで必要なアクセス権限のみ付与した一時的なアクセストークンを発行する](https://dev.classmethod.jp/articles/getting-an-access-token-with-only-the-necessary-permissions-on-github-appsgithub-actions/#toc-3) を参考にしました。
こちらの手順で Github App を作成してください。

#### 作成した Github Apps に権限を設定する

作成した Github App の Permissions & events で [Renovate に必要な権限](https://docs.renovatebot.com/security-and-permissions/)を付与します。


### リポジトリに secrets と variables を設定する

secrets の方は前述の記事で設定しているので、 [Github の公式ドキュメント](https://docs.github.com/ja/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository)を参考に variables に設定します。

各変数に入れる値は、 [Renovate の公式ドキュメント](https://docs.renovatebot.com/modules/platform/github/#running-as-a-github-app)を参考にしつつ以下の例のように設定しました。

| 変数名 | 値(例) |
|-|-|
| RENOVATE_USERNAME | renovate[bot] |
| RENOVATE_GIT_AUTHOR | 123456+renovate[bot]@users.noreply.github.enterprise.com |
| RENOVATE_REPOSITORIES | ['hoge/my-repository'] |

`RENOVATE_GIT_AUTHOR` の値は、
`${Github Apps の id}+${RENOVATE_USERNAME}@users.noreply.github.enterprise.com` です。

### Gtihub Actions の workflow を作る

対象のプロジェクトに `.github/workflows/renovate.yaml` を追加します。

設定内容は、 [Renovate の Github Actions の Readme](https://github.com/renovatebot/github-action#example-with-github-app) を参考にします。

大まかなステップとしては以下の通りです。
- Token の取得
- ブランチへのチェックアウト
- Renovate の 実行


Token の取得については、[先程の記事](https://dev.classmethod.jp/articles/getting-an-access-token-with-only-the-necessary-permissions-on-github-appsgithub-actions/#toc-7)の `.github/workflows/getAccessToken.yml` に記載の `Generate token` のステップほぼそのままです。


Github Actions の workflow を定義した yaml ファイルは以下のようになります。

```yaml:.github/workflows/renovate.yaml
name: Renovate
on: workflow_dispatch
jobs:
  renovate:
    runs-on: ubuntu-latest
    steps:
      - name: Get token
        id: get_token
        uses: tibdex/github-app-token@v1
        with:
          private_key: ${{ secrets.PRIVATE_KEY }}
          app_id: ${{ secrets.APP_ID }}

      - name: Checkout
        uses: actions/checkout@v3.3.0

      - name: Self-hosted Renovate
        uses: renovatebot/github-action@v34.84.2
        with:
          configurationFile: .github/renovate.json
          token: 'x-access-token:${{ steps.get_token.outputs.token }}'
        env:
          RENOVATE_USERNAME: ${{ vars.RENOVATE_USERNAME }}
          RENOVATE_GIT_AUTHOR: ${{ vars.RENOVATE_GIT_AUTHOR }}
          RENOVATE_REPOSITORIES: ${{ vars.RENOVATE_REPOSITORIES }}
```

### Actions permissions の設定 
Github の対象のプロジェクト > Settings > Actions > General で以下のように設定してください。
- `Allow enterprise, and select non-enterprise, actions and reusable workflows` を選択
- `Allow actions created by GitHub` にチェック
- `Allow specified actions and reusable workflows` に今回の workflow で使うものを入力

今回の `renovate.yaml` の場合は以下の様に設定しています。

![actions-permissions.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/877519/418f087c-891b-063d-4f53-8594ec214cb4.jpeg)


### 動作確認
修正内容を develop ブランチにマージしたら、 対象プロジェクトの Actions タブから Workflow を実行します。

### 定期実行
手動ではなく、定期的に実行したいケースがほとんどだと思います。

`renovate.yaml` の `on: workflow_dispatch` の部分を以下のように修正してください。

以下の例は「毎週土曜日9時に実行」です。

```
on:
  schedule:
    - cron: '0 9 ? * 6'
```


## 最後に

Renovate は Github Apps だと非常に簡単に導入できますが、 Github Actions でも思ったより力をかけずに導入できました。
他の人がホストしているサービスを使うことが難しい場合に、こちらの記事がお役にたちますように。

Github Actions に慣れていないため、この部分微妙じゃない？みたいなところがあればご意見いただけると嬉しいです。

ここまで読んでくださってありがとうございました。


## 参考リンク一覧
- [Renovate 公式ドキュメント](https://docs.renovatebot.com/)
- [Renovate Github Apps](https://github.com/apps/renovate)
- [Renovate の Github Actions](https://github.com/renovatebot/github-action)
- [GitHub Apps + GitHub Actionsで必要なアクセス権限のみ付与した一時的なアクセストークンを発行する](https://dev.classmethod.jp/articles/getting-an-access-token-with-only-the-necessary-permissions-on-github-appsgithub-actions)
-  [Github の公式ドキュメント variables の設定](https://docs.github.com/ja/actions/learn-github-actions/variables#creating-configuration-variables-for-a-repository)