blog.euxn.me

GitHub Actions 内で他の repository に push する

2024-02-17 Sat.

追記: よく考えると簡単にできたので大幅に書き換え。元の趣旨である別 repository の workflow の発火は GitHub Actions 内で他の repository の workflow を発火する に移植。


GitHub Actions 内で他の repository に push しようとした際、素朴に行うと以下のようなエラーが発生する。

1remote: Permission to <owner>/<repo>.git denied to github-actions[bot].
2fatal: unable to access 'https://github.com/<owner>/<repo>/': The requested URL returned error: 403

これは Settings > Actions > General > Workflow permissionsRead and write permissions に変更することでは解消しない。 おそらくこの設定は同一 repository 内での write についてのことだからであろう。

これを解決するために、push 先 repository に対する write 権限を持つ一時的な token を発行し push するために、以下を行う。

安全な Token の取り回しのために GitHub Apps を作成する

今回のような処理自体は Personal Access Token を使用することでもできるが、 Personal Access Token を使用することは推奨されない。 その理由も含め、具体的な設定手順は以下の記事を参考にする。

GitHub Apps トークン解体新書:GitHub Actions から PAT を駆逐する技術

この際 App に付与する権限と理由は以下の通りである。

  • Contents: Read and write ... workflow を発火された repository で自身に push するため
  • Workflows: Read and write ... workflow を発火された repository の自身への push で workflow ファイルへの変更を許可するため

これらの権限設定で GitHub Apps のセットアップ > 4. SecretsにApp IDと秘密鍵を登録する までの手順を実施する。 以降については、次項で説明する。 また、作成した App の repository スコープ(インストール先)は push 対象のみでよい。

別 repository に push する workflow を定義する

workflow 定義は以下の通りになる。

1name: trigger-mirror
2on:
3 push:
4 branches:
5 - main
6 workflow_dispatch:
7
8jobs:
9 trigger-mirror:
10 if: github.repository == '<owner>/<repo>'
11 runs-on: ubuntu-latest
12 steps:
13 - uses: actions/create-github-app-token@v1
14 id: app-token
15 with:
16 app_id: ${{ vars.APP_ID }}
17 private_key: ${{ secrets.PRIVATE_KEY }}
18 repositories: <target-repo>
19 - uses: actions/checkout@v4
20 with:
21 token: ${{ steps.app-token.outputs.token }}
22 - run: |
23 git remote add mirror https://github.com/<owner>/<target-repo>.git
24 git push mirror -f

今回のような mirroring のケースでは、双方が同じソースコードとなる。つまり双方に同一の workflow が存在することとなる。 そのため、push 先で再度 workflow が発火し無限ループとなることを防ぐため、 if: github.repository == '<owner>/<repo>' のガード処理を行う。

前述の記事ではサードパーティの tibdex/github-app-token が紹介されているが、現在では GitHub 公式の actions/create-github-app-token が利用できるため、こちらを採用している。

上記の手順で App から発行された token を使用するが、 - uses: actions/checkout の段階で指定することに注意してほしい。.git/config を覗いてみると、 checkout の時点で credentials が設定されていることが確認できる。

最後に

なぜこんなことをしたかったかというと、 Cloudflare Pages では 1 repository 1 環境だからである。本件についても別途記事を書く。

Other Works
2024-12-01 Sun.
OpenAPI Spec を出力できる DSL、TypeSpec の実践例
- ドワンゴ教育サービス開発者ブログ

2024-11-16 Sat.
型付き API リクエストを実現するいくつかの手法とその選択
- TSKaigi Kansai 2024

2024-09-10 Tue.
corepack が標準同梱じゃなくなる未来、 mise でパッケージマネージャを管理する
- Zenn

2024-09-10 Tue.
言語環境の管理は *env や *vm を超えて、 mise へ
- Zenn

2024-06-28 Fri.
TypeSpec を使い倒してる
- Kyoto.js 22

2024-05-11 Sat.
Powerfully Typed TypeScript
- TSKaigi 2024

2024-05-10 Fri.
pnpm の node_modules を探検して理解しよう
- ドワンゴ教育サービス開発者ブログ

2024-03-17 Sun.
neverthrow で局所的に Result 型を使い、 try-catch より安全に記述する
- Zenn

2023-12-20 Wed.
レガシーブラウザ向けのビルドオプションを剪定する
- ドワンゴ教育サービス開発者ブログ

2023-05-26 Fri.
Next.js で dynamic import を使い Client だけで動かす Component を実現する
- Zenn

2023-05-02 Tue.
Node.js でファイル名から拡張子を取り除く/取り出すために path.parse を使う
- Zenn

2023-02-27 Mon.
WSL2 で外部からアクセス可能にするために bridge mode を有効にする
- Zenn

2023-01-26 Thu.
init.vim & dein から init.lua & lazy.nvim へ、シンプル設定で移行した
- Zenn

2023-01-13 Fri.
kindle の本をブクログ形式の csv でエクスポートする@2023初春
- Zenn

2023-01-10 Tue.
自宅サーバの移設に際して docker から nerdctl に移行した
- Zenn

2023-01-10 Tue.
自宅サーバを rootless に移行した際のトラブル対応
- Zenn

2021-11-11 Thu.
並列実行した Promise で throw されても全てハンドルしたいときの方法(allSettled, finally, etc...)
- Zenn