diff --git a/pkg/runs/preparation.go b/pkg/runs/preparation.go index a77c4e8d..b0430490 100644 --- a/pkg/runs/preparation.go +++ b/pkg/runs/preparation.go @@ -2,7 +2,6 @@ package runs import ( "context" - "encoding/json" "fmt" "os" "path/filepath" @@ -15,6 +14,7 @@ import ( "agent-compose/pkg/projects" "agent-compose/pkg/storage/sandboxstore" agentcomposev2 "agent-compose/proto/agentcompose/v2" + "google.golang.org/protobuf/encoding/protojson" ) type PreparationStore interface { @@ -151,7 +151,8 @@ func DecodeRevisionSpec(raw string) (*agentcomposev2.ProjectSpec, error) { if err != nil { return nil, fmt.Errorf("decode project revision spec: %w", err) } - if err := json.Unmarshal(normalizedData, &spec); err != nil { + opts := protojson.UnmarshalOptions{DiscardUnknown: true} + if err := opts.Unmarshal(normalizedData, &spec); err != nil { return nil, fmt.Errorf("decode project revision spec: %w", err) } if err := restoreCanonicalRevisionWorkspaces(data, &spec); err != nil { diff --git a/pkg/runs/preparation_driver_oneof_test.go b/pkg/runs/preparation_driver_oneof_test.go new file mode 100644 index 00000000..b246a74d --- /dev/null +++ b/pkg/runs/preparation_driver_oneof_test.go @@ -0,0 +1,25 @@ +package runs + +import ( + "testing" + + agentcomposev2 "agent-compose/proto/agentcompose/v2" +) + +// DecodeRevisionSpec must preserve oneof fields (e.g. driver runtime config). +// Regression test for the GetProject → PatchProject round-trip where a driver +// decoded via encoding/json lost its config oneof, so PatchProject rejected the +// returned spec with "driver requires exactly one runtime config". +func TestDecodeRevisionSpecPreservesDriverRuntimeConfig(t *testing.T) { + spec, err := DecodeRevisionSpec(`{"name":"demo","agents":[{"name":"worker","driver":{"name":"docker","docker":{}}}]}`) + if err != nil { + t.Fatalf("DecodeRevisionSpec returned error: %v", err) + } + driver := spec.GetAgents()[0].GetDriver() + if driver.GetName() != "docker" { + t.Fatalf("driver name = %q, want docker", driver.GetName()) + } + if _, ok := driver.GetConfig().(*agentcomposev2.DriverSpec_Docker); !ok { + t.Fatalf("driver config = %T, want *agentcomposev2.DriverSpec_Docker", driver.GetConfig()) + } +}