generated from templates/go-generic
checkpoint: skeleton code
This commit is contained in:
parent
7751cf2fe8
commit
ed5f62887c
15 changed files with 253 additions and 28 deletions
|
@ -13,6 +13,14 @@ output:
|
||||||
sort-results: true
|
sort-results: true
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
|
depguard:
|
||||||
|
rules:
|
||||||
|
main:
|
||||||
|
files:
|
||||||
|
- $all
|
||||||
|
allow:
|
||||||
|
- $gostd
|
||||||
|
- codeflow.dananglin.me.uk/apollo/indieauth-server
|
||||||
lll:
|
lll:
|
||||||
line-length: 140
|
line-length: 140
|
||||||
|
|
||||||
|
|
32
cmd/indieauth-server/main.go
Normal file
32
cmd/indieauth-server/main.go
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/executors"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
binaryVersion string
|
||||||
|
buildTime string
|
||||||
|
goVersion string
|
||||||
|
gitCommit string
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// Set up logging
|
||||||
|
loggingLevel := new(slog.LevelVar)
|
||||||
|
|
||||||
|
slogOpts := slog.HandlerOptions{
|
||||||
|
Level: loggingLevel,
|
||||||
|
}
|
||||||
|
|
||||||
|
logger := slog.New(slog.NewTextHandler(os.Stdout, &slogOpts))
|
||||||
|
slog.SetDefault(logger)
|
||||||
|
loggingLevel.Set(slog.LevelInfo)
|
||||||
|
|
||||||
|
if err := executors.Execute(os.Args[1:]); err != nil {
|
||||||
|
slog.Error(err.Error())
|
||||||
|
}
|
||||||
|
}
|
3
go.mod
Normal file
3
go.mod
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
module codeflow.dananglin.me.uk/apollo/indieauth-server
|
||||||
|
|
||||||
|
go 1.23.2
|
27
internal/executors/command.go
Normal file
27
internal/executors/command.go
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package executors
|
||||||
|
|
||||||
|
type command struct {
|
||||||
|
name string
|
||||||
|
args []string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newCommand(args []string) command {
|
||||||
|
if len(args) == 0 {
|
||||||
|
return command{
|
||||||
|
name: "help",
|
||||||
|
args: make([]string, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(args) == 1 {
|
||||||
|
return command{
|
||||||
|
name: args[0],
|
||||||
|
args: make([]string, 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return command{
|
||||||
|
name: args[0],
|
||||||
|
args: args[1:],
|
||||||
|
}
|
||||||
|
}
|
9
internal/executors/errors.go
Normal file
9
internal/executors/errors.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package executors
|
||||||
|
|
||||||
|
type UnrecognisedCommandError struct {
|
||||||
|
command string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e UnrecognisedCommandError) Error() string {
|
||||||
|
return "unrecognised command: "+ e.command
|
||||||
|
}
|
17
internal/executors/executors.go
Normal file
17
internal/executors/executors.go
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package executors
|
||||||
|
|
||||||
|
func Execute(args []string) error {
|
||||||
|
command := newCommand(args)
|
||||||
|
|
||||||
|
executorFuncMap := map[string]func(args []string) error{
|
||||||
|
"serve": executeServeCommand,
|
||||||
|
"version": executeVersionCommand,
|
||||||
|
}
|
||||||
|
|
||||||
|
executeFunc, ok := executorFuncMap[command.name]
|
||||||
|
if !ok {
|
||||||
|
return UnrecognisedCommandError{command.name}
|
||||||
|
}
|
||||||
|
|
||||||
|
return executeFunc(command.args)
|
||||||
|
}
|
1
internal/executors/help.go
Normal file
1
internal/executors/help.go
Normal file
|
@ -0,0 +1 @@
|
||||||
|
package executors
|
55
internal/executors/serve.go
Normal file
55
internal/executors/serve.go
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
package executors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"net/http"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/info"
|
||||||
|
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/router"
|
||||||
|
)
|
||||||
|
|
||||||
|
type serveExecutor struct {
|
||||||
|
*flag.FlagSet
|
||||||
|
|
||||||
|
address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeServeCommand(args []string) error {
|
||||||
|
executorName := "serve"
|
||||||
|
|
||||||
|
executor := serveExecutor{
|
||||||
|
FlagSet: flag.NewFlagSet(executorName, flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.StringVar(&executor.address, "address", "0.0.0.0:8080", "The address that the server will listen on")
|
||||||
|
|
||||||
|
if err := executor.Parse(args); err != nil {
|
||||||
|
return fmt.Errorf("(%s) flag parsing error: %w", executorName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := executor.execute(); err != nil {
|
||||||
|
return fmt.Errorf("(%s) execution error: %w", executorName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *serveExecutor) execute() error {
|
||||||
|
server := http.Server{
|
||||||
|
Addr: e.address,
|
||||||
|
Handler: router.NewServeMux(),
|
||||||
|
ReadHeaderTimeout: 1 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
slog.Info(info.ApplicationName + " is listening for web requests", "address", e.address)
|
||||||
|
|
||||||
|
err := server.ListenAndServe()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error running the server: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
58
internal/executors/version.go
Normal file
58
internal/executors/version.go
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
package executors
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"strings"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"codeflow.dananglin.me.uk/apollo/indieauth-server/internal/info"
|
||||||
|
)
|
||||||
|
|
||||||
|
type versionExecutor struct {
|
||||||
|
*flag.FlagSet
|
||||||
|
|
||||||
|
showFullVersion bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func executeVersionCommand(args []string) error {
|
||||||
|
executorName := "version"
|
||||||
|
|
||||||
|
executor := versionExecutor{
|
||||||
|
FlagSet: flag.NewFlagSet(executorName, flag.ExitOnError),
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.BoolVar(&executor.showFullVersion, "full", false, "Print the applications full build information")
|
||||||
|
|
||||||
|
if err := executor.Parse(args); err != nil {
|
||||||
|
return fmt.Errorf("(%s) flag parsing error: %w", executorName, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
executor.printVersion()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (e *versionExecutor) printVersion() {
|
||||||
|
if !e.showFullVersion {
|
||||||
|
fmt.Fprintf(os.Stdout, "%s %s\n", info.ApplicationName, info.BinaryVersion)
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var builder strings.Builder
|
||||||
|
|
||||||
|
builder.WriteString(info.ApplicationName + "\n\n")
|
||||||
|
|
||||||
|
tableWriter := tabwriter.NewWriter(&builder, 0, 4, 1, ' ', 0)
|
||||||
|
|
||||||
|
_, _ = tableWriter.Write([]byte("Version:" + "\t" + info.BinaryVersion + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte("Git commit:" + "\t" + info.GitCommit + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte("Go version:" + "\t" + info.GoVersion + "\n"))
|
||||||
|
_, _ = tableWriter.Write([]byte("Build date:" + "\t" + info.BuildTime + "\n"))
|
||||||
|
|
||||||
|
tableWriter.Flush()
|
||||||
|
|
||||||
|
os.Stdout.WriteString(builder.String())
|
||||||
|
}
|
12
internal/info/info.go
Normal file
12
internal/info/info.go
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
package info
|
||||||
|
|
||||||
|
const (
|
||||||
|
ApplicationName string = "indieauth-server"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
BinaryVersion string //nolint:gochecknoglobals
|
||||||
|
BuildTime string //nolint:gochecknoglobals
|
||||||
|
GoVersion string //nolint:gochecknoglobals
|
||||||
|
GitCommit string //nolint:gochecknoglobals
|
||||||
|
)
|
9
internal/router/router.go
Normal file
9
internal/router/router.go
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
package router
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
func NewServeMux() *http.ServeMux {
|
||||||
|
mux := http.NewServeMux()
|
||||||
|
|
||||||
|
return mux
|
||||||
|
}
|
5
magefiles/go.mod
Normal file
5
magefiles/go.mod
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
module codeflow.dananglin.me.uk/apollo/indieauth-server/magefiles
|
||||||
|
|
||||||
|
go 1.23.2
|
||||||
|
|
||||||
|
require github.com/magefile/mage v1.15.0
|
2
magefiles/go.sum
Normal file
2
magefiles/go.sum
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
github.com/magefile/mage v1.15.0 h1:BvGheCMAsG3bWUDbZ8AyXXpCNwU9u5CB6sM+HNb9HYg=
|
||||||
|
github.com/magefile/mage v1.15.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A=
|
|
@ -14,7 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
app = "binary"
|
app = "indieauth-server"
|
||||||
defaultInstallPrefix = "/usr/local"
|
defaultInstallPrefix = "/usr/local"
|
||||||
envInstallPrefix = "PROJECT_INSTALL_PREFIX"
|
envInstallPrefix = "PROJECT_INSTALL_PREFIX"
|
||||||
envTestVerbose = "PROJECT_TEST_VERBOSE"
|
envTestVerbose = "PROJECT_TEST_VERBOSE"
|
||||||
|
@ -56,7 +56,7 @@ func Lint() error {
|
||||||
// To rebuild packages that are already up-to-date set PROJECT_BUILD_REBUILD_ALL=1
|
// To rebuild packages that are already up-to-date set PROJECT_BUILD_REBUILD_ALL=1
|
||||||
// To enable verbose mode set PROJECT_BUILD_VERBOSE=1
|
// To enable verbose mode set PROJECT_BUILD_VERBOSE=1
|
||||||
func Build() error {
|
func Build() error {
|
||||||
main := "main.go"
|
main := "./cmd/" + app
|
||||||
flags := ldflags()
|
flags := ldflags()
|
||||||
build := sh.RunCmd("go", "build")
|
build := sh.RunCmd("go", "build")
|
||||||
args := []string{"-ldflags=" + flags, "-o", binary}
|
args := []string{"-ldflags=" + flags, "-o", binary}
|
||||||
|
@ -110,10 +110,21 @@ func Clean() error {
|
||||||
|
|
||||||
// ldflags returns the build flags.
|
// ldflags returns the build flags.
|
||||||
func ldflags() string {
|
func ldflags() string {
|
||||||
ldflagsfmt := "-s -w -X main.binaryVersion=%s -X main.gitCommit=%s -X main.goVersion=%s -X main.buildTime=%s"
|
versionPackage := "codeflow.dananglin.me.uk/apollo/indieauth-server/internal/info"
|
||||||
|
binaryVersionVar := versionPackage + "." + "BinaryVersion"
|
||||||
|
gitCommitVar := versionPackage + "." + "GitCommit"
|
||||||
|
goVersionVar := versionPackage + "." + "GoVersion"
|
||||||
|
buildTimeVar := versionPackage + "." + "BuildTime"
|
||||||
|
ldflagsfmt := "-s -w -X %s=%s -X %s=%s -X %s=%s -X %s=%s"
|
||||||
buildTime := time.Now().UTC().Format(time.RFC3339)
|
buildTime := time.Now().UTC().Format(time.RFC3339)
|
||||||
|
|
||||||
return fmt.Sprintf(ldflagsfmt, version(), gitCommit(), runtime.Version(), buildTime)
|
return fmt.Sprintf(
|
||||||
|
ldflagsfmt,
|
||||||
|
binaryVersionVar, version(),
|
||||||
|
gitCommitVar, gitCommit(),
|
||||||
|
goVersionVar, runtime.Version(),
|
||||||
|
buildTimeVar, buildTime,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// version returns the latest git tag using git describe.
|
// version returns the latest git tag using git describe.
|
||||||
|
|
24
main.go
24
main.go
|
@ -1,24 +0,0 @@
|
||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
binaryVersion string
|
|
||||||
buildTime string
|
|
||||||
goVersion string
|
|
||||||
gitCommit string
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
if err := run(); err != nil {
|
|
||||||
fmt.Printf("ERROR: %v.\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func run() error {
|
|
||||||
return nil
|
|
||||||
}
|
|
Loading…
Reference in a new issue