fix(up): add Service.containerName helper for explicit container_name#113
fix(up): add Service.containerName helper for explicit container_name#113YvanY0 wants to merge 1 commit into
Conversation
|
Nice fix - correct root cause, complete coverage (verified no hardcoded patterns remain), and good call centralizing the rule.
|
Cyb3rDudu
left a comment
There was a problem hiding this comment.
Nice fix - correct root cause, complete coverage (verified no hardcoded patterns remain), and good call centralizing the rule.
Two asks:
the new dynamic test passes even if waitUntilServiceIsRunning is reverted because its timeout is swallowed by the run-loop catch { print(error) } - can you assert the wait/IP path actually succeeded, or unit-test those two functions directly?
the old Info: Using explicit container_name log was dropped - worth re-adding for debuggability.
Thank you @Cyb3rDudu, I will evaluate and push the update based on your comment. |
e724ebe to
270532a
Compare
ComposeUp had three places (getIPForRunningService, waitUntilServiceIsRunning, stopOldStuff) that hard-coded the container name as "\(projectName)-\(serviceName)" instead of reading service.container_name. When a compose file set an explicit container_name, the container started correctly (container run --name used the right value), but the post-start lookups waited for the wrong name and timed out after 30s. Extract a single Service.containerName(projectName:serviceName:) helper and replace all five call sites (four in ComposeUp, one in ComposeDown) with it. Follow-ups from review: - testUpWithExplicitContainerName now asserts the container has a network with an IPv4 address after up, which only happens if both waitUntilServiceIsRunning and getIPForRunningService resolve a real container. This catches a regression where the run-loop catch swallows wait timeouts (the container would still be running but have no networks attached). - Re-add the "Info: Using explicit container_name" log in configService that was dropped when centralizing the rule.
270532a to
e1c1cf9
Compare
Restored. configService now prints Info: Using explicit container_name: when service.container_name != nil One more thing I noticed but didn't address in this PR. The Shape I'd propose for a follow-up: // Errors.swift
public enum ServiceStartupError
// ComposeUp.swift — configService
do {
try await waitUntilServiceIsRunning(service, serviceName: serviceName)
try await updateEnvironmentWithServiceIP(service, serviceName: serviceName)
} catch {
throw ServiceStartupError.failed(serviceName: serviceName, underlying: error)
}
// ComposeUp.swift — run() service loop
for (serviceName, service) in services {
do {
try await configService(service, serviceName: serviceName, from: dockerCompose)
} catch let error as ServiceStartupError {
if case .failed(let name, let underlying) = error {
startupFailures.append((name, underlying))
}
} catch {
throw error // preflight errors (imageNotFound, etc.) still propagate
}
}
if !startupFailures.isEmpty {
throw ServiceStartupError.multipleFailures(startupFailures)
}This is out of the scope of this PR, we can create an new issue to track this if needed. Fixing this do/catch would also strengthen ask 1's |
The bug
When a compose file sets an explicit
container_name, the container starts correctly —container run --namereads the value. ButComposeUphas three other places that look up the running container by name (waitUntilServiceIsRunning,getIPForRunningService,stopOldStuff), and all three hard-code"\(projectName)-\(serviceName)"instead of readingcontainer_name.For example, given:
Run from a directory named
hermes(noname:field), the container starts ashermesbut the post-start poll waits forhermes-hermesand times out:Issue #38 reported the same bug on the
downside; PR #39 fixedComposeDown.stopOldStuffbutComposeUpwas not addressed.The fix
Extract
Service.containerName(projectName:serviceName:)— a single method that encapsulates the rule (prefer explicitcontainer_name, fall back to"\(projectName)-\(serviceName)") — and route all five call sites through it:configService,waitUntilServiceIsRunning,getIPForRunningService,stopOldStuff)stopOldStuffin ComposeDown (refactored to use the same helper, replacing the inlineif/elsefrom PR Handle compose down with container_name case #39)When
container_nameis not set the helper returns the same"\(projectName)-\(serviceName)"string as before; existing compose files without explicit container names are unaffected.Verification
Tested locally against the compose file above:
Before:
container-compose up -dreportsTimed out waiting for container 'hermes-hermes' to be running.After: the container starts and polls successfully with no timeout;
container ls -ashows it inrunningstate.Tests
ServiceNamingTests— two unit tests for the purecontainerNamehelper (explicit name wins, default pattern when unset).testUpWithExplicitContainerName— exercisesComposeUp.run()end-to-end with an explicitcontainer_name(mirrors the pattern in PR feat: Providing tests forComposeDown#50'stestUpAndDownContainerName).Fixes #38