diff --git a/buildmanager.go b/buildmanager.go index fbf12da..16c8eda 100644 --- a/buildmanager.go +++ b/buildmanager.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "github.com/c2h5oh/datasize" + "github.com/prometheus/client_golang/prometheus" "github.com/sethvargo/go-retry" log "github.com/sirupsen/logrus" "os" @@ -26,6 +27,9 @@ type BuildManager struct { building []*ProtoPackage buildingLock *sync.RWMutex queueSignal chan struct{} + metrics struct { + queueSize *prometheus.GaugeVec + } } func (b *BuildManager) buildQueue(ctx context.Context, queue []*ProtoPackage) error { @@ -80,6 +84,7 @@ func (b *BuildManager) buildQueue(ctx context.Context, queue []*ProtoPackage) er doneQLock.Lock() doneQ = append(doneQ, pkg) doneQLock.Unlock() + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "queued").Dec() continue } @@ -106,14 +111,18 @@ func (b *BuildManager) buildQueue(ctx context.Context, queue []*ProtoPackage) er b.building = append(b.building, pkg) b.buildingLock.Unlock() queueNoMatch = false + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "queued").Dec() + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "building").Inc() go func(pkg *ProtoPackage) { dur, err := pkg.build(ctx) + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "building").Dec() if err != nil && !errors.Is(err, ErrorNotEligible) { log.Warningf("[Q] error building package %s->%s in %s: %s", pkg.FullRepo, pkg.Pkgbase, dur, err) b.repoPurge[pkg.FullRepo] <- []*ProtoPackage{pkg} } else if err == nil { log.Infof("[Q] build successful: %s->%s (%s)", pkg.FullRepo, pkg.Pkgbase, dur) + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "built").Inc() } doneQLock.Lock() b.buildingLock.Lock() @@ -147,7 +156,7 @@ func (b *BuildManager) buildQueue(ctx context.Context, queue []*ProtoPackage) er return nil } -func (b *BuildManager) repoWorker(repo string) { +func (b *BuildManager) repoWorker(ctx context.Context, repo string) { for { select { case pkgL := <-b.repoAdd[repo]: @@ -159,7 +168,7 @@ func (b *BuildManager) repoWorker(repo string) { args := []string{"-s", "-v", "-p", "-n", filepath.Join(conf.Basedir.Repo, repo, "os", conf.Arch, repo) + ".db.tar.xz"} args = append(args, toAdd...) - cmd := exec.Command("repo-add", args...) + cmd := exec.CommandContext(ctx, "repo-add", args...) res, err := cmd.CombinedOutput() log.Debug(string(res)) if err != nil && cmd.ProcessState.ExitCode() != 1 { @@ -167,7 +176,7 @@ func (b *BuildManager) repoWorker(repo string) { } for _, pkg := range pkgL { - err = pkg.toDBPackage(true) + err = pkg.toDBPackage(ctx, true) if err != nil { log.Warningf("error getting db entry for %s: %v", pkg.Pkgbase, err) continue @@ -185,10 +194,12 @@ func (b *BuildManager) repoWorker(repo string) { } else { pkgUpd = pkgUpd.SetDebugSymbols(dbpackage.DebugSymbolsNotAvailable) } - pkg.DBPackage = pkgUpd.SaveX(context.Background()) + if pkg.DBPackage, err = pkgUpd.Save(ctx); err != nil { + log.Error(err) + } } - cmd = exec.Command("paccache", "-rc", filepath.Join(conf.Basedir.Repo, repo, "os", conf.Arch), "-k", "1") //nolint:gosec + cmd = exec.CommandContext(ctx, "paccache", "-rc", filepath.Join(conf.Basedir.Repo, repo, "os", conf.Arch), "-k", "1") //nolint:gosec res, err = cmd.CombinedOutput() log.Debug(string(res)) if err != nil { @@ -211,7 +222,10 @@ func (b *BuildManager) repoWorker(repo string) { continue } else if len(pkg.PkgFiles) == 0 { if pkg.DBPackage != nil { - _ = pkg.DBPackage.Update().ClearRepoVersion().ClearTagRev().Exec(context.Background()) + err = pkg.DBPackage.Update().ClearRepoVersion().ClearTagRev().Exec(ctx) + if err != nil { + log.Error(err) + } } continue } @@ -231,7 +245,7 @@ func (b *BuildManager) repoWorker(repo string) { b.repoWG.Add(1) args := []string{"-s", "-v", filepath.Join(conf.Basedir.Repo, pkg.FullRepo, "os", conf.Arch, pkg.FullRepo) + ".db.tar.xz"} args = append(args, realPkgs...) - cmd := exec.Command("repo-remove", args...) + cmd := exec.CommandContext(ctx, "repo-remove", args...) res, err := cmd.CombinedOutput() log.Debug(string(res)) if err != nil && cmd.ProcessState.ExitCode() == 1 { @@ -239,7 +253,10 @@ func (b *BuildManager) repoWorker(repo string) { } if pkg.DBPackage != nil { - _ = pkg.DBPackage.Update().ClearRepoVersion().ClearTagRev().Exec(context.Background()) + err = pkg.DBPackage.Update().ClearRepoVersion().ClearTagRev().Exec(ctx) + if err != nil { + log.Error(err) + } } for _, file := range pkg.PkgFiles { @@ -265,14 +282,14 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { gitPath := filepath.Join(conf.Basedir.Work, stateDir) for { if _, err := os.Stat(gitPath); os.IsNotExist(err) { - cmd := exec.Command("git", "clone", "--depth=1", conf.StateRepo, gitPath) //nolint:gosec + cmd := exec.CommandContext(ctx, "git", "clone", "--depth=1", conf.StateRepo, gitPath) //nolint:gosec res, err := cmd.CombinedOutput() log.Debug(string(res)) if err != nil { log.Fatalf("error cloning state repo: %v", err) } } else if err == nil { - cmd := exec.Command("git", "reset", "--hard") + cmd := exec.CommandContext(ctx, "git", "reset", "--hard") cmd.Dir = gitPath res, err := cmd.CombinedOutput() log.Debug(string(res)) @@ -280,7 +297,7 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { log.Fatalf("error reseting state repo: %v", err) } - cmd = exec.Command("git", "pull") + cmd = exec.CommandContext(ctx, "git", "pull") cmd.Dir = gitPath res, err = cmd.CombinedOutput() log.Debug(string(res)) @@ -294,8 +311,8 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { for _, repo := range repos { wg.Add(1) splitRepo := strings.Split(repo, "-") - go func() { //nolint:contextcheck - err := housekeeping(splitRepo[0], strings.Join(splitRepo[1:], "-"), wg) + go func() { + err := housekeeping(ctx, splitRepo[0], strings.Join(splitRepo[1:], "-"), wg) if err != nil { log.Warningf("[%s] housekeeping failed: %v", repo, err) } @@ -303,7 +320,7 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { } wg.Wait() - err := logHK() //nolint:contextcheck + err := logHK(ctx) if err != nil { log.Warningf("log-housekeeping failed: %v", err) } @@ -317,7 +334,7 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { } if err := retry.Fibonacci(ctx, 1*time.Second, func(_ context.Context) error { - if err := setupChroot(); err != nil { + if err := setupChroot(ctx); err != nil { log.Warningf("unable to upgrade chroot, trying again later") return retry.RetryableError(err) } @@ -333,20 +350,21 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { } b.alpmMutex.Unlock() - queue, err := b.genQueue() //nolint:contextcheck + queue, err := b.genQueue(ctx) if err != nil { log.Errorf("error building queue: %v", err) - } else { - log.Debugf("build-queue with %d items", len(queue)) - err = b.buildQueue(ctx, queue) - if err != nil { - return err - } + return err + } + + log.Debugf("build-queue with %d items", len(queue)) + err = b.buildQueue(ctx, queue) + if err != nil { + return err } if ctx.Err() == nil { for _, repo := range repos { - err = movePackagesLive(repo) //nolint:contextcheck + err = movePackagesLive(ctx, repo) if err != nil { log.Errorf("[%s] error moving packages live: %v", repo, err) } @@ -355,12 +373,13 @@ func (b *BuildManager) syncWorker(ctx context.Context) error { return ctx.Err() } + b.metrics.queueSize.Reset() log.Debugf("build-cycle finished") time.Sleep(time.Duration(*checkInterval) * time.Minute) } } -func (b *BuildManager) genQueue() ([]*ProtoPackage, error) { +func (b *BuildManager) genQueue(ctx context.Context) ([]*ProtoPackage, error) { stateFiles, err := Glob(filepath.Join(conf.Basedir.Work, stateDir, "**/*")) if err != nil { return nil, fmt.Errorf("error scanning for state-files: %w", err) @@ -406,13 +425,13 @@ func (b *BuildManager) genQueue() ([]*ProtoPackage, error) { Arch: arch, } - err = pkg.toDBPackage(false) + err = pkg.toDBPackage(ctx, false) if err != nil { log.Warningf("[QG] error getting/creating dbpackage %s: %v", state.Pkgbase, err) continue } - if !pkg.isAvailable(alpmHandle) { + if !pkg.isAvailable(ctx, alpmHandle) { log.Debugf("[QG] %s->%s not available on mirror, skipping build", pkg.FullRepo, pkg.Pkgbase) continue } @@ -427,7 +446,7 @@ func (b *BuildManager) genQueue() ([]*ProtoPackage, error) { } if pkg.DBPackage == nil { - err = pkg.toDBPackage(true) + err = pkg.toDBPackage(ctx, true) if err != nil { log.Warningf("[QG] error getting/creating dbpackage %s: %v", state.Pkgbase, err) continue @@ -444,12 +463,16 @@ func (b *BuildManager) genQueue() ([]*ProtoPackage, error) { pkg.Srcinfo = srcInfo } - if !pkg.isEligible(context.Background()) { + if !pkg.isEligible(ctx) { continue } - pkg.DBPackage = pkg.DBPackage.Update().SetStatus(dbpackage.StatusQueued).SaveX(context.Background()) + pkg.DBPackage, err = pkg.DBPackage.Update().SetStatus(dbpackage.StatusQueued).Save(ctx) + if err != nil { + log.Warningf("[QG] error updating dbpackage %s: %v", state.Pkgbase, err) + } pkgbuilds = append(pkgbuilds, pkg) + b.metrics.queueSize.WithLabelValues(pkg.FullRepo, "queued").Inc() } } diff --git a/config_dist.yaml b/config_dist.yaml index 6dfae1f..5fd7519 100644 --- a/config_dist.yaml +++ b/config_dist.yaml @@ -44,4 +44,7 @@ build: memory_limit: "16gb" logging: - level: INFO \ No newline at end of file + level: INFO + +metrics: + port: 9568 diff --git a/ent/runtime/runtime.go b/ent/runtime/runtime.go index 8c1160f..1f850a2 100644 --- a/ent/runtime/runtime.go +++ b/ent/runtime/runtime.go @@ -5,6 +5,6 @@ package runtime // The schema-stitching logic is generated in somegit.dev/ALHP/ALHP.GO/ent/runtime.go const ( - Version = "v0.14.1" // Version of ent codegen. - Sum = "h1:fUERL506Pqr92EPHJqr8EYxbPioflJo6PudkrEA8a/s=" // Sum of ent codegen. + Version = "v0.14.2" // Version of ent codegen. + Sum = "h1:ywld/j2Rx4EmnIKs8eZ29cbFA1zpB+DA9TLL5l3rlq0=" // Sum of ent codegen. ) diff --git a/go.mod b/go.mod index 9135b08..e671145 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.23.0 toolchain go1.23.1 require ( - entgo.io/ent v0.14.1 + entgo.io/ent v0.14.2 github.com/Jguer/go-alpm/v2 v2.2.2 github.com/Morganamilo/go-pacmanconf v0.0.0-20210502114700-cff030e927a5 github.com/Morganamilo/go-srcinfo v1.0.0 @@ -14,6 +14,7 @@ require ( github.com/google/uuid v1.6.0 github.com/jackc/pgx/v4 v4.18.3 github.com/otiai10/copy v1.14.1 + github.com/prometheus/client_golang v1.21.0 github.com/sethvargo/go-retry v0.3.0 github.com/sirupsen/logrus v1.9.3 github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117 @@ -21,13 +22,15 @@ require ( ) require ( - ariga.io/atlas v0.30.0 // indirect + ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect + github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar v1.3.4 // indirect + github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect github.com/go-openapi/inflect v0.21.0 // indirect - github.com/google/go-cmp v0.6.0 // indirect + github.com/google/go-cmp v0.7.0 // indirect github.com/hashicorp/hcl/v2 v2.23.0 // indirect github.com/jackc/chunkreader/v2 v2.0.1 // indirect github.com/jackc/pgconn v1.14.3 // indirect @@ -36,15 +39,20 @@ require ( github.com/jackc/pgproto3/v2 v2.3.3 // indirect github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/pgtype v1.14.4 // indirect - github.com/kr/pretty v0.3.0 // indirect + github.com/klauspost/compress v1.17.11 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect + github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/otiai10/mint v1.6.3 // indirect + github.com/prometheus/client_model v0.6.1 // indirect + github.com/prometheus/common v0.62.0 // indirect + github.com/prometheus/procfs v0.15.1 // indirect github.com/zclconf/go-cty v1.16.2 // indirect - golang.org/x/crypto v0.32.0 // indirect - golang.org/x/mod v0.22.0 // indirect - golang.org/x/sync v0.10.0 // indirect - golang.org/x/sys v0.29.0 // indirect - golang.org/x/text v0.21.0 // indirect - golang.org/x/tools v0.29.0 // indirect - gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect + github.com/zclconf/go-cty-yaml v1.1.0 // indirect + golang.org/x/crypto v0.33.0 // indirect + golang.org/x/mod v0.23.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/sys v0.30.0 // indirect + golang.org/x/text v0.22.0 // indirect + golang.org/x/tools v0.30.0 // indirect + google.golang.org/protobuf v1.36.1 // indirect ) diff --git a/go.sum b/go.sum index a3a05ed..01a3f68 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -ariga.io/atlas v0.30.0 h1:Tyi4A1LXDp9VB+EO51e8Xacsw31uJge9fr5pmd3TL9U= -ariga.io/atlas v0.30.0/go.mod h1:lkLAw/t2/P7g5CFYlYmHvNuShlmGujwm3OGsW00xowI= -entgo.io/ent v0.14.1 h1:fUERL506Pqr92EPHJqr8EYxbPioflJo6PudkrEA8a/s= -entgo.io/ent v0.14.1/go.mod h1:MH6XLG0KXpkcDQhKiHfANZSzR55TJyPL5IGNpI8wpco= +ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83 h1:nX4HXncwIdvQ8/8sIUIf1nyCkK8qdBaHQ7EtzPpuiGE= +ariga.io/atlas v0.31.1-0.20250212144724-069be8033e83/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w= +entgo.io/ent v0.14.2 h1:ywld/j2Rx4EmnIKs8eZ29cbFA1zpB+DA9TLL5l3rlq0= +entgo.io/ent v0.14.2/go.mod h1:aDPE/OziPEu8+OWbzy4UlvWmD2/kbRuWfK2A40hcxJM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= @@ -17,10 +17,14 @@ github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7l github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558= github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY= github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0= github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE= github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500 h1:6lhrsTEnloDPXyeZBvSYvQf8u86jbKehZPVDDlkgDl4= github.com/c2h5oh/datasize v0.0.0-20231215233829-aa82cc1e6500/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= +github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= +github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= @@ -28,7 +32,6 @@ github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7 github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -43,8 +46,8 @@ github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= +github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -101,17 +104,23 @@ github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0f github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.3.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= +github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc= +github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= @@ -126,6 +135,8 @@ github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwp github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0= github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= +github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8= github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I= github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs= @@ -134,9 +145,17 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prometheus/client_golang v1.21.0 h1:DIsaGmiaBkSangBgMtWdNfxbMNdku5IK6iNhrEqWvdA= +github.com/prometheus/client_golang v1.21.0/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg= +github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E= +github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY= +github.com/prometheus/common v0.62.0 h1:xasJaQlnWAeyHdUBeGjXmutelfJHWMRr+Fg4QszZ2Io= +github.com/prometheus/common v0.62.0/go.mod h1:vyBcEuLSvWos9B1+CyL7JZ2up+uFzXhkqml0W5zIY1I= +github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= +github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= +github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= @@ -163,8 +182,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117 h1:67A5tweHp3C7osHjrYsy6pQZ00bYkTTttZ7kiOwwHeA= github.com/wercker/journalhook v0.0.0-20230927020745-64542ffa4117/go.mod h1:XCsSkdKK4gwBMNrOCZWww0pX6AOt+2gYc5Z6jBRrNVg= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -172,6 +191,8 @@ github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70 github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo= github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM= +github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0= +github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs= github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= @@ -196,15 +217,15 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.20.0/go.mod h1:Xwo95rrVNIoSMx9wa1JroENMToLWn3RNVrTBpLHgZPQ= -golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc= -golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= -golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -217,8 +238,8 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ= -golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -237,8 +258,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU= -golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -254,8 +275,8 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo= -golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= @@ -267,17 +288,19 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.29.0 h1:Xx0h3TtM9rzQpQuR4dKLrdglAmCEN5Oi+P74JdhdzXE= -golang.org/x/tools v0.29.0/go.mod h1:KMQVMRsVxU6nHCFXrBPhDB8XncLNLM0lIy/F14RP588= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk= +google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/housekeeping.go b/housekeeping.go index 3cc3912..02c7c05 100644 --- a/housekeeping.go +++ b/housekeeping.go @@ -13,7 +13,7 @@ import ( "time" ) -func housekeeping(repo, march string, wg *sync.WaitGroup) error { +func housekeeping(ctx context.Context, repo, march string, wg *sync.WaitGroup) error { defer wg.Done() fullRepo := repo + "-" + march log.Debugf("[%s] start housekeeping", fullRepo) @@ -26,7 +26,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { for _, path := range packages { mPackage := Package(path) - dbPkg, err := mPackage.DBPackage(db) + dbPkg, err := mPackage.DBPackage(ctx, db) if ent.IsNotFound(err) { log.Infof("[HK] removing orphan %s->%s", fullRepo, filepath.Base(path)) pkg := &ProtoPackage{ @@ -89,7 +89,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { log.Errorf("[HK] %s->%s unable to get pkg-files: %v", pkg.FullRepo, mPackage.Name(), err) continue } - err = db.DBPackage.DeleteOne(pkg.DBPackage).Exec(context.Background()) + err = db.DBPackage.DeleteOne(pkg.DBPackage).Exec(ctx) pkg.DBPackage = nil buildManager.repoPurge[pkg.FullRepo] <- []*ProtoPackage{pkg} if err != nil { @@ -99,7 +99,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { } if pkg.DBPackage.LastVerified.Before(pkg.DBPackage.BuildTimeStart) { - err := pkg.DBPackage.Update().SetLastVerified(time.Now().UTC()).Exec(context.Background()) + err := pkg.DBPackage.Update().SetLastVerified(time.Now().UTC()).Exec(ctx) if err != nil { return err } @@ -147,7 +147,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { DBPackage: dbPkg, } - if !pkg.isAvailable(alpmHandle) { + if !pkg.isAvailable(ctx, alpmHandle) { log.Infof("[HK] %s->%s not found on mirror, removing", pkg.FullRepo, pkg.Pkgbase) err = db.DBPackage.DeleteOne(dbPkg).Exec(context.Background()) if err != nil { @@ -161,9 +161,11 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { // check lastVersionBuild if dbPkg.LastVersionBuild != dbPkg.RepoVersion { log.Infof("[HK] %s->%s updating lastVersionBuild %s -> %s", fullRepo, dbPkg.Pkgbase, dbPkg.LastVersionBuild, dbPkg.RepoVersion) - dbPkg, err = dbPkg.Update().SetLastVersionBuild(dbPkg.RepoVersion).Save(context.Background()) + nDBPkg, err := dbPkg.Update().SetLastVersionBuild(dbPkg.RepoVersion).Save(ctx) if err != nil { log.Warningf("[HK] error updating lastVersionBuild for %s->%s: %v", fullRepo, dbPkg.Pkgbase, err) + } else { + dbPkg = nDBPkg } } @@ -188,7 +190,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { ClearRepoVersion(). ClearTagRev(). SetStatus(dbpackage.StatusQueued). - Save(context.Background()) + Save(ctx) if err != nil { return err } @@ -224,14 +226,14 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { if dbPkg.TagRev != nil && state.TagRev == *dbPkg.TagRev && state.PkgVer != dbPkg.Version { log.Infof("[HK] reseting package %s->%s with mismatched state information (%s!=%s)", fullRepo, dbPkg.Pkgbase, state.PkgVer, dbPkg.Version) - err = dbPkg.Update().SetStatus(dbpackage.StatusQueued).ClearTagRev().Exec(context.Background()) + err = dbPkg.Update().SetStatus(dbpackage.StatusQueued).ClearTagRev().Exec(ctx) if err != nil { return err } } case dbPkg.Status == dbpackage.StatusLatest && dbPkg.RepoVersion == "": log.Infof("[HK] reseting missing package %s->%s with no repo version", fullRepo, dbPkg.Pkgbase) - err = dbPkg.Update().SetStatus(dbpackage.StatusQueued).ClearTagRev().ClearRepoVersion().Exec(context.Background()) + err = dbPkg.Update().SetStatus(dbpackage.StatusQueued).ClearTagRev().ClearRepoVersion().Exec(ctx) if err != nil { return err } @@ -264,7 +266,7 @@ func housekeeping(repo, march string, wg *sync.WaitGroup) error { return nil } -func logHK() error { +func logHK(ctx context.Context) error { // check if package for log exists and if error can be fixed by rebuild logFiles, err := Glob(filepath.Join(conf.Basedir.Repo, logDir, "/**/*.log")) if err != nil { @@ -293,7 +295,7 @@ func logHK() error { dbpackage.Pkgbase(pkg.Pkgbase), dbpackage.March(pkg.March), dbpackage.StatusEQ(dbpackage.StatusSkipped), - ).Exist(context.Background()) + ).Exist(ctx) if err != nil { return err } @@ -312,7 +314,7 @@ func logHK() error { if rePortError.MatchString(sLogContent) || reSigError.MatchString(sLogContent) || reDownloadError.MatchString(sLogContent) || reDownloadError2.MatchString(sLogContent) { rows, err := db.DBPackage.Update().Where(dbpackage.Pkgbase(pkg.Pkgbase), dbpackage.March(pkg.March), - dbpackage.StatusEQ(dbpackage.StatusFailed)).ClearTagRev().SetStatus(dbpackage.StatusQueued).Save(context.Background()) + dbpackage.StatusEQ(dbpackage.StatusFailed)).ClearTagRev().SetStatus(dbpackage.StatusQueued).Save(ctx) if err != nil { return err } @@ -326,7 +328,7 @@ func logHK() error { dbpackage.March(pkg.March), dbpackage.StatusEQ(dbpackage.StatusFailed), dbpackage.LtoNotIn(dbpackage.LtoAutoDisabled, dbpackage.LtoDisabled), - ).ClearTagRev().SetStatus(dbpackage.StatusQueued).SetLto(dbpackage.LtoAutoDisabled).Save(context.Background()) + ).ClearTagRev().SetStatus(dbpackage.StatusQueued).SetLto(dbpackage.LtoAutoDisabled).Save(ctx) if err != nil { return err } @@ -343,7 +345,7 @@ func debugHK() { for _, march := range conf.March { if _, err := os.Stat(filepath.Join(conf.Basedir.Debug, march)); err == nil { log.Debugf("[DHK/%s] start cleanup debug packages", march) - cleanCmd := exec.Command("paccache", "-rc", filepath.Join(conf.Basedir.Debug, march), "-k", "1") //nolint:gosec + cleanCmd := exec.Command("paccache", "-rc", filepath.Join(conf.Basedir.Debug, march), "-k", "1") res, err := cleanCmd.CombinedOutput() if err != nil { log.Warningf("[DHK/%s] cleanup debug packages failed: %v (%s)", march, err, string(res)) diff --git a/main.go b/main.go index e5664be..e2e61e5 100644 --- a/main.go +++ b/main.go @@ -86,7 +86,8 @@ func main() { }(db) } - if err := db.Schema.Create(context.Background(), migrate.WithDropIndex(true), migrate.WithDropColumn(true)); err != nil { + ctx, cancel := context.WithCancel(context.Background()) + if err := db.Schema.Create(ctx, migrate.WithDropIndex(true), migrate.WithDropColumn(true)); err != nil { log.Panicf("automigrate failed: %v", err) } @@ -100,11 +101,13 @@ func main() { repoWG: new(sync.WaitGroup), } - err = setupChroot() + buildManager.setupMetrics(conf.MetricsPort) + + err = setupChroot(ctx) if err != nil { log.Panicf("unable to setup chroot: %v", err) } - err = syncMarchs() + err = syncMarchs(ctx) if err != nil { log.Panicf("error syncing marchs: %v", err) } @@ -115,8 +118,6 @@ func main() { log.Panicf("error while ALPM-init: %v", err) } - ctx, cancel := context.WithCancel(context.Background()) - go func() { _ = buildManager.syncWorker(ctx) }() diff --git a/metrics.go b/metrics.go new file mode 100644 index 0000000..cda067a --- /dev/null +++ b/metrics.go @@ -0,0 +1,25 @@ +package main + +import ( + "fmt" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/promhttp" + log "github.com/sirupsen/logrus" + "net/http" +) + +func (b *BuildManager) setupMetrics(port uint32) { + b.metrics.queueSize = prometheus.NewGaugeVec(prometheus.GaugeOpts{ + Name: "build_queue_size", + Help: "Build queue size", + }, []string{"repository", "status"}) + + mux := http.NewServeMux() + mux.Handle("/", promhttp.Handler()) + go func() { + err := http.ListenAndServe(fmt.Sprintf(":%d", port), mux) //nolint:gosec + if err != nil { + log.Errorf("failed to start metrics server: %v", err) + } + }() +} diff --git a/package.go b/package.go index a737691..5e990b2 100644 --- a/package.go +++ b/package.go @@ -70,12 +70,12 @@ func (pkg Package) HasValidSignature() (bool, error) { } // DBPackage returns ent.DBPackage for package -func (pkg Package) DBPackage(db *ent.Client) (*ent.DBPackage, error) { - return pkg.DBPackageIsolated(*pkg.MArch(), pkg.Repo(), db) +func (pkg Package) DBPackage(ctx context.Context, db *ent.Client) (*ent.DBPackage, error) { + return pkg.DBPackageIsolated(ctx, *pkg.MArch(), pkg.Repo(), db) } // DBPackageIsolated returns ent.DBPackage like DBPackage, but not relying on the path for march and repo -func (pkg Package) DBPackageIsolated(march string, repo dbpackage.Repository, db *ent.Client) (*ent.DBPackage, error) { +func (pkg Package) DBPackageIsolated(ctx context.Context, march string, repo dbpackage.Repository, db *ent.Client) (*ent.DBPackage, error) { dbPkg, err := db.DBPackage.Query().Where(func(s *sql.Selector) { s.Where( sql.And( @@ -83,7 +83,7 @@ func (pkg Package) DBPackageIsolated(march string, repo dbpackage.Repository, db sql.EQ(dbpackage.FieldMarch, march), sql.EQ(dbpackage.FieldRepository, repo)), ) - }).Only(context.Background()) + }).Only(ctx) if ent.IsNotFound(err) { log.Debugf("not found in database: %s", pkg.Name()) return nil, err diff --git a/proto_package.go b/proto_package.go index 7659d6b..8b44e25 100644 --- a/proto_package.go +++ b/proto_package.go @@ -465,7 +465,7 @@ func (p *ProtoPackage) importKeys() error { return nil } -func (p *ProtoPackage) isAvailable(h *alpm.Handle) bool { +func (p *ProtoPackage) isAvailable(ctx context.Context, h *alpm.Handle) bool { dbs, err := h.SyncDBs() if err != nil { return false @@ -481,7 +481,7 @@ func (p *ProtoPackage) isAvailable(h *alpm.Handle) bool { case p.DBPackage != nil && len(p.DBPackage.Packages) > 0: pkg, err = dbs.FindSatisfier(p.DBPackage.Packages[0]) default: - cmd := exec.Command("unbuffer", "pacsift", "--exact", "--base="+p.Pkgbase, "--repo="+p.Repo.String(), //nolint:gosec + cmd := exec.CommandContext(ctx, "unbuffer", "pacsift", "--exact", "--base="+p.Pkgbase, "--repo="+p.Repo.String(), //nolint:gosec "--sysroot="+filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot)) var res []byte res, err = cmd.Output() @@ -508,7 +508,10 @@ func (p *ProtoPackage) isAvailable(h *alpm.Handle) bool { } if p.DBPackage != nil { - p.DBPackage = p.DBPackage.Update().SetPackages(splitPkgs).SaveX(context.Background()) + p.DBPackage, err = p.DBPackage.Update().SetPackages(splitPkgs).Save(ctx) + if err != nil { + return false + } } pkg, err = dbs.FindSatisfier(splitPkgs[0]) } else { @@ -651,8 +654,8 @@ func (p *ProtoPackage) findPkgFiles() error { if p.DBPackage != nil { realPkgs = append(realPkgs, p.DBPackage.Packages...) } else { - for _, realPkg := range p.Srcinfo.Packages { - realPkgs = append(realPkgs, realPkg.Pkgname) + for i := 0; i < len(p.Srcinfo.Packages); i++ { + realPkgs = append(realPkgs, p.Srcinfo.Packages[i].Pkgname) } } @@ -671,7 +674,7 @@ func (p *ProtoPackage) findPkgFiles() error { return nil } -func (p *ProtoPackage) toDBPackage(create bool) error { +func (p *ProtoPackage) toDBPackage(ctx context.Context, create bool) error { if p.DBPackage != nil { return nil } @@ -680,13 +683,16 @@ func (p *ProtoPackage) toDBPackage(create bool) error { dbpackage.Pkgbase(p.Pkgbase), dbpackage.March(p.March), dbpackage.RepositoryEQ(p.Repo), - ).Only(context.Background()) + ).Only(ctx) if err != nil && ent.IsNotFound(err) && create { - dbPkg = db.DBPackage.Create(). + dbPkg, err = db.DBPackage.Create(). SetPkgbase(p.Pkgbase). SetMarch(p.March). SetRepository(p.Repo). - SaveX(context.Background()) + Save(ctx) + if err != nil { + return err + } } else if err != nil && !ent.IsNotFound(err) { return err } diff --git a/utils.go b/utils.go index dac4c2b..ee35886 100644 --- a/utils.go +++ b/utils.go @@ -1,6 +1,7 @@ package main import ( + "context" "errors" "fmt" "github.com/Jguer/go-alpm/v2" @@ -86,6 +87,9 @@ type Conf struct { Interval string } MaxCloneRetries uint64 `yaml:"max_clone_retries"` + Metrics struct { + Port uint32 + } } type Globs []string @@ -167,7 +171,7 @@ func stateFileMeta(stateFile string) (repo string, subRepo *string, arch string, return } -func movePackagesLive(fullRepo string) error { +func movePackagesLive(ctx context.Context, fullRepo string) error { if _, err := os.Stat(filepath.Join(conf.Basedir.Work, waitingDir, fullRepo)); os.IsNotExist(err) { return nil } else if err != nil { @@ -187,7 +191,7 @@ func movePackagesLive(fullRepo string) error { for _, file := range pkgFiles { pkg := Package(file) - dbPkg, err := pkg.DBPackageIsolated(march, dbpackage.Repository(repo), db) + dbPkg, err := pkg.DBPackageIsolated(ctx, march, dbpackage.Repository(repo), db) if err != nil { if strings.HasSuffix(pkg.Name(), "-debug") { mkErr := os.MkdirAll(filepath.Join(conf.Basedir.Debug, march), 0o755) @@ -265,8 +269,8 @@ func packages2slice(pkgs any) []string { switch v := pkgs.(type) { case []srcinfo.Package: var sPkgs []string - for _, p := range v { - sPkgs = append(sPkgs, p.Pkgname) + for i := range v { + sPkgs = append(sPkgs, v[i].Pkgname) } return sPkgs @@ -329,12 +333,12 @@ func initALPM(root, dbpath string) (*alpm.Handle, error) { return h, nil } -func setupChroot() error { +func setupChroot(ctx context.Context) error { _, err := os.Stat(filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot)) switch { case err == nil: - cmd := exec.Command("arch-nspawn", "-C", pacmanConf, filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot), //nolint:gosec - "pacman", "-Syuu", "--noconfirm") + cmd := exec.CommandContext(ctx, "arch-nspawn", "-C", pacmanConf, //nolint:gosec + filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot), "pacman", "-Syuu", "--noconfirm") res, err := cmd.CombinedOutput() log.Debug(string(res)) if err != nil { @@ -345,7 +349,7 @@ func setupChroot() error { if err != nil { return err } - cmd := exec.Command("mkarchroot", "-C", pacmanConf, "-M", makepkgConf, //nolint:gosec + cmd := exec.CommandContext(ctx, "mkarchroot", "-C", pacmanConf, "-M", makepkgConf, //nolint:gosec filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot), "base-devel", "multilib-devel") res, err := cmd.CombinedOutput() log.Debug(string(res)) @@ -354,7 +358,7 @@ func setupChroot() error { } // copy pacman.conf into pristine chroot to enable multilib - cmd = exec.Command("sudo", "cp", pacmanConf, //nolint:gosec + cmd = exec.CommandContext(ctx, "sudo", "cp", pacmanConf, //nolint:gosec filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot, "etc/pacman.conf")) res, err = cmd.CombinedOutput() log.Debug(string(res)) @@ -363,7 +367,8 @@ func setupChroot() error { } // remove makepkg conf extension, they are covered by our custom makepkg - cmd = exec.Command("sudo", "rm_chroot.py", filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot, "etc/makepkg.conf.d")) + cmd = exec.CommandContext(ctx, "sudo", "rm_chroot.py", //nolint:gosec + filepath.Join(conf.Basedir.Work, chrootDir, pristineChroot, "etc/makepkg.conf.d")) res, err = cmd.CombinedOutput() log.Debug(string(res)) if err != nil { @@ -375,7 +380,7 @@ func setupChroot() error { return nil } -func syncMarchs() error { +func syncMarchs(ctx context.Context) error { files, err := os.ReadDir(conf.Basedir.Repo) if err != nil { return err @@ -409,7 +414,7 @@ func syncMarchs() error { repos = append(repos, fRepo) buildManager.repoAdd[fRepo] = make(chan []*ProtoPackage, 1000) buildManager.repoPurge[fRepo] = make(chan []*ProtoPackage, 1000) - go buildManager.repoWorker(fRepo) + go buildManager.repoWorker(ctx, fRepo) if _, err := os.Stat(filepath.Join(conf.Basedir.Repo, fRepo, "os", conf.Arch)); os.IsNotExist(err) { log.Debugf("creating path %s", filepath.Join(conf.Basedir.Repo, fRepo, "os", conf.Arch)) @@ -511,7 +516,7 @@ func parseFlagSection(section any, makepkgConf, march string) (string, error) { makepkgConf += fmt.Sprintf("\nexport %s=%s", strings.ToUpper(subSec.(string)), replaceStringsFromMap(sm, replaceMap)) continue case []string: - makepkgConf += fmt.Sprintf("\nexport %s=%q", strings.ToUpper(subSec.(string)), replaceStringsFromMap(strings.Join(sm, " "), replaceMap)) + makepkgConf += fmt.Sprintf("\nexport %s=%q", strings.ToUpper(subSec.(string)), replaceStringsFromMap(strings.Join(sm, " "), replaceMap)) //nolint:lll continue } }