internal/control/deps.go

70dc0648f931f6f7112c6b71b0be485eeae4077f
gitbay/internal/control/deps.go history · blame · raw

110 lines · 3639 bytes

  1package control
  2
  3import (
  4	"errors"
  5	"fmt"
  6	"io"
  7
  8	"gitbay.org/gitbay/internal/policy"
  9	"gitbay.org/gitbay/internal/protocol"
 10	"gitbay.org/gitbay/internal/store"
 11)
 12
 13func init() {
 14	// Dependency update checks. Opt-in per repository: the check tells a
 15	// public registry what the repository depends on, which is the owner's
 16	// disclosure to make, not the instance's.
 17	register(Command{Path: []string{"repo", "deps", "enable"},
 18		Summary: "check dependencies for updates",
 19		Usage:   "repo deps enable <owner/name>", Run: runDepsEnable})
 20	register(Command{Path: []string{"repo", "deps", "disable"},
 21		Summary: "stop checking dependencies",
 22		Usage:   "repo deps disable <owner/name>", Run: runDepsDisable})
 23	register(Command{Path: []string{"repo", "deps", "status"},
 24		Summary: "show dependency check state",
 25		Usage:   "repo deps status <owner/name>", ReadOnly: true, Run: runDepsStatus})
 26}
 27
 28func runDepsEnable(c *Ctx, args []string) int {
 29	if len(args) != 1 {
 30		return c.fail(protocol.ExitUsage, "usage: repo deps enable <owner/name>")
 31	}
 32	repo, code := resolveRepo(c, args[0], policy.CanAdmin)
 33	if code >= 0 {
 34		return code
 35	}
 36	if err := c.Store.EnableDepCheck(repo.ID); err != nil {
 37		return c.fail(protocol.ExitFailure, "%v", err)
 38	}
 39	return c.emit(map[string]any{"enabled": true}, func(w io.Writer) {
 40		fmt.Fprintf(w, "dependency checks enabled on %s\n", repo.Path())
 41	})
 42}
 43
 44func runDepsDisable(c *Ctx, args []string) int {
 45	if len(args) != 1 {
 46		return c.fail(protocol.ExitUsage, "usage: repo deps disable <owner/name>")
 47	}
 48	repo, code := resolveRepo(c, args[0], policy.CanAdmin)
 49	if code >= 0 {
 50		return code
 51	}
 52	if err := c.Store.DisableDepCheck(repo.ID); err != nil {
 53		return c.fail(protocol.ExitFailure, "%v", err)
 54	}
 55	return c.emit(map[string]any{"enabled": false}, func(w io.Writer) {
 56		fmt.Fprintf(w, "dependency checks disabled on %s\n", repo.Path())
 57	})
 58}
 59
 60func runDepsStatus(c *Ctx, args []string) int {
 61	if len(args) != 1 {
 62		return c.fail(protocol.ExitUsage, "usage: repo deps status <owner/name>")
 63	}
 64	repo, code := resolveRepo(c, args[0], policy.CanRead)
 65	if code >= 0 {
 66		return code
 67	}
 68	check, err := c.Store.DepCheckFor(repo.ID)
 69	if errors.Is(err, store.ErrNotFound) {
 70		return c.emit(map[string]any{"enabled": false}, func(w io.Writer) {
 71			fmt.Fprintf(w, "dependency checks are off for %s (repo deps enable %s)\n", repo.Path(), repo.Path())
 72		})
 73	}
 74	if err != nil {
 75		return c.fail(protocol.ExitFailure, "%v", err)
 76	}
 77	reports, err := c.Store.ReportedDeps(repo.ID)
 78	if err != nil {
 79		return c.fail(protocol.ExitFailure, "%v", err)
 80	}
 81	type behind struct {
 82		Ecosystem string `json:"ecosystem"`
 83		Name      string `json:"name"`
 84		Current   string `json:"current"`
 85		Latest    string `json:"latest"`
 86	}
 87	out := struct {
 88		Enabled     bool     `json:"enabled"`
 89		LastCheck   string   `json:"last_check,omitempty"`
 90		LastError   string   `json:"last_error,omitempty"`
 91		IssueNumber int64    `json:"issue_number,omitempty"`
 92		Behind      []behind `json:"behind"`
 93	}{Enabled: true, LastCheck: check.LastCheck, LastError: check.LastError,
 94		IssueNumber: check.IssueNumber, Behind: []behind{}}
 95	for _, r := range reports {
 96		out.Behind = append(out.Behind, behind{r.Ecosystem, r.Name, r.Current, r.Latest})
 97	}
 98	return c.emit(out, func(w io.Writer) {
 99		fmt.Fprintf(w, "checks on, last %s\n", orDash(check.LastCheck))
100		if check.LastError != "" {
101			fmt.Fprintf(w, "last error: %s\n", check.LastError)
102		}
103		if check.IssueNumber != 0 {
104			fmt.Fprintf(w, "tracked in #%d\n", check.IssueNumber)
105		}
106		for _, b := range out.Behind {
107			fmt.Fprintf(w, "%s\t%s\t%s\t-> %s\n", b.Ecosystem, b.Name, b.Current, b.Latest)
108		}
109	})
110}