fix(loader): disable config file rewrite during startup
Some checks failed
CI / build-and-test (push) Failing after -32m45s
Some checks failed
CI / build-and-test (push) Failing after -32m45s
* migrate legacy schemas in memory only * log hint to use amcs-migrate-config for persistence
This commit is contained in:
@@ -260,6 +260,7 @@ go run ./cmd/amcs-migrate-config --config ./configs/dev.yaml
|
|||||||
```
|
```
|
||||||
|
|
||||||
Use `--dry-run` to print migrated YAML without writing.
|
Use `--dry-run` to print migrated YAML without writing.
|
||||||
|
Server startup migrates older config formats in memory only and does not write files.
|
||||||
|
|
||||||
**OAuth Client Credentials flow**:
|
**OAuth Client Credentials flow**:
|
||||||
|
|
||||||
|
|||||||
@@ -83,3 +83,8 @@
|
|||||||
- Added `amcs-migrate-config` binary to the Docker image build output.
|
- Added `amcs-migrate-config` binary to the Docker image build output.
|
||||||
- Added `migrate-config` service in `docker-compose.yml` under the `tools` profile.
|
- Added `migrate-config` service in `docker-compose.yml` under the `tools` profile.
|
||||||
- Documented compose-based migration commands (dry-run and in-place apply) in the README.
|
- Documented compose-based migration commands (dry-run and in-place apply) in the README.
|
||||||
|
|
||||||
|
### 2026-04-21 21h - Startup Migration Write Disabled
|
||||||
|
- Changed config loading to migrate legacy schemas in memory only during startup.
|
||||||
|
- Removed automatic file rewrite and backup creation from the startup config loader.
|
||||||
|
- Added loader log hint to use `amcs-migrate-config` when persistent conversion is needed.
|
||||||
|
|||||||
@@ -40,16 +40,14 @@ func LoadWithLogger(explicitPath string, log *slog.Logger) (*Config, string, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(applied) > 0 {
|
if len(applied) > 0 {
|
||||||
if err := rewriteConfigFile(path, data, raw); err != nil {
|
|
||||||
return nil, path, err
|
|
||||||
}
|
|
||||||
if log != nil {
|
if log != nil {
|
||||||
for _, step := range applied {
|
for _, step := range applied {
|
||||||
log.Warn("config migrated",
|
log.Warn("config migrated in memory",
|
||||||
slog.String("path", path),
|
slog.String("path", path),
|
||||||
slog.Int("from_version", step.From),
|
slog.Int("from_version", step.From),
|
||||||
slog.Int("to_version", step.To),
|
slog.Int("to_version", step.To),
|
||||||
slog.String("describe", step.Describe),
|
slog.String("describe", step.Describe),
|
||||||
|
slog.String("hint", "persist with amcs-migrate-config"),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -81,22 +79,6 @@ func decodeTyped(raw map[string]any) (Config, error) {
|
|||||||
return cfg, nil
|
return cfg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func rewriteConfigFile(path string, original []byte, migrated map[string]any) error {
|
|
||||||
backupPath := fmt.Sprintf("%s.bak.%d", path, time.Now().Unix())
|
|
||||||
if err := os.WriteFile(backupPath, original, 0o600); err != nil {
|
|
||||||
return fmt.Errorf("write backup %q: %w", backupPath, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
out, err := yaml.Marshal(migrated)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("marshal migrated config: %w", err)
|
|
||||||
}
|
|
||||||
if err := os.WriteFile(path, out, 0o600); err != nil {
|
|
||||||
return fmt.Errorf("write migrated config %q: %w", path, err)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func ResolvePath(explicitPath string) string {
|
func ResolvePath(explicitPath string) string {
|
||||||
if path := strings.TrimSpace(explicitPath); path != "" {
|
if path := strings.TrimSpace(explicitPath); path != "" {
|
||||||
if path != ".yaml" && path != ".yml" {
|
if path != ".yaml" && path != ".yml" {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package config
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -215,7 +216,15 @@ logging:
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("glob backups: %v", err)
|
t.Fatalf("glob backups: %v", err)
|
||||||
}
|
}
|
||||||
if len(entries) != 1 {
|
if len(entries) != 0 {
|
||||||
t.Fatalf("backup files = %d, want 1", len(entries))
|
t.Fatalf("backup files = %d, want 0 (load should not rewrite config)", len(entries))
|
||||||
|
}
|
||||||
|
|
||||||
|
originalOnDisk, err := os.ReadFile(configPath)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("read original config: %v", err)
|
||||||
|
}
|
||||||
|
if !strings.Contains(string(originalOnDisk), "provider: \"litellm\"") {
|
||||||
|
t.Fatalf("expected source config to remain unchanged on disk")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user