feat(bat): 完善工作流调度与 dashboard RPC
bat-rust / Build and test Rust (push) Canceled after 0s
bat-rust / Build and test Go API (push) Canceled after 0s

补全资源拉取、解析、翻译、重打包和本地化发布命令,支持单次、限定次数与周期调度。移除 TUI 计划并通过 schedule.* RPC 暴露给 bat-api dashboard。

Closes #43
This commit is contained in:
2026-08-03 22:18:52 +08:00
parent 3b103be8a9
commit 0784d5b532
27 changed files with 2931 additions and 58 deletions
+43
View File
@@ -232,6 +232,29 @@ type UnityFSFieldPatchParams struct {
ExpectedValue json.RawMessage `json:"expected_value,omitempty"`
}
// ScheduleMutationParams is shared by schedule.add, schedule.update, and
// schedule.remove. Omitted pointer fields preserve the existing schedule on
// update; clear_* fields explicitly remove values.
type ScheduleMutationParams struct {
ID string `json:"id,omitempty"`
Group string `json:"group,omitempty"`
Action string `json:"action,omitempty"`
Args []string `json:"args,omitempty"`
NextRunUnixSeconds *uint64 `json:"next_run_unix_seconds,omitempty"`
DelaySeconds *uint64 `json:"delay_seconds,omitempty"`
EverySeconds *uint64 `json:"every_seconds,omitempty"`
Count *uint64 `json:"count,omitempty"`
ClearArgs bool `json:"clear_args,omitempty"`
ClearEvery bool `json:"clear_every,omitempty"`
Enabled *bool `json:"enabled,omitempty"`
}
// ScheduleRunParams selects a schedule or runs every due enabled schedule.
type ScheduleRunParams struct {
ID string `json:"id,omitempty"`
Force bool `json:"force,omitempty"`
}
// Ack is returned by accepted daemon control methods.
type Ack struct {
Command string `json:"command"`
@@ -427,6 +450,26 @@ func (c *Client) ResourceList(ctx context.Context, offset int, limit int) (*Reso
return &out, err
}
func (c *Client) ScheduleList(ctx context.Context) (json.RawMessage, error) {
return c.rawData(ctx, "schedule.list", nil)
}
func (c *Client) ScheduleAdd(ctx context.Context, params ScheduleMutationParams) (json.RawMessage, error) {
return c.rawData(ctx, "schedule.add", params)
}
func (c *Client) ScheduleUpdate(ctx context.Context, params ScheduleMutationParams) (json.RawMessage, error) {
return c.rawData(ctx, "schedule.update", params)
}
func (c *Client) ScheduleRemove(ctx context.Context, params ScheduleMutationParams) (json.RawMessage, error) {
return c.rawData(ctx, "schedule.remove", params)
}
func (c *Client) ScheduleRun(ctx context.Context, params ScheduleRunParams) (json.RawMessage, error) {
return c.rawData(ctx, "schedule.run", params)
}
func (c *Client) CatalogStatus(ctx context.Context) (json.RawMessage, error) {
return c.rawData(ctx, "catalog.status", nil)
}
+46
View File
@@ -252,6 +252,52 @@ func TestResourceListSendsPagination(t *testing.T) {
}
}
func TestScheduleUpdateSendsMutationParams(t *testing.T) {
every := uint64(3600)
count := uint64(4)
enabled := true
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
if req.Method != "schedule.update" {
t.Fatalf("method = %s", req.Method)
}
var params ScheduleMutationParams
if err := json.Unmarshal(req.Params, &params); err != nil {
t.Fatalf("decode params: %v", err)
}
if params.ID != "nightly-pull" || params.Group != "res" || params.Action != "pull" ||
params.EverySeconds == nil || *params.EverySeconds != every ||
params.Count == nil || *params.Count != count || params.Enabled == nil || !*params.Enabled {
t.Fatalf("params = %#v", params)
}
return testResponse{
Result: testEnvelope{
OK: true,
Status: "ok",
RequestID: "req-test-schedule",
Data: map[string]any{
"command": "schedule-update",
"status": "updated",
},
},
}
})
raw, err := client.ScheduleUpdate(context.Background(), ScheduleMutationParams{
ID: "nightly-pull",
Group: "res",
Action: "pull",
EverySeconds: &every,
Count: &count,
Enabled: &enabled,
})
if err != nil {
t.Fatalf("ScheduleUpdate error: %v", err)
}
if !json.Valid(raw) {
t.Fatalf("invalid raw JSON: %s", string(raw))
}
}
func TestApplicationErrorReturnsAPIError(t *testing.T) {
client := newTestClient(t, func(t *testing.T, req testRequest) testResponse {
if req.Method != "task.status" {