Skip to content

Conversation

@elonehoo
Copy link
Member

@elonehoo elonehoo commented Dec 9, 2025

可以看看 #838 ,看看是不是符合我们的想象

在提交PR之前,请确保您执行以下操作:

  • 曾阅读过翻译须知
  • 检查是否已经有PR以同样的方式解决问题,以避免创建重复。
  • 在此PR中描述正在解决的问题,或引用它解决的问题(例如:fixes #123)。

描述

附加上下文

Copilot AI review requested due to automatic review settings December 9, 2025 15:40
@netlify
Copy link

netlify bot commented Dec 9, 2025

Deploy Preview for cn-vitest ready!

Name Link
🔨 Latest commit cc05fa3
🔍 Latest deploy log https://app.netlify.com/projects/cn-vitest/deploys/693842d402b2d700089cb99d
😎 Deploy Preview https://deploy-preview-839--cn-vitest.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link

Copilot AI left a 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}"`)
Copy link

Copilot AI Dec 9, 2025

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.

Copilot uses AI. Check for mistakes.
- name: Run sync script
env:
GITHUB_USERNAME: elonehoo
Copy link

Copilot AI Dec 9, 2025

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 }}
Suggested change
GITHUB_USERNAME: elonehoo
GITHUB_USERNAME: ${{ github.actor }}

Copilot uses AI. Check for mistakes.
Comment on lines +29 to +75
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 || '无记录(首次同步)'}`)

Copy link

Copilot AI Dec 9, 2025

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)
  }
}
Suggested change
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)
}
}

Copilot uses AI. Check for mistakes.
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

Copy link

Copilot AI Dec 9, 2025

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)
}
Suggested change
// 参数校验
if (!username || !token || !email) {
console.error('❌ Missing required parameters: GITHUB_USERNAME, GITHUB_TOKEN, and GITHUB_EMAIL must be provided')
process.exit(1)
}

Copilot uses AI. Check for mistakes.
"pathe": "^2.0.3",
"shelljs": "^0.8.5",
"@octokit/rest": "^21.0.2",
"colors": "^1.4.0",
Copy link

Copilot AI Dec 9, 2025

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.

Suggested change
"colors": "^1.4.0",

Copilot uses AI. Check for mistakes.

// 添加上游仓库作为 remote
console.log(`\n🔗 添加上游仓库 ${sourceRepo} 作为 remote...`)
shell.exec(`git remote add upstream ${sourceUrl} 2>/dev/null || git remote set-url upstream ${sourceUrl}`)
Copy link

Copilot AI Dec 9, 2025

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}`)
}
Suggested change
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);
}
}

Copilot uses AI. Check for mistakes.
env:
GITHUB_USERNAME: elonehoo
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_EMAIL: [email protected]
Copy link

Copilot AI Dec 9, 2025

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
Suggested change
GITHUB_EMAIL: elonehoo@users.noreply.github.com
GITHUB_EMAIL: ${{ github.actor }}@users.noreply.github.com

Copilot uses AI. Check for mistakes.
Comment on lines +305 to +306
if (files.length === 0)
return '_无_'
Copy link

Copilot AI Dec 9, 2025

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 '_无_'
Suggested change
if (files.length === 0)
return '_无_'
if (files.length === 0) return '_无_'

Copilot uses AI. Check for mistakes.
const targetBranch = 'dev' // docs-cn 仓库的默认分支

const sourceUrl = `https://github.com/${owner}/${sourceRepo}.git`
const targetUrl = `https://${username}:${token}@github.com/${owner}/${targetRepo}.git`
Copy link

Copilot AI Dec 9, 2025

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

Copilot uses AI. Check for mistakes.
const actualNewFiles = []
const actualModifiedFiles = []
const actualDeletedFiles = []
const skippedFiles = [] // 跳过的文件(本地有修改)
Copy link

Copilot AI Dec 9, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused variable skippedFiles.

Suggested change
const skippedFiles = [] // 跳过的文件(本地有修改)

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants