Skip to content

Commit 7ea04c0

Browse files
committed
feat: add git garbage collector cronjob
1 parent 1959b0f commit 7ea04c0

3 files changed

Lines changed: 73 additions & 2 deletions

File tree

cmd/soft/serve/server.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,11 @@ func NewServer(ctx context.Context) (*Server, error) {
5959
// Add cron jobs.
6060
sched := cron.NewScheduler(ctx)
6161
for n, j := range jobs.List() {
62-
id, err := sched.AddFunc(j.Runner.Spec(ctx), j.Runner.Func(ctx))
62+
spec := j.Runner.Spec(ctx)
63+
if spec == "" {
64+
continue
65+
}
66+
id, err := sched.AddFunc(spec, j.Runner.Func(ctx))
6367
if err != nil {
6468
logger.Warn("error adding cron job", "job", n, "err", err)
6569
}
@@ -183,7 +187,10 @@ func (s *Server) Shutdown(ctx context.Context) error {
183187
})
184188
errg.Go(func() error {
185189
for _, j := range jobs.List() {
186-
s.Cron.Remove(j.ID)
190+
// jobID from github.com/robfig/cron/v2 starts from 1
191+
if j.ID != 0 {
192+
s.Cron.Remove(j.ID)
193+
}
187194
}
188195
s.Cron.Stop()
189196
return nil

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ type LFSConfig struct {
137137
// JobsConfig is the configuration for cron jobs.
138138
type JobsConfig struct {
139139
MirrorPull string `env:"MIRROR_PULL" yaml:"mirror_pull"`
140+
GitGC string `env:"GIT_GC" yaml:"git_gc"`
140141
}
141142

142143
// Config is the configuration for Soft Serve.

pkg/jobs/garbage_collector.go

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package jobs
2+
3+
import (
4+
"context"
5+
"runtime"
6+
7+
"charm.land/log/v2"
8+
"github.com/charmbracelet/soft-serve/git"
9+
"github.com/charmbracelet/soft-serve/pkg/backend"
10+
"github.com/charmbracelet/soft-serve/pkg/config"
11+
"github.com/charmbracelet/soft-serve/pkg/sync"
12+
)
13+
14+
func init() {
15+
Register("git-gc", gitGC{})
16+
}
17+
18+
type gitGC struct{}
19+
20+
func (g gitGC) Spec(ctx context.Context) string {
21+
cfg := config.FromContext(ctx)
22+
if cfg.Jobs.GitGC != "" {
23+
return cfg.Jobs.GitGC
24+
}
25+
return ""
26+
}
27+
28+
func (g gitGC) Func(ctx context.Context) func() {
29+
b := backend.FromContext(ctx)
30+
logger := log.FromContext(ctx).WithPrefix("jobs.gitgc")
31+
return func() {
32+
repos, err := b.Repositories(ctx)
33+
if err != nil {
34+
logger.Error("error getting repositories", "err", err)
35+
return
36+
}
37+
38+
wq := sync.NewWorkPool(ctx, runtime.GOMAXPROCS(0),
39+
sync.WithWorkPoolLogger(logger.Errorf),
40+
)
41+
42+
logger.Debug("cleaning git garbage")
43+
for _, repo := range repos {
44+
r, err := repo.Open()
45+
if err != nil {
46+
logger.Error("error opening repository", "repo", repo.Name(), "err", err)
47+
continue
48+
}
49+
50+
name := repo.Name()
51+
wq.Add(name, func() {
52+
cmd := git.NewCommand("gc").WithContext(ctx)
53+
if _, err := cmd.RunInDir(r.Path); err != nil {
54+
logger.Error("error running git remote update", "repo", name, "err", err)
55+
}
56+
57+
})
58+
59+
// TODO: clean up lfs
60+
}
61+
62+
}
63+
}

0 commit comments

Comments
 (0)