Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
de29042
chore: modernize dependencies for Node 22 support
gilberthl-mh Apr 28, 2026
ebe1c51
Make Navy proxy image configurable
gilberthl-mh Apr 27, 2026
2f873db
Fix navyFile propagation and add edge-case tests
gilberthl-mh Apr 27, 2026
9505dd6
rename NAVY_PROXY_IMAGE env var to NAVY_HTTP_PROXY_IMAGE
gilberthl-mh Apr 27, 2026
2efa4b4
Use Moneyhub runners for CICD
gilberthl-mh Apr 27, 2026
cf8c21f
style: fix linting issues across navy packages
gilberthl-mh Apr 28, 2026
e49a4cf
fix: restore Flow type-checking under flow-bin 0.311
gilberthl-mh Apr 28, 2026
6b69be6
fix: pin dnsLookup to IPv4 to prevent macOS resolver flake
gilberthl-mh Apr 28, 2026
70f723e
fix: align integration tests with rimraf v5 and commander v12
gilberthl-mh Apr 28, 2026
f3b074c
Fix integration tests
gilberthl-mh Apr 29, 2026
6973bb7
fix(test): silence navy CLI debug output in integration spawns
gilberthl-mh Apr 29, 2026
69d003a
fix(test): always silence navy CLI debug in integration spawns
gilberthl-mh Apr 29, 2026
d7713c4
fix: route navy through DOCKER_HOST socket on setup-docker-action
gilberthl-mh Apr 29, 2026
24c1964
Fix vulnerabilities
gilberthl-mh Apr 29, 2026
be7d695
chore(deps): remediate npm audit vulnerabilities
gilberthl-mh Apr 29, 2026
cb0cc6b
fix: propagate navyFile through https CLI reconfigureHTTPProxy calls
gilberthl-mh Apr 29, 2026
46cb816
test: add c8 coverage tooling and 100% unit test coverage
gilberthl-mh May 5, 2026
4595136
docs: add DSO-638 change intent document
gilberthl-mh May 5, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions .c8rc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"all": true,
"include": [
"packages/*/src/**/*.js"
],
"exclude": [
"**/__tests__/**",
"**/node_modules/**",
"**/*.d.ts",
"packages/*/src/**/index.d.ts"
],
"reporter": [
"text",
"text-summary",
"html",
"lcov"
],
"report-dir": "./coverage",
"check-coverage": true,
"lines": 100,
"branches": 100,
"functions": 100,
"statements": 100
}
1 change: 1 addition & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
lib
website/build
flow-libs
5 changes: 1 addition & 4 deletions .eslintrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

extends: "standard"

plugins: ["flowtype", "import", "chai-friendly"]
plugins: ["import", "chai-friendly"]

rules:
space-before-function-paren: [2, {"anonymous": "always", "named": "never"}]
Expand All @@ -22,8 +22,5 @@

no-return-await: "off"

flowtype/define-flow-type: 2
flowtype/use-flow-type: 2

import/no-duplicates: "off"

3 changes: 1 addition & 2 deletions .flowconfig
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
[include]

[libs]
flow-libs/

[options]
esproposal.export_star_as=enable
suppress_comment= \\(.\\|\n\\)*\\$FlowIgnore
48 changes: 29 additions & 19 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,35 +6,45 @@ on:

jobs:
build:
runs-on: ubuntu-20.04
runs-on: ubuntu-latest
name: node-${{ matrix.node-version }} docker-${{ matrix.docker }} compose-${{ matrix.docker_compose }}
env:
DEBUG: 'navy:*'
NAVY_DEBUG: 'navy:*'
DEBUG: "navy:*"
NAVY_DEBUG: "navy:*"
strategy:
fail-fast: false
matrix:
node-version: [14.x, 16.x]
docker: [18.06-dind, 20.10.5-dind]
docker_compose: [1.14.0, 1.29.2, v2.10.2]
node-version: [22.x, 24.x]
docker: [v24.0.7, v27.3.1]
docker_compose: [v2.20.3, v2.29.7]

steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
env:
DOCKER_TAG: ${{matrix.docker}}
DOCKER_COMPOSE_VERSION: ${{matrix.docker_compose}}
GITHUB_NODE_VERSION: ${{matrix.node-version}}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- name: Setup Node.js
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
with:
node-version: ${{ matrix.node-version }}
- name: Before tests
run: node --version

- name: Setup Docker
uses: docker/setup-docker-action@b2189fbf2a6592b51fee7cdd93ee2bfaeba733db # v5.1.0
with:
version: ${{ matrix.docker }}
# Export DOCKER_HOST so the dockerode client used by navy and the
# `docker compose` CLI invoked by the navy driver both target the
# daemon installed by this action. Without this the action only
# configures a Docker CLI context (consumed by `docker compose`),
# while dockerode falls back to /var/run/docker.sock and ends up
# querying a different daemon, returning no matching containers.
set-host: true

- name: Setup Docker Compose
uses: docker/setup-compose-action@8cccb8c14b6500aaffebff1aa49c502c34d2e5e6 # v2.1.0
with:
version: ${{ matrix.docker_compose }}

- name: Install dependencies
run: npm ci
- name: Bostrap lerna
run: npm run bootstrap

- name: Test
run: npm test


4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,6 @@ npm-debug.log
lib
website/build
.vscode
.node-version
.node-version
coverage
.nyc_output
12 changes: 6 additions & 6 deletions babel.config.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
module.exports =
{
'presets': [
presets: [
'@babel/preset-typescript',
[
'@babel/preset-env', {
'targets': {
'node': '10',
targets: {
node: '22',
},
},
],
],
'plugins': [
plugins: [
'@babel/plugin-proposal-function-bind',
'add-module-exports',
'@babel/transform-flow-strip-types',
'@babel/transform-runtime',
'./resources/babel/transform-error-codes.js',
],
'parserOpts': {
'allowReturnOutsideFunction': true,
parserOpts: {
allowReturnOutsideFunction: true,
},
}
27 changes: 27 additions & 0 deletions docs/http-proxy.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,30 @@ This takes advantage of the [nip.io](http://nip.io) service, which provides a UR
This allows Navy to easily proxy all of your HTTP services by using virtual hosts in nginx, and also allows for you to quickly reconfigure Navy so it is using your external LAN IP for nip.io domains so you can easily test your services on other devices on your LAN.

Navy will automatically pick up and proxy any services which publish port 80, but if your service uses another port then you will need to [explicitly configure it in `Navyfile.js`](navyfile-config.md).

## Customising the proxy image

By default, Navy uses the `navycloud/navy-proxy` Docker image for the HTTP proxy. You can override this to use a custom image.

The image is resolved in the following order of precedence:

1. **`NAVY_HTTP_PROXY_IMAGE` environment variable** - highest precedence. Set this in your shell environment to override the proxy image globally.
2. **`httpProxyImage` property in `Navyfile.js`** - per-project override. See the [Navyfile.js reference](navyfile-config.md) for details.
3. **Default (`navycloud/navy-proxy`)** - used when neither of the above is set, preserving backwards-compatible behaviour.

### Examples

Override via environment variable:

```bash
export NAVY_HTTP_PROXY_IMAGE=myregistry/custom-proxy:latest
navy launch
```

Override via `Navyfile.js`:

```js
module.exports = {
httpProxyImage: 'myregistry/custom-proxy:latest',
}
```
151 changes: 151 additions & 0 deletions docs/intent/DSO-638-make-proxy-image-configurable.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
---
title: DSO-638 - Make Navy proxy image configurable
ticket: DSO-638
branch: dso-638-make-proxy-image-configurable
baseline: origin/master
---

# DSO-638 - Make Navy proxy image configurable

This document captures the intent behind the work on the `dso-638-make-proxy-image-configurable` branch and provides a high-level map of where each change lives. It is written for reviewers and future maintainers who need to understand why this branch is so large and how the changes group together, without reading every line of the diff.

## Snapshot

| Item | Value |
| --- | --- |
| Linear ticket | `DSO-638` |
| Branch | `dso-638-make-proxy-image-configurable` |
| Default branch in this repository | `master` (no `main` exists, so the diff is taken against `origin/master`) |
| Merge baseline (`origin/master`) | `035ecc9fc9fdf25f88cd4d90172cf68ebf7b7983` |
| Branch head | `46cb81613b240a19e7202265ccd067b72564d00c` |
| Commits ahead of `master` | 17 |
| Files changed | 190 |
| Approximate line delta | `+25,163 / -10,345` |

## Headline intent

The branch began as a focused product change: allow consumers of Navy to override the Docker image used by the built-in HTTP reverse proxy, instead of being hard-coded to `navycloud/navy-proxy`. While delivering that, the toolchain and continuous-integration setup turned out to be too stale to support a clean release on modern Node, so the work expanded to cover dependency modernisation, a CI overhaul, and a substantial unit-test backfill. There are therefore two distinct strands of intent in this branch:

1. **Product and operations intent.** Make the HTTP proxy image configurable per project and per environment, with a clear precedence order, while preserving the existing default so no consumer is forced to change anything.
2. **Engineering intent.** Bring the repository onto Node 22 and a current dependency set, fix npm-audit findings, stabilise CI so it works reliably with both the `dockerode` client and the `docker compose` CLI, and lift unit-test coverage to a level that lets future changes be made with confidence.

## Configurable proxy image

The user-facing change is the ability to override the proxy image either by setting the `NAVY_HTTP_PROXY_IMAGE` environment variable or by adding an `httpProxyImage` property to `Navyfile.js`. The environment variable wins if both are set, and the historical default `navycloud/navy-proxy` is used when neither is provided, so existing setups are unaffected.

The resolution logic and the related Docker socket helper now live in:

- `packages/navy/src/http-proxy.js` - new `resolveProxyImage` and `resolveDockerSocketPath` helpers, used when generating the proxy compose config.
- `packages/navy/src/__tests__/http-proxy.js` - covers the precedence order, empty-string fall-through, and `reconfigureHTTPProxy` plumbing.
- `packages/navy/src/middleware/add-service-proxy-config.js` - knock-on changes to keep `navyFile` available where it now matters.

The behaviour and precedence rules are documented for end users in:

- `docs/http-proxy.md` - new "Customising the proxy image" section with worked examples.
- `docs/navyfile-config.md` - new `httpProxyImage` entry in the `Navyfile.js` reference, cross-linked from the proxy guide.

A follow-up commit renamed the environment variable from `NAVY_PROXY_IMAGE` to `NAVY_HTTP_PROXY_IMAGE` so it sits alongside the rest of the HTTP proxy surface area.

## HTTPS and proxy reconfiguration correctness

While testing the configurable image, a latent bug surfaced: the HTTPS CLI path called `reconfigureHTTPProxy` without forwarding the resolved `navyFile`, which meant a custom `httpProxyImage` was silently dropped whenever HTTPS was toggled. The fix threads `navyFile` through the call chain and is covered by edge-case tests.

Primary locations:

- `packages/navy/src/cli/https.js` - propagates `navyFile` through `reconfigureHTTPProxy`.
- `packages/navy/src/cli/__tests__/https.js` - new tests for the propagation path.
- `packages/navy/src/__tests__/http-proxy.js` - asserts that `httpProxyImage` survives reconfiguration.

## Toolchain and monorepo modernisation

To get the proxy change to build and test on a current developer environment, the toolchain was lifted to Node 22 and the dependency tree was refreshed. The bulk of the line-count in the diff comes from the regenerated `package-lock.json`, but the meaningful edits are concentrated in:

- `package.json` - `engines.node` set to `>=22`, npm workspaces left in place, new `coverage` and `coverage-no-check` scripts wired up to `c8`.
- `lerna.json`, `babel.config.js`, `.flowconfig`, `flow-libs/` - Babel, Lerna and Flow configuration brought in line with the new toolchain, including refreshed Flow library definitions for current Node and npm modules.
- `.eslintrc.yml`, `.eslintignore` - lint configuration adjusted for the new parser and ignored paths.
- `.c8rc.json` - new coverage configuration enforcing the high coverage thresholds used by the test suite.
- `packages/navy/package.json`, `packages/navy-plugin-nodejs/package.json` - per-package dependency bumps to match the root.

Two commits in this strand are worth calling out: `chore(deps): remediate npm audit vulnerabilities` and `Fix vulnerabilities`, which together clear the audit output that the modernisation initially exposed.

## Unit-test expansion and coverage tooling

The final commit on the branch (`test: add c8 coverage tooling and 100% unit test coverage`) adds `c8` to the toolchain and lifts unit-test coverage close to 100% across the `navy` package. Most of the new test files do not change runtime behaviour, but they pin behaviour that was previously untested and would have made the modernisation risky to land. The new tests sit next to the modules they exercise, in a consistent `__tests__` layout:

- `packages/navy/src/__tests__/` - core flows: `config-provider.js`, `config.js`, `driver-logging.js`, `driver.js`, `errors.js`, `http-proxy.js`, `index.js`, `service.js`.
- `packages/navy/src/cli/__tests__/` - one test file per CLI command (`develop`, `external-ip`, `health`, `https`, `import`, `index`, `lan-ip`, `launch`, `live`, `local-ip`, `logs`, `open`, `program`, `ps`, `refresh-config`, `run`, `status`, `updates`, `wait-for-healthy`).
- `packages/navy/src/cli/config/__tests__/` and `packages/navy/src/cli/doctor/__tests__/` - configuration wrapper and doctor sub-commands.
- `packages/navy/src/cli/util/__tests__/` - shared CLI helpers (`get-or-initialise-navy`, `import`, `index`, `reconfigure`).
- `packages/navy/src/client/registry/__tests__/` - registry client (`get-credentials`, `get-endpoint`, `get-fat-manifest`, `get-token`, `helpers`).
- `packages/navy/src/config-providers/{filesystem,npm}/__tests__/` - configuration providers.
- `packages/navy/src/domain/__tests__/` - new domain helpers for `container-image` and `oci-api-specification`.
- `packages/navy/src/drivers/docker-compose/__tests__/` - driver client and entry point.
- `packages/navy/src/middleware/__tests__/` - all middleware modules (`add-service-proxy-config`, `develop`, `helpers`, `port-override`, `set-env-vars`, `set-image`, `set-logging-driver`, `tag-override`).
- `packages/navy/src/navy/__tests__/` - core orchestration (`default-middleware`, `index`, `middleware`, `plugin-interface`, `state`, `util`).
- `packages/navy/src/util/__tests__/` - utilities (`exec-async`, `external-ip`, `get-lan-ip`, `has-update`, `https`, `navyrc`, `service-host`, `table`).
- `packages/navy-plugin-nodejs/src/{hooks,middleware}/__tests__/` - plugin-side coverage for `rewrite-linked-node-modules` and `mount-user-home`.

The implementation files alongside these tests received small edits in the same commit to make them more easily testable and to address issues uncovered while writing the tests. These edits are deliberately narrow and do not change public behaviour.

## Integration tests and harness

Several integration-test fixes accompany the toolchain change, mostly to keep the suite working after `commander`, `rimraf`, and `nip.io`-style DNS behaviour shifted under newer dependencies. The Docker-based runner under `test/integration/runner/` was retired because the workflow now provisions Docker directly on the runner.

Primary locations:

- `test/integration/` - step definitions and helpers updated for new dependency versions; debug output silenced in spawned CLI processes to stop noisy logs masking failures.
- `scripts/integration.sh` - aligned with the new test layout.
- `test/integration/runner/Dockerfile`, `docker-entrypoint.sh`, `docker-login.sh` - removed; the workflow no longer needs an in-repo container to host the suite.

Relevant commits: `fix: align integration tests with rimraf v5 and commander v12`, `fix: pin dnsLookup to IPv4 to prevent macOS resolver flake`, `fix(test): silence navy CLI debug output in integration spawns`, `fix(test): always silence navy CLI debug in integration spawns`, and `Fix integration tests`.

## Continuous integration

CI now runs on a Node 22 and 24 matrix against two Docker and two Docker Compose versions, using pinned action SHAs. The most subtle change is the routing of `dockerode` and the `docker compose` CLI through the same daemon: `docker/setup-docker-action` is invoked with `set-host: true`, and a runtime helper honours `DOCKER_HOST` when it points at a unix socket so both clients agree on which daemon to talk to. Without this, `dockerode` would silently fall back to `/var/run/docker.sock` and query a different daemon than `docker compose`, producing empty container listings.

Primary locations:

- `.github/workflows/build.yaml` - Node matrix, Docker / Compose matrix, pinned action SHAs, and the `set-host: true` configuration with an explanatory comment.
- `packages/navy/src/http-proxy.js` - `resolveDockerSocketPath` ensures the proxy container mounts the same socket the rest of Navy uses.

Related commits: `Use Moneyhub runners for CICD` and `fix: route navy through DOCKER_HOST socket on setup-docker-action`.

## Commit narrative

The commits below are listed in chronological order and group naturally into the strands above.

- `de29042` chore: modernize dependencies for Node 22 support
- `ebe1c51` Make Navy proxy image configurable
- `2f873db` Fix navyFile propagation and add edge-case tests
- `9505dd6` rename NAVY_PROXY_IMAGE env var to NAVY_HTTP_PROXY_IMAGE
- `2efa4b4` Use Moneyhub runners for CICD
- `cf8c21f` style: fix linting issues across navy packages
- `e49a4cf` fix: restore Flow type-checking under flow-bin 0.311
- `6b69be6` fix: pin dnsLookup to IPv4 to prevent macOS resolver flake
- `70f723e` fix: align integration tests with rimraf v5 and commander v12
- `f3b074c` Fix integration tests
- `6973bb7` fix(test): silence navy CLI debug output in integration spawns
- `69d003a` fix(test): always silence navy CLI debug in integration spawns
- `d7713c4` fix: route navy through DOCKER_HOST socket on setup-docker-action
- `24c1964` Fix vulnerabilities
- `be7d695` chore(deps): remediate npm audit vulnerabilities
- `cb0cc6b` fix: propagate navyFile through https CLI reconfigureHTTPProxy calls
- `46cb816` test: add c8 coverage tooling and 100% unit test coverage

## Scope appendix - changed files by area

Counts come from `git diff --name-only origin/master...HEAD` aggregated by top-level area, and are useful for orienting reviewers before they open the diff.

| Area | Files changed |
| --- | --- |
| `packages/navy` | 140 |
| `test/integration` | 24 |
| Repository root (config, lockfile, etc.) | 9 |
| `packages/navy-plugin-nodejs` | 6 |
| `website` | 3 |
| `flow-libs` | 3 |
| `scripts` | 2 |
| `docs` | 2 |
| `.github` | 1 |

The heavy concentration in `packages/navy` reflects the unit-test backfill more than any sprawling refactor; the production source changes are narrowly scoped to the proxy-image feature, the HTTPS propagation fix, and small consistency edits that fell out of bringing the test suite to green.
5 changes: 5 additions & 0 deletions docs/navyfile-config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ module.exports = {
httpProxyAutoPorts: [
4080,
],
httpProxyImage: 'myregistry/custom-proxy:latest',
httpProxy: {
myotherservice: { port: 8080 }
},
Expand All @@ -45,6 +46,10 @@ A list of service names in the compose configuration which should be selected by

If using the [built in HTTP proxy](http-proxy.md), you can tell Navy to automatically register a service with the HTTP proxy, if it publishes any port in this list. This overrides port 80 for automatic registration.

### `httpProxyImage: ?string`

Overrides the Docker image used for the [built in HTTP proxy](http-proxy.md). Defaults to `navycloud/navy-proxy` if not set. The `NAVY_HTTP_PROXY_IMAGE` environment variable takes precedence over this property if both are set.

### `httpProxy: ?{[key: string]: { port: Number, enableHttps: Boolean }}`

If using the [built in HTTP proxy](http-proxy.md), you can tell Navy what port a service listens for HTTP connections here. If a service publishes port 80, or alternatively a port specified in `httpProxyAutoPorts`, it will automatically be registered with the HTTP proxy, so configuration here is unnecessary.
Expand Down
13 changes: 13 additions & 0 deletions flow-libs/node-globals.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
declare var process: {
env: {[key: string]: ?string},
argv: Array<string>,
stdout: any,
stderr: any,
cwd(): string,
on(event: string, listener: (...args: Array<any>) => mixed): any,
exit(code?: number): void,
...
};

declare var __dirname: string;
declare var __filename: string;
Loading