Skip to content

Fix eew header

Fix eew header #267

Workflow file for this run

# 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'