Eric Bower
·
2026-02-24
cfg.go
1package git
2
3import (
4 "fmt"
5 "log/slog"
6 "path/filepath"
7 "strings"
8 "time"
9
10 "github.com/knadh/koanf/parsers/toml"
11 "github.com/knadh/koanf/providers/env"
12 "github.com/knadh/koanf/providers/file"
13 "github.com/knadh/koanf/v2"
14 "golang.org/x/crypto/ssh"
15)
16
17var k = koanf.New(".")
18
19type GitCfg struct {
20 DataDir string `koanf:"data_dir"`
21 Url string `koanf:"url"`
22 Host string `koanf:"host"`
23 SshPort string `koanf:"ssh_port"`
24 WebPort string `koanf:"web_port"`
25 PromPort string `koanf:"prom_port"`
26 AdminsStr []string `koanf:"admins"`
27 Admins []ssh.PublicKey `koanf:"admins_pk"`
28 CreateRepo string `koanf:"create_repo"`
29 Theme string `koanf:"theme"`
30 TimeFormat string `koanf:"time_format"`
31 Desc string `koanf:"desc"`
32 Logger *slog.Logger
33}
34
35func LoadConfigFile(fpath string, logger *slog.Logger) {
36 fpp, err := filepath.Abs(fpath)
37 if err != nil {
38 panic(err)
39 }
40 logger.Info("loading configuration file", "fpath", fpp)
41
42 if err := k.Load(file.Provider(fpp), toml.Parser()); err != nil {
43 panic(fmt.Sprintf("error loading config: %v", err))
44 }
45}
46
47func NewGitCfg(logger *slog.Logger) *GitCfg {
48 err := k.Load(env.Provider("GITPR_", ".", func(s string) string {
49 keyword := strings.ToLower(strings.TrimPrefix(s, "GITPR_"))
50 return keyword
51 }), nil)
52 if err != nil {
53 panic(fmt.Sprintf("could not load environment variables: %v", err))
54 }
55
56 var out GitCfg
57 err = k.UnmarshalWithConf("", &out, koanf.UnmarshalConf{Tag: "koanf"})
58 if err != nil {
59 panic(fmt.Sprintf("could not unmarshal config: %v", err))
60 }
61
62 if len(out.AdminsStr) > 0 {
63 keys, err := GetAuthorizedKeys(out.AdminsStr)
64 if err == nil {
65 out.Admins = keys
66 } else {
67 panic(fmt.Sprintf("could not parse authorized keys file: %v", err))
68 }
69 } else {
70 logger.Info("no admin specified in config so no one can submit a review!")
71 }
72
73 // make datadir absolute
74 tmpdir := out.DataDir
75 if out.DataDir == "" {
76 tmpdir = "./data"
77 }
78 datadir, err := filepath.Abs(tmpdir)
79 out.DataDir = datadir
80 if err != nil {
81 panic(err)
82 }
83
84 if out.Host == "" {
85 out.Host = "0.0.0.0"
86 }
87
88 if out.SshPort == "" {
89 out.SshPort = "2222"
90 }
91
92 if out.WebPort == "" {
93 out.WebPort = "3000"
94 }
95
96 if out.Theme == "" {
97 out.Theme = "dracula"
98 }
99
100 if out.TimeFormat == "" {
101 out.TimeFormat = time.RFC3339
102 }
103
104 if out.CreateRepo == "" {
105 out.CreateRepo = "admin"
106 }
107
108 logger.Info(
109 "config",
110 "url", out.Url,
111 "data_dir", out.DataDir,
112 "host", out.Host,
113 "ssh_port", out.SshPort,
114 "web_port", out.WebPort,
115 "theme", out.Theme,
116 "time_format", out.TimeFormat,
117 "create_repo", out.CreateRepo,
118 "desc", out.Desc,
119 )
120
121 for _, pubkey := range out.AdminsStr {
122 logger.Info("admin", "pubkey", pubkey)
123 }
124
125 out.Logger = logger
126 return &out
127}