go-scm/repos/workconfig.go

112 lines
3.1 KiB
Go
Raw Permalink Normal View History

// SPDX-License-Identifier: EUPL-1.2
package repos
import (
filepath "dappco.re/go/core/scm/internal/ax/filepathx"
"time"
"dappco.re/go/core/io"
coreerr "dappco.re/go/core/log"
"gopkg.in/yaml.v3"
)
// WorkConfig holds sync policy for a workspace.
// Stored at .core/work.yaml and checked into git (shared across the team).
type WorkConfig struct {
Version int `yaml:"version"`
Sync SyncConfig `yaml:"sync"`
Agents AgentPolicy `yaml:"agents"`
Triggers []string `yaml:"triggers,omitempty"`
}
// SyncConfig controls how and when repos are synced.
type SyncConfig struct {
Interval time.Duration `yaml:"interval"`
AutoPull bool `yaml:"auto_pull"`
AutoPush bool `yaml:"auto_push"`
CloneMissing bool `yaml:"clone_missing"`
}
// AgentPolicy controls multi-agent clash prevention.
type AgentPolicy struct {
Heartbeat time.Duration `yaml:"heartbeat"`
StaleAfter time.Duration `yaml:"stale_after"`
WarnOnOverlap bool `yaml:"warn_on_overlap"`
}
// DefaultWorkConfig returns sensible defaults for workspace sync.
// Usage: DefaultWorkConfig(...)
func DefaultWorkConfig() *WorkConfig {
return &WorkConfig{
Version: 1,
Sync: SyncConfig{
Interval: 5 * time.Minute,
AutoPull: true,
AutoPush: false,
CloneMissing: true,
},
Agents: AgentPolicy{
Heartbeat: 2 * time.Minute,
StaleAfter: 10 * time.Minute,
WarnOnOverlap: true,
},
Triggers: []string{"on_activate", "on_commit", "scheduled"},
}
}
// LoadWorkConfig reads .core/work.yaml from the given workspace root directory.
// Returns defaults if the file does not exist.
// Usage: LoadWorkConfig(...)
func LoadWorkConfig(m io.Medium, root string) (*WorkConfig, error) {
path := filepath.Join(root, ".core", "work.yaml")
if !m.Exists(path) {
return DefaultWorkConfig(), nil
}
content, err := m.Read(path)
if err != nil {
return nil, coreerr.E("repos.LoadWorkConfig", "failed to read work config", err)
}
wc := DefaultWorkConfig()
if err := yaml.Unmarshal([]byte(content), wc); err != nil {
return nil, coreerr.E("repos.LoadWorkConfig", "failed to parse work config", err)
}
return wc, nil
}
// SaveWorkConfig writes .core/work.yaml to the given workspace root directory.
// Usage: SaveWorkConfig(...)
func SaveWorkConfig(m io.Medium, root string, wc *WorkConfig) error {
coreDir := filepath.Join(root, ".core")
if err := m.EnsureDir(coreDir); err != nil {
return coreerr.E("repos.SaveWorkConfig", "failed to create .core directory", err)
}
data, err := yaml.Marshal(wc)
if err != nil {
return coreerr.E("repos.SaveWorkConfig", "failed to marshal work config", err)
}
path := filepath.Join(coreDir, "work.yaml")
if err := m.Write(path, string(data)); err != nil {
return coreerr.E("repos.SaveWorkConfig", "failed to write work config", err)
}
return nil
}
// HasTrigger returns true if the given trigger name is in the triggers list.
// Usage: HasTrigger(...)
func (wc *WorkConfig) HasTrigger(name string) bool {
for _, t := range wc.Triggers {
if t == name {
return true
}
}
return false
}