mirror of
https://github.com/hustcer/deepseek-review.git
synced 2026-05-13 05:16:05 +08:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0000000089 | ||
|
|
f9f66ccc4c | ||
|
|
eba892d969 | ||
|
|
91bfd9c2d1 | ||
|
|
f781a7d0a9 | ||
|
|
cdba3ce088 | ||
|
|
f7ced8080f | ||
|
|
d9a84f47da | ||
|
|
7ccfa23bd5 | ||
|
|
3cb42fca6a | ||
|
|
e60fc915f8 | ||
|
|
522a0174e3 |
10
.env.example
10
.env.example
@@ -9,6 +9,10 @@ CHAT_TOKEN='Your Deepseek API token'
|
||||
GITHUB_TOKEN='Your GitHub API token'
|
||||
# MAX_LENGTH: The maximum length of the content for review, 0 means no limit.
|
||||
MAX_LENGTH='0'
|
||||
# The comma separated file patterns to include in the code review.
|
||||
INCLUDE_PATTERNS=''
|
||||
# The comma separated file patterns to exclude in the code review.
|
||||
EXCLUDE_PATTERNS='pnpm-lock.yaml,package-lock.json,*.lock'
|
||||
# Default GitHub repository name to fetch PR changes
|
||||
DEFAULT_GITHUB_REPO='hustcer/deepseek-review'
|
||||
# Default local repository absolute path to query commit changes
|
||||
@@ -17,6 +21,12 @@ DEFAULT_LOCAL_REPO='/Users/hustcer/deepseek-review'
|
||||
# Replace with the actual API base URL if different
|
||||
BASE_URL='https://api.deepseek.ai'
|
||||
# USER_PROMPT: User prompt message, customize as needed
|
||||
# OR a yaml file path with key name specified to load the prompt message,
|
||||
# e.g., USER_PROMPT='/User/abc/prompts.yaml:usr-prompt'
|
||||
# Will load the prompt message from the 'usr-prompt' key in the 'prompts.yaml' file
|
||||
USER_PROMPT='Please review the following code changes'
|
||||
# SYSTEM_PROMPT: System prompt message, customize as needed
|
||||
# OR a yaml file path with key name specified to load the prompt message,
|
||||
# e.g., SYSTEM_PROMPT='/User/abc/prompts.yaml:sys-prompt'
|
||||
# Will load the prompt message from the 'sys-prompt' key in the 'prompts.yaml' file
|
||||
SYSTEM_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.'
|
||||
|
||||
78
.github/workflows/cr.yml
vendored
78
.github/workflows/cr.yml
vendored
@@ -1,7 +1,5 @@
|
||||
# Description:
|
||||
# - Deepseek code review with GitHub Actions
|
||||
# REF:
|
||||
# - https://github.com/marketplace/actions/checkout
|
||||
|
||||
name: Code Review
|
||||
on:
|
||||
@@ -10,6 +8,7 @@ on:
|
||||
- opened # Triggers when a PR is opened
|
||||
- reopened # Triggers when a PR is reopened
|
||||
- synchronize # Triggers when a commit is pushed to the PR
|
||||
# - labeled # Triggers when a label is added to the PR
|
||||
|
||||
# fix: GraphQL: Resource not accessible by integration (addComment) error
|
||||
permissions:
|
||||
@@ -19,9 +18,82 @@ jobs:
|
||||
setup-deepseek-review:
|
||||
runs-on: ubuntu-latest
|
||||
name: Code Review
|
||||
# Make sure the code review happens only when the PR has the label 'ai review'
|
||||
# if: contains(github.event.pull_request.labels.*.name, 'ai review')
|
||||
steps:
|
||||
- name: Deepseek Code Review
|
||||
uses: hustcer/deepseek-review@develop
|
||||
with:
|
||||
max-length: 10000
|
||||
max-length: 15000
|
||||
# Store the chat token in GitHub Secrets, don't expose it in the workflow file
|
||||
chat-token: ${{ secrets.CHAT_TOKEN }}
|
||||
sys-prompt: >
|
||||
As a senior DevOps engineer, perform comprehensive review of shell scripts with focus on:
|
||||
|
||||
1. Core Requirements:
|
||||
- Validate POSIX compatibility
|
||||
- Check for proper error handling
|
||||
- Verify safe variable usage
|
||||
- Assess resource management
|
||||
|
||||
2. Security Analysis:
|
||||
- Shell injection prevention
|
||||
- Safe file operations
|
||||
- Proper permissions handling
|
||||
- Secure command execution
|
||||
|
||||
3. Performance Optimization:
|
||||
- Efficient process management
|
||||
- Proper use of subshells
|
||||
- Stream handling best practices
|
||||
- Avoidance of unnecessary forks
|
||||
|
||||
Rules:
|
||||
- Target bash/sh compatibility
|
||||
- Highlight security vulnerabilities
|
||||
- Suggest performance improvements
|
||||
- Keep feedback actionable
|
||||
- Use technical shell terminology
|
||||
|
||||
Required output structure:
|
||||
#### Script Analysis
|
||||
- Key observations
|
||||
|
||||
#### Security Review
|
||||
- Vulnerability findings
|
||||
|
||||
#### Optimization Suggestions
|
||||
- Performance improvements
|
||||
|
||||
**Overall Quality:** Rating (1-5)
|
||||
|
||||
Use the following reference data:
|
||||
```yaml
|
||||
checklist:
|
||||
- Compatibility: ["POSIX compliance", "Shell-specific features", "Portability"]
|
||||
- Security: ["Input validation", "Safe eval usage", "Permission checks"]
|
||||
- Reliability: ["Error handling", "Exit codes", "Signal trapping"]
|
||||
- Performance: ["Process management", "I/O operations", "Subshell usage"]
|
||||
|
||||
examples:
|
||||
- issue: "❗ Unquoted variable expansion in line 42 (shell injection risk)"
|
||||
- issue: "⚠️ Missing error handling for rm operation in line 15"
|
||||
- suggestion: "Replace backticks with $() for better readability and nesting"
|
||||
- suggestion: "Use exec for file handling to reduce file descriptors"
|
||||
|
||||
response_template: |
|
||||
#### Script Analysis
|
||||
- {{observations}}
|
||||
|
||||
{{#security_issues}}
|
||||
#### Security Review
|
||||
- {{security_issues}}
|
||||
{{/security_issues}}
|
||||
|
||||
{{#optimizations}}
|
||||
#### Optimization Suggestions
|
||||
- {{optimizations}}
|
||||
{{/optimizations}}
|
||||
|
||||
**Overall Quality:** {{rating}}
|
||||
```
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
.env
|
||||
prompts.yaml
|
||||
|
||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -1,6 +1,26 @@
|
||||
# Changelog
|
||||
All notable changes to this project will be documented in this file.
|
||||
|
||||
## [1.5.0] - 2025-02-01
|
||||
|
||||
### Documentation
|
||||
|
||||
- Update README (#61)
|
||||
|
||||
### Features
|
||||
|
||||
- Add example of triggering code review by adding `ai review` label (#60)
|
||||
- Load multi-line prompts from yaml config for local code reviewing (#67)
|
||||
- Add `include` and `exclude` for file pattern filtering support (#68)
|
||||
|
||||
### Miscellaneous Tasks
|
||||
|
||||
- Update prompts for current repo's workflow (#63)
|
||||
|
||||
### Refactor
|
||||
|
||||
- Extracted git repo check into `is-repo` custom command (#64)
|
||||
|
||||
## [1.3.0] - 2025-01-31
|
||||
|
||||
### Documentation
|
||||
|
||||
76
README.md
76
README.md
@@ -9,16 +9,18 @@
|
||||
- Analyze Commit Changes with Deepseek for Any Local Repository with CLI
|
||||
- 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
|
||||
- Add `skip cr` or `skip review` to PR title or body to disable code review in GitHub Actions
|
||||
- Cross-platform Support: Compatible with GitHub Runners across `macOS`, `Ubuntu`, and `Windows`.
|
||||
|
||||
## Planned Features
|
||||
|
||||
- [ ] **Trigger Code Review on Mention**: Automatically initiate code review when the `github-actions` bot is mentioned in a PR comment.
|
||||
- [ ] **Exclude Specific File Changes**: Ignore changes to specified files, such as `Cargo.lock`, `pnpm-lock.yaml`, and others.
|
||||
|
||||
## Code Review with GitHub Action
|
||||
|
||||
### Initiate Code Review When PR was Created
|
||||
|
||||
Add a GitHub workflow with the following contents:
|
||||
|
||||
```yaml
|
||||
@@ -45,7 +47,53 @@ jobs:
|
||||
chat-token: ${{ secrets.CHAT_TOKEN }}
|
||||
```
|
||||
|
||||
When a PR is created, Deepseek code review will be automatically triggered, and the review results will be posted as comments on the corresponding PR. For example: [Example](https://github.com/hustcer/deepseek-review/pull/30) & [Run Log](https://github.com/hustcer/deepseek-review/actions/runs/13043609677/job/36390331791#step:2:53).
|
||||
<details>
|
||||
<summary>CHAT_TOKEN Config</summary>
|
||||
|
||||
Follow these steps to config your `CHAT_TOKEN`:
|
||||
|
||||
- Click on the "Settings" tab in your repository navigation bar.
|
||||
- In the left sidebar, click on "Secrets and variables" under "Security".
|
||||
- Click on "Actions" -> "New repository secret" button.
|
||||
- Enter `CHAT_TOKEN` in the "Name" field.
|
||||
- Enter the value of your `CHAT_TOKEN` in the "Secret" field.
|
||||
- Finally, click the "Add secret" button to save the secret.
|
||||
|
||||
</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:
|
||||
- [Example 1](https://github.com/hustcer/deepseek-review/pull/30) with default prompt & [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
|
||||
|
||||
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:
|
||||
|
||||
```yaml
|
||||
name: Code Review
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled # Triggers when a label is added to the PR
|
||||
|
||||
# fix: GraphQL: Resource not accessible by integration (addComment) error
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
setup-deepseek-review:
|
||||
runs-on: ubuntu-latest
|
||||
name: Code Review
|
||||
# Make sure the code review happens only when the PR has the label 'ai review'
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ai review')
|
||||
steps:
|
||||
- name: Deepseek Code Review
|
||||
uses: hustcer/deepseek-review@v1
|
||||
with:
|
||||
chat-token: ${{ secrets.CHAT_TOKEN }}
|
||||
```
|
||||
|
||||
With this setup, Deepseek code review will not run automatically upon PR creation. Instead, it will only be triggered when you manually add the `ai review` label.
|
||||
|
||||
## Input Parameters
|
||||
|
||||
@@ -57,6 +105,8 @@ When a PR is created, Deepseek code review will be automatically triggered, and
|
||||
| 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 |
|
||||
| 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` |
|
||||
| github-token | String | Optional, The `GITHUB_TOKEN` secret or personal access token to authenticate. Defaults to `github.token`. |
|
||||
|
||||
**Deepseek API Call Payload**:
|
||||
@@ -79,6 +129,12 @@ When a PR is created, Deepseek code review will be automatically triggered, and
|
||||
}
|
||||
```
|
||||
|
||||
> [!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.
|
||||
|
||||
## Local Code Review
|
||||
|
||||
### Required Tools
|
||||
@@ -99,14 +155,16 @@ Flags:
|
||||
-d, --debug: Debug mode
|
||||
-r, --repo <string>: GitHub repository name, e.g. hustcer/deepseek-review
|
||||
-n, --pr-number <string>: GitHub PR number
|
||||
--gh-token <string>: Your GitHub token, fallback to GITHUB_TOKEN env var
|
||||
-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
|
||||
-l, --max-length <int>: Maximum length of the content for review, 0 means no limit.
|
||||
-m, --model <string>: Model name, deepseek-chat by default (default: 'deepseek-chat')
|
||||
--base-url <string> (default: 'https://api.deepseek.com')
|
||||
-s, --sys-prompt <string> (default: '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.')
|
||||
-u, --user-prompt <string> (default: 'Please review the following code changes:')
|
||||
-b, --base-url <string> (default: 'https://api.deepseek.com')
|
||||
-s, --sys-prompt <string>: Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
-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
|
||||
-h, --help: Display the help message for this command
|
||||
|
||||
Parameters:
|
||||
@@ -118,6 +176,12 @@ Parameters:
|
||||
|
||||
To perform code reviews locally, you need to modify the configuration file. A sample configuration file `.env.example` is already provided in the repository. Copy it to `.env` and adjust it according to your actual setup.
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> The `.env` configuration file is only used locally and will not be utilized in GitHub
|
||||
> Workflow. Please securely store any sensitive information in it and avoid committing
|
||||
> it to the code repository.
|
||||
|
||||
### Usage Examples
|
||||
|
||||
```sh
|
||||
|
||||
104
README.zh-CN.md
104
README.zh-CN.md
@@ -1,4 +1,4 @@
|
||||
# Deepseek 代码审核
|
||||
# Deepseek 代码审查
|
||||
|
||||
## 特性
|
||||
|
||||
@@ -8,14 +8,16 @@
|
||||
- 完全可定制:选择模型、基础 URL 和提示词
|
||||
- 支持自托管 Deepseek 模型,提供更强的灵活性
|
||||
- 在 PR 的标题或描述中添加 `skip cr` or `skip review` 可跳过 GitHub Actions 里的代码审查
|
||||
- 对指定文件变更进行包含/排除式代码审查
|
||||
- 跨平台:支持 GitHub `macOS`, `Ubuntu` & `Windows` Runners
|
||||
|
||||
## 计划支持特性
|
||||
|
||||
- [ ] **通过提及触发代码审查**:当 PR 评论中提及 `github-actions bot` 时,自动触发代码审查
|
||||
- [ ] **忽略指定文件变更**:忽略对指定文件的更改,例如 `Cargo.lock`、`pnpm-lock.yaml` 等
|
||||
|
||||
## 通过 GitHub Action 进行代码审核
|
||||
## 通过 GitHub Action 进行代码审查
|
||||
|
||||
### 创建 PR 时自动触发代码审查
|
||||
|
||||
创建一个 GitHub workflow 内容如下:
|
||||
|
||||
@@ -43,18 +45,66 @@ jobs:
|
||||
chat-token: ${{ secrets.CHAT_TOKEN }}
|
||||
```
|
||||
|
||||
当 PR 创建的时候会自动触发 Deepseek 代码审核,并将审核结果以评论的方式发布到对应的 PR 上。比如:[示例](https://github.com/hustcer/deepseek-review/pull/30) & [运行日志](https://github.com/hustcer/deepseek-review/actions/runs/13043609677/job/36390331791#step:2:53)
|
||||
<details>
|
||||
<summary>CHAT_TOKEN 配置</summary>
|
||||
|
||||
按照以下步骤配置你的 `CHAT_TOKEN`:
|
||||
|
||||
1. 点击仓库导航栏中的 "Settings" 选项卡
|
||||
2. 在左侧边栏中,点击 "Security" 下的 "Secrets and variables"
|
||||
3. 点击 "Actions" -> "New repository secret" 按钮
|
||||
4. 在 "Name" 字段中输入 `CHAT_TOKEN`
|
||||
5. 在 "Secret" 字段中输入你的 `CHAT_TOKEN` 值
|
||||
6. 最后,点击 "Add secret"按钮保存密钥
|
||||
|
||||
</details>
|
||||
|
||||
当 PR 创建的时候会自动触发 Deepseek 代码审查,并将审查结果(依赖于提示词)以评论的方式发布到对应的 PR 上。比如:
|
||||
- [示例 1](https://github.com/hustcer/deepseek-review/pull/30) 基于默认提示词 & [运行日志](https://github.com/hustcer/deepseek-review/actions/runs/13043609677/job/36390331791#step:2:53).
|
||||
- [示例 2](https://github.com/hustcer/deepseek-review/pull/68) 基于 [这个提示词](https://github.com/hustcer/deepseek-review/blob/eba892d969049caff00b51a31e5c093aeeb536e3/.github/workflows/cr.yml#L32)
|
||||
|
||||
### 当 PR 添加指定 Label 时触发审查
|
||||
|
||||
如果你不希望创建 PR 时自动审查可以选择通过添加标签时触发代码审查,比如创建如下 Workflow:
|
||||
|
||||
```yaml
|
||||
name: Code Review
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- labeled # Triggers when a label is added to the PR
|
||||
|
||||
# fix: GraphQL: Resource not accessible by integration (addComment) error
|
||||
permissions:
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
setup-deepseek-review:
|
||||
runs-on: ubuntu-latest
|
||||
name: Code Review
|
||||
# Make sure the code review happens only when the PR has the label 'ai review'
|
||||
if: contains(github.event.pull_request.labels.*.name, 'ai review')
|
||||
steps:
|
||||
- name: Deepseek Code Review
|
||||
uses: hustcer/deepseek-review@v1
|
||||
with:
|
||||
chat-token: ${{ secrets.CHAT_TOKEN }}
|
||||
```
|
||||
|
||||
如此以来当 PR 创建的时候不会自动触发 Deepseek 代码审查,只有你手工添加 `ai review` 标签的时候才会触发审查。
|
||||
|
||||
## 输入参数
|
||||
|
||||
| 名称 | 类型 | 描述 |
|
||||
| -------------- | ------ | -------------------------------------------------------------- |
|
||||
| chat-token | String | 必填,Deepseek API Token |
|
||||
| model | String | 可选,配置代码审核选用的模型,默认为 `deepseek-chat` |
|
||||
| model | String | 可选,配置代码审查选用的模型,默认为 `deepseek-chat` |
|
||||
| base-url | String | 可选,Deepseek API Base URL, 默认为 `https://api.deepseek.com` |
|
||||
| max-length | Int | 可选,待审核内容的最大 Unicode 长度, 默认 `0` 表示没有限制,超过非零值则跳过审核 |
|
||||
| sys-prompt | String | 可选,系统 Prompt 对应入参中的 `$sys_prompt`, 默认值见后文注释 |
|
||||
| user-prompt | String | 可选,用户 Prompt 对应入参中的 `$user_prompt`, 默认值见后文注释 |
|
||||
| max-length | Int | 可选,待审查内容的最大 Unicode 长度, 默认 `0` 表示没有限制,超过非零值则跳过审查 |
|
||||
| sys-prompt | String | 可选,系统提示词对应入参中的 `$sys_prompt`, 默认值见后文注释 |
|
||||
| user-prompt | String | 可选,用户提示词对应入参中的 `$user_prompt`, 默认值见后文注释 |
|
||||
| include-patterns | String | 可选,代码审查中要包含的以逗号分隔的文件模式,无默认值 |
|
||||
| exclude-patterns | String | 可选,代码审查中要排除的以逗号分隔的文件模式,默认值为 `pnpm-lock.yaml,package-lock.json,*.lock` |
|
||||
| github-token | String | 可选,用于访问 API 进行 PR 管理的 GitHub Token,默认为 `${{ github.token }}` |
|
||||
|
||||
Deepseek 接口调用入参:
|
||||
@@ -77,14 +127,19 @@ Deepseek 接口调用入参:
|
||||
}
|
||||
```
|
||||
|
||||
## 本地代码审核
|
||||
> [!NOTE]
|
||||
>
|
||||
> 可以通过提示词的语言来控制代码审查结果的语言,当前默认的提示词语言是英文的,
|
||||
> 当你使用中文提示词的时候生成的代码审查结果就是中文的
|
||||
|
||||
## 本地代码审查
|
||||
|
||||
### 依赖工具
|
||||
|
||||
在本地进行代码审核,支持 `macOS`, `Ubuntu` & `Windows` 不过需要安装以下工具:
|
||||
在本地进行代码审查,支持 `macOS`, `Ubuntu` & `Windows` 不过需要安装以下工具:
|
||||
|
||||
- [`Nushell`](https://www.nushell.sh/book/installation.html) & [`Just`](https://just.systems/man/en/packages.html), 建议安装最新版本
|
||||
- 如果你需要在本地审核 GitHub PRs 还需要安装 [`gh`](https://cli.github.com/)
|
||||
- 如果你需要在本地审查 GitHub PRs 还需要安装 [`gh`](https://cli.github.com/)
|
||||
- 接下来只需要把本仓库代码克隆到本地,然后进入仓库目录执行 `just code-review -h` 或者 `just cr -h` 即可看到类似如下输出:
|
||||
|
||||
```console
|
||||
@@ -97,14 +152,16 @@ Flags:
|
||||
-d, --debug: Debug mode
|
||||
-r, --repo <string>: GitHub repository name, e.g. hustcer/deepseek-review
|
||||
-n, --pr-number <string>: GitHub PR number
|
||||
--gh-token <string>: Your GitHub token, fallback to GITHUB_TOKEN env var
|
||||
-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
|
||||
-l, --max-length <int>: Maximum length of the content for review, 0 means no limit.
|
||||
-m, --model <string>: Model name, deepseek-chat by default (default: 'deepseek-chat')
|
||||
--base-url <string> (default: 'https://api.deepseek.com')
|
||||
-s, --sys-prompt <string> (default: '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.')
|
||||
-u, --user-prompt <string> (default: 'Please review the following code changes:')
|
||||
-b, --base-url <string> (default: 'https://api.deepseek.com')
|
||||
-s, --sys-prompt <string>: Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
-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
|
||||
-h, --help: Display the help message for this command
|
||||
|
||||
Parameters:
|
||||
@@ -114,20 +171,25 @@ Parameters:
|
||||
|
||||
### 环境配置
|
||||
|
||||
在本地进行代码审核需要先修改配置文件,仓库里已经有了 `.env.example` 配置文件示例,将其拷贝到 `.env` 然后根据自己的实际情况进行修改即可。
|
||||
在本地进行代码审查需要先修改配置文件,仓库里已经有了 `.env.example` 配置文件示例,将其拷贝到 `.env` 然后根据自己的实际情况进行修改即可。
|
||||
|
||||
> [!WARNING]
|
||||
>
|
||||
> `.env` 配置文件仅在本地使用,在 GitHub Workflow 里面不会使用,里面的敏感信息请
|
||||
> 妥善保存,不要提交到代码仓库里面
|
||||
|
||||
### 使用举例
|
||||
|
||||
```sh
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff` 修改内容进行代码审核
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff` 修改内容进行代码审查
|
||||
just cr
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff f536acc` 修改内容进行代码审核
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff f536acc` 修改内容进行代码审查
|
||||
just cr --diff-from f536acc
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff f536acc 0dd0eb5` 修改内容进行代码审核
|
||||
# 对本地 DEFAULT_LOCAL_REPO 仓库 `git diff f536acc 0dd0eb5` 修改内容进行代码审查
|
||||
just cr --diff-from f536acc --diff-to 0dd0eb5
|
||||
# 对远程 DEFAULT_GITHUB_REPO 仓库编号为 31 的 PR 进行代码审核
|
||||
# 对远程 DEFAULT_GITHUB_REPO 仓库编号为 31 的 PR 进行代码审查
|
||||
just cr --pr-number 31
|
||||
# 对远程 hustcer/deepseek-review 仓库编号为 31 的 PR 进行代码审核
|
||||
# 对远程 hustcer/deepseek-review 仓库编号为 31 的 PR 进行代码审查
|
||||
just cr --pr-number 31 --repo hustcer/deepseek-review
|
||||
```
|
||||
|
||||
|
||||
11
action.yaml
11
action.yaml
@@ -38,6 +38,13 @@ inputs:
|
||||
required: false
|
||||
default: 'Please review the following code changes'
|
||||
description: 'The user prompt for deepseek API.'
|
||||
include-patterns:
|
||||
required: false
|
||||
description: 'The comma separated file patterns to include in the code review.'
|
||||
exclude-patterns:
|
||||
required: false
|
||||
default: 'pnpm-lock.yaml,package-lock.json,*.lock'
|
||||
description: 'The comma separated file patterns to exclude in the code review.'
|
||||
github-token:
|
||||
required: false
|
||||
default: '${{ github.token }}'
|
||||
@@ -64,6 +71,8 @@ runs:
|
||||
let sysPrompt = '${{ inputs.sys-prompt }}'
|
||||
let userPrompt = '${{ inputs.user-prompt }}'
|
||||
let pr = '${{ github.event.pull_request.number }}'
|
||||
let includePatterns = '${{ inputs.include-patterns }}'
|
||||
let excludePatterns = '${{ inputs.exclude-patterns }}'
|
||||
let maxLength = try { '${{ inputs.max-length }}' | into int } catch { 0 }
|
||||
(deepseek-review $token
|
||||
--model $model
|
||||
@@ -74,5 +83,7 @@ runs:
|
||||
--max-length $maxLength
|
||||
--sys-prompt $sysPrompt
|
||||
--user-prompt $userPrompt
|
||||
--include $includePatterns
|
||||
--exclude $excludePatterns
|
||||
)
|
||||
|
||||
|
||||
@@ -14,4 +14,6 @@ words:
|
||||
- lefthook
|
||||
- deepseek
|
||||
- linewise
|
||||
- Subshell
|
||||
- subshells
|
||||
ignorePaths:
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "deepseek-review",
|
||||
"version": "1.3.0",
|
||||
"actionVer": "v1.3",
|
||||
"version": "1.5.0",
|
||||
"actionVer": "v1.5",
|
||||
"author": "hustcer",
|
||||
"license": "MIT",
|
||||
"github": "https://github.com/hustcer/deepseek-review",
|
||||
|
||||
100
nu/review.nu
100
nu/review.nu
@@ -2,11 +2,12 @@
|
||||
# Author: hustcer
|
||||
# Created: 2025/01/29 13:02:15
|
||||
# TODO:
|
||||
# [√] Deepseek code review for GitHub PRs
|
||||
# [√] Deepseek code review for local commit changes
|
||||
# [√] Debug mode
|
||||
# [√] Output token usage info
|
||||
# [ ] Add more action outputs
|
||||
# [√] Deepseek code review for GitHub PRs
|
||||
# [√] Deepseek code review for local commit changes
|
||||
# [√] Debug mode
|
||||
# [√] Output token usage info
|
||||
# [√] Perform CR for changes that either include or exclude specific files
|
||||
# [ ] Add more action outputs
|
||||
# Description: A script to do code review by deepseek
|
||||
# Env vars:
|
||||
# GITHUB_TOKEN: Your GitHub API token
|
||||
@@ -15,9 +16,9 @@
|
||||
# SYSTEM_PROMPT: System prompt message
|
||||
# USER_PROMPT: User prompt message
|
||||
# Usage:
|
||||
# 1. Local: just cr
|
||||
# 2. Local: just cr -f HEAD~1 --debug
|
||||
#
|
||||
# - Local Repo Review: just cr
|
||||
# - Local Repo Review: just cr -f HEAD~1 --debug
|
||||
# - Local PR Review: just cr -r hustcer/deepseek-review -n 32
|
||||
|
||||
# Commonly used exit codes
|
||||
const ECODE = {
|
||||
@@ -47,14 +48,16 @@ export def --env deepseek-review [
|
||||
--debug(-d), # Debug mode
|
||||
--repo(-r): string, # GitHub repository name, e.g. hustcer/deepseek-review
|
||||
--pr-number(-n): string, # GitHub PR number
|
||||
--gh-token: string, # Your GitHub token, fallback to GITHUB_TOKEN env var
|
||||
--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
|
||||
--max-length(-l): int, # Maximum length of the content for review, 0 means no limit.
|
||||
--model(-m): string = $DEFAULT_OPTIONS.MODEL, # Model name, deepseek-chat by default
|
||||
--base-url: string = $DEFAULT_OPTIONS.BASE_URL,
|
||||
--sys-prompt(-s): string = $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
--user-prompt(-u): string = $DEFAULT_OPTIONS.USER_PROMPT,
|
||||
--base-url(-b): string = $DEFAULT_OPTIONS.BASE_URL,
|
||||
--sys-prompt(-s): string # Default to $DEFAULT_OPTIONS.SYS_PROMPT,
|
||||
--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
|
||||
]: nothing -> nothing {
|
||||
$env.config.table.mode = 'psql'
|
||||
let is_action = ($env.GITHUB_ACTIONS? == 'true')
|
||||
@@ -66,6 +69,8 @@ export def --env deepseek-review [
|
||||
let max_length = $max_length | default ($env.MAX_LENGTH? | default 0 | into int)
|
||||
let setting = {
|
||||
repo: $repo,
|
||||
include: $include,
|
||||
exclude: $exclude,
|
||||
diff_to: $diff_to,
|
||||
diff_from: $diff_from,
|
||||
pr_number: $pr_number,
|
||||
@@ -89,22 +94,26 @@ export def --env deepseek-review [
|
||||
print $hint; print -n (char nl)
|
||||
if ($pr_number | is-empty) { $setting | compact-record | reject repo | print }
|
||||
|
||||
let diff_content = get-diff --pr-number $pr_number --repo $repo --diff-to $diff_to --diff-from $diff_from
|
||||
let length = $diff_content | str stats | get unicode-width
|
||||
let content = (
|
||||
get-diff --pr-number $pr_number --repo $repo --diff-to $diff_to
|
||||
--diff-from $diff_from --include $include --exclude $exclude)
|
||||
let length = $content | str stats | get unicode-width
|
||||
if ($max_length != 0) and ($length > $max_length) {
|
||||
print $'(char nl)(ansi r)The content length ($length) exceeds the maximum limit ($max_length), review skipped.(ansi reset)'
|
||||
exit $ECODE.SUCCESS
|
||||
}
|
||||
print $'Review content length: (ansi g)($length)(ansi reset), current max length: (ansi g)($max_length)(ansi reset)'
|
||||
let sys_prompt = $sys_prompt | default (load-prompt-from-env SYSTEM_PROMPT) | default $DEFAULT_OPTIONS.SYS_PROMPT
|
||||
let user_prompt = $user_prompt | default (load-prompt-from-env USER_PROMPT) | default $DEFAULT_OPTIONS.USER_PROMPT
|
||||
let payload = {
|
||||
model: $model,
|
||||
stream: false,
|
||||
messages: [
|
||||
{ role: 'system', content: $sys_prompt },
|
||||
{ role: 'user', content: $"($user_prompt):\n($diff_content)" }
|
||||
{ role: 'user', content: $"($user_prompt):\n($content)" }
|
||||
]
|
||||
}
|
||||
if $debug { print $'Code Changes:'; hr-line; print $diff_content }
|
||||
if $debug { print $'Code Changes:'; hr-line; print $content }
|
||||
print $'(char nl)(ansi g)Waiting for response from Deepseek ...(ansi reset)'
|
||||
let response = http post -e -H $header -t application/json $url $payload
|
||||
if ($response | is-empty) {
|
||||
@@ -127,12 +136,29 @@ export def --env deepseek-review [
|
||||
$response.usage | table -e | print
|
||||
}
|
||||
|
||||
# Load the prompt content from the specified env var
|
||||
export def load-prompt-from-env [
|
||||
prompt_key: string,
|
||||
] {
|
||||
let prompt = $env | get -i $prompt_key | default ''
|
||||
if $prompt =~ '.yaml' {
|
||||
let key = $prompt | split row : | last
|
||||
let path = $prompt | split row : | first
|
||||
try { open $path | get -i $key } catch {
|
||||
print $'(ansi r)Failed to load the prompt content from ($path), please check it again.(ansi reset)'
|
||||
exit $ECODE.INVALID_PARAMETER
|
||||
}
|
||||
} else { $prompt }
|
||||
}
|
||||
|
||||
# Get the diff content from GitHub PR or local git changes
|
||||
export def get-diff [
|
||||
--repo: string, # GitHub repository name
|
||||
--pr-number: string, # GitHub PR number
|
||||
--diff-to: string, # Diff to git ref
|
||||
--diff-from: string, # Diff from git ref
|
||||
--include: string, # Comma separated file patterns to include in the code review
|
||||
--exclude: string, # Comma separated file patterns to exclude in the code review
|
||||
] {
|
||||
let local_repo = $env.DEFAULT_LOCAL_REPO? | default (pwd)
|
||||
if not ($local_repo | path exists) {
|
||||
@@ -140,7 +166,7 @@ export def get-diff [
|
||||
exit $ECODE.CONDITION_NOT_SATISFIED
|
||||
}
|
||||
cd $local_repo
|
||||
let diff_content = if ($pr_number | is-not-empty) {
|
||||
mut content = if ($pr_number | is-not-empty) {
|
||||
if ($repo | is-empty) {
|
||||
print $'(ansi r)Please provide the GitHub repository name by `--repo` option.(ansi reset)'
|
||||
exit $ECODE.INVALID_PARAMETER
|
||||
@@ -167,10 +193,18 @@ export def get-diff [
|
||||
exit $ECODE.CONDITION_NOT_SATISFIED
|
||||
} else { git diff }
|
||||
|
||||
if ($diff_content | is-empty) {
|
||||
if ($content | is-empty) {
|
||||
print $'(ansi g)Nothing to review.(ansi reset)'; exit $ECODE.SUCCESS
|
||||
}
|
||||
$diff_content
|
||||
if ($include | is-not-empty) {
|
||||
let patterns = $include | split row ','
|
||||
$content = $content | awk (generate-include-regex $patterns)
|
||||
}
|
||||
if ($exclude | is-not-empty) {
|
||||
let patterns = $exclude | split row ','
|
||||
$content = $content | awk (generate-exclude-regex $patterns)
|
||||
}
|
||||
$content
|
||||
}
|
||||
|
||||
# Compact the record by removing empty columns
|
||||
@@ -197,8 +231,7 @@ export def git-check [
|
||||
}
|
||||
# If we don't need repo check just quit now
|
||||
if ($check_repo != 0) {
|
||||
let checkRepo = (do -i { git rev-parse --is-inside-work-tree } | complete)
|
||||
if not ($checkRepo.stdout =~ 'true') {
|
||||
if not (is-repo) {
|
||||
print $'Current directory is (ansi r)NOT(ansi reset) a git repo, bye...(char nl)'
|
||||
exit $ECODE.CONDITION_NOT_SATISFIED
|
||||
}
|
||||
@@ -206,12 +239,21 @@ export def git-check [
|
||||
true
|
||||
}
|
||||
|
||||
# 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
|
||||
} catch {
|
||||
({ stdout: 'false' })
|
||||
}
|
||||
if ($checkRepo.stdout =~ 'true') { true } else { false }
|
||||
}
|
||||
|
||||
# Check if a git repo has the specified ref: could be a branch or tag, etc.
|
||||
export def has-ref [
|
||||
ref: string # The git ref to check
|
||||
] {
|
||||
let checkRepo = (do -i { git rev-parse --is-inside-work-tree } | complete)
|
||||
if not ($checkRepo.stdout =~ 'true') { return false }
|
||||
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)
|
||||
if ($parse.stdout | is-empty) { false } else { true }
|
||||
@@ -235,4 +277,16 @@ export def hr-line [
|
||||
if $blank_line { char nl }
|
||||
}
|
||||
|
||||
# Generate the awk include regex pattern string for the specified patterns
|
||||
export def generate-include-regex [patterns: list<string>] {
|
||||
let pattern = $patterns | each {|pat| $pat | str replace '/' '\/' } | str join '|'
|
||||
$"/^diff --git/{p=/^diff --git a\\/($pattern)/}p"
|
||||
}
|
||||
|
||||
# Generate the awk exclude regex pattern string for the specified patterns
|
||||
def generate-exclude-regex [patterns: list<string>] {
|
||||
let pattern = $patterns | each {|pat| $pat | str replace '/' '\/' } | str join '|'
|
||||
$"/^diff --git/{p=/^diff --git a\\/($pattern)/}!p"
|
||||
}
|
||||
|
||||
alias main = deepseek-review
|
||||
|
||||
Reference in New Issue
Block a user