1
0
mirror of https://github.com/hustcer/deepseek-review.git synced 2026-05-13 05:16:05 +08:00

24 Commits
v1.17 ... v1

Author SHA1 Message Date
hustcer
90c8878923 Bump to v1.20 2026-01-23 19:53:21 +08:00
Justin Ma
231c2d8432 chore: Update Nushell to 0.110.0 (#196) 2026-01-21 07:50:05 +08:00
hustcer
923ee0f999 deps: Upgrade hustcer/setup-nu to v3.22 2025-12-13 22:42:11 +08:00
Justin Ma
32cffba4d1 deps: Upgrade Nu to 0.109.1 (#195) 2025-12-03 22:34:55 +08:00
Justin Ma
0c001b0ee2 refactor: A better from env parser (#194)
* refactor: A better `from env` parser

* refactor: A better `from env` parser
2025-11-29 22:45:55 +08:00
hustcer
edcd90e48b deps: Upgrade actions/checkout@v6 2025-11-26 23:10:18 +08:00
Justin Ma
dfc4c59c1f fix: Fix from env for .env file parsing (#193)
* fix: Fix `from env` for .env file parsing

* fix: Fix `from env` for .env file parsing

* fix: Fix `from env` for .env file parsing
2025-11-26 23:07:41 +08:00
hustcer
92061e6c82 chore: Update README.md 2025-11-22 23:22:03 +08:00
Justin Ma
3c3f0a3c85 deps: Upgrade hustcer/setup-nu to v3.21 (#192) 2025-10-25 11:13:42 +08:00
Justin Ma
7a87f8adc0 chore: Update nutest to main ref (#191) 2025-10-24 23:06:24 +08:00
Justin Ma
d7b2e3a926 deps: Upgrade Nushell version to 0.108.0 (#190) 2025-10-24 22:51:09 +08:00
hustcer
91ae07bb82 deps: Upgrade hustcer/setup-nu to v3.20 2025-08-25 20:03:18 +08:00
hustcer
d830da6937 deps: Upgrade to actions/checkout@v5 2025-08-25 19:48:24 +08:00
hustcer
885b55dbb0 chore: Update minimum required Nushell version to 0.106.1 2025-08-18 21:16:27 +08:00
hustcer
317d3c92da fix: Make config-check use default value for --config flag 2025-08-13 22:14:52 +08:00
hustcer
938790c65b Bump version to v1.19 2025-07-24 20:05:51 +08:00
Justin Ma
a4d125ecba deps: Upgrade Nu to v0.106 (#186) 2025-07-24 20:01:49 +08:00
hustcer
930e0ae68f fix: Fix getting Nu binary path for Nushell 0.106 2025-07-15 20:16:21 +08:00
Justin Ma
d0b2ea125a fix: Fix "variable not found" error (#185) 2025-07-14 15:28:49 +08:00
hustcer
9852113028 Bump version to v1.18 2025-06-11 15:37:14 +08:00
Justin Ma
9ad3373cd5 chore: Upgrade Nu to 0.105 and pin hustcer/setup-nu to v3.19 (#183) 2025-06-11 15:04:04 +08:00
Justin Ma
981ef03409 feat: Set defalut temperature to 0.3 for code review (#181) 2025-04-29 17:09:53 +08:00
Justin Ma
9852118ba7 deps: Upgrade nutest to v1.1.0 (#179)
* deps: Upgrade nutest to v1.1.0

* fix nutest upgrading
2025-04-29 16:36:21 +08:00
Justin Ma
985f205ae5 chore: Refine diff flag descriptions in docs and scripts (#177) 2025-04-18 11:06:46 +08:00
16 changed files with 231 additions and 132 deletions

View File

@@ -37,7 +37,7 @@ jobs:
As a senior Nushell engineer, perform comprehensive script review with focus on:
### 1. Core Requirements:
- Validate Nu 0.90+ compatibility
- Validate Nu 0.100+ compatibility
- Check structured data handling
- Verify pipeline efficiency
- Assess module organization
@@ -55,7 +55,7 @@ jobs:
- Parallel execution opportunities
**Rules:**
- Target Nu 0.90+ features
- Target Nu 0.100+ features
- Highlight data flow vulnerabilities
- Suggest structured data optimizations
- Keep feedback Nu-specific

View File

@@ -15,6 +15,7 @@ on:
branches:
- main
- develop
- feature/test
paths-ignore:
- '**.md'
- 'docs/**'
@@ -41,12 +42,12 @@ jobs:
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Checkout Nutest Repo
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: v1.0.1
ref: main
path: nutest
repository: vyadh/nutest
sparse-checkout: nutest/

View File

@@ -1,6 +1,60 @@
# Changelog
All notable changes to this project will be documented in this file.
## [1.20.0] - 2026-01-23
### Bug Fixes
- Make config-check use default value for --config flag
- Fix `from env` for .env file parsing (#193)
### Miscellaneous Tasks
- Update minimum required Nushell version to 0.110.0
- Update nutest to main ref (#191)
- Update README.md
### Refactor
- A better `from env` parser (#194)
### Deps
- Upgrade to actions/checkout@v5
- Upgrade `hustcer/setup-nu` to v3.20
- Upgrade Nushell version to 0.108.0 (#190)
- Upgrade `hustcer/setup-nu` to v3.21 (#192)
- Upgrade actions/checkout@v6
- Upgrade Nu to 0.109.1 (#195)
- Update Nushell to 0.110.0 (#196)
- Upgrade `hustcer/setup-nu` to v3.22
## [1.19.0] - 2025-07-23
### Bug Fixes
- Fix "variable not found" error (#185)
- Fix getting Nu binary path for Nushell 0.106
### Deps
- Upgrade Nu to v0.106 (#186)
## [1.18.0] - 2025-06-11
### Features
- Set default `temperature` to **0.3** for code review (#181)
### Miscellaneous Tasks
- Refine diff flag descriptions in docs and scripts (#177)
- Upgrade `Nu` to 0.105 and pin [`hustcer/setup-nu`](https://github.com/hustcer/setup-nu) to v3.19 (#183)
### Deps
- Upgrade `nutest` to v1.1.0 (#179)
## [1.17.0] - 2025-04-11
### Bug Fixes

View File

@@ -28,7 +28,7 @@ alias cr := code-review
# Used to handle the path separator issue
DEEPSEEK_REVIEW_PATH := parent_directory(justfile())
NU_DIR := parent_directory(`(which nu).path.0`)
NU_DIR := parent_directory(`$nu.current-exe`)
_query_plugin := if os_family() == 'windows' { 'nu_plugin_query.exe' } else { 'nu_plugin_query' }
# To pass arguments to a dependency, put the dependency

View File

@@ -7,31 +7,31 @@
[中文说明](README.zh-CN.md)
`deepseek-review` also offers seamless integration with DeepSeek models on SiliconCloud. [Sign Up Now](https://cloud.siliconflow.cn/i/rqCdIxzS) to **Claim Your Free 20 Million Tokens** and start exploring its capabilities!
`deepseek-review` offers seamless integration with DeepSeek models on SiliconCloud. [Sign Up Now](https://cloud.siliconflow.cn/i/rqCdIxzS) to **claim your free 20 million tokens** and start exploring its capabilities!
## Features
### GitHub Action
- Automate PR Reviews with DeepSeek via GitHub Action
- Add `skip cr` or `skip review` to PR Title or Body to Disable Code Review in GitHub Actions
- Add `skip cr` or `skip review` to the PR title or body to disable code review in GitHub Actions
- Cross-platform Support: Compatible with GitHub Runners across `macOS`, `Ubuntu`, and `Windows`.
### Local Code Review
- Streaming Output Support for Local Code Review
- Review Remote GitHub PRs Directly from Your Local CLI
- Review Commit Changes with DeepSeek for Any Local Repository by CLI
- Support On-demand Changes Generation via `git show`/`git diff` Command for Further Code Review
- Output Code Review Result to Specified File in Markdown Format
- Cross-platform Compatibility: Designed to function seamlessly across all platforms capable of running [Nushell](https://github.com/nushell/nushell)
- Streaming output support for local code review
- Review remote GitHub PRs directly from your local CLI
- Review commit changes with DeepSeek for any local repository via CLI
- Support on-demand change generation via `git show`/`git diff` commands for further code review
- Output code review results to a specified file in Markdown format
- Cross-platform compatibility: Designed to function seamlessly across all platforms capable of running [Nushell](https://github.com/nushell/nushell)
### Both GH Action & Local
- Support Both DeepSeek's `V3` & `R1` Models
- Fully Customizable: Choose Models, Base URLs, and Prompts
- Supports Self-Hosted DeepSeek Models for Enhanced Flexibility
- Perform Code Reviews for Changes That either Include or Exclude Specific Files
- Support both DeepSeek's `V3` and `R1` models
- Fully customizable: Choose models, base URLs, and prompts
- Support self-hosted DeepSeek models for enhanced flexibility
- Perform code reviews for changes that either include or exclude specific files
## Planned Features
@@ -40,7 +40,7 @@
## Code Review with GitHub Action
### Initiate Code Review When PR was Created
### Initiate Code Review When a PR is Created
Add a GitHub workflow with the following contents:
@@ -82,13 +82,13 @@ jobs:
</details>
When a PR is created, DeepSeek code review will be automatically triggered, and the review results(depend on your prompt) will be posted as comments on the corresponding PR. For example:
When a PR is created, DeepSeek code review will be automatically triggered, and the review results (depending on your prompt) will be posted as comments on the corresponding PR. For example:
- [Example 1](https://github.com/hustcer/deepseek-review/pull/30) with [default prompts](https://github.com/hustcer/deepseek-review/blob/main/action.yaml#L35) & [Run Log](https://github.com/hustcer/deepseek-review/actions/runs/13043609677/job/36390331791#step:2:53).
- [Example 2](https://github.com/hustcer/deepseek-review/pull/68) with [this prompt](https://github.com/hustcer/deepseek-review/blob/eba892d969049caff00b51a31e5c093aeeb536e3/.github/workflows/cr.yml#L32)
### Trigger CR When a Specific Label was Added
### Trigger Code Review When a Specific Label is Added
If you don't want automatic review on PR creation, you can choose to trigger code review by adding a label. For example, create the following workflow:
If you don't want automatic code review on PR creation, you can choose to trigger code review by adding a label. For example, create the following workflow:
```yaml
name: Code Review
@@ -123,12 +123,12 @@ With this setup, DeepSeek code review will not run automatically upon PR creatio
| chat-token | String | Required, DeepSeek API Token |
| model | String | Optional, The model used for code review, defaults to `deepseek-chat` |
| base-url | String | Optional, DeepSeek API Base URL, defaults to `https://api.deepseek.com` |
| max-length | Int | Optional, Maximum length(Unicode width) of the content for review, if the content length exceeds this value, the review will be skipped. Default `0` means no limit. |
| max-length | Int | Optional, Maximum length (Unicode width) of the content for review. If the content length exceeds this value, the review will be skipped. Default `0` means no limit. |
| sys-prompt | String | Optional, System prompt corresponding to `$sys_prompt` in the payload, default value see note below |
| user-prompt | String | Optional, User prompt corresponding to `$user_prompt` in the payload, default value see note below |
| temperature | Number | Optional, The temperature for the model to generate the response, between `0` and `2`, default value `1.0` |
| include-patterns | String | Optional, The comma separated file patterns to include in the code review. No default |
| exclude-patterns | String | Optional, The comma separated file patterns to exclude in the code review. Default to `pnpm-lock.yaml,package-lock.json,*.lock` |
| temperature | Number | Optional, The temperature for the model to generate the response, between `0` and `2`. Default value is `0.3` |
| include-patterns | String | Optional, Comma-separated file patterns to include in the code review. No default |
| exclude-patterns | String | Optional, Comma-separated file patterns to exclude from the code review. Defaults to `pnpm-lock.yaml,package-lock.json,*.lock` |
| github-token | String | Optional, The `GITHUB_TOKEN` secret or personal access token to authenticate. Defaults to `${{ github.token }}`. |
**DeepSeek API Call Payload**:
@@ -154,18 +154,18 @@ With this setup, DeepSeek code review will not run automatically upon PR creatio
> [!NOTE]
>
> You can control the language of the code review results by the language of the
> Prompt. The default Prompt language is currently English. When you use a Chinese
> Prompt, the generated code review results will be in Chinese.
> You can control the language of the code review results through the language of the
> prompt. The default prompt language is currently English. When you use a Chinese
> prompt, the generated code review results will be in Chinese.
## Local Code Review
### Required Tools
To perform code reviews locally(should works for `macOS`, `Ubuntu`, and `Windows`), you need to install the following tools:
To perform code reviews locally (works on `macOS`, `Ubuntu`, and `Windows`), you need to install the following tools:
- [`Nushell`](https://www.nushell.sh/book/installation.html). It is recommended to install the latest versions(min version required: `0.103`).
- The latest version of [`awk`](https://github.com/onetrueawk/awk) or [`gawk`](https://www.gnu.org/software/gawk/) is required, with `gawk` being the preferred choice.
- [`Nushell`](https://www.nushell.sh/book/installation.html). It is recommended to install the latest version (minimum version required: `0.110.0`).
- The latest version of [`awk`](https://github.com/onetrueawk/awk) or [`gawk`](https://www.gnu.org/software/gawk/) is required, with `gawk` being preferred.
- Clone this repository to your local machine, navigate to the repository directory, and run `nu cr -h`. You should see an output similar to the following:
```console
@@ -179,8 +179,8 @@ Flags:
-r, --repo <string>: GitHub repo name, e.g. hustcer/deepseek-review
-n, --pr-number <string>: GitHub PR number
-k, --gh-token <string>: Your GitHub token, fallback to GITHUB_TOKEN env var
-t, --diff-to <string>: Diff to git REF
-f, --diff-from <string>: Diff from git REF
-f, --diff-from <string>: Git diff starting commit SHA
-t, --diff-to <string>: Git diff ending commit SHA
-c, --patch-cmd <string>: The `git show` or `git diff` command to get the diff content, for local CR only
-l, --max-length <int>: Maximum length of the content for review, 0 means no limit.
-m, --model <string>: Model name, or read from CHAT_MODEL env var, `deepseek-chat` by default
@@ -190,7 +190,7 @@ Flags:
-u, --user-prompt <string>: Default to $DEFAULT_OPTIONS.USER_PROMPT,
-i, --include <string>: Comma separated file patterns to include in the code review
-x, --exclude <string>: Comma separated file patterns to exclude in the code review
-T, --temperature <float>: Temperature for the model, between `0` and `2`, default value `1.0`
-T, --temperature <float>: Temperature for the model, between `0` and `2`, default value `0.3`
-C, --config <string>: Config file path, default to `config.yml`
-o, --output <string>: Output file path
-h, --help: Display the help message for this command
@@ -202,27 +202,27 @@ Parameters:
### Environment Configuration
To perform code review locally, you need to modify the configuration file. The repository already provides a configuration example [`config.example.yml`](https://github.com/hustcer/deepseek-review/blob/main/config.example.yml). Copy it to `config.yml` and modify it according to your actual needs. **Read the comments in the configuration file carefully**, as they explain the purpose of each configuration item.
To perform code reviews locally, you need to modify the configuration file. The repository provides a configuration example [`config.example.yml`](https://github.com/hustcer/deepseek-review/blob/main/config.example.yml). Copy it to `config.yml` and modify it according to your needs. **Read the comments in the configuration file carefully**, as they explain the purpose of each configuration item.
> [!WARNING]
>
> The `config.yml` configuration file is **only used locally** and will not be utilized in GitHub Workflow. **Sensitive information** in this file should be properly secured and **never committed** to the code repository.
> The `config.yml` configuration file is **only used locally** and will not be utilized in GitHub Workflows. **Sensitive information** in this file should be properly secured and **never committed** to the code repository.
>
**Create Command Alias**
**Create a Command Alias**
For convenience in performing code review across any local repository, create a command alias. For example:
For convenience when performing code reviews across any local repository, create a command alias. For example:
```sh
# For Nushell: Modify config.nu and add:
alias cr = nu /absolute/path/to/deepseek-review/cr --config /absolute/path/to/deepseek-review/config.yml
# Modify ~/.zshrc for zsh or ~/.bashrc for bash or ~/.config/fish/config.fish for fish and add:
# Modify ~/.zshrc for zsh, ~/.bashrc for bash, or ~/.config/fish/config.fish for fish and add:
alias cr="nu /absolute/path/to/deepseek-review/cr --config /absolute/path/to/deepseek-review/config.yml"
# After sourcing the modified profile, use `cr` for code review
# After sourcing the modified profile, use `cr` for code reviews
# For Windows powershell users please set cr alias by editing $PROFILE and add:
# For Windows PowerShell users, set the cr alias by editing $PROFILE and add:
function cr {
nu D:\absolute\path\to\deepseek-review\cr --config D:\absolute\path\to\deepseek-review\config.yml @args
}
@@ -235,20 +235,20 @@ function cr {
To review a local repository:
- Navigate to the Git repository directory.
- Use the `cr` command to review current modifications, provided that `config.yml` is correctly configured.
- Use the `cr` command to review current modifications, provided that `config.yml` is correctly configured.
**Usage Examples**
```sh
# Perform code review on the `git diff` changes in current directory
# Perform code review on the `git diff` changes in the current directory
cr
# Perform code review on the `git diff f536acc` changes in current directory
# Perform code review on the `git diff f536acc` changes in the current directory
cr --diff-from f536acc
# Perform code review on the `git diff f536acc` changes and output result to review.md
# Perform code review on the `git diff f536acc` changes and output the result to review.md
cr --diff-from f536acc --output review.md
# Perform code review on the `git diff f536acc 0dd0eb5` changes in current directory
# Perform code review on the `git diff f536acc 0dd0eb5` changes in the current directory
cr --diff-from f536acc --diff-to 0dd0eb5
# Review the changes in current directory using the `--patch-cmd` flag
# Review the changes in the current directory using the `--patch-cmd` flag
cr --patch-cmd 'git diff head~3'
cr -c 'git show head~3'
cr -c 'git diff 2393375 71f5a31'
@@ -261,17 +261,17 @@ cr -c 'git diff 2393375 71f5a31 :!nu/*'
When reviewing a remote GitHub PR locally:
- Always specify the PR number via `--pr-number`
- Always specify the PR number via `--pr-number`.
- Use `--repo` to indicate the target repository (e.g., `hustcer/deepseek-review`). If `--repo` is omitted, the tool reads `settings.default-github-repo` from `config.yml`.
**Usage Examples**
```sh
# Perform code review on PR #31 in the remote DEFAULT_GITHUB_REPO repo
# Perform code review on PR #31 in the remote DEFAULT_GITHUB_REPO repository
cr --pr-number 31
# Perform code review on PR #31 in the remote hustcer/deepseek-review repo
# Perform code review on PR #31 in the remote hustcer/deepseek-review repository
cr --pr-number 31 --repo hustcer/deepseek-review
# Perform code review on PR #31 and exclude changes of pnpm-lock.yaml
# Perform code review on PR #31 and exclude changes in pnpm-lock.yaml
cr --pr-number 31 --exclude pnpm-lock.yaml
```

View File

@@ -124,7 +124,7 @@ jobs:
| max-length | Int | 可选,待审查内容的最大 Unicode 长度, 默认 `0` 表示没有限制,超过非零值则跳过审查 |
| sys-prompt | String | 可选,系统提示词对应入参中的 `$sys_prompt`, 默认值见后文注释 |
| user-prompt | String | 可选,用户提示词对应入参中的 `$user_prompt`, 默认值见后文注释 |
| temperature | Number | 可选,采样温度,介于 `0``2` 之间, 默认值 `1.0` |
| temperature | Number | 可选,采样温度,介于 `0``2` 之间, 默认值 `0.3` |
| include-patterns | String | 可选,代码审查中要包含的以逗号分隔的文件模式,无默认值 |
| exclude-patterns | String | 可选,代码审查中要排除的以逗号分隔的文件模式,默认值为 `pnpm-lock.yaml,package-lock.json,*.lock` |
| github-token | String | 可选,用于访问 API 进行 PR 管理的 GitHub Token默认为 `${{ github.token }}` |
@@ -161,7 +161,7 @@ DeepSeek 接口调用入参:
在本地进行代码审查,支持 `macOS`, `Ubuntu` & `Windows` 不过需要安装以下工具:
- [`Nushell`](https://www.nushell.sh/book/installation.html), 建议安装最新版本(最低版本 `0.103`)
- [`Nushell`](https://www.nushell.sh/book/installation.html), 建议安装最新版本(最低版本 `0.110.0`)
- [`awk`](https://github.com/onetrueawk/awk) 或者 [`gawk`](https://www.gnu.org/software/gawk/) 的最新版版本,优先推荐 `gawk`
- 接下来只需要把本仓库代码克隆到本地,然后进入仓库目录执行 `nu cr -h` 即可看到类似如下输出:
@@ -176,8 +176,8 @@ Flags:
-r, --repo <string>: GitHub repo name, e.g. hustcer/deepseek-review
-n, --pr-number <string>: GitHub PR number
-k, --gh-token <string>: Your GitHub token, fallback to GITHUB_TOKEN env var
-t, --diff-to <string>: Diff to git REF
-f, --diff-from <string>: Diff from git REF
-f, --diff-from <string>: Git diff starting commit SHA
-t, --diff-to <string>: Git diff ending commit SHA
-c, --patch-cmd <string>: The `git show` or `git diff` command to get the diff content, for local CR only
-l, --max-length <int>: Maximum length of the content for review, 0 means no limit.
-m, --model <string>: Model name, or read from CHAT_MODEL env var, `deepseek-chat` by default
@@ -187,7 +187,7 @@ Flags:
-u, --user-prompt <string>: Default to $DEFAULT_OPTIONS.USER_PROMPT,
-i, --include <string>: Comma separated file patterns to include in the code review
-x, --exclude <string>: Comma separated file patterns to exclude in the code review
-T, --temperature <float>: Temperature for the model, between `0` and `2`, default value `1.0`
-T, --temperature <float>: Temperature for the model, between `0` and `2`, default value `0.3`
-C, --config <string>: Config file path, default to `config.yml`
-o, --output <string>: Output file path
-h, --help: Display the help message for this command

View File

@@ -28,7 +28,7 @@ inputs:
description: 'The DeepSeek model to choose for code review.'
temperature:
required: false
default: 1.0
default: 0.3
description: 'The temperature of the model.'
base-url:
required: false
@@ -58,9 +58,9 @@ runs:
using: 'composite'
steps:
- name: Setup Nu
uses: hustcer/setup-nu@v3
uses: hustcer/setup-nu@v3.22
with:
version: 0.103.0
version: 0.110.0
- name: DeepSeek Code Review
shell: nu {0}
@@ -78,7 +78,7 @@ runs:
let includePatterns = '${{ inputs.include-patterns }}'
let excludePatterns = '${{ inputs.exclude-patterns }}'
let maxLength = try { '${{ inputs.max-length }}' | into int } catch { 0 }
let temperature = try { '${{ inputs.temperature }}' | into float } catch { 1.0 }
let temperature = try { '${{ inputs.temperature }}' | into float } catch { 0.3 }
(deepseek-review $token
--model $model
--repo $repo

View File

@@ -17,8 +17,8 @@ settings:
# If the content length exceeds the non-zero limit, the review will be skipped
# Note that it's unicode width not LLM token length
max-length: 0
# The temperature of the model, The value should be between 0 and 2, with default value 1.0
temperature: 1.0
# The temperature of the model, The value should be between 0 and 2, with default value 0.3
temperature: 0.3
# The user prompt name to use for DeepSeek API select from 'prompts.user'
user-prompt: 'default'
# The system prompt name to use for DeepSeek API select from 'prompts.system'

6
cr
View File

@@ -14,8 +14,8 @@ def main [
--repo(-r): string, # GitHub repo name, e.g. hustcer/deepseek-review
--pr-number(-n): string, # GitHub PR number
--gh-token(-k): string, # Your GitHub token, fallback to GITHUB_TOKEN env var
--diff-to(-t): string, # Diff to git REF
--diff-from(-f): string, # Diff from git REF
--diff-from(-f): string, # Git diff starting commit SHA
--diff-to(-t): string, # Git diff ending commit SHA
--patch-cmd(-c): string, # The `git show` or `git diff` command to get the diff content, for local CR only
--max-length(-l): int, # Maximum length of the content for review, 0 means no limit.
--model(-m): string, # Model name, or read from CHAT_MODEL env var, `deepseek-chat` by default
@@ -25,7 +25,7 @@ def main [
--user-prompt(-u): string # Default to $DEFAULT_OPTIONS.USER_PROMPT,
--include(-i): string, # Comma separated file patterns to include in the code review
--exclude(-x): string, # Comma separated file patterns to exclude in the code review
--temperature(-T): float, # Temperature for the model, between `0` and `2`, default value `1.0`
--temperature(-T): float, # Temperature for the model, between `0` and `2`, default value `0.3`
--config(-C): string # Config file path, default to `config.yml`
--output(-o): string, # Output file path
] {

View File

@@ -1,7 +1,7 @@
{
"name": "deepseek-review",
"version": "1.17.0",
"actionVer": "v1.17",
"version": "1.20.0",
"actionVer": "v1.20",
"author": "hustcer",
"license": "MIT",
"github": "https://github.com/hustcer/deepseek-review",

View File

@@ -51,8 +51,8 @@ export def compare-ver [v1: string, v2: string] {
# If you want to compare more parts use the following code:
# for i in 0..([2 ($a | length) ($b | length)] | math max)
for i in 0..2 {
let x = $a | get -i $i | default 0
let y = $b | get -i $i | default 0
let x = $a | get -o $i | default 0
let y = $b | get -o $i | default 0
if $x > $y { return 1 }
if $x < $y { return (-1) }
}
@@ -81,28 +81,69 @@ export def check-nushell [--debug] {
}
# Converts a .env file into a record
# may be used like this: open .env | load-env
# works with quoted and unquoted .env files
export def 'from env' []: string -> record {
lines
| split column '#' # remove comments
| get column1
| parse '{key}={value}'
| update value {
str trim # Trim whitespace between value and inline comments
| str trim -c '"' # unquote double-quoted values
| str trim -c "'" # unquote single-quoted values
| str replace -a "\\n" "\n" # replace `\n` with newline char
| str replace -a "\\r" "\r" # replace `\r` with carriage return
| str replace -a "\\t" "\t" # replace `\t` with tab
}
| transpose -r -d
# May be used like this: open .env | load-env
# Works with quoted and unquoted .env files
export def "from env" []: string -> record {
let input = $in
# Process escape sequences in double-quoted values using str replace chain
# Use NUL char as placeholder to avoid replacement conflicts
let process_escapes = {|content: string|
$content
| str replace -a '\\' (char nul) # Placeholder for \\ to avoid conflicts
| str replace -a '\n' (char nl)
| str replace -a '\r' (char cr)
| str replace -a '\t' (char tab)
| str replace -a '\"' '"'
| str replace -a (char nul) '\' # Restore \\ to single \
}
# Parse double-quoted value with escape sequence support
let parse_double_quoted = {|val: string|
let matched = ($val | parse -r '^"(?P<content>(?:[^"\\]|\\.)*)"')
if ($matched | is-empty) { $val | str trim -c '"' } else { do $process_escapes $matched.0.content }
}
# Parse single-quoted value (no escape processing)
let parse_single_quoted = {|val: string|
let matched = ($val | parse -r "^'(?P<content>[^']*)'")
if ($matched | is-empty) { $val | str trim -c "'" } else { $matched.0.content }
}
# Parse unquoted value: handle escaped hash (\#) and strip inline comments
let parse_unquoted = {|val: string|
$val
| str replace -a '\#' (char nul) # Placeholder for \#
| split row '#' # Split by comment delimiter
| first # Take content before first #
| str replace -a (char nul) '#' # Restore \# to #
| str trim
}
# Parse value based on its format
let parse_value = {|val: string|
match $val {
$v if ($v | str starts-with '"') => { do $parse_double_quoted $v }
$v if ($v | str starts-with "'") => { do $parse_single_quoted $v }
_ => { do $parse_unquoted $val }
}
}
let parsed = $input | lines
| str trim
| compact -e
| where {|line| not ($line | str starts-with '#') }
| parse "{key}={value}"
| update key {|row| $row.key | str trim | str replace -r '^export\s+' '' }
| update value {|row| do $parse_value ($row.value | str trim) }
if ($parsed | is-empty) { {} } else { $parsed | transpose -r -d -l }
}
# Compact the record by removing empty columns
export def compact-record []: record -> record {
let record = $in
let empties = $record | columns | filter {|it| $record | get $it | is-empty }
let empties = $record | columns | where {|it| $record | get $it | is-empty }
$record | reject ...$empties
}

View File

@@ -28,15 +28,15 @@ def check-prompts [options: record] {
# Check if the specified type of prompt key exists in the config.yml file
def check-prompt [options: record, type: string] {
let prompt_key = $options.settings | get -i $'($type)-prompt' | default ''
let prompt_key = $options.settings | get -o $'($type)-prompt' | default ''
if ($prompt_key | is-empty) {
print $'(ansi r)The ($type) prompt key is missing in `settings.($type)-prompt` config.yml file.(ansi reset)'
exit $ECODE.INVALID_PARAMETER
}
let prompt = $options.prompts | get -i $type
let prompt = $options.prompts | get -o $type
| default []
| where name == $prompt_key
| get -i 0.prompt
| get -o 0.prompt
if ($prompt | is-empty) {
print $'The ($type) prompt (ansi r)($prompt_key)(ansi reset) is missing in `prompts.($type)` of config.yml file.'
exit $ECODE.INVALID_PARAMETER
@@ -59,11 +59,11 @@ def check-providers [options: record] {
exit $ECODE.INVALID_PARAMETER
}
# Each provider should have name, token and models field
$options.providers | each {|it|
let empties = [name token models] | filter { |field| $it | get -i $field | is-empty }
$options.providers | each {|p|
let empties = [name token models] | where { |field| $p | get -o $field | is-empty }
if ($empties | is-not-empty) {
print $'Field (ansi r)`($empties | str join ,)`(ansi reset) should not be empty for provider:'
$it | table -e -t psql | print
$p | table -e -t psql | print
exit $ECODE.INVALID_PARAMETER
}
}
@@ -91,7 +91,8 @@ def check-models [options: record] {
}
# Check if the config.yml file exists and if it's valid
export def config-check [--config: string = $SETTING_FILE] {
export def config-check [--config: string] {
let config = $config | default $SETTING_FILE
file-exists $config
let options = open $config
check-prompts $options
@@ -105,7 +106,7 @@ def get-model-envs [settings: record, model?: string = ''] {
let provider = $settings.providers
| default []
| where name == $name
| get -i 0
| get -o 0
| default {}
let model_name = $provider.models
| default []
@@ -114,7 +115,7 @@ def get-model-envs [settings: record, model?: string = ''] {
} else {
$it.name == $model or $it.alias? == $model }
}
| get -i 0.name
| get -o 0.name
| default $model
{ CHAT_TOKEN: $provider.token?, BASE_URL: $provider.base-url?, CHAT_URL: $provider.chat-url?, CHAT_MODEL: $model_name }
@@ -132,12 +133,12 @@ export def --env config-load [
let user_prompt = $all_settings.prompts?.user?
| default []
| where name == ($settings.user-prompt? | default '')
| get -i 0.prompt
| get -o 0.prompt
let system_prompt = $all_settings.prompts?.system?
| default []
| where name == ($settings.system-prompt? | default '')
| get -i 0.prompt
| get -o 0.prompt
let model_envs = get-model-envs $all_settings $model

View File

@@ -44,7 +44,7 @@ const HTTP_HEADERS = [User-Agent curl/8.9]
const DEFAULT_OPTIONS = {
MODEL: 'deepseek-chat',
TEMPERATURE: 1.0,
TEMPERATURE: 0.3,
BASE_URL: 'https://api.deepseek.com',
USER_PROMPT: 'Please review the following code changes:',
SYS_PROMPT: 'You are a professional code review assistant responsible for analyzing code changes in GitHub Pull Requests. Identify potential issues such as code style violations, logical errors, security vulnerabilities, and provide improvement suggestions. Clearly list the problems and recommendations in a concise manner.',
@@ -58,8 +58,8 @@ export def --env deepseek-review [
--output(-o): string, # Output file path
--pr-number(-n): string, # GitHub PR number
--gh-token(-k): string, # Your GitHub token, fallback to GITHUB_TOKEN env var
--diff-to(-t): string, # Diff to git REF
--diff-from(-f): string, # Diff from git REF
--diff-to(-t): string, # Git diff ending commit SHA
--diff-from(-f): string, # Git diff starting commit SHA
--patch-cmd(-c): string, # The `git show` or `git diff` command to get the diff content, for local CR only
--max-length(-l): int, # Maximum length of the content for review, 0 means no limit.
--model(-m): string, # Model name, or read from CHAT_MODEL env var, `deepseek-chat` by default
@@ -69,7 +69,7 @@ export def --env deepseek-review [
--user-prompt(-u): string # Default to $DEFAULT_OPTIONS.USER_PROMPT,
--include(-i): string, # Comma separated file patterns to include in the code review
--exclude(-x): string, # Comma separated file patterns to exclude in the code review
--temperature(-T): float, # Temperature for the model, between `0` and `2`, default value `1.0`
--temperature(-T): float, # Temperature for the model, between `0` and `2`, default value `0.3`
]: nothing -> nothing {
$env.config.table.mode = 'psql'
@@ -114,7 +114,7 @@ export def --env deepseek-review [
print $hint; print -n (char nl)
if ($pr_number | is-empty) {
print 'Current Settings:'; hr-line
$setting | compact-record | reject -i repo | print; print -n (char nl)
$setting | compact-record | reject -o repo | print; print -n (char nl)
}
let content = (
@@ -151,9 +151,9 @@ export def --env deepseek-review [
print $'✖️ Code review failedError: '; hr-line; print $response
exit $ECODE.SERVER_ERROR
}
let message = $response | get -i choices.0.message
let message = $response | get -o choices.0.message
let reason = $message | coalesce-reasoning
let review = $message.content? | default ($response | get -i message.content)
let review = $message.content? | default ($response | get -o message.content)
let result = ['<details>' '<summary> Reasoning Details</summary>' $reason "</details>\n" $review] | str join "\n"
if ($review | is-empty) {
print $'✖️ Code review failedNo review result returned from ($base_url) ...'
@@ -192,7 +192,7 @@ def write-review-to-file [
'# DeepSeek Code Review Result', ''
$"Generated at: (date now | format date '%Y/%m/%d %H:%M:%S')", ''
'## Code Review Settings', ''
($setting | compact-record | reject -i repo | transpose key val | to md --pretty)
($setting | compact-record | reject -o repo | transpose key val | to md --pretty)
'', '## Review Detail', '', $result, '', ...$token_usage
]
try {
@@ -264,10 +264,10 @@ def streaming-output [
| try { lines } catch { print $'(ansi r)Error Happened ...(ansi reset)'; exit $ECODE.SERVER_ERROR }
| each {|line|
if ($line | is-empty) { return }
if ($IGNORED_MESSAGES | get -i $line | default false) { return }
if ($IGNORED_MESSAGES | get -o $line | default false) { return }
let $last = $line | parse-line
if $debug { $last | to json | kv set last-reply }
$last | get -i choices.0.delta | default ($last | get -i message) | if ($in | is-not-empty) {
$last | get -o choices.0.delta | default ($last | get -o message) | if ($in | is-not-empty) {
let delta = $in
if ($delta | coalesce-reasoning | is-not-empty) { kv set reasoning ((kv get reasoning) + 1) }
if (kv get reasoning) == 1 { print $'(char nl)Reasoning Details:'; hr-line }
@@ -279,7 +279,7 @@ def streaming-output [
if $debug and (kv get last-reply | is-not-empty) {
print $'(char nl)(char nl)Model & Token Usage:'; hr-line
kv get last-reply | from json | select -i model usage | table -e | print
kv get last-reply | from json | select -o model usage | table -e | print
}
}

View File

@@ -132,7 +132,7 @@ def install-gawk-for-actions [] {
Invoke-Expression (New-Object System.Net.WebClient).DownloadString("https://get.scoop.sh")
$env:Path = "$env:USERPROFILE\scoop\shims;" + $env:Path; scoop update; scoop install gawk
'# | complete | get stdout | print
let awk_bin = $'($nu.home-path)/scoop/shims/gawk.exe'
let awk_bin = $'($nu.home-dir)/scoop/shims/gawk.exe'
let version = get-awk-ver $awk_bin
{ awk_bin: $awk_bin, version: $version }
}

View File

@@ -1,39 +1,40 @@
use std/assert
use std/testing *
use ../nu/common.nu [
compare-ver, 'from env', is-installed, has-ref,
git-check, compact-record, is-repo, windows?, mac?,
]
#[test]
@test
def 'compare-verv1.0.0 is greater than v0.999.0' [] {
assert equal (compare-ver 1.0.0 0.999.0) 1
assert equal (compare-ver v1.0.0 v0.999.0) 1
}
#[test]
@test
def 'compare-verv1.0.1 is equal to v1.0.1' [] {
assert equal (compare-ver 1.0.1 1.0.1) 0
}
#[test]
@test
def 'compare-verv1.0.0 is equal to v1' [] {
assert equal (compare-ver v1.0.0 v1) 0
}
#[test]
@test
def 'compare-verv1.0.1 is greater than v1' [] {
assert equal (compare-ver v1.0.1 v1) 1
}
#[test]
@test
def 'compare-verv1.0.1 is lower than v1.1.0' [] {
assert less (compare-ver 1.0.1 v1.1) 0
assert equal (compare-ver 1.0.1 1.1.0) (-1)
}
#[test]
@test
def 'from-env.env load should work' [] {
open tests/resources/.env.test | from env | load-env
assert equal $env.CHAT_MODEL deepseek-chat
@@ -43,35 +44,35 @@ def 'from-env.env load should work' [] {
assert equal $env.USER_PROMPT 'Please review the following code changes'
}
#[test]
@test
def 'is-installedbinary install check should work' [] {
assert equal (is-installed git) true
assert equal (is-installed abc) false
}
#[test]
@test
def 'has-refgit repo should has HEAD ref' [] {
assert equal (has-ref HEAD) true
assert equal (has-ref 0000) false
}
#[test]
@test
def 'is-repocurrent dir is a git repo' [] {
assert equal (is-repo) true
}
#[test]
@test
def 'git-checkcurrent dir is a git repo' [] {
assert equal (git-check (pwd) --check-repo=1) true
}
#[test]
@test
def 'compact-recordshould work as expected' [] {
assert equal ({a: null, b: '', c: 'abc' } | compact-record) { c: 'abc' }
assert equal ({a: null, b: 0, c: 1, e: { f: 'g' } } | compact-record) { b: 0, c: 1, e: { f: 'g' } }
}
#[test]
@test
def 'OS check should work as expected' [] {
# `$env.RUNNER_OS` Possible values are Linux, Windows, or macOS in GitHub Actions
match $nu.os-info.name {

View File

@@ -1,12 +1,13 @@
use std/assert
use std/testing *
use ../nu/diff.nu [get-diff]
use ../nu/util.nu [is-safe-git, prepare-awk, generate-include-regex, generate-exclude-regex]
# Get the unicode width of the input string
def get-uw [] { $in | str stats | get unicode-width }
#[before-all]
@before-all
def setup [] {
let awk_bin = (prepare-awk)
let patch = open -r tests/resources/diff.patch
@@ -14,7 +15,7 @@ def setup [] {
{ patch: $patch, awk: $awk_bin, SHA: 22e7b71 }
}
#[test]
@test
def 'is-safe-gitshould work as expected' [] {
assert equal (is-safe-git 'git diff') true
assert equal (is-safe-git 'git show') true
@@ -45,7 +46,7 @@ def 'is-safe-gitshould work as expected' [] {
assert equal (is-safe-git 'git show HEAD:nu/common.nu') true
}
#[test]
@test
def 'generate-include-regexshould work as expected' [] {
let patch = $in.patch
let awk_bin = $in.awk
@@ -55,7 +56,7 @@ def 'generate-include-regexshould work as expected' [] {
assert equal ($patch | ^$awk_bin (generate-include-regex [.env*, *.md, nu/*]) | get-uw) 6871
}
#[test]
@test
def 'generate-exclude-regexshould work as expected' [] {
let patch = $in.patch
let awk_bin = $in.awk
@@ -63,7 +64,7 @@ def 'generate-exclude-regexshould work as expected' [] {
assert equal ($patch | ^$awk_bin (generate-exclude-regex [.env*, *.md, nu/*]) | get-uw) (1350 + 99)
}
#[test]
@test
def 'both include and exclude should work as expected' [] {
let patch = $in.patch
let awk_bin = $in.awk
@@ -73,7 +74,7 @@ def 'both include and exclude should work as expected' [] {
| get-uw) 2576
}
#[test]
@test
def 'both exclude and include should work as expected' [] {
let patch = $in.patch
let awk_bin = $in.awk
@@ -83,7 +84,7 @@ def 'both exclude and include should work as expected' [] {
| get-uw) 2576
}
#[test]
@test
def 'get-diffget patch from remote PR should work' [] {
$env.GH_TOKEN = $env.GITHUB_TOKEN?
const repo = 'hustcer/deepseek-review'
@@ -93,7 +94,7 @@ def 'get-diffget patch from remote PR should work' [] {
| str join "\n" | get-uw) 7923
}
#[test]
@test
def 'get-diffget patch from remote PR with include should work' [] {
$env.GH_TOKEN = $env.GITHUB_TOKEN?
const repo = 'hustcer/deepseek-review'
@@ -102,7 +103,7 @@ def 'get-diffget patch from remote PR with include should work' [] {
assert equal ($patch | get-uw) 2576
}
#[test]
@test
def 'get-diffget patch from remote PR with exclude should work' [] {
$env.GH_TOKEN = $env.GITHUB_TOKEN?
const repo = 'hustcer/deepseek-review'
@@ -111,7 +112,7 @@ def 'get-diffget patch from remote PR with exclude should work' [] {
assert equal ($patch | get-uw) 555
}
#[test]
@test
def 'get-diffget patch from remote PR with exclude & include should work' [] {
$env.GH_TOKEN = $env.GITHUB_TOKEN?
const repo = 'hustcer/deepseek-review'