diff --git a/.gitignore b/.gitignore index b0ac3ed..74ed256 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,40 @@ .aider* + +# Go build artifacts +/inventory +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool +*.out + +# Dependency directories +vendor/ + +# SQLite database files +*.sqlite +*.db + +# Node.js dependencies +node_modules/ +web/node_modules/ +web/dist/ + +# IDE files +.idea/ +.vscode/ +*.swp +*.swo + +# OS specific files +.DS_Store +Thumbs.db + +# Build artifacts +/artifacts/ diff --git a/.woodpecker.yml b/.woodpecker.yml new file mode 100644 index 0000000..3a02eba --- /dev/null +++ b/.woodpecker.yml @@ -0,0 +1,58 @@ +pipeline: + backend-lint: + image: golang:1.21 + group: lint + commands: + - go vet ./... + - go fmt ./... + + frontend-lint: + image: node:20 + group: lint + commands: + - cd web + - npm ci + - npm run lint + + frontend-build: + image: node:20 + commands: + - cd web + - npm ci + - npm run build + when: + status: [success] + + backend-build: + image: golang:1.21 + commands: + - go mod download + - go generate ./... + # Build with embedded frontend + - go build -o inventory -ldflags="-s -w" . + when: + status: [success] + + # Create artifacts + artifacts: + image: alpine:latest + commands: + - mkdir -p artifacts + - cp inventory artifacts/ + - tar -czvf artifacts/inventory.tar.gz inventory + when: + status: [success] + + # Optional step for creating a Docker image + docker-build: + image: plugins/docker + settings: + repo: ${DRONE_REPO_OWNER}/inventory + tags: + - latest + - ${DRONE_TAG##v} + dockerfile: Dockerfile + when: + branch: main + event: [push, tag] + status: [success] diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..f34214b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,32 @@ +FROM golang:1.21-alpine as builder + +WORKDIR /app +COPY . . + +# Install build dependencies +RUN apk add --no-cache git build-base + +# Build the frontend +RUN apk add --no-cache nodejs npm +RUN cd web && npm ci && npm run build + +# Build the backend with embedded frontend +RUN go mod download +RUN go generate ./... +RUN go build -o inventory -ldflags="-s -w" . + +# Create minimal runtime image +FROM alpine:latest +RUN apk --no-cache add ca-certificates tzdata + +WORKDIR /app +COPY --from=builder /app/inventory . +COPY --from=builder /app/config.yaml ./config.yaml + +# Create a non-root user to run the application +RUN adduser -D -H -h /app appuser +RUN chown -R appuser:appuser /app +USER appuser + +EXPOSE 8088 +CMD ["./inventory"] diff --git a/main.go b/main.go index fcfdfb8..739d767 100644 --- a/main.go +++ b/main.go @@ -26,7 +26,7 @@ import ( db "git.entr0py.de/garionion/inventory/database/sqlite/generated" ) -//go:embed static/* +//go:embed static/* web/dist var staticFiles embed.FS //go:embed database/sqlite/migration/*.sql @@ -239,7 +239,37 @@ func main() { apiHandler.RegisterRoutes(e, oauthMiddleware) // Serve static files - must be after API routes - e.GET("/*", echo.WrapHandler(http.FileServer(http.FS(staticFiles)))) + // First try to serve from web/dist (for the Vue app) + e.GET("/*", func(c echo.Context) error { + path := c.Request().URL.Path + + // Try to serve from web/dist first + content, err := staticFiles.ReadFile("web/dist" + path) + if err == nil { + // Determine content type + contentType := http.DetectContentType(content) + if strings.HasSuffix(path, ".css") { + contentType = "text/css" + } else if strings.HasSuffix(path, ".js") { + contentType = "application/javascript" + } else if strings.HasSuffix(path, ".html") { + contentType = "text/html" + } + + return c.Blob(http.StatusOK, contentType, content) + } + + // If the path is a directory or doesn't exist, try index.html for SPA routing + if path == "/" || err != nil { + indexContent, err := staticFiles.ReadFile("web/dist/index.html") + if err == nil { + return c.HTMLBlob(http.StatusOK, indexContent) + } + } + + // Fall back to the static directory + return echo.WrapHandler(http.FileServer(http.FS(staticFiles)))(c) + }) // Start server addr := fmt.Sprintf(":%d", cfg.Server.Port) diff --git a/web/index.html b/web/index.html index 8abc79c..4766591 100644 --- a/web/index.html +++ b/web/index.html @@ -4,7 +4,8 @@ - Welcome to Vuetify 3 + Inventory Management System +