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
20 changes: 20 additions & 0 deletions .claude/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"permissions": {
"allow": [
"WebSearch",
"WebFetch(domain:github.com)",
"WebFetch(domain:raw.githubusercontent.com)",
"Bash(gh issue *)",
"Bash(gh pr *)",
"Bash(gh release *)",
"Bash(git stash *)",
"Bash(git fetch *)",
"Bash(docker compose *)",
"Bash(docker build *)",
"Bash(docker run *)",
"Bash(python -c *)",
"Bash(pip install *)",
"Bash(ruff *)"
]
}
}
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ config.py
*.pid
*.sock
config/
config-dev/
images/
docker-compose.override.yml
docker-compose-dev.yml

# Virtual environments
venv/
Expand Down
115 changes: 115 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# Changelog

All notable changes to this project will be documented in this file.

The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

---

## [0.3.0] — 2026-05-12

### Added
- Shared logging setup module consumed by `main.py` and all notifier
modules. No more duplicated handler configuration across files.
- Shared retry helper. DNS notifier now retries with backoff using the
same policy as the STD notifier.
- Common kwargs contract: every notifier module's `register()`
receives a documented base set of kwargs (`container_name`,
`container_id`, `docker_host`, `docker_status`, `image_name`,
`stack_name`, `started_at`, `action`). Notifier-specific extras
are layered on top.
- Boolean and integer coercion for STD health-check and sort-priority
labels at the notifier boundary. `dockernotifier.std.internal.health`
and `dockernotifier.std.external.health` label values are converted
from string to bool, and `dockernotifier.std.sort.priority` is
converted from string to int, before being sent to STD.
- PRD §3.3 documents the notifier module contract.
- `notifiers/_template.py` reference implementation for adding new
notifier targets.

### Changed
- STD notifier emits canonical key names (`host`, `group_name`,
`internal_health_check_enabled`, `image_icon`, `sort_priority`, ...)
and posts to `/api/v1/register` instead of `/api/register`. The
notifier translates legacy label-derived keys to canonical names
client-side; unknown keys are dropped before sending so STD's
strict pydantic validator does not reject the request.
- Stack-name resolution: when `com.docker.compose.project` is missing,
the notifier passes `stack_name=None` rather than splitting the
container name on `_`.
- Replaced per-notifier `DNS_LOG_TO_STDOUT` and `STD_LOG_TO_STDOUT`
env vars with a single `NOTIFIER_LOG_TO_STDOUT`. Default unchanged
(console on). Operators who previously set `DNS_LOG_TO_STDOUT=0` or
`STD_LOG_TO_STDOUT=0` should switch to `NOTIFIER_LOG_TO_STDOUT=0`.
- DNS notifier now raises on HTTP 4xx/5xx responses from Technitium
and retries transient failures. Previously HTTP errors were silently
logged as successes.
- DNS notifier's "triggered for" log line now reports the actual Docker
action (e.g. `start`, `boot`, `refresh`) instead of the literal string
`"event"`. Operators with log filters or alerts that grep specifically
for `due to "event"` will need to update them.

### Removed
- Unused `trigger_reason` parameter from the DNS notifier's `register()`
signature.
- Inline `watched_actions` literal in `main()`; the Docker event loop
now reads from the module-level `WATCHED_DOCKER_ACTIONS` constant.

### Fixed
- Real Docker actions and synthetic actions (`boot`, `refresh`) are now
declared as separate constants in `main.py` (`WATCHED_DOCKER_ACTIONS`
and `SYNTHETIC_ACTIONS`) and composed into `NOTIFIER_TRIGGERS`. No
behavior change — clarifies what the notifier subscribes to from
Docker vs. what it injects internally.
- Misleading comment on `STD_REFRESH_SECONDS` ("60 minutes" → "60
seconds").

---

## [0.2.3] — 2026-XX-XX

Released. Detailed notes not retained.

## [0.2.2] — 2026-XX-XX
Released.

## [0.2.1] — 2026-XX-XX
Released.

## [0.2.0] — 2026-XX-XX
Released.

## [0.1.5] — 2026-XX-XX
Released.

## [0.1.4] — 2026-XX-XX
Released.

## [0.1.3] — 2026-XX-XX
Released.

## [0.1.2] — 2026-XX-XX
Released.

## [0.1.1] — 2026-XX-XX
Released.

## [0.1.0] — 2026-XX-XX

Initial public release.

[Unreleased]: https://github.com/crzykidd/docker-api-notifier/compare/v0.3.0...HEAD
[0.3.0]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.3.0
[0.2.3]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.2.3
[0.2.2]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.2.2
[0.2.1]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.2.1
[0.2.0]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.2.0
[0.1.5]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.5
[0.1.4]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.4
[0.1.3]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.3
[0.1.2]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.2
[0.1.1]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.1
[0.1.0]: https://github.com/crzykidd/docker-api-notifier/releases/tag/v0.1.0
125 changes: 125 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# docker-api-notifier — Claude Code Instructions

## Always

- After any change that affects architecture, dependencies, supported
notifier targets, or the wire contract with downstream consumers,
update `docs/PRD.md` and `README.md` accordingly.
- After completing a phase, update `README.md` with what has been built.
- Never leave PRD or README out of sync with the codebase.

## Commit style

- `feat:` new feature
- `chore:` config, tooling, maintenance
- `fix:` bug fix
- `docs:` documentation only changes
- `refactor:` non-behavior-changing internal cleanup

## Stack

- Python 3.11
- `docker` (Docker SDK for Python) — Docker event subscription
- `requests` — DNS notifier HTTP calls
- `tenacity` — retry-with-backoff for downstream notifier calls
- Container: single-image Docker, no compose orchestration of its own
- `Dockerfile` — production image
- `docker-compose.yml` — example deployment

## Configuration

- All configuration is via environment variables. There is no config file.
- Per-container behavior comes from `dockernotifier.*` labels on the
containers being watched.
- Full ENV reference: `README.md` → Environment Variables section.

## Project Documentation

- Full PRD is at `docs/PRD.md` — read this before starting any phase.
- Project history (structural events, milestones) at `docs/HISTORY.md`.
- `README.md` at the root — keep it current with what has been built.
- Commit doc updates in the same commit as the code changes they describe.

## Build Status

Current shipped release: **v0.2.3** (latest tag on `main`)

Next release target: **v0.3.0** — cleanup release. Cannot ship until
**STD v0.5.0** is released (v0.3.0 emits canonical keys against
`/api/v1/register`, which STD v0.5.0 introduces).

- Phase 1 — Documentation baseline: IN PROGRESS
- Phase 2 — Logging consolidation: NOT STARTED
- Phase 3 — Shared retry helper: NOT STARTED
- Phase 4 — Stack-name fallback fix: NOT STARTED
- Phase 5 — `watched_actions` / `NOTIFIER_TRIGGERS` cleanup: NOT STARTED
- Phase 6 — Drop `trigger_reason` param: NOT STARTED
- Phase 7 — Switch to `/api/v1/register` + canonical keys: NOT STARTED
*(blocked until STD v0.5.0 is released)*

## Git Workflow

- Work on `dev` branch for all changes.
- Push to `dev` freely — builds `:dev` images.
- When ready to release:
- Create PR `dev` → `main` on GitHub.
- Merge after CI passes.
- Tag release from `main` via the GitHub Releases UI.
- Never push directly to `main`.
- Branch protection on `main` requires PR + green build, blocks
force-push and deletion.
- Do NOT add `Co-authored-by` to commits.

## Release Process

- Push to `dev` — GitHub Actions builds and pushes `:dev` and
`:sha-<short>` images to Docker Hub.
- Push to `main` (via PR from `dev`) — GitHub Actions builds and pushes
`:latest` and `:sha-<short>` images.
- When the build is stable and ready to ship:
1. GitHub → Releases → Draft new release.
2. Create a new tag in `vX.Y.Z` format.
3. Publish the release.
4. GitHub Actions builds and pushes `:latest`, `:X.Y.Z`, and `:X` to
Docker Hub.

## Changelog Process

- `CHANGELOG.md` lives at repo root.
- Follow Keep a Changelog format (keepachangelog.com).
- Add entries to `[Unreleased]` section as features are built.
- User-facing language only — describe what changed for the operator.
- Categories: Added, Changed, Fixed, Security, Deprecated, Removed.
- On release: move `[Unreleased]` to a new version section dated today.
- GitHub release body = that version's CHANGELOG section (single source
of truth).

## Cross-Repo Coordination

This project is paired with
[service-tracker-dashboard](https://github.com/crzykidd/service-tracker-dashboard).
The contract is:

- **STD** owns the wire contract for the register endpoint.
- **Notifier** is a producer — it sends what STD documents.
- Wire-format changes start in STD. The notifier follows.
- For v0.3.0 specifically: STD v0.5.0 must ship first; this notifier
release switches to canonical keys + `/api/v1/register` after.

## Notifier Module Conventions

The notifier module contract is documented in `docs/PRD.md` §3.3.
A reference template is at `notifiers/_template.py`.

In short: one module per downstream system under `notifiers/`,
exposing `register(**kwargs)`. Modules consume shared logging
(`logging_setup`) and shared retry (`retry`). They own their own
auth and wire format.

When adding a new notifier: copy `notifiers/_template.py`, replace
the placeholders, wire it into `main.py`'s `NOTIFIER_TRIGGERS` and
dispatch, document env vars and labels in `README.md`.

## Git Rules

- Do NOT add `Co-authored-by` lines to commit messages.
Loading
Loading