GitHub ActionsでOpenCodeに記事PRを自動レビューさせる

PR #24 で OpenCode を動かしたとき、レビューは始まりませんでした。Actions のコメントに残ったのは、次の 1 行です。

fatal: could not read Username for 'https://github.com': No such device or address

checkout 自体は成功していました。失敗したのは、その後に OpenCode が実行したgit fetch originです。actions/checkoutに認証情報を残し、runner の token をGITHUB_TOKENTOKENへ渡す必要がありました。

この修正を記事へ同期したのが PR #26 です。その後、PR #27 で hibanas-net #15 の品質バーを自動レビューの prompt へ加えました。ここでは、2026 年 8 月 18 日時点の main にある 2 本の workflow を、そのまま使います。

前回から今回への差分

前回のGit管理ブログへ安全に書き込むcronでは、記事を content branch へ push するところまでを扱いました。

前回完了時今回完了後
記事とOGをcontent branchへpushします記事PRを開くとOpenCodeが差分を読みます
品質ゲートはローカルコマンドで実行しますhibanas-net #15の項目もPR上で検査します
GitHub側の失敗は人がActionsを開いて調べます認証失敗と権限不足の切り分け方が決まっています

OpenRouter の secret を登録済みなら、「main の workflow を確認する」まで飛ばせます。

なぜTOKENとpersist-credentialsが要るのか

GitHub Actions は job ごとにGITHUB_TOKENを発行します。ただし、token が存在するだけではgit fetchに使われません。

actions/checkoutpersist-credentials: trueは、checkout 後の Git コマンドでも認証情報を使えるようにします。OpenCode Action にはGITHUB_TOKENTOKENの両方を渡します。今回使った Action が GitHub API と Git 操作で参照する変数名を揃えるためです。

自動レビュー側のcontentsreadのままです。コメント起動側にはcontents: writeがあります。この 2 つを混ぜると、レビューだけの job にもファイル変更権限を渡してしまいます。

用語表

用語hibanas-netでの役割
OpenCodeGitHub-hosted runnerでPR差分を読むエージェントです
OpenRouterdeepseek-v4-flash-0731へ接続するproviderです
GITHUB_TOKENGitHubがjobごとに発行するrepository用tokenです
TOKENOpenCode Actionへ同じrunner tokenを渡す環境変数です
persist-credentialscheckout後のGitコマンドへ認証情報を残す設定です
synchronizePRのhead branchへ追加commitをpushしたときのeventです

2本のworkflowを分ける

コメントに /oc または /opencode
  └─ opencode.yml
       └─ 明示された作業を実行できます

記事またはOGを変更したPR
  └─ opencode-pr-review.yml
       ├─ PR差分だけを読みます
       ├─ #15とdocs/guidelines.mdを確認します
       └─ コメントだけを投稿します

画面の説明用に生成画像は使っていません。実スクリーンショットを取れない箇所は、このテキスト図だけにしています。

mainのworkflowを確認する

記憶や過去 PR から YAML を写さず、origin/mainのファイルを読みます。hibanas-net で実行したコマンドは次の 2 つです。

git show origin/main:.github/workflows/opencode.yml
git show origin/main:.github/workflows/opencode-pr-review.yml

コメント起動用のopencode.yml

次のコードブロックは、main の.github/workflows/opencode.ymlと同じ内容です。

name: opencode

on:
  issue_comment:
    types: [created]
  pull_request_review_comment:
    types: [created]

jobs:
  opencode:
    if: |
      contains(github.event.comment.body, '/oc') ||
      contains(github.event.comment.body, '/opencode')
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: write
      pull-requests: write
      issues: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          fetch-depth: 1
          persist-credentials: true

      - name: Run OpenCode
        uses: anomalyco/opencode/github@latest
        env:
          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          model: openrouter/deepseek/deepseek-v4-flash-0731
          use_github_token: true

/oc/opencodeを含むコメントで起動します。contents: writeがあるため、記事 PR を自動で読むだけの job には流用しません。

記事PR用のopencode-pr-review.yml

次のコードブロックも、main の.github/workflows/opencode-pr-review.ymlと同じ内容です。prompt には PR #27 で追加した hibanas-net #15 の品質バーが入っています。

name: opencode-pr-review

on:
  pull_request:
    types: [opened, synchronize, reopened, ready_for_review]
    paths:
      - "src/content/posts/**"
      - "public/images/posts/**"

jobs:
  review:
    runs-on: ubuntu-latest
    permissions:
      id-token: write
      contents: read
      pull-requests: write
      issues: write
    steps:
      - name: Checkout repository
        uses: actions/checkout@v6
        with:
          persist-credentials: true

      - name: Run OpenCode
        uses: anomalyco/opencode/github@latest
        env:
          OPENROUTER_API_KEY: ${{ secrets.OPENROUTER_API_KEY }}
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          TOKEN: ${{ secrets.GITHUB_TOKEN }}
        with:
          model: openrouter/deepseek/deepseek-v4-flash-0731
          use_github_token: true
          prompt: |
            Review only this pull request's diff. Do not review unrelated files.

            If the PR title, description, or changed content is Japanese, write the review in Japanese. Otherwise match the language of the PR.

            Post one concise review comment only.
            Do not merge the pull request.
            Do not apply patches, edit files, or commit.
            Do not dump secrets, tokens, or environment values.

            Review posts against hibanas-net issue #15 and docs/guidelines.md. For each applicable post, treat every item below as required:
            - Use consistent です・ます調 (desu/masu).
            - Have full serial hands-on depth, not a short tips article.
            - Include a table showing the delta from the previous installment to this one.
            - Explain Why before How.
            - Include a glossary, a text architecture diagram, runnable commands with honest expected output, clearly skippable sections, a common-errors table, and a primary-source references table.
            - Keep draft: true. Flag changing it to draft: false or removing it unless the PR title or body explicitly says 公開 or publish.
            - Require the OG image to be 16:9 with no article title or other typography baked in.
            - Require procedure images to be real screenshots from reachable systems; generated procedure screenshots are prohibited. A text diagram is allowed when a real screen is unavailable.

            Label any missing required quality-bar item as "required". Label subjective prose or style preferences as "nit".
            Never return LGTM while any required item is missing.
            A successful OpenCode review is not permission to publish the article.

pathsは記事と OG だけに反応します。synchronizeがあるため、指摘を直して同じ PR へ push すると再レビューが走ります。OpenCode が成功しても、merge や公開の許可にはなりません。

3本のPRで実動を確認する

main へ入った結果を、GitHub CLI で読み直します。この確認も hibanas-net で実行しました。

~/.local/bin/gh pr view 24 --repo dicekanbe/hibanas-net --json number,state,headRefName --jq '"#\(.number) \(.state) \(.headRefName)"'
~/.local/bin/gh pr view 26 --repo dicekanbe/hibanas-net --json number,state,headRefName --jq '"#\(.number) \(.state) \(.headRefName)"'
~/.local/bin/gh pr view 27 --repo dicekanbe/hibanas-net --json number,state,headRefName --jq '"#\(.number) \(.state) \(.headRefName)"'

実行結果は次のとおりです。

#24 MERGED content/2026-08-18-ai-agent-draft-approval-publish-gates
#26 MERGED content/2026-08-18-sync-opencode-workflow-article
#27 MERGED ci/opencode-review-issue-15-quality-bar

PR #24 では最初のgit fetch originが認証で失敗しました。PR #26 では、persist-credentials: trueGITHUB_TOKENTOKENを含む本番 YAML と記事を一致させました。PR #27 では、短い記事へ安易に LGTM を返さないよう、#15 の必須項目を prompt へ入れました。

よくあるエラー

症状実際に確認する場所対応
could not read Usernameで止まりますcheckout後のgit fetch originですpersist-credentials: trueTOKENを本番YAMLどおりに揃えます
OpenRouterの認証で止まりますRun OpenCode stepですOPENROUTER_API_KEYのsecret名を確認します。値はログへ出しません
PRを開いても起動しませんPRのFiles changedです変更がsrc/content/posts/**public/images/posts/**にあるか確認します
コメントを投稿できませんjobのpermissionsですpull-requests: writeissues: writeを確認します
修正push後に動きませんpull_request.typesですsynchronizeを残します
品質項目が抜けても通りますpromptですPR #27後の#15項目とNever return LGTMを残します

運用で残した境界

第三者 Action のanomalyco/opencode/github@latestは、参照先が将来変わります。固定運用へ進めるなら、動作確認した commit SHA へ切り替える余地があります。ただし、この記事では main に存在しない設定を完成形として書き足していません。

自動レビューjob のcontents: readも広げません。修正を頼む場合はコメント起動用 workflow へ明示します。レビューjob は、差分を読み、1 件のコメントを返すところで止めます。

出典

一次情報確認した内容
OpenCode公式ドキュメント: GitHubGitHub Actions、use_github_token、custom prompt
GitHub Docs: GITHUB_TOKENで認証するjobごとのtokenとpermissions
hibanas-net PR #24git fetch originで起きた認証失敗
hibanas-net PR #26記事と本番workflowの同期
hibanas-net PR #27#15品質バーを含むprompt
hibanas-netのopencode.ymlコメント起動workflowの本番内容
hibanas-netのopencode-pr-review.yml記事PRレビューworkflowの本番内容
この記事をシェア