feat: add reader vote widget and vote-service
The skills-review desk is static, so "which draft would you ship?" needs a stateful counterpart. vote-service is a small Go API on its own pod backed by a JSON file on a ReadWriteOnce PVC, with one active vote per skill per source IP as the anti-abuse rule and CORS (ALLOWED_ORIGIN) as the caller boundary. Deployment notes that differ from the obvious path, all confirmed against the live cluster: the image is side-loaded with `ctr image import` plus `imagePullPolicy: Never` because kubelet has no credentials for the Nexus ref; the pod is pinned to `kubernets` because the hostpath PV takes a nodeAffinity for whichever node first binds it; and public exposure is Caddy on the VPS, not the cloudflared tunnel. The ingress controller runs with `use-forwarded-headers` off, so nginx overwrites X-Forwarded-For with its own peer — every visitor would collapse into one voter and each skill would cap at one vote overall. Caddy stamps the true remote address into X-Client-IP, which nginx forwards untouched, and clientIP() reads that first. Scoped to this app rather than flipping the global flag, which would change client-IP handling for every other ingress. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,16 @@
|
||||
FROM golang:1.22-alpine AS build
|
||||
WORKDIR /src
|
||||
COPY go.mod ./
|
||||
COPY main.go ./
|
||||
RUN CGO_ENABLED=0 go build -trimpath -ldflags="-s -w" -o /out/vote-service . \
|
||||
&& mkdir -p /out/data
|
||||
|
||||
FROM gcr.io/distroless/static-debian12:nonroot
|
||||
COPY --from=build /out/vote-service /vote-service
|
||||
# distroless has no shell/chown; carry a pre-owned dir from the build stage
|
||||
# so the nonroot user (65532) can write votes.json even without a mounted
|
||||
# PVC (e.g. local `docker run` smoke tests).
|
||||
COPY --from=build --chown=nonroot:nonroot /out/data /data
|
||||
VOLUME ["/data"]
|
||||
EXPOSE 8080
|
||||
ENTRYPOINT ["/vote-service"]
|
||||
Reference in New Issue
Block a user