Compare commits

...

2 commits

Author SHA1 Message Date
f393d982f5
run gosec and staticcheck in ci
Some checks failed
CI / Tests (pull_request) Failing after 2m18s
CI / Style (pull_request) Failing after 8s
2024-10-13 12:04:20 +01:00
ed5f62887c
checkpoint: skeleton code 2024-10-12 21:38:53 +01:00
16 changed files with 280 additions and 33 deletions

View file

@ -1,5 +1,5 @@
--- ---
name: Workflow name: CI
on: on:
pull_request: pull_request:
@ -8,12 +8,10 @@ on:
- synchronize - synchronize
jobs: jobs:
test: tests:
name: Tests
if: ${{ ! github.event.pull_request.draft }} if: ${{ ! github.event.pull_request.draft }}
runs-on: docker runs-on: docker
env:
GO_TEST_VERBOSE: "1"
GO_TEST_COVER: "1"
steps: steps:
- name: Checkout Repository - name: Checkout Repository
uses: https://code.forgejo.org/actions/checkout@v4 uses: https://code.forgejo.org/actions/checkout@v4
@ -24,3 +22,19 @@ jobs:
env: env:
PROJECT_TEST_VERBOSE: "1" PROJECT_TEST_VERBOSE: "1"
PROJECT_TEST_COVER: "1" PROJECT_TEST_COVER: "1"
- name: Gosec
uses: https://codeflow.dananglin.me.uk/actions/mage-ci@main
with:
target: gosec
style:
name: Style
if: ${{ ! github.event.pull_request.draft }}
runs-on: docker
steps:
- name: Checkout Repository
uses: https://code.forgejo.org/actions/checkout@v4
- name: Run staticcheck
uses: https://codeflow.dananglin.me.uk/actions/mage-ci@main
with:
target: staticcheck

View file

@ -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

View 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
View file

@ -0,0 +1,3 @@
module codeflow.dananglin.me.uk/apollo/indieauth-server
go 1.23.2

View 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:],
}
}

View file

@ -0,0 +1,9 @@
package executors
type UnrecognisedCommandError struct {
command string
}
func (e UnrecognisedCommandError) Error() string {
return "unrecognised command: " + e.command
}

View 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)
}

View file

@ -0,0 +1 @@
package executors

View 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
}

View 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
View 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
)

View 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
View 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
View 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=

View file

@ -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"
@ -52,11 +52,19 @@ func Lint() error {
return sh.RunV("golangci-lint", "run", "--color", "always") return sh.RunV("golangci-lint", "run", "--color", "always")
} }
func Gosec() error {
return sh.RunV("gosec", "./...")
}
func Staticcheck() error {
return sh.RunV("staticcheck", "./...")
}
// Build build the executable. // Build build the executable.
// 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 +118,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
View file

@ -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
}