Skip to content

fix(docker): INFRA-908 fail loudly on shared Dockerfile collisions - #199

Open
amanda-orin wants to merge 4 commits into
masterfrom
INFRA-908
Open

fix(docker): INFRA-908 fail loudly on shared Dockerfile collisions#199
amanda-orin wants to merge 4 commits into
masterfrom
INFRA-908

Conversation

@amanda-orin

@amanda-orin amanda-orin commented Aug 28, 2026

Copy link
Copy Markdown

Clever Coding Standards Agreement

Linear

INFRA-908

About

BuildTargets keys its output map by Dockerfile path. When two apps publish to different artifacts but resolve to the same Dockerfile path (e.g. both omit build.docker.file and land on the default Dockerfile), the second app silently overwrote the first in the map — one image was never built or pushed, and which app "won" depended on Go's map iteration order.

This is what happened with lms-connect-ingest-google-users-docker and lms-connect-update-google-mappings-docker: the ingest image went missing and deploys timed out, with no error surfaced anywhere in CI.

This PR makes BuildTargets detect the collision and return an error instead of silently dropping an image. goci surfaces it as a ValidationError (exit code 2) with a message naming both apps and telling the developer to give each app its own build.docker.file. Apps that legitimately share an artifact name still dedupe to a single build, unchanged.

Checklist

  • Increment the version number in VERSION
  • Add release notes

Testing

  • Added TestBuildTargets (internal/docker/targets_test.go) covering: distinct artifacts with distinct Dockerfile paths (each builds), distinct artifacts sharing the default Dockerfile path (errors), distinct artifacts sharing an explicit Dockerfile path (errors), apps sharing one artifact name (dedupes to a single build), lambda apps (no docker targets), and a single docker app.
  • go test ./... green; go vet, gofmt, staticcheck clean on the changed package.

@amanda-orin
amanda-orin marked this pull request as ready for review August 31, 2026 18:15
@amanda-orin
amanda-orin requested a review from a team as a code owner August 31, 2026 18:15
@amanda-orin
amanda-orin requested review from dmartschenko and removed request for a team August 31, 2026 18:15
Comment thread internal/docker/targets.go Outdated
"artifacts (%q and %q); goci cannot build distinct images from a "+
"shared Dockerfile path. Give each app its own build.docker.file",
prev.app, name, dockerfileDisplayName(launch.Dockerfile),
prev.artifact, artifact,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

minor - i think the artifacts are going to print as pointer addresses?

I've also noticed that circle ci will blank out custom fields in messages with *****. I'm not sure if this will display well in the circleci build. It might be fine to just drop printing the artifacts and hope the surround message around the blanked out bits is enough.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Every value we interpolate here is a plain string. prev.app and name are string map keys, dockerfileDisplayName(...) returns a string, and artifact and prev.artifact are the ArtifactName string from AppConfig — all through %q, so they render as quoted names like "worker-a". I added TestBuildTargets_CollisionErrorMessage, which checks the exact rendered err.Error() to make sure we have test coverage for this.

On the CircleCI ***** masking — good flag, and it can genuinely happen since we set APP_NAME as a context var and it could appear in these names. I reworked the message to lead with the diagnosis, the Dockerfile path, and the fix, and moved the app/artifact names to the end:

shared Dockerfile path collision: %q is claimed by two apps that publish to different artifacts, so goci cannot build distinct images from it. Give each app its own build.docker.file. Conflicting apps: %q (artifact %q) and %q (artifact %q)

The leading part never contains APP_NAME, so even if masking blanks the trailing names the message is still fully actionable. TestBuildTargets_CollisionErrorMessage pins this exact output too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants