P1.3: rename storage files to gosentry.json / jobs.json

- ConfigFileName → "gosentry.json", JobsFileName → "jobs.json"
- Remove exported LegacyConfigFileName ("pysentry.yaml")
- Add unexported legacyYAMLConfigFileName / legacyYAMLJobsFileName for
  the upcoming one-time YAML import (P1.4)
- Update store.go fallback path and comments to describe YAML→JSON
  migration rather than the old PySentry→GoSentry rename
- Align store_test.go references and test comments

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
mixeme
2026-06-22 21:33:02 +03:00
parent 7ec5521309
commit 8df248a1b2
4 changed files with 23 additions and 25 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ These land together because both edit `domain/job.go` and `storage/store.go`.
### Phase 1 — Storage JSON + exit-code removal ### Phase 1 — Storage JSON + exit-code removal
- [x] P1.1 — JSON struct tags - [x] P1.1 — JSON struct tags
- [x] P1.2 — `writeJSON` + JSON unmarshal - [x] P1.2 — `writeJSON` + JSON unmarshal
- [ ] P1.3 — `gosentry.json` / `jobs.json` paths; drop pysentry name - [x] P1.3 — `gosentry.json` / `jobs.json` paths; drop pysentry name
- [ ] P1.4 — One-time YAML import - [ ] P1.4 — One-time YAML import
- [ ] P1.5 — Remove `SuccessExitCodes` across code - [ ] P1.5 — Remove `SuccessExitCodes` across code
- [ ] P1.6 — Update storage/runner/format tests + TESTS.md - [ ] P1.6 — Update storage/runner/format tests + TESTS.md
+8 -7
View File
@@ -8,15 +8,16 @@ import (
const ( const (
// The config file stays beside the executable so the portable build behaves // The config file stays beside the executable so the portable build behaves
// predictably: moving the program folder moves its settings with it. // predictably: moving the program folder moves its settings with it.
ConfigFileName = "gosentry.yaml" ConfigFileName = "gosentry.json"
// Older builds were named PySentry. Keep the old config name readable during // Jobs are kept in a separate JSON file because the user can choose a
// the rename window so portable installations can start once and rewrite the
// settings to gosentry.yaml without manual file copying.
LegacyConfigFileName = "pysentry.yaml"
// Jobs are kept in a separate YAML file because the user can choose a
// different jobs directory, while application settings remain local to the // different jobs directory, while application settings remain local to the
// installed/copied program. // installed/copied program.
JobsFileName = "jobs.yaml" JobsFileName = "jobs.json"
// Legacy YAML file names used by builds before the JSON migration. These are
// read once on first start (P1.4) and then replaced by the JSON equivalents.
legacyYAMLConfigFileName = "gosentry.yaml"
legacyYAMLJobsFileName = "jobs.yaml"
) )
// Paths contains both the physical program location and the resolved runtime // Paths contains both the physical program location and the resolved runtime
+6 -8
View File
@@ -41,9 +41,9 @@ func OpenStore() (*Store, []domain.Job, error) {
return nil, nil, err return nil, nil, err
} }
normalizeJobs(jobs) normalizeJobs(jobs)
// Jobs are also rewritten after normalization. That keeps jobs.yaml compact: // Jobs are also rewritten after normalization. That keeps jobs.json compact:
// only durable job definitions remain, because runtime fields are tagged // only durable job definitions remain, because runtime fields are tagged
// yaml:"-" in the model. // json:"-" in the model.
if err := store.SaveJobs(jobs); err != nil { if err := store.SaveJobs(jobs); err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -80,13 +80,11 @@ func loadOrCreateConfig(paths Paths) (domain.Config, error) {
configPath := paths.ConfigPath configPath := paths.ConfigPath
if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) { if _, err := os.Stat(configPath); errors.Is(err, os.ErrNotExist) {
legacyPath := filepath.Join(paths.AppDir, LegacyConfigFileName) legacyPath := filepath.Join(paths.AppDir, legacyYAMLConfigFileName)
if _, legacyErr := os.Stat(legacyPath); legacyErr == nil { if _, legacyErr := os.Stat(legacyPath); legacyErr == nil {
// The rename from PySentry to GoSentry changed the preferred config // gosentry.yaml is the pre-JSON-migration config file. Read it once
// filename. Read the old file once if it is still present so portable // when gosentry.json is absent so existing installs migrate without
// installs continue to start without a manual migration step. The // manual intervention. SaveConfig rewrites the result as gosentry.json.
// caller later saves the loaded config back through SaveConfig, which
// naturally rewrites it under gosentry.yaml.
configPath = legacyPath configPath = legacyPath
} else { } else {
return config, writeJSON(paths.ConfigPath, config) return config, writeJSON(paths.ConfigPath, config)
+8 -9
View File
@@ -155,15 +155,14 @@ func TestNormalizeJobsFillsDefaults(t *testing.T) {
} }
} }
// TestLoadOrCreateConfigMigratesFromLegacy verifies that when gosentry.yaml is // TestLoadOrCreateConfigMigratesFromLegacy verifies that when gosentry.json is
// absent but pysentry.yaml exists the config is read from the legacy file. This // absent but gosentry.yaml exists the config is read from the legacy YAML file.
// lets portable installs that still carry a pysentry.yaml start without manual // This lets installs that pre-date the JSON migration start without manual steps.
// migration.
func TestLoadOrCreateConfigMigratesFromLegacy(t *testing.T) { func TestLoadOrCreateConfigMigratesFromLegacy(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
paths := Paths{ paths := Paths{
AppDir: dir, AppDir: dir,
ConfigPath: filepath.Join(dir, ConfigFileName), // gosentry.yaml — not created ConfigPath: filepath.Join(dir, ConfigFileName), // gosentry.json — not created
} }
legacy := domain.Config{ legacy := domain.Config{
@@ -173,7 +172,7 @@ func TestLoadOrCreateConfigMigratesFromLegacy(t *testing.T) {
MaxLogAgeDays: 13, MaxLogAgeDays: 13,
StartOnLogin: true, StartOnLogin: true,
} }
if err := writeYAML(filepath.Join(dir, LegacyConfigFileName), legacy); err != nil { if err := writeYAML(filepath.Join(dir, legacyYAMLConfigFileName), legacy); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@@ -199,7 +198,7 @@ func TestLoadOrCreateConfigMigratesFromLegacy(t *testing.T) {
} }
// TestLoadOrCreateConfigCreatesDefaultsOnFirstRun verifies that the first run // TestLoadOrCreateConfigCreatesDefaultsOnFirstRun verifies that the first run
// (no config files present) writes gosentry.yaml and returns sensible defaults. // (no config files present) writes gosentry.json and returns sensible defaults.
func TestLoadOrCreateConfigCreatesDefaultsOnFirstRun(t *testing.T) { func TestLoadOrCreateConfigCreatesDefaultsOnFirstRun(t *testing.T) {
dir := t.TempDir() dir := t.TempDir()
paths := Paths{ paths := Paths{
@@ -223,9 +222,9 @@ func TestLoadOrCreateConfigCreatesDefaultsOnFirstRun(t *testing.T) {
if got.MaxLogAgeDays != 30 { if got.MaxLogAgeDays != 30 {
t.Errorf("default MaxLogAgeDays = %d, want 30", got.MaxLogAgeDays) t.Errorf("default MaxLogAgeDays = %d, want 30", got.MaxLogAgeDays)
} }
// The function must have written the defaults to gosentry.yaml. // The function must have written the defaults to gosentry.json.
if _, err := os.Stat(paths.ConfigPath); err != nil { if _, err := os.Stat(paths.ConfigPath); err != nil {
t.Errorf("gosentry.yaml should have been created: %v", err) t.Errorf("gosentry.json should have been created: %v", err)
} }
} }