Better config options, change package structure
Signed-off-by: jolheiser <john.olheiser@gmail.com>pull/3/head
parent
6d7150e0a2
commit
35b809dc85
10
Makefile
10
Makefile
|
@ -4,7 +4,7 @@ VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
|
|
||||||
.PHONY: build
|
.PHONY: build
|
||||||
build:
|
build:
|
||||||
$(GO) build -ldflags '-s -w -X "go.jolheiser.com/vanity/version.Version=$(VERSION)"'
|
$(GO) build -ldflags '-s -w -X "go.jolheiser.com/vanity/api.Version=$(VERSION)"'
|
||||||
|
|
||||||
.PHONY: fmt
|
.PHONY: fmt
|
||||||
fmt:
|
fmt:
|
||||||
|
@ -17,3 +17,11 @@ test:
|
||||||
.PHONY: vet
|
.PHONY: vet
|
||||||
vet:
|
vet:
|
||||||
$(GO) 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
|
44
README.md
44
README.md
|
@ -4,6 +4,20 @@ A simple web service to serve vanity Go imports. Feel free to check it out using
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
When choosing a service, the default `base-url` will be the default server of that service:
|
||||||
|
|
||||||
|
| Service | Default |
|
||||||
|
|:-------:|:------------------:|
|
||||||
|
| Gitea | https://gitea.com |
|
||||||
|
| GitHub | https://github.com |
|
||||||
|
| GitLab | https://gitlab.com |
|
||||||
|
|
||||||
|
Configuration will be set, in order of priority
|
||||||
|
|
||||||
|
1. Flags
|
||||||
|
2. Environment
|
||||||
|
3. Config file
|
||||||
|
|
||||||
```
|
```
|
||||||
NAME:
|
NAME:
|
||||||
vanity - Vanity Go Imports
|
vanity - Vanity Go Imports
|
||||||
|
@ -12,15 +26,15 @@ USAGE:
|
||||||
vanity [global options] command [command options] [arguments...]
|
vanity [global options] command [command options] [arguments...]
|
||||||
|
|
||||||
VERSION:
|
VERSION:
|
||||||
0.1.0+2-g49cd123
|
0.1.0+3-g6d7150e
|
||||||
|
|
||||||
COMMANDS:
|
COMMANDS:
|
||||||
help, h Shows a list of commands or help for one command
|
help, h Shows a list of commands or help for one command
|
||||||
|
|
||||||
GLOBAL OPTIONS:
|
GLOBAL OPTIONS:
|
||||||
--config value Path to a config file (default: ".vanity.toml") [$VANITY_CONFIG]
|
--config value Path to a config file [$VANITY_CONFIG]
|
||||||
--port value Port to run the vanity server on (default: 7777) [$VANITY_PORT]
|
--port value Port to run the vanity server on (default: 7777) [$VANITY_PORT]
|
||||||
--domain value Domain, e.g. go.domain.tld [$VANITY_DOMAIN]
|
--domain value Vanity domain, e.g. go.domain.tld [$VANITY_DOMAIN]
|
||||||
--service value Service type (Gitea, GitHub, GitLab) (default: "gitea") [$VANITY_SERVICE]
|
--service value Service type (Gitea, GitHub, GitLab) (default: "gitea") [$VANITY_SERVICE]
|
||||||
--base-url value Base URL to service [$VANITY_BASE_URL]
|
--base-url value Base URL to service [$VANITY_BASE_URL]
|
||||||
--namespace value Owner namespace [$VANITY_NAMESPACE]
|
--namespace value Owner namespace [$VANITY_NAMESPACE]
|
||||||
|
@ -31,11 +45,33 @@ GLOBAL OPTIONS:
|
||||||
--fork Include forked repositories (default: false) [$VANITY_FORK]
|
--fork Include forked repositories (default: false) [$VANITY_FORK]
|
||||||
--mirror Include mirrored repositories (default: false) [$VANITY_MIRROR]
|
--mirror Include mirrored repositories (default: false) [$VANITY_MIRROR]
|
||||||
--archive Include archived repositories (default: false) [$VANITY_ARCHIVE]
|
--archive Include archived repositories (default: false) [$VANITY_ARCHIVE]
|
||||||
|
--override value Repository name to override (NAME=OVERRIDE) [$VANITY_OVERRIDE]
|
||||||
--interval value Interval between updating repositories (default: 15m0s) [$VANITY_INTERVAL]
|
--interval value Interval between updating repositories (default: 15m0s) [$VANITY_INTERVAL]
|
||||||
--debug Debug logging (default: false) [$VANITY_DEBUG]
|
--debug Debug logging (default: false) [$VANITY_DEBUG]
|
||||||
--help, -h show help (default: false)
|
--help, -h show help (default: false)
|
||||||
--version, -v print the version (default: false)
|
--version, -v print the version (default: false)
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Vanity also supports [git-import](https://gitea.com/jolheiser/git-import).
|
Vanity also supports [git-import](https://gitea.com/jolheiser/git-import).
|
||||||
|
|
||||||
|
## Docker
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker run \
|
||||||
|
--env VANITY_DOMAIN=go.domain.tld \
|
||||||
|
--env VANITY_NAMESPACE=<jolheiser> \
|
||||||
|
--env VANITY_TOKEN=<token> \
|
||||||
|
--publish 80:7777 \
|
||||||
|
--restart always
|
||||||
|
jolheiser/vanity:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
## Overrides
|
||||||
|
|
||||||
|
Certain modules may not align perfectly with their repository name.
|
||||||
|
|
||||||
|
Overrides are available via config or by setting an environment variable `VANITY_OVERRIDE_PACKAGE=NAME`
|
||||||
|
|
||||||
|
## Config-only Mode
|
||||||
|
|
||||||
|
To run Vanity in config-only mode for packages, set `--service` to `off`.
|
|
@ -0,0 +1,24 @@
|
||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Package struct {
|
||||||
|
Name string `toml:"name"`
|
||||||
|
Description string `toml:"description"`
|
||||||
|
Branch string `toml:"branch"`
|
||||||
|
WebURL string `toml:"web_url"`
|
||||||
|
CloneHTTP string `toml:"clone_http"`
|
||||||
|
CloneSSH string `toml:"clone_ssh"`
|
||||||
|
|
||||||
|
Private bool `toml:"-"`
|
||||||
|
Fork bool `toml:"-"`
|
||||||
|
Mirror bool `toml:"-"`
|
||||||
|
Archive bool `toml:"-"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Package) Module(domain string) string {
|
||||||
|
return fmt.Sprintf("%s/%s", domain, strings.ToLower(p.Name))
|
||||||
|
}
|
|
@ -1,3 +1,3 @@
|
||||||
package version
|
package api
|
||||||
|
|
||||||
var Version = "develop"
|
var Version = "develop"
|
|
@ -1,12 +0,0 @@
|
||||||
# For each package, an entry like the following
|
|
||||||
[[package]]
|
|
||||||
# The name of the package (can be anything)
|
|
||||||
name = "Go-Vanity"
|
|
||||||
# The path to the package (this NEEDS to match the import path)
|
|
||||||
path = "vanity"
|
|
||||||
# The repository to direct go-import to
|
|
||||||
repo = "https://gitea.com/jolheiser/vanity.git"
|
|
||||||
# git-import for SSH (optional)
|
|
||||||
ssh = "git@gitea.com:jolheiser/vanity.git"
|
|
||||||
# A description of the project (optional)
|
|
||||||
description = "The code responsible for hosting this service!"
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
FROM golang:1.15-alpine as builder
|
||||||
|
RUN apk --no-cache add build-base git
|
||||||
|
COPY . /app
|
||||||
|
WORKDIR /app
|
||||||
|
RUN make build
|
||||||
|
|
||||||
|
FROM alpine:latest
|
||||||
|
LABEL maintainer="john.olheiser@gmail.com"
|
||||||
|
COPY --from=builder /app/vanity vanity
|
||||||
|
EXPOSE 7777
|
||||||
|
ENTRYPOINT ["/vanity"]
|
|
@ -0,0 +1,14 @@
|
||||||
|
version: "2"
|
||||||
|
|
||||||
|
services:
|
||||||
|
vanity:
|
||||||
|
image: jolheiser/vanity:latest
|
||||||
|
environment:
|
||||||
|
- VANITY_DOMAIN=go.domain.tld
|
||||||
|
- VANITY_NAMESPACE=<jolheiser>
|
||||||
|
- VANITY_TOKEN=<token>\
|
||||||
|
#- VANITY_SERVICE=gitea
|
||||||
|
#- VANITY_BASE_URL=https://gitea.com
|
||||||
|
restart: always
|
||||||
|
ports:
|
||||||
|
- "80:7777"
|
|
@ -0,0 +1,101 @@
|
||||||
|
package flags
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
|
|
||||||
|
"github.com/BurntSushi/toml"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
"go.jolheiser.com/beaver"
|
||||||
|
)
|
||||||
|
|
||||||
|
type tomlConfig struct {
|
||||||
|
Port int `toml:"port"`
|
||||||
|
Domain string `toml:"domain"`
|
||||||
|
Service string `toml:"service"`
|
||||||
|
BaseURL string `toml:"base_url"`
|
||||||
|
Namespace string `toml:"namespace"`
|
||||||
|
Token string `toml:"token"`
|
||||||
|
Include []string `toml:"include"`
|
||||||
|
Exclude []string `toml:"exclude"`
|
||||||
|
Private bool `toml:"private"`
|
||||||
|
Fork bool `toml:"fork"`
|
||||||
|
Mirror bool `toml:"mirror"`
|
||||||
|
Archive bool `toml:"archive"`
|
||||||
|
Override []string `toml:"override"`
|
||||||
|
Interval time.Duration `toml:"interval"`
|
||||||
|
Debug bool `toml:"debug"`
|
||||||
|
|
||||||
|
Packages []*api.Package `toml:"packages"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func setConfig(ctx *cli.Context) {
|
||||||
|
for _, env := range os.Environ() {
|
||||||
|
kv := strings.Split(env, "=")
|
||||||
|
if strings.HasPrefix(kv[0], "VANITY_OVERRIDES_") {
|
||||||
|
override := strings.ToLower(strings.TrimPrefix(kv[0], "VANITY_OVERRIDES_"))
|
||||||
|
Override[override] = kv[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var cfg tomlConfig
|
||||||
|
if configPath != "" {
|
||||||
|
beaver.Infof("Loading configuration from %s", configPath)
|
||||||
|
_, err := toml.DecodeFile(configPath, &cfg)
|
||||||
|
if err != nil {
|
||||||
|
beaver.Errorf("Could not load configuration from %s: %v", configPath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ctx.IsSet("port") && cfg.Port > 0 {
|
||||||
|
Port = cfg.Port
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("domain") && cfg.Domain != "" {
|
||||||
|
Domain = cfg.Domain
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("service") && cfg.Service != "" {
|
||||||
|
Service = cfg.Service
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("base-url") && cfg.BaseURL != "" {
|
||||||
|
baseURL = cfg.BaseURL
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("namespace") && cfg.Namespace != "" {
|
||||||
|
Namespace = cfg.Namespace
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("token") && cfg.Token != "" {
|
||||||
|
Token = cfg.Token
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("include") && len(cfg.Include) > 0 {
|
||||||
|
_ = include.Set(strings.Join(cfg.Include, ","))
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("exclude") && len(cfg.Exclude) > 0 {
|
||||||
|
_ = exclude.Set(strings.Join(cfg.Exclude, ","))
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("override") && len(cfg.Override) > 0 {
|
||||||
|
_ = override.Set(strings.Join(cfg.Override, ","))
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("private") && cfg.Private {
|
||||||
|
Private = cfg.Private
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("fork") && cfg.Fork {
|
||||||
|
Fork = cfg.Fork
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("mirror") && cfg.Mirror {
|
||||||
|
Mirror = cfg.Mirror
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("archive") && cfg.Archive {
|
||||||
|
Archive = cfg.Archive
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("interval") && cfg.Interval.Seconds() > 0 {
|
||||||
|
Interval = cfg.Interval
|
||||||
|
}
|
||||||
|
if !ctx.IsSet("debug") && cfg.Debug {
|
||||||
|
Debug = cfg.Debug
|
||||||
|
}
|
||||||
|
|
||||||
|
ConfigPackages = cfg.Packages
|
||||||
|
}
|
191
flags/flags.go
191
flags/flags.go
|
@ -1,49 +1,43 @@
|
||||||
package flags
|
package flags
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/BurntSushi/toml"
|
"go.jolheiser.com/vanity/api"
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"go.jolheiser.com/beaver"
|
"go.jolheiser.com/beaver"
|
||||||
)
|
)
|
||||||
|
|
||||||
type flagConfig struct {
|
|
||||||
Port int `toml:"port"`
|
|
||||||
Domain string `toml:"domain"`
|
|
||||||
Service string `toml:"service"`
|
|
||||||
BaseURL string `toml:"base_url"`
|
|
||||||
URL *url.URL `toml:"-"`
|
|
||||||
Namespace string `toml:"namespace"`
|
|
||||||
Token string `toml:"token"`
|
|
||||||
Include []*regexp.Regexp `toml:"-"`
|
|
||||||
Exclude []*regexp.Regexp `toml:"-"`
|
|
||||||
Private bool `toml:"private"`
|
|
||||||
Fork bool `toml:"fork"`
|
|
||||||
Mirror bool `toml:"mirror"`
|
|
||||||
Archive bool `toml:"archive"`
|
|
||||||
Interval time.Duration `toml:"interval"`
|
|
||||||
Debug bool `toml:"debug"`
|
|
||||||
|
|
||||||
Overrides map[string]nameOverride `toml:"overrides"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type nameOverride struct {
|
|
||||||
Name string `toml:"name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Config = flagConfig{
|
|
||||||
Overrides: make(map[string]nameOverride),
|
|
||||||
}
|
|
||||||
|
|
||||||
configPath string
|
configPath string
|
||||||
|
baseURL string
|
||||||
include cli.StringSlice
|
include cli.StringSlice
|
||||||
exclude cli.StringSlice
|
exclude cli.StringSlice
|
||||||
|
override cli.StringSlice
|
||||||
|
|
||||||
|
Port int
|
||||||
|
Domain string
|
||||||
|
Service string
|
||||||
|
BaseURL *url.URL
|
||||||
|
Namespace string
|
||||||
|
Token string
|
||||||
|
Include []*regexp.Regexp
|
||||||
|
Exclude []*regexp.Regexp
|
||||||
|
Private bool
|
||||||
|
Fork bool
|
||||||
|
Mirror bool
|
||||||
|
Archive bool
|
||||||
|
Override = make(map[string]string)
|
||||||
|
Interval time.Duration
|
||||||
|
Debug bool
|
||||||
|
|
||||||
|
ConfigPackages []*api.Package
|
||||||
)
|
)
|
||||||
|
|
||||||
var Flags = []cli.Flag{
|
var Flags = []cli.Flag{
|
||||||
|
@ -58,41 +52,39 @@ var Flags = []cli.Flag{
|
||||||
Usage: "Port to run the vanity server on",
|
Usage: "Port to run the vanity server on",
|
||||||
Value: 7777,
|
Value: 7777,
|
||||||
EnvVars: []string{"VANITY_PORT"},
|
EnvVars: []string{"VANITY_PORT"},
|
||||||
Destination: &Config.Port,
|
Destination: &Port,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "domain",
|
Name: "domain",
|
||||||
Usage: "Vanity domain, e.g. go.domain.tld",
|
Usage: "Vanity domain, e.g. go.domain.tld",
|
||||||
EnvVars: []string{"VANITY_DOMAIN"},
|
EnvVars: []string{"VANITY_DOMAIN"},
|
||||||
Required: true,
|
Required: true,
|
||||||
Destination: &Config.Domain,
|
Destination: &Domain,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "service",
|
Name: "service",
|
||||||
Usage: "Service type (Gitea, GitHub, GitLab)",
|
Usage: "Service type (Gitea, GitHub, GitLab)",
|
||||||
Value: "gitea",
|
Value: "gitea",
|
||||||
EnvVars: []string{"VANITY_SERVICE"},
|
EnvVars: []string{"VANITY_SERVICE"},
|
||||||
Destination: &Config.Service,
|
Destination: &Service,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "base-url",
|
Name: "base-url",
|
||||||
Usage: "BaseURL URL to service",
|
Usage: "Base URL to service",
|
||||||
EnvVars: []string{"VANITY_BASE_URL"},
|
EnvVars: []string{"VANITY_BASE_URL"},
|
||||||
Destination: &Config.BaseURL,
|
Destination: &baseURL,
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "namespace",
|
Name: "namespace",
|
||||||
Usage: "Owner namespace",
|
Usage: "Owner namespace",
|
||||||
EnvVars: []string{"VANITY_NAMESPACE"},
|
EnvVars: []string{"VANITY_NAMESPACE"},
|
||||||
Required: true,
|
Destination: &Namespace,
|
||||||
Destination: &Config.Namespace,
|
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "token",
|
Name: "token",
|
||||||
Usage: "Access token",
|
Usage: "Access token",
|
||||||
EnvVars: []string{"VANITY_TOKEN"},
|
EnvVars: []string{"VANITY_TOKEN"},
|
||||||
Required: true,
|
Destination: &Token,
|
||||||
Destination: &Config.Token,
|
|
||||||
},
|
},
|
||||||
&cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "include",
|
Name: "include",
|
||||||
|
@ -110,128 +102,103 @@ var Flags = []cli.Flag{
|
||||||
Name: "private",
|
Name: "private",
|
||||||
Usage: "Include private repositories",
|
Usage: "Include private repositories",
|
||||||
EnvVars: []string{"VANITY_PRIVATE"},
|
EnvVars: []string{"VANITY_PRIVATE"},
|
||||||
Destination: &Config.Private,
|
Destination: &Private,
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "fork",
|
Name: "fork",
|
||||||
Usage: "Include forked repositories",
|
Usage: "Include forked repositories",
|
||||||
EnvVars: []string{"VANITY_FORK"},
|
EnvVars: []string{"VANITY_FORK"},
|
||||||
Destination: &Config.Private,
|
Destination: &Fork,
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "mirror",
|
Name: "mirror",
|
||||||
Usage: "Include mirrored repositories",
|
Usage: "Include mirrored repositories",
|
||||||
EnvVars: []string{"VANITY_MIRROR"},
|
EnvVars: []string{"VANITY_MIRROR"},
|
||||||
Destination: &Config.Mirror,
|
Destination: &Mirror,
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "archive",
|
Name: "archive",
|
||||||
Usage: "Include archived repositories",
|
Usage: "Include archived repositories",
|
||||||
EnvVars: []string{"VANITY_ARCHIVE"},
|
EnvVars: []string{"VANITY_ARCHIVE"},
|
||||||
Destination: &Config.Archive,
|
Destination: &Archive,
|
||||||
|
},
|
||||||
|
&cli.StringSliceFlag{
|
||||||
|
Name: "override",
|
||||||
|
Usage: "Repository name to override (NAME=OVERRIDE)",
|
||||||
|
EnvVars: []string{"VANITY_OVERRIDE"},
|
||||||
|
Destination: &override,
|
||||||
},
|
},
|
||||||
&cli.DurationFlag{
|
&cli.DurationFlag{
|
||||||
Name: "interval",
|
Name: "interval",
|
||||||
Usage: "Interval between updating repositories",
|
Usage: "Interval between updating repositories",
|
||||||
Value: time.Minute * 15,
|
Value: time.Minute * 15,
|
||||||
EnvVars: []string{"VANITY_INTERVAL"},
|
EnvVars: []string{"VANITY_INTERVAL"},
|
||||||
Destination: &Config.Interval,
|
Destination: &Interval,
|
||||||
},
|
},
|
||||||
&cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "Debug logging",
|
Usage: "Debug logging",
|
||||||
EnvVars: []string{"VANITY_DEBUG"},
|
EnvVars: []string{"VANITY_DEBUG"},
|
||||||
Destination: &Config.Debug,
|
Destination: &Debug,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func Before(ctx *cli.Context) error {
|
func Before(ctx *cli.Context) error {
|
||||||
setConfig(ctx)
|
setConfig(ctx)
|
||||||
|
|
||||||
if Config.BaseURL == "" {
|
var defaultURL string
|
||||||
switch strings.ToLower(Config.Service) {
|
var configOnly bool
|
||||||
|
switch strings.ToLower(Service) {
|
||||||
case "gitea":
|
case "gitea":
|
||||||
Config.BaseURL = "https://gitea.com"
|
defaultURL = "https://gitea.com"
|
||||||
case "github":
|
case "github":
|
||||||
Config.BaseURL = "https://github.com"
|
defaultURL = "https://github.com"
|
||||||
case "gitlab":
|
case "gitlab":
|
||||||
Config.BaseURL = "https://gitlab.com"
|
defaultURL = "https://gitlab.com"
|
||||||
}
|
case "off":
|
||||||
|
configOnly = true
|
||||||
|
beaver.Infof("Running in config-only mode")
|
||||||
|
defaultURL = "https://domain.tld"
|
||||||
|
default:
|
||||||
|
return errors.New("unrecognized service type")
|
||||||
}
|
}
|
||||||
|
|
||||||
u, err := url.Parse(Config.BaseURL)
|
if baseURL == "" {
|
||||||
|
baseURL = defaultURL
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
BaseURL, err = url.Parse(baseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
Config.URL = u
|
|
||||||
|
|
||||||
Config.Include = make([]*regexp.Regexp, len(include.Value()))
|
if !configOnly {
|
||||||
|
errs := make([]string, 0, 2)
|
||||||
|
if Namespace == "" {
|
||||||
|
errs = append(errs, "namespace")
|
||||||
|
}
|
||||||
|
if Token == "" {
|
||||||
|
errs = append(errs, "token")
|
||||||
|
}
|
||||||
|
if len(errs) > 0 {
|
||||||
|
return fmt.Errorf("%s is required with a service", strings.Join(errs, ", "))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Include = make([]*regexp.Regexp, len(include.Value()))
|
||||||
for idx, i := range include.Value() {
|
for idx, i := range include.Value() {
|
||||||
Config.Include[idx] = regexp.MustCompile(i)
|
Include[idx] = regexp.MustCompile(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
Config.Exclude = make([]*regexp.Regexp, len(exclude.Value()))
|
Exclude = make([]*regexp.Regexp, len(exclude.Value()))
|
||||||
for idx, e := range exclude.Value() {
|
for idx, e := range exclude.Value() {
|
||||||
Config.Exclude[idx] = regexp.MustCompile(e)
|
Exclude[idx] = regexp.MustCompile(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if Config.Debug {
|
if Debug {
|
||||||
beaver.Console.Level = beaver.DEBUG
|
beaver.Console.Level = beaver.DEBUG
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func setConfig(ctx *cli.Context) {
|
|
||||||
for _, env := range os.Environ() {
|
|
||||||
kv := strings.Split(env, "=")
|
|
||||||
if strings.HasPrefix(kv[0], "VANITY_OVERRIDES_") {
|
|
||||||
override := strings.ToLower(strings.TrimPrefix(kv[0], "VANITY_OVERRIDES_"))
|
|
||||||
Config.Overrides[override] = nameOverride{kv[1]}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var cfg flagConfig
|
|
||||||
if configPath != "" {
|
|
||||||
beaver.Infof("Loading configuration from %s", configPath)
|
|
||||||
_, err := toml.DecodeFile(configPath, &cfg)
|
|
||||||
if err != nil {
|
|
||||||
beaver.Errorf("Could not load configuration from %s: %v", configPath, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if !ctx.IsSet("port") && cfg.Port > 0 {
|
|
||||||
Config.Port = cfg.Port
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("domain") && cfg.Domain != "" {
|
|
||||||
Config.Domain = cfg.Domain
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("service") && cfg.Service != "" {
|
|
||||||
Config.Service = cfg.Service
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("base-url") && cfg.BaseURL != "" {
|
|
||||||
Config.BaseURL = cfg.BaseURL
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("namespace") && cfg.Namespace != "" {
|
|
||||||
Config.Namespace = cfg.Namespace
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("token") && cfg.Token != "" {
|
|
||||||
Config.Token = cfg.Token
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("private") && cfg.Private {
|
|
||||||
Config.Private = cfg.Private
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("fork") && cfg.Fork {
|
|
||||||
Config.Fork = cfg.Fork
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("mirror") && cfg.Mirror {
|
|
||||||
Config.Mirror = cfg.Mirror
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("archive") && cfg.Archive {
|
|
||||||
Config.Archive = cfg.Archive
|
|
||||||
}
|
|
||||||
if !ctx.IsSet("debug") && cfg.Debug {
|
|
||||||
Config.Debug = cfg.Debug
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
4
main.go
4
main.go
|
@ -5,9 +5,9 @@ import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
"go.jolheiser.com/vanity/router"
|
"go.jolheiser.com/vanity/router"
|
||||||
"go.jolheiser.com/vanity/version"
|
|
||||||
|
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
"go.jolheiser.com/beaver"
|
"go.jolheiser.com/beaver"
|
||||||
|
@ -17,7 +17,7 @@ func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "vanity"
|
app.Name = "vanity"
|
||||||
app.Usage = "Vanity Go Imports"
|
app.Usage = "Vanity Go Imports"
|
||||||
app.Version = version.Version
|
app.Version = api.Version
|
||||||
app.Action = doAction
|
app.Action = doAction
|
||||||
app.Flags = flags.Flags
|
app.Flags = flags.Flags
|
||||||
app.Before = flags.Before
|
app.Before = flags.Before
|
||||||
|
|
|
@ -3,19 +3,19 @@ package router
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"go.jolheiser.com/vanity/service"
|
"go.jolheiser.com/vanity/api"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cache = &packageCache{
|
var cache = &packageCache{
|
||||||
packages: make(map[string]*service.Package),
|
packages: make(map[string]*api.Package),
|
||||||
}
|
}
|
||||||
|
|
||||||
type packageCache struct {
|
type packageCache struct {
|
||||||
packages map[string]*service.Package
|
packages map[string]*api.Package
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *packageCache) Update(packages map[string]*service.Package) {
|
func (c *packageCache) Update(packages map[string]*api.Package) {
|
||||||
c.Lock()
|
c.Lock()
|
||||||
c.packages = packages
|
c.packages = packages
|
||||||
c.Unlock()
|
c.Unlock()
|
||||||
|
|
|
@ -13,7 +13,7 @@ import (
|
||||||
var svc service.Service
|
var svc service.Service
|
||||||
|
|
||||||
func cronStart() {
|
func cronStart() {
|
||||||
ticker := time.NewTicker(flags.Config.Interval)
|
ticker := time.NewTicker(flags.Interval)
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
<-ticker.C
|
||||||
beaver.Debug("Running package update...")
|
beaver.Debug("Running package update...")
|
||||||
|
@ -36,8 +36,16 @@ func cronUpdate() {
|
||||||
delete(packages, name)
|
delete(packages, name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if !svc.GoMod(pkg) {
|
goMod, err := svc.GoMod(pkg)
|
||||||
beaver.Debugf("%s isn't a Go project", pkg.Name)
|
if err != nil {
|
||||||
|
beaver.Debugf("No go.mod could be found in the root directory of %s", pkg.Name)
|
||||||
|
delete(packages, name)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
lines := strings.Split(goMod, "\n")
|
||||||
|
line := strings.Fields(lines[0])
|
||||||
|
if !strings.HasPrefix(line[1], flags.Domain) {
|
||||||
|
beaver.Debugf("%s is a Go project, however its module does not include this domain", pkg.Name)
|
||||||
delete(packages, name)
|
delete(packages, name)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -46,15 +54,20 @@ func cronUpdate() {
|
||||||
|
|
||||||
// Overrides
|
// Overrides
|
||||||
for name, pkg := range packages {
|
for name, pkg := range packages {
|
||||||
for key, override := range flags.Config.Overrides {
|
for key, override := range flags.Override {
|
||||||
if strings.EqualFold(name, key) {
|
if strings.EqualFold(name, key) {
|
||||||
beaver.Debugf("Overriding %s -> %s", name, override.Name)
|
beaver.Debugf("Overriding %s -> %s", name, override)
|
||||||
delete(packages, key)
|
delete(packages, key)
|
||||||
pkg.Name = override.Name
|
pkg.Name = override
|
||||||
packages[override.Name] = pkg
|
packages[override] = pkg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add packages manually added to config
|
||||||
|
for _, pkg := range flags.ConfigPackages {
|
||||||
|
packages[pkg.Name] = pkg
|
||||||
|
}
|
||||||
|
|
||||||
cache.Update(packages)
|
cache.Update(packages)
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
"go.jolheiser.com/vanity/router/templates"
|
"go.jolheiser.com/vanity/router/templates"
|
||||||
"go.jolheiser.com/vanity/service"
|
"go.jolheiser.com/vanity/service"
|
||||||
"go.jolheiser.com/vanity/version"
|
|
||||||
|
|
||||||
"github.com/go-chi/chi"
|
"github.com/go-chi/chi"
|
||||||
"github.com/go-chi/chi/middleware"
|
"github.com/go-chi/chi/middleware"
|
||||||
|
@ -39,14 +39,14 @@ func Init() *chi.Mux {
|
||||||
beaver.Infof("Finished warming up cache: %s", cache.Names())
|
beaver.Infof("Finished warming up cache: %s", cache.Names())
|
||||||
go cronStart()
|
go cronStart()
|
||||||
|
|
||||||
beaver.Infof("Running vanity server at http://localhost:%d", flags.Config.Port)
|
beaver.Infof("Running vanity server at http://localhost:%d", flags.Port)
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|
||||||
func doIndex(res http.ResponseWriter, _ *http.Request) {
|
func doIndex(res http.ResponseWriter, _ *http.Request) {
|
||||||
if err := index.Execute(res, map[string]interface{}{
|
if err := index.Execute(res, map[string]interface{}{
|
||||||
"Packages": cache.packages,
|
"Packages": cache.packages,
|
||||||
"AppVer": version.Version,
|
"AppVer": api.Version,
|
||||||
"GoVer": runtime.Version(),
|
"GoVer": runtime.Version(),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
beaver.Error(err)
|
beaver.Error(err)
|
||||||
|
@ -63,9 +63,9 @@ func doVanity(res http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
if err := vanity.Execute(res, map[string]interface{}{
|
if err := vanity.Execute(res, map[string]interface{}{
|
||||||
"Package": pkg,
|
"Package": pkg,
|
||||||
"AppVer": version.Version,
|
"AppVer": api.Version,
|
||||||
"GoVer": runtime.Version(),
|
"GoVer": runtime.Version(),
|
||||||
"GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(), pkg.HTTP, svc.GoDir(pkg), svc.GoFile(pkg)),
|
"GoSource": fmt.Sprintf("%s %s %s %s", pkg.Module(flags.Domain), pkg.CloneHTTP, svc.GoDir(pkg), svc.GoFile(pkg)),
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
beaver.Error(err)
|
beaver.Error(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,11 +11,11 @@ var Head = `
|
||||||
<meta name="og:description" content="{{.Package.Description}}"/>
|
<meta name="og:description" content="{{.Package.Description}}"/>
|
||||||
|
|
||||||
<!-- Go -->
|
<!-- Go -->
|
||||||
<meta name="go-import" content="{{.Package.Module}} git {{.Package.HTTP}}"/>
|
<meta name="go-import" content="{{.Package.Module}} git {{.Package.CloneHTTP}}"/>
|
||||||
<meta name="go-source" content="{{.GoSource}}">
|
<meta name="go-source" content="{{.GoSource}}">
|
||||||
|
|
||||||
<!-- Git Import -->
|
<!-- Git Import -->
|
||||||
<meta name="git-import" content="{{.Package.Name}} {{.Package.HTTP}} {{.Package.SSH}}"/>
|
<meta name="git-import" content="{{.Package.Name}} {{.Package.CloneHTTP}} {{.Package.CloneSSH}}"/>
|
||||||
{{end}}
|
{{end}}
|
||||||
<title>Vanity - {{if .Package}}{{.Package.Name}}{{else}}Index{{end}}</title>
|
<title>Vanity - {{if .Package}}{{.Package.Name}}{{else}}Index{{end}}</title>
|
||||||
</head>
|
</head>
|
||||||
|
|
|
@ -4,7 +4,7 @@ var Vanity = `
|
||||||
<h1><a href="../">Index</a></h1>
|
<h1><a href="../">Index</a></h1>
|
||||||
<hr/>
|
<hr/>
|
||||||
<p><strong>Name: </strong>{{.Package.Name}}</p>
|
<p><strong>Name: </strong>{{.Package.Name}}</p>
|
||||||
<p><strong>Source: </strong><a href="{{.Package.URL}}">{{.Package.URL}}</a></p>
|
<p><strong>Source: </strong><a href="{{.Package.WebURL}}">{{.Package.WebURL}}</a></p>
|
||||||
{{if .Package.Description}}<p><strong>Description: </strong>{{.Package.Description}}</p>{{end}}
|
{{if .Package.Description}}<p><strong>Description: </strong>{{.Package.Description}}</p>{{end}}
|
||||||
<p><strong>Documentation: <a href="https://pkg.go.dev/{{.Package.Module}}">https://pkg.go.dev/{{.Package.Module}}</a></strong></p>
|
<p><strong>Documentation: <a href="https://pkg.go.dev/{{.Package.Module}}">https://pkg.go.dev/{{.Package.Module}}</a></strong></p>
|
||||||
`
|
`
|
||||||
|
|
|
@ -3,6 +3,7 @@ package service
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
|
||||||
"code.gitea.io/sdk/gitea"
|
"code.gitea.io/sdk/gitea"
|
||||||
|
@ -11,7 +12,7 @@ import (
|
||||||
var _ Service = &Gitea{}
|
var _ Service = &Gitea{}
|
||||||
|
|
||||||
func NewGitea() *Gitea {
|
func NewGitea() *Gitea {
|
||||||
client := gitea.NewClient(flags.Config.BaseURL, flags.Config.Token)
|
client := gitea.NewClient(flags.BaseURL.String(), flags.Token)
|
||||||
return &Gitea{
|
return &Gitea{
|
||||||
client: client,
|
client: client,
|
||||||
}
|
}
|
||||||
|
@ -21,8 +22,8 @@ type Gitea struct {
|
||||||
client *gitea.Client
|
client *gitea.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Gitea) Packages() (map[string]*Package, error) {
|
func (g Gitea) Packages() (map[string]*api.Package, error) {
|
||||||
packages := make(map[string]*Package)
|
packages := make(map[string]*api.Package)
|
||||||
page := 0
|
page := 0
|
||||||
for {
|
for {
|
||||||
opts := gitea.ListReposOptions{
|
opts := gitea.ListReposOptions{
|
||||||
|
@ -32,23 +33,23 @@ func (g Gitea) Packages() (map[string]*Package, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, err := g.client.ListUserRepos(flags.Config.Namespace, opts)
|
repos, err := g.client.ListUserRepos(flags.Namespace, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
packages[repo.Name] = &Package{
|
packages[repo.Name] = &api.Package{
|
||||||
Name: repo.Name,
|
Name: repo.Name,
|
||||||
Description: repo.Description,
|
Description: repo.Description,
|
||||||
Branch: repo.DefaultBranch,
|
Branch: repo.DefaultBranch,
|
||||||
URL: repo.HTMLURL,
|
WebURL: repo.HTMLURL,
|
||||||
HTTP: repo.CloneURL,
|
CloneHTTP: repo.CloneURL,
|
||||||
SSH: repo.SSHURL,
|
CloneSSH: repo.SSHURL,
|
||||||
private: repo.Private,
|
Private: repo.Private,
|
||||||
fork: repo.Fork,
|
Fork: repo.Fork,
|
||||||
mirror: repo.Mirror,
|
Mirror: repo.Mirror,
|
||||||
archive: repo.Archived,
|
Archive: repo.Archived,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,15 +62,15 @@ func (g Gitea) Packages() (map[string]*Package, error) {
|
||||||
return packages, nil
|
return packages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Gitea) GoDir(pkg *Package) string {
|
func (g Gitea) GoDir(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/src/branch/%s{/dir}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/src/branch/%s{/dir}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Gitea) GoFile(pkg *Package) string {
|
func (g Gitea) GoFile(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/src/branch/%s{/dir}/{file}#L{line}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/src/branch/%s{/dir}/{file}#L{line}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Gitea) GoMod(pkg *Package) bool {
|
func (g Gitea) GoMod(pkg *api.Package) (string, error) {
|
||||||
_, err := g.client.GetFile(flags.Config.Namespace, pkg.Name, pkg.Branch, "go.mod")
|
content, err := g.client.GetFile(flags.Namespace, pkg.Name, pkg.Branch, "go.mod")
|
||||||
return err == nil
|
return string(content), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
|
||||||
"github.com/google/go-github/v32/github"
|
"github.com/google/go-github/v32/github"
|
||||||
|
@ -14,11 +15,11 @@ var _ Service = &GitHub{}
|
||||||
|
|
||||||
func NewGitHub() *GitHub {
|
func NewGitHub() *GitHub {
|
||||||
ts := oauth2.StaticTokenSource(
|
ts := oauth2.StaticTokenSource(
|
||||||
&oauth2.Token{AccessToken: flags.Config.Token},
|
&oauth2.Token{AccessToken: flags.Token},
|
||||||
)
|
)
|
||||||
client := oauth2.NewClient(context.Background(), ts)
|
client := oauth2.NewClient(context.Background(), ts)
|
||||||
ghClient := github.NewClient(client)
|
ghClient := github.NewClient(client)
|
||||||
ghClient.BaseURL = flags.Config.URL
|
ghClient.BaseURL = flags.BaseURL
|
||||||
return &GitHub{
|
return &GitHub{
|
||||||
client: ghClient,
|
client: ghClient,
|
||||||
}
|
}
|
||||||
|
@ -28,8 +29,8 @@ type GitHub struct {
|
||||||
client *github.Client
|
client *github.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitHub) Packages() (map[string]*Package, error) {
|
func (g GitHub) Packages() (map[string]*api.Package, error) {
|
||||||
packages := make(map[string]*Package)
|
packages := make(map[string]*api.Package)
|
||||||
page := 0
|
page := 0
|
||||||
for {
|
for {
|
||||||
opts := github.RepositoryListOptions{
|
opts := github.RepositoryListOptions{
|
||||||
|
@ -39,23 +40,23 @@ func (g GitHub) Packages() (map[string]*Package, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, _, err := g.client.Repositories.List(context.Background(), flags.Config.Namespace, &opts)
|
repos, _, err := g.client.Repositories.List(context.Background(), flags.Namespace, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
packages[repo.GetName()] = &Package{
|
packages[repo.GetName()] = &api.Package{
|
||||||
Name: repo.GetName(),
|
Name: repo.GetName(),
|
||||||
Description: repo.GetDescription(),
|
Description: repo.GetDescription(),
|
||||||
Branch: repo.GetDefaultBranch(),
|
Branch: repo.GetDefaultBranch(),
|
||||||
URL: repo.GetHTMLURL(),
|
WebURL: repo.GetHTMLURL(),
|
||||||
HTTP: repo.GetCloneURL(),
|
CloneHTTP: repo.GetCloneURL(),
|
||||||
SSH: repo.GetSSHURL(),
|
CloneSSH: repo.GetSSHURL(),
|
||||||
private: repo.GetPrivate(),
|
Private: repo.GetPrivate(),
|
||||||
fork: repo.GetFork(),
|
Fork: repo.GetFork(),
|
||||||
mirror: false,
|
Mirror: false,
|
||||||
archive: repo.GetArchived(),
|
Archive: repo.GetArchived(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,18 +69,21 @@ func (g GitHub) Packages() (map[string]*Package, error) {
|
||||||
return packages, nil
|
return packages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitHub) GoDir(pkg *Package) string {
|
func (g GitHub) GoDir(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/tree/%s{/dir}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/tree/%s{/dir}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitHub) GoFile(pkg *Package) string {
|
func (g GitHub) GoFile(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/blob/%s{/dir}/{file}#L{line}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/blob/%s{/dir}/{file}#L{line}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitHub) GoMod(pkg *Package) bool {
|
func (g GitHub) GoMod(pkg *api.Package) (string, error) {
|
||||||
_, _, _, err := g.client.Repositories.GetContents(context.Background(), flags.Config.Namespace, pkg.Name, "go.mod",
|
content, _, _, err := g.client.Repositories.GetContents(context.Background(), flags.Namespace, pkg.Name, "go.mod",
|
||||||
&github.RepositoryContentGetOptions{
|
&github.RepositoryContentGetOptions{
|
||||||
Ref: pkg.Branch,
|
Ref: pkg.Branch,
|
||||||
})
|
})
|
||||||
return err == nil
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
return content.GetContent()
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"html"
|
"html"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
|
|
||||||
"github.com/xanzy/go-gitlab"
|
"github.com/xanzy/go-gitlab"
|
||||||
|
@ -13,7 +14,7 @@ import (
|
||||||
var _ Service = &GitLab{}
|
var _ Service = &GitLab{}
|
||||||
|
|
||||||
func NewGitLab() *GitLab {
|
func NewGitLab() *GitLab {
|
||||||
client, err := gitlab.NewClient(flags.Config.Token, gitlab.WithBaseURL(flags.Config.BaseURL))
|
client, err := gitlab.NewClient(flags.Token, gitlab.WithBaseURL(flags.BaseURL.String()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
beaver.Errorf("could not create GitLab client: %v", err)
|
beaver.Errorf("could not create GitLab client: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -26,8 +27,8 @@ type GitLab struct {
|
||||||
client *gitlab.Client
|
client *gitlab.Client
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitLab) Packages() (map[string]*Package, error) {
|
func (g GitLab) Packages() (map[string]*api.Package, error) {
|
||||||
packages := make(map[string]*Package)
|
packages := make(map[string]*api.Package)
|
||||||
page := 0
|
page := 0
|
||||||
for {
|
for {
|
||||||
opts := gitlab.ListProjectsOptions{
|
opts := gitlab.ListProjectsOptions{
|
||||||
|
@ -37,23 +38,23 @@ func (g GitLab) Packages() (map[string]*Package, error) {
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
repos, _, err := g.client.Projects.ListUserProjects(flags.Config.Namespace, &opts)
|
repos, _, err := g.client.Projects.ListUserProjects(flags.Namespace, &opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, repo := range repos {
|
for _, repo := range repos {
|
||||||
packages[repo.Name] = &Package{
|
packages[repo.Name] = &api.Package{
|
||||||
Name: repo.Name,
|
Name: repo.Name,
|
||||||
Description: repo.Description,
|
Description: repo.Description,
|
||||||
Branch: repo.DefaultBranch,
|
Branch: repo.DefaultBranch,
|
||||||
URL: repo.WebURL,
|
WebURL: repo.WebURL,
|
||||||
HTTP: repo.HTTPURLToRepo,
|
CloneHTTP: repo.HTTPURLToRepo,
|
||||||
SSH: repo.SSHURLToRepo,
|
CloneSSH: repo.SSHURLToRepo,
|
||||||
private: repo.Visibility != gitlab.PublicVisibility,
|
Private: repo.Visibility != gitlab.PublicVisibility,
|
||||||
fork: repo.ForkedFromProject != nil,
|
Fork: repo.ForkedFromProject != nil,
|
||||||
mirror: repo.Mirror,
|
Mirror: repo.Mirror,
|
||||||
archive: repo.Archived,
|
Archive: repo.Archived,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,18 +67,18 @@ func (g GitLab) Packages() (map[string]*Package, error) {
|
||||||
return packages, nil
|
return packages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitLab) GoDir(pkg *Package) string {
|
func (g GitLab) GoDir(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/-/tree/%s{/dir}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/-/tree/%s{/dir}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitLab) GoFile(pkg *Package) string {
|
func (g GitLab) GoFile(pkg *api.Package) string {
|
||||||
return fmt.Sprintf("%s/-/blob/%s{/dir}/{file}#L{line}", pkg.URL, pkg.Branch)
|
return fmt.Sprintf("%s/-/blob/%s{/dir}/{file}#L{line}", pkg.WebURL, pkg.Branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g GitLab) GoMod(pkg *Package) bool {
|
func (g GitLab) GoMod(pkg *api.Package) (string, error) {
|
||||||
id := fmt.Sprintf("%s/%s", flags.Config.Namespace, pkg.Name)
|
id := fmt.Sprintf("%s/%s", flags.Namespace, pkg.Name)
|
||||||
_, _, err := g.client.RepositoryFiles.GetRawFile(html.EscapeString(id), "go.mod", &gitlab.GetRawFileOptions{
|
content, _, err := g.client.RepositoryFiles.GetRawFile(html.EscapeString(id), "go.mod", &gitlab.GetRawFileOptions{
|
||||||
Ref: &pkg.Branch,
|
Ref: &pkg.Branch,
|
||||||
})
|
})
|
||||||
return err == nil
|
return string(content), err
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
package service
|
||||||
|
|
||||||
|
import "go.jolheiser.com/vanity/api"
|
||||||
|
|
||||||
|
var _ Service = Off{}
|
||||||
|
|
||||||
|
type Off struct{}
|
||||||
|
|
||||||
|
func (o Off) Packages() (map[string]*api.Package, error) {
|
||||||
|
return make(map[string]*api.Package), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Off) GoDir(*api.Package) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Off) GoFile(*api.Package) string {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o Off) GoMod(*api.Package) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
|
@ -4,78 +4,62 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"go.jolheiser.com/vanity/api"
|
||||||
"go.jolheiser.com/vanity/flags"
|
"go.jolheiser.com/vanity/flags"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Package struct {
|
|
||||||
Name string
|
|
||||||
Description string
|
|
||||||
Branch string
|
|
||||||
URL string
|
|
||||||
HTTP string
|
|
||||||
SSH string
|
|
||||||
|
|
||||||
private bool
|
|
||||||
fork bool
|
|
||||||
mirror bool
|
|
||||||
archive bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *Package) Module() string {
|
|
||||||
return fmt.Sprintf("%s/%s", flags.Config.Domain, strings.ToLower(p.Name))
|
|
||||||
}
|
|
||||||
|
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Packages() (map[string]*Package, error)
|
Packages() (map[string]*api.Package, error)
|
||||||
GoDir(*Package) string
|
GoDir(*api.Package) string
|
||||||
GoFile(*Package) string
|
GoFile(*api.Package) string
|
||||||
GoMod(*Package) bool
|
GoMod(*api.Package) (string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
func New() Service {
|
func New() Service {
|
||||||
switch strings.ToLower(flags.Config.Service) {
|
switch strings.ToLower(flags.Service) {
|
||||||
case "gitea":
|
case "gitea":
|
||||||
return NewGitea()
|
return NewGitea()
|
||||||
case "github":
|
case "github":
|
||||||
return NewGitHub()
|
return NewGitHub()
|
||||||
case "gitlab":
|
case "gitlab":
|
||||||
return NewGitLab()
|
return NewGitLab()
|
||||||
|
default:
|
||||||
|
return Off{}
|
||||||
}
|
}
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Check(pkg *Package) error {
|
func Check(pkg *api.Package) error {
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
if pkg.private && !flags.Config.Private {
|
if pkg.Private && !flags.Private {
|
||||||
return fmt.Errorf("%s is private and --private wasn't used", pkg.Name)
|
return fmt.Errorf("%s is private and --private wasn't used", pkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Forked
|
// Forked
|
||||||
if pkg.fork && !flags.Config.Fork {
|
if pkg.Fork && !flags.Fork {
|
||||||
return fmt.Errorf("%s is a fork and --fork wasn't used", pkg.Name)
|
return fmt.Errorf("%s is a fork and --fork wasn't used", pkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Mirrored
|
// Mirrored
|
||||||
if pkg.mirror && !flags.Config.Mirror {
|
if pkg.Mirror && !flags.Mirror {
|
||||||
return fmt.Errorf("%s is a mirror and --mirror wasn't used", pkg.Name)
|
return fmt.Errorf("%s is a mirror and --mirror wasn't used", pkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Archived
|
// Archived
|
||||||
if pkg.archive && !flags.Config.Archive {
|
if pkg.Archive && !flags.Archive {
|
||||||
return fmt.Errorf("%s is archived and --archive wasn't used", pkg.Name)
|
return fmt.Errorf("%s is archived and --archive wasn't used", pkg.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exclusions
|
// Exclusions
|
||||||
for _, exclude := range flags.Config.Exclude {
|
for _, exclude := range flags.Exclude {
|
||||||
if exclude.MatchString(pkg.Name) {
|
if exclude.MatchString(pkg.Name) {
|
||||||
return fmt.Errorf("%s is was excluded by the rule %s", pkg.Name, exclude.String())
|
return fmt.Errorf("%s is was excluded by the rule %s", pkg.Name, exclude.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inclusions
|
// Inclusions
|
||||||
if len(flags.Config.Include) > 0 {
|
if len(flags.Include) > 0 {
|
||||||
for _, include := range flags.Config.Include {
|
for _, include := range flags.Include {
|
||||||
if include.MatchString(pkg.Name) {
|
if include.MatchString(pkg.Name) {
|
||||||
return fmt.Errorf("%s is was included by the rule %s", pkg.Name, include.String())
|
return fmt.Errorf("%s is was included by the rule %s", pkg.Name, include.String())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue