Commit Graph
106 Commits
Author SHA1 Message Date
shcizo 92e7646221 fix(master): say why a pinned pick fails on a protocol 2 agent (#9) 2026-10-13 08:25:21 +02:00
shcizo 2e87d98012 docs: registry polling, version history and phase 4 plan (#9) 2026-10-13 08:16:47 +02:00
shcizo 687e411052 test(e2e): pick a pinned version and poll an auto service end to end (#9) 2026-10-13 08:15:29 +02:00
shcizo 2390b6151e feat(master): POLL_INTERVAL, poller wiring and version picker in the UI (#9) 2026-10-13 08:14:43 +02:00
shcizo c6ea2d3710 feat(master): registry digest lookup and polling loop (#9) 2026-10-13 08:11:37 +02:00
shcizo d0726ca992 feat(master,agent): deploy digest-pinned refs and route them to protocol 3 agents (#9) 2026-10-13 08:07:45 +02:00
shcizo af61f17dee feat(master): record image versions and track poll suggestions in the store (#9) 2026-10-13 08:05:21 +02:00
shcizo 41a619b316 feat: master/agent phase 3 — webhook and auto mode (#8) (#22)
Docker Build / docker (push) Successful in 38s
## Summary
- `POST /update` on the master (outside OIDC, bearer `UPDATER_API_KEY`; unset → 503). Matches `image` against `image_repo` on all agents, marks `available_*` on every match, starts webhook-triggered jobs for `auto` services targeting `<image_repo>:<tag>` (followed tag when no tag is given), and waits for them up to `UPDATE_TIMEOUT` (default 5m). 404 on no match, 500 if any auto job failed or timed out, otherwise 200.
- Manual/auto toggle per service on the overview and service page (`POST /services/{id}/mode`, CSRF); auto is blocked for self, `build:` and container services with the reason shown. "Update available" badge and an "Available" row.
- `FinishJob` clears `available_*` only when the successful job was created for that exact ref, after it was reported. Migration `0003_webhook.sql`, phase-3 plan doc, README / gitea-action README / CLAUDE.md / deploy example updated. `action.yml` unchanged.

Closes #8

## Behaviour changes for CI
- Mixed results now return 500 (the old 207 is gone); no match returns 404 instead of 200.
- With a `tag`, Compose services get pinned to `<image_repo>:<tag>` via `compose.override.yaml`; the tag must be a pushed tag.
- `busy` (job already active) and `refused` (not updatable) are reported but return 200.
- The reverse proxy read timeout must exceed `UPDATE_TIMEOUT`.

## Test plan
- [x] `go test ./...` and `go test -race ./internal/agent/... ./internal/master/... ./internal/e2e/`
- [x] `go test -tags integration ./internal/master/store/` against throwaway Postgres
- [x] UI verified in browser (mode toggle, disabled reason, badge via SSE, Available row)
- [ ] Manual: webhook with manual service → `marked` + badge
- [ ] Manual: webhook with auto service → waits, `succeeded`, badge cleared, override pinned
- [ ] Manual: wrong token 401, unknown image 404, offline agent 500
- [ ] Gitea action pointed at the master's `/update` in a real CI run

Reviewed-on: #22
v0.5.0
2026-10-12 20:03:22 +00:00
shcizo 417ef315c2 Merge pull request 'feat: master/agent phase 2 — jobs and manual update (#7)' (#20) from feat/master-agent-jobs-7 into main
Docker Build / docker (push) Successful in 40s
Reviewed-on: #20
v0.4.0
2026-10-12 17:58:48 +00:00
shcizo ec96d5687d fix(agent): reset per-service warnings after a successful build check (#7) 2026-10-12 19:45:29 +02:00
shcizo c5dba96cf8 fix(agent): list all compose profiles and fail closed on unknown services (#7) 2026-10-12 19:38:07 +02:00
shcizo 27c4200dda feat(agent): report and refuse Compose services built from source; honour --env-file (#7) 2026-10-12 19:32:05 +02:00
shcizo 69ef55837e docs: compose environment and built-from-source services (#7) 2026-10-12 19:30:38 +02:00
shcizo 3d3dfb47e6 feat(master): show built-from-source services but never update them (#7) 2026-10-12 19:30:38 +02:00
shcizo c3bd4ca1ed test(master): CreateJob waits for a concurrent revoke (#7) 2026-10-12 19:29:43 +02:00
shcizo 91cb027ef6 feat(protocol): Service.Built marks Compose services built from source (#7) 2026-10-12 19:29:18 +02:00
shcizo 7e23e1843f docs: spell out the upgrade risk and the bare-image rule (#7) 2026-10-12 19:15:24 +02:00
shcizo 961ddd275c test(master): wait for the replacement connection to register (#7) 2026-10-12 19:15:24 +02:00
shcizo caa6c81716 fix(master): treat a bare image as :latest and handle a revoked agent in Trigger (#7) 2026-10-12 19:14:59 +02:00
shcizo c09e774d74 fix(master): refuse jobs for revoked agents, signal revoked jobs, agent start time wins (#7) 2026-10-12 19:14:32 +02:00
shcizo 93ba6915b9 fix(agent): minimal env and explicit project dir for compose, resolve every config file's symlinks (#7) 2026-10-12 19:13:25 +02:00
shcizo 8b2c10cc05 fix(web): job log polls while active, one service history limit (#7) 2026-10-12 19:13:01 +02:00
shcizo 88d5507217 docs: describe Swarm registry auth (#7) 2026-10-12 18:50:12 +02:00
shcizo b7e25bb1fb docs: master/agent phase 2 — jobs and manual update (#7) 2026-10-12 18:48:53 +02:00
shcizo b392e11b37 test: jobs end to end over pinned TLS (#7) 2026-10-12 18:48:06 +02:00
shcizo 55f8021b0a build: agent is the image's default entrypoint; drop the old server examples (#7) 2026-10-12 18:45:47 +02:00
shcizo 601c6da0d4 feat(agent): run jobs from the master and resend results until acked (#7) 2026-10-12 18:45:44 +02:00
shcizo e313365686 feat(agent): job runner, compose override executor and swarm executor (#7) 2026-10-12 18:45:44 +02:00
shcizo 32c30194c4 feat(master): wire jobs into the master (#7) 2026-10-12 18:43:20 +02:00
shcizo 02de0b8cf3 feat(master): start manual update jobs with self-protection (#7) 2026-10-12 18:43:11 +02:00
shcizo 68e5c33722 feat(master): route jobs to agents and reconcile them on reconnect (#7) 2026-10-12 18:42:30 +02:00
shcizo 574f425267 feat(web): service page, manual update, jobs list and live job log (#7)
Also publishes the jobs topic on agent revoke and updates the agent
snippet to mount stacks read-write at the same path.
2026-10-12 18:41:46 +02:00
shcizo 9d3a6f808c feat(master): store update jobs (#7) 2026-10-12 18:40:48 +02:00
shcizo e2b73dfd81 feat(agent): UPDATE_TIMEOUT and DOCKER_CONFIG settings (#7) 2026-10-12 18:40:15 +02:00
shcizo c9c4e0cadb refactor(web): web.New takes the jobs service (#7) 2026-10-12 18:39:57 +02:00
shcizo 9e09de0a16 feat(protocol): job messages, protocol version and job model (#7) 2026-10-12 18:38:39 +02:00
shcizo eb41967cd1 docs: plan revisions after review (#7) 2026-10-12 18:37:28 +02:00
shcizo 7e55ec3b33 docs: implementation plan for master/agent phase 2 (jobs) (#7) 2026-10-12 17:13:15 +02:00
shcizo 3090b6d4f0 Merge pull request 'feat: master/agent phase 1 — live inventory (#6)' (#19) from feat/master-agent-inventory-6 into main
Docker Build / docker (push) Successful in 58s
v0.3.0
2026-10-12 13:50:09 +00:00
shcizo 2fe9b5ba0d fix(master): block inventory writes from revoked agents (#6)
ApplySnapshot and UpsertService now take a FOR SHARE lock on the agent's
row and refuse with model.ErrRevoked when it is revoked. RevokeAgent's
UPDATE waits on that lock, so an in-flight snapshot or upsert can no
longer bring a revoked agent's services back after the revoke cleanup.
2026-10-12 15:18:51 +02:00
shcizo 0e9e34db06 fix: address final review findings for master/agent phase 1 (#6)
- inventory: resolve the image reference via ContainerInspect when a moved
  tag makes ContainerList report the image ID
- store: allow reusing a revoked agent's name (partial unique index) and
  mark the revoked agent's compose/container services removed
- web: publish a services event on revoke; no-store on the one-time token page
- webauth: reject empty OIDC state; accept the CSRF form token from the body only
- agent conn: bound the WebSocket handshake to 30s
- hub: log agent_replaced when a connection replaces an older one
2026-10-12 15:16:29 +02:00
shcizo 4f092eaf79 docs: document master/agent phase 1 and add master stack example 2026-10-12 15:04:43 +02:00
shcizo 05610391e3 test: agent to master inventory over pinned TLS end to end 2026-10-12 15:02:50 +02:00
shcizo e8f7cb3378 feat(master): add updater-master binary wiring store, hub, auth and UI 2026-10-12 15:01:11 +02:00
shcizo a596d67728 feat(master): htmx UI with live service overview and agent management
Vendored static assets (sha256):
e209dda5c8235479f3166defc7750e1dbcd5a5c1808b7792fc2e6733768fb447  htmx.min.js (htmx.org@2.0.4)
83eca6fa0611fe2b0bf1700b424b88b5eced38ef448ef9760a2ea08fbc875611  htmx-ext-sse.js (htmx-ext-sse@2.2.2)
2026-10-12 14:57:23 +02:00
shcizo b4894db6d7 feat(master): OIDC login with group check, sessions and CSRF protection 2026-10-12 14:54:11 +02:00
shcizo 049324b2f4 fix(master): recheck revocation after register, reject duplicate hello 2026-10-12 14:52:24 +02:00
shcizo 75e28262f8 feat(master): agent hub that authenticates agents and stores their inventory 2026-10-12 14:50:22 +02:00
shcizo 5d75f9a7da feat(master): in-process broker for live UI change signals 2026-10-12 14:48:03 +02:00
shcizo 8a1fb45971 feat(master): store service inventory snapshots and web sessions 2026-10-12 14:45:46 +02:00