Fix eew header #267
Workflow file for this run
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # OpenCodeReview - GitHub Actions PR Auto-Review Demo | |
| # | |
| # Demonstrates invoking the reusable action for both automatic PR review | |
| # (pull_request_target: opened/synchronize/reopened) and on-demand re-review | |
| # via comments starting with '/open-code-review' or '@open-code-review'. | |
| # | |
| # Required org/repo secrets (Settings -> Secrets and variables -> Actions): | |
| # OCR_LLM_URL LLM API endpoint | |
| # OCR_LLM_AUTH_TOKEN LLM auth token (mapped to OCR_LLM_TOKEN) | |
| # OCR_LLM_MODEL model name | |
| # OCR_LLM_USE_ANTHROPIC 'true' for Anthropic, 'false' for OpenAI-compatible | |
| # | |
| # For the full list of action inputs/outputs and the four comment-posting modes | |
| # (sticky / incremental), see action.yml at the repo root. | |
| name: OpenCodeReview PR Review | |
| # Conditional concurrency group. | |
| # | |
| # GitHub Actions evaluates concurrency BEFORE job-level if-conditions. With a | |
| # flat group (ocr-<pr_number>), every comment on the PR — even an unrelated | |
| # conversation reply that will be skipped — enters the same group and, because | |
| # cancel-in-progress is true, cancels any in-progress review. The result: a | |
| # single normal comment kills a running review, and you see "two runs, one | |
| # cancelled" in the Actions tab. | |
| # | |
| # Fix: matching events (PR events + /open-code-review comments) share a per-PR | |
| # group so a new review cancels any stale one for the same PR. Non-matching | |
| # comments land in a unique noop-<run_id> group that can never collide with a | |
| # real review, so they are skipped instantly without disrupting anything. | |
| concurrency: | |
| group: >- | |
| ${{ | |
| ( | |
| github.event_name == 'pull_request_target' | |
| || ( | |
| github.event_name == 'issue_comment' | |
| && github.event.issue.pull_request | |
| && github.event.comment.user.type != 'Bot' | |
| && ( | |
| github.event.comment.author_association == 'MEMBER' | |
| || github.event.comment.author_association == 'OWNER' | |
| || github.event.comment.author_association == 'COLLABORATOR' | |
| ) | |
| && ( | |
| startsWith(github.event.comment.body, '/open-code-review') | |
| || startsWith(github.event.comment.body, '@open-code-review') | |
| ) | |
| ) | |
| ) | |
| && format('ocr-{0}', github.event.pull_request.number || github.event.issue.number) | |
| || format('noop-{0}', github.run_id) | |
| }} | |
| cancel-in-progress: true | |
| on: | |
| # Use pull_request_target instead of pull_request so that secrets are | |
| # available even for PRs from forks. This is safe because the reusable | |
| # action only reads the diff and does not execute any code from the PR. | |
| pull_request_target: | |
| types: [opened, synchronize, reopened] | |
| issue_comment: | |
| types: [created] | |
| permissions: | |
| contents: read | |
| pull-requests: write | |
| jobs: | |
| code-review: | |
| runs-on: ubuntu-latest | |
| # A backstop, not the cap. The review itself is capped at 15 minutes on its | |
| # own step, where a timeout can be swallowed; a job-level timeout cannot be, | |
| # and would fail the check. This only catches something wedging outside the | |
| # review step, which should never happen and should be loud if it does. | |
| timeout-minutes: 20 | |
| # Run on PR events, or on human-authored comments starting with trigger | |
| # keywords. Bot comments are excluded as a safety net: GITHUB_TOKEN already | |
| # suppresses events from bot-posted comments, but a PAT/App token would not. | |
| # issue_comment triggers are further gated on author_association so only | |
| # MEMBER/OWNER/COLLABORATOR users can spend LLM quota via re-review. | |
| if: | | |
| github.event_name == 'pull_request_target' | |
| || ( | |
| github.event_name == 'issue_comment' | |
| && github.event.issue.pull_request | |
| && github.event.comment.user.type != 'Bot' | |
| && ( | |
| github.event.comment.author_association == 'MEMBER' | |
| || github.event.comment.author_association == 'OWNER' | |
| || github.event.comment.author_association == 'COLLABORATOR' | |
| ) | |
| && ( | |
| startsWith(github.event.comment.body, '/open-code-review') | |
| || startsWith(github.event.comment.body, '@open-code-review') | |
| ) | |
| ) | |
| steps: | |
| - name: Get PR context | |
| id: pr-context | |
| if: github.event_name == 'issue_comment' | |
| uses: actions/github-script@v7 | |
| with: | |
| script: | | |
| // For issue_comment events, resolve PR base/head so the action | |
| // can review the right diff (issue_comment has no top-level | |
| // pull_request payload fields). | |
| const prNumber = context.issue.number; | |
| const { data: pullRequest } = await github.rest.pulls.get({ | |
| owner: context.repo.owner, | |
| repo: context.repo.repo, | |
| pull_number: prNumber | |
| }); | |
| core.setOutput('base_ref', pullRequest.base.ref); | |
| core.setOutput('head_sha', pullRequest.head.sha); | |
| # Advisory, and therefore never a reason a pull request cannot merge. | |
| # | |
| # `continue-on-error` is what makes that true. A required check has three | |
| # outcomes and only one of them lets a merge through: a skipped job | |
| # reports Success, but a FAILED one blocks — and this step can fail for | |
| # reasons that have nothing to do with the code under review. The LLM | |
| # endpoint is down, the token expired, the quota ran out, the diff was too | |
| # large, the model returned something unparseable. None of those are a | |
| # statement about the pull request, and none of them should hold it. | |
| # | |
| # `timeout-minutes` here rather than on the job for the same reason: a | |
| # job-level timeout fails the job and there is nothing downstream that can | |
| # swallow it, whereas a step-level one is an error like any other and | |
| # `continue-on-error` absorbs it. 15 minutes is well past how long a review | |
| # of a normal diff takes, so hitting it means something is wedged. | |
| # | |
| # This makes the check green when the review did not happen, which is a | |
| # real cost — so the step below says so out loud. Green and silent would | |
| # be the version of this that goes unnoticed for months. | |
| - name: Run OpenCodeReview | |
| id: review | |
| continue-on-error: true | |
| timeout-minutes: 15 | |
| uses: alibaba/open-code-review@main | |
| with: | |
| llm_url: ${{ secrets.OCR_LLM_URL }} | |
| llm_auth_token: ${{ secrets.OCR_LLM_AUTH_TOKEN }} | |
| llm_model: ${{ secrets.OCR_LLM_MODEL }} | |
| llm_use_anthropic: false | |
| language: 中文 | |
| background: | | |
| 一律使用台灣繁體中文撰寫所有 review 評論與摘要。 | |
| 禁止簡體字、禁止英文為主的評論(程式識別子除外)。 | |
| # For issue_comment triggers, pass the resolved refs; for | |
| # pull_request_target the action resolves them from the event. | |
| base_ref: ${{ steps.pr-context.outputs.base_ref }} | |
| head_sha: ${{ steps.pr-context.outputs.head_sha }} | |
| # `outcome` is the step's real result; `conclusion` is what | |
| # continue-on-error rewrote it to. Reading the first is the only way to | |
| # tell "reviewed and found nothing" from "never reviewed anything", which | |
| # otherwise look identical from outside: one green check either way. | |
| - name: Say so if the review did not run | |
| if: steps.review.outcome != 'success' | |
| run: | | |
| printf '::warning::the code review did not complete (%s). ' \ | |
| "${{ steps.review.outcome }}" | |
| printf 'This check is advisory and stays green on purpose, so nothing ' | |
| printf 'is blocked — but this pull request has not been reviewed. ' | |
| printf 'Comment /open-code-review to try again.\n' |