Skip to content

release: 5.10.0 - #1918

Merged
Jaro-c merged 5 commits into
mainfrom
develop
Sep 24, 2026
Merged

Jaro-c merged 5 commits into
mainfrom
develop

Conversation

@Jaro-c

@Jaro-c Jaro-c commented Sep 24, 2026

Copy link
Copy Markdown
Member

Release 5.10.0: implicit start order for volumes_from, links and service: references (#1911), watch ignore/include relative to the rule path (#1913), forcerm on builds (#1915) and five new audit checks (#1916).

Signed-off-by: Jaro-c 75870284+Jaro-c@users.noreply.github.com

…erences (#1911)

`volumes_from`, `links` and `network_mode` / `ipc` / `pid` / `uts` set
to `service:<name>` all need the referenced container to exist before
the dependent is created. podup ordered services only by `depends_on`,
so both landed in the same dependency level, started concurrently, and
`up` failed:

```
podman API error (HTTP 500): looking up container to share net namespace with: no container with name or ID "i1907net-zdb-1" found: no such container
```

docker compose v5.1.3 turns each of those references into an implicit
`depends_on` entry when it loads the file (measured with `docker-compose
config`): `volumes_from` as `service_started` without restart
propagation, `links` and the `service:` namespace keys as
`service_started` with `restart: true`, `container:<name>` as nothing,
and an explicit entry for the same service is kept as written.

What I changed:

- `internal/compose/dependencies.rs`: `effective_depends_on` returns the
explicit `depends_on` plus those implicit entries. It is computed on
demand instead of written into `Service::depends_on` at load, because
`config_hash` serializes the whole service; mutating it would have
recreated every existing container that uses one of these references on
the first `up` after upgrading. `config` keeps printing `depends_on` as
written.
- The `volumes_from` grammar (`:ro`/`:rw`, `container:`, `service:`) now
lives in one parser that both the container-name rewrite and the
dependency computation use.
- Every consumer that orders, waits on, expands or restarts by
dependency uses it: `resolve_order`/`resolve_levels` (so a
`volumes_from` cycle is rejected at config time), readiness, scheduling,
target expansion, `up`'s per-service wait, restart propagation, profile
activation, `pull --include-deps`, and the Quadlet `After=`/`Requires=`
lines.

Tests: unit tests for each reference form and for explicit-wins;
ordering tests whose service names sort in the wrong start order, so the
old code cannot pass by luck; a pin that parsing leaves `depends_on`
untouched; consumer tests for restart propagation, profiles and Quadlet;
and a live test on Podman 5.7.0 that failed with the error above before
the change and passes after. Reverting only `order.rs` turns exactly the
four ordering tests red.

Closes #1907

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>

---------

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
….dockerignore syntax (#1913)

`develop.watch` read each rule's `ignore:` and `include:` relative to
the project directory, with a literal prefix match. The Compose
Specification uses `.dockerignore` syntax for both, loads the build
context's `.dockerignore` as implicit `ignore` content, and its own
example (`path: ./web`, `ignore: [node_modules/]`) only works when
patterns are read relative to the rule's `path`. Measured on podup
5.9.8: with `path: ./api`, only `api/cache` was ignored; `cache/`,
`cache/**`, `**/cache/**` and `*.txt` all triggered a rebuild.

What I changed:

- The `.dockerignore` matcher the build context already used moved to
`internal/engine/ignore_patterns.rs`, unchanged, so build and watch
share one implementation. It gained `evaluate`, which also says whether
any pattern matched at all.
- Watch matches each changed file relative to the rule's `path` with
that matcher. For a service with a local build context, that context's
ignore file is read once at watch start and matched relative to the
context.
- Rules written the old way keep working: only when no pattern matched
in the new reading, the old project-relative matcher decides, and podup
warns once per pattern with the form to write instead (`write "cache"
instead` when the pattern started with the rule's path). A `!`
re-include is never overridden by the fallback.
- `docs/commands.md` describes the semantics and the fallback.

Tests: matcher and pipeline tests for rule-relative globs, negation, the
build-context ignore file, include, the fallback and its single warning
across repeated events; a live test on Podman 5.7.0 where `ignore:
["*.tmp"]` with `path: ./src` keeps `a.tmp` out of the container and
lets `b.txt` in. On `develop` that live test fails because `a.tmp` is
synced. Removing the "nothing matched" guard fails only the negation
test; matching against the project path fails the four rule-relative
pipeline tests.

This keeps existing rules working, so it fits a minor release. Refs
#1897 (part 4).

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>

---------

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
#1915)

Every `podup build` that failed left one buildah working container
behind (visible in `buildah containers`, not in `podman ps -a`); this
machine had collected more than a hundred.

`rm=true` removes intermediate containers only after a successful build.
After a failed step the container stays unless `forcerm=true` is sent,
which `podman build` and `podman --remote build` do by default and podup
never did. Measured on 2026-09-24 against Podman 5.7.0 by posting the
same failing build with curl: without `forcerm` one container per run
was left (2 of 2), with `forcerm=true` none (0 of 2), and an unchanged
build still used the layer cache.

What I changed:

- The build query carries `forcerm=true` next to `rm=true`.
- A unit test pins that both appear exactly once in the query the fake
Podman receives.
- A live test runs the binary on a Containerfile ending in `RUN exit 1`,
asserts it failed on that step, and fails naming any working container
rooted at an image of that build. Without `forcerm=true` it fails naming
the leaked container; with it, it passes. It drives the binary because
the in-process engine path did not reproduce the leak when I measured
it.

The full live suite passed locally on Podman 5.7.0 (226 of 226).

This replaces #1912, which changed the request line instead and turned
off the build cache. The request line is tracked in #1914.

Closes #1910

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>

---------

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
…ound and CPU limit (#1916)

`podup audit` gains five checks, all on by default like the existing
ones except `--wildcard-binds`:

| id | fires when |
|---|---|
| `no_restart_policy` | neither `restart:` nor `deploy.restart_policy`
is set (an explicit `restart: "no"` is a choice and does not fire) |
| `no_init` | `init` is not `true` |
| `no_health_action` | a compose `healthcheck` that is not disabled has
no `x-podman-on-failure` |
| `swap_unbounded` | a memory limit is in effect and `memswap_limit` is
absent, `-1`, or differs from it |
| `no_cpu_limit` | no positive `cpu_quota`, no `cpus` (service or
`deploy.resources.limits`), and no `cpuset` |

The audit reads memory and CPU through the same helpers
`build_resource_limits` uses, so it applies the engine's precedence
(top-level `mem_limit`/`cpus` first, `deploy.resources.limits` only when
the top level is unset) and cannot disagree with what the container
gets. What the engine forwards is unchanged: a test pins that
`cpu_quota: -1` next to `cpus: "2"` still forwards `-1`. The two helpers
are re-exported from the library root as `#[doc(hidden)]`, for the
binary's `audit` command only.

Anyone running `podup audit --strict` in CI will see these five as new
findings on services that do not set them; `podup audit --list-checks`
lists them.

Tests: a firing and a non-firing case of the same shape for each check,
the precedence case (`mem_limit: 256m`, deploy `512m`, `memswap_limit:
256m` is silent), `cpu_quota` `-1` and `0`, `cpuset`, an invalid
`x-podman-on-failure`, and CLI tests for `--strict` exit codes and the
JSON ids. Removing the `cpuset` clause fails only its test; inverting
`no_init` fails its three tests and the registry and fully-hardened
tests. The full live suite passed locally (225 of 225).

Closes #1894

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>

---------

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
Bumps `Cargo.toml`, `Cargo.lock` and `debian/changelog` to 5.10.0
together, which the release workflow checks before building.

Minor, not patch: `podup audit` gains five checks that run by default,
so `audit --strict` reports new findings on existing projects. The rest
are fixes: implicit start order for `volumes_from`, `links` and
`service:` namespace references (#1907), `develop.watch` ignore/include
relative to the rule's path (#1897), and no leftover buildah container
after a failed build (#1910).

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>

Signed-off-by: Jaro-c <75870284+Jaro-c@users.noreply.github.com>
@Jaro-c Jaro-c added prio:P2 Medium priority effort:XS Extra small type:chore Maintenance with no product impact release area:release Subsystem: release labels Sep 24, 2026
@Jaro-c
Jaro-c merged commit 849ab26 into main Sep 24, 2026
81 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:release Subsystem: release effort:XS Extra small prio:P2 Medium priority release type:chore Maintenance with no product impact

Development

Successfully merging this pull request may close these issues.

1 participant