mirror of
https://github.com/Yuyi-Oak/BlueArchiveToolkit.git
synced 2026-09-18 11:56:23 +08:00
feat(bat): 补全工作流校验与调度过滤
新增 parse clear-cache 和 i18n validate,补齐 schedule 的作用域过滤与单轮执行上限,并将列表过滤参数暴露给 bat-api dashboard。同步 RPC、OpenAPI、用户文档和回归测试。 Refs #43
This commit is contained in:
@@ -13,9 +13,9 @@ use bat_infrastructure::{
|
||||
read_file_no_symlink, read_localized_patch_manifest_at, read_localized_version_state,
|
||||
read_parse_cache_at, read_snapshot, read_textunit_index_at, read_translation_workbench,
|
||||
read_version_state, redact_proxy_url, repack_bundle, resolve_curl_proxy, set_translation,
|
||||
validate_output_root, validate_runtime_state_dir, write_file_atomic,
|
||||
write_official_textunit_queues, CurlProxyConfig, CurlProxyMode, LocalizedPatchConfig,
|
||||
LocalizedPatchReport, LocalizedPatchService, OfficialEndpointMarkerRole,
|
||||
validate_output_root, validate_runtime_state_dir, validate_translation_workbench,
|
||||
write_file_atomic, write_official_textunit_queues, CurlProxyConfig, CurlProxyMode,
|
||||
LocalizedPatchConfig, LocalizedPatchReport, LocalizedPatchService, OfficialEndpointMarkerRole,
|
||||
OfficialFailedVersionRecord, OfficialParseCacheService, OfficialParseConfig,
|
||||
OfficialResourceHashVerification, OfficialResourceVerification, OfficialServerInfoSource,
|
||||
OfficialTextUnitQuery, OfficialTextUnitTaskQuery, OfficialUpdateConfig, OfficialUpdateProgress,
|
||||
@@ -24,10 +24,10 @@ use bat_infrastructure::{
|
||||
PatchApplyParams, PatchApplyReport, ReleaseFlowStatusCode, RepackReport,
|
||||
SqliteResourceRepository, SqliteTranslationTaskRepository, TranslationTaskStatus,
|
||||
UnityFsFieldPatchParams, UnityFsPatchReport, UnityFsStringFieldPatchParams,
|
||||
UnityFsTextAssetPatchParams, LOCALIZED_CURRENT_LINK, LOCALIZED_PATCH_MANIFEST_FILE,
|
||||
LOCALIZED_VERSIONS_DIR, LOCALIZED_VERSION_STATE_FILE, MAX_DOWNLOAD_CONCURRENCY,
|
||||
MIN_DOWNLOAD_CONCURRENCY, OFFICIAL_PARSE_CACHE_FILE, OFFICIAL_TEXTUNIT_INDEX_FILE,
|
||||
PRIVATE_FILE_MODE,
|
||||
UnityFsTextAssetPatchParams, CROWDIN_TEXTUNIT_QUEUE_FILE, LOCALIZED_CURRENT_LINK,
|
||||
LOCALIZED_PATCH_MANIFEST_FILE, LOCALIZED_VERSIONS_DIR, LOCALIZED_VERSION_STATE_FILE,
|
||||
MAX_DOWNLOAD_CONCURRENCY, MIN_DOWNLOAD_CONCURRENCY, OFFICIAL_PARSE_CACHE_FILE,
|
||||
OFFICIAL_TEXTUNIT_INDEX_FILE, OFFICIAL_TEXTUNIT_TASK_QUEUE_FILE, PRIVATE_FILE_MODE,
|
||||
};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
@@ -79,7 +79,8 @@ use translation_query::{
|
||||
update_translation_task_status_report,
|
||||
};
|
||||
use workflow_commands::{
|
||||
run_parse_once, run_publish_localized, run_repack, run_translate_once, run_translation_set,
|
||||
run_parse_clear_cache, run_parse_once, run_publish_localized, run_repack, run_translate_once,
|
||||
run_translation_set, run_translation_validate,
|
||||
};
|
||||
|
||||
const EXIT_ERROR: i32 = 1;
|
||||
@@ -192,10 +193,18 @@ fn run() -> anyhow::Result<i32> {
|
||||
run_repeated_workflow(&options, "parse", run_parse_once)?;
|
||||
Ok(0)
|
||||
}
|
||||
CliCommand::ParseClearCache => {
|
||||
run_parse_clear_cache(&options)?;
|
||||
Ok(0)
|
||||
}
|
||||
CliCommand::Translate => {
|
||||
run_repeated_workflow(&options, "translate", run_translate_once)?;
|
||||
Ok(0)
|
||||
}
|
||||
CliCommand::TranslationValidate => {
|
||||
run_translation_validate(&options)?;
|
||||
Ok(0)
|
||||
}
|
||||
CliCommand::TranslationSet => {
|
||||
run_translation_set(&options)?;
|
||||
Ok(0)
|
||||
@@ -356,6 +365,7 @@ struct CliOptions {
|
||||
schedule_delay: Option<Duration>,
|
||||
schedule_every: Option<Duration>,
|
||||
schedule_count: Option<usize>,
|
||||
schedule_max_runs: Option<usize>,
|
||||
schedule_args: Vec<String>,
|
||||
schedule_clear_args: bool,
|
||||
schedule_clear_every: bool,
|
||||
@@ -438,6 +448,7 @@ impl Default for CliOptions {
|
||||
schedule_delay: None,
|
||||
schedule_every: None,
|
||||
schedule_count: None,
|
||||
schedule_max_runs: None,
|
||||
schedule_args: Vec::new(),
|
||||
schedule_clear_args: false,
|
||||
schedule_clear_every: false,
|
||||
@@ -504,7 +515,9 @@ enum CliCommand {
|
||||
Run,
|
||||
Pull,
|
||||
Parse,
|
||||
ParseClearCache,
|
||||
Translate,
|
||||
TranslationValidate,
|
||||
TranslationSet,
|
||||
Repack,
|
||||
PublishLocalized,
|
||||
@@ -1762,11 +1775,31 @@ fn dispatch_rpc_method(
|
||||
"resource.state",
|
||||
build_resource_state_report(state_dir),
|
||||
),
|
||||
RPC_METHOD_SCHEDULE_LIST => rpc_envelope_from_result(
|
||||
request_id,
|
||||
RPC_METHOD_SCHEDULE_LIST,
|
||||
schedule_commands::schedule_list_report(state_dir),
|
||||
),
|
||||
RPC_METHOD_SCHEDULE_LIST => {
|
||||
let params = request
|
||||
.params
|
||||
.as_ref()
|
||||
.filter(|params| !params.is_null())
|
||||
.map(|params| serde_json::from_value(params.clone()))
|
||||
.transpose()
|
||||
.map_err(|error| {
|
||||
ApiError::new(
|
||||
ErrorCode::RPC_INVALID_PARAMS,
|
||||
RPC_METHOD_SCHEDULE_LIST,
|
||||
format!("params 无效:{error}"),
|
||||
)
|
||||
});
|
||||
let params = match params {
|
||||
Ok(Some(params)) => params,
|
||||
Ok(None) => schedule_commands::ScheduleListRequest::default(),
|
||||
Err(error) => return rpc_envelope_error(request_id, error),
|
||||
};
|
||||
rpc_envelope_from_result(
|
||||
request_id,
|
||||
RPC_METHOD_SCHEDULE_LIST,
|
||||
schedule_commands::schedule_list_report_with_request(state_dir, params),
|
||||
)
|
||||
}
|
||||
RPC_METHOD_SCHEDULE_ADD => {
|
||||
let params = match rpc_struct_params::<schedule_commands::ScheduleMutationRequest>(
|
||||
request.params.as_ref(),
|
||||
@@ -6754,6 +6787,16 @@ fn parse_args_with_env(
|
||||
options.schedule_count = Some(value);
|
||||
options.schedule_option_explicit = true;
|
||||
}
|
||||
"--schedule-max-runs" => {
|
||||
let value = next_option_value(&mut args, &flag)?
|
||||
.parse::<usize>()
|
||||
.map_err(|error| anyhow::anyhow!("{flag} 无效:{error}"))?;
|
||||
if value == 0 {
|
||||
return Err(anyhow::anyhow!("--schedule-max-runs 必须大于 0"));
|
||||
}
|
||||
options.schedule_max_runs = Some(value);
|
||||
options.schedule_option_explicit = true;
|
||||
}
|
||||
"--schedule-arg" => {
|
||||
options
|
||||
.schedule_args
|
||||
@@ -7120,11 +7163,40 @@ fn parse_args_with_env(
|
||||
));
|
||||
}
|
||||
}
|
||||
CliCommand::ParseClearCache => {
|
||||
if options.watch || options.daemon || options.daemon_child {
|
||||
return Err(anyhow::anyhow!("parse clear-cache 只支持单次执行"));
|
||||
}
|
||||
if !options.config.force {
|
||||
return Err(anyhow::anyhow!(
|
||||
"parse clear-cache 是破坏性操作,必须显式指定 --force"
|
||||
));
|
||||
}
|
||||
if options.config.dry_run || options.run_count.is_some() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"parse clear-cache 不支持 --dry-run 或 --run-count"
|
||||
));
|
||||
}
|
||||
options.progress = false;
|
||||
options.banner = false;
|
||||
}
|
||||
CliCommand::TranslationValidate => {
|
||||
if options.watch || options.daemon || options.daemon_child {
|
||||
return Err(anyhow::anyhow!("i18n validate 只支持单次执行"));
|
||||
}
|
||||
if options.config.force || options.config.dry_run || options.run_count.is_some() {
|
||||
return Err(anyhow::anyhow!(
|
||||
"i18n validate 不支持 --force、--dry-run 或 --run-count"
|
||||
));
|
||||
}
|
||||
options.progress = false;
|
||||
options.banner = false;
|
||||
}
|
||||
CliCommand::TranslationSet | CliCommand::Repack => {
|
||||
if options.watch || options.daemon || options.daemon_child {
|
||||
return Err(anyhow::anyhow!("translation set/repack 只支持单次执行"));
|
||||
}
|
||||
if options.config.force || options.sync_option_explicit {
|
||||
if options.config.force || options.sync_option_explicit || options.run_count.is_some() {
|
||||
return Err(anyhow::anyhow!("translation set/repack 不接受资源同步选项"));
|
||||
}
|
||||
options.progress = false;
|
||||
@@ -7151,6 +7223,11 @@ fn parse_args_with_env(
|
||||
if options.interval_explicit && !matches!(options.command, CliCommand::ScheduleRun) {
|
||||
return Err(anyhow::anyhow!("--interval 只适用于 schedule run 的轮询"));
|
||||
}
|
||||
if options.schedule_max_runs.is_some()
|
||||
&& !matches!(options.command, CliCommand::ScheduleRun)
|
||||
{
|
||||
return Err(anyhow::anyhow!("--schedule-max-runs 只适用于 schedule run"));
|
||||
}
|
||||
options.progress = false;
|
||||
options.banner = false;
|
||||
}
|
||||
@@ -7294,6 +7371,7 @@ fn parse_parse_command(
|
||||
"status" => CliCommand::ParseStatus,
|
||||
"text-units" => CliCommand::ParseTextUnits,
|
||||
"errors" => CliCommand::ParseErrors,
|
||||
"clear-cache" => CliCommand::ParseClearCache,
|
||||
"schedule" => {
|
||||
options.schedule_group = Some("parse".to_string());
|
||||
return parse_schedule_command(args, options);
|
||||
@@ -7315,6 +7393,7 @@ fn parse_translation_command(
|
||||
"run" => CliCommand::Translate,
|
||||
"export" => CliCommand::Translate,
|
||||
"set" => CliCommand::TranslationSet,
|
||||
"validate" => CliCommand::TranslationValidate,
|
||||
"publish" => CliCommand::PublishLocalized,
|
||||
"tasks" => CliCommand::TranslationTasks,
|
||||
"handoff" => CliCommand::TranslationHandoff,
|
||||
@@ -7435,10 +7514,12 @@ fn print_usage(binary: &str) {
|
||||
eprintln!(" res pull Pull official resources once or repeatedly");
|
||||
eprintln!(" res schedule Manage resource pull schedules (CLI/RPC/dashboard)");
|
||||
eprintln!(" parse run Parse current official release");
|
||||
eprintln!(" parse clear-cache Clear regenerable parse and translation queue files");
|
||||
eprintln!(" parse repack Repack a UnityFS bundle from a JSON spec");
|
||||
eprintln!(" i18n run Refresh offline translation work");
|
||||
eprintln!(" i18n export Export an editable translation workbench");
|
||||
eprintln!(" i18n set Update one translation workbench entry");
|
||||
eprintln!(" i18n validate Validate workbench against the current official release");
|
||||
eprintln!(" i18n publish Publish a localized release");
|
||||
eprintln!(" i18n schedule Manage translation schedules");
|
||||
eprintln!(" refresh Run one update check, or ask a live daemon to refresh");
|
||||
@@ -7589,6 +7670,7 @@ fn print_usage(binary: &str) {
|
||||
eprintln!(" --schedule-delay <DURATION> Delay first execution from now");
|
||||
eprintln!(" --schedule-every <DURATION> Period between executions");
|
||||
eprintln!(" --schedule-count <N> Bounded execution count");
|
||||
eprintln!(" --schedule-max-runs <N> Maximum plans executed by one schedule run");
|
||||
eprintln!(" --schedule-arg <ARG> Argument passed to scheduled child command");
|
||||
eprintln!(" --schedule-clear-args Clear args during schedule update");
|
||||
eprintln!(" --schedule-clear-every Convert a periodic plan to one-shot");
|
||||
|
||||
Reference in New Issue
Block a user