--- name: add-ingestr-source description: Add Bruin CLI support for a new ingestr source. Use when a task asks to implement a new ingestr connection/source type, wire that source into Bruin ingestr assets, update available source tables, add ingestion docs or example assets, regenerate connection schema expectations, or address review feedback for a newly added ingestr source. --- # Add Ingestr Source ## Workflow 1. Read the ingestr docs first: https://getbruin.com/docs/ingestr/. Then read the upstream source-specific docs or PR. Capture the source URI scheme, required URI parameters, optional URI parameters, supported `source_table` values, incremental behavior, primary keys, and any file/table hints. 2. Inspect similar Bruin sources before editing. Prefer an existing package with the same shape: API/table source, OAuth/API-key source, database-like source, or file/path source. 3. Implement the connection config and URI builder. 4. Wire the connection into config loading, connection manager registration, and ingestr asset source discovery. 5. Add source-table registry entries, docs, example assets, tests, and regenerated expectations. 6. Run the checks required by the repo instructions before committing. ## Implementation Checklist Add or update these files for a new source named ``: - `pkg//config.go`: the `Config` struct and `GetIngestrURI()`. - `pkg//db.go` (or `client.go`, matching the package you copy from): the `Client` and `NewClient`. - `pkg/config/connections.go`: add `Connection` with YAML/JSON/mapstructure tags and `GetName()`. Tag every credential/secret field — anything that must not be printed in logs (API keys, tokens, passwords, client secrets, access keys, etc.) — with `sensitive:"true"` so it is redacted. For fields that hold a **path to a credential file** (e.g. a service-account JSON or private-key file), use `sensitive_file:"true"` instead — `sensitive:"true"` would mask only the path, while `sensitive_file:"true"` redacts the file's contents. - `pkg/config/manager.go`: add the connection slice to `Connections`, then update `AddConnection`, `DeleteConnection`, and `MergeFrom`. - `pkg/connection/connection.go`: import the package, add a `Manager` map, add `AddConnectionFromConfig`, store it in `availableConnections` and `AllConnectionDetails`, and process it in `NewManagerFromConfigWithContext`. - `pkg/pipeline/pipeline.go`: add a `defaultMapping` entry `"": "-default"`. - `pkg/ingestr/sources.go`: add `SourceTablesRegistry[""]`. - `docs/ingestion/.md`: document `.bruin.yml` config, ingestr asset YAML, source tables, options, incremental behavior, and example assets. - `docs/.vitepress/config.mjs`: add the docs sidebar entry. - `pkg/config/manager_test.go`: cover the new connection in `AddConnection`/`DeleteConnection`/`MergeFrom`. - `pkg/config/testdata/simple.yml`: add a sample connection block. - `pkg/config/testdata/simple_win.yml`: add the same block (keep in sync with `simple.yml`). - `integration-tests/expectations/expected_connections_schema.json`: regenerate after the connection schema changes. Add **every** required and optional parameter from the source URI — do not stop at the common ones. Take the authoritative list from the ingestr repo (`bruin-data/ingestr`) source code — the source's URI/DSN parser — not just the docs, and match each param's name and type exactly. For sources without fixed tables, add representative `source_table` formats instead of pretending the source has enumerated tables. File/path sources usually need examples for exact paths, globs, and format hints. ## URI Builder Pattern Build ingestr URIs with `net/url.Values`; do not concatenate unescaped query parameters. Validate required fields in deterministic order using a slice, not a map. This keeps user-facing errors stable and makes tests precise. ```go type requiredField struct { key string value string } requiredFields := []requiredField{ {"tenant_id", c.TenantID}, {"client_id", c.ClientID}, } for _, field := range requiredFields { field.value = strings.TrimSpace(field.value) if field.value == "" { return "", fmt.Errorf("%s: %s must be provided", sourceName, field.key) } params.Set(field.key, field.value) } ``` Use pointer fields for optional numeric values where zero is meaningful, such as `max_files: 0`. Reject negative limits before adding them to the URI. ## Tests Add focused tests for: - URI encoding, optional parameters, zero-valued pointer options, missing required fields, and invalid limits in `pkg/`. - `AddConnectionFromConfig` registering the client and connection details. - `Config.AddConnection`, `Config.DeleteConnection`, and `Connections.MergeFrom`. - `GetSourceTables("")` when source-table examples are added. Regenerate the connection schema expectation after adding a connection type: ```bash go run -tags="no_duckdb_arrow" . internal connections | jq . > integration-tests/expectations/expected_connections_schema.json ``` Inspect the generated diff. Ordering-only movement can happen, but keep only intentional changes. ## Docs Base docs on ingestr's source documentation, not guesses. Include: - `.bruin.yml` connection config with required and optional fields. - One minimal ingestr asset. - Several realistic example assets when `source_table` syntax has variants. - A table of available fixed tables, or available `source_table` formats for path/query-based sources. - Primary keys, metadata columns, and whether extraction is incremental or full-refresh. Keep examples executable-looking but generic. Use the same destination pattern as nearby ingestion docs unless the source needs something different. ## Version Caveat Check the pinned ingestr version before bumping it, usually in `pkg/python/uv.go`. If the upstream source exists only in an unreleased ingestr PR or commit, wire Bruin support but do not bump to a nonexistent release. Mention the release dependency in the final note or PR when relevant. ## Validation During iteration, run focused package tests first. Before finishing app-code changes, follow the repo instructions exactly: run `make format` and `make test`. For docs-only follow-ups, use the smallest relevant validation such as `git diff --check`, Markdown inspection, or docs build if the repo has a fast docs check.