From ca22dd8596e8b3baf3d9cf69cc32c3df565ffbc4 Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 16:16:52 +0200 Subject: [PATCH 1/6] =?UTF-8?q?Test=20f=C3=BCr=20Git=20AutoClone?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Dockerfile | 7 +- Dockerfile_Slim | 41 +++++++++++ cmd/blog/main.go | 181 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 225 insertions(+), 4 deletions(-) create mode 100644 Dockerfile_Slim 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) + } +} From 87493fe40c4267c1f341b7c340af0dde52c3aa2b Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 16:22:48 +0200 Subject: [PATCH 2/6] removeall fix --- cmd/blog/main.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 7492df5..83550bb 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -272,22 +272,22 @@ func cloneRepo(repoURL, branch, dir string) { fmt.Println(err) } - err = os.Remove("/content") + err = os.RemoveAll("/content") if err != nil { fmt.Println(err, "/content") } - err = os.Remove("/static") + err = os.RemoveAll("/static") if err != nil { fmt.Println(err, "/static") } - err = os.Remove("/pages") + err = os.RemoveAll("/pages") if err != nil { fmt.Println(err, "/pages") } - err = os.Remove("/templates") + err = os.RemoveAll("/templates") if err != nil { fmt.Println(err, "/templates") } From 445db0ec10604038e0318de846e04cc6859dee5e Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 16:29:16 +0200 Subject: [PATCH 3/6] fix --- cmd/blog/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 83550bb..6047d55 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -312,7 +312,7 @@ func cloneRepo(repoURL, branch, dir string) { return } - if err := copyDirContents("/git-temp/content", "/content"); err != nil { + if err := copyDirContents("/git-temp/articles", "/content"); err != nil { fmt.Println("Fehler beim Kopieren:", err) } else { fmt.Println("Kopieren abgeschlossen.") From 7493ca278ecc43bc63b98473f564924b209e40e0 Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 16:39:14 +0200 Subject: [PATCH 4/6] fix --- cmd/blog/main.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 6047d55..89ecbd7 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -223,7 +223,7 @@ func main() { if gitEnable { xMinute, _ := strconv.Atoi(gitInterval) xDuration := time.Duration(xMinute) * time.Minute - startAutoClone(gitRepo, gitBranch, gitDir, xDuration) + go startAutoClone(gitRepo, gitBranch, gitDir, xDuration) } StopServer(http.ListenAndServe(":8080", mux)) From dce90ca88ba82c3150e1c92e308736e4a6167a7f Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 16:56:08 +0200 Subject: [PATCH 5/6] bugfix --- cmd/blog/main.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 89ecbd7..8723bd9 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -174,8 +174,8 @@ func main() { /* */ - for a, b := range articles { - articles[a].Counter = getTick(b.Slug) + for a, b := range Xarticles { + Xarticles[a].Counter = getTick(b.Slug) } /* */ @@ -183,7 +183,7 @@ func main() { if err := tplList.ExecuteTemplate(w, "layout", article.ListPage{ Title: "Startseite", Description: "Alle Artikel im Überblick", - Articles: articles, + Articles: Xarticles, }); err != nil { http.Error(w, err.Error(), 500) } @@ -191,7 +191,7 @@ func main() { mux.HandleFunc("/post/", func(w http.ResponseWriter, r *http.Request) { slug := strings.TrimPrefix(r.URL.Path, "/post/") - for _, a := range articles { + for _, a := range Xarticles { if a.Slug == slug { IncTick(slug) t := getTick(slug) From 7ef6b551ac2b368af163f12f72ff9fb41b433098 Mon Sep 17 00:00:00 2001 From: jbergner Date: Sun, 11 May 2025 17:10:56 +0200 Subject: [PATCH 6/6] Bugfix Einlesen der Artikel vor Erstellen der Ressourcen --- cmd/blog/main.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/cmd/blog/main.go b/cmd/blog/main.go index 8723bd9..2093ee6 100644 --- a/cmd/blog/main.go +++ b/cmd/blog/main.go @@ -267,12 +267,7 @@ func cloneRepo(repoURL, branch, dir string) { contentDir := getenv("BLOG_CONTENT_DIR", "/content") - articles, err := article.LoadDir(contentDir) - if err != nil { - fmt.Println(err) - } - - err = os.RemoveAll("/content") + err := os.RemoveAll("/content") if err != nil { fmt.Println(err, "/content") } @@ -336,6 +331,11 @@ func cloneRepo(repoURL, branch, dir string) { fmt.Println("Kopieren abgeschlossen.") } + articles, err := article.LoadDir(contentDir) + if err != nil { + fmt.Println(err) + } + Xarticles = articles }