mirror of
https://github.com/lukaszraczylo/harness-sync.git
synced 2026-10-12 00:45:22 +00:00
75 lines
2.1 KiB
Go
75 lines
2.1 KiB
Go
package canonical
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/lukaszraczylo/harness-sync/internal/secrets"
|
|
)
|
|
|
|
// SubstituteSecrets walks the bundle and replaces ${VAR} placeholders in all
|
|
// config fields using lookup. Skill/agent/instruction bodies are intentionally
|
|
// NOT substituted — they are content, not config.
|
|
//
|
|
// Returns an error (wrapping the offending field path) if any referenced
|
|
// variable is missing from lookup.
|
|
func SubstituteSecrets(b *Bundle, lookup secrets.Lookup) error {
|
|
var err error
|
|
|
|
// Gateway
|
|
if b.Profile.Gateway.Token, err = sub(lookup, "profile.gateway.token", b.Profile.Gateway.Token); err != nil {
|
|
return err
|
|
}
|
|
if b.Profile.Gateway.URL, err = sub(lookup, "profile.gateway.url", b.Profile.Gateway.URL); err != nil {
|
|
return err
|
|
}
|
|
if b.Profile.Gateway.DefaultModel, err = sub(lookup, "profile.gateway.default_model", b.Profile.Gateway.DefaultModel); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Upstreams
|
|
for i := range b.Profile.Upstreams {
|
|
u := &b.Profile.Upstreams[i]
|
|
field := fmt.Sprintf("profile.upstreams[%d](%s)", i, u.Name)
|
|
if u.APIKey, err = sub(lookup, field+".api_key", u.APIKey); err != nil {
|
|
return err
|
|
}
|
|
if u.BaseURL, err = sub(lookup, field+".base_url", u.BaseURL); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// MCP servers
|
|
for i := range b.MCP.Servers {
|
|
sv := &b.MCP.Servers[i]
|
|
field := fmt.Sprintf("mcp.servers[%d](%s)", i, sv.Name)
|
|
|
|
if sv.Command, err = sub(lookup, field+".command", sv.Command); err != nil {
|
|
return err
|
|
}
|
|
if sv.URL, err = sub(lookup, field+".url", sv.URL); err != nil {
|
|
return err
|
|
}
|
|
for j, arg := range sv.Args {
|
|
if sv.Args[j], err = sub(lookup, fmt.Sprintf("%s.args[%d]", field, j), arg); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
for k, v := range sv.Env {
|
|
if sv.Env[k], err = sub(lookup, fmt.Sprintf("%s.env[%s]", field, k), v); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// sub applies secrets.Substitute and wraps errors with field context.
|
|
func sub(lookup secrets.Lookup, field, value string) (string, error) {
|
|
result, err := secrets.Substitute(value, lookup)
|
|
if err != nil {
|
|
return "", fmt.Errorf("%s: %w", field, err)
|
|
}
|
|
return result, nil
|
|
}
|