fix(jenkins): reuse stdb scm checkout
This commit is contained in:
@@ -20,8 +20,9 @@
|
|||||||
|
|
||||||
- 背景:`Genarrative-Stdb-Module-Build` 在 Windows Jenkins 本地环境里调用裸 `powershell` step 时触发 `CreateProcess error=5, 拒绝访问`,而 `powershell.exe` 本体与 workspace ACL 都正常。
|
- 背景:`Genarrative-Stdb-Module-Build` 在 Windows Jenkins 本地环境里调用裸 `powershell` step 时触发 `CreateProcess error=5, 拒绝访问`,而 `powershell.exe` 本体与 workspace ACL 都正常。
|
||||||
- 决策:Windows Jenkins 上凡是需要执行 PowerShell 逻辑的流水线,优先通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File ...`,不要再依赖 Jenkins `powershell` step 的隐式启动器。
|
- 决策:Windows Jenkins 上凡是需要执行 PowerShell 逻辑的流水线,优先通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File ...`,不要再依赖 Jenkins `powershell` step 的隐式启动器。
|
||||||
|
- 追加决策:`Genarrative-Stdb-Module-Build` 的 Checkout 逻辑应复用 Jenkins GitSCM 已完成的工作区状态。`COMMIT_HASH` 为空或已与当前 `HEAD` 一致时,不再额外执行 `git clean` / `git checkout`;只有需要切到指定且不同的 commit 时才补 fetch、校验和切换,避免在 Windows workspace 里二次清理触发权限拒绝。
|
||||||
- 影响范围:`jenkins/Jenkinsfile.production-stdb-module-build` 及后续所有同类 Windows 构建流水线。
|
- 影响范围:`jenkins/Jenkinsfile.production-stdb-module-build` 及后续所有同类 Windows 构建流水线。
|
||||||
- 验证方式:Jenkins 日志中应能看到 `[jenkins-powershell] user:` 和 `[jenkins-powershell] exe:`,并继续执行 checkout / build;不再停在 `PipelineNodeTreeScanner... Cannot run program "powershell"`。
|
- 验证方式:Jenkins 日志中应能看到 `[jenkins-powershell] user:` 和 `[jenkins-powershell] exe:`,Checkout 阶段会打印当前 `HEAD` 与请求 commit,并在 `COMMIT_HASH` 为空或一致时直接继续;不再停在 `PipelineNodeTreeScanner... Cannot run program "powershell"` 或重复 `git clean` 的退出码 5。
|
||||||
- 关联文档:`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`、`.hermes/shared-memory/pitfalls.md`。
|
- 关联文档:`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`、`.hermes/shared-memory/pitfalls.md`。
|
||||||
|
|
||||||
## 2026-05-17 容器化方案只作为隔离压测与预发模拟路径
|
## 2026-05-17 容器化方案只作为隔离压测与预发模拟路径
|
||||||
|
|||||||
@@ -947,7 +947,7 @@
|
|||||||
## Windows Jenkins `powershell` step 在 Stdb module 构建里曾触发 CreateProcess error=5
|
## Windows Jenkins `powershell` step 在 Stdb module 构建里曾触发 CreateProcess error=5
|
||||||
|
|
||||||
- 现象:`Genarrative-Stdb-Module-Build` 在 Windows Jenkins 节点上报 `java.io.IOException: Cannot run program "powershell" (in directory "C:\\Users\\DSK\\.jenkins-local\\workspace\\Genarrative-Stdb-Module-Build"): CreateProcess error=5, 拒绝访问。`;日志里能看到 `durable-task` 已写出 `powershellWrapper.ps1`,但在真正启动裸 `powershell` 子进程时失败。
|
- 现象:`Genarrative-Stdb-Module-Build` 在 Windows Jenkins 节点上报 `java.io.IOException: Cannot run program "powershell" (in directory "C:\\Users\\DSK\\.jenkins-local\\workspace\\Genarrative-Stdb-Module-Build"): CreateProcess error=5, 拒绝访问。`;日志里能看到 `durable-task` 已写出 `powershellWrapper.ps1`,但在真正启动裸 `powershell` 子进程时失败。
|
||||||
- 原因:Jenkins durable-task 的 `powershell` step 依赖一个隐式命令解析/启动路径,在这台 Windows 本地 Jenkins 环境里会被拒绝。`powershell.exe` 本体和 workspace ACL 都是正常的,问题出在 Jenkins step 的启动方式,而不是 PowerShell 脚本内容。
|
- 原因:Jenkins durable-task 的 `powershell` step 依赖一个隐式命令解析/启动路径,在这台 Windows 本地 Jenkins 环境里会被拒绝。`powershell.exe` 本体和 workspace ACL 都是正常的,问题出在 Jenkins step 的启动方式,而不是 PowerShell 脚本内容。修复后若日志能打印 `[jenkins-powershell] exe:`,但随后仅报 `拒绝访问` / `script returned exit code 5`,通常已经不是 PowerShell 启动失败,而是 Checkout 脚本内部命令在 Windows workspace 里触发权限拒绝。
|
||||||
- 处理:把 `jenkins/Jenkinsfile.production-stdb-module-build` 的 `Checkout` 和 `Build Stdb Module` 两处 `powershell` step 收口成 `runWindowsPowerShell(...)` helper,先用 `writeFile` 写出临时 `.ps1`,再通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File ...`。`Checkout` 阶段保留 `.jenkins-*.ps1`,并用 `git clean -e ".jenkins-*.ps1"` 避免被清掉。
|
- 处理:把 `jenkins/Jenkinsfile.production-stdb-module-build` 的 `Checkout` 和 `Build Stdb Module` 两处 `powershell` step 收口成 `runWindowsPowerShell(...)` helper,先用 `writeFile` 写出临时 `.ps1`,再通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Bypass -File ...`。Checkout 阶段优先复用 Jenkins GitSCM 已完成的工作区结果;`COMMIT_HASH` 为空或已经等于当前 `HEAD` 时不再重复 `git fetch` / `git checkout` / `git clean`,只有确实要切到另一个指定 commit 时才补 fetch、归属校验和 checkout。
|
||||||
- 验证:检查 Jenkins build log 中是否出现 `[jenkins-powershell] user:` 和 `[jenkins-powershell] exe:`,以及后续 `Checkout` / `Build Stdb Module` 是否继续执行;同时确认 `builds/<n>/log` 不再停在 `PipelineNodeTreeScanner... Cannot run program "powershell"`。
|
- 验证:检查 Jenkins build log 中是否出现 `[jenkins-powershell] user:` 和 `[jenkins-powershell] exe:`,以及 `[stdb-checkout] current HEAD:`。上游 Full Build 传下来的 `COMMIT_HASH` 若已等于当前 GitSCM checkout,日志应显示 `requested commit already matches Jenkins GitSCM checkout` 并继续进入构建阶段;同时确认 `builds/<n>/log` 不再停在 `PipelineNodeTreeScanner... Cannot run program "powershell"` 或 Checkout 内部 exit code 5。
|
||||||
- 关联:`jenkins/Jenkinsfile.production-stdb-module-build`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
- 关联:`jenkins/Jenkinsfile.production-stdb-module-build`、`docs/【开发运维】本地开发验证与生产运维-2026-05-15.md`。
|
||||||
|
|||||||
@@ -149,7 +149,7 @@ Nginx 负责站点和反向代理
|
|||||||
Jenkins 按 web / api / Spacetime module / build / deploy / publish 拆分
|
Jenkins 按 web / api / Spacetime module / build / deploy / publish 拆分
|
||||||
```
|
```
|
||||||
|
|
||||||
Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该流水线需要执行 PowerShell 逻辑时,统一通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,不要直接使用 Jenkins `powershell` step;本地 Jenkins durable-task 曾在 `Genarrative-Stdb-Module-Build` workspace 中启动裸 `powershell` 时触发 `CreateProcess error=5, 拒绝访问`。排查时先看对应 build log、`@tmp/durable-*` 下的 `powershellWrapper.ps1`,以及日志中的 `[jenkins-powershell] user/exe`。
|
Windows Stdb module 构建流水线运行在 Jenkins `windows` 节点上。该流水线需要执行 PowerShell 逻辑时,统一通过 `bat` 显式调用 `%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe`,不要直接使用 Jenkins `powershell` step;本地 Jenkins durable-task 曾在 `Genarrative-Stdb-Module-Build` workspace 中启动裸 `powershell` 时触发 `CreateProcess error=5, 拒绝访问`。Checkout 阶段要优先复用 Jenkins GitSCM 已经完成的结果:`COMMIT_HASH` 为空或与当前 `HEAD` 一致时,不要再额外 `git clean` / `git checkout`,只在确实需要切到别的指定 commit 时才补 fetch、校验和切换。排查时先看对应 build log、`@tmp/durable-*` 下的 `powershellWrapper.ps1`,以及日志中的 `[jenkins-powershell] user/exe`。
|
||||||
|
|
||||||
生产环境变量模板:`deploy/env/api-server.env.example`。真实密钥只放服务器,不提交 Git,不写入文档示例。
|
生产环境变量模板:`deploy/env/api-server.env.example`。真实密钥只放服务器,不提交 Git,不写入文档示例。
|
||||||
|
|
||||||
|
|||||||
@@ -70,13 +70,85 @@ pipeline {
|
|||||||
$sourceBranch = if ($env:SOURCE_BRANCH) { $env:SOURCE_BRANCH } else { 'master' }
|
$sourceBranch = if ($env:SOURCE_BRANCH) { $env:SOURCE_BRANCH } else { 'master' }
|
||||||
$commitHash = if ($env:COMMIT_HASH) { $env:COMMIT_HASH } else { '' }
|
$commitHash = if ($env:COMMIT_HASH) { $env:COMMIT_HASH } else { '' }
|
||||||
$gitRemoteUrl = if ($env:GIT_REMOTE_URL) { $env:GIT_REMOTE_URL } else { 'https://git.genarrative.world/GenarrativeAI/Genarrative.git' }
|
$gitRemoteUrl = if ($env:GIT_REMOTE_URL) { $env:GIT_REMOTE_URL } else { 'https://git.genarrative.world/GenarrativeAI/Genarrative.git' }
|
||||||
git fetch --no-tags --prune --depth=1 $gitRemoteUrl "+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}"
|
|
||||||
if ($commitHash) {
|
function Invoke-GitCommand {
|
||||||
git checkout --force $commitHash
|
param(
|
||||||
} else {
|
[string]$Label,
|
||||||
git checkout --force "origin/$sourceBranch"
|
[string[]]$Arguments
|
||||||
|
)
|
||||||
|
|
||||||
|
Write-Host "[stdb-checkout] $Label"
|
||||||
|
& git @Arguments
|
||||||
|
$exitCode = $LASTEXITCODE
|
||||||
|
if ($exitCode -ne 0) {
|
||||||
|
throw "[stdb-checkout] $Label failed with exit code $exitCode"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
git clean -ffdx -e ".jenkins-*.ps1"
|
|
||||||
|
Write-Host "[stdb-checkout] sourceBranch: $sourceBranch"
|
||||||
|
Write-Host "[stdb-checkout] remote: $gitRemoteUrl"
|
||||||
|
$currentCommit = (git rev-parse HEAD).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $currentCommit) {
|
||||||
|
throw '[stdb-checkout] cannot resolve current HEAD'
|
||||||
|
}
|
||||||
|
Write-Host "[stdb-checkout] current HEAD: $currentCommit"
|
||||||
|
|
||||||
|
if ($commitHash) {
|
||||||
|
Write-Host "[stdb-checkout] requested commit: $commitHash"
|
||||||
|
$resolvedCommit = (git rev-parse --verify "${commitHash}^{commit}" 2>$null).Trim()
|
||||||
|
if ($LASTEXITCODE -eq 0 -and $resolvedCommit -eq $currentCommit) {
|
||||||
|
Write-Host '[stdb-checkout] requested commit already matches Jenkins GitSCM checkout'
|
||||||
|
} else {
|
||||||
|
Invoke-GitCommand -Label 'fetch source branch history' -Arguments @(
|
||||||
|
'fetch',
|
||||||
|
'--no-tags',
|
||||||
|
'--prune',
|
||||||
|
$gitRemoteUrl,
|
||||||
|
"+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}"
|
||||||
|
)
|
||||||
|
$isShallowRepository = (git rev-parse --is-shallow-repository 2>$null).Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0) {
|
||||||
|
throw '[stdb-checkout] cannot determine whether repository is shallow'
|
||||||
|
}
|
||||||
|
if ($isShallowRepository -eq 'true') {
|
||||||
|
Invoke-GitCommand -Label 'deepen source branch history' -Arguments @(
|
||||||
|
'fetch',
|
||||||
|
'--unshallow',
|
||||||
|
'--no-tags',
|
||||||
|
$gitRemoteUrl,
|
||||||
|
"+refs/heads/${sourceBranch}:refs/remotes/origin/${sourceBranch}"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Invoke-GitCommand -Label 'validate source branch ref' -Arguments @(
|
||||||
|
'cat-file',
|
||||||
|
'-e',
|
||||||
|
"refs/remotes/origin/${sourceBranch}^{commit}"
|
||||||
|
)
|
||||||
|
Invoke-GitCommand -Label 'validate requested commit' -Arguments @(
|
||||||
|
'cat-file',
|
||||||
|
'-e',
|
||||||
|
"${commitHash}^{commit}"
|
||||||
|
)
|
||||||
|
$resolvedCommit = (git rev-parse --verify "${commitHash}^{commit}").Trim()
|
||||||
|
if ($LASTEXITCODE -ne 0 -or -not $resolvedCommit) {
|
||||||
|
throw "[stdb-checkout] cannot resolve requested commit: $commitHash"
|
||||||
|
}
|
||||||
|
Invoke-GitCommand -Label 'validate requested commit belongs to branch' -Arguments @(
|
||||||
|
'merge-base',
|
||||||
|
'--is-ancestor',
|
||||||
|
$resolvedCommit,
|
||||||
|
"refs/remotes/origin/${sourceBranch}"
|
||||||
|
)
|
||||||
|
Invoke-GitCommand -Label "checkout commit $resolvedCommit" -Arguments @(
|
||||||
|
'checkout',
|
||||||
|
'--force',
|
||||||
|
$resolvedCommit
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Write-Host "[stdb-checkout] COMMIT_HASH empty, reusing Jenkins GitSCM checkout result"
|
||||||
|
}
|
||||||
|
|
||||||
$resolvedCommit = (git rev-parse HEAD).Trim()
|
$resolvedCommit = (git rev-parse HEAD).Trim()
|
||||||
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
|
||||||
[System.IO.File]::WriteAllText((Join-Path (Get-Location) '.jenkins-source-commit'), "$resolvedCommit`n", $utf8NoBom)
|
[System.IO.File]::WriteAllText((Join-Path (Get-Location) '.jenkins-source-commit'), "$resolvedCommit`n", $utf8NoBom)
|
||||||
|
|||||||
Reference in New Issue
Block a user