Repository navigation
Releases: evsinev/deploy
Release list
1.0-29
What's Changed
Full Changelog: 1.0-28...1.0-29
1.0-28 — Restart a service without starting a process
A service is restarted without starting a process
Asking a supervisor to reload a service used to run the svc program. A host watching for unexpected launches
inside a container reported every deploy — both the program itself and jspawnhelper, the helper the JVM starts
in order to launch anything at all.
The command is now written straight to the supervisor's control channel: the named pipe at
<service>/supervise/control, one letter per command (h for a reload, t for a termination). That is exactly
what svc does, and the supervisor still does the signalling. Nothing is executed, so those reports stop.
A running supervisor holds the reading end of that pipe open, so the write happens at once. Nothing reading it
means the supervisor is not running: the step says so rather than waiting, and the command is not delivered
later when the supervisor comes back — a command arriving at an arbitrary later moment would be worse than none.
Also in this release
signalnow takestermas well ashup.- A supervisor with no control channel is still supported: set
serviceControl: programin the agent policy and
the step runsserviceControlBinarywith a fixed argument list, as before. - The agent no longer needs the control program mounted into its container.
Upgrading
Nothing to change. An agent policy that still names serviceControlBinary keeps working; the setting is simply
unused unless serviceControl: program is set. Leaving the control program mounted for a release or two keeps
that fallback available.
See Deploy steps for the step and the policy, and the
changelog for the releases before this one.
1.0-27
What's Changed
Full Changelog: 1.0-26...1.0-27
1.0-26
What's Changed
Full Changelog: 1.0-25...1.0-26
1.0-25 — Dashboard live streams behind nginx
Dashboard live streams survive a reverse proxy
The dashboard log tails went silent behind nginx and filled its error log with
upstream timed out (110: Connection timed out) while reading response header from upstream,
request: "GET /deploy/dashboard/agentlog/events"
No configuration change is needed. Upgrading the server jar is enough; nginx defaults
(proxy_read_timeout 60s, proxy_buffering on) now work as they are.
What was wrong
/deploy/dashboard/agentlog/events and /deploy/dashboard/log/events staged their response headers
and then wrote nothing until a new log line appeared. Vert.x flushes the status line and the headers
together with the first body write, so on a quiet server not a single byte left the socket. nginx
waited out its proxy_read_timeout and dropped the connection while still reading the response
header, the browser's EventSource reconnected, and the loop repeated for as long as the dashboard
stayed open. The Live screen was never affected: it pushes a full card snapshot on connect and
on every tick.
What changed
All three streams ({DASHBOARD_PATH}/events, /log/events, /agentlog/events) now:
- open with a
: connectedcomment, which flushes the status line and headers immediately; - send a
: keepalivecomment after 15 s of silence, four times inside the 60 s nginx default, so an
idle tail never trips a proxy idle timeout; - set
X-Accel-Buffering: no, so nginx streams the events through instead of buffering them.
SSE comments are ignored by EventSource, so the vendored htmx client is unchanged.
Behind a second proxy
If the deploy server sits behind an outer proxy as well, that one must also pass the stream through
unbuffered — it either honours X-Accel-Buffering or needs proxy_buffering off. Otherwise the
events still arrive, but in bursts. A minimal location:
location /deploy {
proxy_pass http://127.0.0.1:9090;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_buffering off;
}See Behind a reverse proxy
in the docs.
Verification
An integration test now asserts that both tail endpoints answer 200 text/event-stream with
X-Accel-Buffering: no and deliver their opening comment while the logs are still empty — the exact
case that used to hang until the proxy timed out.
1.0-24 — Deploy review webhook
Deploy review webhook at deploy start
Notifies an external service the moment a deploy starts — the same moment as the 🛫 Telegram message
— so a release can be analysed while it is still being rolled out. The analysis on the receiving side
takes ~10 minutes, which is why the call happens at takeoff rather than after the rollout.
Disabled by default. Nothing changes on an existing installation until DEPLOY_REVIEW_ENABLED=true
is set, and no other behaviour was modified in this release.
The notification
POST <DEPLOY_REVIEW_URL>
Authorization: Bearer <DEPLOY_REVIEW_TOKEN>
Content-Type: application/json
{"project":"payneteasy/paynet","app":"ams2-paynet-proc","instance":"AMS-2",
"old_version":"3.36.16-117","new_version":"3.36.16-118","deployed_at":"2026-08-11T15:07:39Z"}
deployed_at is stamped when the notification is enqueued, so a retry or a replay after a restart
still reports the real deploy moment rather than the time of the retry.
Configuration
A new independent config interface, shown (with the token masked) on the dashboard Config screen:
| Env var | Default | Meaning |
|---|---|---|
DEPLOY_REVIEW_ENABLED |
false |
Enable the deploy-start webhook. |
DEPLOY_REVIEW_URL |
"" |
Endpoint the notification is posted to. |
DEPLOY_REVIEW_TOKEN |
"" |
Bearer token (secret). |
DEPLOY_REVIEW_TIMEOUT_MS |
20000 |
Connect/read timeout (ms). |
Enabling the webhook without a URL fails fast at startup instead of silently doing nothing. The token
is read from the environment only — it is never logged and never written to the spool.
New alias fields
project, app and instance name the deployed thing for the receiving service (gitlabProjectId
is a numeric id, and there was no notion of an instance before). They are three new optional fields
in the alias diff: block:
diff:
enabled: true
versionUrl: http://ams2-app:8080/version
gitlabProjectId: 114
agent: ams2-app
newVersionArg: 1
project: payneteasy/paynet # new — GitLab project path
app: ams2-paynet-proc # new — optional, defaults to the alias name
instance: AMS-2 # new — target instanceThe webhook reuses the versions the diff: block already resolves, so it is sent only for aliases
with diff.enabled: true that set project and instance; anything else is skipped with a log line.
The plain ?command=run path never reads the old version, so it sends nothing.
Delivery
A third durable spool alongside redmine and telegram:
- the request body is written to
QUEUE_DIR/deploy-reviewbefore the call, removed after success, and
replayed on restart, so a notification survives a crash or an unreachable receiver; - delivery is at-least-once, which is safe because the receiver dedupes by version;
5xxand network failures are retried with backoff, then dead-lettered;4xxanswers (bad token,
bad version format) are dead-lettered immediately rather than burning ten attempts on a rejection
that cannot succeed;- visible as
queue="deploy-review"in the Prometheus queue metrics and as a row on the dashboard
Delivery card; - enqueueing cannot abort a deploy — any failure there is logged and the rollout continues.
Docs
Upgrading
Drop in the new deploy-server-1.0-24.jar; no configuration change is required. To switch the
webhook on: set the four DEPLOY_REVIEW_* variables and add project / instance to the aliases
that should report. The agent jar is unchanged in behaviour and can be upgraded independently.
1.0-23
What's new
Group diff commit messages by date in Telegram and Redmine
When a deploy is triggered, the commit list posted to Telegram and added as a Redmine issue comment is now grouped by commit date instead of repeating the date on every line.
- Telegram — each date appears once as a header line, with its commits listed as bullets underneath (newest day first).
- Redmine — the comment table now has just
Issue | Subjectcolumns, with each date rendered as a colspan header row (|\2. *DATE* |). - Undated commits are grouped under a
(no date)header, shown last. - Long Telegram messages still split at the 4000-char limit, and the date header is re-emitted at the top of each continuation message so bullets stay under their date.
1.0-22
What's new
Keep the Delivery card visible as agent logs grow
Fixes a layout bug on the Live dashboard where the Delivery card (Telegram/Redmine queue depths and send-latency percentiles) could be squeezed down to just its header as the agent-log stream accumulated, making the card look empty.
- The Delivery card now keeps its full height and the agent-log pane scrolls internally.
- This is a dashboard-only (CSS) fix — no server behavior or configuration changed. The card content was never wrong; it was simply being clipped by the layout.
See the dashboard documentation: https://evsinev.github.io/deploy/guides/dashboard/
1.0-21
What's Changed
Dependency maintenance release — the first batch of Dependabot updates.
Dependencies
- Maven minor/patch group (20 updates), including Jackson 2.22.1, Logback 1.6.0, SnakeYAML 2.6, Mockito 5.23, Gson 2.14, Immutables 2.12, Lombok, and the Maven build plugins.
- Guava 33.6.0-jre, JetBrains annotations 26.1.0, and the internal logging-extensions 1.0-4.
CI
actions/checkoutbumped to v7 andactions/setup-javato v5.
Notes
- Micrometer is pinned below 1.13 (updated to 1.12.13) so the
io.micrometer.prometheus.*package it still ships stays available. - The Vert.x 5 upgrade was intentionally deferred — it requires a code migration (breaking
deployVerticle/ Future-based API changes).
Full Changelog: 1.0-20...1.0-21
1.0-20
What's Changed
Security and maintenance:
- Bumped vulnerable dependencies to patched versions (Logback, Vert.x, Jackson, Guava, SnakeYAML) and removed the obsolete OWASP dependency-check plugin.
- Added Dependabot configuration for Maven and GitHub Actions.
- Enriched the GitLab compare test mock so the diff table renders the Date and Issue columns.
Full Changelog: 1.0-19...1.0-20