From c8e866c36998ac4cc1cac2fb2cea555aac12f795 Mon Sep 17 00:00:00 2001 From: Icereed Date: Mon, 13 Jan 2025 08:02:55 +0100 Subject: [PATCH] feat: add versioning information to Docker build and application startup (#113) * feat: add versioning information to Docker build and application startup Bonus: Pin Alpine package versions. --- .github/workflows/docker-build-and-push.yml | 4 ++ Dockerfile | 46 +++++++++++++++++---- go.mod | 4 +- go.sum | 8 ++++ main.go | 28 +++++++++++++ renovate.json | 13 +++++- version.go | 7 ++++ 7 files changed, 100 insertions(+), 10 deletions(-) create mode 100644 version.go diff --git a/.github/workflows/docker-build-and-push.yml b/.github/workflows/docker-build-and-push.yml index 361f876..09e65d6 100644 --- a/.github/workflows/docker-build-and-push.yml +++ b/.github/workflows/docker-build-and-push.yml @@ -96,3 +96,7 @@ jobs: cache-from: type=gha cache-to: type=gha,mode=max tags: ${{ env.TAGS }} + build-args: | + VERSION=${{ github.ref_type == 'tag' && github.ref_name || github.sha }} + COMMIT=${{ github.sha }} + BUILD_DATE=${{ github.event.repository.pushed_at }} diff --git a/Dockerfile b/Dockerfile index 92e32c9..42b5697 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,17 +1,33 @@ +# Define top-level build arguments +ARG VERSION=docker-dev +ARG COMMIT=unknown +ARG BUILD_DATE=unknown + # Stage 1: Build the Go binary -FROM golang:1.22-alpine AS builder +FROM golang:1.23.4-alpine3.21 AS builder # Set the working directory inside the container WORKDIR /app -# Install necessary packages -RUN apk add --no-cache \ - git \ - gcc \ - musl-dev \ - mupdf \ - mupdf-dev +# Package versions for Renovate +# renovate: datasource=repology depName=alpine_3_21/gcc versioning=loose +ENV GCC_VERSION=14.2.0-r4 +# renovate: datasource=repology depName=alpine_3_21/musl-dev versioning=loose +ENV MUSL_DEV_VERSION=1.2.5-r8 +# renovate: datasource=repology depName=alpine_3_21/mupdf versioning=loose +ENV MUPDF_VERSION=1.24.10-r0 +# renovate: datasource=repology depName=alpine_3_21/mupdf-dev versioning=loose +ENV MUPDF_DEV_VERSION=1.24.10-r0 +# renovate: datasource=repology depName=alpine_3_21/sed versioning=loose +ENV SED_VERSION=4.9-r2 +# Install necessary packages with pinned versions +RUN apk add --no-cache \ + "gcc=${GCC_VERSION}" \ + "musl-dev=${MUSL_DEV_VERSION}" \ + "mupdf=${MUPDF_VERSION}" \ + "mupdf-dev=${MUPDF_DEV_VERSION}" \ + "sed=${SED_VERSION}" # Copy go.mod and go.sum files COPY go.mod go.sum ./ @@ -24,6 +40,18 @@ RUN CGO_ENABLED=1 go build -tags musl -o /dev/null github.com/mattn/go-sqlite3 # Now copy the actual source files COPY *.go . +# Import ARGs from top level +ARG VERSION +ARG COMMIT +ARG BUILD_DATE + +# Update version information +RUN sed -i \ + -e "s/devVersion/${VERSION}/" \ + -e "s/devBuildDate/${BUILD_DATE}/" \ + -e "s/devCommit/${COMMIT}/" \ + version.go + # Build the binary using caching for both go modules and build cache RUN CGO_ENABLED=1 GOMAXPROCS=$(nproc) go build -tags musl -o paperless-gpt . @@ -51,6 +79,8 @@ RUN npm run build # Stage 3: Create a lightweight image with the Go binary and frontend FROM alpine:latest +ENV GIN_MODE=release + # Install necessary runtime dependencies RUN apk add --no-cache \ ca-certificates diff --git a/go.mod b/go.mod index 2857ef0..2762c7d 100644 --- a/go.mod +++ b/go.mod @@ -28,6 +28,7 @@ require ( github.com/davecgh/go-spew v1.1.1 // indirect github.com/dlclark/regexp2 v1.10.0 // indirect github.com/ebitengine/purego v0.8.0 // indirect + github.com/fatih/color v1.18.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -42,6 +43,7 @@ require ( github.com/jupiterrider/ffi v0.2.0 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-sqlite3 v1.14.24 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect @@ -58,7 +60,7 @@ require ( golang.org/x/arch v0.8.0 // indirect golang.org/x/crypto v0.26.0 // indirect golang.org/x/net v0.25.0 // indirect - golang.org/x/sys v0.23.0 // indirect + golang.org/x/sys v0.25.0 // indirect golang.org/x/text v0.20.0 // indirect google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 945e689..6af29a1 100644 --- a/go.sum +++ b/go.sum @@ -25,6 +25,8 @@ github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/ebitengine/purego v0.8.0 h1:JbqvnEzRvPpxhCJzJJ2y0RbiZ8nyjccVUrSM3q+GvvE= github.com/ebitengine/purego v0.8.0/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= +github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= +github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/gen2brain/go-fitz v1.24.14 h1:09weRkjVtLYNGo7l0J7DyOwBExbwi8SJ9h8YPhw9WEo= @@ -70,6 +72,9 @@ github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZY github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M= github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= +github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= +github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM= @@ -155,6 +160,7 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -162,6 +168,8 @@ golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.23.0 h1:YfKFowiIMvtgl1UERQoTPPToxltDeZfbj4H7dVUCwmM= golang.org/x/sys v0.23.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34= +golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= diff --git a/main.go b/main.go index 783fa7e..178791b 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "net/http" "os" "path/filepath" + "runtime" "strconv" "strings" "sync" @@ -13,6 +14,7 @@ import ( "time" "github.com/Masterminds/sprig/v3" + "github.com/fatih/color" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" "github.com/tmc/langchaingo/llms" @@ -94,6 +96,9 @@ func main() { // Initialize logrus logger initLogger() + // Print version + printVersion() + // Initialize PaperlessClient client := NewPaperlessClient(paperlessBaseURL, paperlessAPIToken) @@ -236,6 +241,29 @@ func main() { } } +func printVersion() { + cyan := color.New(color.FgCyan).SprintFunc() + yellow := color.New(color.FgYellow).SprintFunc() + + banner := ` + ╔═══════════════════════════════════════╗ + ║ Paperless GPT ║ + ╚═══════════════════════════════════════╝` + + fmt.Printf("%s\n", cyan(banner)) + fmt.Printf("\n%s %s\n", yellow("Version:"), version) + if commit != "" { + fmt.Printf("%s %s\n", yellow("Commit:"), commit) + } + if buildDate != "" { + fmt.Printf("%s %s\n", yellow("Build Date:"), buildDate) + } + fmt.Printf("%s %s/%s\n", yellow("Platform:"), runtime.GOOS, runtime.GOARCH) + fmt.Printf("%s %s\n", yellow("Go Version:"), runtime.Version()) + fmt.Printf("%s %s\n", yellow("Started:"), time.Now().Format(time.RFC1123)) + fmt.Println() +} + func initLogger() { switch logLevel { case "debug": diff --git a/renovate.json b/renovate.json index 5db72dd..36162ef 100644 --- a/renovate.json +++ b/renovate.json @@ -2,5 +2,16 @@ "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": [ "config:recommended" + ], + "regexManagers": [ + { + "description": "Update VERSION variables in Dockerfiles", + "fileMatch": ["^Dockerfile$"], + "matchStrings": [ + "# renovate: datasource=(?[a-z-]+?) depName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s(?:ENV|ARG) .+?_VERSION=\"(?.+?)\"\\s", + "# renovate: datasource=(?[a-z-]+?) depName=(?.+?)(?: versioning=(?[a-z-]+?))?\\s(?:ENV|ARG) VERSION=\"(?.+?)\"\\s" + ], + "versioningTemplate": "{{#if versioning}}{{versioning}}{{else}}semver{{/if}}" + } ] -} +} \ No newline at end of file diff --git a/version.go b/version.go new file mode 100644 index 0000000..750920c --- /dev/null +++ b/version.go @@ -0,0 +1,7 @@ +package main + +var ( + version = "devVersion" + buildDate = "devBuildDate" + commit = "devCommit" +)