@florianpat/lando-core 3.26.3-1florianPat.8 → 3.26.5-1florianPat.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +40 -0
- package/CHANGELOG.md +11 -1
- package/app.js +23 -3
- package/builders/lando-compose.js +51 -0
- package/components/docker-engine.js +1 -0
- package/components/l337-v4.js +2 -2
- package/config.yml +6 -6
- package/hooks/app-add-2-landonet.js +1 -2
- package/hooks/app-add-proxy-2-landonet.js +1 -2
- package/hooks/app-add-v3-services.js +7 -7
- package/hooks/app-generate-v3-certs.js +2 -0
- package/hooks/app-purge-proxy-certs-and-config.js +24 -0
- package/hooks/app-start-proxy.js +3 -4
- package/hooks/lando-clean-networks.js +5 -1
- package/hooks/lando-setup-buildx.js +91 -0
- package/hooks/lando-setup-orchestrator.js +2 -2
- package/index.js +3 -0
- package/jsconfig.json +33 -0
- package/lib/app.js +13 -6
- package/lib/cli.js +1 -1
- package/lib/compose.js +2 -1
- package/lib/daemon.js +1 -1
- package/lib/lando.js +2 -2
- package/netlify.toml +4 -1
- package/node_modules/lodash/README.md +2 -2
- package/node_modules/lodash/_baseUnset.js +47 -2
- package/node_modules/lodash/core.js +1 -1
- package/node_modules/lodash/core.min.js +1 -1
- package/node_modules/lodash/lodash.js +43 -4
- package/node_modules/lodash/lodash.min.js +57 -57
- package/node_modules/lodash/package.json +1 -1
- package/node_modules/undici/README.md +7 -1
- package/node_modules/undici/docs/docs/api/ProxyAgent.md +3 -2
- package/node_modules/undici/index-fetch.js +3 -0
- package/node_modules/undici/lib/core/errors.js +162 -0
- package/node_modules/undici/lib/dispatcher/proxy-agent.js +83 -1
- package/node_modules/undici/lib/mock/mock-errors.js +11 -0
- package/node_modules/undici/lib/web/fetch/body.js +0 -4
- package/node_modules/undici/lib/web/fetch/index.js +16 -10
- package/node_modules/undici/lib/web/fetch/response.js +5 -0
- package/node_modules/undici/package.json +1 -1
- package/node_modules/undici/types/proxy-agent.d.ts +1 -0
- package/package.json +12 -8
- package/release-aliases/3-EDGE +1 -1
- package/release-aliases/3-STABLE +1 -1
- package/scripts/install-docker-engine.sh +1 -1
- package/scripts/lando-entrypoint.sh +8 -7
- package/scripts/load-keys.sh +5 -4
- package/scripts/user-perm-helpers.sh +64 -52
- package/scripts/user-perms.sh +34 -29
- package/tasks/exec.js +0 -1
- package/tasks/setup.js +6 -0
- package/utils/get-compose-x.js +1 -1
- package/utils/get-config-defaults.js +2 -1
- package/utils/load-compose-files.js +52 -5
- package/utils/load-config-files.js +1 -1
- package/builders/_lando-compose.js +0 -11
- package/node_modules/lodash/flake.lock +0 -40
- package/node_modules/lodash/flake.nix +0 -20
- package/node_modules/lodash/release.md +0 -48
- package/utils/parse-compose-services.js +0 -31
package/AGENTS.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
Lando is a local development orchestration tool built around Docker, recipes, and plugin-driven automation for app environments and developer tooling. Lando Core (`@lando/core`) is the event-driven Node.js runtime and plugin base behind the `lando` CLI: it bootstraps config, tasks, engine integration, app loading, and built-in plugin behavior.
|
|
4
|
+
|
|
5
|
+
## Maintenance
|
|
6
|
+
- Keep this file up to date. If you identify a serious repo-specific gotcha that is likely to trip future agents, update this file in the same change.
|
|
7
|
+
|
|
8
|
+
## Commands
|
|
9
|
+
- Use `npm`. Node 20 required.
|
|
10
|
+
- Full verification: `npm test`. Focused unit test: `npx mocha --timeout 5000 test/<file>.spec.js`.
|
|
11
|
+
- Integration tests: `npm run test:leia`. **Do not run locally** — they modify the host system and are CI-only.
|
|
12
|
+
- The `.lando.yml` at the project root is solely for docs work (VitePress); it has no relation to app code.
|
|
13
|
+
|
|
14
|
+
## Architecture
|
|
15
|
+
- `bin/lando` — CLI entrypoint/runtime selector.
|
|
16
|
+
- `lib/lando.js` — package main export; owns bootstrap sequencing.
|
|
17
|
+
- `index.js` — **not** the library entrypoint; it's the core plugin bootstrap that registers default config and lifecycle hooks.
|
|
18
|
+
- Most behavior is wired through events and hook modules, not direct imports. Start with `lib/lando.js`, `app.js`, and `index.js`, then follow `hooks/`.
|
|
19
|
+
- Bootstrap levels: `config → tasks → engine → app`. Tooling commands may only reach `engine` if compose cache exists, so not every CLI path initializes a full app.
|
|
20
|
+
|
|
21
|
+
## Config And Caches
|
|
22
|
+
- Landofile loading order (from the app root directory): `.lando.base.yml`, `.lando.dist.yml`, `.lando.recipe.yml`, `.lando.upstream.yml`, `.lando.yml`, `.lando.local.yml`, `.lando.user.yml`.
|
|
23
|
+
- CLI relies heavily on task cache and compose cache to decide bootstrap level and available commands.
|
|
24
|
+
- If a command change seems ignored, clear caches with `lando --clear` before assuming the code path is wrong.
|
|
25
|
+
|
|
26
|
+
## Writing
|
|
27
|
+
- Keep commit messages, PR descriptions, and issue comments concise.
|
|
28
|
+
- User-facing changes only in `CHANGELOG.md`'s `## {{ UNRELEASED_VERSION }}` section; follow the existing bullet and verb style.
|
|
29
|
+
|
|
30
|
+
## Repo-Specific Gotchas
|
|
31
|
+
- **Packaged binary**: adding runtime-loaded files or new top-level directories requires updating `pkg.assets` and `pkg.scripts` in `package.json`, or they'll be missing from the packaged CLI.
|
|
32
|
+
- **New source directories** must be added to `jsconfig.json` `include`, `package.json` `nyc.include`, and `package.json` `pkg.scripts`.
|
|
33
|
+
- **ESLint**: `require-jsdoc` applies to `FunctionDeclaration` only — arrow functions and expressions do not need JSDoc to pass lint.
|
|
34
|
+
- **`examples/**/README.md`** files are executable Leia specs — edits there affect CI test behavior.
|
|
35
|
+
|
|
36
|
+
## TypeScript Migration
|
|
37
|
+
- We are incrementally migrating to TypeScript via JSDoc type definitions. Add `@param`, `@return`, `@typedef` to any functions you modify or create.
|
|
38
|
+
- Type definitions go in co-located `.types.js` files (e.g., `utils/foo.types.js` next to `utils/foo.js`).
|
|
39
|
+
- `npm run typecheck` is not gated in CI. Use `npm run typecheck:full` to include node_modules errors.
|
|
40
|
+
- Use proper TypeScript types in JSDoc annotations.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }})
|
|
2
2
|
|
|
3
|
-
## v3.26.
|
|
3
|
+
## v3.26.5-1florianPat.0 - [May 24, 2026](https://github.com/HDNET/lando-core/releases/tag/v3.26.5-1florianPat.0)
|
|
4
|
+
|
|
5
|
+
## v3.26.4 - [April 28, 2026](https://github.com/lando/core/releases/tag/v3.26.4)
|
|
6
|
+
|
|
7
|
+
* Fixed `lando ssh` defaulting to a v3 service instead of the v4 `appserver` in mixed-api apps [#461](https://github.com/lando/core/pull/461)
|
|
8
|
+
|
|
9
|
+
## v3.26.3 - [April 14, 2026](https://github.com/lando/core/releases/tag/v3.26.3)
|
|
10
|
+
|
|
11
|
+
* Fixed crash when `config.yml` is empty instead of containing `{}` [#439](https://github.com/lando/core/issues/439)
|
|
12
|
+
* Updated `lando setup` to install `docker-buildx` if missing
|
|
13
|
+
* Fixed `buildx` built images not being available locally by adding `--load` flag
|
|
4
14
|
|
|
5
15
|
## v3.26.2 - [December 17, 2025](https://github.com/lando/core/releases/tag/v3.26.2)
|
|
6
16
|
|
package/app.js
CHANGED
|
@@ -137,9 +137,29 @@ module.exports = async (app, lando) => {
|
|
|
137
137
|
// Add localhost info to our containers if they are up
|
|
138
138
|
app.events.on('post-init-engine', async () => await require('./hooks/app-find-localhosts')(app, lando));
|
|
139
139
|
|
|
140
|
+
// Set LANDO_DOCKER_DATA_ROOT from docker info
|
|
141
|
+
// @NOTE: post-init-engine is skipped when noEngine is true (eg lando setup) so we dont
|
|
142
|
+
// try to hit docker when its not installed yet. app-find-localhosts above calls engine.list
|
|
143
|
+
// which goes through daemon.up() so docker is guaranteed running by this point.
|
|
144
|
+
app.events.on('post-init-engine', async () => {
|
|
145
|
+
try {
|
|
146
|
+
const info = await lando.engine.docker.info();
|
|
147
|
+
if (!info?.DockerRootDir) {
|
|
148
|
+
throw new Error();
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
app.env.LANDO_DOCKER_DATA_ROOT = info.DockerRootDir;
|
|
152
|
+
} catch (e) {
|
|
153
|
+
app.log.error('could not get docker info for data root');
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
|
|
140
157
|
// override default tooling commands if needed
|
|
141
158
|
app.events.on('ready', 1, async () => await require('./hooks/app-override-tooling-defaults')(app, lando));
|
|
142
159
|
|
|
160
|
+
// Generate certs for v3 SSL services as needed
|
|
161
|
+
app.events.on('ready', 2, async () => await require('./hooks/app-generate-v3-certs')(app, lando));
|
|
162
|
+
|
|
143
163
|
// set tooling compose cache
|
|
144
164
|
app.events.on('ready', async () => await require('./hooks/app-set-compose-cache')(app, lando));
|
|
145
165
|
|
|
@@ -173,9 +193,6 @@ module.exports = async (app, lando) => {
|
|
|
173
193
|
// Check for updates if the update cache is empty
|
|
174
194
|
app.events.on('pre-start', 1, async () => await require('./hooks/app-check-for-updates')(app, lando));
|
|
175
195
|
|
|
176
|
-
// Generate certs for v3 SSL services as needed
|
|
177
|
-
app.events.on('pre-start', 2, async () => await require('./hooks/app-generate-v3-certs')(app, lando));
|
|
178
|
-
|
|
179
196
|
// If the app already is installed but we can't determine the builtAgainst, then set it to something bogus
|
|
180
197
|
app.events.on('pre-start', async () => await require('./hooks/app-update-built-against-pre')(app, lando));
|
|
181
198
|
|
|
@@ -230,6 +247,9 @@ module.exports = async (app, lando) => {
|
|
|
230
247
|
// remove tooling cache
|
|
231
248
|
app.events.on('post-uninstall', async () => await require('./hooks/app-purge-recipe-cache')(app, lando));
|
|
232
249
|
|
|
250
|
+
// remove proxy certs and config
|
|
251
|
+
app.events.on('post-uninstall', async () => await require('./hooks/app-purge-proxy-certs-and-config')(app, lando));
|
|
252
|
+
|
|
233
253
|
// Remove meta cache on destroy
|
|
234
254
|
app.events.on('post-destroy', async () => await require('./hooks/app-purge-metadata-cache')(app, lando));
|
|
235
255
|
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const _ = require('lodash');
|
|
4
|
+
|
|
5
|
+
const toArray = value => Array.isArray(value) ? value : [];
|
|
6
|
+
|
|
7
|
+
module.exports = {
|
|
8
|
+
name: 'lando-compose',
|
|
9
|
+
api: 3,
|
|
10
|
+
parent: '_lando',
|
|
11
|
+
builder: parent => class LandoComposeServiceV3 extends parent {
|
|
12
|
+
constructor(id, options = {}) {
|
|
13
|
+
// get the original entrypoint and command from the compose data
|
|
14
|
+
// load-compose-files ensures these are populated from the image if not set in compose
|
|
15
|
+
const composeServices = _.get(options, '_app.composeData[0].data[0].services', {});
|
|
16
|
+
const composeService = _.get(composeServices, options.name, {});
|
|
17
|
+
|
|
18
|
+
const originalEntrypoint = toArray(composeService.entrypoint);
|
|
19
|
+
const originalCommand = toArray(composeService.command);
|
|
20
|
+
const composeWorkingDir = composeService.working_dir || null;
|
|
21
|
+
|
|
22
|
+
if (originalEntrypoint.length === 1 &&
|
|
23
|
+
(originalEntrypoint[0] === '/lando-entrypoint.sh' || originalEntrypoint[0] === '/helpers/lando-entrypoint.sh')
|
|
24
|
+
) {
|
|
25
|
+
options.landoEntrypoint = false;
|
|
26
|
+
}
|
|
27
|
+
const command = [...originalEntrypoint, ...originalCommand];
|
|
28
|
+
|
|
29
|
+
// If appMount is not explicitly set in options, use the compose working_dir (which
|
|
30
|
+
// load-compose-files resolves from the image if not set in compose), falling back to '/'
|
|
31
|
+
const appMount = options.appMount ?? composeWorkingDir ?? '/';
|
|
32
|
+
|
|
33
|
+
const opts = _.merge({}, {
|
|
34
|
+
// let the parent _lando set entrypoint to /lando-entrypoint.sh
|
|
35
|
+
data: null, // NOTE: Do not create the data volume
|
|
36
|
+
dataHome: null, // NOTE: Do not create the dataHome volume
|
|
37
|
+
appMount,
|
|
38
|
+
sslExpose: false,
|
|
39
|
+
ssl: true,
|
|
40
|
+
}, options);
|
|
41
|
+
|
|
42
|
+
if ((options.landoEntrypoint ?? true) && command.length > 0) {
|
|
43
|
+
opts.overrides = _.merge({}, {command}, options.overrides);
|
|
44
|
+
} else {
|
|
45
|
+
opts.entrypoint = undefined;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
super(id, opts);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
};
|
package/components/l337-v4.js
CHANGED
|
@@ -90,7 +90,7 @@ class L337ServiceV4 extends EventEmitter {
|
|
|
90
90
|
merge(this.#app.info.find(service => service.service === this.id) ?? {}, data);
|
|
91
91
|
}
|
|
92
92
|
this.emit('state', this.#data.info);
|
|
93
|
-
this.#app.v4.updateComposeCache();
|
|
93
|
+
if (this.#app.initialized) this.#app.v4.updateComposeCache();
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
get info() {
|
|
@@ -253,7 +253,7 @@ class L337ServiceV4 extends EventEmitter {
|
|
|
253
253
|
this.#app.compose = require('../utils/dump-compose-data')(this.#app.composeData, this.#app._dir);
|
|
254
254
|
|
|
255
255
|
// update and log
|
|
256
|
-
this.#app.v4.updateComposeCache();
|
|
256
|
+
if (this.#app.initialized) this.#app.v4.updateComposeCache();
|
|
257
257
|
}
|
|
258
258
|
|
|
259
259
|
// adds files/dirs to the build context
|
package/config.yml
CHANGED
|
@@ -11,23 +11,23 @@ stats:
|
|
|
11
11
|
|
|
12
12
|
dockerSupportedVersions:
|
|
13
13
|
compose:
|
|
14
|
-
satisfies: "1.x.x ||
|
|
15
|
-
recommendUpdate: "<=
|
|
16
|
-
tested: "<=
|
|
14
|
+
satisfies: "1.x.x || <6"
|
|
15
|
+
recommendUpdate: "<=5.1.0"
|
|
16
|
+
tested: "<=5.1.1"
|
|
17
17
|
link:
|
|
18
18
|
linux: https://docs.docker.com/compose/install/#install-compose-on-linux-systems
|
|
19
19
|
darwin: https://docs.docker.com/desktop/install/mac-install/
|
|
20
20
|
win32: https://docs.docker.com/desktop/install/windows-install/
|
|
21
21
|
desktop:
|
|
22
22
|
satisfies: ">=4.0.0 <5"
|
|
23
|
-
tested: "
|
|
24
|
-
recommendUpdate: "<=4.
|
|
23
|
+
tested: "<5"
|
|
24
|
+
recommendUpdate: "<=4.66"
|
|
25
25
|
link:
|
|
26
26
|
darwin: https://docs.docker.com/desktop/install/mac-install/
|
|
27
27
|
win32: https://docs.docker.com/desktop/install/windows-install/
|
|
28
28
|
wsl: https://docs.docker.com/desktop/install/windows-install/
|
|
29
29
|
engine:
|
|
30
30
|
satisfies: ">=18 <30"
|
|
31
|
-
tested: "
|
|
31
|
+
tested: "<30"
|
|
32
32
|
link:
|
|
33
33
|
linux: https://docs.docker.com/engine/install/debian/#install-using-the-convenience-script
|
|
@@ -15,8 +15,7 @@ module.exports = async (app, lando) => {
|
|
|
15
15
|
return landonet.disconnect({Container: container.id, Force: true})
|
|
16
16
|
// Only throw non not connected errors
|
|
17
17
|
.catch(error => {
|
|
18
|
-
if (!_.includes(error.message, 'is not connected to network')
|
|
19
|
-
!_.includes(error.message, 'is not connected to the network')) throw error;
|
|
18
|
+
if (!_.includes(error.message, 'is not connected to network')) throw error;
|
|
20
19
|
})
|
|
21
20
|
// Connect
|
|
22
21
|
.then(() => {
|
|
@@ -34,8 +34,7 @@ module.exports = async (app, lando) => {
|
|
|
34
34
|
return bridgeNet.disconnect({Container: proxyContainer, Force: true})
|
|
35
35
|
// Only throw non not connected errors
|
|
36
36
|
.catch(error => {
|
|
37
|
-
if (!_.includes(error.message, 'is not connected to network')
|
|
38
|
-
!_.includes(error.message, 'is not connected to the network')) throw error;
|
|
37
|
+
if (!_.includes(error.message, 'is not connected to network')) throw error;
|
|
39
38
|
})
|
|
40
39
|
// Connect
|
|
41
40
|
.then(() => {
|
|
@@ -5,14 +5,14 @@ const _ = require('lodash');
|
|
|
5
5
|
module.exports = async (app, lando) => {
|
|
6
6
|
// add parsed services to app object so we can use them downstream
|
|
7
7
|
app.cachedInfo = _.get(lando.cache.get(app.composeCache), 'info', []);
|
|
8
|
+
app.config.services = _.mapValues(_.get(app, 'config.services', {}), (service, name) => {
|
|
9
|
+
const composeServices = _.keys(_.get(app, 'composeData[0].data[0].services', {}));
|
|
10
|
+
if (!_.includes(composeServices, name) || service?.api === 4) {
|
|
11
|
+
return service;
|
|
12
|
+
}
|
|
13
|
+
return _.merge({}, {type: 'lando-compose', version: 'custom', api: 3}, service);
|
|
14
|
+
});
|
|
8
15
|
app.parsedServices = require('../utils/parse-v3-services')(_.get(app, 'config.services', {}), app);
|
|
9
|
-
app.parsedServices = app.parsedServices.concat(
|
|
10
|
-
require('../utils/parse-compose-services')(
|
|
11
|
-
_.get(app, 'config.services', {}),
|
|
12
|
-
_.keys(_.get(app, 'composeData[0].data[0].services', {})),
|
|
13
|
-
app,
|
|
14
|
-
),
|
|
15
|
-
);
|
|
16
16
|
app.parsedV3Services = _(app.parsedServices).filter(service => service.api === 3).value();
|
|
17
17
|
app.servicesList = app.parsedV3Services.map(service => service.name);
|
|
18
18
|
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const remove = require('../utils/remove');
|
|
6
|
+
|
|
7
|
+
module.exports = async (app, lando) => {
|
|
8
|
+
const certsDir = path.join(lando.config.userConfRoot, 'certs');
|
|
9
|
+
const proxyConfigDir = lando.config.proxyConfigDir;
|
|
10
|
+
|
|
11
|
+
for (const dir of [certsDir, proxyConfigDir]) {
|
|
12
|
+
if (!fs.existsSync(dir)) continue;
|
|
13
|
+
fs.readdirSync(dir)
|
|
14
|
+
.filter(f => f.includes(`.${app.project}.`))
|
|
15
|
+
.forEach(f => {
|
|
16
|
+
try {
|
|
17
|
+
remove(path.join(dir, f));
|
|
18
|
+
app.log.debug('removed proxy cert/config %s', f);
|
|
19
|
+
} catch {
|
|
20
|
+
app.log.debug('could not remove proxy cert/config %s', f);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
};
|
package/hooks/app-start-proxy.js
CHANGED
|
@@ -281,10 +281,9 @@ module.exports = async (app, lando) => {
|
|
|
281
281
|
}
|
|
282
282
|
|
|
283
283
|
// Get list of services that *should* have certs for SSL
|
|
284
|
-
const sslReady = _(
|
|
285
|
-
.
|
|
286
|
-
.
|
|
287
|
-
.map(data => data.name)
|
|
284
|
+
const sslReady = _(app.info)
|
|
285
|
+
.filter(data => data?.hasCerts)
|
|
286
|
+
.map(data => data.service)
|
|
288
287
|
.value();
|
|
289
288
|
|
|
290
289
|
// Make sure we augment ssl ready if we have served by candidates
|
|
@@ -3,7 +3,10 @@
|
|
|
3
3
|
// Modules
|
|
4
4
|
const _ = require('lodash');
|
|
5
5
|
|
|
6
|
-
module.exports = async lando =>
|
|
6
|
+
module.exports = async lando => {
|
|
7
|
+
if (lando.cache.get('_.networks.checked')) return;
|
|
8
|
+
lando.cache.set('_.networks.checked', true);
|
|
9
|
+
return lando.engine.getNetworks().then(networks => {
|
|
7
10
|
if (_.size(networks) >= lando.config.networkLimit) {
|
|
8
11
|
// Warn user about this action
|
|
9
12
|
lando.log.warn('Lando has detected you are at Docker\'s network limit!');
|
|
@@ -37,3 +40,4 @@ module.exports = async lando => lando.engine.getNetworks().then(networks => {
|
|
|
37
40
|
});
|
|
38
41
|
}
|
|
39
42
|
});
|
|
43
|
+
};
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const axios = require('../utils/get-axios')();
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
/*
|
|
8
|
+
* Helper to get buildx download url
|
|
9
|
+
*/
|
|
10
|
+
const getBuildxDownloadUrl = (version = '0.30.1') => {
|
|
11
|
+
const arch = process.arch === 'arm64' ? 'arm64' : 'amd64';
|
|
12
|
+
|
|
13
|
+
switch (process.platform) {
|
|
14
|
+
case 'darwin':
|
|
15
|
+
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.darwin-${arch}`;
|
|
16
|
+
case 'linux':
|
|
17
|
+
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.linux-${arch}`;
|
|
18
|
+
case 'win32':
|
|
19
|
+
return `https://github.com/docker/buildx/releases/download/v${version}/buildx-v${version}.windows-${arch}.exe`;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* Helper to get buildx download destination
|
|
25
|
+
*/
|
|
26
|
+
const getBuildxDownloadDest = home => {
|
|
27
|
+
const dir = path.join(home, '.docker', 'cli-plugins');
|
|
28
|
+
switch (process.platform) {
|
|
29
|
+
case 'linux':
|
|
30
|
+
case 'darwin':
|
|
31
|
+
return path.join(dir, 'docker-buildx');
|
|
32
|
+
case 'win32':
|
|
33
|
+
return path.join(dir, 'docker-buildx.exe');
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
module.exports = async (lando, options) => {
|
|
38
|
+
const debug = require('../utils/debug-shim')(lando.log);
|
|
39
|
+
const {color} = require('listr2');
|
|
40
|
+
|
|
41
|
+
// get stuff from config/opts
|
|
42
|
+
const {home} = lando.config;
|
|
43
|
+
const {buildx} = options;
|
|
44
|
+
|
|
45
|
+
// if buildx is set to false allow it to be skipped
|
|
46
|
+
if (buildx === false) return;
|
|
47
|
+
|
|
48
|
+
const dest = getBuildxDownloadDest(home);
|
|
49
|
+
const url = getBuildxDownloadUrl(buildx);
|
|
50
|
+
|
|
51
|
+
options.tasks.push({
|
|
52
|
+
title: `Downloading buildx`,
|
|
53
|
+
id: 'setup-buildx',
|
|
54
|
+
dependsOn: ['setup-build-engine'],
|
|
55
|
+
description: '@lando/buildx (docker-buildx)',
|
|
56
|
+
version: `Docker Buildx v${buildx}`,
|
|
57
|
+
hasRun: async () => {
|
|
58
|
+
try {
|
|
59
|
+
await require('../utils/run-command')('docker', ['buildx', 'version'], {debug});
|
|
60
|
+
return true;
|
|
61
|
+
} catch {
|
|
62
|
+
return false;
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
canRun: async () => {
|
|
66
|
+
// throw error if we cannot ping the download link
|
|
67
|
+
await axios.head(url);
|
|
68
|
+
// true if we get here
|
|
69
|
+
return true;
|
|
70
|
+
},
|
|
71
|
+
task: async (ctx, task) => new Promise((resolve, reject) => {
|
|
72
|
+
// ensure the cli-plugins directory exists
|
|
73
|
+
fs.mkdirSync(path.dirname(dest), {recursive: true});
|
|
74
|
+
|
|
75
|
+
const download = require('../utils/download-x')(url, {debug, dest, test: ['version']});
|
|
76
|
+
// success
|
|
77
|
+
download.on('done', data => {
|
|
78
|
+
task.title = `Installed buildx (Docker Buildx) to ${dest}`;
|
|
79
|
+
resolve(data);
|
|
80
|
+
});
|
|
81
|
+
// handle errors
|
|
82
|
+
download.on('error', error => {
|
|
83
|
+
reject(error);
|
|
84
|
+
});
|
|
85
|
+
// update title to reflect download progress
|
|
86
|
+
download.on('progress', progress => {
|
|
87
|
+
task.title = `Downloading buildx ${color.dim(`[${progress.percentage}%]`)}`;
|
|
88
|
+
});
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
};
|
|
@@ -7,7 +7,7 @@ const path = require('path');
|
|
|
7
7
|
/*
|
|
8
8
|
* Helper to get docker compose v2 download url
|
|
9
9
|
*/
|
|
10
|
-
const getComposeDownloadUrl = (version = '
|
|
10
|
+
const getComposeDownloadUrl = (version = '5.1.1') => {
|
|
11
11
|
const mv = version.split('.')[0] > 1 ? '2' : '1';
|
|
12
12
|
const arch = process.arch === 'arm64' ? 'aarch64' : 'x86_64';
|
|
13
13
|
const toggle = `${process.platform}-${mv}`;
|
|
@@ -31,7 +31,7 @@ const getComposeDownloadUrl = (version = '2.40.3') => {
|
|
|
31
31
|
/*
|
|
32
32
|
* Helper to get docker compose v2 download destination
|
|
33
33
|
*/
|
|
34
|
-
const getComposeDownloadDest = (base, version = '
|
|
34
|
+
const getComposeDownloadDest = (base, version = '5.1.1') => {
|
|
35
35
|
switch (process.platform) {
|
|
36
36
|
case 'linux':
|
|
37
37
|
case 'darwin':
|
package/index.js
CHANGED
|
@@ -97,6 +97,9 @@ module.exports = async lando => {
|
|
|
97
97
|
// ensure we setup docker-compose if needed
|
|
98
98
|
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-orchestrator')(lando, options));
|
|
99
99
|
|
|
100
|
+
// ensure we setup buildx if needed
|
|
101
|
+
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-buildx')(lando, options));
|
|
102
|
+
|
|
100
103
|
// ensure we setup landonet
|
|
101
104
|
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-landonet')(lando, options));
|
|
102
105
|
|
package/jsconfig.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"allowJs": true,
|
|
4
|
+
"checkJs": true,
|
|
5
|
+
"noEmit": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": false,
|
|
8
|
+
"moduleResolution": "node",
|
|
9
|
+
"ignoreDeprecations": "6.0",
|
|
10
|
+
"target": "es2022",
|
|
11
|
+
"resolveJsonModule": true
|
|
12
|
+
},
|
|
13
|
+
"include": [
|
|
14
|
+
"app.js",
|
|
15
|
+
"index.js",
|
|
16
|
+
"builders/**/*.js",
|
|
17
|
+
"components/**/*.js",
|
|
18
|
+
"experimental/**/*.js",
|
|
19
|
+
"hooks/**/*.js",
|
|
20
|
+
"inits/**/*.js",
|
|
21
|
+
"lib/**/*.js",
|
|
22
|
+
"messages/**/*.js",
|
|
23
|
+
"packages/**/*.js",
|
|
24
|
+
"plugins/**/*.js",
|
|
25
|
+
"renderers/**/*.js",
|
|
26
|
+
"sources/**/*.js",
|
|
27
|
+
"tasks/**/*.js",
|
|
28
|
+
"utils/**/*.js"
|
|
29
|
+
],
|
|
30
|
+
"exclude": [
|
|
31
|
+
"node_modules"
|
|
32
|
+
]
|
|
33
|
+
}
|
package/lib/app.js
CHANGED
|
@@ -300,8 +300,11 @@ module.exports = class App {
|
|
|
300
300
|
_.get(this, 'config.compose', []),
|
|
301
301
|
this.root,
|
|
302
302
|
this._dir,
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
this.engine,
|
|
304
|
+
this.project,
|
|
305
|
+
composeEnvFiles,
|
|
306
|
+
this.log,
|
|
307
|
+
_.get(this, '_config.orchestratorSeparator', '_'),
|
|
305
308
|
))
|
|
306
309
|
.then(composeFileData => {
|
|
307
310
|
this.composeData = [new this.ComposeService('compose', {}, ...composeFileData)];
|
|
@@ -381,11 +384,15 @@ module.exports = class App {
|
|
|
381
384
|
|
|
382
385
|
// reset the default service to the primary v4 service if we only have v4 services
|
|
383
386
|
if (this._serviceApi === 4) this._defaultService = this.v4.primaryService.name;
|
|
384
|
-
// reset the default service to the first v3 service if there is no appserver
|
|
385
|
-
else if (this.serviceGroups['3'].length > 0
|
|
387
|
+
// reset the default service to the first v3 service if there is no appserver in v3 or v4
|
|
388
|
+
else if (this.serviceGroups['3'].length > 0
|
|
389
|
+
&& !_.find(this.serviceGroups['3'], {service: 'appserver'})
|
|
390
|
+
&& !_.find(this.serviceGroups['4'], {service: 'appserver'})) {
|
|
386
391
|
this._defaultService = this.serviceGroups['3'][0].service;
|
|
387
|
-
// reset the default service to the first compose service if there is no appserver
|
|
388
|
-
} else if (this.serviceGroups.compose.length > 0
|
|
392
|
+
// reset the default service to the first compose service if there is no appserver in compose or v4
|
|
393
|
+
} else if (this.serviceGroups.compose.length > 0
|
|
394
|
+
&& !_.find(this.serviceGroups.compose, {service: 'appserver'})
|
|
395
|
+
&& !_.find(this.serviceGroups['4'], {service: 'appserver'})) {
|
|
389
396
|
this._defaultService = this.serviceGroups.compose[0].service;
|
|
390
397
|
}
|
|
391
398
|
|
package/lib/cli.js
CHANGED
|
@@ -560,7 +560,7 @@ module.exports = class Cli {
|
|
|
560
560
|
const Yaml = require(`../lib/yaml`);
|
|
561
561
|
const yaml = new Yaml();
|
|
562
562
|
const configFile = path.join(this.defaultConfig().userConfRoot, 'config.yml');
|
|
563
|
-
const config = (fs.existsSync(configFile)) ? yaml.load(configFile) : {};
|
|
563
|
+
const config = (fs.existsSync(configFile)) ? yaml.load(configFile) || {} : {};
|
|
564
564
|
const file = yaml.dump(configFile, _.assign({}, config, data));
|
|
565
565
|
return yaml.load(file);
|
|
566
566
|
}
|
package/lib/compose.js
CHANGED
|
@@ -15,6 +15,7 @@ const composeFlags = {
|
|
|
15
15
|
noTTY: '-T',
|
|
16
16
|
pull: '--pull',
|
|
17
17
|
q: '--quiet',
|
|
18
|
+
quietPull: '--quiet-pull',
|
|
18
19
|
recreate: '--force-recreate',
|
|
19
20
|
removeOrphans: '--remove-orphans',
|
|
20
21
|
rm: '--rm',
|
|
@@ -33,7 +34,7 @@ const composeFlagOptionMapping = {
|
|
|
33
34
|
ps: ['q'],
|
|
34
35
|
pull: ['q', 'ignoreBuildable'],
|
|
35
36
|
rm: ['force', 'volumes'],
|
|
36
|
-
up: ['background', 'detach', 'noRecreate', 'noDeps', 'pull', 'q', 'recreate', 'removeOrphans', 'timestamps'],
|
|
37
|
+
up: ['background', 'detach', 'noRecreate', 'noDeps', 'pull', 'q', 'recreate', 'removeOrphans', 'timestamps', 'quietPull'],
|
|
37
38
|
config: ['outputFilePath', 'q'],
|
|
38
39
|
};
|
|
39
40
|
|
package/lib/daemon.js
CHANGED
|
@@ -54,7 +54,7 @@ module.exports = class LandoDaemon {
|
|
|
54
54
|
log = new Log(),
|
|
55
55
|
context = 'node',
|
|
56
56
|
compose = require('../utils/get-compose-x')(),
|
|
57
|
-
orchestratorVersion = '
|
|
57
|
+
orchestratorVersion = '5.1.1',
|
|
58
58
|
userConfRoot = path.join(os.homedir(), '.lando'),
|
|
59
59
|
) {
|
|
60
60
|
this.cache = cache;
|
package/lib/lando.js
CHANGED
|
@@ -402,7 +402,7 @@ module.exports = class Lando {
|
|
|
402
402
|
caKey = this.config.caKey,
|
|
403
403
|
domains = [],
|
|
404
404
|
organization = 'Lando Alliance',
|
|
405
|
-
validity =
|
|
405
|
+
validity = 3650,
|
|
406
406
|
} = {}) {
|
|
407
407
|
const read = require('../utils/read-file');
|
|
408
408
|
const write = require('../utils/write-file');
|
|
@@ -465,7 +465,7 @@ module.exports = class Lando {
|
|
|
465
465
|
}
|
|
466
466
|
|
|
467
467
|
// Load the config and augment so we can get an App
|
|
468
|
-
const config = lmerge({}, ..._.map(landoFiles, file => yaml.load(file)));
|
|
468
|
+
const config = lmerge({}, ..._.map(landoFiles, file => yaml.load(file) || {}));
|
|
469
469
|
this.log.info('loading app %s from config files', config.name, landoFiles);
|
|
470
470
|
// Return us some app!
|
|
471
471
|
const App = require('./app');
|
package/netlify.toml
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# lodash v4.17.
|
|
1
|
+
# lodash v4.17.23
|
|
2
2
|
|
|
3
3
|
The [Lodash](https://lodash.com/) library exported as [Node.js](https://nodejs.org/) modules.
|
|
4
4
|
|
|
@@ -28,7 +28,7 @@ var at = require('lodash/at');
|
|
|
28
28
|
var curryN = require('lodash/fp/curryN');
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
See the [package source](https://github.com/lodash/lodash/tree/4.17.
|
|
31
|
+
See the [package source](https://github.com/lodash/lodash/tree/4.17.23-npm) for more details.
|
|
32
32
|
|
|
33
33
|
**Note:**<br>
|
|
34
34
|
Install [n_](https://www.npmjs.com/package/n_) for Lodash use in the Node.js < 6 REPL.
|