penguin/flatgit

flatgit showcase

commit 4e46c3b4f88381d28f3bcdb436e373841c29b1df

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-06-18T21:13:12Z
subjectGithub workflow
commit 4e46c3b4f88381d28f3bcdb436e373841c29b1df
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-06-18T21:13:12Z

    Github workflow
---
 .github/workflows/ci.yml                          | 116 ++++++++++++++++++++--
 dockerfiles/github.Dockerfile                     |  54 ++++++++++
 dockerfiles/runtime.Dockerfile                    |   4 +
 internal/buildinfo/buildinfo_gen.go               |   4 +-
 resources/flatgit.chart/Chart.yaml                |   6 ++
 resources/flatgit.chart/templates/_helpers.tpl    |  18 ++++
 resources/flatgit.chart/templates/configmap.yaml  |  26 +++++
 resources/flatgit.chart/templates/deployment.yaml |  85 ++++++++++++++++
 resources/flatgit.chart/templates/pvc.yaml        |  17 ++++
 resources/flatgit.chart/templates/secret.yaml     |   9 ++
 resources/flatgit.chart/templates/service.yaml    |  15 +++
 resources/flatgit.chart/values.yaml               |  56 +++++++++++
 12 files changed, 400 insertions(+), 10 deletions(-)

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 4e78e38..d1519cd 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -1,17 +1,117 @@
-name: build
+name: flatgit CI
 
 on:
+  workflow_dispatch:
   push:
+    branches: ["main"]
+    tags: ["v*"]
   pull_request:
+    branches: ["main"]
+
+permissions:
+  contents: read
 
 jobs:
-  test:
+  build:
+    name: Go build and test
     runs-on: ubuntu-latest
+
     steps:
-      - uses: actions/checkout@v4
-      - uses: actions/setup-go@v5
+      - &checkout
+        uses: actions/checkout@v4
+
+      - name: Set up Go
+        uses: actions/setup-go@v5
+        with:
+          go-version: "1.26.x"
+          cache: true
+
+      - name: Test
+        run: go test ./...
+
+      - name: Vet
+        run: go vet ./...
+
+      - name: Build
+        run: go build -trimpath -o ./bin/flatgit ./cmd/flatgit
+
+      - name: Smoke test
+        run: ./bin/flatgit version
+
+  docker:
+    name: Docker image
+    runs-on: ubuntu-latest
+
+    needs:
+      - build
+
+    if: startsWith(github.ref, 'refs/tags/v')
+
+    permissions:
+      contents: read
+      packages: write
+
+    steps:
+      - *checkout
+
+      - &set_build_version
+        name: Set build version
+        id: set_build_version
+        shell: bash
+        run: |
+          set -eu
+
+          if [ "${GITHUB_REF_TYPE:-}" = "tag" ]; then
+            BUILD_VER="${GITHUB_REF_NAME}"
+          else
+            BUILD_VER="dev-${GITHUB_SHA::12}"
+          fi
+
+          echo "BUILD_VER=${BUILD_VER}" >> "$GITHUB_ENV"
+          echo "build_ver=${BUILD_VER}" >> "$GITHUB_OUTPUT"
+          echo "Build version: ${BUILD_VER}"
+
+      - &set_image_name
+        name: Set image name
+        shell: bash
+        run: |
+          set -eu
+
+          image="ghcr.io/${GITHUB_REPOSITORY}"
+          image="${image,,}"
+
+          echo "IMAGE_NAME=${image}" >> "$GITHUB_ENV"
+          echo "Image name: ${image}"
+
+      - &setup_buildx
+        name: Set up Docker Buildx
+        uses: docker/setup-buildx-action@v4
+
+      - &login_ghcr
+        name: Login to GHCR
+        uses: docker/login-action@v4
+        with:
+          registry: ghcr.io
+          username: ${{ github.actor }}
+          password: ${{ github.token }}
+
+      - name: Docker metadata
+        id: meta
+        uses: docker/metadata-action@v6
+        with:
+          images: ${{ env.IMAGE_NAME }}
+          tags: |
+            type=raw,value=${{ env.BUILD_VER }}-debian-slim
+            type=raw,value=latest-debian-slim,enable=${{ startsWith(github.ref, 'refs/tags/v') }}
+
+      - name: Build and push image
+        uses: docker/build-push-action@v7
         with:
-          go-version: '1.26.x'
-      - run: go test ./...
-      - run: go vet ./...
-      - run: go build ./cmd/flatgit
+          context: .
+          file: ./dockerfiles/github.Dockerfile
+          platforms: linux/amd64,linux/arm64
+          push: true
+          build-args: |
+            BUILD_VER=${{ env.BUILD_VER }}
+          tags: ${{ steps.meta.outputs.tags }}
+          labels: ${{ steps.meta.outputs.labels }}
diff --git a/dockerfiles/github.Dockerfile b/dockerfiles/github.Dockerfile
new file mode 100644
index 0000000..10995a7
--- /dev/null
+++ b/dockerfiles/github.Dockerfile
@@ -0,0 +1,54 @@
+# syntax=docker/dockerfile:1.7
+
+FROM golang:1.26-trixie AS build
+
+ARG TARGETOS
+ARG TARGETARCH
+ARG BUILD_VER=dev
+
+WORKDIR /src
+
+COPY go.mod go.sum ./
+
+RUN --mount=type=cache,target=/go/pkg/mod \
+    go mod download
+
+COPY internal ./internal
+COPY cmd ./cmd
+
+RUN --mount=type=cache,target=/go/pkg/mod \
+    --mount=type=cache,target=/root/.cache/go-build \
+    mkdir -p /out/bin && \
+    CGO_ENABLED=0 \
+    GOOS=${TARGETOS:-linux} \
+    GOARCH=${TARGETARCH:-amd64} \
+    go build \
+      -trimpath \
+      -ldflags="-s -w -X main.version=${BUILD_VER}" \
+      -o /out/bin/flatgit \
+      ./cmd/flatgit
+
+FROM debian:trixie-slim AS runtime
+
+RUN apt-get update && \
+    apt-get install -y --no-install-recommends \
+      ca-certificates \
+      git \
+      tzdata && \
+    rm -rf /var/lib/apt/lists/*
+
+RUN groupadd -r -g 10001 flatgit && \
+    useradd -r -u 10001 -g 10001 -d /var/lib/flatgit -s /usr/sbin/nologin flatgit && \
+    mkdir -p /var/lib/flatgit /tmp && \
+    chown -R 10001:10001 /var/lib/flatgit && \
+    chmod 1777 /tmp
+
+COPY --from=build /out/bin/flatgit /usr/local/bin/flatgit
+
+USER 10001:10001
+
+VOLUME ["/var/lib/flatgit"]
+
+EXPOSE 8080
+
+ENTRYPOINT ["/usr/local/bin/flatgit"]
diff --git a/dockerfiles/runtime.Dockerfile b/dockerfiles/runtime.Dockerfile
index 0364b34..ce8fcda 100644
--- a/dockerfiles/runtime.Dockerfile
+++ b/dockerfiles/runtime.Dockerfile
@@ -33,6 +33,10 @@ RUN if [ -n "${APT_PROXY}" ]; then \
       echo "Acquire::http::Proxy \"http://${APT_PROXY}\";" > /etc/apt/apt.conf.d/01proxy; \
     fi
 
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends git ca-certificates \
+ && rm -rf /var/lib/apt/lists/*
+
 COPY --from=build /src/bin/flatgit /usr/local/bin/flatgit
 COPY --from=build /out/tmp /tmp
 
diff --git a/internal/buildinfo/buildinfo_gen.go b/internal/buildinfo/buildinfo_gen.go
index f11f874..c50b854 100644
--- a/internal/buildinfo/buildinfo_gen.go
+++ b/internal/buildinfo/buildinfo_gen.go
@@ -2,6 +2,6 @@ package buildinfo
 
 const (
     Version     = "dev"
-    GitRevision = "b5be7ec12ae5b4b0075f0f9bea40aca17fa904ff"
-    Timestamp   = "20260618.203511"
+    GitRevision = "34c40f8839cd8ead6a3e4900d67abf0feea76ea7"
+    Timestamp   = "20260618.204600"
 )
diff --git a/resources/flatgit.chart/Chart.yaml b/resources/flatgit.chart/Chart.yaml
new file mode 100644
index 0000000..1020989
--- /dev/null
+++ b/resources/flatgit.chart/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v2
+name: flatgit
+description: Static Git web generator with webhook updates
+type: application
+version: 0.1.0
+appVersion: "dev"
diff --git a/resources/flatgit.chart/templates/_helpers.tpl b/resources/flatgit.chart/templates/_helpers.tpl
new file mode 100644
index 0000000..4b6f973
--- /dev/null
+++ b/resources/flatgit.chart/templates/_helpers.tpl
@@ -0,0 +1,18 @@
+{{- define "flatgit.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{- define "flatgit.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- include "flatgit.name" . -}}
+{{- end -}}
+{{- end -}}
+
+{{- define "flatgit.labels" -}}
+app.kubernetes.io/name: {{ include "flatgit.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
\ No newline at end of file
diff --git a/resources/flatgit.chart/templates/configmap.yaml b/resources/flatgit.chart/templates/configmap.yaml
new file mode 100644
index 0000000..4b8e16c
--- /dev/null
+++ b/resources/flatgit.chart/templates/configmap.yaml
@@ -0,0 +1,26 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "flatgit.fullname" . }}-config
+  labels:
+    {{- include "flatgit.labels" . | nindent 4 }}
+data:
+  config.json: |
+    {
+      "addr": {{ .Values.flatgit.addr | quote }},
+      "data_dir": {{ .Values.flatgit.dataDir | quote }},
+      "public_url": {{ .Values.flatgit.publicUrl | quote }},
+      "webhook": {
+        "secret_env": "FLATGIT_WEBHOOK_SECRET"
+      },
+      "git": {
+        "command": {{ .Values.flatgit.git.command | quote }},
+        "clone_timeout": {{ .Values.flatgit.git.cloneTimeout | quote }},
+        "fetch_timeout": {{ .Values.flatgit.git.fetchTimeout | quote }}
+      },
+      "render": {
+        "workers": {{ .Values.flatgit.render.workers }},
+        "max_commits": {{ .Values.flatgit.render.maxCommits }}
+      },
+      "repos": {{ .Values.flatgit.repos | toJson }}
+    }
\ No newline at end of file
diff --git a/resources/flatgit.chart/templates/deployment.yaml b/resources/flatgit.chart/templates/deployment.yaml
new file mode 100644
index 0000000..c5b3db4
--- /dev/null
+++ b/resources/flatgit.chart/templates/deployment.yaml
@@ -0,0 +1,85 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "flatgit.fullname" . }}
+  labels:
+    {{- include "flatgit.labels" . | nindent 4 }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  strategy:
+    type: Recreate
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: {{ include "flatgit.name" . }}
+      app.kubernetes.io/instance: {{ .Release.Name }}
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: {{ include "flatgit.name" . }}
+        app.kubernetes.io/instance: {{ .Release.Name }}
+    spec:
+      securityContext:
+        runAsNonRoot: {{ .Values.securityContext.runAsNonRoot }}
+        runAsUser: {{ .Values.securityContext.runAsUser }}
+        runAsGroup: {{ .Values.securityContext.runAsGroup }}
+        fsGroup: {{ .Values.securityContext.fsGroup }}
+        fsGroupChangePolicy: {{ .Values.securityContext.fsGroupChangePolicy | quote }}
+
+      containers:
+        - name: flatgit
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+
+          args:
+            - daemon
+            - -c
+            - /etc/flatgit/config.json
+
+          env:
+            - name: TZ
+              value: {{ .Values.timezone | quote }}
+            - name: FLATGIT_WEBHOOK_SECRET
+              valueFrom:
+                secretKeyRef:
+                  name: {{ include "flatgit.fullname" . }}-webhook
+                  key: secret
+
+          ports:
+            - name: http
+              containerPort: 8080
+
+          volumeMounts:
+            - name: config
+              mountPath: /etc/flatgit
+              readOnly: true
+            - name: data
+              mountPath: {{ .Values.flatgit.dataDir }}
+
+          readinessProbe:
+            httpGet:
+              path: /healthz
+              port: http
+            initialDelaySeconds: 3
+            periodSeconds: 10
+
+          livenessProbe:
+            httpGet:
+              path: /healthz
+              port: http
+            initialDelaySeconds: 10
+            periodSeconds: 30
+
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+
+      volumes:
+        - name: config
+          configMap:
+            name: {{ include "flatgit.fullname" . }}-config
+        - name: data
+          {{- if .Values.persistence.enabled }}
+          persistentVolumeClaim:
+            claimName: {{ include "flatgit.fullname" . }}-data
+          {{- else }}
+          emptyDir: {}
+          {{- end }}
\ No newline at end of file
diff --git a/resources/flatgit.chart/templates/pvc.yaml b/resources/flatgit.chart/templates/pvc.yaml
new file mode 100644
index 0000000..cd1ebc9
--- /dev/null
+++ b/resources/flatgit.chart/templates/pvc.yaml
@@ -0,0 +1,17 @@
+{{- if .Values.persistence.enabled }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: {{ include "flatgit.fullname" . }}-data
+  labels:
+    {{- include "flatgit.labels" . | nindent 4 }}
+spec:
+  accessModes:
+    - ReadWriteOnce
+  {{- if .Values.persistence.storageClassName }}
+  storageClassName: {{ .Values.persistence.storageClassName | quote }}
+  {{- end }}
+  resources:
+    requests:
+      storage: {{ .Values.persistence.size | quote }}
+{{- end }}
\ No newline at end of file
diff --git a/resources/flatgit.chart/templates/secret.yaml b/resources/flatgit.chart/templates/secret.yaml
new file mode 100644
index 0000000..10bd0a5
--- /dev/null
+++ b/resources/flatgit.chart/templates/secret.yaml
@@ -0,0 +1,9 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ include "flatgit.fullname" . }}-webhook
+  labels:
+    {{- include "flatgit.labels" . | nindent 4 }}
+type: Opaque
+stringData:
+  secret: {{ .Values.webhook.secret | quote }}
\ No newline at end of file
diff --git a/resources/flatgit.chart/templates/service.yaml b/resources/flatgit.chart/templates/service.yaml
new file mode 100644
index 0000000..c3d3cec
--- /dev/null
+++ b/resources/flatgit.chart/templates/service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "flatgit.fullname" . }}
+  labels:
+    {{- include "flatgit.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.service.type }}
+  selector:
+    app.kubernetes.io/name: {{ include "flatgit.name" . }}
+    app.kubernetes.io/instance: {{ .Release.Name }}
+  ports:
+    - name: http
+      port: {{ .Values.service.port }}
+      targetPort: http
\ No newline at end of file
diff --git a/resources/flatgit.chart/values.yaml b/resources/flatgit.chart/values.yaml
new file mode 100644
index 0000000..2c02fa3
--- /dev/null
+++ b/resources/flatgit.chart/values.yaml
@@ -0,0 +1,56 @@
+replicaCount: 1
+
+image:
+  repository: ghcr.io/tgckpg/flatgit
+  tag: dev
+  pullPolicy: Always
+
+timezone: Asia/Tokyo
+
+service:
+  type: ClusterIP
+  port: 8080
+
+persistence:
+  enabled: true
+  size: 5Gi
+  storageClassName: ""
+
+webhook:
+  secret: change-me
+
+flatgit:
+  addr: ":8080"
+  dataDir: /var/lib/flatgit
+  publicUrl: "http://127.0.0.1:8080"
+
+  git:
+    command: git
+    cloneTimeout: 120s
+    fetchTimeout: 120s
+
+  render:
+    workers: 1
+    maxCommits: 500
+
+  repos:
+    - name: penguin/tinyproxy
+      owner: penguin
+      description: flatgit stub repo
+      url: https://github.com/tgckpg/flatgit.git
+      defaultBranch: main
+
+resources:
+  requests:
+    cpu: 50m
+    memory: 128Mi
+  limits:
+    cpu: "1"
+    memory: 512Mi
+
+securityContext:
+  runAsNonRoot: true
+  runAsUser: 10001
+  runAsGroup: 10001
+  fsGroup: 10001
+  fsGroupChangePolicy: OnRootMismatch