fuzzyworld

template / files / IMPROVEMENTS.md

IMPROVEMENTS.md

4.0 KB · history · blame

Improvement Plan

Ordered roughly by effort, lowest first. Each section lists the concrete changes needed.


✅ 1. Drop golang.org/x/exp dependency

Replaced golang.org/x/exp/slices with the stdlib slices package in config.go, profile.go, and name_pattern_test.go. Removed the dependency from go.mod via go mod tidy.


✅ 2. Upgrade Go version

go.mod now declares go 1.25.0, driven by the project's actual transitive deps. The GitLab CI image (golang:1.25) is aligned.


✅ 3. Reorganize source files into a nested directory

All source files moved out of the repo root into:

cmd/
  template/
    main.go       ← 14-line entry point; sets Version, calls core.Run()
internal/
  core/
    app.go        ← CLI wiring + all orchestration logic
    config.go
    profile.go
    ... (all other files)

Makefile build and install targets updated to ./cmd/template/. .goreleaser.yaml updated with main: ./cmd/template/.


✅ 4. Tool management via separate module

Dev tools (golangci-lint, gomarklint, goreleaser) are now version-pinned in tools/go.mod, keeping their hundreds of transitive dependencies out of the main go.mod. The Makefile installs them via cd tools && go install ... and exposes make lint and make lint-docs targets.


✅ 5. Reduce main.go size

cmd/template/main.go is now 14 lines. All CLI wiring, settings construction (createSettings), profile resolution (findProfile), and orchestration (runMain) live in internal/core/app.go where they are reachable by tests without going through the CLI layer.


✅ 6. Improve test coverage

Coverage raised from ~56% to 67.7%. Threshold gate in Makefile raised to 65%.

New tests added across:

Remaining uncovered paths are inherently untestable in unit tests: CLI wiring (Run, createSettings, runMain), the Windows branch of shellCommandAndArgs, and error branches in yaml.Marshal / bufio.Writer that the library panics on rather than returning errors.


✅ 7. Clean up default_config.go

default_config.go shrunk from 396 lines to 18 by switching to //go:embed defaults.yaml. All 14 profiles now live in defaults.yaml as plain YAML, editable without touching Go code.

Added omitempty to the IsDefault and IsDisabled bool fields in Profile so marshaling produces clean output (zero values omitted).


✅ 8. Minor housekeeping

Source
1# Improvement Plan
2
3Ordered roughly by effort, lowest first. Each section lists the concrete changes needed.
4
5---
6
7## ✅ 1. Drop `golang.org/x/exp` dependency
8
9Replaced `golang.org/x/exp/slices` with the stdlib `slices` package in
10[config.go](internal/core/config.go), [profile.go](internal/core/profile.go), and
11[name_pattern_test.go](internal/core/name_pattern_test.go). Removed the dependency
12from [go.mod](go.mod) via `go mod tidy`.
13
14---
15
16## ✅ 2. Upgrade Go version
17
18[go.mod](go.mod) now declares `go 1.25.0`, driven by the project's actual transitive
19deps. The GitLab CI image (`golang:1.25`) is aligned.
20
21---
22
23## ✅ 3. Reorganize source files into a nested directory
24
25All source files moved out of the repo root into:
26
27```text
28cmd/
29 template/
30 main.go ← 14-line entry point; sets Version, calls core.Run()
31internal/
32 core/
33 app.go ← CLI wiring + all orchestration logic
34 config.go
35 profile.go
36 ... (all other files)
37```
38
39[Makefile](Makefile) build and install targets updated to `./cmd/template/`.
40[.goreleaser.yaml](.goreleaser.yaml) updated with `main: ./cmd/template/`.
41
42---
43
44## ✅ 4. Tool management via separate module
45
46Dev tools (golangci-lint, gomarklint, goreleaser) are now version-pinned in
47[tools/go.mod](tools/go.mod), keeping their hundreds of transitive dependencies
48out of the main [go.mod](go.mod). The [Makefile](Makefile) installs them via
49`cd tools && go install ...` and exposes `make lint` and `make lint-docs` targets.
50
51---
52
53## ✅ 5. Reduce `main.go` size
54
55[cmd/template/main.go](cmd/template/main.go) is now 14 lines. All CLI wiring,
56settings construction (`createSettings`), profile resolution (`findProfile`), and
57orchestration (`runMain`) live in [internal/core/app.go](internal/core/app.go)
58where they are reachable by tests without going through the CLI layer.
59
60---
61
62## ✅ 6. Improve test coverage
63
64Coverage raised from ~56% to 67.7%. Threshold gate in [Makefile](Makefile) raised
65to 65%.
66
67New tests added across:
68
69- **[app_test.go](internal/core/app_test.go)** — `readEnvVars` (all env var
70 branches), `loadAndMergeUserConfig` (file not found, valid merge, invalid YAML,
71 merge error from invalid global config), `findProfile` (named profile, default
72 profile, no-profile error)
73- **[file_test.go](internal/core/file_test.go)** — `createFile` error paths
74 (`OSCreate` failure, `OSWriteFile` failure in template and empty-template paths),
75 `readFile` (happy path and missing file)
76- **[profile_test.go](internal/core/profile_test.go)** — `createEntity` error
77 paths (mkdir failure, chdir failure, invalid file-name pattern inside folder,
78 subdir mkdir failure, `createFile` failure for both `FolderType` and `FileType`),
79 `processProfile` edge cases (target-dir mkdir/chdir failures, `createEntity`
80 error with and without `RunPostscriptOnFailure` swallow, invalid post-script
81 template, post script with no output, post script that exits non-zero),
82 `ScriptType` profile
83- **[profile_test.go](internal/core/profile_test.go)** — new
84 `TestCreateNewNameForPatternsGetVersionError`: `getVersion` used in a non-last
85 pattern returns an error
86
87Remaining uncovered paths are inherently untestable in unit tests: CLI wiring
88(`Run`, `createSettings`, `runMain`), the Windows branch of `shellCommandAndArgs`,
89and error branches in `yaml.Marshal` / `bufio.Writer` that the library panics on
90rather than returning errors.
91
92---
93
94## ✅ 7. Clean up `default_config.go`
95
96[default_config.go](internal/core/default_config.go) shrunk from 396 lines to 18
97by switching to `//go:embed defaults.yaml`. All 14 profiles now live in
98[defaults.yaml](internal/core/defaults.yaml) as plain YAML, editable without
99touching Go code.
100
101Added `omitempty` to the `IsDefault` and `IsDisabled` bool fields in `Profile`
102so marshaling produces clean output (zero values omitted).
103
104---
105
106## ✅ 8. Minor housekeeping
107
108- **Empty `src/` directory** — removed.
109- **`.DS_Store`** — `**/.DS_Store` added to [.gitignore](.gitignore).
110- **CI image pinning** — [.fw-ci.yml](.fw-ci.yml) pinned to
111 `golang:1.25.4`.