补齐空部署目标防护与进度清单

This commit is contained in:
xuans 2026-09-30 06:04:54 +08:00
parent 9414b5c5d8
commit cb88602882
8 changed files with 77 additions and 0 deletions

View File

@ -231,6 +231,9 @@ func (w *CertificateWorkflow) deploy(ctx context.Context, result certificate.Iss
if err != nil {
return deployment.Report{}, fmt.Errorf("查询域名部署服务器失败:%w", err)
}
if len(servers) == 0 {
return deployment.Report{Status: "failed"}, errors.New("\u57df\u540d\u5c1a\u672a\u5173\u8054\u4efb\u4f55\u90e8\u7f72\u670d\u52a1\u5668")
}
targets := make([]deployment.Target, 0, len(servers))
for _, server := range servers {
resolved, resolveErr := deployment.ResolveServerPaths(server, domainItem.Name, string(domainItem.CertificateType))

View File

@ -125,6 +125,24 @@ func TestCertificateWorkflowDeploysIssuedCertificateToAssociatedServers(t *testi
}
}
func TestCertificateWorkflowRejectsDomainWithoutDeploymentServers(t *testing.T) {
deployer := &workflowDeployer{report: deployment.Report{Total: 1, Success: 1, Status: "success"}}
state := &workflowDomainState{item: domain.Domain{ID: "domain-1", Name: "example.com", CertificateType: domain.CertificateSingle}}
workflow := &CertificateWorkflow{
Domains: state,
Servers: workflowServerLister{},
Deployment: deployer,
}
report, err := workflow.deploy(context.Background(), certificate.IssueResult{DomainID: "domain-1"})
if err == nil || !strings.Contains(err.Error(), "\u5c1a\u672a\u5173\u8054\u4efb\u4f55\u90e8\u7f72\u670d\u52a1\u5668") {
t.Fatalf("\u672a\u5173\u8054\u670d\u52a1\u5668\u65f6\u5e94\u8fd4\u56de\u660e\u786e\u9519\u8bef\xef\xbc\x9a%v", err)
}
if report.Status != "failed" || deployer.targets != nil {
t.Fatalf("\u672a\u5173\u8054\u670d\u52a1\u5668\u65f6\u4e0d\u5f97\u6267\u884c\u8fdc\u7a0b\u90e8\u7f72\xef\xbc\x9a%+v %+v", report, deployer.targets)
}
}
func TestCertificateWorkflowReturnsPartialDeploymentError(t *testing.T) {
deployer := &workflowDeployer{report: deployment.Report{
Total: 2, Success: 1, Failed: 1, Status: "partial",

View File

@ -57,6 +57,10 @@ func NewService(factory ClientFactory) *Service {
func (s *Service) Deploy(ctx context.Context, targets []Target, artifact Artifact) Report {
report := Report{Total: len(targets), Results: make([]Result, 0, len(targets))}
if len(targets) == 0 {
report.Status = "failed"
return report
}
if s == nil || s.factory == nil {
report.Status = "failed"
report.Failed = len(targets)

View File

@ -269,6 +269,14 @@ func TestDeployReportsPartialSuccess(t *testing.T) {
}
}
func TestDeployRejectsEmptyTargets(t *testing.T) {
service := NewService(fixedClientFactory{client: newMemoryClient()})
report := service.Deploy(context.Background(), nil, testArtifact(t))
if report.Status != "failed" || report.Total != 0 || report.Success != 0 || report.Failed != 0 {
t.Fatalf("\u7a7a\u90e8\u7f72\u76ee\u6807\u4e0d\u5f97\u88ab\u89c6\u4e3a\u6210\u529f\xef\xbc\x9a%+v", report)
}
}
func TestDeployCleansPartialPrivateKeyUploadWithoutReplacingCurrentFiles(t *testing.T) {
client := newMemoryClient()
client.uploadError = "key.pem"

View File

@ -3702,3 +3702,14 @@ Linux Ubuntu 22.04 上的 `Scert-admin` 手动启停、无开机自启动、无
- [~] 进行中:P0-10 其他任务入口、跨数据库验证、崩溃恢复、重试幂等和统一复审。
- [ ] 未开始:P0-12 备份恢复、密码 SSH、浏览器清缓存、远端部署及最终生产门禁。
- [!] 总体验收仍为 **P0-03:完成,待复审**,不得把本地自动化结果标记为生产验收通过。
## 本轮开发进度(2026-09-29,P0-10 空部署目标防护)
总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅继续完成 P0-10 批量部署边界防护,不代表 P0-10 统一复审通过或生产部署验收通过。
- [x] 已完成,等待复审:批量部署目标为空时显式返回失败,不再把 0 台服务器错判为部署成功。
- [x] 已完成,等待复审:证书工作流在域名未关联任何部署服务器时提前失败,不调用远程部署。
- [x] 已完成:新增应用层与部署层回归测试;`go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。
- [~] 进行中:P0-10 其余任务入口、失败回滚结果持久化、跨数据库矩阵、崩溃恢复与统一复审仍需继续。
- [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署、真实 DNS/ACME 和最终生产门禁仍未完成。
- [!] 总体验收不得升级:当前仍为 **P0-03:完成,待复审**,本轮没有新增 `[✓]` 复审通过项。

View File

@ -1006,3 +1006,14 @@ P0-05 从 `[!]` 调整为 `[~]`,并未标记完成;P0-04 剩余门禁和全
- [~] 进行中:DNS 验证任务、批量部署结果、崩溃恢复、重试幂等、三数据库实机矩阵和统一复审。
- [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署及最终生产门禁。
- [!] 总体验收不得升级,仍为 **P0-03:完成,待复审**,没有新增 `[✓]`。
## 本轮开发进度(2026-09-29,P0-10 空部署目标防护)
总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅继续完成 P0-10 批量部署边界防护,不代表 P0-10 统一复审通过或生产部署验收通过。
- [x] 已完成,等待复审:批量部署目标为空时显式返回失败,不再把 0 台服务器错判为部署成功。
- [x] 已完成,等待复审:证书工作流在域名未关联任何部署服务器时提前失败,不调用远程部署。
- [x] 已完成:新增应用层与部署层回归测试;`go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。
- [~] 进行中:P0-10 其余任务入口、失败回滚结果持久化、跨数据库矩阵、崩溃恢复与统一复审仍需继续。
- [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署、真实 DNS/ACME 和最终生产门禁仍未完成。
- [!] 总体验收不得升级:当前仍为 **P0-03:完成,待复审**,本轮没有新增 `[✓]` 复审通过项。

View File

@ -1653,3 +1653,14 @@ P0-11 生产验收门禁
- [~] 进行中:P0-10 其他任务入口、跨数据库实机矩阵、崩溃恢复、重试幂等和统一复审仍需继续。
- [ ] 未开始:P0-12 备份恢复及最终生产门禁仍未完成。
- [!] 总体验收不得升级,当前仍为 **P0-03:完成,待复审**,没有新增 `[✓]` 复审通过项。
## 本轮开发进度(2026-09-29,P0-10 空部署目标防护)
总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅继续完成 P0-10 批量部署边界防护,不代表 P0-10 统一复审通过或生产部署验收通过。
- [x] 已完成,等待复审:批量部署目标为空时显式返回失败,不再把 0 台服务器错判为部署成功。
- [x] 已完成,等待复审:证书工作流在域名未关联任何部署服务器时提前失败,不调用远程部署。
- [x] 已完成:新增应用层与部署层回归测试;`go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。
- [~] 进行中:P0-10 其余任务入口、失败回滚结果持久化、跨数据库矩阵、崩溃恢复与统一复审仍需继续。
- [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署、真实 DNS/ACME 和最终生产门禁仍未完成。
- [!] 总体验收不得升级:当前仍为 **P0-03:完成,待复审**,本轮没有新增 `[✓]` 复审通过项。

View File

@ -583,3 +583,14 @@ P0-06 与 P0-07 均维持 `[~]`,六阶段中的隔离、生产和最终验收
- [x] 本轮专项测试、静态检查通过,代码提交 `9741721` 已推送。
- [~] P0-10 其他任务链、跨数据库实机行为、崩溃恢复、重试幂等和统一复审继续进行。
- [!] 本地测试结果不得替代真实 DNS/ACME、多服务器推送、密码 SSH 和最终生产门禁。
## 本轮开发进度(2026-09-29,P0-10 空部署目标防护)
总体验收位置继续保持 **P0-03:完成,待复审**;本轮仅继续完成 P0-10 批量部署边界防护,不代表 P0-10 统一复审通过或生产部署验收通过。
- [x] 已完成,等待复审:批量部署目标为空时显式返回失败,不再把 0 台服务器错判为部署成功。
- [x] 已完成,等待复审:证书工作流在域名未关联任何部署服务器时提前失败,不调用远程部署。
- [x] 已完成:新增应用层与部署层回归测试;`go test ./...`、`go vet ./...` 和 `git diff --check` 均通过。
- [~] 进行中:P0-10 其余任务入口、失败回滚结果持久化、跨数据库矩阵、崩溃恢复与统一复审仍需继续。
- [ ] 未开始:P0-12 备份恢复、浏览器清缓存、密码 SSH、远端部署、真实 DNS/ACME 和最终生产门禁仍未完成。
- [!] 总体验收不得升级:当前仍为 **P0-03:完成,待复审**,本轮没有新增 `[✓]` 复审通过项。