Files
devops-lib-gcp/docs/adr/0015-node-install-logic-paired-across-buildnode-groovy-and-dockerfile.md
T
2026-08-26 02:02:24 +05:30

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_arg in config.yaml without forking the library Dockerfile — observed in #devops-tech (Nov 2025) when a team added --legacy-peer-deps purely via config.
  • The Dockerfile's else fallback means a developer can docker build locally without Jenkins or config.yaml and 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.

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_arg in config.yaml is a documented public extension point — see service-team usage in #devops-tech (Nov 2025) for the --legacy-peer-deps case.
  • Discovery id: PATTERN-2