Commit 8dc5de3
authored
chore: fix make test-json hang under Swift 6.3.1 + restore CI test execution (#172)
* ci: switch test target filter to underscore form for Swift 6.3.1
Verified empirically: the prior dash form `Container-Compose-StaticTests` matches **zero tests** under Swift 6.3.1 (which normalizes module names dashes -> underscores in the test filter grammar). The 5 most recent CI runs on main / phase-4c branches all silently reported:
warning: No matching test cases were run
Executed 0 tests, with 0 failures
Test run with 0 tests in 0 suites passed after 0.001 seconds
conclusion: success
Both matrix targets (Static + Dynamic) were affected. Switching to the underscore form `Container_Compose_StaticTests` / `Container_Compose_DynamicTests` makes `swift test --filter` actually match the intended targets. PR 170 + CHAOS-1507 follow-up surfaced this.
* chore(makefile): switch test-json to working --filter pattern (drop --experimental-event-stream-output)
Under Swift 6.3.1 the prior `make test-json` hangs indefinitely:
* `--experimental-event-stream-output .build/test-events.jsonl` opens a socket-backed event stream that errors out without an active reader, deadlocking the whole `swift test` invocation. Tail of `.build/test-events.jsonl` shows the socket errors when this hits.
* `--skip Container-Compose-DynamicTests` is non-functional in 6.3.1 — the dash form matches no targets (same root cause as the CI workflow fix in the previous commit).
New target uses positive `--filter Container_Compose_StaticTests --no-parallel`:
* Underscore form actually selects the static target (verified locally — dash form returns 'No matching test cases were run').
* `--no-parallel` is explicit (not just defaulted) because multiple suites `dup2` global STDOUT to a Pipe to capture warnings (ResourceArgsTests, LifecycleArgsTests, GpusBlkioTests, SecurityArgsTests, NetworkArgsTests, ComposePort runtime-argv, ComposeDown orphan-volume recovery, ComposeUp block-image migration guard, ShutdownWatchdog) and race on the shared FD under `--parallel`.
* JSONL + `swift run test-report` pipeline is removed — plain swift-testing stdout is the canonical agent-readable surface again.
* docs(agents): update test invocation guidance for Swift 6.3.1
Reflect the fixes from the two preceding commits:
* `make test-json` now uses `swift test --filter Container_Compose_StaticTests --no-parallel` (underscore form because Swift 6.3.1 normalizes module-name dashes; `--no-parallel` because multiple static suites `dup2` STDOUT under parallel and race on the shared FD).
* JSONL + `swift run test-report` pipeline removed — plain swift-testing stdout is the canonical agent-readable surface again. Exit code is the plain `swift test` exit code.
* Expanded list of dup2-using suites (ResourceArgsTests, LifecycleArgsTests, GpusBlkioTests, SecurityArgsTests, NetworkArgsTests, ComposePort runtime-argv, ComposeDown orphan-volume recovery, ComposeUp block-image migration guard, ShutdownWatchdog) is documented so contributors know not to re-introduce `--parallel` to the local test target.
Cross-references PR #170 + CHAOS-1507 follow-up where this was empirically verified.
* fix(tests): reset warn-once dedup in SecurityFeatureIntegrationTests
`SecurityArgsTests` runs alphabetically before `SecurityFeatureIntegrationTests` and exercises `service.privileged`, `service.security_opt`, and `service.group_add` via `SecurityArgs.build()`, consuming the warnings in the process-global `warnUnsupportedRuntimeFieldOnce` dedup set. When the static suite runs serially via `make test-json` / `swift test --no-parallel`, `SecurityFeatureIntegrationTests` then asserts that `captureStdout(...).contains("Note: ...")` succeeds — but the dedup gate suppresses the second emission, so captured stdout is empty and three tests fail.
Mirror the pattern from `LifecycleArgsTests.init`: reset the warn-once set in `init()`. The suite is already `.serialized` so the reset runs deterministically before each test.
Surfaced by `--filter Container_Compose_StaticTests` (the underscore form Swift 6.3.1 actually matches). The legacy dashed filter on main matched zero tests and silently passed.
* fix(runtime): honor absolute paths + guard empty argv in ProductionRunner.resolveBinary
`resolveBinary(forArgv:)` previously routed everything-not-`"container-compose"` to the `container` binary unconditionally. The `LineBufferTests` PLAN.md §4 regression guard (`endToEndChunkedStdoutProducesOneLineAtATime`) drives `ProductionRunner` against `/bin/sh -c "..."` and was silently spawning `container -c "..."` instead, which exits 64 with `Error: unknown option '-c'` on any host where apple/container is installed.
Two changes, both no-ops for production callsites that always pass an unqualified program name:
1. argv[0] starting with `/` now short-circuits to `URL(fileURLWithPath: first)` and bypasses the cached resolver. Production never fires this branch; it exists so test code can drive a real `/bin/sh` subprocess through `ProductionRunner` without being silently re-routed.
2. Empty argv now throws `RuntimeError.backendFailure` via `guard let` instead of silently falling through to `containerBin` (which would launch the apple/container CLI with no arguments and print its help banner — a confusing diagnostic for what is really a caller bug).
Surfaced together with the SecurityFeatureIntegrationTests failures once `--filter Container_Compose_StaticTests` actually executed the suite under Swift 6.3.1.
* chore(ci): fail loudly when test filter matches < 1500 tests
CI's `swift test --filter Container-Compose-StaticTests` was a silent no-op: Swift 6.3.1 normalizes the dashed target name to underscores in the filter grammar, so the dashed form matched zero tests, swift test exited 0, and the job reported green. Earlier commits on this branch correct the filter to `Container_Compose_StaticTests`.
Add a min-tests assertion as defense-in-depth so a future filter typo, target rename, or Swift Testing grammar shift cannot silently regress the suite to a zero-match again:
- `.github/workflows/tests.yml`: matrix entries gain a `min_tests` field (1500 for Static, 0 for Dynamic — CI runners do not ship apple/container so Dynamic legitimately reports `0 tests`). The run step pipes through `tee`, parses the Swift Testing summary line for the executed count, and fails with `::error::` when count is below the floor.
- `Makefile`: `test-json` gets the same guard inline. Honors the upstream swift-test exit code; only overrides on the filter-matched-too-few condition.
- `AGENTS.md`: documents the guard alongside the existing `--parallel` caveat and the underscore-filter rationale.1 parent 3efd36f commit 8dc5de3
5 files changed
Lines changed: 121 additions & 30 deletions
File tree
- .github/workflows
- Sources/Container-Compose/Runtime
- Tests/Container-Compose-StaticTests
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
56 | | - | |
| 56 | + | |
57 | 57 | | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
58 | 65 | | |
59 | | - | |
| 66 | + | |
60 | 67 | | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
61 | 73 | | |
62 | 74 | | |
63 | 75 | | |
| |||
88 | 100 | | |
89 | 101 | | |
90 | 102 | | |
91 | | - | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
| 109 | + | |
| 110 | + | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
| 114 | + | |
| 115 | + | |
| 116 | + | |
| 117 | + | |
| 118 | + | |
92 | 119 | | |
93 | 120 | | |
94 | 121 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
393 | 393 | | |
394 | 394 | | |
395 | 395 | | |
396 | | - | |
397 | | - | |
398 | | - | |
399 | | - | |
400 | | - | |
401 | | - | |
402 | | - | |
403 | | - | |
404 | | - | |
405 | | - | |
| 396 | + | |
| 397 | + | |
| 398 | + | |
| 399 | + | |
| 400 | + | |
| 401 | + | |
| 402 | + | |
| 403 | + | |
| 404 | + | |
| 405 | + | |
| 406 | + | |
| 407 | + | |
| 408 | + | |
| 409 | + | |
| 410 | + | |
| 411 | + | |
| 412 | + | |
| 413 | + | |
| 414 | + | |
| 415 | + | |
| 416 | + | |
| 417 | + | |
406 | 418 | | |
407 | 419 | | |
408 | 420 | | |
| |||
442 | 454 | | |
443 | 455 | | |
444 | 456 | | |
445 | | - | |
446 | | - | |
| 457 | + | |
| 458 | + | |
| 459 | + | |
447 | 460 | | |
448 | 461 | | |
449 | 462 | | |
| |||
503 | 516 | | |
504 | 517 | | |
505 | 518 | | |
506 | | - | |
| 519 | + | |
507 | 520 | | |
508 | 521 | | |
| 522 | + | |
| 523 | + | |
509 | 524 | | |
510 | 525 | | |
511 | 526 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
72 | 72 | | |
73 | 73 | | |
74 | 74 | | |
75 | | - | |
76 | | - | |
77 | | - | |
78 | | - | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
79 | 78 | | |
80 | | - | |
81 | | - | |
82 | | - | |
83 | | - | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
84 | 86 | | |
85 | | - | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
86 | 93 | | |
87 | | - | |
88 | | - | |
89 | | - | |
| 94 | + | |
| 95 | + | |
| 96 | + | |
| 97 | + | |
| 98 | + | |
| 99 | + | |
| 100 | + | |
| 101 | + | |
| 102 | + | |
| 103 | + | |
| 104 | + | |
| 105 | + | |
| 106 | + | |
90 | 107 | | |
91 | 108 | | |
92 | 109 | | |
| |||
108 | 125 | | |
109 | 126 | | |
110 | 127 | | |
111 | | - | |
| 128 | + | |
112 | 129 | | |
113 | 130 | | |
114 | 131 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
| 216 | + | |
| 217 | + | |
| 218 | + | |
206 | 219 | | |
207 | | - | |
| 220 | + | |
| 221 | + | |
| 222 | + | |
| 223 | + | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
| 228 | + | |
208 | 229 | | |
209 | 230 | | |
210 | 231 | | |
| |||
Lines changed: 11 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
60 | 60 | | |
61 | 61 | | |
62 | 62 | | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
63 | 74 | | |
64 | 75 | | |
65 | 76 | | |
| |||
0 commit comments