Skip to content

Commit dcbb99e

Browse files
committed
chore: standardize eco-wide infra (versioning, CI, hooks, templates)
- VERSION file as single source of truth - CODEOWNERS for auto-review routing - Canonical Makefile with standard targets - release-please config + workflow - lefthook/pre-commit hooks (conventional commits, fmt, lint, secrets) - Canonical CI + release GitHub Actions workflows - Standardized .editorconfig, .gitattributes, CODE_OF_CONDUCT, SECURITY, CONTRIBUTING - goreleaser config (where applicable) Part of hawk-eco standardization sweep.
1 parent 6496439 commit dcbb99e

14 files changed

Lines changed: 785 additions & 358 deletions

.editorconfig

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,67 @@
1+
# EditorConfig — https://editorconfig.org
2+
# Canonical eco-wide template (.shared-templates/editorconfig.tmpl).
3+
14
root = true
25

6+
# Default for everything.
37
[*]
48
charset = utf-8
59
end_of_line = lf
610
insert_final_newline = true
711
trim_trailing_whitespace = true
812
indent_style = space
9-
indent_size = 2
13+
indent_size = 4
1014

11-
# Go uses tabs.
15+
# Go uses tabs by convention.
1216
[*.go]
1317
indent_style = tab
1418
indent_size = 4
1519

16-
# Makefile-likes use tabs by language convention.
17-
[{Makefile,*.mk,**.mk}]
18-
indent_style = tab
20+
# Python — PEP 8.
21+
[*.py]
1922
indent_size = 4
2023

21-
# Shell scripts: 2 spaces matches POSIX convention used in scripts/ and mise-tasks/.
22-
[*.{sh,bash,zsh}]
23-
indent_style = space
24+
# TypeScript / JavaScript — 2 spaces, ecosystem default.
25+
[*.{ts,tsx,js,jsx,mjs,cjs}]
2426
indent_size = 2
2527

26-
# YAML / JSON / TOML: 2 spaces.
27-
[*.{yml,yaml,json,toml}]
28-
indent_style = space
28+
# Web assets.
29+
[*.{html,css,scss}]
30+
indent_size = 2
31+
32+
# YAML — 2 spaces (ecosystem standard, GitHub Actions, k8s, etc.).
33+
[*.{yml,yaml}]
34+
indent_size = 2
35+
36+
# JSON / JSONC.
37+
[*.{json,jsonc}]
38+
indent_size = 2
39+
40+
# TOML.
41+
[*.toml]
2942
indent_size = 2
3043

31-
# Markdown: trailing whitespace is sometimes significant (line break with two spaces).
44+
# Markdown — 2 spaces, preserve trailing whitespace (used for line breaks).
3245
[*.md]
3346
trim_trailing_whitespace = false
47+
indent_size = 2
48+
49+
# Shell scripts.
50+
[*.{sh,bash,zsh,fish}]
51+
indent_size = 4
52+
53+
# Makefiles must use tabs.
54+
[{Makefile,*.mk}]
55+
indent_style = tab
56+
57+
# Dockerfiles.
58+
[Dockerfile*]
59+
indent_size = 4
60+
61+
# GitHub Actions workflows — 2 spaces.
62+
[.github/**/*.{yml,yaml}]
63+
indent_size = 2
64+
65+
# Config files.
66+
[*.{cfg,ini,conf}]
67+
indent_size = 4

.gitattributes

Lines changed: 73 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,86 @@
1-
# Default: normalize line endings to LF on commit, leave the working copy alone.
1+
# Canonical eco-wide .gitattributes template (.shared-templates/gitattributes.tmpl).
2+
# Auto-detect text files and normalise line endings to LF.
3+
24
* text=auto eol=lf
35

4-
# Explicitly LF for source, scripts, and config — never CRLF.
5-
*.go text eol=lf
6-
*.md text eol=lf
7-
*.yml text eol=lf
8-
*.yaml text eol=lf
9-
*.json text eol=lf
10-
*.toml text eol=lf
6+
# --- Source code -----------------------------------------------------------
7+
*.go text eol=lf diff=golang
8+
*.py text eol=lf diff=python
9+
*.ts text eol=lf
10+
*.tsx text eol=lf
11+
*.js text eol=lf
12+
*.jsx text eol=lf
13+
*.mjs text eol=lf
14+
*.cjs text eol=lf
15+
*.rs text eol=lf diff=rust
16+
17+
# --- Shell + config --------------------------------------------------------
1118
*.sh text eol=lf
12-
Makefile text eol=lf
19+
*.bash text eol=lf
20+
*.toml text eol=lf
21+
*.yaml text eol=lf
22+
*.yml text eol=lf
23+
*.json text eol=lf linguist-language=JSON
24+
*.jsonc text eol=lf linguist-language=JSON
25+
*.cff text eol=lf
26+
27+
# --- Documentation ---------------------------------------------------------
28+
*.md text eol=lf diff=markdown
29+
*.txt text eol=lf
30+
31+
# --- Build / packaging ----------------------------------------------------
32+
Makefile text eol=lf
33+
*.mk text eol=lf
34+
Dockerfile* text eol=lf
35+
docker-compose*.yml text eol=lf
36+
.github/**/*.yml text eol=lf
37+
.github/**/*.yaml text eol=lf
38+
39+
# --- Generated artefacts (mark as such for diffs and language stats) ------
40+
go.mod text eol=lf linguist-generated
41+
go.sum text eol=lf linguist-generated
42+
*.pb.go linguist-generated
43+
*_generated.go linguist-generated
44+
package-lock.json linguist-generated
45+
pnpm-lock.yaml linguist-generated
46+
yarn.lock linguist-generated
1347

14-
# Windows-only files keep CRLF (matches WINDOWS.md guidance).
15-
*.bat text eol=crlf
16-
*.cmd text eol=crlf
17-
*.ps1 text eol=crlf
48+
# --- Vendored / external sources ------------------------------------------
49+
vendor/** linguist-vendored
50+
node_modules/** linguist-vendored
51+
testdata/** linguist-vendored
52+
benchmarks/data/** linguist-vendored
1853

19-
# Binary files — never diffed, never EOL-normalized.
54+
# --- Binary files (do not text-normalise) ---------------------------------
55+
*.exe binary
56+
*.dll binary
57+
*.so binary
58+
*.dylib binary
59+
*.a binary
60+
*.o binary
61+
*.db binary
62+
*.sqlite binary
2063
*.png binary
2164
*.jpg binary
2265
*.jpeg binary
2366
*.gif binary
2467
*.ico binary
68+
*.svg text eol=lf
69+
*.pdf binary
2570
*.zip binary
26-
*.tar binary
2771
*.tar.gz binary
28-
*.gz binary
29-
*.pdf binary
30-
31-
# Generated files — collapse in PR diffs (GitHub linguist hint).
32-
go.sum linguist-generated=true
33-
.opencode/package-lock.json linguist-generated=true
34-
.opencode/bun.lock linguist-generated=true
72+
*.tgz binary
73+
*.whl binary
3574

36-
# Documentation — exclude from language stats.
37-
docs/** linguist-documentation=true
38-
AGENTS.md linguist-documentation=true
39-
CLAUDE.md linguist-documentation=true
40-
WINDOWS.md linguist-documentation=true
75+
# --- Source archive hygiene (excluded from `git archive`) -----------------
76+
.github export-ignore
77+
.shared-templates export-ignore
78+
.gitattributes export-ignore
79+
.gitignore export-ignore
80+
.editorconfig export-ignore
81+
.golangci.yml export-ignore
82+
.goreleaser.yml export-ignore
83+
.goreleaser.yaml export-ignore
84+
testdata/ export-ignore
85+
benchmarks/ export-ignore
86+
e2e/ export-ignore

.github/workflows/ci.yml

Lines changed: 124 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,161 @@
1+
# Canonical CI workflow for hawk-eco Go repos.
2+
# Source of truth: .shared-templates/workflows/go-ci.yml.tmpl
3+
#
4+
# Two deployment models:
5+
#
6+
# 1. NOW — render this template inline into each repo's
7+
# .github/workflows/ci.yml. Every repo has identical content.
8+
#
9+
# 2. LATER — once GrayCodeAI/.github exists as a central repo, move this
10+
# file to GrayCodeAI/.github/.github/workflows/go-ci.yml with
11+
# `on: workflow_call:`. Each repo's ci.yml becomes a 5-line caller:
12+
#
13+
# name: CI
14+
# on: { push: { branches: [main] }, pull_request: }
15+
# jobs:
16+
# ci:
17+
# uses: GrayCodeAI/.github/.github/workflows/go-ci.yml@main
18+
119
name: CI
20+
221
on:
322
push:
423
branches: [main, dev]
524
pull_request:
625
branches: [main, dev]
726

27+
permissions:
28+
contents: read
29+
30+
concurrency:
31+
group: ci-${{ github.workflow }}-${{ github.ref }}
32+
cancel-in-progress: true
33+
34+
env:
35+
GO_VERSION: "1.26.1"
36+
837
jobs:
9-
build:
38+
# -------------------------------------------------------------------------
39+
# Format + vet — fastest, fail fast.
40+
# -------------------------------------------------------------------------
41+
fmt-vet:
42+
name: fmt + vet
1043
runs-on: ubuntu-latest
1144
steps:
1245
- uses: actions/checkout@v4
1346
- uses: actions/setup-go@v5
1447
with:
15-
go-version: '1.26.2'
16-
- run: go build ./...
48+
go-version: ${{ env.GO_VERSION }}
49+
cache: true
50+
- name: gofumpt diff
51+
run: |
52+
go install mvdan.cc/gofumpt@latest
53+
out=$(gofumpt -l .)
54+
if [ -n "$out" ]; then
55+
echo "::error::gofumpt would reformat the following files:"
56+
echo "$out"
57+
exit 1
58+
fi
59+
- name: go vet
60+
run: go vet ./...
1761

62+
# -------------------------------------------------------------------------
63+
# Lint — golangci-lint covers most static checks.
64+
# -------------------------------------------------------------------------
1865
lint:
66+
name: lint
1967
runs-on: ubuntu-latest
2068
steps:
2169
- uses: actions/checkout@v4
2270
- uses: actions/setup-go@v5
2371
with:
24-
go-version: '1.26.2'
72+
go-version: ${{ env.GO_VERSION }}
73+
cache: true
2574
- uses: golangci/golangci-lint-action@v7
2675
with:
27-
version: v2.11.3
76+
version: v2.1.0
77+
install-mode: goinstall
78+
verify: false
79+
args: --timeout=5m
2880

81+
# -------------------------------------------------------------------------
82+
# Tests with race detector + coverage upload.
83+
# -------------------------------------------------------------------------
2984
test:
85+
name: test (race + cover)
3086
runs-on: ubuntu-latest
31-
continue-on-error: true
3287
steps:
3388
- uses: actions/checkout@v4
3489
- uses: actions/setup-go@v5
3590
with:
36-
go-version: '1.26.2'
37-
- name: Setup Keyring
91+
go-version: ${{ env.GO_VERSION }}
92+
cache: true
93+
- name: Tidy check
3894
run: |
39-
sudo apt-get update && sudo apt-get install -y gnome-keyring
40-
echo 'testpass' | gnome-keyring-daemon --unlock
41-
- run: go test -race -count=1 -timeout=120s ./...
42-
- name: Coverage
43-
run: |
44-
go test -coverprofile=coverage.out ./... 2>/dev/null || true
45-
go tool cover -func=coverage.out | tail -1 || true
95+
go mod tidy
96+
if ! git diff --quiet; then
97+
echo "::error::go.mod / go.sum out of date — run 'go mod tidy' and commit"
98+
git diff
99+
exit 1
100+
fi
101+
- name: Test
102+
run: go test ./... -race -count=1 -coverprofile=coverage.out -covermode=atomic -timeout=180s
103+
- name: Coverage summary
104+
run: go tool cover -func=coverage.out | tail -1
105+
- name: Upload coverage
106+
uses: actions/upload-artifact@v4
107+
with:
108+
name: coverage
109+
path: coverage.out
46110

111+
# -------------------------------------------------------------------------
112+
# Security scan — vulnerability database + (optional) gosec.
113+
# -------------------------------------------------------------------------
47114
security:
115+
name: security
116+
runs-on: ubuntu-latest
117+
steps:
118+
- uses: actions/checkout@v4
119+
- uses: actions/setup-go@v5
120+
with:
121+
go-version: ${{ env.GO_VERSION }}
122+
cache: true
123+
- name: govulncheck
124+
run: |
125+
go install golang.org/x/vuln/cmd/govulncheck@latest
126+
govulncheck ./...
127+
- name: gosec (advisory)
128+
continue-on-error: true
129+
run: |
130+
go install github.com/securego/gosec/v2/cmd/gosec@latest
131+
gosec -exclude=G104,G301,G302,G304,G306 ./...
132+
133+
# -------------------------------------------------------------------------
134+
# Cross-platform build matrix — only for repos that produce a binary.
135+
# Repos that are pure libraries can keep this job (it'll just `go build ./...`)
136+
# or remove it locally.
137+
# -------------------------------------------------------------------------
138+
build:
139+
name: build (${{ matrix.goos }}/${{ matrix.goarch }})
48140
runs-on: ubuntu-latest
141+
needs: [fmt-vet, lint, test]
142+
strategy:
143+
fail-fast: false
144+
matrix:
145+
goos: [linux, darwin, windows]
146+
goarch: [amd64, arm64]
147+
exclude:
148+
- goos: windows
149+
goarch: arm64
49150
steps:
50151
- uses: actions/checkout@v4
51152
- uses: actions/setup-go@v5
52153
with:
53-
go-version: '1.26.2'
54-
- name: Install govulncheck
55-
run: go install golang.org/x/vuln/cmd/govulncheck@latest
56-
- name: Run govulncheck
57-
run: govulncheck ./... || true
154+
go-version: ${{ env.GO_VERSION }}
155+
cache: true
156+
- name: Build
157+
env:
158+
GOOS: ${{ matrix.goos }}
159+
GOARCH: ${{ matrix.goarch }}
160+
CGO_ENABLED: "0"
161+
run: go build ./...

0 commit comments

Comments
 (0)