-
Notifications
You must be signed in to change notification settings - Fork 88
Resolve service name conflicts when the name is computed to the same value #308
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR resolves service container name conflicts when multiple services use the same Docker image. Previously, services were named based solely on the image name (e.g., "redis" from "redis:8.0.3-alpine"), causing Kubernetes pod creation to fail with duplicate container name errors when multiple services used the same image.
Changes:
- Implements a two-pass naming strategy: first counting occurrences of each base name, then appending index suffixes (-0, -1, etc.) only when conflicts exist
- Adds comprehensive test coverage for the collision scenario with two services using identical images
- Preserves backward compatibility by only adding suffixes when conflicts are detected (single services retain their original names)
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| packages/k8s/tests/prepare-job-test.ts | Adds test case verifying unique names ('redis-0', 'redis-1') are generated when two services use the same image |
| packages/k8s/src/hooks/prepare-job.ts | Implements conflict detection and resolution logic using occurrence counting and index tracking, passes resolved names through to response file generation |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if (args.services?.length) { | ||
| const occurrences = new Map<string, number>() | ||
| for (const s of args.services) { | ||
| const base = generateContainerName(s.image) | ||
| occurrences.set(base, (occurrences.get(base) || 0) + 1) | ||
| } | ||
|
|
||
| const indices = new Map<string, number>() | ||
| services = args.services.map(service => { | ||
| return createContainerSpec( | ||
| service, | ||
| generateContainerName(service.image), | ||
| false, | ||
| extension | ||
| ) | ||
| const base = generateContainerName(service.image) | ||
| const total = occurrences.get(base) || 0 | ||
| const idx = indices.get(base) || 0 | ||
|
|
||
| let name: string | ||
| if (total > 1) { | ||
| name = `${base}-${idx}` | ||
| } else { | ||
| name = base | ||
| } | ||
|
|
||
| indices.set(base, idx + 1) | ||
| serviceNames.push(name) | ||
| return createContainerSpec(service, name, false, extension) | ||
| }) |
Copilot
AI
Jan 26, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The conflict resolution logic doesn't account for cases where a generated name (e.g., 'redis-0') might collide with another service's base name (e.g., a service using image 'redis-0:latest'). This could still result in duplicate container names. Consider using a two-pass approach: first detect all conflicts (including potential conflicts with suffixed names), then generate unique names that avoid all collisions. Alternatively, use a different separator or suffix format that's less likely to collide with valid image names (e.g., '--0' or '.0').
The service name is generated the same way on the runner, based on the image. The change resolves the conflict by appending the index when the conflict exists.
Let's say there are two service containers using
redisimage.The service names would be
redis-0andredis-1. Index suffixes are only added for the names with conflicts.Fixes #241