go webserver template added
Some checks failed
Update Child Repos / update (push) Failing after 1m2s

This commit is contained in:
2025-12-17 10:49:43 +01:00
parent 9cbfd850bc
commit 8d1555249a
11 changed files with 319 additions and 0 deletions

6
.dockerignore Normal file
View File

@@ -0,0 +1,6 @@
LICENSE
dockerfile
makefile
.makeVars
*.md
*.sh

4
config.yaml.example Normal file
View File

@@ -0,0 +1,4 @@
---
listen:
address: 0.0.0.0
port: 80

39
deploy.sh Normal file
View File

@@ -0,0 +1,39 @@
#!/usr/bin/env bash
# Convert deployment paths into array
ENVIRONMENTS=($DEPLOYMENT_PATHS)
# Check if the DEPLOYMENT_PATH is not already set
if [ -z "${DEPLOYMENT_PATH}" ]; then
# Print and ask for deployment environment (if more than one)
if [ "${#ENVIRONMENTS[@]}" -gt 1 ]; then
for i in "${!ENVIRONMENTS[@]}"; do
echo "$i: ${ENVIRONMENTS[$i]}"
done
read -p "Deployment environment: " DEPLOYMENT_ENVIRONMENT
fi
if [ -z "${DEPLOYMENT_ENVIRONMENT}" ]; then
DEPLOYMENT_ENVIRONMENT=0
fi
# Select correct path
DEPLOYMENT_PATH="${ENVIRONMENTS[$DEPLOYMENT_ENVIRONMENT]}"
fi
# Check if the DEPLOYMENT_VERSION is not already set
if [ -z "${DEPLOYMENT_VERSION}" ]; then
# Ask for deployment version
read -p "Version [latest]: " DEPLOYMENT_VERSION
if [ -z "${DEPLOYMENT_VERSION}" ]; then
DEPLOYMENT_VERSION=latest
fi
fi
echo "${DEPLOYMENT_PATH}"
echo "${DEPLOYMENT_VERSION}"
ssh $DEPLOYMENT_HOST \
"cd ${DEPLOYMENT_PATH} && \
git pull && \
sed -i "s/VERSION=.*/VERSION=${DEPLOYMENT_VERSION}/" .env && \
docker compose pull && \
docker compose up -d"

33
dockerfile Normal file
View File

@@ -0,0 +1,33 @@
# Stage 1 · go builder
ARG GO_BUILDER=golang
ARG GO_VERSION=latest
FROM ${GO_BUILDER}:${GO_VERSION} AS build
ARG GO_OS
ARG GO_ARCH
ARG GIT_HOST
ARG REPO_ORG
ARG REPO_NAME
ARG APP_VERSION
# Copy the project inside the builder container
WORKDIR $GOPATH/src/${GIT_HOST}/$REPO_ORG/$REPO_NAME/
COPY . .
# Build the binary
RUN CGO_ENABLED=0 GOOS=${GO_OS} GOARCH=${GO_ARCH} \
go build \
-installsuffix cgo \
-ldflags="-w -s -X 'main.APP_VERSION=${APP_VERSION}' -X 'main.COMMIT_ID=$(git log HEAD --oneline | awk '{print $1}' | head -n1)'" \
--o /app
# Stage 2 · scratch image
FROM scratch
# Copy the necessary stuff from the build stage
COPY --from=build /app /app
# Copy the certificates - in case of fetches
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/cert.pem
# Execute the binary
ENTRYPOINT ["/app"]

42
main.go Normal file
View File

@@ -0,0 +1,42 @@
package main
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
var APP_VERSION string = "latest"
var COMMIT_ID string = "undefined"
var ws *WebServer
func main() {
// Create a channel to receive the OS signals
sc := make(chan os.Signal, 1)
signal.Notify(sc, syscall.SIGINT, syscall.SIGTERM)
// Initialize the WebService structure
ws = new(WebServer)
ws.Initialize()
// Start the WebService
go ws.Start()
// Wait for a signal
<-sc
fmt.Println("Shutting down...")
// Create a context with a timeout for graceful shutdown
shCtx, shCancel := context.WithTimeout(context.Background(), 5*time.Second)
defer shCancel()
// Shutdown the HTTP server
err := ws.HTTPServer.Shutdown(shCtx)
if err != nil {
fmt.Printf("Server shutdown error: %s", err)
os.Exit(1)
}
}

54
makefile Normal file
View File

@@ -0,0 +1,54 @@
#!make
include .vars
default: version
clean:
if [ "$$(docker images "$${CONTAINER_ORG}/$${CONTAINER_IMAGE}" --format "{{.Repository}}:{{.Tag}}")" != "" ]; then \
docker image rm $$(docker images "$${CONTAINER_ORG}/$${CONTAINER_IMAGE}" --all --format "{{.Repository}}:{{.Tag}}"); \
fi
docker: clean
docker build \
--build-arg GO_BUILDER=$${GO_BUILDER} \
--build-arg GO_VERSION=$${GO_VERSION} \
--build-arg GO_OS=$${GO_OS} \
--build-arg GO_ARCH=$${GO_ARCH} \
--build-arg GIT_HOST=$${GIT_HOST} \
--build-arg REPO_ORG=$${REPO_ORG} \
--build-arg REPO_NAME=$${REPO_NAME} \
--build-arg APP_VERSION=$${APP_VERSION} \
-t $${CONTAINER_ORG}/$${CONTAINER_IMAGE}:$${APP_VERSION} .; \
if [ "$$(docker images --filter "dangling=true" --quiet --no-trunc)" != "" ]; then \
docker image rm $$(docker images --filter "dangling=true" --quiet --no-trunc); \
fi
dockerpush:
docker push \
$${CONTAINER_ORG}/$${CONTAINER_IMAGE}:$${APP_VERSION}
deploy:
bash -c "./deploy.sh"
version:
bash -c "./version.sh"
run:
docker run \
--rm \
--tty \
--interactive \
--publish $${CONTAINER_IP}:$${CONTAINER_PORT}:80 \
--workdir /go/src/$${GIT_HOST}/$${REPO_ORG}/$${REPO_NAME} \
--volume $(shell pwd):/go/src/$${GIT_HOST}/$${REPO_ORG}/$${REPO_NAME} \
$${GO_BUILDER}:$${GO_VERSION} \
go run .
dockerrun:
docker run \
--rm \
--tty \
--interactive \
--publish $${CONTAINER_IP}:$${CONTAINER_PORT}:80 \
--volume $(shell pwd)/config.yml:/config.yml \
$${CONTAINER_ORG}/$${CONTAINER_IMAGE}:latest

7
routes.go Normal file
View File

@@ -0,0 +1,7 @@
package main
import "github.com/gorilla/mux"
func (s *WebServer) Routes(r *mux.Router) {
r.HandleFunc("/version", handleVersion).Methods("GET")
}

View File

@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<title>{{.Name}}</title>
</head>
<body>
<p>
Version: {{.Version}}<br />
Commit ID: {{.CommitId}}
</p>
</body>
</html>

67
type_webserver.go Normal file
View File

@@ -0,0 +1,67 @@
package main
import (
"fmt"
"net/http"
"os"
"github.com/gorilla/mux"
"gopkg.in/yaml.v2"
)
type WebServer struct {
HTTPServer *http.Server
Listen WSListen `yaml:"listen"`
}
type WSListen struct {
Address string `yaml:"address"`
Port string `yaml:"port"`
}
func (s *WebServer) Initialize() {
// Initialize default values
s.Listen = WSListen{
Address: "0.0.0.0",
Port: "80",
}
// Attempt to read the config file
configFile, err := os.ReadFile("config.yml")
if err != nil {
if os.IsNotExist(err) {
// File does not exist, log and use default config
fmt.Println("Config file not found, using default settings.")
} else {
// Some other error occurred when trying to read the file, exit
fmt.Println("Error reading config file:", err)
os.Exit(1)
}
} else {
// If the file exists, unmarshal it into the ServiceSettings struct
err = yaml.Unmarshal(configFile, &s)
if err != nil {
fmt.Println("Error parsing config file:", err)
os.Exit(1)
}
}
}
func (s *WebServer) Start() error {
// Create a new MUX router and an HTTP server
r := mux.NewRouter()
s.HTTPServer = &http.Server{
Addr: s.Listen.Address + ":" + s.Listen.Port,
Handler: r,
}
// Associate the various handlers (routes)
s.Routes(r)
// Start the server
fmt.Println("Listening on", s.Listen.Address+":"+s.Listen.Port)
err := s.HTTPServer.ListenAndServe()
// Return error, or nil
return err
}

26
version.go Normal file
View File

@@ -0,0 +1,26 @@
package main
import (
_ "embed"
"html/template"
"net/http"
)
//go:embed templates/html/version.html
var versionTemplate string
func handleVersion(w http.ResponseWriter, r *http.Request) {
type SiteInfo struct {
CommitId string
Name string
Version string
}
tmpl, _ := template.New("version.html").Parse(versionTemplate)
// Return (write) the version to the response body
tmpl.Execute(w, SiteInfo{
CommitId: COMMIT_ID,
Name: "YASKM",
Version: APP_VERSION,
})
}

29
version.sh Normal file
View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
# Get version from user
read -p "Version [latest]: " VERSIONINPUT
# If version was not provided, use the latest commit short hash as version
if [ -z ${VERSIONINPUT} ]; then
APP_VERSION="latest"
else
APP_VERSION=${VERSIONINPUT}
fi
# Get docker push option from user
read -p "Docker push? [n]: " DOCKERPUSH
if [ -z ${DOCKERPUSH} ]; then
DOCKERPUSH=n
fi
# Create version tag (if provided)
if [ ! -z ${VERSIONINPUT} ]; then
git tag ${APP_VERSION}
fi
# Build the app
export APP_VERSION
make docker
# If wanted, push the docker image
if [ ${DOCKERPUSH} = "y" ]; then
make dockerpush
fi