Skip to content

[DSO-638] make proxy image configurable - #153

Open
gilberthl-mh wants to merge 18 commits into
masterfrom
dso-638-make-proxy-image-configurable
Open

gilberthl-mh wants to merge 18 commits into
masterfrom
dso-638-make-proxy-image-configurable

Conversation

@gilberthl-mh

@gilberthl-mh gilberthl-mh commented Apr 27, 2026

Copy link
Copy Markdown
Contributor

Note

Medium Risk
Moderate risk: introduces new configuration paths for the HTTP proxy container (including Docker socket mounting via DOCKER_HOST) and significantly modernizes the Node/Docker CI matrix and dev tooling, which could cause environment-specific regressions.

Overview
Adds support for overriding the built-in HTTP proxy Docker image via NAVY_HTTP_PROXY_IMAGE (highest precedence) or Navyfile.js httpProxyImage, and ensures proxy reconfiguration (including the HTTPS CLI path) passes navyFile through so custom images are not dropped.

Updates proxy compose generation to mount the Docker socket resolved from DOCKER_HOST when it points at a unix socket, aligning dockerode and docker compose usage (notably in CI).

Modernizes the toolchain and CI: bumps Babel Node target to 22, adds c8 coverage config with 100% coverage thresholds, updates Flow libs/config, ignores flow-libs in ESLint, refreshes Lerna config, and overhauls GitHub Actions to run on Node 22/24 with pinned action SHAs and explicit Docker/Docker Compose setup.

Reviewed by Cursor Bugbot for commit 4595136. Bugbot is set up for automated code reviews on this repo. Configure here.

Comment thread packages/navy/src/navy/index.js
Comment thread packages/navy/src/navy/index.js
@gilberthl-mh
gilberthl-mh force-pushed the dso-638-make-proxy-image-configurable branch 3 times, most recently from e4c8707 to a442903 Compare April 28, 2026 11:10

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 1 potential issue.

There are 3 total unresolved issues (including 2 from previous reviews).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit a442903. Configure here.

Comment thread packages/navy/src/http-proxy.js
The repo previously could not be installed on Node 22 because node-pty@0.9
has no prebuilt binaries for Node 22 and the bundled node-gyp pipeline fails
on Python 3.12+ where distutils was removed.

Bumps the install-blocking and deprecated dependencies across the monorepo
to majors compatible with Node 22, and applies the corresponding source
rewrites for breaking API changes.

Tooling

- engines.node: >=10 -> >=22 (root + both workspace packages)
- babel preset-env target: node 10 -> node 22
- Drop unmaintained npm-force-resolutions preinstall hook
- Drop empty resolutions block
- Add npm workspaces config and remove lerna bootstrap script
- Migrate lerna 5 -> 8 (npm workspaces driven)
- Remove obsolete per-package package-lock.json files

Native / install blockers

- node-pty 0.9 -> 1.0 (ships prebuilt darwin-arm64, darwin-x64,
  win32-arm64, win32-x64 binaries for Node 22)

Deprecated package replacements

- opn -> open@8 (last CJS major)
- findit -> findit2 (maintained drop-in fork)
- mkdirp@0.5 + rimraf@2 (runtime) -> native fs.promises.mkdir/rm
- eslint-plugin-standard removed (no longer required by
  eslint-config-standard 17)
- eslint-plugin-node -> eslint-plugin-n
- eslint-plugin-flowtype removed (unmaintained, peer-dep blocks
  eslint 8); flowtype/* lint rules removed from .eslintrc.yml.
  Flow type-checking still works via flow-bin and Babel strips the
  annotations.

Lint / Flow

- eslint 7 -> 8 (staying on legacy config rather than flat config)
- eslint-config-standard 11 -> 17
- eslint-plugin-import 2.25 -> 2.32
- eslint-plugin-promise 5 -> 6 (peer-pinned by eslint-config-standard)
- eslint-plugin-n 16 (peer-pinned by eslint-config-standard)
- eslint-plugin-chai-friendly 0.5 -> 1.2
- flow-bin 0.75 -> 0.311

Test stack

- mocha 10 -> 11
- @cucumber/cucumber 7 -> 11 (only Given/When/Then/After/
  setDefaultTimeout in use, all stable since v6)
- regenerator-runtime 0.13 -> 0.14
- strip-ansi 3 -> 6 (last CJS major)
- chai stays on 4 (5 is ESM-only)
- node-fetch stays on 2 (3 is ESM-only)
- rimraf devDep 2 -> 5

Runtime deps in packages/navy

- chalk 1 -> 4 (last CJS major; API used unchanged)
- commander 2 -> 12 (named import {program} required)
- inquirer 7 -> 8 (last CJS major; API used unchanged)
- js-yaml 3 -> 4 (safeLoad/safeDump renamed to load/dump)
- debug 2 -> 4
- dockerode 3 -> 4 (Promise constructor option removed; uses native promises)
- promise-retry 1 -> 2
- ramda 0.28 -> 0.30

Out of scope

- website/ workspace
- Migrating Flow type annotations to TypeScript
- Achieving fully green tests (the goal here is "installs and builds
  cleanly on Node 22")
- The DNS-lookup unit test for getExternalIP fails on Node 22's default
  IPv6-first resolution order; that's an environmental quirk surfaced by
  the runtime upgrade, not by any dep change.

Made-with: Cursor
DSO-638

Add resolveProxyImage helper to allow the HTTP proxy Docker image to be
overridden via NAVY_PROXY_IMAGE env var or httpProxyImage in Navyfile.js,
falling back to the default navycloud/navy-proxy. Update documentation
and add unit tests covering the resolution order.

Made-with: Cursor
DSO-638

Pass navyFile to reconfigureHTTPProxy in launch(), destroy(), and
start() so the Navyfile httpProxyImage fallback works at runtime.
Add tests for empty-string httpProxyImage and NAVY_PROXY_IMAGE.

Made-with: Cursor
Align the environment variable name with the httpProxyImage config property.

DSO-638

Made-with: Cursor
@gilberthl-mh
gilberthl-mh force-pushed the dso-638-make-proxy-image-configurable branch from a442903 to 2efa4b4 Compare April 28, 2026 12:50
Apply consistent code style: add spaces inside destructuring braces and
remove unnecessary quotes around object keys.

DSO-638

Made-with: Cursor
@gilberthl-mh
gilberthl-mh force-pushed the dso-638-make-proxy-image-configurable branch from c6552aa to cf8c21f Compare April 28, 2026 12:57
The flow-bin upgrade to 0.311 removed the .flowconfig options that
were keeping the Flow server alive (`esproposal.export_star_as`,
`suppress_comment`) and surfaced 157 latent type errors that the
older Flow had silently tolerated, blocking `npm test` in CI.

- Drop the removed options from `.flowconfig` and add a `flow-libs/`
  directory with ambient declarations for Node globals, Node built-in
  modules, and the `pad` package so the new resolver can find them.
- Replace deprecated `Promise<bool>` with `Promise<boolean>` and
  migrate `// $FlowIgnore` to `// $FlowFixMe[unsupported-syntax]` for
  the dynamic `require()` sites; remove suppressions that are no
  longer needed once the libdefs are in place.
- Add explicit parameter, empty-array, and exported-function return
  type annotations to satisfy the stricter `missing-local-annot` and
  `signature-verification-failure` checks.
- Introduce `{[string]: T}` index signatures on map-shaped object
  literals (Config, NAME_MAP, OPTION_LABEL_MAP, lookup tables, state
  services) and refactor spread-with-computed-key patterns that
  triggered `cannot-spread-indexer`.
- Replace `this` references inside object-literal "class" methods
  with named `provider`/`driver` locals to clear `object-this-reference`.
- Tighten genuine type bugs surfaced by stricter checking: array
  typing for `cli/https.js` services, nullable handling in
  `getUrlFromService` and `container.raw`, and align
  `getImportOptionsForCLI` to `Promise<State>`.
- Add `flow-libs/` to `.eslintignore` so eslint does not lint the
  ambient Flow declarations.

Result: `npm run flow` reports "No errors!" (157 -> 0) and
`npm run lint` is clean.

DSO-638

Made-with: Cursor
`dns.lookup(hostname, null, ...)` lets the OS resolver choose the
address family. On macOS the system resolver returns IPv6 first
for `localhost` (`::1`, family 6), which `dnsLookup` rejects
because it requires `ipFamily === IPV4_FAMILY`, causing
`getExternalIP > should resolve the hostname from DOCKER_HOST if
it isn't an ipv4 address` to fail with `Failed to lookup hostname
"localhost"`. Linux CI returns IPv4 first, hiding the bug there.

Pass `{ family: 4 }` so the resolver only returns IPv4 addresses,
matching the existing `IPV4_FAMILY` invariant. The downstream
family check is retained as defence-in-depth.

DSO-638

Made-with: Cursor
Addresses two breakages introduced by the Node 22 dependency
modernisation:

- rimraf v5's CJS module has no default export, so the existing
  `import rimraf from 'rimraf'` resolved to undefined under Babel's
  `__importDefault` interop and `rimraf.sync(...)` threw. Switch to
  the named `rimrafSync` import in `hooks.js` and `develop.js`.
- commander v12 no longer attaches subcommand options as own
  properties of the command instance, so the CLI tests that relied
  on the env-derived `defaultNavy` hit `NO_NAVY_PROVIDED`. Pass
  `-e dev` (via the existing `ENV_NAME` constant) explicitly in
  `port-cli.js` and `start-stop-cli.js`.

DSO-638

Made-with: Cursor
CI exports NAVY_DEBUG=navy:* to aid diagnosis, but the cli-automator
inherited it into every spawned navy CLI. node-pty merges stdout and
stderr, so `navy:cli Invoked CLI action +0ms` ended up in the captured
output and broke JSON parsing and equality assertions across the
config and external-ip scenarios. Default NAVY_DEBUG to "null" for the
spawned CLI (with an opt-in via opts.env) and drop the now-redundant
per-step override in port-cli.js.

DSO-638

Made-with: Cursor
The previous attempt only suppressed NAVY_DEBUG when opts.env was
absent, but step definitions like the external-ip override one spread
process.env into their own opts.env, so they kept inheriting
NAVY_DEBUG=navy:* from CI and the captured CLI output still contained
`navy:cli Invoked CLI action +0ms`. Force NAVY_DEBUG to "null"
unconditionally - no test in the suite asserts on CLI debug output, so
there is no need for an opt-in path.

DSO-638

Made-with: Cursor
docker/setup-docker-action installs the daemon on a custom path under
/home/runner/setup-docker-action-<id>/docker.sock and only exposes it
via a Docker CLI context. With set-host left at its default of false,
DOCKER_HOST stays unset so dockerode (used by `navy.ps()` and the
proxy reconfigure step) falls back to /var/run/docker.sock and queries
a different daemon, while the navy http-proxy compose file mounts the
same hard-coded path into the nginx-proxy container. This made every
integration scenario that depends on container visibility fail with
either an empty `ps` array or the proxy's "Service not found" page.

- Set `set-host: true` on the Setup Docker workflow step so DOCKER_HOST
  is exported to all subsequent steps.
- Derive the proxy compose volume mount from DOCKER_HOST when it points
  at a unix socket, and fall back to /var/run/docker.sock for normal
  deployments.

Adds unit tests for the new `resolveDockerSocketPath` helper covering
the unset, empty, unix://, malformed unix:// and tcp:// cases.

DSO-638

Made-with: Cursor
Resolve all 29 reported npm audit vulnerabilities (1 low, 6 moderate,
22 high) by upgrading direct dependencies and applying tightly-scoped
overrides for unfixable transitive issues.

- Upgrade @cucumber/cucumber 11.x -> 12.8.2 (major)
- Upgrade lerna 8.x -> 9.0.7 (major)
- Override mocha -> diff ^8.0.3, serialize-javascript ^7.0.5
- Override lerna -> nx -> brace-expansion ^5.0.5, follow-redirects
  ^1.16.0, yaml ^2.8.3
- Drop --publish-quiet from cucumber-js invocation (removed in v12;
  publishing is now off by default)

Final state: 0 vulnerabilities across 1156 packages. Lint, flow,
unit tests, build, and cucumber dry-run all pass.

DSO-638

Made-with: Cursor
The two reconfigureHTTPProxy calls in cli/https.js were not updated to
pass navyFile alongside the navy/index.js call sites, so a custom
httpProxyImage from the user's Navyfile was silently overwritten with
the default navycloud/navy-proxy image whenever the HTTPS CLI command
recreated the proxy. Pass navyFile through in both branches, guarding
isInitialised in the --disable path so it still works without a
launched navy.

DSO-638

Made-with: Cursor
@gilberthl-mh
gilberthl-mh force-pushed the dso-638-make-proxy-image-configurable branch 4 times, most recently from 3131f9d to 841e149 Compare May 5, 2026 10:49
Wire up c8 with --all and 100% line/branch/function/statement thresholds
and add Mocha/Chai/Sinon/proxyquire/nock unit tests across the navy and
navy-plugin-nodejs packages so every module is exercised.

Remove three small clusters of unreachable defensive guards uncovered
during this work so the suite hits 100% in every dimension without any
c8/istanbul ignore comments:

- cli/live.js: drop the (state.services || {})[service] fallback that
  the early-return at the top of the function already makes unreachable.
- middleware/port-override.js: drop the always-truthy hasPortConfig
  ternary - getPortConfig always returns an object so the falsy branch
  was dead.
- navy/index.js: drop the redundant (await getState()) || {} and
  state.services || {} fallbacks in useTag, resetTag, usePort, and
  resetPort. Those methods all subsequently call kill/launch/update
  which require an initialised state, so a null/empty state would fail
  downstream regardless.

Co-authored-by: Cursor <cursoragent@cursor.com>
@gilberthl-mh
gilberthl-mh force-pushed the dso-638-make-proxy-image-configurable branch from 841e149 to 46cb816 Compare May 5, 2026 11:12
Capture the purpose of the dso-638-make-proxy-image-configurable branch
and provide a high-level map of where each change lives, so reviewers
and future maintainers can navigate the diff without re-reading every
commit.

DSO-638

Co-authored-by: Cursor <cursoragent@cursor.com>
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.

1 participant