New Check now button on the service page (POST /services/{id}/poll). It runs the poller's check for that service only: digest HEAD, auto job with the usual guards (drift, last_tag_digest, desired_ref), and the newer-tag suggestion. The request waits for the registry, then redirects with 303 to the service page.
Cycle's body after ListServices has moved unchanged into pollServices. PollService(ctx, id) calls it with a list that holds only that service, so only that service gets new values. The existing Cycle tests pass unchanged.
A registry error is not an HTTP error. It is saved as last_poll_error and shows up in the Polling row. A service that is not polled (no tag, built from source, no digest) gets a disabled button with the reason below it, the same way AutoBlocked works, plus a 409 if someone posts anyway.
If the request context is cancelled (client gone, or master shutting down), the handler still answers with a 303 instead of an empty 200.
go test ./... and go test -race ./internal/master/...
TestPollService (table: manual/auto, drift, last_tag_digest, desired_ref, registry error, cleared error, SkipReason, unknown/removed, comparable/non-comparable tag), plus tests for only-this-service and cancellation
Handler tests: 303, 404, 400, 409, and rendering of the enabled and disabled button
CSRF is not covered by the handler tests (the fake middleware skips it). It is enforced by webauth.Require for every POST, and the new route goes through route(...).
Manual: click Check now on a polled service, and look at a service without a tag (disabled button). This has not been checked in a browser, because there is no local OIDC environment.
Note: TestCycleStopsOnCancel sometimes fails on main too (reproduced with -count=30). It is unrelated to this change and should get its own issue.
## Summary
- New **Check now** button on the service page (`POST /services/{id}/poll`). It runs the poller's check for that service only: digest HEAD, auto job with the usual guards (drift, `last_tag_digest`, `desired_ref`), and the newer-tag suggestion. The request waits for the registry, then redirects with 303 to the service page.
- `Cycle`'s body after `ListServices` has moved unchanged into `pollServices`. `PollService(ctx, id)` calls it with a list that holds only that service, so only that service gets new values. The existing `Cycle` tests pass unchanged.
- A registry error is not an HTTP error. It is saved as `last_poll_error` and shows up in the Polling row. A service that is not polled (no tag, built from source, no digest) gets a disabled button with the reason below it, the same way `AutoBlocked` works, plus a 409 if someone posts anyway.
- If the request context is cancelled (client gone, or master shutting down), the handler still answers with a 303 instead of an empty 200.
Closes #35
## Test plan
- [x] `go test ./...` and `go test -race ./internal/master/...`
- [x] `TestPollService` (table: manual/auto, drift, `last_tag_digest`, `desired_ref`, registry error, cleared error, SkipReason, unknown/removed, comparable/non-comparable tag), plus tests for only-this-service and cancellation
- [x] Handler tests: 303, 404, 400, 409, and rendering of the enabled and disabled button
- [ ] CSRF is not covered by the handler tests (the fake middleware skips it). It is enforced by `webauth.Require` for every POST, and the new route goes through `route(...)`.
- [ ] Manual: click Check now on a polled service, and look at a service without a tag (disabled button). This has not been checked in a browser, because there is no local OIDC environment.
Note: `TestCycleStopsOnCancel` sometimes fails on `main` too (reproduced with `-count=30`). It is unrelated to this change and should get its own issue.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
POST /services/{id}/poll). It runs the poller's check for that service only: digest HEAD, auto job with the usual guards (drift,last_tag_digest,desired_ref), and the newer-tag suggestion. The request waits for the registry, then redirects with 303 to the service page.Cycle's body afterListServiceshas moved unchanged intopollServices.PollService(ctx, id)calls it with a list that holds only that service, so only that service gets new values. The existingCycletests pass unchanged.last_poll_errorand shows up in the Polling row. A service that is not polled (no tag, built from source, no digest) gets a disabled button with the reason below it, the same wayAutoBlockedworks, plus a 409 if someone posts anyway.Closes #35
Test plan
go test ./...andgo test -race ./internal/master/...TestPollService(table: manual/auto, drift,last_tag_digest,desired_ref, registry error, cleared error, SkipReason, unknown/removed, comparable/non-comparable tag), plus tests for only-this-service and cancellationwebauth.Requirefor every POST, and the new route goes throughroute(...).Note:
TestCycleStopsOnCancelsometimes fails onmaintoo (reproduced with-count=30). It is unrelated to this change and should get its own issue.