Some checks are pending
CI / test (push) Waiting to run
config.yaml previously mixed secrets with the phrase list, forcing private-only edits. Now config supports phrases_file, which is loaded and merged with any private phrases: entries, so the repo-tracked phrases.yaml can be extended via PR while per-deployment additions stay private. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
90 lines
2.4 KiB
Go
90 lines
2.4 KiB
Go
// Package config loads yaju-keisatsu's YAML configuration file.
|
|
package config
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"gopkg.in/yaml.v3"
|
|
)
|
|
|
|
type Config struct {
|
|
ListenAddr string `yaml:"listen_addr"`
|
|
WebhookSecret string `yaml:"webhook_secret"`
|
|
Forgejo Forgejo `yaml:"forgejo"`
|
|
Bot Bot `yaml:"bot"`
|
|
// PhrasesFile, if set, is loaded and merged with Phrases. It lets a
|
|
// deployment point at the repo's community-maintained phrases.yaml while
|
|
// still keeping any private additions inline below.
|
|
PhrasesFile string `yaml:"phrases_file"`
|
|
Phrases []string `yaml:"phrases"`
|
|
}
|
|
|
|
type phrasesFile struct {
|
|
Phrases []string `yaml:"phrases"`
|
|
}
|
|
|
|
type Forgejo struct {
|
|
BaseURL string `yaml:"base_url"`
|
|
Token string `yaml:"token"`
|
|
}
|
|
|
|
type Bot struct {
|
|
// Username is the Forgejo account the API token belongs to. Comments
|
|
// authored by this account are ignored so the bot never replies to itself.
|
|
Username string `yaml:"username"`
|
|
// BranchPrefix is prepended to the auto-generated correction branch name.
|
|
BranchPrefix string `yaml:"branch_prefix"`
|
|
// TargetExtensions limits which pushed files are scanned for corrections.
|
|
// An empty list scans every file.
|
|
TargetExtensions []string `yaml:"target_extensions"`
|
|
}
|
|
|
|
func Load(path string) (*Config, error) {
|
|
data, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read config: %w", err)
|
|
}
|
|
|
|
cfg := &Config{
|
|
ListenAddr: ":8080",
|
|
Bot: Bot{
|
|
BranchPrefix: "bot/goroku-fix/",
|
|
},
|
|
}
|
|
if err := yaml.Unmarshal(data, cfg); err != nil {
|
|
return nil, fmt.Errorf("parse config: %w", err)
|
|
}
|
|
|
|
if cfg.PhrasesFile != "" {
|
|
fp := cfg.PhrasesFile
|
|
if !filepath.IsAbs(fp) {
|
|
fp = filepath.Join(filepath.Dir(path), fp)
|
|
}
|
|
data, err := os.ReadFile(fp)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("read phrases_file: %w", err)
|
|
}
|
|
var pf phrasesFile
|
|
if err := yaml.Unmarshal(data, &pf); err != nil {
|
|
return nil, fmt.Errorf("parse phrases_file: %w", err)
|
|
}
|
|
cfg.Phrases = append(pf.Phrases, cfg.Phrases...)
|
|
}
|
|
|
|
if cfg.Forgejo.BaseURL == "" {
|
|
return nil, fmt.Errorf("forgejo.base_url is required")
|
|
}
|
|
if cfg.Forgejo.Token == "" {
|
|
return nil, fmt.Errorf("forgejo.token is required")
|
|
}
|
|
if cfg.WebhookSecret == "" {
|
|
return nil, fmt.Errorf("webhook_secret is required")
|
|
}
|
|
if len(cfg.Phrases) == 0 {
|
|
return nil, fmt.Errorf("phrases list is empty (set phrases and/or phrases_file)")
|
|
}
|
|
|
|
return cfg, nil
|
|
}
|