Adds a new global `vector-networks` property on the logs plugin that takes a comma-separated list of Docker networks. When set, the rendered compose file declares each network plus `bridge` as external and joins them on the vector service, so `docker compose up` reconciles attachments on every `logs:vector-start`. When unset, the existing `network_mode: bridge` template is preserved unchanged. The value is validated against `docker network inspect` at set time, rejects the reserved `bridge` entry, and is surfaced in `dokku logs:report` via `--logs-vector-global-networks`.
The ports plugin's `post-certs-update` trigger was rewriting every `https:443:*` mapping from the app's `http:80:*` mappings, silently overwriting any user-defined mapping such as `https:443:443` used by apps that terminate TLS inside the container. The trigger now skips the rewrite when an `https:443:*` mapping already exists, keeping the default behavior only when the app has no explicit HTTPS mapping configured.
Closes#8619.
The bare `tls-internal` key previously returned the computed value, so external tooling could not tell whether the property had been set on the app or was merely defaulting to `false`. The property is now also configurable with `--global`, the report exposes `computed-tls-internal` and `global-tls-internal` keys alongside the bare raw key, and the deploy path honors the per-app value with a fallback to the global value before the built-in default. Closes#8625.
# History
## 0.38.4
Install/update via the bootstrap script:
```shell
wget -NP . https://dokku.com/install/v0.38.4/bootstrap.sh
sudo DOKKU_TAG=v0.38.4 bash bootstrap.sh
```
### Bug Fixes
- #8615: @josegonzalez Reject per-app sets for openresty global-only properties
- #8613: @josegonzalez Expose raw deploy-branch and keep-git-dir in git:report
- #8549: @josegonzalez Route CNB images through launcher on scheduler-k3s
### New Features
- #8614: @josegonzalez Split scheduler-docker-local report into raw, computed, and global
### Documentation
- #8603: @cheif Add `dokku-http-oauth` to community plugins
### Tests
- #8618: @josegonzalez Isolate scheduler-k3s registry tags per bats file
- #8616: @josegonzalez Migrate from junit_files to files in EnricoMi/publish-unit-test-result-action
- #8617: @josegonzalez Upgrade actions in shared build-image compose action
- #8609: @josegonzalez Skip packer lint job on dependabot PRs
- #8604: @dependabot[bot] chore(deps): bump python from 3.14.3-bookworm to 3.15.0b1-bookworm in /tests/apps/dockerfile-release
### Dependencies
- #8606: @dependabot[bot] chore(deps): bump golang.org/x/crypto from 0.50.0 to 0.51.0 in /plugins/common
- #8608: @dependabot[bot] chore(deps): bump github.com/traefik/traefik/v2 from 2.11.45 to 2.11.46 in /plugins/scheduler-k3s
- #8607: @dependabot[bot] chore(deps): bump dokku/openresty-docker-proxy from 0.10.0 to 0.11.0 in /plugins/openresty-vhosts
- #8605: @dependabot[bot] chore(deps): bump python from 3.14.3-alpine to 3.15.0b1-alpine in /docs/_build
Parallel `unit.scheduler-k3s-*` matrix jobs all pushed to the same `savant/rdmtestapp:1` tag on Docker Hub, so a herokuish run pod could pull a CNB or dockerfile image that another job had just overwritten and fail with `exec: "/exec": stat /exec: no such file or directory`. The image-repo-template now embeds the bats file basename so each job owns its own tag namespace.
`openresty:set <app>` previously accepted per-app writes for properties whose readers only consult the global store, so `:set myapp image foo` printed a success message while `:report myapp` kept showing the global default. The per-app form is now rejected with `The key '<key>' can only be set globally`, matching the behavior introduced for `caddy`, `haproxy`, and `traefik` in #8602.
The bare `init-process` and `parallel-schedule-count` keys previously returned the computed value, so external tooling could not tell whether a property had been set on the app or was merely defaulting. Both properties are now also configurable with `--global`, the report exposes `computed-*` and `global-*` keys alongside the bare raw keys, and the deploy path honors the global value before falling back to the linuxserver.io vendor heuristic.
The bare `deploy-branch` and `keep-git-dir` keys in `git:report` returned the computed (effective) value rather than the raw per-app value, with no separate `computed-*` key to distinguish "set per-app" from "falling back to global or default". This left external tooling unable to detect a per-app unset without out-of-band state. The bare keys now hold the raw per-app value (empty when unset) and new `computed-deploy-branch` and `computed-keep-git-dir` keys hold the effective value, matching the convention used by `nginx-vhosts`, `network`, and `builder`. Closes#8610.
Dependabot PRs don't receive `secrets.DIGITALOCEAN_TOKEN`, so the `packer validate` step fails on every dependency bump. Guarding the job by PR author skips it cleanly while keeping it active for human PRs and pushes to `master`.
The cron-id label could exceed Kubernetes' 63-byte cap when commands or
schedules were long, and an all-digit job-suffix or cron-id rendered as
an unquoted YAML scalar caused the API server to reject manifests. Run
pods built from dockerfiles also occasionally hit the 10s startup wait
on a cold image pull, even though the pod was scheduled correctly.
The cron-id is now stored as an annotation and a shorter hash is used as
the selector label. Every interpolated annotation and label value in the
cron-job and deployment templates is now quoted to prevent numeric
coercion, and the run-pod wait timeout is raised to 30 seconds.
Extends bats coverage for the scheduler-k3s scheduler so that
herokuish and dockerfile builders match the cnb test surface for
`dokku run`, `dokku run:detached`, `dokku cron:run`, deployment
manifests, cronjob manifests, and Procfile-key resolution. Adds
the corresponding `app-cron-procfile.json` fixture for the python
app and `app-cron.json` / `app-cron-procfile.json` fixtures for
the dockerfile-procfile app.
After streaming logs from a run pod on scheduler-k3s, the apiserver may still report `PodRunning` for a short window due to kubelet status propagation lag, causing `dokku run` to fail with `Unable to attach as the pod is in an unknown state: Running`. Wait briefly for the pod to reach a terminal phase before classifying the outcome.
For short-lived commands the run pod can transition Running to Succeeded
between the running-pod check and the kubectl exec SPDY upgrade, leaving
the upgrade to fail with `container not found`. When stdout is not a TTY
(and DOKKU_FORCE_TTY is not set) the exec attach is only being used to
capture stdout, so stream the run pod logs in follow mode instead. The
pod's `TTLSecondsAfterFinished` of 60s keeps the kubelet's log file
readable for the duration of the call, eliminating the race.
Drop the assertion that the web deployment has no command since the python buildpack auto-emits a web Procfile entry, which correctly routes through launcher just like docker-local. Shorten the cron command fixture so the base36-encoded cron-id stays under the 63-byte kubernetes label limit, and relax the `dokku run` and `dokku cron:run` output assertions to `assert_output_contains` so they tolerate the leading blank line emitted on k3s.
Mirror the docker-local fix in #8525 for the k3s scheduler. CNB images default to a `/cnb/process/web` entrypoint that ignores incoming args, so non-web deployments, scheduled cron jobs, and ad-hoc `dokku run` / `cron:run` commands all need an explicit `launcher` entrypoint. The deployment and cron-job helm templates now set `command: [launcher]` when `image.type` is `pack`, and `TriggerSchedulerRun` sets the entrypoint to `launcher` for pack images while finishing the previously stubbed Procfile lookup branch so the resolved command is actually scheduled.