refactor: centralize private file writes and tighten config migration coverage

Move duplicated writePrivateFile logic into pkg/utils.WritePrivateFile, reuse it from config and cron, add the glm-4.7 no-provider-keys test, and extend CI with go vet plus race-enabled tests.
This commit is contained in:
Jared Mahotiere 2026-02-18 14:35:43 -05:00
parent 3f66ccbbfa
commit e2f3b43b81
5 changed files with 40 additions and 18 deletions

View file

@ -29,5 +29,8 @@ jobs:
exit 1
fi
- name: Run tests
run: go test ./...
- name: Run go vet
run: go vet ./...
- name: Run tests (race)
run: go test -race ./...

View file

@ -7,6 +7,7 @@ import (
"sync"
"github.com/caarlos0/env/v11"
"github.com/sipeed/picoclaw/pkg/utils"
)
type Config struct {
@ -252,7 +253,7 @@ func SaveConfig(path string, cfg *Config) error {
return err
}
return writePrivateFile(path, data)
return utils.WritePrivateFile(path, data)
}
func (c *Config) WorkspacePath() string {
@ -320,13 +321,6 @@ func expandHome(path string) string {
return path
}
func writePrivateFile(path string, data []byte) error {
if err := os.WriteFile(path, data, 0600); err != nil {
return err
}
return os.Chmod(path, 0600)
}
func normalizeLegacyModelDefaults(cfg *Config) {
if cfg == nil {
return

View file

@ -86,3 +86,23 @@ func TestLoadConfigKeepsLegacyGLMModelWhenZhipuConfigured(t *testing.T) {
t.Fatalf("model = %q, want %q", cfg.Agents.Defaults.Model, "glm-4.7")
}
}
func TestLoadConfigKeepsLegacyGLMModelWhenNoProviderKeysConfigured(t *testing.T) {
path := filepath.Join(t.TempDir(), "config.json")
content := `{
"agents": { "defaults": { "model": "glm-4.7" } }
}`
if err := os.WriteFile(path, []byte(content), 0644); err != nil {
t.Fatalf("failed to write config fixture: %v", err)
}
cfg, err := LoadConfig(path)
if err != nil {
t.Fatalf("LoadConfig failed: %v", err)
}
if cfg.Agents.Defaults.Model != "glm-4.7" {
t.Fatalf("model = %q, want %q", cfg.Agents.Defaults.Model, "glm-4.7")
}
}

View file

@ -12,6 +12,7 @@ import (
"time"
"github.com/adhocore/gronx"
"github.com/sipeed/picoclaw/pkg/utils"
)
type CronSchedule struct {
@ -318,7 +319,7 @@ func (cs *CronService) saveStoreUnsafe() error {
return err
}
return writePrivateFile(cs.storePath, data)
return utils.WritePrivateFile(cs.storePath, data)
}
func (cs *CronService) AddJob(name string, schedule CronSchedule, message string, deliver bool, channel, to string) (*CronJob, error) {
@ -456,10 +457,3 @@ func generateID() string {
}
return hex.EncodeToString(b)
}
func writePrivateFile(path string, data []byte) error {
if err := os.WriteFile(path, data, 0600); err != nil {
return err
}
return os.Chmod(path, 0600)
}

11
pkg/utils/file.go Normal file
View file

@ -0,0 +1,11 @@
package utils
import "os"
// WritePrivateFile writes data and enforces 0600 permissions for both new and existing files.
func WritePrivateFile(path string, data []byte) error {
if err := os.WriteFile(path, data, 0600); err != nil {
return err
}
return os.Chmod(path, 0600)
}