-
-
Notifications
You must be signed in to change notification settings - Fork 90
chore: add sync vitest docs script #839
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
✅ Deploy Preview for cn-vitest ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces an automated synchronization system to keep the Chinese translation documentation (docs-cn) in sync with the upstream Vitest repository. The automation includes a Node.js script that handles git operations, file synchronization, and PR creation, along with a GitHub Actions workflow to trigger the sync process.
Key Changes
- Added a comprehensive sync script that tracks changes between upstream Vitest docs and the translation repository using git tags
- Implemented GitHub Actions workflow for manual synchronization triggers
- Added required npm dependencies (@octokit/rest, shelljs, colors) for API interactions and shell operations
Reviewed changes
Copilot reviewed 3 out of 4 changed files in this pull request and generated 13 comments.
| File | Description |
|---|---|
| scripts/sync-vitest-docs.mjs | Main synchronization script handling git operations, file tracking, and automated PR creation |
| .github/workflows/sync-docs.yml | GitHub Actions workflow configuration for triggering the sync process |
| package.json | Added sync script command and new dependencies |
| pnpm-lock.yaml | Lock file updates for new dependencies (@octokit/rest, shelljs, colors) |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| - Modified files: ${actualModifiedFiles.length} | ||
| - Deleted files: ${actualDeletedFiles.length}` | ||
|
|
||
| shell.exec(`git commit -m "${commitMessage}"`) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The commit message construction uses double quotes with template variables, which could break if the variables contain double quotes. This should use a template literal with backticks or proper escaping:
shell.exec(`git commit -m ${JSON.stringify(commitMessage)}`)or use a safer approach with git's -F option to read from a file.
| - name: Run sync script | ||
| env: | ||
| GITHUB_USERNAME: elonehoo |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded username "elonehoo" should be derived from the GitHub Actions context instead of being hardcoded. Use ${{ github.actor }} to get the user who triggered the workflow:
GITHUB_USERNAME: ${{ github.actor }}| GITHUB_USERNAME: elonehoo | |
| GITHUB_USERNAME: ${{ github.actor }} |
| if (!shell.test('-d', tempDir)) { | ||
| shell.mkdir('-p', tempDir) | ||
| } | ||
| shell.cd(tempDir) | ||
|
|
||
| // 克隆目标仓库 (docs-cn) - 包含完整历史 | ||
| console.log(`\n📦 正在克隆目标仓库 ${targetRepo}...`) | ||
| if (shell.test('-d', targetRepo)) { | ||
| shell.rm('-rf', targetRepo) | ||
| } | ||
| const cloneResult = shell.exec(`git clone ${targetUrl} ${targetRepo}`) | ||
| if (cloneResult.code !== 0) { | ||
| console.error('❌ 克隆目标仓库失败!') | ||
| process.exit(1) | ||
| } | ||
|
|
||
| // 进入目标仓库 | ||
| shell.cd(path.join(tempDir, targetRepo)) | ||
|
|
||
| // 配置 git | ||
| shell.exec(`git config user.name "${username}"`) | ||
| shell.exec(`git config user.email "${email}"`) | ||
|
|
||
| // 添加上游仓库作为 remote | ||
| console.log(`\n🔗 添加上游仓库 ${sourceRepo} 作为 remote...`) | ||
| shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`) | ||
|
|
||
| // 获取上游仓库的更新(获取完整历史以便比较) | ||
| console.log(`\n📥 正在获取上游仓库更新...`) | ||
| const fetchResult = shell.exec(`git fetch upstream ${sourceBranch}`) | ||
| if (fetchResult.code !== 0) { | ||
| console.error('❌ 获取上游仓库失败!') | ||
| process.exit(1) | ||
| } | ||
|
|
||
| // 获取上游最新 commit hash | ||
| const upstreamHash = shell.exec(`git rev-parse upstream/${sourceBranch}`).stdout.trim() | ||
| const shortHash = upstreamHash.substring(0, 8) | ||
|
|
||
| // 检查是否已经同步过(通过 tag 记录上次同步的上游 commit) | ||
| const lastSyncTag = shell.exec('git tag -l "synced-*" --sort=-creatordate | head -1').stdout.trim() | ||
| const lastSyncHash = lastSyncTag ? lastSyncTag.replace('synced-', '') : '' | ||
|
|
||
| console.log(`\n📋 同步状态:`) | ||
| console.log(` 上游最新: ${shortHash}`) | ||
| console.log(` 上次同步: ${lastSyncHash || '无记录(首次同步)'}`) | ||
|
|
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The error handling exits the process before cleanup occurs. If any git operation fails, the temporary directory is not cleaned up. Consider wrapping the main logic in a try-finally block or using process.on('exit') to ensure cleanup:
try {
// main logic
} finally {
shell.cd(originalCwd)
if (shell.test('-d', tempDir)) {
shell.rm('-rf', tempDir)
}
}| if (!shell.test('-d', tempDir)) { | |
| shell.mkdir('-p', tempDir) | |
| } | |
| shell.cd(tempDir) | |
| // 克隆目标仓库 (docs-cn) - 包含完整历史 | |
| console.log(`\n📦 正在克隆目标仓库 ${targetRepo}...`) | |
| if (shell.test('-d', targetRepo)) { | |
| shell.rm('-rf', targetRepo) | |
| } | |
| const cloneResult = shell.exec(`git clone ${targetUrl} ${targetRepo}`) | |
| if (cloneResult.code !== 0) { | |
| console.error('❌ 克隆目标仓库失败!') | |
| process.exit(1) | |
| } | |
| // 进入目标仓库 | |
| shell.cd(path.join(tempDir, targetRepo)) | |
| // 配置 git | |
| shell.exec(`git config user.name "${username}"`) | |
| shell.exec(`git config user.email "${email}"`) | |
| // 添加上游仓库作为 remote | |
| console.log(`\n🔗 添加上游仓库 ${sourceRepo} 作为 remote...`) | |
| shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`) | |
| // 获取上游仓库的更新(获取完整历史以便比较) | |
| console.log(`\n📥 正在获取上游仓库更新...`) | |
| const fetchResult = shell.exec(`git fetch upstream ${sourceBranch}`) | |
| if (fetchResult.code !== 0) { | |
| console.error('❌ 获取上游仓库失败!') | |
| process.exit(1) | |
| } | |
| // 获取上游最新 commit hash | |
| const upstreamHash = shell.exec(`git rev-parse upstream/${sourceBranch}`).stdout.trim() | |
| const shortHash = upstreamHash.substring(0, 8) | |
| // 检查是否已经同步过(通过 tag 记录上次同步的上游 commit) | |
| const lastSyncTag = shell.exec('git tag -l "synced-*" --sort=-creatordate | head -1').stdout.trim() | |
| const lastSyncHash = lastSyncTag ? lastSyncTag.replace('synced-', '') : '' | |
| console.log(`\n📋 同步状态:`) | |
| console.log(` 上游最新: ${shortHash}`) | |
| console.log(` 上次同步: ${lastSyncHash || '无记录(首次同步)'}`) | |
| try { | |
| if (!shell.test('-d', tempDir)) { | |
| shell.mkdir('-p', tempDir) | |
| } | |
| shell.cd(tempDir) | |
| // 克隆目标仓库 (docs-cn) - 包含完整历史 | |
| console.log(`\n📦 正在克隆目标仓库 ${targetRepo}...`) | |
| if (shell.test('-d', targetRepo)) { | |
| shell.rm('-rf', targetRepo) | |
| } | |
| const cloneResult = shell.exec(`git clone ${targetUrl} ${targetRepo}`) | |
| if (cloneResult.code !== 0) { | |
| console.error('❌ 克隆目标仓库失败!') | |
| process.exit(1) | |
| } | |
| // 进入目标仓库 | |
| shell.cd(path.join(tempDir, targetRepo)) | |
| // 配置 git | |
| shell.exec(`git config user.name "${username}"`) | |
| shell.exec(`git config user.email "${email}"`) | |
| // 添加上游仓库作为 remote | |
| console.log(`\n🔗 添加上游仓库 ${sourceRepo} 作为 remote...`) | |
| shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`) | |
| // 获取上游仓库的更新(获取完整历史以便比较) | |
| console.log(`\n📥 正在获取上游仓库更新...`) | |
| const fetchResult = shell.exec(`git fetch upstream ${sourceBranch}`) | |
| if (fetchResult.code !== 0) { | |
| console.error('❌ 获取上游仓库失败!') | |
| process.exit(1) | |
| } | |
| // 获取上游最新 commit hash | |
| const upstreamHash = shell.exec(`git rev-parse upstream/${sourceBranch}`).stdout.trim() | |
| const shortHash = upstreamHash.substring(0, 8) | |
| // 检查是否已经同步过(通过 tag 记录上次同步的上游 commit) | |
| const lastSyncTag = shell.exec('git tag -l "synced-*" --sort=-creatordate | head -1').stdout.trim() | |
| const lastSyncHash = lastSyncTag ? lastSyncTag.replace('synced-', '') : '' | |
| console.log(`\n📋 同步状态:`) | |
| console.log(` 上游最新: ${shortHash}`) | |
| console.log(` 上次同步: ${lastSyncHash || '无记录(首次同步)'}`) | |
| // ... rest of main logic ... | |
| } finally { | |
| shell.cd(originalCwd) | |
| if (shell.test('-d', tempDir)) { | |
| shell.rm('-rf', tempDir) | |
| } | |
| } |
| const username = process.argv[2] || process.env.GITHUB_USERNAME | ||
| const token = process.argv[3] || process.env.GITHUB_TOKEN | ||
| const email = process.argv[4] || process.env.GITHUB_EMAIL | ||
|
|
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missing input validation for required parameters. The script should validate that username, token, and email are provided before proceeding:
if (!username || !token || !email) {
console.error('❌ Missing required parameters: GITHUB_USERNAME, GITHUB_TOKEN, and GITHUB_EMAIL must be provided')
process.exit(1)
}| // 参数校验 | |
| if (!username || !token || !email) { | |
| console.error('❌ Missing required parameters: GITHUB_USERNAME, GITHUB_TOKEN, and GITHUB_EMAIL must be provided') | |
| process.exit(1) | |
| } |
| "pathe": "^2.0.3", | ||
| "shelljs": "^0.8.5", | ||
| "@octokit/rest": "^21.0.2", | ||
| "colors": "^1.4.0", |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The colors package is imported in package.json but never used in the sync script. This dependency appears to be unnecessary and should be removed unless there's a specific plan to use it for terminal output formatting.
| "colors": "^1.4.0", |
|
|
||
| // 添加上游仓库作为 remote | ||
| console.log(`\n🔗 添加上游仓库 ${sourceRepo} 作为 remote...`) | ||
| shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error output is suppressed with 2>/dev/null which makes debugging difficult if the command fails. Consider either logging the error or checking the result:
const remoteResult = shell.exec(`git remote add upstream ${sourceUrl}`)
if (remoteResult.code !== 0) {
shell.exec(`git remote set-url upstream ${sourceUrl}`)
}| shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`) | |
| const remoteResult = shell.exec(`git remote add upstream ${sourceUrl}`); | |
| if (remoteResult.code !== 0) { | |
| console.warn(`⚠️ 添加 upstream remote 失败: ${remoteResult.stderr.trim() || remoteResult.stdout.trim()}`); | |
| const setUrlResult = shell.exec(`git remote set-url upstream ${sourceUrl}`); | |
| if (setUrlResult.code !== 0) { | |
| console.error(`❌ 设置 upstream remote URL 失败: ${setUrlResult.stderr.trim() || setUrlResult.stdout.trim()}`); | |
| process.exit(1); | |
| } | |
| } |
| env: | ||
| GITHUB_USERNAME: elonehoo | ||
| GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| GITHUB_EMAIL: [email protected] |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The hardcoded email "[email protected]" should be dynamically generated based on the GitHub username or use GitHub Actions context:
GITHUB_EMAIL: ${{ github.actor }}@users.noreply.github.com| GITHUB_EMAIL: elonehoo@users.noreply.github.com | |
| GITHUB_EMAIL: ${{ github.actor }}@users.noreply.github.com |
| if (files.length === 0) | ||
| return '_无_' |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The format of the formatFileList function has inconsistent line breaks. Line 305 has the opening brace on a new line which breaks the expected formatting pattern. This should be:
function formatFileList(files, maxShow = 15) {
if (files.length === 0) return '_无_'| if (files.length === 0) | |
| return '_无_' | |
| if (files.length === 0) return '_无_' |
| const targetBranch = 'dev' // docs-cn 仓库的默认分支 | ||
|
|
||
| const sourceUrl = `https://github.com/${owner}/${sourceRepo}.git` | ||
| const targetUrl = `https://${username}:${token}@github.com/${owner}/${targetRepo}.git` |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The authentication token is being embedded directly in the URL which will be visible in shell output and logs. Consider using git credential helpers or environment variables to avoid exposing the token in command execution traces. For example:
shell.exec(`git config credential.helper store`)
// Then use URL without token embedded| const actualNewFiles = [] | ||
| const actualModifiedFiles = [] | ||
| const actualDeletedFiles = [] | ||
| const skippedFiles = [] // 跳过的文件(本地有修改) |
Copilot
AI
Dec 9, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused variable skippedFiles.
| const skippedFiles = [] // 跳过的文件(本地有修改) |
可以看看 #838 ,看看是不是符合我们的想象
在提交PR之前,请确保您执行以下操作:
fixes #123)。描述
附加上下文