@enspirit/emb 0.22.1 → 0.24.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.
Files changed (54) hide show
  1. package/README.md +91 -117
  2. package/dist/src/cli/abstract/KubernetesCommand.d.ts +5 -1
  3. package/dist/src/cli/abstract/KubernetesCommand.js +11 -2
  4. package/dist/src/cli/commands/components/shell.d.ts +1 -1
  5. package/dist/src/cli/commands/components/shell.js +8 -6
  6. package/dist/src/cli/commands/down.d.ts +4 -0
  7. package/dist/src/cli/commands/down.js +17 -12
  8. package/dist/src/cli/commands/kubernetes/logs.js +7 -12
  9. package/dist/src/cli/commands/kubernetes/ps.js +2 -1
  10. package/dist/src/cli/commands/kubernetes/restart.js +2 -1
  11. package/dist/src/cli/commands/kubernetes/shell.js +7 -10
  12. package/dist/src/cli/commands/logs/archive.d.ts +1 -1
  13. package/dist/src/cli/commands/logs/archive.js +12 -11
  14. package/dist/src/cli/commands/logs/index.d.ts +1 -1
  15. package/dist/src/cli/commands/logs/index.js +12 -12
  16. package/dist/src/cli/commands/restart.d.ts +1 -1
  17. package/dist/src/cli/commands/restart.js +10 -9
  18. package/dist/src/cli/commands/start.d.ts +1 -1
  19. package/dist/src/cli/commands/start.js +7 -10
  20. package/dist/src/cli/commands/stop.d.ts +4 -0
  21. package/dist/src/cli/commands/stop.js +17 -12
  22. package/dist/src/cli/commands/up.d.ts +1 -1
  23. package/dist/src/cli/commands/up.js +20 -19
  24. package/dist/src/config/schema.d.ts +33 -1
  25. package/dist/src/config/schema.json +42 -1
  26. package/dist/src/docker/compose/client.d.ts +15 -1
  27. package/dist/src/docker/compose/client.js +32 -2
  28. package/dist/src/docker/compose/operations/ComposeDownOperation.d.ts +6 -6
  29. package/dist/src/docker/compose/operations/ComposeDownOperation.js +28 -9
  30. package/dist/src/docker/compose/operations/ComposeLogsArchiveOperation.d.ts +3 -3
  31. package/dist/src/docker/compose/operations/ComposeLogsArchiveOperation.js +12 -13
  32. package/dist/src/docker/compose/operations/ComposeStopOperation.d.ts +6 -6
  33. package/dist/src/docker/compose/operations/ComposeStopOperation.js +28 -9
  34. package/dist/src/docker/compose/operations/ComposeUpOperation.d.ts +1 -1
  35. package/dist/src/docker/compose/operations/ComposeUpOperation.js +4 -4
  36. package/dist/src/kubernetes/index.d.ts +1 -0
  37. package/dist/src/kubernetes/index.js +1 -0
  38. package/dist/src/kubernetes/operations/GetComponentPodOperation.d.ts +17 -0
  39. package/dist/src/kubernetes/operations/GetComponentPodOperation.js +77 -0
  40. package/dist/src/kubernetes/operations/GetDeploymentPodsOperation.js +3 -2
  41. package/dist/src/kubernetes/operations/PodExecOperation.d.ts +20 -0
  42. package/dist/src/kubernetes/operations/PodExecOperation.js +158 -0
  43. package/dist/src/kubernetes/operations/index.d.ts +3 -0
  44. package/dist/src/kubernetes/operations/index.js +3 -0
  45. package/dist/src/kubernetes/utils/index.d.ts +1 -0
  46. package/dist/src/kubernetes/utils/index.js +1 -0
  47. package/dist/src/kubernetes/utils/resolveNamespace.d.ts +13 -0
  48. package/dist/src/kubernetes/utils/resolveNamespace.js +12 -0
  49. package/dist/src/monorepo/operations/tasks/RunTasksOperation.d.ts +2 -0
  50. package/dist/src/monorepo/operations/tasks/RunTasksOperation.js +43 -3
  51. package/oclif.manifest.json +228 -278
  52. package/package.json +1 -1
  53. package/dist/src/cli/commands/components/logs.d.ts +0 -14
  54. package/dist/src/cli/commands/components/logs.js +0 -44
@@ -4,7 +4,7 @@ import { ComposeExecShellOperation } from '../../../docker/index.js';
4
4
  import { ShellExitError } from '../../../errors.js';
5
5
  export default class ComponentShellCommand extends BaseCommand {
6
6
  static aliases = ['shell'];
7
- static description = 'Get a shell on a running component.';
7
+ static description = 'Get a shell on a running service.';
8
8
  static enableJsonFlag = false;
9
9
  static examples = ['<%= config.bin %> <%= command.id %>'];
10
10
  static flags = {
@@ -16,18 +16,20 @@ export default class ComponentShellCommand extends BaseCommand {
16
16
  }),
17
17
  };
18
18
  static args = {
19
- component: Args.string({
20
- name: 'component',
21
- description: 'The component you want to get a shell on',
19
+ service: Args.string({
20
+ name: 'service',
21
+ description: 'The service you want to get a shell on',
22
22
  required: true,
23
23
  }),
24
24
  };
25
25
  async run() {
26
26
  const { flags, args } = await this.parse(ComponentShellCommand);
27
- const { monorepo } = await getContext();
27
+ const { monorepo, compose } = getContext();
28
+ // Validate service exists in docker-compose.yml
29
+ await compose.validateService(args.service);
28
30
  try {
29
31
  await monorepo.run(new ComposeExecShellOperation(), {
30
- service: args.component,
32
+ service: args.service,
31
33
  shell: flags.shell,
32
34
  });
33
35
  }
@@ -4,5 +4,9 @@ export default class DownCommand extends FlavoredCommand<typeof DownCommand> {
4
4
  static enableJsonFlag: boolean;
5
5
  static examples: string[];
6
6
  static flags: {};
7
+ static args: {
8
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
9
+ };
10
+ static strict: boolean;
7
11
  run(): Promise<void>;
8
12
  }
@@ -1,4 +1,4 @@
1
- import { Listr } from 'listr2';
1
+ import { Args } from '@oclif/core';
2
2
  import { FlavoredCommand, getContext } from '../index.js';
3
3
  import { ComposeDownOperation } from '../../docker/index.js';
4
4
  export default class DownCommand extends FlavoredCommand {
@@ -6,17 +6,22 @@ export default class DownCommand extends FlavoredCommand {
6
6
  static enableJsonFlag = true;
7
7
  static examples = ['<%= config.bin %> <%= command.id %>'];
8
8
  static flags = {};
9
+ static args = {
10
+ service: Args.string({
11
+ name: 'service',
12
+ description: 'The service(s) to stop and remove',
13
+ }),
14
+ };
15
+ static strict = false;
9
16
  async run() {
10
- const { monorepo } = getContext();
11
- const runner = new Listr([
12
- {
13
- rendererOptions: { persistentOutput: true },
14
- async task(ctx, task) {
15
- return monorepo.run(new ComposeDownOperation(task.stdout()), {});
16
- },
17
- title: 'Stopping project',
18
- },
19
- ]);
20
- await runner.run();
17
+ const { argv } = await this.parse(DownCommand);
18
+ const { monorepo, compose } = getContext();
19
+ let services;
20
+ if (argv.length > 0) {
21
+ services = await compose.validateServices(argv);
22
+ }
23
+ await monorepo.run(new ComposeDownOperation(), {
24
+ services,
25
+ });
21
26
  }
22
27
  }
@@ -2,7 +2,7 @@ import { Log } from '@kubernetes/client-node';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { PassThrough } from 'node:stream';
4
4
  import { KubernetesCommand } from '../../index.js';
5
- import { GetDeploymentPodsOperation } from '../../../kubernetes/operations/GetDeploymentPodsOperation.js';
5
+ import { GetComponentPodOperation } from '../../../kubernetes/operations/index.js';
6
6
  export default class KubernetesLogs extends KubernetesCommand {
7
7
  static description = 'Follow kubernetes logs.';
8
8
  static enableJsonFlag = false;
@@ -26,23 +26,18 @@ export default class KubernetesLogs extends KubernetesCommand {
26
26
  async run() {
27
27
  const { flags, args } = await this.parse(KubernetesLogs);
28
28
  const { monorepo, kubernetes } = this.context;
29
- // Check the component name is valid (would raise otherwise)
30
- monorepo.component(args.component);
31
- const pods = await monorepo.run(new GetDeploymentPodsOperation(), {
32
- namespace: flags.namespace,
33
- deployment: args.component,
29
+ const namespace = this.resolveNamespace(flags.namespace);
30
+ const component = monorepo.component(args.component);
31
+ const { pod, container } = await monorepo.run(new GetComponentPodOperation(), {
32
+ namespace,
33
+ component,
34
34
  });
35
- if (pods.length === 0) {
36
- throw new Error(`No running pod found for component ${args.component}`);
37
- }
38
35
  const k8sLogs = new Log(kubernetes.config);
39
36
  const transform = new PassThrough();
40
37
  transform.on('data', (chunk) => {
41
38
  process.stdout.write(chunk);
42
39
  });
43
- const pod = pods[0];
44
- const container = pod.spec.containers[0];
45
- await k8sLogs.log(flags.namespace, pod.metadata.name, container.name, transform, {
40
+ await k8sLogs.log(namespace, pod.metadata.name, container, transform, {
46
41
  follow: flags.follow,
47
42
  tailLines: 50,
48
43
  pretty: false,
@@ -15,8 +15,9 @@ export default class KPSCommand extends KubernetesCommand {
15
15
  async run() {
16
16
  const { flags } = await this.parse(KPSCommand);
17
17
  const { kubernetes } = getContext();
18
+ const namespace = this.resolveNamespace(flags.namespace);
18
19
  const { items } = await kubernetes.core.listNamespacedPod({
19
- namespace: flags.namespace,
20
+ namespace,
20
21
  });
21
22
  const pods = items.map((i) => {
22
23
  const restarts = i.status?.containerStatuses
@@ -14,8 +14,9 @@ export default class KRestartCommand extends KubernetesCommand {
14
14
  async run() {
15
15
  const { flags, argv } = await this.parse(KRestartCommand);
16
16
  const { monorepo } = getContext();
17
+ const namespace = this.resolveNamespace(flags.namespace);
17
18
  await monorepo.run(new PodsRestartOperation(), {
18
- namespace: flags.namespace,
19
+ namespace,
19
20
  deployments: argv.length > 0 ? argv : undefined,
20
21
  });
21
22
  }
@@ -1,7 +1,7 @@
1
1
  import { Exec } from '@kubernetes/client-node';
2
2
  import { Args, Flags } from '@oclif/core';
3
3
  import { getContext, KubernetesCommand } from '../../index.js';
4
- import { GetDeploymentPodsOperation } from '../../../kubernetes/operations/GetDeploymentPodsOperation.js';
4
+ import { GetComponentPodOperation } from '../../../kubernetes/operations/index.js';
5
5
  import { enableRawMode } from '../../../utils/streams.js';
6
6
  export default class PodShellCommand extends KubernetesCommand {
7
7
  static aliases = ['shell'];
@@ -26,18 +26,15 @@ export default class PodShellCommand extends KubernetesCommand {
26
26
  async run() {
27
27
  const { flags, args } = await this.parse(PodShellCommand);
28
28
  const { monorepo, kubernetes } = await getContext();
29
- const pods = await monorepo.run(new GetDeploymentPodsOperation(), {
30
- namespace: flags.namespace,
31
- deployment: args.component,
29
+ const namespace = this.resolveNamespace(flags.namespace);
30
+ const component = monorepo.component(args.component);
31
+ const { pod, container } = await monorepo.run(new GetComponentPodOperation(), {
32
+ namespace,
33
+ component,
32
34
  });
33
- if (pods.length === 0) {
34
- throw new Error(`No running pod found for component ${args.component}`);
35
- }
36
- const pod = pods[0];
37
- const container = pod.spec.containers[0];
38
35
  const exec = new Exec(kubernetes.config);
39
36
  enableRawMode(process.stdin);
40
- const res = await exec.exec(flags.namespace, pod.metadata.name, container.name, [flags.shell], process.stdout, process.stderr, process.stdin, true);
37
+ const res = await exec.exec(namespace, pod.metadata.name, container, [flags.shell], process.stdout, process.stderr, process.stdin, true);
41
38
  res.on('close', () => {
42
39
  // eslint-disable-next-line n/no-process-exit, unicorn/no-process-exit
43
40
  process.exit(0);
@@ -10,7 +10,7 @@ export default class LogsArchive extends BaseCommand {
10
10
  output: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
11
11
  };
12
12
  static args: {
13
- component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
13
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
14
14
  };
15
15
  run(): Promise<void>;
16
16
  }
@@ -2,7 +2,7 @@ import { Args, Flags } from '@oclif/core';
2
2
  import { BaseCommand, getContext } from '../../index.js';
3
3
  import { ComposeLogsArchiveOperation } from '../../../docker/index.js';
4
4
  export default class LogsArchive extends BaseCommand {
5
- static description = 'Archive docker compose logs to files (one file per component).';
5
+ static description = 'Archive docker compose logs to files (one file per service).';
6
6
  static enableJsonFlag = true;
7
7
  static examples = [
8
8
  '<%= config.bin %> <%= command.id %>',
@@ -26,22 +26,23 @@ export default class LogsArchive extends BaseCommand {
26
26
  }),
27
27
  };
28
28
  static args = {
29
- component: Args.string({
30
- name: 'component',
31
- description: 'The component(s) to archive logs for (all if omitted)',
29
+ service: Args.string({
30
+ name: 'service',
31
+ description: 'The service(s) to archive logs for (all if omitted)',
32
32
  required: false,
33
33
  }),
34
34
  };
35
35
  async run() {
36
36
  const { flags, argv } = await this.parse(LogsArchive);
37
- const { monorepo } = await getContext();
38
- const componentNames = argv;
39
- // Validate that all specified components exist
40
- if (componentNames.length > 0) {
41
- componentNames.forEach((name) => monorepo.component(name));
37
+ const { monorepo, compose } = getContext();
38
+ const serviceNames = argv;
39
+ // Validate that all specified services exist in docker-compose.yml
40
+ let services;
41
+ if (serviceNames.length > 0) {
42
+ services = await compose.validateServices(serviceNames);
42
43
  }
43
44
  const result = await monorepo.run(new ComposeLogsArchiveOperation(), {
44
- components: componentNames.length > 0 ? componentNames : undefined,
45
+ services,
45
46
  outputDir: flags.output,
46
47
  timestamps: flags.timestamps,
47
48
  tail: flags.tail,
@@ -52,7 +53,7 @@ export default class LogsArchive extends BaseCommand {
52
53
  else {
53
54
  this.log('Archived logs:');
54
55
  for (const file of result) {
55
- this.log(` ${file.component}: ${file.path}`);
56
+ this.log(` ${file.service}: ${file.path}`);
56
57
  }
57
58
  }
58
59
  }
@@ -8,7 +8,7 @@ export default class Logs extends BaseCommand {
8
8
  follow: import("@oclif/core/interfaces").BooleanFlag<boolean>;
9
9
  };
10
10
  static args: {
11
- component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
11
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
12
12
  };
13
13
  run(): Promise<void>;
14
14
  }
@@ -2,7 +2,7 @@ import { Args, Flags } from '@oclif/core';
2
2
  import { BaseCommand, getContext } from '../../index.js';
3
3
  import { ComposeLogsOperation } from '../../../docker/index.js';
4
4
  export default class Logs extends BaseCommand {
5
- static description = 'Get components logs.';
5
+ static description = 'Get service logs.';
6
6
  static enableJsonFlag = false;
7
7
  static examples = [
8
8
  '<%= config.bin %> <%= command.id %>',
@@ -21,23 +21,23 @@ export default class Logs extends BaseCommand {
21
21
  }),
22
22
  };
23
23
  static args = {
24
- component: Args.string({
25
- name: 'component',
26
- description: 'The component(s) you want to see the logs of (all if omitted)',
24
+ service: Args.string({
25
+ name: 'service',
26
+ description: 'The service(s) you want to see the logs of (all if omitted)',
27
27
  required: false,
28
28
  }),
29
29
  };
30
30
  async run() {
31
31
  const { flags, argv } = await this.parse(Logs);
32
- const { monorepo } = await getContext();
33
- const componentNames = argv;
34
- // Validate that all specified components exist
35
- const services = componentNames.map((name) => {
36
- const component = monorepo.component(name);
37
- return component.name;
38
- });
32
+ const { monorepo, compose } = getContext();
33
+ const serviceNames = argv;
34
+ // Validate that all specified services exist in docker-compose.yml
35
+ let services;
36
+ if (serviceNames.length > 0) {
37
+ services = await compose.validateServices(serviceNames);
38
+ }
39
39
  await monorepo.run(new ComposeLogsOperation(), {
40
- services: services.length > 0 ? services : undefined,
40
+ services,
41
41
  follow: flags.follow,
42
42
  });
43
43
  }
@@ -7,7 +7,7 @@ export default class RestartComand extends BaseCommand {
7
7
  'no-deps': import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  };
9
9
  static args: {
10
- component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
10
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
11
11
  };
12
12
  static strict: boolean;
13
13
  run(): Promise<void>;
@@ -9,26 +9,27 @@ export default class RestartComand extends BaseCommand {
9
9
  'no-deps': Flags.boolean({
10
10
  char: 'f',
11
11
  default: false,
12
- description: "Don't restart depdendent components",
12
+ description: "Don't restart dependent services",
13
13
  name: 'no-deps',
14
14
  }),
15
15
  };
16
16
  static args = {
17
- component: Args.string({
18
- name: 'component',
19
- description: 'The component(s) to restart',
17
+ service: Args.string({
18
+ name: 'service',
19
+ description: 'The service(s) to restart',
20
20
  }),
21
21
  };
22
22
  static strict = false;
23
23
  async run() {
24
24
  const { flags, argv } = await this.parse(RestartComand);
25
- const { monorepo } = getContext();
26
- const components = argv.length > 0
27
- ? argv.map((name) => monorepo.component(name))
28
- : undefined;
25
+ const { monorepo, compose } = getContext();
26
+ let services;
27
+ if (argv.length > 0) {
28
+ services = await compose.validateServices(argv);
29
+ }
29
30
  await monorepo.run(new ComposeRestartOperation(), {
30
31
  noDeps: flags['no-deps'],
31
- services: components?.map((c) => c.name),
32
+ services,
32
33
  });
33
34
  }
34
35
  }
@@ -5,7 +5,7 @@ export default class StartCommand extends BaseCommand {
5
5
  static examples: string[];
6
6
  static flags: {};
7
7
  static args: {
8
- component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
8
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
9
9
  };
10
10
  static strict: boolean;
11
11
  run(): Promise<void>;
@@ -7,24 +7,21 @@ export default class StartCommand extends BaseCommand {
7
7
  static examples = ['<%= config.bin %> <%= command.id %>'];
8
8
  static flags = {};
9
9
  static args = {
10
- component: Args.string({
11
- name: 'component',
12
- description: 'The component(s) to start',
10
+ service: Args.string({
11
+ name: 'service',
12
+ description: 'The service(s) to start',
13
13
  }),
14
14
  };
15
15
  static strict = false;
16
16
  async run() {
17
17
  const { argv } = await this.parse(StartCommand);
18
- const { monorepo } = getContext();
19
- let components;
18
+ const { monorepo, compose } = getContext();
19
+ let services;
20
20
  if (argv.length > 0) {
21
- components =
22
- argv.length > 0
23
- ? argv.map((name) => monorepo.component(name))
24
- : undefined;
21
+ services = await compose.validateServices(argv);
25
22
  }
26
23
  await monorepo.run(new ComposeStartOperation(), {
27
- services: components?.map((c) => c.name),
24
+ services,
28
25
  });
29
26
  }
30
27
  }
@@ -4,5 +4,9 @@ export default class StopCommand extends FlavoredCommand<typeof StopCommand> {
4
4
  static enableJsonFlag: boolean;
5
5
  static examples: string[];
6
6
  static flags: {};
7
+ static args: {
8
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
9
+ };
10
+ static strict: boolean;
7
11
  run(): Promise<void>;
8
12
  }
@@ -1,4 +1,4 @@
1
- import { Listr } from 'listr2';
1
+ import { Args } from '@oclif/core';
2
2
  import { FlavoredCommand, getContext } from '../index.js';
3
3
  import { ComposeStopOperation } from '../../docker/index.js';
4
4
  export default class StopCommand extends FlavoredCommand {
@@ -6,17 +6,22 @@ export default class StopCommand extends FlavoredCommand {
6
6
  static enableJsonFlag = true;
7
7
  static examples = ['<%= config.bin %> <%= command.id %>'];
8
8
  static flags = {};
9
+ static args = {
10
+ service: Args.string({
11
+ name: 'service',
12
+ description: 'The service(s) to stop',
13
+ }),
14
+ };
15
+ static strict = false;
9
16
  async run() {
10
- const { monorepo } = getContext();
11
- const runner = new Listr([
12
- {
13
- rendererOptions: { persistentOutput: true },
14
- async task(ctx, task) {
15
- return monorepo.run(new ComposeStopOperation(task.stdout()), {});
16
- },
17
- title: 'Stopping project',
18
- },
19
- ]);
20
- await runner.run();
17
+ const { argv } = await this.parse(StopCommand);
18
+ const { monorepo, compose } = getContext();
19
+ let services;
20
+ if (argv.length > 0) {
21
+ services = await compose.validateServices(argv);
22
+ }
23
+ await monorepo.run(new ComposeStopOperation(), {
24
+ services,
25
+ });
21
26
  }
22
27
  }
@@ -7,7 +7,7 @@ export default class UpCommand extends FlavoredCommand<typeof UpCommand> {
7
7
  force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
8
8
  };
9
9
  static args: {
10
- component: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
10
+ service: import("@oclif/core/interfaces").Arg<string | undefined, Record<string, unknown>>;
11
11
  };
12
12
  static strict: boolean;
13
13
  run(): Promise<void>;
@@ -15,27 +15,25 @@ export default class UpCommand extends FlavoredCommand {
15
15
  }),
16
16
  };
17
17
  static args = {
18
- component: Args.string({
19
- name: 'component',
20
- description: 'The component(s) to build and start',
18
+ service: Args.string({
19
+ name: 'service',
20
+ description: 'The service(s) to build and start',
21
21
  }),
22
22
  };
23
23
  static strict = false;
24
24
  async run() {
25
25
  const { flags, argv } = await this.parse(UpCommand);
26
- const { monorepo } = getContext();
27
- const buildFlags = [];
28
- if (flags.force) {
29
- buildFlags.push('--force');
30
- }
31
- let components;
26
+ const { monorepo, compose } = getContext();
27
+ let services;
32
28
  let resources;
33
29
  if (argv.length > 0) {
34
- components =
35
- argv.length > 0
36
- ? argv.map((name) => monorepo.component(name))
37
- : monorepo.components;
38
- resources = components.reduce((resources, component) => {
30
+ // Validate service names against docker-compose.yml
31
+ services = await compose.validateServices(argv);
32
+ // Build resources for services that have corresponding components
33
+ const componentNames = new Set(monorepo.components.map((c) => c.name));
34
+ const componentsToBuild = services.filter((s) => componentNames.has(s));
35
+ resources = componentsToBuild.reduce((resources, name) => {
36
+ const component = monorepo.component(name);
39
37
  return [
40
38
  ...resources,
41
39
  ...Object.values(component.resources).map((r) => r.id),
@@ -45,13 +43,16 @@ export default class UpCommand extends FlavoredCommand {
45
43
  else {
46
44
  resources = monorepo.resources.map((r) => r.id);
47
45
  }
48
- await monorepo.run(new BuildResourcesOperation(), {
49
- force: flags.force,
50
- resources,
51
- });
46
+ // Only build resources if there are any to build
47
+ if (resources && resources.length > 0) {
48
+ await monorepo.run(new BuildResourcesOperation(), {
49
+ force: flags.force,
50
+ resources,
51
+ });
52
+ }
52
53
  await monorepo.run(new ComposeUpOperation(), {
53
54
  forceRecreate: flags.force,
54
- components: components?.map((c) => c.name),
55
+ services,
55
56
  });
56
57
  }
57
58
  }
@@ -18,7 +18,7 @@ export type TaskConfig = TaskConfig1 & {
18
18
  [k: string]: unknown;
19
19
  };
20
20
  pre?: QualifiedIdentifier[];
21
- executors?: ("local" | "container")[];
21
+ executors?: ("local" | "container" | "kubernetes")[];
22
22
  /**
23
23
  * Whether the task is interactive (requires TTY)
24
24
  */
@@ -107,6 +107,24 @@ export interface DefaultsConfig {
107
107
  };
108
108
  [k: string]: unknown;
109
109
  };
110
+ kubernetes?: KubernetesConfig;
111
+ }
112
+ /**
113
+ * Kubernetes configuration for the project
114
+ */
115
+ export interface KubernetesConfig {
116
+ /**
117
+ * Default Kubernetes namespace to use
118
+ */
119
+ namespace?: string;
120
+ /**
121
+ * Kubernetes context to use from kubeconfig
122
+ */
123
+ context?: string;
124
+ /**
125
+ * Label name used in pod selectors. Defaults to 'app.kubernetes.io/component'
126
+ */
127
+ selectorLabel?: string;
110
128
  }
111
129
  export interface ComponentConfig {
112
130
  /**
@@ -126,6 +144,7 @@ export interface ComponentConfig {
126
144
  flavors?: {
127
145
  [k: string]: ComponentFlavorConfig;
128
146
  };
147
+ kubernetes?: ComponentKubernetesConfig;
129
148
  }
130
149
  export interface ComponentFlavorConfig {
131
150
  patches?: JsonPatchOperation[];
@@ -154,6 +173,19 @@ export interface JsonPatchCopyOperation {
154
173
  path: string;
155
174
  from: string;
156
175
  }
176
+ /**
177
+ * Kubernetes configuration for a component
178
+ */
179
+ export interface ComponentKubernetesConfig {
180
+ /**
181
+ * Label selector to find pods (e.g., 'app=api,tier=backend'). Defaults to '{componentLabel}={component}'
182
+ */
183
+ selector?: string;
184
+ /**
185
+ * Container name for multi-container pods
186
+ */
187
+ container?: string;
188
+ }
157
189
  export interface ProjectFlavorConfig {
158
190
  patches?: JsonPatchOperation[];
159
191
  }
@@ -71,6 +71,40 @@
71
71
  "type": "string",
72
72
  "pattern": "^([a-zA-Z]+[\\w._-]+:)?[a-zA-Z]+[\\w._-]+$"
73
73
  },
74
+ "KubernetesConfig": {
75
+ "type": "object",
76
+ "description": "Kubernetes configuration for the project",
77
+ "properties": {
78
+ "namespace": {
79
+ "type": "string",
80
+ "description": "Default Kubernetes namespace to use"
81
+ },
82
+ "context": {
83
+ "type": "string",
84
+ "description": "Kubernetes context to use from kubeconfig"
85
+ },
86
+ "selectorLabel": {
87
+ "type": "string",
88
+ "description": "Label name used in pod selectors. Defaults to 'app.kubernetes.io/component'"
89
+ }
90
+ },
91
+ "additionalProperties": false
92
+ },
93
+ "ComponentKubernetesConfig": {
94
+ "type": "object",
95
+ "description": "Kubernetes configuration for a component",
96
+ "properties": {
97
+ "selector": {
98
+ "type": "string",
99
+ "description": "Label selector to find pods (e.g., 'app=api,tier=backend'). Defaults to '{componentLabel}={component}'"
100
+ },
101
+ "container": {
102
+ "type": "string",
103
+ "description": "Container name for multi-container pods"
104
+ }
105
+ },
106
+ "additionalProperties": false
107
+ },
74
108
  "DefaultsConfig": {
75
109
  "type": "object",
76
110
  "description": "Default settings for build aspects",
@@ -103,6 +137,9 @@
103
137
  }
104
138
  }
105
139
  }
140
+ },
141
+ "kubernetes": {
142
+ "$ref": "#/definitions/KubernetesConfig"
106
143
  }
107
144
  }
108
145
  },
@@ -138,7 +175,8 @@
138
175
  "items": {
139
176
  "anyOf": [
140
177
  { "const": "local" },
141
- { "const": "container" }
178
+ { "const": "container" },
179
+ { "const": "kubernetes" }
142
180
  ]
143
181
  }
144
182
  },
@@ -200,6 +238,9 @@
200
238
  "additionalProperties": {
201
239
  "$ref": "#/definitions/ComponentFlavorConfig"
202
240
  }
241
+ },
242
+ "kubernetes": {
243
+ "$ref": "#/definitions/ComponentKubernetesConfig"
203
244
  }
204
245
  },
205
246
  "additionalProperties": false