From 315027ab0d73fa00729576f188d17e10f204de80 Mon Sep 17 00:00:00 2001 From: Ivan Godwin Date: Sat, 18 Jul 2026 09:16:12 -0700 Subject: [PATCH] ci: add Gitea Actions pipeline, golangci-lint config, vuln target - .gitea/workflows/ci.yml: lint, race tests (e2e excluded), and govulncheck on push to main and PRs; shared composite action installs protoc + pinned protoc-gen-go/protoc-gen-go-grpc and generates the (gitignored) protobuf code before each Go job. - .golangci.yml (v2 schema): govet, staticcheck, errcheck, ineffassign, unused, misspell, gosec, revive; generated api/grpc/pb excluded. - Makefile: vuln target (govulncheck) added and chained into qa. Co-Authored-By: Claude Fable 5 --- .gitea/actions/generate-proto/action.yml | 37 ++++++++ .gitea/workflows/ci.yml | 113 +++++++++++++++++++++++ .golangci.yml | 46 +++++++++ Makefile | 11 ++- 4 files changed, 205 insertions(+), 2 deletions(-) create mode 100644 .gitea/actions/generate-proto/action.yml create mode 100644 .gitea/workflows/ci.yml create mode 100644 .golangci.yml diff --git a/.gitea/actions/generate-proto/action.yml b/.gitea/actions/generate-proto/action.yml new file mode 100644 index 0000000..3b69111 --- /dev/null +++ b/.gitea/actions/generate-proto/action.yml @@ -0,0 +1,37 @@ +name: Generate protobuf code +description: > + Installs protoc and the pinned protoc-gen-go / protoc-gen-go-grpc plugins, + then runs `make proto-gen`. api/grpc/pb/ is gitignored (see .gitignore) and + regenerated at build time (mirrors what the Dockerfile does for image + builds), so any job that compiles Go code needs this step first or + `github.com/igodwin/notifier/api/grpc/pb` won't resolve. +# +# Local composite action, referenced from ci.yml via: +# uses: ./.gitea/actions/generate-proto +# Gitea Actions supports local composite actions the same way GitHub Actions +# does. Must run after a Go toolchain is on PATH (i.e. after actions/setup-go). + +runs: + using: composite + steps: + - name: Install protoc + shell: bash + run: | + sudo apt-get update + sudo apt-get install -y --no-install-recommends protobuf-compiler + protoc --version + + # Pinned exactly to the versions this module already depends on + # (google.golang.org/protobuf in go.mod, and the matching + # protoc-gen-go-grpc release) - deliberately not @latest, so CI can't + # drift out from under the checked-in go.mod without review. + - name: Install protoc-gen-go / protoc-gen-go-grpc (pinned) + shell: bash + run: | + go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.36.10 + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.5.1 + echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" + + - name: Generate protobuf code (make proto-gen) + shell: bash + run: make proto-gen diff --git a/.gitea/workflows/ci.yml b/.gitea/workflows/ci.yml new file mode 100644 index 0000000..37ebf1a --- /dev/null +++ b/.gitea/workflows/ci.yml @@ -0,0 +1,113 @@ +name: CI + +# Gitea Actions reads workflows from .gitea/workflows/ and executes them with +# a GitHub-Actions-compatible engine (act_runner). Standard actions/* steps +# work as long as the runner can resolve github.com (either directly or via a +# configured actions mirror on the Gitea instance) - see notes at the bottom +# of this file for offline/mirrored setups. + +on: + push: + branches: + - main + pull_request: + +# Cancel superseded runs for the same ref to save runner capacity. +# Gitea Actions accepts both the `gitea.*` and `github.*` context aliases; +# `github.*` is used here since it's the more portable spelling. +concurrency: + group: ci-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + lint: + name: Lint + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + # api/grpc/pb/ is gitignored and generated at build time (see + # .gitignore and the Dockerfile), so anything that compiles this + # module - including the linter, which type-checks packages - needs + # the generated code in place first. + - name: Generate protobuf code + uses: ./.gitea/actions/generate-proto + + # Installing the pinned binary via the official install script is more + # portable across Gitea Actions runner images than golangci-lint-action, + # which assumes a GitHub-hosted runner environment (it works, but the + # install script approach has fewer surprises on self-hosted runners + # and lets us pin an exact version without depending on the action's + # own release cadence). + - name: Install golangci-lint + run: | + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | \ + sh -s -- -b "$(go env GOPATH)/bin" v2.12.2 + echo "$(go env GOPATH)/bin" >> "$GITHUB_PATH" + + - name: Run golangci-lint + run: golangci-lint run ./... + + test: + name: Test + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + # api/grpc/pb/ is gitignored and generated at build time; without this + # the module won't compile (pkg/client, internal/service, etc. import + # the generated package). + - name: Generate protobuf code + uses: ./.gitea/actions/generate-proto + + # tests/e2e uses testcontainers-go and requires a Docker daemon that + # isn't guaranteed to be available/usable on Gitea Actions runners, so + # it is excluded from CI here via `go list ... | grep -v`. Run it + # locally (or on a runner with Docker-in-Docker configured) with: + # go test -race ./tests/e2e/... + - name: Run tests (excluding e2e) + run: | + go test -race -covermode=atomic -coverprofile=coverage.out \ + $(go list ./... | grep -v '/tests/e2e') + # coverage.out is left in the workspace for inspection; artifact + # upload is intentionally omitted since actions/upload-artifact + # support varies by Gitea version/configuration - add it back once + # your instance's artifact storage is confirmed working. + + vuln: + name: Vulnerability scan + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + cache: true + + # govulncheck also loads and type-checks the module's packages, so the + # generated protobuf code has to exist first. + - name: Generate protobuf code + uses: ./.gitea/actions/generate-proto + + - name: Install govulncheck + run: go install golang.org/x/vuln/cmd/govulncheck@latest + + - name: Run govulncheck + run: govulncheck ./... diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 0000000..8ac6fca --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,46 @@ +# golangci-lint configuration. +# +# Schema: golangci-lint v2 (this machine had no golangci-lint installed at +# authoring time, so this targets the latest stable v2 config schema - +# https://golangci-lint.run/usage/configuration/ - as of v2.12.x). If your +# CI/local installs a v1 binary, upgrade it rather than downgrading this file; +# v1 binaries do not understand `version: "2"` configs. +version: "2" + +run: + timeout: 5m + +linters: + # Start from nothing and opt in explicitly, rather than `standard`/`all`, + # so the enabled set below is the complete, intentional list. + default: none + + enable: + - govet # suspicious constructs (vet) + - staticcheck # bugs, deprecated APIs, simplifications (includes old `gosimple`/`stylecheck` checks) + - errcheck # unchecked error return values + - ineffassign # assignments that are never used + - unused # unused constants, variables, functions, types + - misspell # common English misspellings in comments/strings + - gosec # security-focused static analysis + - revive # style/lint rules (golint replacement) + + settings: + gosec: + # G104 (unchecked errors) is already covered by errcheck above and is + # noisy/redundant when both linters are enabled together. + excludes: + - G104 + + exclusions: + # Generated protobuf code should never be linted or hand-edited. This is + # a plain path match against whatever is on disk at lint time, so it + # excludes api/grpc/pb/ whether or not the directory happens to exist - + # it's gitignored and regenerated by `make proto-gen` before CI lints + # (see .gitea/actions/generate-proto), not committed to the repo. + paths: + - api/grpc/pb/ + + # Keep the generated-code detector on too, in case other generated files + # show up elsewhere in the tree in the future. + generated: strict diff --git a/Makefile b/Makefile index 403e67c..90447a5 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -.PHONY: proto proto-gen proto-clean deps build build-dev run run-grpc run-rest test lint fmt vet check docker-build docker-build-dev docker-buildx-setup docker-run clean help +.PHONY: proto proto-gen proto-clean deps build build-dev run run-grpc run-rest test lint vuln fmt vet check docker-build docker-build-dev docker-buildx-setup docker-run clean help # Variables REGISTRY ?= @@ -137,8 +137,15 @@ lint: golangci-lint run ./... @echo "Linting passed" +# Run vulnerability scan (requires govulncheck) +vuln: + @echo "Running vulnerability scan..." + @which govulncheck > /dev/null || (echo "govulncheck not installed. Run: go install golang.org/x/vuln/cmd/govulncheck@latest" && exit 1) + govulncheck ./... + @echo "Vulnerability scan passed" + # Run all quality checks -qa: fmt vet lint test +qa: fmt vet lint vuln test @echo "All quality checks passed!" # Build Docker image (production - optimized)