feat(actions): support configured hydrate fields
This commit is contained in:
parent
94b15c8e2e
commit
c30e7221a8
@ -315,6 +315,8 @@ class: beast
|
||||
actions:
|
||||
workflow: .github/workflows/crabbox.yml
|
||||
ref: main
|
||||
fields:
|
||||
- crabbox_docker_cache=true
|
||||
runnerLabels:
|
||||
- crabbox
|
||||
sync:
|
||||
|
||||
@ -40,6 +40,8 @@ actions:
|
||||
workflow: .github/workflows/crabbox.yml
|
||||
job: hydrate
|
||||
ref: main
|
||||
fields:
|
||||
- crabbox_docker_cache=true
|
||||
runnerLabels:
|
||||
- crabbox
|
||||
runnerVersion: latest
|
||||
@ -48,6 +50,7 @@ actions:
|
||||
|
||||
Workflow jobs should target the dynamic label printed by registration, for example `crabbox-cbx-123`, plus any static labels configured for the project.
|
||||
When `actions.job` is set and the workflow declares `crabbox_job`, Crabbox sends it and verifies that the ready marker came from that job. Older workflows can omit both.
|
||||
Use `actions.fields` for repository-specific workflow inputs that should be sent on every hydration. CLI `-f key=value` values override matching configured fields for that dispatch.
|
||||
|
||||
## Hydration Flow
|
||||
|
||||
|
||||
@ -110,7 +110,8 @@ func (a App) actionsHydrate(ctx context.Context, args []string) error {
|
||||
return err
|
||||
}
|
||||
ref := actionsRef(cfg, repo)
|
||||
fields := actionsHydrateFields(leaseID, label, cfg.Actions.Job, *keepAliveMinutes, fieldFlags)
|
||||
extraFields := mergeWorkflowInputFields(cfg.Actions.Fields, fieldFlags)
|
||||
fields := actionsHydrateFields(leaseID, label, cfg.Actions.Job, *keepAliveMinutes, extraFields)
|
||||
if inputs, ok, err := githubWorkflowDispatchInputs(ctx, repo.Root, ghRepo, cfg.Actions.Workflow, ref); err != nil {
|
||||
fmt.Fprintf(a.Stderr, "warning: inspect workflow inputs failed: %v\n", err)
|
||||
} else if ok {
|
||||
@ -327,6 +328,28 @@ func actionsHydrateFields(leaseID, label, job string, keepAliveMinutes int, extr
|
||||
return fields
|
||||
}
|
||||
|
||||
func mergeWorkflowInputFields(base, override []string) []string {
|
||||
fields := append([]string{}, base...)
|
||||
index := map[string]int{}
|
||||
for i, field := range fields {
|
||||
if name := fieldName(field); name != "" {
|
||||
index[name] = i
|
||||
}
|
||||
}
|
||||
for _, field := range override {
|
||||
name := fieldName(field)
|
||||
if name != "" {
|
||||
if existing, ok := index[name]; ok {
|
||||
fields[existing] = field
|
||||
continue
|
||||
}
|
||||
index[name] = len(fields)
|
||||
}
|
||||
fields = append(fields, field)
|
||||
}
|
||||
return fields
|
||||
}
|
||||
|
||||
func githubWorkflowDispatchInputs(ctx context.Context, dir string, repo GitHubRepo, workflow, ref string) (map[string]bool, bool, error) {
|
||||
workflow = strings.TrimPrefix(workflow, "/")
|
||||
if !strings.HasPrefix(workflow, ".github/workflows/") {
|
||||
|
||||
@ -46,6 +46,17 @@ func TestActionsHydrateFieldsOmitsEmptyJobForOldWorkflows(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestMergeWorkflowInputFieldsLetsFlagsOverrideConfig(t *testing.T) {
|
||||
got := mergeWorkflowInputFields(
|
||||
[]string{"crabbox_docker_cache=false", "crabbox_prepare_images=1"},
|
||||
[]string{"crabbox_docker_cache=true", "custom=value"},
|
||||
)
|
||||
want := []string{"crabbox_docker_cache=true", "crabbox_prepare_images=1", "custom=value"}
|
||||
if strings.Join(got, "\n") != strings.Join(want, "\n") {
|
||||
t.Fatalf("fields=%#v want %#v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFilterWorkflowInputsDropsUndeclaredOptionalInputs(t *testing.T) {
|
||||
fields := actionsHydrateFields("cbx_123", "crabbox-cbx-123", "hydrate", 90, []string{"custom=value"})
|
||||
filtered, dropped := filterWorkflowInputs(fields, map[string]bool{
|
||||
|
||||
@ -76,6 +76,7 @@ type ActionsConfig struct {
|
||||
Workflow string
|
||||
Job string
|
||||
Ref string
|
||||
Fields []string
|
||||
RunnerLabels []string
|
||||
RunnerVersion string
|
||||
Ephemeral bool
|
||||
@ -282,6 +283,7 @@ type fileActionsConfig struct {
|
||||
Workflow string `yaml:"workflow,omitempty"`
|
||||
Job string `yaml:"job,omitempty"`
|
||||
Ref string `yaml:"ref,omitempty"`
|
||||
Fields []string `yaml:"fields,omitempty"`
|
||||
RunnerLabels []string `yaml:"runnerLabels,omitempty"`
|
||||
RunnerVersion string `yaml:"runnerVersion,omitempty"`
|
||||
Ephemeral *bool `yaml:"ephemeral,omitempty"`
|
||||
@ -583,6 +585,9 @@ func applyFileConfig(cfg *Config, file fileConfig) {
|
||||
if file.Actions.Ref != "" {
|
||||
cfg.Actions.Ref = file.Actions.Ref
|
||||
}
|
||||
if len(file.Actions.Fields) > 0 {
|
||||
cfg.Actions.Fields = appendUniqueStrings(nil, file.Actions.Fields...)
|
||||
}
|
||||
if len(file.Actions.RunnerLabels) > 0 {
|
||||
cfg.Actions.RunnerLabels = appendUniqueStrings(nil, file.Actions.RunnerLabels...)
|
||||
}
|
||||
|
||||
@ -84,6 +84,9 @@ actions:
|
||||
workflow: .github/workflows/crabbox.yml
|
||||
job: hydrate
|
||||
ref: main
|
||||
fields:
|
||||
- crabbox_docker_cache=true
|
||||
- crabbox_prepare_images=1
|
||||
runnerLabels:
|
||||
- crabbox
|
||||
- linux-large
|
||||
@ -164,6 +167,9 @@ ssh:
|
||||
if cfg.Actions.Repo != "openclaw/crabbox" || cfg.Actions.Workflow != ".github/workflows/crabbox.yml" || cfg.Actions.Job != "hydrate" || cfg.Actions.Ref != "main" {
|
||||
t.Fatalf("actions config not loaded: %#v", cfg.Actions)
|
||||
}
|
||||
if len(cfg.Actions.Fields) != 2 || cfg.Actions.Fields[0] != "crabbox_docker_cache=true" || cfg.Actions.Fields[1] != "crabbox_prepare_images=1" {
|
||||
t.Fatalf("actions fields config not loaded: %#v", cfg.Actions.Fields)
|
||||
}
|
||||
if cfg.Actions.Ephemeral || len(cfg.Actions.RunnerLabels) != 2 || cfg.Actions.RunnerLabels[1] != "linux-large" {
|
||||
t.Fatalf("actions runner config not loaded: %#v", cfg.Actions)
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user