The browser uses only the /app/{key} WebSocket. Laravel sends events to
Reverb over 127.0.0.1, so the generated Traefik and Caddy configs no longer
route /apps to port 6001, and the WebSocket rule only matches /app/.
Closes#12390
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Save build_server_id as soon as a build server is selected, so the cancel
cleanup finds the helper container on the build server. Let the final
helper stop run after a cancel.
Closes#12383
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An invited user who set a password with Forgot password kept the forced
reset flag. A re-invite then replaced the password, and a revoked or
expired invitation deleted the account.
Re-inviting an email after its invitation expired, or re-inviting a user
who never set a password, sent a link that needs a login the user cannot
complete. Unused invited accounts now get a magic link again, and changing
another user's password no longer ends the current session.
Two applications that build the same Docker image name push the same
tags (commit SHA, latest, pr-<id>), so one can run the image of the
other. Deployments, the General form, and the API now reject such a
name for applications of the same team.
Closes#9834
ServerManagerJob and the Docker cleanup step of ScheduledJobManager
load the settings of every server with SELECT *. That reads the
patch_check_result JSON, which holds the full update list of each
server. With 12,709 rows, the scan took about 4 ms, but the full fetch
took 390-536 ms and 294 MB of PHP memory. Without the column it took
74 ms and 111 MB.
Add ServerSetting::withoutPatchCheckResult() and use it in both loops.
Queued jobs reload the full settings through SerializesModels.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
An OR of two correlated EXISTS subqueries made Postgres estimate a
per-server scan of the runner executions, so JIT compilation took most
of the time of the per-minute reconcile query. Select the server ids
from both runner tables with one UNION and index executions by status
and server.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
When another process held the control socket, `ssh -fN` disabled
multiplexing and stayed open as a plain connection forever. Each one
kept an sshd process on the server, which used up its memory.
Run `true` instead of -fN. ControlPersist moves a new master to the
background; a process that cannot become the master exits.
Public pull request previews no longer get production values, and no
preview falls back to production variables. Existing previews were
deployed with these values; for example, their databases were
initialized with the production password, so they broke on redeploy.
Previews that exist at the upgrade get keeps_production_values and
keep the earlier behavior. Previews created later do not. Server
transfer moves the flag.
The retry labels (Traefik retry middleware, Caddy lb_try_duration)
changed the labels of every application. On the first rolling update
after a settings save, the old and the new container defined the same
Traefik router differently, so Traefik dropped the route and returned
503 until the old container stopped.
Remove the retry labels from this release. The rolling update drain
wait stays.