diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5b4fd87..e13643d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,6 +28,7 @@ jobs: shellcheck tests/setup-opencode.sh shellcheck tests/run-opencode.sh shellcheck tests/github-run-opencode.sh + shellcheck tests/review-action.sh shellcheck tests/test.sh shellcheck tests/fixtures/fake-installer.sh @@ -72,6 +73,16 @@ jobs: github-token: smoke-gh-token zhipu-api-key: smoke-zhipu-token + - name: Run review convenience action + uses: ./review + with: + install-url: http://127.0.0.1:8765/fake-installer.sh + cache: false + install-attempts: 1 + attempts: 1 + github-token: smoke-gh-token + zhipu-api-key: smoke-zhipu-token + - name: Stop fake installer server if: always() run: | diff --git a/README.md b/README.md index 7e2df4a..d1227ef 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ This repository is licensed under Apache 2.0. ## What it includes +- `review`: opinionated PR review wrapper with built-in prompt and model defaults - `github-run-opencode`: one-step wrapper for the common `opencode github run` workflow - `setup-opencode`: installs OpenCode, restores a dedicated cache, and exports the binary path - `run-opencode`: runs `opencode` with optional retry logic for flaky GitHub network failures @@ -37,6 +38,14 @@ Use this when you want the shortest consumer workflow for `opencode github run`. `github-run-opencode` also accepts the setup-related inputs from `setup-opencode`, such as `cache`, `cache-key`, `install-attempts`, `install-url`, and `allow-preinstalled`. +## review + +Use this when you want the simplest PR review setup. + +- built-in `prompt` review template (same as `github-run-opencode`) +- built-in `model` default: `zhipuai-coding-plan/glm-5` +- still allows overriding any input when needed + ## setup-opencode ### Inputs @@ -85,6 +94,7 @@ In the common same-job case, `setup-opencode` already exports `opencode` to `PAT Public consumers should reference the subdirectory action path: ```yaml +uses: Svtter/opencode-actions/review@v1 uses: Svtter/opencode-actions/github-run-opencode@v1 uses: Svtter/opencode-actions/setup-opencode@v1 uses: Svtter/opencode-actions/run-opencode@v1 @@ -92,11 +102,8 @@ uses: Svtter/opencode-actions/run-opencode@v1 ```yaml - name: Run OpenCode review - uses: Svtter/opencode-actions/github-run-opencode@v1 + uses: Svtter/opencode-actions/review@v1 with: - model: zhipuai-coding-plan/glm-5.1 - prompt: | - Review this pull request (read-only mode, DO NOT modify any code): github-token: ${{ secrets.GITHUB_TOKEN }} zhipu-api-key: ${{ secrets.ZHIPU_API_KEY }} opencode-go-api-key: ${{ secrets.OPENCODE_GO_API_KEY }} @@ -122,7 +129,7 @@ This repository includes a CI workflow that: - runs `shellcheck` on every bundled shell script - runs the local shell-based regression suite -- smoke-tests all three actions through `uses: ./setup-opencode`, `uses: ./run-opencode`, and `uses: ./github-run-opencode` +- smoke-tests all four actions through `uses: ./setup-opencode`, `uses: ./run-opencode`, `uses: ./github-run-opencode`, and `uses: ./review` ## Release Policy @@ -137,7 +144,7 @@ This repository includes a CI workflow that: 2. Verify `CI` passes on `main`. 3. Create a GitHub release with a semver tag such as `v1.0.0`. 4. Confirm the `Update Major Tag` workflow moved `v1` to that release. -5. Use `owner/repo/github-run-opencode@v1` for the shortest path, or `owner/repo/setup-opencode@v1` plus `owner/repo/run-opencode@v1` for more control. +5. Use `owner/repo/review@v1` for the simplest review setup, `owner/repo/github-run-opencode@v1` for generic `github run`, or `owner/repo/setup-opencode@v1` plus `owner/repo/run-opencode@v1` for more control. The initial release-notes template lives at `docs/releases/v1.0.0.md`. diff --git a/examples/opencode-review.yml b/examples/opencode-review.yml index f36e125..a547018 100644 --- a/examples/opencode-review.yml +++ b/examples/opencode-review.yml @@ -20,21 +20,8 @@ jobs: ref: ${{ github.event.pull_request.head.ref }} - name: Run OpenCode review - uses: Svtter/opencode-actions/github-run-opencode@v1 + uses: Svtter/opencode-actions/review@v1 with: - model: zhipuai-coding-plan/glm-5.1 - prompt: | - Review this pull request (read-only mode, DO NOT modify any code): - - Please check: - - Code quality issues - - Potential bugs or logic errors - - Code style consistency - - Security concerns - - Performance issues - - Suggest improvements - - Please respond in Chinese. DO NOT modify any code, only provide review comments. github-token: ${{ secrets.GITHUB_TOKEN }} zhipu-api-key: ${{ secrets.ZHIPU_API_KEY }} opencode-go-api-key: ${{ secrets.OPENCODE_GO_API_KEY }} diff --git a/review/action.yml b/review/action.yml new file mode 100644 index 0000000..d490125 --- /dev/null +++ b/review/action.yml @@ -0,0 +1,175 @@ +name: OpenCode Review +description: Opinionated review wrapper with built-in defaults for `opencode github run`. + +inputs: + install-url: + description: Installer URL used to bootstrap OpenCode. + required: false + default: https://opencode.ai/install + install-dir: + description: Directory where the opencode binary should be installed. + required: false + default: "" + xdg-cache-home: + description: Dedicated XDG cache directory for OpenCode. + required: false + default: "" + cache: + description: Cache the install and XDG cache directories with actions/cache. + required: false + default: "true" + cache-key: + description: Cache key suffix used to invalidate installer-based caches. + required: false + default: v1 + install-attempts: + description: Number of installer retry attempts. + required: false + default: "3" + allow-preinstalled: + description: Reuse an existing opencode found on PATH instead of forcing installer bootstrap. + required: false + default: "false" + working-directory: + description: Optional working directory before running opencode. + required: false + default: "" + attempts: + description: Total number of attempts before failing. + required: false + default: "3" + retry-profile: + description: Built-in retry profile, defaults to github-network for common GitHub usage. + required: false + default: github-network + retry-on-regex: + description: Retry only when stderr or stdout matches this regex. + required: false + default: "" + retry-delay-seconds: + description: Base delay between retries in seconds. + required: false + default: "15" + model: + description: Value exported as MODEL before running `opencode github run`. + required: false + default: zhipuai-coding-plan/glm-5 + prompt: + description: Value exported as PROMPT before running `opencode github run`. + required: false + default: | + Review this pull request (read-only mode, DO NOT modify any code): + + Please check: + - Code quality issues + - Potential bugs or logic errors + - Code style consistency + - Security concerns + - Performance issues + - Suggest improvements + + Please respond in Chinese. DO NOT modify any code, only provide review comments. + The first line of your response must be exactly one of: + - 可合并 + - 有条件合并 + - 不可合并 + + Decision rules: + - Use "可合并" only when there are no blocking issues. + - Use "有条件合并" when merge is acceptable only after specific issues are fixed. + - Use "不可合并" when there are blocking risks, correctness issues, or major concerns that should stop the merge. + + Output format: + - First line: the decision only + - Then a short summary + - Then "阻塞项" listing required fixes for merge; if none, write "阻塞项:无" + - Then "建议项" listing non-blocking improvements; if none, write "建议项:无" + use-github-token: + description: Value exported as USE_GITHUB_TOKEN before running `opencode github run`. + required: false + default: "true" + github-token: + description: Value exported as GITHUB_TOKEN before running `opencode github run`. + required: false + default: "" + zhipu-api-key: + description: Value exported as ZHIPU_API_KEY before running `opencode github run`. + required: false + default: "" + opencode-go-api-key: + description: Value exported as OPENCODE_GO_API_KEY before running `opencode github run`. + required: false + default: "" + +runs: + using: composite + steps: + - if: ${{ runner.os != 'Linux' }} + shell: bash + run: | + set -euo pipefail + printf 'review currently supports Linux runners only\n' >&2 + exit 1 + + - id: paths + shell: bash + env: + INPUT_INSTALL_DIR: ${{ inputs.install-dir }} + INPUT_XDG_CACHE_HOME: ${{ inputs.xdg-cache-home }} + run: | + set -euo pipefail + install_dir="$INPUT_INSTALL_DIR" + xdg_cache_home="$INPUT_XDG_CACHE_HOME" + + if [[ -z "$install_dir" ]]; then + install_dir="${RUNNER_TOOL_CACHE:-$HOME/.cache}/opencode/bin" + fi + + if [[ -z "$xdg_cache_home" ]]; then + xdg_cache_home="${RUNNER_TOOL_CACHE:-$HOME/.cache}/opencode/cache" + fi + + printf 'install_dir=%s\n' "$install_dir" >>"$GITHUB_OUTPUT" + printf 'xdg_cache_home=%s\n' "$xdg_cache_home" >>"$GITHUB_OUTPUT" + + - id: key + shell: bash + env: + INPUT_INSTALL_URL: ${{ inputs.install-url }} + run: | + set -euo pipefail + install_url_hash="$(printf '%s' "$INPUT_INSTALL_URL" | sha256sum | cut -d' ' -f1)" + printf 'install_url_hash=%s\n' "$install_url_hash" >>"$GITHUB_OUTPUT" + + - id: cache + if: ${{ inputs.cache == 'true' }} + uses: actions/cache@v5 + with: + path: | + ${{ steps.paths.outputs.install_dir }} + ${{ steps.paths.outputs.xdg_cache_home }} + key: review-opencode-${{ runner.os }}-${{ runner.arch }}-${{ steps.key.outputs.install_url_hash }}-${{ inputs.cache-key }} + + - shell: bash + env: + OPENCODE_INSTALL_DIR: ${{ steps.paths.outputs.install_dir }} + XDG_CACHE_HOME: ${{ steps.paths.outputs.xdg_cache_home }} + OPENCODE_INSTALL_URL: ${{ inputs.install-url }} + OPENCODE_INSTALL_ATTEMPTS: ${{ inputs.install-attempts }} + OPENCODE_ALLOW_PREINSTALLED: ${{ inputs.allow-preinstalled }} + run: ${{ github.action_path }}/../setup-opencode/install-opencode.sh + + - shell: bash + env: + GITHUB_RUN_OPENCODE_WORKING_DIRECTORY: ${{ inputs.working-directory }} + GITHUB_RUN_OPENCODE_ATTEMPTS: ${{ inputs.attempts }} + GITHUB_RUN_OPENCODE_RETRY_PROFILE: ${{ inputs.retry-profile }} + GITHUB_RUN_OPENCODE_RETRY_ON_REGEX: ${{ inputs.retry-on-regex }} + GITHUB_RUN_OPENCODE_RETRY_DELAY_SECONDS: ${{ inputs.retry-delay-seconds }} + GITHUB_RUN_OPENCODE_MODEL: ${{ inputs.model }} + GITHUB_RUN_OPENCODE_PROMPT: ${{ inputs.prompt }} + GITHUB_RUN_OPENCODE_USE_GITHUB_TOKEN: ${{ inputs.use-github-token }} + GITHUB_RUN_OPENCODE_GITHUB_TOKEN: ${{ inputs.github-token }} + GITHUB_RUN_OPENCODE_ZHIPU_API_KEY: ${{ inputs.zhipu-api-key }} + GITHUB_RUN_OPENCODE_OPENCODE_GO_API_KEY: ${{ inputs.opencode-go-api-key }} + run: ${{ github.action_path }}/../github-run-opencode/run-github-opencode.sh diff --git a/tests/review-action.sh b/tests/review-action.sh new file mode 100755 index 0000000..7c74562 --- /dev/null +++ b/tests/review-action.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" + +extract_prompt_default() { + local action_file="$1" + awk ' + /^ prompt:$/ {in_prompt=1; next} + in_prompt && /^ default: \|$/ {in_default=1; next} + in_default { + if ($0 ~ /^ [a-zA-Z0-9_-]+:$/) { + exit + } + sub(/^ /, "") + print + } + ' "$action_file" +} + +github_run_prompt_file="$(mktemp)" +review_prompt_file="$(mktemp)" +trap 'rm -f "$github_run_prompt_file" "$review_prompt_file"' EXIT + +extract_prompt_default "$repo_root/github-run-opencode/action.yml" >"$github_run_prompt_file" +extract_prompt_default "$repo_root/review/action.yml" >"$review_prompt_file" + +if ! diff -u "$github_run_prompt_file" "$review_prompt_file" >/dev/null; then + printf 'review/action.yml prompt default must match github-run-opencode/action.yml\n' >&2 + exit 1 +fi + +if ! grep -Eq '^ default: zhipuai-coding-plan/glm-5$' "$repo_root/review/action.yml"; then + printf 'review/action.yml model default is not zhipuai-coding-plan/glm-5\n' >&2 + exit 1 +fi + +printf 'review action metadata test passed\n' diff --git a/tests/test.sh b/tests/test.sh index d917bc2..470a5e9 100755 --- a/tests/test.sh +++ b/tests/test.sh @@ -5,3 +5,4 @@ set -euo pipefail bash tests/setup-opencode.sh bash tests/run-opencode.sh bash tests/github-run-opencode.sh +bash tests/review-action.sh