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
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ project adheres to [Semantic Versioning](https://semver.org/).

### Added

- Notifications: a `notifications` item sends `drift_detected`, `out_of_sync`, `sync_succeeded`, `sync_failed` and `back_in_sync` to a webhook (any receiver, with bearer, basic or header auth, a body template and optional HMAC signing) or to an Ascender or AWX job template (its webhook receiver or its launch API), one message per run, queued and retried, never with a field's value; `GET /api/v1/notifications` shows each one's last send and `POST /api/v1/notifications/{id}/test` sends a test (see `docs/notifications.md`).
- Webhooks: a `webhooks` item sends, for `all` applications or the ones it names, `drift_detected`, `out_of_sync`, `sync_succeeded`, `sync_failed` and `back_in_sync` to a webhook (any receiver, with bearer, basic or header auth, a body template and optional HMAC signing) or to an Ascender or AWX job template (through the template's own webhook receiver, so no user is needed), one message per run, drift told apart from a commit by the application's own folder in git, queued and retried without one receiver holding up the others, its changes listed by name and never with a field's value; `GET /api/v1/webhooks` shows each one's last send, `GET /api/v1/webhooks/{id}` its last 50, and `POST /api/v1/webhooks/{id}/test` sends a test (see `docs/webhooks.md`).
- Metrics `unified_gitops_git_requests_total{project,operation,outcome}` and `unified_gitops_git_request_duration_seconds`: every clone, pull and rollback fetch this instance makes to a git server, as `unified_gitops_connector_calls_total` counts those to the systems.

### Changed

Expand Down
8 changes: 4 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,17 +45,17 @@ src/
│ ├── desired.rs # desired-state files: parse, load a folder, validate, order
│ ├── plan.rs # THE DIFF: only declared fields compared → Operation list
│ ├── run.rs # SyncStatus, RunRecord, PlanSnapshot, AppStateRegistry
│ ├── notification.rs # Notification: type (webhook/ascender/awx), events, its block
│ ├── webhook.rs # Webhook: type (webhook/ascender/awx), events, its block
│ ├── yaml.rs # YAML → JSON with exact scalars ("0644" stays a string)
│ ├── credential.rs, api_key.rs, ldap.rs, project.rs, sync_health.rs
├── application/
│ ├── reconcile.rs # THE LOOP: validate → list → copy → diff → apply → re-list
│ ├── projects.rs # pull a checkout (bounded by timeout_seconds)
│ ├── notify.rs # event per run (detect), message, request per type, queue + worker
│ ├── webhooks.rs # event per run (detect), message, request per type, queue + worker
│ ├── scripts.rs # per-run script path resolution into checkouts
│ ├── credentials.rs, login.rs, config.rs (reload)
├── ports/ # connector, state_store, git, secrets, directory, config_store, venv,
│ # notifier (sends one built HTTP request)
│ # http_sender (sends one built HTTP request)
└── adapters/
├── in/http/ # applications (+ state copies), connectors, projects,
│ # credentials, settings, users (auth), config, login, session,
Expand All @@ -64,7 +64,7 @@ src/
└── out/
├── connectors/process.rs # ConnectorPort → script (scrubbed env, APPLICATION_CONFIG, timeout kills)
├── state/fs.rs # StateStorePort → <state.dir>/<application>/<kind>.yaml
├── notify/http.rs # HttpSenderPort → reqwest (no redirects followed)
├── webhooks/http.rs # HttpSenderPort → reqwest (no redirects followed)
├── git/, secrets/, directory/, config/, python.rs, process_env.rs
tests/ # integration tests; tests/connectors/ holds test connector scripts
# (kv.py + the SDK, copied from unified-connectors)
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ network, and a change made by hand on a system shows up as drift.
- **Self-describing connectors**: a script says what it manages, each type's key and what goes first
- **One application, one system**: its address and credentials live in config, never in git
- **Run history**: which commit was applied, when, and the result of every operation
- **Notifications**: drift, applied commits and failures to a webhook or an Ascender or AWX job
- **Webhooks**: drift, applied commits and failures to a webhook or an Ascender or AWX job
- **Config as code**: one item per file, any folders; `name` is the identity
- **Strict validation**: a typo in desired state or config fails before any system is touched
- **Web UI and LDAP sign-in**: the same UI family and sign-in as unified-api, on its own address
Expand All @@ -42,7 +42,7 @@ network, and a change made by hand on a system shows up as drift.
| [How it works](docs/how-it-works.md) | The reconcile loop: pull, list, diff, apply, and what each status means |
| [Connectors](docs/connectors.md) | The script contract, the Python SDK, and writing a connector |
| [Configuration](docs/configuration.md) | Every YAML file field by field, and desired-state files |
| [Notifications](docs/notifications.md) | Drift, syncs and failures to a webhook or an Ascender or AWX job template |
| [Webhooks](docs/webhooks.md) | Drift, syncs and failures to a webhook or an Ascender or AWX job template |
| [API](docs/api.md) | All routes with authentication and examples |
| [Architecture](docs/architecture.md) | The layers, the dependency rule, and what is shared with unified-api |
| [Configuration API](docs/config-api.md) | Pushing the config directory over HTTP and reloading it live |
Expand Down
1 change: 0 additions & 1 deletion deny.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ allow = [
"ISC",
"Zlib",
"Unicode-3.0",
"MPL-2.0",
"CDLA-Permissive-2.0",
]

Expand Down
5 changes: 3 additions & 2 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ session also need its `X-CSRF-Token`). Every failure is `{"error": "..."}`.
| `/api/v1/applications/{id}/state/{kind}` | GET | key granted the app | The system's current settings, as of its last check |
| `/api/v1/search?q=` | GET | any key (its apps) | Find an object by key or value: its application, kind, whether git declares it |
| `/api/v1/connectors` | GET | admin | Connectors: script, project, timeout, who uses them |
| `/api/v1/notifications` | GET | admin | Notifications: events, destination, last send |
| `/api/v1/notifications/{id}/test` | POST | admin | Send a test message now, once; answers the outcome |
| `/api/v1/webhooks` | GET | admin | Webhooks: events, destination, last send |
| `/api/v1/webhooks/{id}` | GET | admin | One webhook and its last 50 sends |
| `/api/v1/webhooks/{id}/test` | POST | admin | Send a test message now, once; answers the outcome |
| `/api/v1/projects` | GET | admin | Git checkouts, their health, what uses them |
| `/api/v1/projects/{id}/sync` | POST | admin | Pull a project now |
| `/api/v1/credentials` | GET | admin | Credentials: where from, whether they resolve |
Expand Down
18 changes: 9 additions & 9 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ as startup does, and exits.
│ └── cred-isilon.yaml
├── api_keys/
│ └── key-pipeline.yaml
└── notifications/
└── ntf-failures.yaml
└── webhooks/
└── wh-failures.yaml
```

| Top-level key | Holds |
Expand All @@ -33,7 +33,7 @@ as startup does, and exits.
| `projects` | Git repositories: desired state, and connector scripts |
| `credentials` | Where each credential's secrets come from (never the values) |
| `api_keys` | API keys by name and role (the values come from env vars) |
| `notifications` | What runs report, and where: webhooks, Ascender and AWX job templates |
| `webhooks` | What runs report, and where: webhooks, Ascender and AWX job templates |

- **The key says what an item is, never the folder.** A file in `connectors/` holding `applications:` is
read as an application.
Expand Down Expand Up @@ -172,17 +172,17 @@ api_keys:
`UNIFIED_GITOPS_KEY`, if set, is one more admin key. With no keys at all the API is open, which is
logged loudly at startup.

## notifications
## webhooks

Which events, from which applications, go where. The full reference is [notifications.md](notifications.md):
Which events, from which applications, go where. The full reference is [webhooks.md](webhooks.md):

```yaml
# notifications/ntf-ascender-drift.yaml
notifications:
- name: ntf-ascender-drift
# webhooks/wh-ascender-drift.yaml
webhooks:
- name: wh-ascender-drift
type: ascender # webhook | ascender | awx
events: [drift_detected]
applications: [isilon-prod] # empty = every application
applications: [isilon-prod] # or all; left out or [] = none
ascender:
url: "https://ascender.example.com"
job_template: 123
Expand Down
6 changes: 4 additions & 2 deletions docs/observability.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ stops running pushes nothing, so only a scrape-time gauge shows the silence.
| `unified_gitops_project_sync_last_success_age_seconds` | project | Seconds since the last good pull |
| `unified_gitops_connector_calls_total` | application, connector, command, outcome | Calls to the systems: `list` reads, `apply` writes, `describe` starts a run |
| `unified_gitops_connector_call_duration_seconds` | application, connector, command | How long each call to a system took (histogram) |
| `unified_gitops_notifications_total` | notification, event, outcome | Messages sent (`success`), failed after retries (`error`), or dropped by a full queue |
| `unified_gitops_notification_duration_seconds` | notification | How long a send took, retries included (histogram) |
| `unified_gitops_git_requests_total` | project, operation, outcome | Requests to git servers: a `clone` or a `pull` per project, the `fetch` a rollback makes |
| `unified_gitops_git_request_duration_seconds` | project, operation | How long each request to a git server took (histogram) |
| `unified_gitops_webhooks_total` | webhook, event, outcome | Messages sent (`success`), failed after retries (`error`), or dropped by a full queue |
| `unified_gitops_webhook_duration_seconds` | webhook | How long a send took, retries included (histogram) |
| `unified_gitops_http_requests_total` | method, path, status | Requests, by matched route |
| `unified_gitops_http_request_duration_seconds` | method, path | Latency histogram |
| `unified_gitops_config_generation` | | Bumped by every applied reload |
Expand Down
Loading
Loading