From 72eaaa4d9f1a6e2ddb6b65be2f903d27fd6a47d4 Mon Sep 17 00:00:00 2001 From: julio4 <30329843+julio4@users.noreply.github.com> Date: Tue, 10 Mar 2026 15:37:42 +0800 Subject: [PATCH 1/2] feat: host_path support in recipes --- playground/local_runner.go | 5 +++++ playground/manifest.go | 15 +++++++++++++-- playground/recipe_yaml.go | 23 +++++++++++++++-------- playground/recipe_yaml_test.go | 16 ++++++++++++++++ 4 files changed, 49 insertions(+), 10 deletions(-) diff --git a/playground/local_runner.go b/playground/local_runner.go index de3bc724..5cc45277 100644 --- a/playground/local_runner.go +++ b/playground/local_runner.go @@ -632,6 +632,11 @@ func (d *LocalRunner) toDockerComposeService(s *Service) (map[string]interface{} // create the bind volumes var createdVolumes []string for localPath, volume := range s.VolumesMapped { + if volume.HostPath != "" { + volumes[volume.HostPath] = localPath + continue + } + dockerVolumeName := d.createVolumeName(s.Name, volume.Name) if volume.IsLocal { diff --git a/playground/manifest.go b/playground/manifest.go index eaa4129a..109acea4 100644 --- a/playground/manifest.go +++ b/playground/manifest.go @@ -453,8 +453,9 @@ type Service struct { } type VolumeMapped struct { - Name string - IsLocal bool + Name string + IsLocal bool + HostPath string } type DependsOnCondition string @@ -607,6 +608,16 @@ func (s *Service) WithVolume(name, localPath string, isLocalTri ...bool) *Servic return s } +func (s *Service) WithHostVolume(hostPath, containerPath string) *Service { + if s.VolumesMapped == nil { + s.VolumesMapped = make(map[string]*VolumeMapped) + } + s.VolumesMapped[containerPath] = &VolumeMapped{ + HostPath: hostPath, + } + return s +} + func (s *Service) WithArtifact(localPath, artifactName string) *Service { if s.FilesMapped == nil { s.FilesMapped = make(map[string]string) diff --git a/playground/recipe_yaml.go b/playground/recipe_yaml.go index e6379a67..7ab77e43 100644 --- a/playground/recipe_yaml.go +++ b/playground/recipe_yaml.go @@ -116,8 +116,9 @@ type YAMLServiceConfig struct { } type YAMLVolumeMappedConfig struct { - Name string `yaml:"name"` - IsLocal bool `yaml:"is_local"` + Name string `yaml:"name"` + IsLocal bool `yaml:"is_local"` + HostPath string `yaml:"host_path"` } // YAMLReleaseConfig specifies a GitHub release to download @@ -481,9 +482,7 @@ func applyServiceOverrides(svc *Service, config *YAMLServiceConfig, root *Compon applyFilesToService(svc, config.Files) } if config.Volumes != nil { - for containerPath, volumeMapping := range config.Volumes { - svc.WithVolume(volumeMapping.Name, containerPath, volumeMapping.IsLocal) - } + applyVolumesToService(svc, config.Volumes) } if config.DependsOn != nil { applyDependsOn(svc, config.DependsOn, root) @@ -574,6 +573,16 @@ func yamlReleaseToRelease(cfg *YAMLReleaseConfig) *release { } // applyFilesToService maps files to a service +func applyVolumesToService(svc *Service, volumes map[string]*YAMLVolumeMappedConfig) { + for containerPath, volumeMapping := range volumes { + if volumeMapping.HostPath != "" { + svc.WithHostVolume(volumeMapping.HostPath, containerPath) + } else { + svc.WithVolume(volumeMapping.Name, containerPath, volumeMapping.IsLocal) + } + } +} + func applyFilesToService(svc *Service, files map[string]string) { for containerPath, fileSource := range files { var artifactName string @@ -662,9 +671,7 @@ func createServiceFromConfig(name string, config *YAMLServiceConfig, root *Compo applyFilesToService(svc, config.Files) } if config.Volumes != nil { - for containerPath, volumeMapping := range config.Volumes { - svc.WithVolume(volumeMapping.Name, containerPath, volumeMapping.IsLocal) - } + applyVolumesToService(svc, config.Volumes) } if config.DependsOn != nil { applyDependsOn(svc, config.DependsOn, root) diff --git a/playground/recipe_yaml_test.go b/playground/recipe_yaml_test.go index b5ee8f09..ff086662 100644 --- a/playground/recipe_yaml_test.go +++ b/playground/recipe_yaml_test.go @@ -417,6 +417,22 @@ func TestCreateServiceFromConfig_WithVolumes(t *testing.T) { require.Equal(t, "myvolume", svc.VolumesMapped["/data"].Name) } +func TestCreateServiceFromConfig_WithHostPathVolume(t *testing.T) { + config := &YAMLServiceConfig{ + Image: "test-image", + Volumes: map[string]*YAMLVolumeMappedConfig{"/var/run/docker.sock": { + HostPath: "/var/run/docker.sock", + }}, + } + + svc := createServiceFromConfig("my-service", config, nil, "") + + require.NotNil(t, svc.VolumesMapped) + require.Equal(t, "/var/run/docker.sock", svc.VolumesMapped["/var/run/docker.sock"].HostPath) + require.Empty(t, svc.VolumesMapped["/var/run/docker.sock"].Name) + require.False(t, svc.VolumesMapped["/var/run/docker.sock"].IsLocal) +} + func TestParseYAMLRecipe(t *testing.T) { tmpDir, err := os.MkdirTemp("", "recipe-test") require.NoError(t, err) From a5ccbcbaf12fe173ccf96c636ad7df1db0ff7948 Mon Sep 17 00:00:00 2001 From: Julio <30329843+julio4@users.noreply.github.com> Date: Tue, 10 Mar 2026 23:15:12 +0800 Subject: [PATCH 2/2] Update playground/recipe_yaml.go Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com> --- playground/recipe_yaml.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/playground/recipe_yaml.go b/playground/recipe_yaml.go index 7ab77e43..c99273fe 100644 --- a/playground/recipe_yaml.go +++ b/playground/recipe_yaml.go @@ -572,7 +572,7 @@ func yamlReleaseToRelease(cfg *YAMLReleaseConfig) *release { } } -// applyFilesToService maps files to a service +// applyVolumesToService maps volumes to a service func applyVolumesToService(svc *Service, volumes map[string]*YAMLVolumeMappedConfig) { for containerPath, volumeMapping := range volumes { if volumeMapping.HostPath != "" {