兼容历史预览构建记录
Project CI / Repository checks (push) Successful in 1m2s
Project CI / Frontend tests (push) Successful in 2m58s
Project CI / Native shell tests (push) Successful in 14m17s
Project CI / Backend tests (push) Successful in 3m56s

启动时回填旧记录的 Jenkins 构建编号

将旧 loopback 构建详情转换为局域网地址

补充历史记录迁移测试
This commit is contained in:
2026-08-17 12:52:40 +08:00
parent 38ae9d7d07
commit e455cd593c
2 changed files with 46 additions and 0 deletions
@@ -1052,6 +1052,7 @@ fn load_deployments(config: &Config) -> Result<HashMap<String, DeploymentRecord>
if record.public.id.as_deref() == Some(record.instance_id.as_str()) {
record.public.id = None;
}
recover_legacy_build_details(&mut record.public, config);
validate_deployment_id(&record.instance_id)
.map_err(|_| "状态文件包含无效预览实例 ID".to_string())?;
if let Some(build_id) = record.public.id.as_deref() {
@@ -1269,6 +1270,38 @@ fn validate_record_id(value: &str) -> Result<(), ApiError> {
.ok_or_else(|| ApiError::bad_request("构建编号无效"))
}
fn recover_legacy_build_details(deployment: &mut Deployment, config: &Config) {
let Some(build_url) = deployment.jenkins_build_url.as_deref() else {
return;
};
let Some(number) = jenkins_build_number(build_url, &config.jenkins_base_url) else {
deployment.jenkins_build_url = None;
return;
};
if deployment.id.is_none() {
deployment.id = Some(number.to_string());
}
deployment.jenkins_build_url = config
.jenkins_public_base_url
.join(&format!("{number}/"))
.ok()
.map(|url| url.to_string());
}
fn jenkins_build_number(value: &str, job_url: &Url) -> Option<u64> {
let parsed = Url::parse(value).ok()?;
if !parsed.username().is_empty() || parsed.password().is_some() {
return None;
}
parsed
.path()
.strip_prefix(job_url.path())?
.trim_end_matches('/')
.parse::<u64>()
.ok()
.filter(|number| *number > 0)
}
fn map_artifact_status(value: &str) -> Option<DeploymentStatus> {
match value.to_ascii_uppercase().as_str() {
"QUEUED" => Some(DeploymentStatus::Queued),
@@ -698,6 +698,7 @@ fn legacy_running_state_recovers_web_port_from_validated_url() {
"status": "running",
"health": "healthy",
"webUrl": "http://192.168.35.82:8407",
"jenkinsBuildUrl": "http://127.0.0.1:18080/jenkins/job/shared/job/Genarrative-Preview-Deployer/42/",
"createdAt": 1,
"updatedAt": 2,
"canUninstall": true
@@ -720,6 +721,18 @@ fn legacy_running_state_recovers_web_port_from_validated_url() {
.web_port,
Some(8407)
);
let deployment = state
.deployments
.blocking_read()
.get(&id)
.unwrap()
.public
.clone();
assert_eq!(deployment.id.as_deref(), Some("42"));
assert_eq!(
deployment.jenkins_build_url.as_deref(),
Some("http://192.168.35.82:8080/jenkins/job/shared/job/Genarrative-Preview-Deployer/42/")
);
std::fs::remove_file(&state.config.state_file).unwrap();
}