每日运行先检查京东日账单、京东钱包和抖音账单的月份覆盖,按旧到新补齐缺口,历史未补齐时暂停拉取新数据。页面回验按京东/京喜各自口径核对,并在服务端已完整但本地状态滞后时回填状态,避免重复导入;上传断开统一进入重试流程。 > 开工时标题使用 `WIP: <任务名称>` 并先填写“任务占用与边界”。Codex 完成独立合并前自审后补齐其余内容并移除 `WIP:`。 ## 任务占用与边界 - 任务名称: - 实际开发者: - 任务来源/团队分工: - 目标结果: - 预计修改路径: - 将写入的公共契约(路由、Controller 方法、Repository、表/视图、`source_key`、`scope`、权限名、菜单键或共享组件): - 仅复用、明确不修改的公共契约: - 数据源、表/视图和字段: - 上游 `source_key` / `scope`: - 权限名、菜单键或共享组件: - 明确不修改的范围: ## 开工碰撞检查 - [ ] Codex 已执行 `scripts/codex-task-preflight.ps1` - [ ] 已检查最新 `main` 和所有远程任务分支 - [ ] 已搜索主线既有页面、接口、Repository 和数据查询 - [ ] 已把“将写入”和“仅复用、不修改”的公共契约分开;仅复用项不作为单独阻断条件 - [ ] 未发现实际写入重叠;或已在下方写明相关分支、具体重叠项和协调结论 相关分支、重叠项与协调结论: ## 实际改动 - 完成内容: - Codex 实际修改的文件: - 新增或变更的公共契约: - 与原计划的差异: ## 验证证据 - 正常流程: - 空数据/错误输入/无权限场景: - 受影响旧功能: - 自动测试及结果: - 实际页面、接口或只读业务查询结果: ## 风险检查 - [ ] 不涉及金额、权限、审批、数据库迁移、生产配置或数据修复 - [ ] 如涉及上述高风险内容,已在下方写明影响、回滚和所需授权 - [ ] 未提交 `.env`、密码、Token、私钥、真实财务数据、生产日志或构建产物 - [ ] 前端改动符合 `DESIGN.md`;无前端改动则写“不适用” 高风险影响、回滚和授权状态: ## 合并前复查 - [ ] 已重新拉取远程引用并用实际修改范围再次运行碰撞检查 - [ ] PR 不再是 `WIP:`,所有测试结果已经补齐 - [ ] Codex 已重新读取原始需求和验收标准,并逐文件审核 `origin/main...任务分支` 的完整 diff - [ ] Codex 自审确认无越界修改、重复实现、敏感内容、未处理冲突和未验证结果 - [ ] 合并顺序不会覆盖其他未合并任务 - [ ] 已授权当前任务的 Codex 执行 Squash merge、验证 `main` 并清理任务分支 - [ ] 如涉及生产迁移、数据修复、删除、覆盖配置或部署,已另行取得对应高风险授权 Reviewed-on: #873
97 lines
3.8 KiB
PowerShell
97 lines
3.8 KiB
PowerShell
<#
|
||
每日账单脚本的远程执行辅助:上传 + 远程执行 + 失败重试。
|
||
|
||
远端命令失败(包括 SSH 连接被服务器断开)时不再静默当成功:
|
||
统一返回 { Ok; Output; Attempts },由调用方决定是否写本地状态、是否归档。
|
||
上传与远程执行都按 Attempts 重试;重试时会重新上传 CSV,
|
||
避免上一次失败已经把远端文件删掉导致二次失败。
|
||
#>
|
||
|
||
function New-ErpRemoteResult {
|
||
param([bool]$Ok, [string]$Output, [int]$Attempts)
|
||
|
||
return [pscustomobject]@{ Ok = $Ok; Output = $Output; Attempts = $Attempts }
|
||
}
|
||
|
||
function Get-ErpCoverageBackfillJobs {
|
||
param(
|
||
[object[]]$CoverageReport,
|
||
[Parameter(Mandatory = $true)][string]$Dataset,
|
||
[Parameter(Mandatory = $true)][string]$CurrentMonth
|
||
)
|
||
|
||
# 只返回当前拉取月份之前的缺口;当前月由本轮整月重导自然覆盖。
|
||
return @(
|
||
$CoverageReport |
|
||
Where-Object {
|
||
$_.dataset -eq $Dataset -and
|
||
$_.month -lt $CurrentMonth -and
|
||
$_.status -ne 'ok'
|
||
} |
|
||
Sort-Object month
|
||
)
|
||
}
|
||
|
||
function Invoke-ErpRemoteUpload {
|
||
param(
|
||
[Parameter(Mandatory = $true)][string]$PwshPath,
|
||
[Parameter(Mandatory = $true)][string]$UploaderScript,
|
||
[Parameter(Mandatory = $true)][string]$LocalFile,
|
||
[Parameter(Mandatory = $true)][string]$RemoteFile
|
||
)
|
||
|
||
$out = (& $PwshPath -NoProfile -ExecutionPolicy Bypass -File $UploaderScript -LocalPath $LocalFile -RemotePath $RemoteFile 2>&1 | Out-String)
|
||
|
||
return (New-ErpRemoteResult -Ok ($LASTEXITCODE -eq 0) -Output $out -Attempts 1)
|
||
}
|
||
|
||
function Invoke-ErpRemote {
|
||
param(
|
||
[Parameter(Mandatory = $true)][string]$PwshPath,
|
||
[Parameter(Mandatory = $true)][string]$SshScript,
|
||
[Parameter(Mandatory = $true)][string]$Body,
|
||
[string]$LocalFile = '',
|
||
[string]$RemoteFile = '',
|
||
[string]$UploaderScript = '',
|
||
[int]$Attempts = 3,
|
||
[int]$RetryDelaySeconds = 10,
|
||
[scriptblock]$Log = $null
|
||
)
|
||
|
||
$write = { param([string]$Message) if ($Log) { & $Log $Message } }
|
||
$tmp = [IO.Path]::GetTempFileName() + '.sh'
|
||
[IO.File]::WriteAllText($tmp, ($Body -replace "`r`n", "`n"))
|
||
try {
|
||
$output = ''
|
||
for ($attempt = 1; $attempt -le $Attempts; $attempt++) {
|
||
if ($LocalFile -and $RemoteFile -and $UploaderScript) {
|
||
$upload = Invoke-ErpRemoteUpload -PwshPath $PwshPath -UploaderScript $UploaderScript -LocalFile $LocalFile -RemoteFile $RemoteFile
|
||
if (-not $upload.Ok) {
|
||
$output = $upload.Output
|
||
& $write ('上传失败(第 {0}/{1} 次):{2}' -f $attempt, $Attempts, ($output.Trim() -replace "`r?`n", ' | '))
|
||
if ($attempt -lt $Attempts) {
|
||
Start-Sleep -Seconds $RetryDelaySeconds
|
||
continue
|
||
}
|
||
|
||
return (New-ErpRemoteResult -Ok $false -Output $output -Attempts $attempt)
|
||
}
|
||
}
|
||
|
||
$output = (& $PwshPath -NoProfile -ExecutionPolicy Bypass -File $SshScript -ScriptPath $tmp 2>&1 | Out-String)
|
||
if ($LASTEXITCODE -eq 0) {
|
||
return (New-ErpRemoteResult -Ok $true -Output $output -Attempts $attempt)
|
||
}
|
||
|
||
& $write ('远程执行失败(第 {0}/{1} 次,exit={2}):{3}' -f $attempt, $Attempts, $LASTEXITCODE, ($output.Trim() -replace "`r?`n", ' | '))
|
||
if ($attempt -lt $Attempts) {
|
||
Start-Sleep -Seconds $RetryDelaySeconds
|
||
}
|
||
}
|
||
|
||
return (New-ErpRemoteResult -Ok $false -Output $output -Attempts $Attempts)
|
||
} finally {
|
||
Remove-Item -LiteralPath $tmp -Force -ErrorAction SilentlyContinue
|
||
}
|
||
}
|