Merge pull request 'staging' (#9) from staging into main
All checks were successful
release-tag / release-image (push) Successful in 2m11s
All checks were successful
release-tag / release-image (push) Successful in 2m11s
Reviewed-on: #9
This commit is contained in:
@@ -49,3 +49,16 @@ jobs:
|
|||||||
tags: | # replace it with your local IP and tags
|
tags: | # replace it with your local IP and tags
|
||||||
${{ vars.DOCKER_REGISTRY }}/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
${{ vars.DOCKER_REGISTRY }}/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ steps.meta.outputs.REPO_VERSION }}
|
||||||
${{ vars.DOCKER_REGISTRY }}/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
${{ vars.DOCKER_REGISTRY }}/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:${{ env.DOCKER_LATEST }}
|
||||||
|
- name: Build and push StarCitizen
|
||||||
|
uses: docker/build-push-action@v4
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./Dockerfile
|
||||||
|
build-args: |
|
||||||
|
CONTENT_REPO=https://git.send.nrw/b1tsblog/sccontent.git
|
||||||
|
CONTENT_REF=main
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
push: true
|
||||||
|
tags: | # replace it with your local IP and tags
|
||||||
|
${{ vars.DOCKER_REGISTRY }}/${{ env.DOCKER_ORG }}/${{ steps.meta.outputs.REPO_NAME }}:sc-${{ env.DOCKER_LATEST }}
|
@@ -27,7 +27,7 @@ RUN git clone --depth 1 --branch ${CONTENT_REF} ${CONTENT_REPO} /src
|
|||||||
# • statische Seiten: /pages/* → /out/pages
|
# • statische Seiten: /pages/* → /out/pages
|
||||||
# (Pfad‑Anpassung hier nach DEINEM Repository‑Layout)
|
# (Pfad‑Anpassung hier nach DEINEM Repository‑Layout)
|
||||||
|
|
||||||
RUN mkdir -p /out/content /out/static /out/pages
|
RUN mkdir -p /out/content /out/static /out/pages /out/templates/
|
||||||
RUN find /src/articles -name '*.md' -exec cp {} /out/content/ \;
|
RUN find /src/articles -name '*.md' -exec cp {} /out/content/ \;
|
||||||
RUN cp -r /src/static/* /out/static/
|
RUN cp -r /src/static/* /out/static/
|
||||||
RUN cp -r /src/pages/* /out/pages/
|
RUN cp -r /src/pages/* /out/pages/
|
||||||
@@ -48,7 +48,7 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
|||||||
COPY --from=build /blog /usr/local/bin/blog
|
COPY --from=build /blog /usr/local/bin/blog
|
||||||
|
|
||||||
# ─── Content + Assets ───
|
# ─── Content + Assets ───
|
||||||
RUN mkdir -p /content /static /pages /app
|
RUN mkdir -p /content /static /pages /app /templates /ticks
|
||||||
COPY . /app
|
COPY . /app
|
||||||
COPY --from=content /out/content /content
|
COPY --from=content /out/content /content
|
||||||
COPY --from=content /out/static /static
|
COPY --from=content /out/static /static
|
||||||
@@ -59,6 +59,7 @@ ENV BLOG_CONTENT_DIR=/content
|
|||||||
ENV BLOG_STATIC_DIR=/static
|
ENV BLOG_STATIC_DIR=/static
|
||||||
ENV BLOG_PAGES_DIR=/pages
|
ENV BLOG_PAGES_DIR=/pages
|
||||||
ENV BLOG_TEMPLATES_DIR=/templates
|
ENV BLOG_TEMPLATES_DIR=/templates
|
||||||
|
ENV BLOG_TICKS_DIR=/ticks
|
||||||
|
|
||||||
EXPOSE 8080
|
EXPOSE 8080
|
||||||
CMD ["blog"]
|
CMD ["blog"]
|
||||||
|
@@ -1,5 +1,8 @@
|
|||||||
# b1tsblog
|
# b1tsblog
|
||||||
|
|
||||||
|
## B1tsBlog
|
||||||
|
|
||||||
|
- Anpassung Datenschutzerklärung
|
||||||
- Windows Server 2025 Domänen-Controller legt Netzwerkprofil auf Öffentlich fest
|
- Windows Server 2025 Domänen-Controller legt Netzwerkprofil auf Öffentlich fest
|
||||||
- TLS-Zertifikat mit SHA3 auf Windows Server 2016 einspielen
|
- TLS-Zertifikat mit SHA3 auf Windows Server 2016 einspielen
|
||||||
- Warum personenbezogene Daten nie in die Betreffzeile einer E-Mail gehören
|
- Warum personenbezogene Daten nie in die Betreffzeile einer E-Mail gehören
|
||||||
@@ -15,3 +18,8 @@
|
|||||||
- Ein eigenes Docker-Image erstellen - so geht's
|
- Ein eigenes Docker-Image erstellen - so geht's
|
||||||
- Der eigene DNS-Server im Homelab
|
- Der eigene DNS-Server im Homelab
|
||||||
- Content-Update 2025-05-04
|
- Content-Update 2025-05-04
|
||||||
|
|
||||||
|
## B1ts Star Citizen Blog
|
||||||
|
|
||||||
|
- Anpassung Datenschutzerklärung
|
||||||
|
- Invictus 2955 - Das Jahr der Idris-P?
|
128
cmd/blog/main.go
128
cmd/blog/main.go
@@ -1,17 +1,71 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"html/template"
|
"html/template"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
|
"os/signal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.send.nrw/sendnrw/b1tsblog/internal/article"
|
"git.send.nrw/sendnrw/b1tsblog/internal/article"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var TickCatalog []TickEntry
|
||||||
|
|
||||||
|
func SaveTickCatalog(filename string) error {
|
||||||
|
file, err := os.Create(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
encoder := json.NewEncoder(file)
|
||||||
|
encoder.SetIndent("", " ")
|
||||||
|
return encoder.Encode(TickCatalog)
|
||||||
|
}
|
||||||
|
|
||||||
|
func LoadTickCatalog(filename string) error {
|
||||||
|
file, err := os.Open(filename)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
return json.NewDecoder(file).Decode(&TickCatalog)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IncTick(xSlug string) error {
|
||||||
|
for a, b := range TickCatalog {
|
||||||
|
if b.Slug == xSlug {
|
||||||
|
TickCatalog[a].Count = TickCatalog[a].Count + 1
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
newEntry := TickEntry{Slug: xSlug, Count: 1}
|
||||||
|
TickCatalog = append(TickCatalog, newEntry)
|
||||||
|
return fmt.Errorf("")
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTick(xSlug string) string {
|
||||||
|
for _, b := range TickCatalog {
|
||||||
|
if b.Slug == xSlug {
|
||||||
|
var n int64 = b.Count
|
||||||
|
return strconv.FormatInt(n, 10)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
type TickEntry struct {
|
||||||
|
Slug string `json:"slug"`
|
||||||
|
Count int64 `json:"count"`
|
||||||
|
}
|
||||||
|
|
||||||
func getenv(k, d string) string {
|
func getenv(k, d string) string {
|
||||||
if v := os.Getenv(k); v != "" {
|
if v := os.Getenv(k); v != "" {
|
||||||
return v
|
return v
|
||||||
@@ -41,36 +95,38 @@ var (
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
|
// Signal-Kanal einrichten
|
||||||
|
stop := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
|
||||||
|
|
||||||
|
// Goroutine, die auf Signale wartet
|
||||||
|
go func() {
|
||||||
|
<-stop
|
||||||
|
fmt.Println("Stop Sign...")
|
||||||
|
prepareExit()
|
||||||
|
os.Exit(0)
|
||||||
|
}()
|
||||||
|
|
||||||
// --- Verzeichnisse konfigurierbar machen -------------------------
|
// --- Verzeichnisse konfigurierbar machen -------------------------
|
||||||
contentDir := os.Getenv("BLOG_CONTENT_DIR")
|
contentDir := getenv("BLOG_CONTENT_DIR", "/content")
|
||||||
if contentDir == "" {
|
staticDir := getenv("BLOG_STATIC_DIR", "/app/internal/web/static")
|
||||||
contentDir = "/content" // Fallback für local run
|
pagesDir := getenv("BLOG_PAGES_DIR", "/pages")
|
||||||
|
templatesDir := getenv("BLOG_TEMPLATES_DIR", "/templates")
|
||||||
|
ticksDir := getenv("BLOG_TICKS_DIR", "/ticks")
|
||||||
|
|
||||||
|
TickCatalog = nil
|
||||||
|
if err := LoadTickCatalog(ticksDir + "/ticks.json"); err != nil {
|
||||||
|
fmt.Println("Fehler beim Laden:", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
staticDir := os.Getenv("BLOG_STATIC_DIR")
|
fmt.Println("Geladener Katalog:", TickCatalog)
|
||||||
if staticDir == "" {
|
|
||||||
staticDir = "/app/internal/web/static"
|
|
||||||
}
|
|
||||||
|
|
||||||
pagesDir := os.Getenv("BLOG_PAGES_DIR")
|
|
||||||
if staticDir == "" {
|
|
||||||
staticDir = "/pages"
|
|
||||||
}
|
|
||||||
|
|
||||||
templatesDir := os.Getenv("BLOG_TEMPLATES_DIR")
|
|
||||||
if templatesDir == "" {
|
|
||||||
templatesDir = "/templates"
|
|
||||||
}
|
|
||||||
|
|
||||||
funcs := template.FuncMap{
|
funcs := template.FuncMap{
|
||||||
"now": time.Now, // jetzt‑Zeit bereitstellen
|
"now": time.Now, // jetzt‑Zeit bereitstellen
|
||||||
}
|
}
|
||||||
|
|
||||||
// Basislayout zuerst parsen
|
// Basislayout zuerst parsen
|
||||||
layout := template.Must(
|
layout := template.Must(template.New("base").Funcs(funcs).ParseFiles(templatesDir + "/base.html"))
|
||||||
template.New("base").Funcs(funcs).
|
|
||||||
ParseFiles(templatesDir + "/base.html"),
|
|
||||||
)
|
|
||||||
|
|
||||||
// LIST‑Seite: base + list.html
|
// LIST‑Seite: base + list.html
|
||||||
tplList = template.Must(layout.Clone())
|
tplList = template.Must(layout.Clone())
|
||||||
@@ -103,6 +159,15 @@ func main() {
|
|||||||
http.NotFound(w, r)
|
http.NotFound(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
|
for a, b := range articles {
|
||||||
|
articles[a].Counter = getTick(b.Slug)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* */
|
||||||
|
|
||||||
if err := tplList.ExecuteTemplate(w, "layout", article.ListPage{
|
if err := tplList.ExecuteTemplate(w, "layout", article.ListPage{
|
||||||
Title: "Startseite",
|
Title: "Startseite",
|
||||||
Description: "Alle Artikel im Überblick",
|
Description: "Alle Artikel im Überblick",
|
||||||
@@ -116,6 +181,9 @@ func main() {
|
|||||||
slug := strings.TrimPrefix(r.URL.Path, "/post/")
|
slug := strings.TrimPrefix(r.URL.Path, "/post/")
|
||||||
for _, a := range articles {
|
for _, a := range articles {
|
||||||
if a.Slug == slug {
|
if a.Slug == slug {
|
||||||
|
IncTick(slug)
|
||||||
|
t := getTick(slug)
|
||||||
|
a.Counter = t
|
||||||
if err := tplArticle.ExecuteTemplate(w, "layout", a); err != nil {
|
if err := tplArticle.ExecuteTemplate(w, "layout", a); err != nil {
|
||||||
http.Error(w, err.Error(), 500)
|
http.Error(w, err.Error(), 500)
|
||||||
}
|
}
|
||||||
@@ -142,5 +210,21 @@ func main() {
|
|||||||
cacheControl(http.StripPrefix("/static/",
|
cacheControl(http.StripPrefix("/static/",
|
||||||
http.FileServer(http.Dir(staticDir)))))
|
http.FileServer(http.Dir(staticDir)))))
|
||||||
|
|
||||||
http.ListenAndServe(":8080", mux)
|
StopServer(http.ListenAndServe(":8080", mux))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareExit() {
|
||||||
|
fmt.Println("~", "Running exit tasks...")
|
||||||
|
if err := SaveTickCatalog(getenv("BLOG_TICKS_DIR", "/ticks") + "/ticks.json"); err != nil {
|
||||||
|
fmt.Println("Fehler beim Speichern:", err)
|
||||||
|
}
|
||||||
|
fmt.Println("Geladener Katalog:", TickCatalog)
|
||||||
|
fmt.Println("~", "Exit completed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func StopServer(e error) {
|
||||||
|
fmt.Println("~", "Stopping server...")
|
||||||
|
prepareExit()
|
||||||
|
fmt.Println("~", "Server stopped!")
|
||||||
}
|
}
|
||||||
|
@@ -13,6 +13,7 @@ type Article struct {
|
|||||||
Cover string
|
Cover string
|
||||||
Body template.HTML
|
Body template.HTML
|
||||||
Description string
|
Description string
|
||||||
|
Counter string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ListPage struct {
|
type ListPage struct {
|
||||||
|
@@ -10,7 +10,7 @@
|
|||||||
{{ end }}
|
{{ end }}
|
||||||
<div class="card-content">
|
<div class="card-content">
|
||||||
<h2>{{ .Title }}</h2>
|
<h2>{{ .Title }}</h2>
|
||||||
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "02.01.2006" }}</time>
|
<time datetime="{{ .Date.Format "2006-01-02" }}">{{ .Date.Format "02.01.2006" }}</time> ({{ .Counter }})
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
Reference in New Issue
Block a user