3.8 KiB
ADR-0015: Node install logic paired across buildNode.groovy and Dockerfile
Status: Accepted Category: PATTERN Date decided: Early on Date documented: 2026-05-13
Context
Meesho Node services use both npm and pnpm depending on the repo. Some teams need to pass extra flags (e.g. --legacy-peer-deps) and the shared library cannot anticipate every combination. The install step has to run inside the Docker build (the image needs node_modules baked in), but the choice of which package manager and which flags to run is information the Dockerfile alone can't recover from a clean container — it has to be told.
Decision
The install step is split deliberately across the two files. src/com/meesho/stages/buildNode.groovy does the detection: it reads config.yaml, sees whether the repo uses npm or pnpm, and resolves the optional npm_install_arg override; it then passes the resolved values to resources/com/meesho/node-Dockerfile as Docker build-args. The Dockerfile does the execution: it consumes those build-args and runs the actual install, falling back to a sane default in an else branch when no value was passed. Detection lives at the layer that can see the config; execution lives at the layer that runs inside the container.
Alternatives Considered
No alternatives were explicitly evaluated by the team during this interview. The split mirrors what is naturally separable — config interpretation vs runtime install — and has not been revisited.
Consequences
Positive:
- Teams can override the install command for their service through
npm_install_arginconfig.yamlwithout forking the library Dockerfile — observed in #devops-tech (Nov 2025) when a team added--legacy-peer-depspurely via config. - The Dockerfile's
elsefallback means a developer candocker buildlocally without Jenkins orconfig.yamland still get a working install. - Neither layer needs to know more than it actually does: Groovy doesn't run
npm, the Dockerfile doesn't read YAML.
Negative:
- Any change to install behaviour has to land in both files at once (tribal-knowledge #11). The pair-edit invariant is real but has not yet caused a production incident.
- Build-args are stringly-typed, so a typo on either side fails late — at install time inside the Docker build.
Neutral:
- The "detection in Groovy, execution in Dockerfile" split is mirrored elsewhere in
devops-lib(e.g. Maven, Go); Node just happens to be the most config-driven and therefore the most visible example.
Constraints
- The package-manager choice has to be visible at Docker-build time inside the container; build-args are the cleanest way to inject it.
- The library must support repos that build locally (no Jenkins, no
config.yaml) for developer ergonomics.
Current Assessment
- Still appropriate — the split works, the override knob is being used as intended, and no incident has surfaced. A future hardening could add a CI check that any PR touching the install logic on one side also touches the other, but it is not load-bearing today.
Related Decisions
None directly. The "detection in Groovy, execution in container" split is a pattern repeated in other build stages (Maven, Go), but each has its own per-language ADR scope.
Notes
- Key files:
src/com/meesho/stages/buildNode.groovy,resources/com/meesho/node-Dockerfile npm_install_arginconfig.yamlis a documented public extension point — see service-team usage in #devops-tech (Nov 2025) for the--legacy-peer-depscase.- Discovery id: PATTERN-2