banner
Birdgg

Birdgg

Keep it simple, stupid!
bilibili
github
twitter
telegram
email

xLog GitHub Actions の権限問題の解決を記録する

image

更新:リポジトリ設定 - アクション - 読み書き権限を有効にする必要があります。そうしないと、権限がありません。@innei-4525 大佬のリマインダーに感謝します。

水曜日に xLog に PR を提出した際、1 つのチェックが通らないことに気付きました。エラーメッセージを開いてみると、Next.js バンドル分析ワークフローがコメントの作成に失敗したことがわかりました。

Run peter-evans/create-or-update-comment@v2
Error: Resource not accessible by integration
Error: See this action's readme for details about this error

夜に Innei 大佬がまだこの問題を解決しているのを見て、チャンスが来たことを知りました(逃

peter-evans/create-or-update-comment の README と issue を調べた結果、pull_request イベントトリガーの下で、サードパーティのフォークリポジトリが PR を提出する際に書き込み権限が不足しているため、PR コメントを作成できないことがわかりました。README では、この問題を解決するために pull_request_target をイベントトリガーとして使用することを推奨しています。

注意:公開リポジトリでは、このアクションはフォークによってトリガーされた pull_request ワークフローでは機能しません。試みると、リソースが統合によってアクセスできないというエラーが発生します。これは、GitHub Actions によって設定されたトークン制限によるものです。プライベートリポジトリは、フォークからのワークフローを制限なしで実行できるように構成できます。詳細については、こちらを参照してください。あるいは、PR にコメントするために pull_request_target イベントを使用してください。

そのため、GitHub の公式ドキュメントで pull_request_target の説明を確認したところ、警告があることに気付きました。

警告: pull_request_target イベントによってトリガーされるワークフローでは、permissions キーが指定されていない限り、GITHUB_TOKEN に読み書きリポジトリ権限が付与され、ワークフローはフォークからトリガーされてもシークレットにアクセスできます。ワークフローは PR のベースのコンテキストで実行されますが、このイベントで PR から信頼できないコードをチェックアウト、ビルド、または実行しないようにする必要があります。さらに、キャッシュはベースブランチと同じスコープを共有します。キャッシュの汚染を防ぐために、キャッシュの内容が変更される可能性がある場合はキャッシュを保存しないでください。詳細については、GitHub Security Lab ウェブサイトの「GitHub Actions とワークフローを安全に保つ: pwn リクエストを防ぐ」を参照してください。

大まかな意味は、pull_request_target がフォークリポジトリからの PR 提出に対してターゲットリポジトリへの読み書き権限を提供するため、悪意のある PR がセキュリティリスクを引き起こす可能性があるため、使用時には適用シーンを慎重に選択する必要があるということです。警告に記載されている記事 Keeping your GitHub Actions and workflows secure: Preventing pwn requests では、この問題について詳しく説明されており、PR コメントを更新しつつ pull_request_target を使用しない解決策が提供されています。この解決策では、全体のワークフローを 2 つの部分に分割します。まず、pull_request を使用して不安全なコードを含む可能性のあるワークフローをトリガーし、必要な結果(テスト結果やカバレッジなど)をアップロードします。次に、書き込み権限を持つ workflow_on でこれらの結果をダウンロードし、PR を更新します。

この解決策に基づいて、Next.js バンドル分析ワークフローを 2 つのファイルに分割しました。

nextjs_bundle_analysis.yml

name: "Next.js バンドル分析"

on:
  pull_request:

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      # ビルドプロセス

      - name: 分析結果のアップロード
        if: success() && github.event.number
        uses: actions/upload-artifact@v2
        with:
          name: analysis_comment
          path: .next/analyze/__bundle_analysis_comment.txt

      - name: PR 番号の保存
        if: ${{ always() }}
        run: echo ${{ github.event.number }} > ./pr-id.txt

      - name: PR 番号のアップロード
        if: ${{ always() }}
        uses: actions/upload-artifact@v2
        with:
          name: pr
          path: ./pr-id.txt
      

comment-pr.yml

name: PR にコメントする

# 読み書きリポジトリトークン
# シークレットへのアクセス
on:
  workflow_run:
    workflows: ["Next.js バンドル分析"]
    types:
      - completed

jobs:
  upload:
    runs-on: ubuntu-latest
    if: >
      github.event.workflow_run.event == 'pull_request' &&
      github.event.workflow_run.conclusion == 'success'
    steps:
      - name: PR アーティファクトのダウンロード
        uses: dawidd6/action-download-artifact@v2
        with:
          workflow: ${{ github.event.workflow_run.workflow_id }}
          name: pr

      - name: PR ID の保存
        id: pr
        run: echo "::set-output name=id::$(<pr-id.txt)"

      - name: 分析コメントのダウンロード
        uses: dawidd6/action-download-artifact@v2
        with:
          workflow: ${{ github.event.workflow_run.workflow_id }}
          name: analysis_comment
          path: .next/analyze

      - name: コメント本文の取得
        id: get-comment-body
        if: success() && steps.pr.outputs.id
        run: |
          echo "body<<EOF" >> $GITHUB_OUTPUT
          echo "$(cat .next/analyze/__bundle_analysis_comment.txt)" >> $GITHUB_OUTPUT
          echo EOF >> $GITHUB_OUTPUT

      - name: コメントの検索
        uses: peter-evans/find-comment@v2
        if: success() && steps.pr.outputs.id
        id: fc
        with:
          issue-number: ${{ steps.pr.outputs.id }}
          body-includes: "<!-- __NEXTJS_BUNDLE -->"

      - name: コメントの作成
        uses: peter-evans/create-or-update-comment@v2
        if: success() && steps.pr.outputs.id && steps.fc.outputs.comment-id == 0
        with:
          issue-number: ${{ steps.pr.outputs.id }}
          body: ${{ steps.get-comment-body.outputs.body }}

      - name: コメントの更新
        uses: peter-evans/create-or-update-comment@v2
        if: success() && steps.pr.outputs.id && steps.fc.outputs.comment-id != 0
        with:
          issue-number: ${{ steps.pr.outputs.id }}
          body: ${{ steps.get-comment-body.outputs.body }}
          comment-id: ${{ steps.fc.outputs.comment-id }}
          edit-mode: replace

これで問題が解決しました。

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。