fuzzyworld

template / commit

adding plan of near-future improvements

6e0dbce37b4aaaa7983f1e94be96b6a40f5a3c4f · Pavel Safronov · 2026-04-30 23:29:36 -0700 · parents 4137df01bff3

adding plan of near-future improvements
 IMPROVEMENTS.md | 153 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 153 insertions(+)

diff --git a/IMPROVEMENTS.md b/IMPROVEMENTS.md
new file mode 100644
index 0000000..0a6d1d0
--- /dev/null
+++ b/IMPROVEMENTS.md
@@ -0,0 +1,153 @@
+# Improvement Plan
+
+Ordered roughly by effort, lowest first. Each section lists the concrete changes needed.
+
+---
+
+## 1. Drop `golang.org/x/exp` dependency
+
+`golang.org/x/exp/slices` was a backport of the stdlib `slices` package (available since
+Go 1.21). Replace every import with the stdlib package.
+
+Files to update:
+
+- [config.go](config.go) — `import "golang.org/x/exp/slices"` → `import "slices"`
+- [profile.go](profile.go) — same
+- [name_pattern_test.go](name_pattern_test.go) — same
+
+After swapping imports, run `go mod tidy` to remove the `golang.org/x/exp` entries from
+`go.mod` and `go.sum`.
+
+---
+
+## 2. Upgrade Go version
+
+`go.mod` declares `go 1.24.0` / `toolchain go1.24.4`, but the GitLab CI image is already
+`golang:1.25`. Align `go.mod` with the CI image so the declared minimum matches what is
+actually tested against.
+
+Steps:
+
+1. Run `go mod tidy` after updating the `go` directive in [go.mod](go.mod).
+2. Update `toolchain` line to match the current patch release.
+3. Verify all tests still pass.
+
+---
+
+## 3. Reorganize source files into a nested directory
+
+All `.go` files currently live at the repo root alongside config files, making the layout
+cluttered. The standard Go layout for a CLI tool is:
+
+```text
+cmd/
+  template/
+    main.go          ← entry point only; wire dependencies here
+internal/
+  core/              ← or any name: "engine", "template", etc.
+    config.go
+    config_test.go
+    default_config.go
+    ...all other .go files...
+```
+
+Concrete steps:
+
+1. Create `cmd/template/` and `internal/core/` directories.
+2. Move `main.go` to `cmd/template/main.go`. Keep it thin — just flag parsing and calls
+   into `internal/core`.
+3. Move every other `.go` file (including test files) to `internal/core/`.
+4. Change the package declaration in all moved files from `package main` to `package core`
+   (or chosen name).
+5. Re-export only what `cmd/template/main.go` needs.
+6. Update the `Makefile` build target: `go build ./cmd/template/`.
+7. Update `.goreleaser.yaml` main path if it references a specific file.
+8. Run `go test ./...` to confirm nothing broke.
+
+**Note:** `monkey-patch.go` and `test-common.go` contain test-support code. They can live
+alongside the production code in `internal/core/` (Go only compiles `_test.go` files during
+tests) or move into a `internal/core/testutil/` sub-package.
+
+---
+
+## 4. Improve test coverage
+
+Current tests focus on the happy path. Priority areas for new tests:
+
+### 4a. Error paths in config handling ([config.go](config.go))
+
+- `loadConfig` — file not found, malformed YAML, invalid permissions
+- `saveConfig` — write failure (read-only directory)
+- `validateConfig` — all validation branches (duplicate names, multiple defaults)
+
+### 4b. Error paths in file creation ([file.go](file.go))
+
+- `createFile` — template parse error, template execution error, `os.Create` failure,
+  `os.WriteFile` failure
+- `readFile` — file not found
+
+### 4c. Profile processing edge cases ([profile.go](profile.go))
+
+- `processProfile` with `ScriptType` (currently untested or minimally tested)
+- `createEntity` failure cases: mkdir failure, nested file creation failure
+- `validateProfile` — all invalid combinations (missing target, unsupported OS, etc.)
+
+### 4d. Extras loading ([extras.go](extras.go))
+
+- Missing extras file (should not error)
+- Malformed extras YAML
+
+### 4e. `mainLogic` integration ([main.go](main.go))
+
+- Profile not found
+- Config load failure
+- Piped stdin with a folder-type profile (should be an error or no-op)
+
+### 4f. Coverage tooling
+
+Add a coverage threshold gate to the Makefile so CI fails if coverage drops below a chosen
+minimum (e.g., 70%):
+
+```makefile
+test:
+    go test ./... -coverprofile=test-coverage.out
+    go tool cover -func=test-coverage.out | grep total | awk '{if ($$3+0 < 70) exit 1}'
+```
+
+---
+
+## 5. Reduce `main.go` size
+
+At 584 lines, [main.go](main.go) mixes CLI wiring, settings construction, and business
+logic. After the reorganization in item 3, consider splitting it further:
+
+- Keep `main.go` (in `cmd/template/`) to flag definitions and `main()` only (~100 lines).
+- Move `createSettings()`, `mainLogic()`, and `findProfile()` into `internal/core/` where
+  they are easier to unit-test without going through the CLI layer.
+
+---
+
+## 6. Clean up `default_config.go`
+
+At 397 lines, [default_config.go](default_config.go) is unwieldy. Options:
+
+- Split into per-profile files: `profiles_daily.go`, `profiles_git.go`, etc.
+- Or load default profiles from an embedded YAML file (`//go:embed defaults.yaml`) so
+  non-Go contributors can read and edit profiles without touching Go code.
+
+The embedded YAML approach also makes it easy to write a single test that validates every
+default profile passes `validateProfile()`.
+
+---
+
+## 7. Minor housekeeping
+
+- **Empty `src/` directory** — remove it (or document its purpose).
+- **`test-common.go`** — this file contains only a package declaration. Either add shared
+  test helpers to it or delete it.
+- **`dev-setup` script** — is gitignored but checked-in? Verify its contents don't contain
+  credentials and decide if it should be tracked.
+- **`.DS_Store`** — add `**/.DS_Store` to [.gitignore](.gitignore) to prevent future
+  commits of macOS metadata files.
+- **CI image pinning** — `.gitlab-ci.yml` uses `golang:1.25` (unpinned minor). Pin to a
+  digest or a patch tag (`golang:1.25.0`) for reproducible builds.