@florianpat/lando-core 3.23.27-1florianPat.0 → 3.23.27-4florianPat.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/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  ## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }})
2
2
 
3
- ## v3.23.27-1florianPat.0 - [February 17, 2025](https://github.com/florianPat/lando-core/releases/tag/v3.23.27-1florianPat.0)
3
+ ## v3.23.27-4florianPat.0 - [March 4, 2025](https://github.com/florianPat/lando-core/releases/tag/v3.23.27-4florianPat.0)
4
4
 
5
5
  ## v3.23.26 - [January 24, 2025](https://github.com/lando/core/releases/tag/v3.23.26)
6
6
 
package/app.js CHANGED
@@ -113,6 +113,9 @@ module.exports = async (app, lando) => {
113
113
  // Add tooling if applicable
114
114
  app.events.on('post-init', async () => await require('./hooks/app-add-tooling')(app, lando));
115
115
 
116
+ // Add _init tooling for bootstrap reference
117
+ app.events.on('pre-bootstrap', async () => await require('./hooks/app-add-init-tooling')(app, lando));
118
+
116
119
  // Collect info so we can inject LANDO_INFO
117
120
  // @NOTE: this is not currently the full lando info because a lot of it requires the app to be on
118
121
  app.events.on('post-init', 10, async () => await require('./hooks/app-set-lando-info')(app, lando));
@@ -0,0 +1,21 @@
1
+ 'use strict';
2
+
3
+ const _ = require('lodash');
4
+
5
+ module.exports = async (app, lando) => {
6
+ if (!_.isEmpty(_.get(app, 'config.tooling', {}))) {
7
+ app.log.verbose('additional tooling detected');
8
+
9
+ // Add the _init tasks for the bootstrap event!
10
+ // TODO(flo): They are duplicated through "app-add-tooling" but I do not care for now!
11
+ _.forEach(require('../utils/get-tooling-tasks')(app.config.tooling, app), task => {
12
+ if (task.service !== '_init') {
13
+ return;
14
+ }
15
+
16
+ app.log.debug('adding app cli task %s', task.name);
17
+ const injectable = _.has(app, 'engine') ? app : lando;
18
+ app.tasks.push(require('../utils/build-tooling-task')(task, injectable));
19
+ });
20
+ }
21
+ };
package/lib/app.js CHANGED
@@ -11,8 +11,8 @@ const fs = require('node:fs');
11
11
  /*
12
12
  * Helper to init and then report
13
13
  */
14
- const initAndReport = (app, method = 'start') => {
15
- return app.init().then(() => {
14
+ const initAndReport = (app, method, shouldBootstrap = false) => {
15
+ return app.init({shouldBootstrap}).then(() => {
16
16
  app.metrics.report(method, utils.metricsParse(app));
17
17
  return Promise.resolve(true);
18
18
  });
@@ -257,6 +257,8 @@ module.exports = class App {
257
257
  .then(() => this.log.info('destroyed app.'));
258
258
  };
259
259
 
260
+ static isBootstrapCommand = undefined;
261
+
260
262
  /**
261
263
  * Initializes the app
262
264
  *
@@ -270,21 +272,39 @@ module.exports = class App {
270
272
  * @fires ready
271
273
  * @return {Promise} A Promise.
272
274
  */
273
- init({noEngine = false} = {}) {
275
+ init({noEngine = false, shouldBootstrap = false} = {}) {
274
276
  // We should only need to initialize once, if we have just go right to app ready
275
277
  if (this.initialized) return this.events.emit('ready', this);
278
+ if (undefined === App.isBootstrapCommand) {
279
+ App.isBootstrapCommand = !fs.existsSync(this._dir);
280
+ }
281
+ const bootstrapping = App.isBootstrapCommand && shouldBootstrap && !noEngine;
282
+ if (bootstrapping) {
283
+ console.log(require('yargonaut').chalk().cyan('Looks like this is the first time to start the app. Lets bootstrap it...'));
284
+ }
285
+
286
+ const composeEnvFiles = require('../utils/normalize-files')(_.get(this, 'config.compose_env_file', []), this.root);
287
+
288
+ return loadPlugins(this, this._lando)
289
+ /**
290
+ * Event that only gets triggered if the app never started before (or was destroyed)
291
+ *
292
+ * @since 3.23.25
293
+ * @alias app.events:pre-bootstrap
294
+ * @event pre-bootstrap
295
+ * @property {App} app The app instance.
296
+ */
297
+ .then(() => bootstrapping ? this.events.emit('pre-bootstrap', this) : undefined)
276
298
  // Get compose data if we have any, otherwise set to []
277
- return require('../utils/load-compose-files')(
299
+ .then(() => noEngine === true ? [] : require('../utils/load-compose-files')(
278
300
  _.get(this, 'config.compose', []),
279
301
  this.root,
280
302
  this._dir,
281
303
  (composeFiles, outputFilePath) =>
282
- this.engine.getComposeConfig({compose: composeFiles, project: this.project, outputFilePath}),
283
- )
304
+ this.engine.getComposeConfig({compose: composeFiles, project: this.project, outputFilePath, opts: {envFiles: composeEnvFiles}}),
305
+ ))
284
306
  .then(composeFileData => {
285
- if (undefined !== composeFileData) {
286
- this.composeData = [new this.ComposeService('compose', {}, composeFileData)];
287
- }
307
+ this.composeData = [new this.ComposeService('compose', {}, ...composeFileData)];
288
308
  // Validate and set env files
289
309
  this.envFiles = require('../utils/normalize-files')(_.get(this, 'config.env_file', []), this.root);
290
310
  // Log some things
@@ -303,8 +323,6 @@ module.exports = class App {
303
323
  * @event pre_init
304
324
  * @property {App} app The app instance.
305
325
  */
306
- .then(() => loadPlugins(this, this._lando))
307
-
308
326
  .then(() => this.events.emit('pre-init', this))
309
327
  // Actually assemble this thing so its ready for that engine
310
328
  .then(() => {
@@ -501,25 +519,15 @@ module.exports = class App {
501
519
  * @alias app.start
502
520
  * @fires pre_start
503
521
  * @fires post_start
522
+ * @fires post_bootstrap
504
523
  * @return {Promise} A Promise.
505
524
  *
506
525
  */
507
526
  start() {
508
527
  // Log
509
528
  this.log.info('starting app...');
510
- const shouldBootstrap = fs.existsSync(this._dir);
511
529
 
512
- return initAndReport(this)
513
-
514
- /**
515
- * Event that only gets triggered if the app never started before (or was destroyed)
516
- *
517
- * @since 3.22.3
518
- * @alias app.events:pre-bootstrap
519
- * @event pre-bootstrap
520
- * @property {App} app The app instance.
521
- */
522
- .then(() => shouldBootstrap ? this.events.emit('pre-bootstrap', this) : undefined)
530
+ return initAndReport(this, 'start', true)
523
531
 
524
532
  /**
525
533
  * Event that runs before an app starts up.
@@ -551,12 +559,12 @@ module.exports = class App {
551
559
  /**
552
560
  * Event that only gets triggered if the app never started before (or was destroyed)
553
561
  *
554
- * @since 3.22.3
562
+ * @since 3.23.25
555
563
  * @alias app.events:post-bootstrap
556
564
  * @event post-bootstrap
557
565
  * @property {App} app The app instance.
558
566
  */
559
- .then(() => shouldBootstrap ? this.events.emit('post-bootstrap', this) : undefined)
567
+ .then(() => App.isBootstrapCommand ? this.events.emit('post-bootstrap', this) : undefined)
560
568
 
561
569
  .then(() => this.log.info('started app.'));
562
570
  };
package/lib/compose.js CHANGED
@@ -77,21 +77,22 @@ const parseOptions = (opts = {}) => {
77
77
  /*
78
78
  * Helper to standardize construction of docker commands
79
79
  */
80
- const buildCmd = (run, name, compose, {services, cmd}, opts = {}) => {
80
+ const buildCmd = (run, name, compose, {services, cmd, envFiles}, opts = {}) => {
81
81
  if (!name) throw new Error('Need to give this composition a project name!');
82
82
  // @TODO: we need to strip out opts.user on start/stop because we often get it as part of run
83
83
  const project = ['--project-name', name];
84
84
  const files = _.flatten(_.map(compose, unit => ['--file', unit]));
85
+ const envFile = _.flatten(_.map(envFiles, unit => ['--env-file', unit]));
85
86
  const options = parseOptions(opts);
86
87
  const argz = _.flatten(_.compact([services, cmd]));
87
- return _.flatten([project, files, run, options, argz]);
88
+ return _.flatten([project, files, envFile, run, options, argz]);
88
89
  };
89
90
 
90
91
  /*
91
92
  * Helper to build build object needed by lando.shell.sh
92
93
  */
93
94
  const buildShell = (run, name, compose, opts = {}) => ({
94
- cmd: buildCmd(run, name, compose, {services: opts.services, cmd: opts.cmd}, mergeOpts(run, opts)),
95
+ cmd: buildCmd(run, name, compose, {services: opts.services, cmd: opts.cmd, envFiles: opts.envFiles ?? []}, mergeOpts(run, opts)),
95
96
  opts: {mode: 'spawn', cstdio: opts.cstdio, silent: opts.silent},
96
97
  });
97
98
 
package/lib/engine.js CHANGED
@@ -172,7 +172,7 @@ module.exports = class Engine {
172
172
  * return lando.engine.exists(compose);
173
173
  */
174
174
  exists(data) {
175
- return this.engineCmd('exists', data);
175
+ return this.engineCmd('exists', _.merge({}, {separator: this.separator}, data));
176
176
  };
177
177
 
178
178
  /*
@@ -506,6 +506,7 @@ module.exports = class Engine {
506
506
  * @param {String} data.project A String of the project name (Usually this is the same as the app name)
507
507
  * @param {String} [data.outputFilePath='/path/to/file.yml'] String to output path
508
508
  * @param {Object} [data.opts] Options
509
+ * @param {Array} [data.opts.envFiles] An Array of paths to env files
509
510
  * @return {Promise} A Promise.
510
511
  * @example
511
512
  * return lando.engine.stop(app);
package/lib/formatters.js CHANGED
@@ -135,7 +135,7 @@ exports.handleInteractive = (inquiry, argv, command, lando) => lando.Promise.try
135
135
  // NOTE: We need to clone deep here otherwise any apps with interactive options get 2x all their events
136
136
  // NOTE: Not exactly clear on why app here gets conflated with the app returned from lando.getApp
137
137
  const app = _.cloneDeep(lando.getApp(argv._app.root));
138
- return app.init().then(() => {
138
+ return app.init({noEngine: true}).then(() => {
139
139
  inquiry = exports.getInteractive(_.find(app.tasks.concat(lando.tasks), {command: command}).options, argv);
140
140
  return inquirer.prompt(_.sortBy(inquiry, 'weight'));
141
141
  });
package/lib/router.js CHANGED
@@ -55,7 +55,7 @@ exports.destroy = (data, compose, docker) => retryEach(data, datum => {
55
55
  exports.exists = (data, compose, docker, ids = []) => {
56
56
  if (data.compose) return compose('getId', data).then(id => !_.isEmpty(id));
57
57
  else {
58
- return docker.list()
58
+ return docker.list({}, data.separator)
59
59
  .each(container => {
60
60
  ids.push(container.id);
61
61
  ids.push(container.name);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@florianpat/lando-core",
3
3
  "description": "The libraries that power all of Lando. Fork by flo for compose integration",
4
- "version": "3.23.27-1florianPat.0",
4
+ "version": "3.23.27-4florianPat.0",
5
5
  "author": "Florian Patruck @florianPat",
6
6
  "license": "GPL-3.0",
7
7
  "repository": "florianPat/lando-core",
@@ -247,9 +247,9 @@
247
247
  "yargs-parser"
248
248
  ],
249
249
  "dist": {
250
- "integrity": "sha512-EF8oq87DSgrav9p/64DkDyDuudJ/hW3soeFWiiuZzhjIIZ52UV98g6DGiIjVVyowcVtuAL6sAf/cidZkv7s+tQ==",
251
- "shasum": "7fa58d190ddcacde2bb53ede9fffc5d92c0bb42c",
252
- "filename": "florianpat-lando-core-3.23.27-1florianPat.0.tgz",
253
- "unpackedSize": 60965868
250
+ "integrity": "sha512-/98U+xsnU1BnJCQAsZZlui8fGnMYfhATamRCi/wy9j29g76GPwXAR5/smdRmEq+Ibyt6SRSvxRVLp9cC7HvERw==",
251
+ "shasum": "4a4b0505a255aaf87c0a7e663f143a1c43de652d",
252
+ "filename": "florianpat-lando-core-3.23.27-4florianPat.0.tgz",
253
+ "unpackedSize": 60967690
254
254
  }
255
255
  }
@@ -23,7 +23,7 @@ module.exports = (config, injected) => {
23
23
  const run = answers => {
24
24
  let initToolingRunner = null;
25
25
 
26
- return injected.Promise.try(() => (_.isEmpty(app.compose)) ? app.init() : true)
26
+ return injected.Promise.try(() => (_.isEmpty(app.compose) && '_init' !== service) ? app.init() : true)
27
27
  // Kick off the pre event wrappers
28
28
  .then(() => app.events.emit(`pre-${eventName}`, config, answers))
29
29
  // Get an interable of our commandz
@@ -74,5 +74,6 @@ module.exports = (config, injected) => {
74
74
  describe,
75
75
  run,
76
76
  options,
77
+ service,
77
78
  };
78
79
  };
@@ -5,8 +5,6 @@ const path = require('path');
5
5
 
6
6
  module.exports = (platform = process.landoPlatform ?? process.platform) => {
7
7
  switch (platform) {
8
- case 'darwin':
9
- return '/Applications/Docker.app/Contents/Resources/bin';
10
8
  case 'linux':
11
9
  return '/usr/share/lando/bin';
12
10
  case 'win32':
@@ -3,6 +3,7 @@
3
3
  const _ = require('lodash');
4
4
  const fs = require('fs');
5
5
  const path = require('path');
6
+ const App = require('../lib/app');
6
7
 
7
8
  /*
8
9
  * Paths to /
@@ -40,9 +41,10 @@ const loadCacheFile = file => {
40
41
  */
41
42
  const appRunner = command => (argv, lando) => {
42
43
  const app = lando.getApp(argv._app.root);
44
+ const service = _.get(app.config, `tooling.${command}.service`, '');
43
45
  return lando.events.emit('pre-app-runner', app)
44
46
  .then(() => lando.events.emit('pre-command-runner', app))
45
- .then(() => app.init().then(() => _.find(app.tasks, {command}).run(argv)));
47
+ .then(() => app.init({noEngine: '_init' === service}).then(() => _.find(app.tasks, {command}).run(argv)));
46
48
  };
47
49
 
48
50
  /*
@@ -128,7 +130,7 @@ module.exports = (config = {}, argv = {}, tasks = []) => {
128
130
 
129
131
  // If the tooling command is being called lets assess whether we can get away with engine bootstrap level
130
132
  const ids = _(config.tooling).map(task => task.id).filter(_.identity).value();
131
- const level = (_.includes(ids, argv._[0])) ? getBsLevel(config, argv._[0]) : 'app';
133
+ const level = !App.isBootstrapCommand && (_.includes(ids, argv._[0])) ? getBsLevel(config, argv._[0]) : 'app';
132
134
 
133
135
  // Load all the tasks, remember we need to remove "disabled" tasks (eg non-object tasks) here
134
136
  _.forEach(_.get(config, 'tooling', {}), (task, command) => {
@@ -12,7 +12,7 @@ const remove = require('./remove');
12
12
  module.exports = async (files, dir, landoComposeConfigDir = undefined, outputConfigFunction = undefined) => {
13
13
  const composeFilePaths = _(require('./normalize-files')(files, dir)).value();
14
14
  if (_.isEmpty(composeFilePaths)) {
15
- return {};
15
+ return [];
16
16
  }
17
17
 
18
18
  if (undefined === outputConfigFunction) {
@@ -29,5 +29,5 @@ module.exports = async (files, dir, landoComposeConfigDir = undefined, outputCon
29
29
  fs.unlinkSync(outputFile);
30
30
  remove(path.dirname(outputFile));
31
31
 
32
- return result;
32
+ return [result];
33
33
  };