Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 4 additions & 5 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ cd rigging
make ci

# Or run individual checks
make test
make test-race
make test # race-enabled test suite
make fmt
```

Expand All @@ -41,7 +40,7 @@ make fmt

### Testing Requirements
- All exported functions must have tests
- Aim for >80% coverage
- Keep coverage healthy; the current `make ci` gate fails below 70% total coverage
- Use table-driven tests
- Test error paths, not just happy paths

Expand Down Expand Up @@ -124,8 +123,8 @@ We reject:

**Using Make (recommended):**
```bash
make ci # Run all CI checks (fmt, vet, test, lint)
make test # Run tests
make ci # Run all CI checks (fmt, vet, test, lint, coverage gate)
make test # Run race-enabled tests
make fmt # Format code
make vet # Run go vet
make lint # Run golangci-lint
Expand Down
4 changes: 2 additions & 2 deletions docs/api-reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ Configure binding and validation with the `conf` tag:
| Tag | Description | Example |
|-----|-------------|---------|
| `required` | Field must have a value | `conf:"required"` |
| `env:VAR` | Bind from an explicit env-style key path (normalized with `__` -> `.` and lowercased) | `conf:"env:APP__DATABASE__HOST"` |
| `env:VAR` | Bind from an explicit env-style key path (normalized with `__` -> `.` and lowercased) after any `sourceenv.Options.Prefix` stripping | `conf:"env:DATABASE__HOST"` |
| `default:X` | Default value if not provided | `conf:"default:8080"` |
| `min:N` | Minimum value (numeric) or length (string) | `conf:"min:1024"` |
| `max:N` | Maximum value (numeric) or length (string) | `conf:"max:65535"` |
Expand All @@ -373,7 +373,7 @@ type Config struct {
**Tag precedence:**

- `name:` overrides all key derivation (ignores `prefix:` and field name)
- `env:` is used when `name:` is not set
- `env:` is used when `name:` is not set; it matches the env-style key after any source prefix stripping
- otherwise keys are derived from field names (snake_case), with parent `prefix:` for nested structs
- env-style normalization converts `__` to `.` and preserves single `_`

Expand Down
6 changes: 4 additions & 2 deletions docs/configuration-sources.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,11 +150,13 @@ Important:
- File source flattens nested objects but does not rewrite separators.
- File source can optionally adapt flattened keys via `SnakeCaseKeys` and `KeyPrefix` in `sourcefile.Options`.
- Rigging lowercases keys during loader merge for consistent matching across sources.
- If your file keys are snake_case, use `name:` tags to match them.
- Derived field keys are already snake_case, so `MaxConnections` matches `max_connections` without tags.
- Use `name:` only when the source key path differs from the derived path, or use `SnakeCaseKeys` / `KeyPrefix` to adapt file keys at the source boundary.

```go
type Config struct {
MaxConnections int `conf:"name:max_connections"`
MaxConnections int // matches max_connections
LegacyPort int `conf:"name:service.port"`
}
```

Expand Down
8 changes: 5 additions & 3 deletions docs/patterns.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,12 @@ type Config struct {
}
```

If your source keys use snake_case or custom paths, map explicitly:
Derived keys already use snake_case.
Use `name:` when a source key path differs from the derived path:

```go
type Config struct {
MaxConnections int `conf:"name:max_connections"`
MaxConnections int // matches max_connections
APIKey string `conf:"name:api.key"`
}
```
Expand All @@ -53,11 +54,12 @@ This is useful during migrations or when a legacy env variable name must be pres

```go
type Config struct {
DatabaseHost string `conf:"env:APP__DATABASE__HOST,required"`
DatabaseHost string `conf:"env:DATABASE__HOST,required"`
}
```

`env:` normalizes env-style syntax (`__` -> `.`, lowercased) before matching.
When `sourceenv` is configured with `Prefix: "APP_"`, `conf:"env:DATABASE__HOST"` matches `APP_DATABASE__HOST`.
Prefer `name:` for general cross-source key mapping; use `env:` when the intent is specifically env-key compatibility.

## 4. Normalize Typed Values Before Validation
Expand Down
9 changes: 6 additions & 3 deletions docs/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,15 +116,18 @@ File source behavior:
- keys are flattened from file structure and lowercased
- separators are not rewritten (for example, `max_connections` stays `max_connections`)

If your file keys are snake_case, map explicitly:
Derived field keys are already snake_case, so `MaxConnections` matches `max_connections` without extra tags.
Use `name:` only when the source key path differs, or adapt file keys at the source boundary with `sourcefile.Options{SnakeCaseKeys: true}` / `KeyPrefix`.

```go
type Config struct {
MaxConnections int `conf:"name:max_connections"`
MaxConnections int // matches max_connections
LegacyPort int `conf:"name:service.port"`
}
```

If you need to bind a field to a specific environment-style key path, use `env:` (for example, `conf:"env:APP__DATABASE__HOST"`).
If you need to bind a field to a specific environment-style key path, use `env:`.
The tag matches the normalized key after any `sourceenv.Options.Prefix` stripping, so with `Prefix: "APP_"`, `APP_DATABASE__HOST` maps via `conf:"env:DATABASE__HOST"`.

## 7. Fail-Fast Validation

Expand Down
2 changes: 1 addition & 1 deletion examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Use this page to quickly find the right example format.
## Runnable Examples

- [basic](basic/) - End-to-end app config loading with file + env layering, validation, provenance, and redaction.
- [transformer](transformer/) - Typed `WithTransformer(...)` canonicalization before tag validation.
- [transformer](transformer/) - Typed transform-stage canonicalization before tag validation, shown with `WithTransformerFunc(...)`.

Run it from the repository root:

Expand Down
3 changes: 2 additions & 1 deletion examples/basic/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@ go run main.go
# Switch to production environment
export APP_ENVIRONMENT=production
export APP_DATABASE__HOST=prod-db.example.com
export APP_DATABASE__SSL_MODE=require
go run main.go

# Enable feature flags
export APP_FEATURES__ENABLE_METRICS=true
export APP_FEATURES__RATELIMIT=5000
export APP_FEATURES__RATE_LIMIT=5000
go run main.go
```

Expand Down
18 changes: 9 additions & 9 deletions examples/basic/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,23 @@ database:
name: myapp_staging
user: app_user
password: staging_password_123
maxconnections: 25
sslmode: require
connecttimeout: 10s
max_connections: 25
ssl_mode: require
connect_timeout: 10s

server:
host: 0.0.0.0
port: 8080
readtimeout: 30s
writetimeout: 30s
shutdowntimeout: 10s
read_timeout: 30s
write_timeout: 30s
shutdown_timeout: 10s

logging:
level: info
format: json
output: stdout

features:
enablemetrics: true
enabletracing: false
ratelimit: 1000
enable_metrics: true
enable_tracing: false
rate_limit: 1000