From 528ed5bd74efd40a2ff520ddcbba16427fd4793f Mon Sep 17 00:00:00 2001 From: clawbot Date: Tue, 17 Mar 2026 01:58:41 -0700 Subject: [PATCH] rework: multi-stage Dockerfile lint/build/runtime pattern Rewrites CI to use a multi-stage Dockerfile per REPO_POLICIES: - Lint stage: golangci/golangci-lint:v2.1.6-alpine runs make fmt-check and make lint - Build stage: golang:1.24.4-alpine runs make test, then builds binary with CGO enabled (required for mattn/go-sqlite3) - Runtime stage: alpine:3.21 copies binary, runs as non-root user All base images pinned by @sha256 hash. CI workflow simplified to just 'docker build .' since the Dockerfile already runs make check (fmt-check + lint + test). Makefile aligned with REPO_POLICIES: - check target uses prereqs (fmt-check lint test) - fmt-check is read-only (gofmt -l, not go fmt) - Added docker and hooks targets - test uses -race -timeout 30s Added .dockerignore for efficient build context. --- .dockerignore | 8 +++++ .gitea/workflows/check.yml | 16 +++------- Dockerfile | 61 ++++++++++++++++++++++++++++++++++++++ Makefile | 45 +++++++++++----------------- 4 files changed, 91 insertions(+), 39 deletions(-) create mode 100644 .dockerignore create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..0b09869 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,8 @@ +.git +.gitea +*.md +LICENSE +vaultik +coverage.out +coverage.html +.DS_Store diff --git a/.gitea/workflows/check.yml b/.gitea/workflows/check.yml index b8292f8..fb6ef70 100644 --- a/.gitea/workflows/check.yml +++ b/.gitea/workflows/check.yml @@ -8,15 +8,7 @@ jobs: check: runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5 - with: - go-version-file: go.mod - - name: Install system dependencies - run: | - sudo apt-get update -qq - sudo apt-get install -y -qq sqlite3 - - name: Install golangci-lint - run: curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/5d1e709b7be35cb2025444e19de266b056b7b7ee/install.sh | sh -s -- -b "$(go env GOPATH)/bin" v2.10.1 - - name: Run checks - run: make check + # actions/checkout v4, 2024-09-16 + - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 + - name: Build and check + run: docker build . diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..c9e1f7a --- /dev/null +++ b/Dockerfile @@ -0,0 +1,61 @@ +# Lint stage +# golangci/golangci-lint:v2.1.6-alpine, 2025-04-22 +FROM golangci/golangci-lint:v2.1.6-alpine@sha256:b122e5b85ddc99f62cb750039b5137247dda2327cbb96cac617bc0987be4f575 AS lint + +RUN apk add --no-cache make build-base + +WORKDIR /src + +# Copy go mod files first for better layer caching +COPY go.mod go.sum ./ +RUN go mod download + +# Copy source code +COPY . . + +# Run formatting check and linter +RUN make fmt-check +RUN make lint + +# Build stage +# golang:1.24.4-alpine, 2026-03-17 +FROM golang:1.24.4-alpine@sha256:68932fa6d4d4059845c8f40ad7e654e626f3ebd3706eef7846f319293ab5cb7a AS builder + +# Depend on lint stage passing +COPY --from=lint /src/go.sum /dev/null + +ARG VERSION=dev + +# Install build dependencies for CGO (mattn/go-sqlite3) and sqlite3 CLI (tests) +RUN apk add --no-cache make build-base sqlite + +WORKDIR /src + +# Copy go mod files first for better layer caching +COPY go.mod go.sum ./ +RUN go mod download + +# Copy source code +COPY . . + +# Run tests +RUN make test + +# Build with CGO enabled (required for mattn/go-sqlite3) +RUN CGO_ENABLED=1 go build -ldflags "-X 'git.eeqj.de/sneak/vaultik/internal/globals.Version=${VERSION}' -X 'git.eeqj.de/sneak/vaultik/internal/globals.Commit=$(git rev-parse HEAD 2>/dev/null || echo unknown)'" -o /vaultik ./cmd/vaultik + +# Runtime stage +# alpine:3.21, 2026-02-25 +FROM alpine:3.21@sha256:c3f8e73fdb79deaebaa2037150150191b9dcbfba68b4a46d70103204c53f4709 + +RUN apk add --no-cache ca-certificates sqlite + +# Copy binary from builder +COPY --from=builder /vaultik /usr/local/bin/vaultik + +# Create non-root user +RUN adduser -D -H -s /sbin/nologin vaultik + +USER vaultik + +ENTRYPOINT ["/usr/local/bin/vaultik"] diff --git a/Makefile b/Makefile index 2315f89..5fdec05 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: test fmt lint build clean all +.PHONY: test fmt lint fmt-check check build clean all docker hooks # Version number VERSION := 0.0.1 @@ -14,21 +14,12 @@ LDFLAGS := -X 'git.eeqj.de/sneak/vaultik/internal/globals.Version=$(VERSION)' \ all: vaultik # Run tests -test: lint fmt-check - @echo "Running tests..." - @if ! go test -v -timeout 10s ./... 2>&1; then \ - echo ""; \ - echo "TEST FAILURES DETECTED"; \ - echo "Run 'go test -v ./internal/database' to see database test details"; \ - exit 1; \ - fi +test: + go test -race -timeout 30s ./... -# Check if code is formatted +# Check if code is formatted (read-only) fmt-check: - @if [ -n "$$(go fmt ./...)" ]; then \ - echo "Error: Code is not formatted. Run 'make fmt' to fix."; \ - exit 1; \ - fi + @test -z "$$(gofmt -l .)" || (echo "Files not formatted:" && gofmt -l . && exit 1) # Format code fmt: @@ -36,7 +27,7 @@ fmt: # Run linter lint: - golangci-lint run + golangci-lint run ./... # Build binary vaultik: internal/*/*.go cmd/vaultik/*.go @@ -47,11 +38,6 @@ clean: rm -f vaultik go clean -# Install dependencies -deps: - go mod download - go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest - # Run tests with coverage test-coverage: go test -v -coverprofile=coverage.out ./... @@ -69,10 +55,15 @@ install: vaultik cp ./vaultik $(HOME)/bin/ # Run all checks (formatting, linting, tests) without modifying files -check: - @echo "==> Checking formatting..." - @test -z "$$(gofmt -l .)" || (echo "Files not formatted:" && gofmt -l . && exit 1) - @echo "==> Running linter..." - golangci-lint run ./... - @echo "==> Running tests..." - go test -race -timeout 30s ./... +check: fmt-check lint test + +# Build Docker image +docker: + docker build -t vaultik . + +# Install pre-commit hook +hooks: + @printf '#!/bin/sh\nset -e\n' > .git/hooks/pre-commit + @printf 'go mod tidy\ngo fmt ./...\ngit diff --exit-code -- go.mod go.sum || { echo "go mod tidy changed files; please stage and retry"; exit 1; }\n' >> .git/hooks/pre-commit + @printf 'make check\n' >> .git/hooks/pre-commit + @chmod +x .git/hooks/pre-commit