mirror of
https://github.com/hustcer/deepseek-review.git
synced 2026-05-13 05:16:05 +08:00
Compare commits
26 Commits
feature/pr
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9163ca2434 | ||
|
|
cb78a000a7 | ||
|
|
d1dcf1311d | ||
|
|
6cbc5ef631 | ||
|
|
92a3c2ae17 | ||
|
|
90c8878923 | ||
|
|
231c2d8432 | ||
|
|
923ee0f999 | ||
|
|
32cffba4d1 | ||
|
|
0c001b0ee2 | ||
|
|
edcd90e48b | ||
|
|
dfc4c59c1f | ||
|
|
92061e6c82 | ||
|
|
3c3f0a3c85 | ||
|
|
7a87f8adc0 | ||
|
|
d7b2e3a926 | ||
|
|
91ae07bb82 | ||
|
|
d830da6937 | ||
|
|
885b55dbb0 | ||
|
|
317d3c92da | ||
|
|
938790c65b | ||
|
|
a4d125ecba | ||
|
|
930e0ae68f | ||
|
|
d0b2ea125a | ||
|
|
9852113028 | ||
|
|
9ad3373cd5 |
4
.github/workflows/cr.yml
vendored
4
.github/workflows/cr.yml
vendored
@@ -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
|
||||
|
||||
6
.github/workflows/tests.yml
vendored
6
.github/workflows/tests.yml
vendored
@@ -42,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.1.0
|
||||
ref: main
|
||||
path: nutest
|
||||
repository: vyadh/nutest
|
||||
sparse-checkout: nutest/
|
||||
|
||||
54
CHANGELOG.md
54
CHANGELOG.md
@@ -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
|
||||
|
||||
2
Justfile
2
Justfile
@@ -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
|
||||
|
||||
92
README.md
92
README.md
@@ -7,31 +7,29 @@
|
||||
|
||||
[中文说明](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!
|
||||
|
||||
## 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 +38,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 +80,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
|
||||
@@ -121,21 +119,21 @@ With this setup, DeepSeek code review will not run automatically upon PR creatio
|
||||
| Name | Type | Description |
|
||||
| -------------- | ------ | ----------------------------------------------------------------------- |
|
||||
| chat-token | String | Required, DeepSeek API Token |
|
||||
| model | String | Optional, The model used for code review, defaults to `deepseek-chat` |
|
||||
| model | String | Optional, The model used for code review, defaults to `deepseek-v4-flash` |
|
||||
| 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 `0.3` |
|
||||
| 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**:
|
||||
|
||||
```js
|
||||
{
|
||||
// `$model` default value: deepseek-chat
|
||||
// `$model` default value: deepseek-v4-flash
|
||||
model: $model,
|
||||
stream: false,
|
||||
temperature: $temperature,
|
||||
@@ -154,18 +152,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.112.2`).
|
||||
- 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
|
||||
@@ -183,7 +181,7 @@ Flags:
|
||||
-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
|
||||
-m, --model <string>: Model name, or read from CHAT_MODEL env var, `deepseek-v4-flash` by default
|
||||
-b, --base-url <string>: DeepSeek API base URL, fallback to BASE_URL env var
|
||||
-U, --chat-url <string>: DeepSeek Model chat full API URL, e.g. http://localhost:11535/api/chat
|
||||
-s, --sys-prompt <string>: Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
@@ -202,27 +200,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 +233,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 +259,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
|
||||
```
|
||||
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||

|
||||

|
||||
|
||||
本工具也支持使用 SiliconCloud 上的 DeepSeek 模型,[注册](https://cloud.siliconflow.cn/i/rqCdIxzS) 就**免费赠送 2000 万 Token**,赶紧试试吧!
|
||||
|
||||
## 特性
|
||||
|
||||
### GitHub Action
|
||||
@@ -119,7 +117,7 @@ jobs:
|
||||
| 名称 | 类型 | 描述 |
|
||||
| -------------- | ------ | -------------------------------------------------------------- |
|
||||
| chat-token | String | 必填,DeepSeek API Token |
|
||||
| model | String | 可选,配置代码审查选用的模型,默认为 `deepseek-chat` |
|
||||
| model | String | 可选,配置代码审查选用的模型,默认为 `deepseek-v4-flash` |
|
||||
| base-url | String | 可选,DeepSeek API Base URL, 默认为 `https://api.deepseek.com` |
|
||||
| max-length | Int | 可选,待审查内容的最大 Unicode 长度, 默认 `0` 表示没有限制,超过非零值则跳过审查 |
|
||||
| sys-prompt | String | 可选,系统提示词对应入参中的 `$sys_prompt`, 默认值见后文注释 |
|
||||
@@ -133,7 +131,7 @@ DeepSeek 接口调用入参:
|
||||
|
||||
```js
|
||||
{
|
||||
// `$model` default value: deepseek-chat
|
||||
// `$model` default value: deepseek-v4-flash
|
||||
model: $model,
|
||||
stream: false,
|
||||
temperature: $temperature,
|
||||
@@ -161,7 +159,7 @@ DeepSeek 接口调用入参:
|
||||
|
||||
在本地进行代码审查,支持 `macOS`, `Ubuntu` & `Windows` 不过需要安装以下工具:
|
||||
|
||||
- [`Nushell`](https://www.nushell.sh/book/installation.html), 建议安装最新版本(最低版本 `0.103`)
|
||||
- [`Nushell`](https://www.nushell.sh/book/installation.html), 建议安装最新版本(最低版本 `0.112.2`)
|
||||
- [`awk`](https://github.com/onetrueawk/awk) 或者 [`gawk`](https://www.gnu.org/software/gawk/) 的最新版版本,优先推荐 `gawk`
|
||||
- 接下来只需要把本仓库代码克隆到本地,然后进入仓库目录执行 `nu cr -h` 即可看到类似如下输出:
|
||||
|
||||
@@ -180,7 +178,7 @@ Flags:
|
||||
-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
|
||||
-m, --model <string>: Model name, or read from CHAT_MODEL env var, `deepseek-v4-flash` by default
|
||||
-b, --base-url <string>: DeepSeek API base URL, fallback to BASE_URL env var
|
||||
-U, --chat-url <string>: DeepSeek Model chat full API URL, e.g. http://localhost:11535/api/chat
|
||||
-s, --sys-prompt <string>: Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
|
||||
@@ -24,7 +24,7 @@ inputs:
|
||||
description: 'The maximum length of the content for review, 0 means no limit.'
|
||||
model:
|
||||
required: false
|
||||
default: 'deepseek-chat'
|
||||
default: 'deepseek-v4-flash'
|
||||
description: 'The DeepSeek model to choose for code review.'
|
||||
temperature:
|
||||
required: false
|
||||
@@ -58,9 +58,9 @@ runs:
|
||||
using: 'composite'
|
||||
steps:
|
||||
- name: Setup Nu
|
||||
uses: hustcer/setup-nu@v3
|
||||
uses: hustcer/setup-nu@v3.23
|
||||
with:
|
||||
version: 0.103.0
|
||||
version: 0.112.2
|
||||
|
||||
- name: DeepSeek Code Review
|
||||
shell: nu {0}
|
||||
|
||||
@@ -50,7 +50,7 @@ providers:
|
||||
token: 'YOUR_DEEPSEEK_TOKEN' # Required, The API token for the provider
|
||||
base-url: 'https://api.deepseek.com'
|
||||
models:
|
||||
- name: 'deepseek-chat' # Required, Pass the model name to --model flag to use it
|
||||
- name: 'deepseek-v4-flash' # Required, Pass the model name to --model flag to use it
|
||||
alias: v3 # Optional, Alias name could also be passed to --model flag
|
||||
enabled: true # One and Only one model could be enabled in one model group
|
||||
description: 'DeepSeek V3' # Optional, Description of the model, won't be used actually
|
||||
|
||||
2
cr
2
cr
@@ -18,7 +18,7 @@ def main [
|
||||
--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
|
||||
--model(-m): string, # Model name, or read from CHAT_MODEL env var, `deepseek-v4-flash` by default
|
||||
--base-url(-b): string, # DeepSeek API base URL, fallback to BASE_URL env var
|
||||
--chat-url(-U): string, # DeepSeek Model chat full API URL, e.g. http://localhost:11535/api/chat
|
||||
--sys-prompt(-s): string # Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
|
||||
@@ -20,6 +20,7 @@ words:
|
||||
- hustcer
|
||||
- Nushell
|
||||
- creatio
|
||||
- pipefail
|
||||
- justfile
|
||||
- lefthook
|
||||
- deepseek
|
||||
|
||||
@@ -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",
|
||||
|
||||
86
nu/common.nu
86
nu/common.nu
@@ -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
|
||||
}
|
||||
|
||||
@@ -152,7 +193,8 @@ export def git-check [
|
||||
# Check if current directory is a git repo
|
||||
export def is-repo [] {
|
||||
let checkRepo = try {
|
||||
do -i { git rev-parse --is-inside-work-tree } | complete
|
||||
# Put `complete` inside `do` block to avoid pipefail error in Nushell 0.110+
|
||||
do { git rev-parse --is-inside-work-tree | complete }
|
||||
} catch {
|
||||
({ stdout: 'false' })
|
||||
}
|
||||
@@ -164,8 +206,8 @@ export def has-ref [
|
||||
ref: string # The git ref to check
|
||||
] {
|
||||
if not (is-repo) { return false }
|
||||
# Brackets were required here, or error will occur
|
||||
let parse = (do -i { git rev-parse --verify -q $ref } | complete)
|
||||
# Put `complete` inside `do` block to avoid pipefail error in Nushell 0.110+
|
||||
let parse = (do { git rev-parse --verify -q $ref | complete })
|
||||
if ($parse.stdout | is-empty) { false } else { true }
|
||||
}
|
||||
|
||||
|
||||
23
nu/config.nu
23
nu/config.nu
@@ -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
|
||||
|
||||
|
||||
@@ -80,6 +80,13 @@ def get-pr-diff [
|
||||
exit $ECODE.SUCCESS
|
||||
}
|
||||
|
||||
let commit_msg = http get -H $BASE_HEADER $'($GITHUB_API_BASE)/repos/($repo)/pulls/($pr_number)/commits'
|
||||
| last | get commit.message
|
||||
if ($IGNORE_REVIEW_KEYWORDS | any {|it| $commit_msg =~ $it }) {
|
||||
print $'(ansi r)The latest PR commit message contains keywords to skip the review, bye...(ansi reset)'
|
||||
exit $ECODE.SUCCESS
|
||||
}
|
||||
|
||||
# Get the diff content of the PR
|
||||
http get -H $DIFF_HEADER $'($GITHUB_API_BASE)/repos/($repo)/pulls/($pr_number)' | str trim
|
||||
}
|
||||
|
||||
@@ -46,9 +46,9 @@ export def 'make-release' [
|
||||
export def has-ref [
|
||||
ref: string # The git ref to check
|
||||
] {
|
||||
let checkRepo = (do -i { git rev-parse --is-inside-work-tree } | complete)
|
||||
# Put `complete` inside `do` block to avoid pipefail error in Nushell 0.110+
|
||||
let checkRepo = (do { git rev-parse --is-inside-work-tree | complete })
|
||||
if not ($checkRepo.stdout =~ 'true') { return false }
|
||||
# Brackets were required here, or error will occur
|
||||
let parse = (do -i { git rev-parse --verify -q $ref } | complete)
|
||||
let parse = (do { git rev-parse --verify -q $ref | complete })
|
||||
if ($parse.stdout | is-empty) { false } else { true }
|
||||
}
|
||||
|
||||
21
nu/review.nu
21
nu/review.nu
@@ -43,7 +43,7 @@ const IGNORED_MESSAGES = {
|
||||
const HTTP_HEADERS = [User-Agent curl/8.9]
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
MODEL: 'deepseek-chat',
|
||||
MODEL: 'deepseek-v4-flash',
|
||||
TEMPERATURE: 0.3,
|
||||
BASE_URL: 'https://api.deepseek.com',
|
||||
USER_PROMPT: 'Please review the following code changes:',
|
||||
@@ -62,7 +62,7 @@ export def --env deepseek-review [
|
||||
--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
|
||||
--model(-m): string, # Model name, or read from CHAT_MODEL env var, `deepseek-v4-flash` by default
|
||||
--base-url(-b): string, # DeepSeek API base URL, fallback to BASE_URL env var
|
||||
--chat-url(-U): string, # DeepSeek Model chat full API URL, e.g. http://localhost:11535/api/chat
|
||||
--sys-prompt(-s): string # Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
@@ -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 = (
|
||||
@@ -135,7 +135,8 @@ export def --env deepseek-review [
|
||||
messages: [
|
||||
{ role: 'system', content: $sys_prompt },
|
||||
{ role: 'user', content: $"($user_prompt):\n($content)" }
|
||||
]
|
||||
],
|
||||
thinking: { type: 'disabled' }
|
||||
}
|
||||
if $debug { print $'(char nl)Code Changes:'; hr-line; print $content }
|
||||
print $'(char nl)Waiting for response from (ansi g)($url)(ansi reset) ...'
|
||||
@@ -151,9 +152,9 @@ export def --env deepseek-review [
|
||||
print $'✖️ Code review failed!Error: '; 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 failed!No review result returned from ($base_url) ...'
|
||||
@@ -192,7 +193,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 +265,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 +280,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
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user