From 6ef23a7c5bcc76663b5b008a3ddc9e580711ebe1 Mon Sep 17 00:00:00 2001 From: jolheiser Date: Sun, 20 Mar 2022 04:15:24 +0000 Subject: [PATCH] Refactor for ff, zerolog, and re-integrate SDK (#14) Reviewed-on: https://git.jojodev.com/jolheiser/vanity/pulls/14 --- .drone.yml | 43 ----- .gitignore | 6 +- .woodpecker.yml | 37 ++++ Makefile | 41 ---- cmd/add.go | 69 ------- cmd/cmd.go | 181 ------------------ cmd/flags/flags.go | 14 -- cmd/remove.go | 67 ------- cmd/server.go | 55 ------ cmd/update.go | 76 -------- cmd/vanity-cli/add.go | 36 ++++ cmd/vanity-cli/cmd.go | 127 ++++++++++++ cmd/vanity-cli/main.go | 18 ++ cmd/vanity-cli/remove.go | 48 +++++ cmd/vanity-cli/update.go | 49 +++++ cmd/vanity-server/main.go | 18 ++ cmd/vanity-server/server.go | 75 ++++++++ contrib/contrib.go | 28 --- go-vanity/go.mod | 3 - go.mod | 11 +- go.sum | 57 ++++-- main.go | 24 --- {go-vanity => sdk}/client.go | 2 +- {go-vanity => sdk}/package.go | 2 +- {go-vanity => sdk}/source.go | 2 +- {go-vanity => sdk}/vanity_test.go | 2 +- {database => server/database}/database.go | 12 +- {database => server/database}/errors.go | 0 {router => server/router}/router.go | 55 +++--- {router => server/router}/router_test.go | 28 +-- {router => server/router}/templates.go | 28 +-- {router => server/router}/templates/base.tmpl | 0 .../router}/templates/import.tmpl | 0 .../router}/templates/index.tmpl | 0 .../router}/templates/static/sakura.css | 0 .../router}/templates/vanity.tmpl | 0 tools.go | 8 + 37 files changed, 524 insertions(+), 698 deletions(-) delete mode 100644 .drone.yml create mode 100644 .woodpecker.yml delete mode 100644 Makefile delete mode 100644 cmd/add.go delete mode 100644 cmd/cmd.go delete mode 100644 cmd/flags/flags.go delete mode 100644 cmd/remove.go delete mode 100644 cmd/server.go delete mode 100644 cmd/update.go create mode 100644 cmd/vanity-cli/add.go create mode 100644 cmd/vanity-cli/cmd.go create mode 100644 cmd/vanity-cli/main.go create mode 100644 cmd/vanity-cli/remove.go create mode 100644 cmd/vanity-cli/update.go create mode 100644 cmd/vanity-server/main.go create mode 100644 cmd/vanity-server/server.go delete mode 100644 contrib/contrib.go delete mode 100644 go-vanity/go.mod delete mode 100644 main.go rename {go-vanity => sdk}/client.go (98%) rename {go-vanity => sdk}/package.go (99%) rename {go-vanity => sdk}/source.go (98%) rename {go-vanity => sdk}/vanity_test.go (99%) rename {database => server/database}/database.go (85%) rename {database => server/database}/errors.go (100%) rename {router => server/router}/router.go (74%) rename {router => server/router}/router_test.go (81%) rename {router => server/router}/templates.go (60%) rename {router => server/router}/templates/base.tmpl (100%) rename {router => server/router}/templates/import.tmpl (100%) rename {router => server/router}/templates/index.tmpl (100%) rename {router => server/router}/templates/static/sakura.css (100%) rename {router => server/router}/templates/vanity.tmpl (100%) create mode 100644 tools.go diff --git a/.drone.yml b/.drone.yml deleted file mode 100644 index 6182b87..0000000 --- a/.drone.yml +++ /dev/null @@ -1,43 +0,0 @@ ---- -kind: pipeline -name: compliance -trigger: - event: - - pull_request -steps: - - name: build - pull: always - image: golang:1.16 - commands: - - make test - - make build - - name: check - pull: always - image: golang:1.16 - commands: - - make vet - - ---- -kind: pipeline -name: release -trigger: - event: - - push - branch: - - main -steps: - - name: build - pull: always - image: golang:1.16 - commands: - - make build - - name: gitea-release - pull: always - image: jolheiser/drone-gitea-main:latest - settings: - token: - from_secret: gitea_token - base: https://git.jojodev.com - files: - - "vanity" \ No newline at end of file diff --git a/.gitignore b/.gitignore index 9185e86..d9e9c82 100644 --- a/.gitignore +++ b/.gitignore @@ -1,7 +1,5 @@ # GoLand -.idea +.idea/ # Vanity -/vanity -/vanity.exe -/vanity.db \ No newline at end of file +/vanity* \ No newline at end of file diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..aa443a6 --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,37 @@ +clone: + git: + image: woodpeckerci/plugin-git:next + +pipeline: + compliance: + image: golang:1.17 + commands: + - go test -race ./... + - go run github.com/rs/zerolog/cmd/lint ./cmd/vanity-cli + - go run github.com/rs/zerolog/cmd/lint ./cmd/vanity-server + - go vet ./... + when: + event: pull_request + + build: + image: golang:1.17 + commands: + - GOOS="linux" go build ./cmd/vanity-cli + - GOOS="windows" go build ./cmd/vanity-cli + - GOOS="linux" go build ./cmd/vanity-server + - GOOS="windows" go build ./cmd/vanity-server + + release-main: + image: jolheiser/drone-gitea-main:latest + settings: + base: https://git.jojodev.com + token: + from_secret: gitea_token + files: + - "vanity-cli" + - "vanity-cli.exe" + - "vanity-server" + - "vanity-server.exe" + when: + event: push + branch: main diff --git a/Makefile b/Makefile deleted file mode 100644 index a3af058..0000000 --- a/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -GO ?= go - -VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//') - -.PHONY: build -build: - $(GO) build -ldflags '-s -w -X "go.jolheiser.com/vanity/router.Version=$(VERSION)"' - -.PHONY: fmt -fmt: fmt-cli fmt-lib - -.PHONY: test -test: test-cli test-lib - -.PHONY: fmt-cli -fmt-cli: - $(GO) fmt ./... - -.PHONY: test-cli -test-cli: - $(GO) test -race ./... - -.PHONY: fmt-lib -fmt-lib: - @cd go-vanity && $(GO) fmt ./... - -.PHONY: test-lib -test-lib: - @cd go-vanity && $(GO) test -race ./... - -.PHONY: vet -vet: - $(GO) vet ./... - -.PHONY: docker-build -docker-build: - docker build -f docker/Dockerfile -t jolheiser/vanity . - -.PHONY: docker-push -docker-push: - docker push jolheiser/vanity \ No newline at end of file diff --git a/cmd/add.go b/cmd/add.go deleted file mode 100644 index ad7c815..0000000 --- a/cmd/add.go +++ /dev/null @@ -1,69 +0,0 @@ -package cmd - -import ( - "context" - "net/url" - - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Add = cli.Command{ - Name: "add", - Aliases: []string{"a"}, - Usage: "Add a package", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "force", - Aliases: []string{"f"}, - Usage: "Overwrite existing package without prompt", - Destination: &flags.Force, - }, - &cli.BoolFlag{ - Name: "local", - Aliases: []string{"l"}, - Usage: "local mode", - Destination: &flags.Local, - }, - }, - Before: localOrToken, - Action: doAdd, -} - -func doAdd(_ *cli.Context) error { - pkg, err := pkgPrompt(vanity.Package{}) - if err != nil { - return err - } - - if flags.Local { - db, err := database.Load(flags.Database) - if err != nil { - return err - } - if err := db.PutPackage(pkg); err != nil { - return err - } - } else { - client := vanity.New(flags.Token, vanity.WithServer(flags.Server)) - if err := client.Add(context.Background(), pkg); err != nil { - return err - } - } - - beaver.Infof("Added %s", yellow.Format(pkg.Name)) - return nil -} - -func validURL(ans interface{}) error { - if err := survey.Required(ans); err != nil { - return err - } - _, err := url.Parse(ans.(string)) - return err -} diff --git a/cmd/cmd.go b/cmd/cmd.go deleted file mode 100644 index b60c8a4..0000000 --- a/cmd/cmd.go +++ /dev/null @@ -1,181 +0,0 @@ -package cmd - -import ( - "context" - "errors" - "fmt" - "net/url" - "os" - "path/filepath" - "strings" - - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/contrib" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" - "go.jolheiser.com/vanity/router" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver/color" -) - -var yellow = color.FgYellow - -func New() *cli.App { - app := cli.NewApp() - app.Name = "vanity" - app.Usage = "Vanity Import URLs" - app.Version = router.Version - app.Commands = []*cli.Command{ - &Add, - &Remove, - &Server, - &Update, - } - app.Flags = []cli.Flag{ - &cli.StringFlag{ - Name: "server", - Aliases: []string{"s"}, - Usage: "vanity server to use", - Value: vanity.DefaultServer, - EnvVars: []string{"VANITY_SERVER"}, - Destination: &flags.Server, - }, - &cli.StringFlag{ - Name: "token", - Aliases: []string{"t"}, - Usage: "vanity auth token to use", - DefaultText: "${VANITY_TOKEN}", - EnvVars: []string{"VANITY_TOKEN"}, - Destination: &flags.Token, - }, - &cli.StringFlag{ - Name: "database", - Aliases: []string{"d"}, - Usage: "path to vanity database for server", - Value: dbPath(), - DefaultText: "`${HOME}/vanity.db` or `${BINPATH}/vanity.db`", - EnvVars: []string{"VANITY_DATABASE"}, - Destination: &flags.Database, - }, - &cli.BoolFlag{ - Name: "systemd-service", - Usage: "Output example systemd service", - Destination: &flags.SystemdService, - Hidden: true, - }, - } - app.Action = action - return app -} - -func action(ctx *cli.Context) error { - if flags.SystemdService { - fmt.Println(contrib.SystemdService) - return nil - } - return cli.ShowAppHelp(ctx) -} - -func dbPath() string { - fn := "vanity.db" - home, err := os.UserHomeDir() - if err != nil { - bin, err := os.Executable() - if err != nil { - return fn - } - return filepath.Join(filepath.Dir(bin), fn) - } - return filepath.Join(home, fn) -} - -func localOrToken(_ *cli.Context) error { - if flags.Local && flags.Token == "" { - return errors.New("server interaction requires --token") - } - return nil -} - -func listPackages() ([]vanity.Package, error) { - var pkgs []vanity.Package - if flags.Local { - db, err := database.Load(flags.Database) - if err != nil { - return pkgs, err - } - pkgs, err = db.Packages() - if err != nil { - return pkgs, err - } - } else { - client := vanity.New(flags.Token, vanity.WithServer(flags.Server)) - info, err := client.Info(context.Background()) - if err != nil { - return pkgs, err - } - pkgs = info.Packages - } - return pkgs, nil -} - -func pkgPrompt(def vanity.Package) (vanity.Package, error) { - if def.Branch == "" { - def.Branch = "main" - } - var pkg vanity.Package - questions := []*survey.Question{ - { - Name: "name", - Prompt: &survey.Input{Message: "Name", Default: def.Name}, - Validate: survey.Required, - }, - { - Name: "description", - Prompt: &survey.Multiline{Message: "Description", Default: def.Description}, - Validate: survey.Required, - }, - { - Name: "branch", - Prompt: &survey.Input{Message: "Branch", Default: def.Branch}, - Validate: survey.Required, - }, - { - Name: "weburl", - Prompt: &survey.Input{Message: "Web URL", Default: def.WebURL}, - Validate: validURL, - }, - } - if err := survey.Ask(questions, &pkg); err != nil { - return pkg, err - } - - defHTTP, defSSH := def.CloneHTTP, def.CloneSSH - if def.WebURL != pkg.WebURL { - u, err := url.Parse(pkg.WebURL) - if err != nil { - return pkg, err - } - defHTTP = pkg.WebURL + ".git" - defSSH = fmt.Sprintf("git@%s:%s.git", u.Host, strings.TrimPrefix(u.Path, "/")) - } - - questions = []*survey.Question{ - { - Name: "clonehttp", - Prompt: &survey.Input{Message: "HTTP(S) CLone URL", Default: defHTTP}, - Validate: validURL, - }, - { - Name: "clonessh", - Prompt: &survey.Input{Message: "SSH CLone URL", Default: defSSH}, - Validate: survey.Required, - }, - } - if err := survey.Ask(questions, &pkg); err != nil { - return pkg, err - } - - return pkg, nil -} diff --git a/cmd/flags/flags.go b/cmd/flags/flags.go deleted file mode 100644 index b9b584a..0000000 --- a/cmd/flags/flags.go +++ /dev/null @@ -1,14 +0,0 @@ -package flags - -var ( - Server string - Domain string - Token string - Database string - - Local bool - Force bool - Port int - - SystemdService bool -) diff --git a/cmd/remove.go b/cmd/remove.go deleted file mode 100644 index 4de7bf6..0000000 --- a/cmd/remove.go +++ /dev/null @@ -1,67 +0,0 @@ -package cmd - -import ( - "context" - - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Remove = cli.Command{ - Name: "remove", - Aliases: []string{"rm"}, - Usage: "Remove package(s)", - Before: localOrToken, - Action: doRemove, -} - -func doRemove(_ *cli.Context) error { - pkgs, err := listPackages() - if err != nil { - return err - } - - pkgSlice := make([]string, len(pkgs)) - pkgMap := make(map[string]vanity.Package) - for idx, pkg := range pkgs { - pkgSlice[idx] = pkg.Name - pkgMap[pkg.Name] = pkg - } - - pkgQuestion := &survey.Select{ - Message: "Select package to remove", - Options: pkgSlice, - } - - var pkgName string - if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { - return err - } - - pkg := vanity.Package{ - Name: pkgName, - } - - if flags.Local { - db, err := database.Load(flags.Database) - if err != nil { - return err - } - if err := db.RemovePackage(pkg.Name); err != nil { - return err - } - } else { - client := vanity.New(flags.Token, vanity.WithServer(flags.Server)) - if err := client.Remove(context.Background(), pkg); err != nil { - return err - } - } - - beaver.Infof("Removed %s", yellow.Format(pkgName)) - return nil -} diff --git a/cmd/server.go b/cmd/server.go deleted file mode 100644 index 9a28c1a..0000000 --- a/cmd/server.go +++ /dev/null @@ -1,55 +0,0 @@ -package cmd - -import ( - "errors" - "fmt" - "net/http" - - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/router" - - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Server = cli.Command{ - Name: "server", - Aliases: []string{"web"}, - Usage: "Start the vanity server", - Flags: []cli.Flag{ - &cli.IntFlag{ - Name: "port", - Aliases: []string{"p"}, - Usage: "Port to run the vanity server on", - Value: 3333, - EnvVars: []string{"VANITY_PORT"}, - Destination: &flags.Port, - }, - &cli.StringFlag{ - Name: "domain", - Aliases: []string{"d"}, - Usage: "The Go module domain (e.g. go.jolheiser.com)", - EnvVars: []string{"VANITY_DOMAIN"}, - Destination: &flags.Domain, - }, - }, - Action: doServer, -} - -func doServer(_ *cli.Context) error { - if flags.Token == "" || flags.Domain == "" { - return errors.New("vanity server requires --token and --domain") - } - - db, err := database.Load(flags.Database) - if err != nil { - beaver.Fatalf("could not load database at %s: %v", flags.Database, err) - } - - beaver.Infof("Running vanity server at http://localhost:%d", flags.Port) - if err := http.ListenAndServe(fmt.Sprintf(":%d", flags.Port), router.New(flags.Token, db)); err != nil { - return err - } - return nil -} diff --git a/cmd/update.go b/cmd/update.go deleted file mode 100644 index c9b3f0f..0000000 --- a/cmd/update.go +++ /dev/null @@ -1,76 +0,0 @@ -package cmd - -import ( - "context" - - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" - - "github.com/AlecAivazis/survey/v2" - "github.com/urfave/cli/v2" - "go.jolheiser.com/beaver" -) - -var Update = cli.Command{ - Name: "update", - Aliases: []string{"u"}, - Usage: "Update a package", - Flags: []cli.Flag{ - &cli.BoolFlag{ - Name: "local", - Aliases: []string{"l"}, - Usage: "local mode", - Destination: &flags.Local, - }, - }, - Before: localOrToken, - Action: doUpdate, -} - -func doUpdate(_ *cli.Context) error { - pkgs, err := listPackages() - if err != nil { - return err - } - - pkgSlice := make([]string, len(pkgs)) - pkgMap := make(map[string]vanity.Package) - for idx, pkg := range pkgs { - pkgSlice[idx] = pkg.Name - pkgMap[pkg.Name] = pkg - } - - pkgQuestion := &survey.Select{ - Message: "Select package to update", - Options: pkgSlice, - } - - var pkgName string - if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { - return err - } - - pkg, err := pkgPrompt(pkgMap[pkgName]) - if err != nil { - return err - } - - if flags.Local { - db, err := database.Load(flags.Database) - if err != nil { - return err - } - if err := db.PutPackage(pkg); err != nil { - return err - } - } else { - client := vanity.New(flags.Token, vanity.WithServer(flags.Server)) - if err := client.Update(context.Background(), pkg); err != nil { - return err - } - } - - beaver.Infof("Updated %s", yellow.Format(pkgName)) - return nil -} diff --git a/cmd/vanity-cli/add.go b/cmd/vanity-cli/add.go new file mode 100644 index 0000000..e02750c --- /dev/null +++ b/cmd/vanity-cli/add.go @@ -0,0 +1,36 @@ +package main + +import ( + "context" + "net/url" + + "go.jolheiser.com/vanity/sdk" + + "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" +) + +func add(token, server *string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { + pkg, err := pkgPrompt(sdk.Package{}) + if err != nil { + return err + } + + client := sdk.New(*token, sdk.WithServer(*server)) + if err := client.Add(context.Background(), pkg); err != nil { + return err + } + + log.Info().Msgf("Added %q", pkg.Name) + return nil + } +} + +func validURL(ans interface{}) error { + if err := survey.Required(ans); err != nil { + return err + } + _, err := url.Parse(ans.(string)) + return err +} diff --git a/cmd/vanity-cli/cmd.go b/cmd/vanity-cli/cmd.go new file mode 100644 index 0000000..f1cf6b7 --- /dev/null +++ b/cmd/vanity-cli/cmd.go @@ -0,0 +1,127 @@ +package main + +import ( + "context" + "flag" + "fmt" + "net/url" + "strings" + + "go.jolheiser.com/vanity/sdk" + + "github.com/AlecAivazis/survey/v2" + "github.com/peterbourgon/ff/v3" + "github.com/peterbourgon/ff/v3/ffcli" + "github.com/peterbourgon/ff/v3/fftoml" +) + +func New() *ffcli.Command { + fs := flag.NewFlagSet("vanity", flag.ExitOnError) + serverFlag := fs.String("server", sdk.DefaultServer, "vanity server to use") + tokenFlag := fs.String("token", "", "vanity auth token to use") + + cmd := &ffcli.Command{ + Name: "vanity", + ShortUsage: "vanity [add|update|remove]", + ShortHelp: "Vanity CLI", + LongHelp: "Vanity CLI to work with a remote Vanity server", + FlagSet: fs, + Options: []ff.Option{ + ff.WithEnvVarPrefix("VANITY"), + ff.WithAllowMissingConfigFile(true), + ff.WithConfigFileFlag("config"), + ff.WithConfigFileParser(fftoml.New().Parse), + }, + Subcommands: []*ffcli.Command{ + { + Name: "add", + ShortHelp: "add package", + LongHelp: "add a package to the vanity server", + Exec: add(tokenFlag, serverFlag), + }, + { + Name: "remove", + ShortHelp: "remove package", + LongHelp: "remove a package from the vanity server", + Exec: remove(tokenFlag, serverFlag), + }, + { + Name: "update", + ShortHelp: "update package", + LongHelp: "update a package on the vanity server", + Exec: update(tokenFlag, serverFlag), + }, + }, + } + + return cmd +} + +func listPackages(token, server string) ([]sdk.Package, error) { + client := sdk.New(token, sdk.WithServer(server)) + info, err := client.Info(context.Background()) + if err != nil { + return nil, err + } + return info.Packages, nil +} + +func pkgPrompt(def sdk.Package) (sdk.Package, error) { + if def.Branch == "" { + def.Branch = "main" + } + var pkg sdk.Package + questions := []*survey.Question{ + { + Name: "name", + Prompt: &survey.Input{Message: "Name", Default: def.Name}, + Validate: survey.Required, + }, + { + Name: "description", + Prompt: &survey.Multiline{Message: "Description", Default: def.Description}, + Validate: survey.Required, + }, + { + Name: "branch", + Prompt: &survey.Input{Message: "Branch", Default: def.Branch}, + Validate: survey.Required, + }, + { + Name: "weburl", + Prompt: &survey.Input{Message: "Web URL", Default: def.WebURL}, + Validate: validURL, + }, + } + if err := survey.Ask(questions, &pkg); err != nil { + return pkg, err + } + + defHTTP, defSSH := def.CloneHTTP, def.CloneSSH + if def.WebURL != pkg.WebURL { + u, err := url.Parse(pkg.WebURL) + if err != nil { + return pkg, err + } + defHTTP = pkg.WebURL + ".git" + defSSH = fmt.Sprintf("git@%s:%s.git", u.Host, strings.TrimPrefix(u.Path, "/")) + } + + questions = []*survey.Question{ + { + Name: "clonehttp", + Prompt: &survey.Input{Message: "HTTP(S) CLone URL", Default: defHTTP}, + Validate: validURL, + }, + { + Name: "clonessh", + Prompt: &survey.Input{Message: "SSH CLone URL", Default: defSSH}, + Validate: survey.Required, + }, + } + if err := survey.Ask(questions, &pkg); err != nil { + return pkg, err + } + + return pkg, nil +} diff --git a/cmd/vanity-cli/main.go b/cmd/vanity-cli/main.go new file mode 100644 index 0000000..9fd71fe --- /dev/null +++ b/cmd/vanity-cli/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "context" + "os" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + + cmd := New() + if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil { + log.Fatal().Err(err).Msg("") + } +} diff --git a/cmd/vanity-cli/remove.go b/cmd/vanity-cli/remove.go new file mode 100644 index 0000000..802dca7 --- /dev/null +++ b/cmd/vanity-cli/remove.go @@ -0,0 +1,48 @@ +package main + +import ( + "context" + + "go.jolheiser.com/vanity/sdk" + + "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" +) + +func remove(token, server *string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { + pkgs, err := listPackages(*token, *server) + if err != nil { + return err + } + + pkgSlice := make([]string, len(pkgs)) + pkgMap := make(map[string]sdk.Package) + for idx, pkg := range pkgs { + pkgSlice[idx] = pkg.Name + pkgMap[pkg.Name] = pkg + } + + pkgQuestion := &survey.Select{ + Message: "Select package to remove", + Options: pkgSlice, + } + + var pkgName string + if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { + return err + } + + pkg := sdk.Package{ + Name: pkgName, + } + + client := sdk.New(*token, sdk.WithServer(*server)) + if err := client.Remove(context.Background(), pkg); err != nil { + return err + } + + log.Info().Msgf("Removed %q", pkgName) + return nil + } +} diff --git a/cmd/vanity-cli/update.go b/cmd/vanity-cli/update.go new file mode 100644 index 0000000..04a2d9a --- /dev/null +++ b/cmd/vanity-cli/update.go @@ -0,0 +1,49 @@ +package main + +import ( + "context" + + "go.jolheiser.com/vanity/sdk" + + "github.com/AlecAivazis/survey/v2" + "github.com/rs/zerolog/log" +) + +func update(token, server *string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { + pkgs, err := listPackages(*token, *server) + if err != nil { + return err + } + + pkgSlice := make([]string, len(pkgs)) + pkgMap := make(map[string]sdk.Package) + for idx, pkg := range pkgs { + pkgSlice[idx] = pkg.Name + pkgMap[pkg.Name] = pkg + } + + pkgQuestion := &survey.Select{ + Message: "Select package to update", + Options: pkgSlice, + } + + var pkgName string + if err := survey.AskOne(pkgQuestion, &pkgName); err != nil { + return err + } + + pkg, err := pkgPrompt(pkgMap[pkgName]) + if err != nil { + return err + } + + client := sdk.New(*token, sdk.WithServer(*server)) + if err := client.Update(context.Background(), pkg); err != nil { + return err + } + + log.Info().Msgf("Updated %q", pkgName) + return nil + } +} diff --git a/cmd/vanity-server/main.go b/cmd/vanity-server/main.go new file mode 100644 index 0000000..9fd71fe --- /dev/null +++ b/cmd/vanity-server/main.go @@ -0,0 +1,18 @@ +package main + +import ( + "context" + "os" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" +) + +func main() { + log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr}) + + cmd := New() + if err := cmd.ParseAndRun(context.Background(), os.Args[1:]); err != nil { + log.Fatal().Err(err).Msg("") + } +} diff --git a/cmd/vanity-server/server.go b/cmd/vanity-server/server.go new file mode 100644 index 0000000..5ba58f7 --- /dev/null +++ b/cmd/vanity-server/server.go @@ -0,0 +1,75 @@ +package main + +import ( + "context" + "errors" + "flag" + "fmt" + "net/http" + "os" + "path/filepath" + + "go.jolheiser.com/vanity/server/database" + "go.jolheiser.com/vanity/server/router" + + "github.com/peterbourgon/ff/v3" + "github.com/peterbourgon/ff/v3/ffcli" + "github.com/peterbourgon/ff/v3/fftoml" + "github.com/rs/zerolog/log" +) + +func New() *ffcli.Command { + fs := flag.NewFlagSet("vanity", flag.ExitOnError) + portFlag := fs.Int("port", 3333, "Port to run the vanity server on") + domainFlag := fs.String("domain", "", "The Go module domain (e.g. go.jolheiser.com)") + tokenFlag := fs.String("token", "", "vanity auth token to use") + dbFlag := fs.String("database", dbPath(), "The path to the database") + + cmd := &ffcli.Command{ + Name: "vanity", + ShortUsage: "vanity", + ShortHelp: "Vanity Server", + LongHelp: "Vanity Server to serve the Go module vanity domain", + FlagSet: fs, + Options: []ff.Option{ + ff.WithEnvVarPrefix("VANITY"), + ff.WithAllowMissingConfigFile(true), + ff.WithConfigFileFlag("config"), + ff.WithConfigFileParser(fftoml.New().Parse), + }, + Exec: server(portFlag, domainFlag, tokenFlag, dbFlag), + } + return cmd +} + +func server(port *int, domain, token, dbPath *string) func(context.Context, []string) error { + return func(ctx context.Context, args []string) error { + if *token == "" || *domain == "" { + return errors.New("vanity server requires --token and --domain") + } + + db, err := database.Load(*dbPath) + if err != nil { + log.Fatal().Msgf("could not load database at %s: %v", *dbPath, err) + } + + log.Info().Msgf("Running vanity server at http://localhost:%d", *port) + if err := http.ListenAndServe(fmt.Sprintf(":%d", *port), router.New(*token, *domain, db)); err != nil { + return err + } + return nil + } +} + +func dbPath() string { + fn := "vanity.db" + home, err := os.UserHomeDir() + if err != nil { + bin, err := os.Executable() + if err != nil { + return fn + } + return filepath.Join(filepath.Dir(bin), fn) + } + return filepath.Join(home, fn) +} diff --git a/contrib/contrib.go b/contrib/contrib.go deleted file mode 100644 index 65e707e..0000000 --- a/contrib/contrib.go +++ /dev/null @@ -1,28 +0,0 @@ -package contrib - -import ( - _ "embed" - "os" - "strings" -) - -//go:embed vanity.service -var SystemdService string - -func init() { - bin, err := os.Executable() - if err != nil { - return - } - SystemdService = os.Expand(SystemdService, func(s string) string { - switch strings.ToUpper(s) { - case "BIN": - return bin - case "VANITY_TOKEN": - return os.Getenv("VANITY_TOKEN") - case "VANITY_DOMAIN": - return os.Getenv("VANITY_DOMAIN") - } - return "" - }) -} diff --git a/go-vanity/go.mod b/go-vanity/go.mod deleted file mode 100644 index 97706e6..0000000 --- a/go-vanity/go.mod +++ /dev/null @@ -1,3 +0,0 @@ -module go.jolheiser.com/vanity/go-vanity - -go 1.16 diff --git a/go.mod b/go.mod index 981270b..bad26dc 100644 --- a/go.mod +++ b/go.mod @@ -2,18 +2,11 @@ module go.jolheiser.com/vanity go 1.16 -replace go.jolheiser.com/vanity/go-vanity => ./go-vanity - require ( github.com/AlecAivazis/survey/v2 v2.2.8 - github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect github.com/go-chi/chi/v5 v5.0.3 - github.com/urfave/cli/v2 v2.2.0 + github.com/peterbourgon/ff/v3 v3.1.2 + github.com/rs/zerolog v1.26.1 go.etcd.io/bbolt v1.3.5 - go.jolheiser.com/beaver v1.0.2 go.jolheiser.com/overlay v0.0.3 - go.jolheiser.com/vanity/go-vanity v0.0.0-00010101000000-000000000000 - golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 // indirect - golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 // indirect - golang.org/x/text v0.3.3 // indirect ) diff --git a/go.sum b/go.sum index 26fca36..43c6b0c 100644 --- a/go.sum +++ b/go.sum @@ -1,15 +1,15 @@ github.com/AlecAivazis/survey/v2 v2.2.8 h1:TgxCwybKdBckmC+/P9/5h49rw/nAHe/itZL0dgHs+Q0= github.com/AlecAivazis/survey/v2 v2.2.8/go.mod h1:9DYvHgXtiXm6nCn+jXnOXLKbH+Yo9u8fAS/SduGdoPk= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8/go.mod h1:oX5x61PbNXchhh0oikYAH+4Pcfw5LKv21+Jnpr6r6Pc= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= -github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM= -github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= 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= github.com/go-chi/chi/v5 v5.0.3 h1:khYQBdPivkYG1s1TAzDQG1f6eX4kD2TItYVZexL5rS4= github.com/go-chi/chi/v5 v5.0.3/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= @@ -22,38 +22,59 @@ github.com/mattn/go-isatty v0.0.8 h1:HLtExJ+uU2HOZ+wI0Tt5DtUDrx8yhUqDcp7fYERX4CE github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= +github.com/pelletier/go-toml v1.6.0 h1:aetoXYr0Tv7xRU/V4B4IZJ2QcbtMUFoNb3ORp7TzIK4= +github.com/pelletier/go-toml v1.6.0/go.mod h1:5N711Q9dKgbdkxHL+MEfF31hpT7l0S0s/t2kKREewys= +github.com/peterbourgon/ff/v3 v3.1.2 h1:0GNhbRhO9yHA4CC27ymskOsuRpmX0YQxwxM9UPiP6JM= +github.com/peterbourgon/ff/v3 v3.1.2/go.mod h1:XNJLY8EIl6MjMVjBS4F0+G0LYoAqs0DTa4rmHHukKDE= +github.com/pkg/errors v0.9.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/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo= -github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= +github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= +github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/stretchr/testify v1.2.1 h1:52QO5WkIUcHGIR7EnGagH88x1bUzqGXTC5/1bDTUQ7U= github.com/stretchr/testify v1.2.1/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/urfave/cli/v2 v2.2.0 h1:JTTnM6wKzdA0Jqodd966MVj4vWbbquZykeX1sKbe2C4= -github.com/urfave/cli/v2 v2.2.0/go.mod h1:SE9GqnLQmjVa0iPEY0f1w3ygNIYcIJ0OKPMoW2caLfQ= +github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0= go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ= -go.jolheiser.com/beaver v1.0.2 h1:KA2D6iO8MQhZi1nZYi/Chak/f1Cxfrs6b1XO623+Khk= -go.jolheiser.com/beaver v1.0.2/go.mod h1:7X4F5+XOGSC3LejTShoBdqtRCnPWcnRgmYGmG3EKW8g= go.jolheiser.com/overlay v0.0.3 h1:5WoXtnRi1w5KkU9xq+si/wV0GINOMJphfSOvgG2l53I= go.jolheiser.com/overlay v0.0.3/go.mod h1:xNbssakJ3HjK4RnjuP38q9yQNS4wxXKsyprYIWWr2bg= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= -golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e h1:1SzTfNOXwIS2oWiMF+6qu0OUDKb0dauo6MoDUQyu+yU= +golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo= +golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= 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= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= 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= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190530182044-ad28b68e88f1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009 h1:W0lCpv29Hv0UaM1LXb9QlBHLNP8UFfcKjblhVCWftOM= -golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e h1:WUoyKPm6nCo1BnNUvPGnFG3T5DUVem42yDJZZ4CNxMA= +golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= +golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= +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 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4 h1:/eiJrUcujPVeJ3xlSWaiNi3uSVmDGBK1pDHUHAnao1I= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/main.go b/main.go deleted file mode 100644 index 59f2e39..0000000 --- a/main.go +++ /dev/null @@ -1,24 +0,0 @@ -package main - -import ( - "os" - - "go.jolheiser.com/vanity/cmd" - - "go.jolheiser.com/beaver" -) - -func main() { - - beaver.Console.Format = beaver.FormatOptions{ - TimePrefix: true, - StackPrefix: true, - StackLimit: 15, - LevelPrefix: true, - LevelColor: true, - } - - if err := cmd.New().Run(os.Args); err != nil { - beaver.Fatal(err) - } -} diff --git a/go-vanity/client.go b/sdk/client.go similarity index 98% rename from go-vanity/client.go rename to sdk/client.go index 9c1b76d..9fe6bda 100644 --- a/go-vanity/client.go +++ b/sdk/client.go @@ -1,4 +1,4 @@ -package vanity +package sdk import ( "context" diff --git a/go-vanity/package.go b/sdk/package.go similarity index 99% rename from go-vanity/package.go rename to sdk/package.go index 1e8ef76..7d13e33 100644 --- a/go-vanity/package.go +++ b/sdk/package.go @@ -1,4 +1,4 @@ -package vanity +package sdk import ( "bytes" diff --git a/go-vanity/source.go b/sdk/source.go similarity index 98% rename from go-vanity/source.go rename to sdk/source.go index ea58e74..79fba7b 100644 --- a/go-vanity/source.go +++ b/sdk/source.go @@ -1,4 +1,4 @@ -package vanity +package sdk import ( "errors" diff --git a/go-vanity/vanity_test.go b/sdk/vanity_test.go similarity index 99% rename from go-vanity/vanity_test.go rename to sdk/vanity_test.go index 93f9852..9715f4d 100644 --- a/go-vanity/vanity_test.go +++ b/sdk/vanity_test.go @@ -1,4 +1,4 @@ -package vanity +package sdk import ( "context" diff --git a/database/database.go b/server/database/database.go similarity index 85% rename from database/database.go rename to server/database/database.go index aba2c68..ae58402 100644 --- a/database/database.go +++ b/server/database/database.go @@ -6,7 +6,7 @@ import ( "os" "path/filepath" - "go.jolheiser.com/vanity/go-vanity" + "go.jolheiser.com/vanity/sdk" "go.etcd.io/bbolt" ) @@ -33,8 +33,8 @@ func Load(dbPath string) (*Database, error) { }) } -func (d *Database) Package(name string) (vanity.Package, error) { - var pkg vanity.Package +func (d *Database) Package(name string) (sdk.Package, error) { + var pkg sdk.Package data, err := d.PackageJSON(name) if err != nil { return pkg, err @@ -54,10 +54,10 @@ func (d *Database) PackageJSON(name string) (pkg []byte, err error) { }) } -func (d *Database) Packages() (pkgs []vanity.Package, err error) { +func (d *Database) Packages() (pkgs []sdk.Package, err error) { return pkgs, d.db.View(func(tx *bbolt.Tx) error { return tx.Bucket(packageBucket).ForEach(func(key, val []byte) error { - var pkg vanity.Package + var pkg sdk.Package if err := json.NewDecoder(bytes.NewReader(val)).Decode(&pkg); err != nil { return err } @@ -67,7 +67,7 @@ func (d *Database) Packages() (pkgs []vanity.Package, err error) { }) } -func (d *Database) PutPackage(pkg vanity.Package) error { +func (d *Database) PutPackage(pkg sdk.Package) error { return d.db.Update(func(tx *bbolt.Tx) error { data, err := json.Marshal(pkg) if err != nil { diff --git a/database/errors.go b/server/database/errors.go similarity index 100% rename from database/errors.go rename to server/database/errors.go diff --git a/router/router.go b/server/router/router.go similarity index 74% rename from router/router.go rename to server/router/router.go index 0d38e24..a000b58 100644 --- a/router/router.go +++ b/server/router/router.go @@ -8,56 +8,55 @@ import ( "strings" "time" - "go.jolheiser.com/vanity/cmd/flags" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" + "go.jolheiser.com/vanity/sdk" + "go.jolheiser.com/vanity/server/database" "github.com/go-chi/chi/v5" "github.com/go-chi/chi/v5/middleware" - "go.jolheiser.com/beaver" + "github.com/rs/zerolog/log" ) -func New(token string, db *database.Database) *chi.Mux { +func New(token, domain string, db *database.Database) *chi.Mux { r := chi.NewRouter() r.Use(middleware.Recoverer) r.Use(middleware.Timeout(60 * time.Second)) r.Mount("/_/", http.StripPrefix("/_/", static())) - r.Get("/", indexGET(db)) + r.Get("/", indexGET(domain, db)) r.Options("/", infoPackages(db)) r.Post("/", addUpdatePackage(db, token)) r.Patch("/", addUpdatePackage(db, token)) r.Delete("/", removePackage(db, token)) - r.Get("/*", vanityGET(db)) + r.Get("/*", vanityGET(domain, db)) return r } -func indexGET(db *database.Database) http.HandlerFunc { +func indexGET(domain string, db *database.Database) http.HandlerFunc { return func(res http.ResponseWriter, req *http.Request) { packages, err := db.Packages() if err != nil { - beaver.Errorf("could not load packages: %v", err) + log.Error().Msgf("could not load packages: %v", err) http.Error(res, "could not load packages", http.StatusInternalServerError) return } - tpl, err := tmpl("index.tmpl") + tpl, err := tmpl(domain, "index.tmpl") if err != nil { - beaver.Warnf("could not load index template: %v", err) + log.Warn().Msgf("could not load index template: %v", err) } if err := tpl.Execute(res, map[string]interface{}{ "Packages": packages, "Index": true, }); err != nil { - beaver.Errorf("could not write response: %v", err) + log.Error().Msgf("could not write response: %v", err) } } } -func vanityGET(db *database.Database) http.HandlerFunc { +func vanityGET(domain string, db *database.Database) http.HandlerFunc { return func(res http.ResponseWriter, req *http.Request) { key := chi.URLParam(req, "*") key = strings.Split(key, "/")[0] @@ -72,36 +71,36 @@ func vanityGET(db *database.Database) http.HandlerFunc { return } - sdf, err := vanity.AnalyzeSDF(pkg) + sdf, err := sdk.AnalyzeSDF(pkg) if err != nil { - beaver.Warnf("could not get SDF for %s: %v", key, err) + log.Warn().Msgf("could not get SDF for %s: %v", key, err) } ctx := map[string]interface{}{ "Package": pkg, - "Module": pkg.Module(flags.Domain), - "GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(flags.Domain), pkg.CloneHTTP, sdf.Dir, sdf.File), + "Module": pkg.Module(domain), + "GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(domain), pkg.CloneHTTP, sdf.Dir, sdf.File), "Index": false, } q := req.URL.Query() if q.Get("go-get") != "" || q.Get("git-import") != "" { - tpl, err := tmpl("import.tmpl") + tpl, err := tmpl(domain, "import.tmpl") if err != nil { - beaver.Warnf("could not load import template: %v", err) + log.Warn().Msgf("could not load import template: %v", err) } if err := tpl.Execute(res, ctx); err != nil { - beaver.Errorf("could not write response: %v", err) + log.Error().Msgf("could not write response: %v", err) } return } - tpl, err := tmpl("vanity.tmpl") + tpl, err := tmpl(domain, "vanity.tmpl") if err != nil { - beaver.Warnf("could not load vanity template: %v", err) + log.Warn().Msgf("could not load vanity template: %v", err) } if err := tpl.Execute(res, ctx); err != nil { - beaver.Errorf("could not write response: %v", err) + log.Error().Msgf("could not write response: %v", err) } } } @@ -114,7 +113,7 @@ func infoPackages(db *database.Database) func(http.ResponseWriter, *http.Request return } - info := vanity.Info{ + info := sdk.Info{ Version: Version, NumPackages: len(packages), Packages: packages, @@ -128,7 +127,7 @@ func infoPackages(db *database.Database) func(http.ResponseWriter, *http.Request func addUpdatePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { return func(res http.ResponseWriter, req *http.Request) { - if req.Header.Get(vanity.TokenHeader) != token { + if req.Header.Get(sdk.TokenHeader) != token { res.WriteHeader(http.StatusUnauthorized) return } @@ -140,7 +139,7 @@ func addUpdatePackage(db *database.Database, token string) func(http.ResponseWri } defer req.Body.Close() - var pkg vanity.Package + var pkg sdk.Package if err := json.Unmarshal(data, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return @@ -181,7 +180,7 @@ func addUpdatePackage(db *database.Database, token string) func(http.ResponseWri func removePackage(db *database.Database, token string) func(http.ResponseWriter, *http.Request) { return func(res http.ResponseWriter, req *http.Request) { - if req.Header.Get(vanity.TokenHeader) != token { + if req.Header.Get(sdk.TokenHeader) != token { res.WriteHeader(http.StatusUnauthorized) return } @@ -193,7 +192,7 @@ func removePackage(db *database.Database, token string) func(http.ResponseWriter } defer req.Body.Close() - var pkg vanity.Package + var pkg sdk.Package if err := json.Unmarshal(data, &pkg); err != nil { res.WriteHeader(http.StatusBadRequest) return diff --git a/router/router_test.go b/server/router/router_test.go similarity index 81% rename from router/router_test.go rename to server/router/router_test.go index dea64e6..4fc40ed 100644 --- a/router/router_test.go +++ b/server/router/router_test.go @@ -9,10 +9,10 @@ import ( "path/filepath" "testing" - "go.jolheiser.com/vanity/database" - "go.jolheiser.com/vanity/go-vanity" + "go.jolheiser.com/vanity/sdk" + "go.jolheiser.com/vanity/server/database" - "go.jolheiser.com/beaver" + "github.com/rs/zerolog/log" ) var ( @@ -31,10 +31,10 @@ func TestMain(m *testing.M) { db, err := database.Load(dbPath) if err != nil { - beaver.Fatalf("could not load database at %s: %v", dbPath, err) + log.Fatal().Msgf("could not load database at %s: %v", dbPath, err) } - server = httptest.NewServer(New(token, db)) + server = httptest.NewServer(New(token, "", db)) code := m.Run() @@ -48,12 +48,12 @@ func TestMain(m *testing.M) { func TestRouter(t *testing.T) { ctx := context.Background() - client := vanity.New("", vanity.WithServer(server.URL)) + client := sdk.New("", sdk.WithServer(server.URL)) // Info checkInfo(t, client, 0) - pkg1 := vanity.Package{ + pkg1 := sdk.Package{ Name: "test1", Description: "test1", Branch: "main", @@ -61,7 +61,7 @@ func TestRouter(t *testing.T) { CloneHTTP: "https://gitea.com/jolheiser/test1.git", CloneSSH: "https://gitea.com/jolheiser/test1", } - pkg2 := vanity.Package{ + pkg2 := sdk.Package{ Name: "test2", Description: "test2", Branch: "main", @@ -77,7 +77,7 @@ func TestRouter(t *testing.T) { } // Add (with token) - client = vanity.New(token, vanity.WithServer(server.URL)) + client = sdk.New(token, sdk.WithServer(server.URL)) checkAdd(t, client, pkg1, pkg2) // Info (after second package) @@ -102,7 +102,7 @@ func TestRouter(t *testing.T) { checkInfo(t, client, 1) } -func checkInfo(t *testing.T, client *vanity.Client, numPackages int) { +func checkInfo(t *testing.T, client *sdk.Client, numPackages int) { info, err := client.Info(context.Background()) if err != nil { t.Logf("info should not return error: %v\n", err) @@ -114,7 +114,7 @@ func checkInfo(t *testing.T, client *vanity.Client, numPackages int) { } } -func checkAdd(t *testing.T, client *vanity.Client, pkg1, pkg2 vanity.Package) { +func checkAdd(t *testing.T, client *sdk.Client, pkg1, pkg2 sdk.Package) { ctx := context.Background() if err := client.Add(ctx, pkg1); err != nil { t.Logf("pkg1 should be added: %v\n", err) @@ -131,10 +131,10 @@ func checkAdd(t *testing.T, client *vanity.Client, pkg1, pkg2 vanity.Package) { } } -func checkUpdate(t *testing.T, client *vanity.Client, pkg vanity.Package) { +func checkUpdate(t *testing.T, client *sdk.Client, pkg sdk.Package) { ctx := context.Background() // Update invalid package - if err := client.Update(ctx, vanity.Package{Name: "test4"}); err == nil { + if err := client.Update(ctx, sdk.Package{Name: "test4"}); err == nil { t.Log("should not be able to update invalid package") t.Fail() } @@ -146,7 +146,7 @@ func checkUpdate(t *testing.T, client *vanity.Client, pkg vanity.Package) { } } -func checkRemove(t *testing.T, client *vanity.Client, pkg vanity.Package) { +func checkRemove(t *testing.T, client *sdk.Client, pkg sdk.Package) { ctx := context.Background() if err := client.Remove(ctx, pkg); err != nil { t.Logf("should be able to remove package: %v\n", err) diff --git a/router/templates.go b/server/router/templates.go similarity index 60% rename from router/templates.go rename to server/router/templates.go index 0191c20..8afcfb8 100644 --- a/router/templates.go +++ b/server/router/templates.go @@ -11,8 +11,6 @@ import ( "strings" "go.jolheiser.com/overlay" - - "go.jolheiser.com/vanity/cmd/flags" ) var ( @@ -34,8 +32,8 @@ func customRoot() string { return customPath } -func tmpl(name string) (*template.Template, error) { - return template.New(name).Funcs(funcMap).ParseFS(ofs, "templates/base.tmpl", "templates/"+name) +func tmpl(domain, name string) (*template.Template, error) { + return template.New(name).Funcs(funcMap(domain)).ParseFS(ofs, "templates/base.tmpl", "templates/"+name) } func static() http.Handler { @@ -46,14 +44,16 @@ func static() http.Handler { return http.FileServer(http.FS(sub)) } -var funcMap = template.FuncMap{ - "AppVer": func() string { - return Version - }, - "GoVer": func() string { - return runtime.Version() - }, - "Domain": func() string { - return strings.TrimSuffix(flags.Domain, "/") - }, +func funcMap(domain string) template.FuncMap { + return template.FuncMap{ + "AppVer": func() string { + return Version + }, + "GoVer": func() string { + return runtime.Version() + }, + "Domain": func() string { + return strings.TrimSuffix(domain, "/") + }, + } } diff --git a/router/templates/base.tmpl b/server/router/templates/base.tmpl similarity index 100% rename from router/templates/base.tmpl rename to server/router/templates/base.tmpl diff --git a/router/templates/import.tmpl b/server/router/templates/import.tmpl similarity index 100% rename from router/templates/import.tmpl rename to server/router/templates/import.tmpl diff --git a/router/templates/index.tmpl b/server/router/templates/index.tmpl similarity index 100% rename from router/templates/index.tmpl rename to server/router/templates/index.tmpl diff --git a/router/templates/static/sakura.css b/server/router/templates/static/sakura.css similarity index 100% rename from router/templates/static/sakura.css rename to server/router/templates/static/sakura.css diff --git a/router/templates/vanity.tmpl b/server/router/templates/vanity.tmpl similarity index 100% rename from router/templates/vanity.tmpl rename to server/router/templates/vanity.tmpl diff --git a/tools.go b/tools.go new file mode 100644 index 0000000..048b2fa --- /dev/null +++ b/tools.go @@ -0,0 +1,8 @@ +//go:build tools +// +build tools + +package main + +import ( + _ "github.com/rs/zerolog/cmd/lint" +)