// Copyright (C) 2024 Umorpha Systems // SPDX-License-Identifier: AGPL-3.0-or-later package leader import ( "encoding/json" "fmt" "os" "path/filepath" "strings" "git.mothstuff.lol/lukeshu/eclipse/lib/common" ) // Main config ///////////////////////////////////////////////////////////////// type Config struct { PubKeyFile string `json:"pubkey_file"` StateDir string `json:"state_dir"` CacheDir string `json:"cache_dir"` ActionsDir string `json:"actions_dir"` GitCacheFor common.Duration `json:"cache_git_for"` ParallelDownloads int `json:"parallel_downloads"` } func LoadConfig(filename string) (Config, error) { return common.LoadYAML[Config](filename) } // Actions ///////////////////////////////////////////////////////////////////// type Action struct { Triggers []Trigger `json:"triggers"` Run string `json:"run"` } type Trigger struct { // GitRev triggers once for each matching rev. // // For example, given the config // // rev="refs/tags/v*" // // and the refs // // "refs/tags/v1" => 0001 // "refs/tags/v2" => 0002 // "refs/tags/v3" => 0003 // // it would trigger 3 times: // // {"git_rev":{"url":"…","rev":"refs/tags/v1"}} => 0001 // {"git_rev":{"url":"…","rev":"refs/tags/v2"}} => 0002 // {"git_rev":{"url":"…","rev":"refs/tags/v3"}} => 0003 GitRev *struct { URL string `json:"url"` Rev string `json:"rev"` } `json:"git_rev,omitempty"` // GitRevs triggers once with the list of all matching revs. // // For example, given the config // // revs="refs/tags/v*" // // and the refs // // "refs/tags/v1" => 0001 // "refs/tags/v2" => 0002 // "refs/tags/v3" => 0003 // // it would trigger just once: // // {"git_revs:"{"url":"…","revs":"refs/tags/v*"}} => "refs/tags/v1\t0001\nrefs/tags/v2\t0002\nrefs/tags/v3\t0003" GitRevs *struct { URL string `json:"url"` Revs string `json:"revs"` } `json:"git_revs,omitempty"` } func (trigger *Trigger) UnmarshalJSON(dat []byte) error { type untypedTrigger Trigger var obj untypedTrigger if err := json.Unmarshal(dat, &obj); err != nil { return err } cnt := 0 if obj.GitRev != nil { cnt++ } if obj.GitRevs != nil { cnt++ } if cnt != 1 { return fmt.Errorf("trigger must have exactly 1 field set") } *trigger = Trigger(obj) return nil } func (cfg Config) Actions() ([]Action, error) { entries, err := os.ReadDir(cfg.ActionsDir) if err != nil { return nil, err } var ret []Action for _, entry := range entries { if !strings.HasSuffix(entry.Name(), ".yml") && !strings.HasSuffix(entry.Name(), ".yaml") { continue } actions, err := common.LoadYAML[[]Action](filepath.Join(cfg.ActionsDir, entry.Name())) if err != nil { return nil, fmt.Errorf("%q: %w", entry.Name(), err) } ret = append(ret, actions...) } return ret, nil }