diff --git a/Dockerfile b/Dockerfile index 065aa59..3aab3bd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -41,7 +41,7 @@ FROM debian:bookworm-slim # (optional) MySQL‑Client für später RUN apt-get update && apt-get install -y --no-install-recommends \ - ca-certificates \ + ca-certificates git \ && rm -rf /var/lib/apt/lists/* # ─── Binärdatei ───── @@ -60,6 +60,11 @@ ENV BLOG_STATIC_DIR=/static ENV BLOG_PAGES_DIR=/pages ENV BLOG_TEMPLATES_DIR=/templates ENV BLOG_TICKS_DIR=/ticks +ENV GIT_ENABLE=false +ENV GIT_REPO=null +ENV GIT_BRANCH=main +ENV GIT_DIR=/git-temp +ENV GIT_INTERVAL=10 EXPOSE 8080 CMD ["blog"] diff --git a/Dockerfile_Slim b/Dockerfile_Slim new file mode 100644 index 0000000..787acf4 --- /dev/null +++ b/Dockerfile_Slim @@ -0,0 +1,41 @@ +############################ +# 1) Go‑Build +############################ +FROM golang:1.23.1 AS build + +WORKDIR /app +COPY go.mod go.sum ./ +RUN go mod download +COPY . . +RUN CGO_ENABLED=0 go build -o /blog ./cmd/blog + +############################ +# 3) Runtime‑Image +############################ +FROM debian:bookworm-slim + +# (optional) MySQL‑Client für später +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates git \ + && rm -rf /var/lib/apt/lists/* + +# ─── Binärdatei ───── +COPY --from=build /blog /usr/local/bin/blog + +# ─── Content + Assets ─── +RUN mkdir -p /content /static /pages /app /templates /ticks /git-temp +COPY . /app + +ENV BLOG_CONTENT_DIR=/content +ENV BLOG_STATIC_DIR=/static +ENV BLOG_PAGES_DIR=/pages +ENV BLOG_TEMPLATES_DIR=/templates +ENV BLOG_TICKS_DIR=/ticks +ENV GIT_ENABLE=false +ENV GIT_REPO=null +ENV GIT_BRANCH=main +ENV GIT_DIR=/git-temp +ENV GIT_INTERVAL=10 + +EXPOSE 8080 +CMD ["blog"] diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 756496c..7492df5 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -4,9 +4,12 @@ import ( "encoding/json" "fmt" "html/template" + "io" "net/http" "os" + "os/exec" "os/signal" + "path/filepath" "strconv" "strings" "syscall" @@ -93,6 +96,8 @@ var ( tplArticle *template.Template ) +var Xarticles []article.Article + func main() { // Signal-Kanal einrichten @@ -113,6 +118,11 @@ func main() { pagesDir := getenv("BLOG_PAGES_DIR", "/pages") templatesDir := getenv("BLOG_TEMPLATES_DIR", "/templates") ticksDir := getenv("BLOG_TICKS_DIR", "/ticks") + gitEnable := enabled("GIT_ENABLE", false) + gitRepo := getenv("GIT_REPO", "null") + gitBranch := getenv("GIT_BRANCH", "main") + gitDir := getenv("GIT_DIR", "/git-temp") + gitInterval := getenv("GIT_INTERVAL", "10") TickCatalog = nil if err := LoadTickCatalog(ticksDir + "/ticks.json"); err != nil { @@ -146,6 +156,8 @@ func main() { fmt.Println(err) } + Xarticles = articles + staticPages, err := article.LoadStatic(pagesDir) if err != nil { fmt.Println(err) @@ -206,9 +218,13 @@ func main() { } }) - mux.Handle("/static/", - cacheControl(http.StripPrefix("/static/", - http.FileServer(http.Dir(staticDir))))) + mux.Handle("/static/", cacheControl(http.StripPrefix("/static/", http.FileServer(http.Dir(staticDir))))) + + if gitEnable { + xMinute, _ := strconv.Atoi(gitInterval) + xDuration := time.Duration(xMinute) * time.Minute + startAutoClone(gitRepo, gitBranch, gitDir, xDuration) + } StopServer(http.ListenAndServe(":8080", mux)) @@ -228,3 +244,162 @@ func StopServer(e error) { prepareExit() fmt.Println("~", "Server stopped!") } + +func cloneRepo(repoURL, branch, dir string) { + fmt.Printf("Starte Klonvorgang für Branch '%s'...\n", branch) + + // Verzeichnis löschen + if err := os.RemoveAll(dir); err != nil { + fmt.Println("Fehler beim Löschen des Verzeichnisses:", err) + return + } + + // Git-Clone mit Branch + cmd := exec.Command("git", "clone", "--branch", branch, "--single-branch", repoURL, dir) + cmd.Stdout = os.Stdout + cmd.Stderr = os.Stderr + + if err := cmd.Run(); err != nil { + fmt.Println("Fehler beim Klonen:", err) + } else { + fmt.Println("Repo erfolgreich geklont.") + } + + contentDir := getenv("BLOG_CONTENT_DIR", "/content") + + articles, err := article.LoadDir(contentDir) + if err != nil { + fmt.Println(err) + } + + err = os.Remove("/content") + if err != nil { + fmt.Println(err, "/content") + } + + err = os.Remove("/static") + if err != nil { + fmt.Println(err, "/static") + } + + err = os.Remove("/pages") + if err != nil { + fmt.Println(err, "/pages") + } + + err = os.Remove("/templates") + if err != nil { + fmt.Println(err, "/templates") + } + + if err := os.MkdirAll("/content", 0755); err != nil { + fmt.Println("Fehler beim Erstellen des Zielordners:", err) + return + } + + if err := os.MkdirAll("/static", 0755); err != nil { + fmt.Println("Fehler beim Erstellen des Zielordners:", err) + return + } + + if err := os.MkdirAll("/pages", 0755); err != nil { + fmt.Println("Fehler beim Erstellen des Zielordners:", err) + return + } + + if err := os.MkdirAll("/templates", 0755); err != nil { + fmt.Println("Fehler beim Erstellen des Zielordners:", err) + return + } + + if err := copyDirContents("/git-temp/content", "/content"); err != nil { + fmt.Println("Fehler beim Kopieren:", err) + } else { + fmt.Println("Kopieren abgeschlossen.") + } + + if err := copyDirContents("/git-temp/static", "/static"); err != nil { + fmt.Println("Fehler beim Kopieren:", err) + } else { + fmt.Println("Kopieren abgeschlossen.") + } + + if err := copyDirContents("/git-temp/pages", "/pages"); err != nil { + fmt.Println("Fehler beim Kopieren:", err) + } else { + fmt.Println("Kopieren abgeschlossen.") + } + + if err := copyDirContents("/git-temp/templates", "/templates"); err != nil { + fmt.Println("Fehler beim Kopieren:", err) + } else { + fmt.Println("Kopieren abgeschlossen.") + } + + Xarticles = articles + +} + +func copyDirContents(srcDir, destDir string) error { + entries, err := os.ReadDir(srcDir) + if err != nil { + return fmt.Errorf("Fehler beim Lesen von %s: %w", srcDir, err) + } + + for _, entry := range entries { + srcPath := filepath.Join(srcDir, entry.Name()) + destPath := filepath.Join(destDir, entry.Name()) + + info, err := entry.Info() + if err != nil { + return err + } + + if info.IsDir() { + if err := os.MkdirAll(destPath, info.Mode()); err != nil { + return fmt.Errorf("Fehler beim Erstellen von Ordner %s: %w", destPath, err) + } + // rekursiv kopieren + if err := copyDirContents(srcPath, destPath); err != nil { + return err + } + } else { + if err := copyFile(srcPath, destPath, info); err != nil { + return err + } + } + } + + return nil +} + +func copyFile(src, dest string, info os.FileInfo) error { + in, err := os.Open(src) + if err != nil { + return err + } + defer in.Close() + + out, err := os.Create(dest) + if err != nil { + return err + } + defer out.Close() + + if _, err := io.Copy(out, in); err != nil { + return err + } + + return os.Chmod(dest, info.Mode()) +} + +func startAutoClone(repoURL, branch, dir string, interval time.Duration) { + go cloneRepo(repoURL, branch, dir) // sofortiger Start + + ticker := time.NewTicker(interval) + defer ticker.Stop() + + for range ticker.C { + go cloneRepo(repoURL, branch, dir) + } +}