Federated via graft
0

Configure Feed

Select the types of activity you want to include in your feed.

graft-source / cmd / sync / main.go
2.0 kB 90 lines
1// Command sync runs the Forgejo <-> Radicle sync daemon: on an interval, it 2// mirrors git content, issues and patches for every repo pair listed in the 3// config file, then sleeps until the next pass. 4package main 5 6import ( 7 "flag" 8 "log/slog" 9 "net/http" 10 "os" 11 "time" 12 13 "graft/internal/config" 14 "graft/internal/state" 15 "graft/internal/status" 16 "graft/internal/sync" 17) 18 19func main() { 20 configPath := flag.String("config", "/etc/graft/config.yaml", "path to config.yaml") 21 once := flag.Bool("once", false, "run a single pass and exit, instead of looping") 22 listen := flag.String("listen", ":8090", "address to serve /healthz and / (status) on; empty disables it") 23 flag.Parse() 24 25 log := slog.New(slog.NewJSONHandler(os.Stdout, nil)) 26 27 cfg, err := config.Load(*configPath) 28 if err != nil { 29 log.Error("load config", "err", err) 30 os.Exit(1) 31 } 32 33 st, err := state.Open(cfg.StateDB) 34 if err != nil { 35 log.Error("open state db", "err", err) 36 os.Exit(1) 37 } 38 defer st.Close() 39 40 stateDir := cfg.StateDB 41 if idx := lastSlash(stateDir); idx >= 0 { 42 stateDir = stateDir[:idx] 43 } 44 45 syncers := make([]*sync.RepoSyncer, 0, len(cfg.Repos)) 46 for _, pair := range cfg.Repos { 47 rs, err := sync.New(pair, st, sync.WorkDirFor(stateDir, pair.Name)) 48 if err != nil { 49 log.Error("set up repo pair", "pair", pair.Name, "err", err) 50 os.Exit(1) 51 } 52 syncers = append(syncers, rs) 53 } 54 55 tracker := status.NewTracker(st) 56 runAll := func() { 57 for _, rs := range syncers { 58 gitErr, issuesErr, patchErr := rs.Run(log) 59 tracker.Record(rs.Name(), gitErr, issuesErr, patchErr) 60 } 61 } 62 63 if *listen != "" { 64 go func() { 65 if err := http.ListenAndServe(*listen, tracker.Handler()); err != nil { 66 log.Error("status server stopped", "err", err) 67 } 68 }() 69 } 70 71 runAll() 72 if *once { 73 return 74 } 75 76 ticker := time.NewTicker(cfg.SyncInterval) 77 defer ticker.Stop() 78 for range ticker.C { 79 runAll() 80 } 81} 82 83func lastSlash(s string) int { 84 for i := len(s) - 1; i >= 0; i-- { 85 if s[i] == '/' { 86 return i 87 } 88 } 89 return -1 90}