now looking at the json: I'm fine changing the stable API, this is a new project and there is only one external dependency using it yet. some of the reviews sounded as if the json isn't in a consisten · Entire
CLI repo PR gates (what runs on every PR)
| Workflow | What it does |
|---|---|
| ci.yml | Unit + integration tests with -race detection, via mise run test:ci |
| lint.yml | golangci-lint (60+ linters, inline PR annotations), gofmt check, go mod tidy check, shellcheck, mise task validation |
| license-check.yml | Reusable workflow from entireio/shared for license compliance |
E2E tests only run on push to main, not as PR gates (too expensive/flaky).
git-sync current state
No CI at all - no .github/workflows/ directory exists. But the building blocks are ready in mise.toml:
mise run test→go test ./...mise run fmt→gofmt -s -wgolangci-lint2.11.3 installed (but no.golangci.ymlconfig file)shellcheckinstalled
What I'd propose for git-sync PR gates
| Workflow | Based on CLI's | Notes |
|---|---|---|
| ci.yml — Tests | Same pattern | go test -race ./... — skip the smoke/integration tests that need external services (test:git-http-backend, test:entire-local-smoke, etc.) |
| lint.yml — Linting | Same pattern | golangci-lint + gofmt check + go mod tidy check. We'd need to create a .golangci.yml — we could start with a reasonable subset of the CLI's 60+ linters, or copy it wholesale. Also add the golangci-lint-action for inline PR annotations. |
| license-check.yml | Direct reuse | Same shared workflow from entireio/shared |
Things to decide:
- Linter strictness — Start with a copy of the CLI's
.golangci.yml(may surface existing violations to fix) or start lighter and tighten over time? - Race detection — The CLI runs tests with
-racein CI. Worth doing here too? (Slight slowdown but catches real bugs in concurrent code.) - gnome-keyring — git-sync uses
go-keyringlike the CLI. The CLI's CI sets up gnome-keyring on Ubuntu for this. We'd likely need the same if any tests touch auth/keyring code. - License check — Want to include the shared
entireio/sharedlicense check workflow?
That's ~330 real violations (the ones like sb, buf etc. are grep false positives). The breakdown of the significant ones:
| Linter | Count | Effort |
|---|---|---|
wrapcheck |
114 | Medium — needs fmt.Errorf("...: %w", err) wrapping |
perfsprint |
50 | Easy — mechanical fmt.Errorf → errors.New, fmt.Sprintf → concat |
errcheck |
45 | Easy/Medium — add _ = or handle errors |
intrange |
25 | Easy — for i := 0; i < n; i++ → for i := range n |
forbidigo |
14 | Needs review — likely os.Getwd or similar banned calls |
revive |
13 | Easy — style fixes |
inamedparam |
11 | Easy — name interface params |
embeddedstructfieldcheck |
9 | Easy — add blank lines in structs |
| Others | ~40 | Mixed |
Fixing all 330 in one go is doable but it's a big diff. A few options:
- Fix them all now — one big cleanup PR, then the gates enforce a clean baseline
- Use golangci-lint's
--new-from-rev=HEAD— only lint new/changed code in PRs, then fix existing violations incrementally - Fix the easy mechanical ones now, disable the noisy ones (
wrapcheck,errcheck) temporarily, enable them as you clean up
Everything is clean. All four issues are fixed:
- Restored
graphStore = nilwith//nolint:ineffassign,wastedassign— preserves the ~4.6 GB early reclamation beforeruntime.GC() - Reverted JSON tags on stable API types (
RefMapping,RefScope,SyncPolicy) — no wire-format change - Removed double-wrapping in
internalbridge— the bridge is now pass-through,pkg/gitsync/client.goadds the only context layer - Reverted JSON tags on
unstable.AdvancedOptions— no serialization change;musttagsuppressed on the bench tool's debug output instead
Here's the picture:
Output types (Result, ProbeResult, RefResult, Stats, etc.) — all consistently snake_case tagged. These are what actually hits json.Marshal in cmd/git-sync/main.go.
Input/config types (Endpoint, RefMapping, RefScope, SyncPolicy, AdvancedOptions, all Request structs) — no tags at all. These default to PascalCase if ever marshaled. Currently they're only used programmatically (never serialized), but if a caller ever did marshal a SyncRequest, they'd get a mix of PascalCase config fields containing snake_case result fields.
Two options:
- Tag the input types with
snake_caseto match the output types — consistent wire format everywhere - Leave input types untagged since they're never serialized today — accept the asymmetry
Since this is early and you said there's only one external dependency — now is the cheapest time to switch to camelCase everywhere if that's what you'd prefer. What's your call?
Switch to camelCase — committed as cc2de54. 10 files changed, perfectly balanced (155 insertions, 155 deletions — pure renames).