Skip to content

Commit 15db6ed

Browse files
committed
feat(cli): allow --hot=* in dev/deploy commands
Passing an asterisk (*) to the --hot/--hot-reload option deploys all compatible services with hot reloading enabled (i.e. all services belonging to a module specifying the hotReload field). Also throw an error before initializing the environment or proceeding with deployment if one or more service names passed to the --hot/--hotReload option aren't configured for hot reloading.
1 parent d692401 commit 15db6ed

File tree

5 files changed

+89
-22
lines changed

5 files changed

+89
-22
lines changed

docs/reference/commands.md

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -146,13 +146,14 @@ Optionally stays running and automatically re-builds and re-deploys services if
146146

147147
Examples:
148148

149-
garden deploy # deploy all modules in the project
150-
garden deploy my-service # only deploy my-service
151-
garden deploy service-a,service-b # only deploy service-a and service-b
152-
garden deploy --force # force re-deploy of modules, even if they're already deployed
153-
garden deploy --watch # watch for changes to code
154-
garden deploy --watch --hot-reload=my-service # deploys all services, with hot reloading enabled for my-service
155-
garden deploy --env stage # deploy your services to an environment called stage
149+
garden deploy # deploy all modules in the project
150+
garden deploy my-service # only deploy my-service
151+
garden deploy service-a,service-b # only deploy service-a and service-b
152+
garden deploy --force # force re-deploy of modules, even if they're already deployed
153+
garden deploy --watch # watch for changes to code
154+
garden deploy --hot=my-service # deploys all services, with hot reloading enabled for my-service
155+
garden deploy --hot=* # deploys all compatible services with hot reloading enabled
156+
garden deploy --env stage # deploy your services to an environment called stage
156157

157158
##### Usage
158159

@@ -171,7 +172,7 @@ Examples:
171172
| `--force` | | boolean | Force redeploy of service(s).
172173
| `--force-build` | | boolean | Force rebuild of module(s).
173174
| `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-deploy.
174-
| `--hot-reload` | `-hot` | array:string | The name(s) of the service(s) to deploy with hot reloading enabled. Use comma as a separator to specify multiple services. When this option is used, the command is run in watch mode (i.e. implicitly assumes the --watch/-w flag).
175+
| `--hot-reload` | `-hot` | array:string | The name(s) of the service(s) to deploy with hot reloading enabled. Use comma as a separator to specify multiple services. Use * to deploy all services with hot reloading enabled (ignores services belonging to modules that don't support or haven't configured hot reloading). When this option is used, the command is run in watch mode (i.e. implicitly assumes the --watch/-w flag).
175176

176177
### garden dev
177178

@@ -186,6 +187,7 @@ Examples:
186187
garden dev
187188
garden dev --hot-reload=foo-service # enable hot reloading for foo-service
188189
garden dev --hot=foo-service,bar-service # enable hot reloading for foo-service and bar-service
190+
garden dev --hot=* # enable hot reloading for all compatible services
189191

190192
##### Usage
191193

@@ -195,7 +197,7 @@ Examples:
195197

196198
| Argument | Alias | Type | Description |
197199
| -------- | ----- | ---- | ----------- |
198-
| `--hot-reload` | `-hot` | array:string | The name(s) of the service(s) to deploy with hot reloading enabled. Use comma as a separator to specify multiple services.
200+
| `--hot-reload` | `-hot` | array:string | The name(s) of the service(s) to deploy with hot reloading enabled. Use comma as a separator to specify multiple services. Use * to deploy all services with hot reloading enabled (ignores services belonging to modules that don't support or haven't configured hot reloading).
199201

200202
### garden exec
201203

docs/using-garden/hot-reload.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ For example, services that can be run with a file system watcher that automatica
88

99
Currently, services are only deployed with hot reloading enabled when their names are passed to the `--hot` option via `garden deploy` or `garden dev` commands (e.g. `garden dev --hot=foo-service,bar-service`). If these services don't belong to a module defining a `hotReload` configuration (see below for an example), an error will be thrown if their names are passed to the `--hot` option.
1010

11+
You can also pass `*` (e.g. `--hot=*`/`--hot-reload=*`) to deploy all compatible services with hot reloading enabled (i.e. all services belonging to a module that defines a `hotReload` configuration).
12+
1113
Subsequently deploying a service belonging to a module configured for hot reloading via `garden deploy` (without the watch flag) results in the service being redeployed in standard configuration.
1214

1315
Since hot reloading is triggered via Garden's file system watcher, hot reloading only occurs while a watch-mode Garden command is running.

garden-service/src/commands/deploy.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { processServices } from "../process"
2323
import { logHeader } from "../logger/util"
2424
import { HotReloadTask } from "../tasks/hot-reload"
2525
import { BaseTask } from "../tasks/base"
26+
import { getHotReloadServiceNames, validateHotReloadServiceNames } from "./helpers"
2627

2728
const deployArgs = {
2829
services: new StringsParameter({
@@ -41,7 +42,9 @@ const deployOpts = {
4142
}),
4243
"hot-reload": new StringsParameter({
4344
help: deline`The name(s) of the service(s) to deploy with hot reloading enabled.
44-
Use comma as a separator to specify multiple services. When this option is used,
45+
Use comma as a separator to specify multiple services. Use * to deploy all
46+
services with hot reloading enabled (ignores services belonging to modules that
47+
don't support or haven't configured hot reloading). When this option is used,
4548
the command is run in watch mode (i.e. implicitly assumes the --watch/-w flag).
4649
`,
4750
alias: "hot",
@@ -64,13 +67,14 @@ export class DeployCommand extends Command<Args, Opts> {
6467
6568
Examples:
6669
67-
garden deploy # deploy all modules in the project
68-
garden deploy my-service # only deploy my-service
69-
garden deploy service-a,service-b # only deploy service-a and service-b
70-
garden deploy --force # force re-deploy of modules, even if they're already deployed
71-
garden deploy --watch # watch for changes to code
72-
garden deploy --watch --hot-reload=my-service # deploys all services, with hot reloading enabled for my-service
73-
garden deploy --env stage # deploy your services to an environment called stage
70+
garden deploy # deploy all modules in the project
71+
garden deploy my-service # only deploy my-service
72+
garden deploy service-a,service-b # only deploy service-a and service-b
73+
garden deploy --force # force re-deploy of modules, even if they're already deployed
74+
garden deploy --watch # watch for changes to code
75+
garden deploy --hot=my-service # deploys all services, with hot reloading enabled for my-service
76+
garden deploy --hot=* # deploys all compatible services with hot reloading enabled
77+
garden deploy --env stage # deploy your services to an environment called stage
7478
`
7579

7680
arguments = deployArgs
@@ -89,11 +93,15 @@ export class DeployCommand extends Command<Args, Opts> {
8993
return { result: {} }
9094
}
9195

92-
const hotReloadServiceNames = opts["hot-reload"] || []
93-
96+
const hotReloadServiceNames = await getHotReloadServiceNames(opts["hot-reload"], initGraph)
9497
let watch
9598
if (hotReloadServiceNames.length > 0) {
9699
await initGraph.getServices(hotReloadServiceNames) // validate the existence of these services
100+
const errMsg = await validateHotReloadServiceNames(hotReloadServiceNames, initGraph)
101+
if (errMsg) {
102+
log.error({ msg: errMsg })
103+
return { result: {} }
104+
}
97105
watch = true
98106
} else {
99107
watch = opts.watch

garden-service/src/commands/dev.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { Module } from "../types/module"
3030
import { getTestTasks } from "../tasks/test"
3131
import { HotReloadTask } from "../tasks/hot-reload"
3232
import { ConfigGraph } from "../config-graph"
33+
import { getHotReloadServiceNames, validateHotReloadServiceNames } from "./helpers"
3334

3435
const ansiBannerPath = join(STATIC_DIR, "garden-banner-2.txt")
3536

@@ -38,7 +39,9 @@ const devArgs = {}
3839
const devOpts = {
3940
"hot-reload": new StringsParameter({
4041
help: deline`The name(s) of the service(s) to deploy with hot reloading enabled.
41-
Use comma as a separator to specify multiple services.
42+
Use comma as a separator to specify multiple services. Use * to deploy all
43+
services with hot reloading enabled (ignores services belonging to modules that
44+
don't support or haven't configured hot reloading).
4245
`,
4346
alias: "hot",
4447
}),
@@ -65,6 +68,7 @@ export class DevCommand extends Command<Args, Opts> {
6568
garden dev
6669
garden dev --hot-reload=foo-service # enable hot reloading for foo-service
6770
garden dev --hot=foo-service,bar-service # enable hot reloading for foo-service and bar-service
71+
garden dev --hot=* # enable hot reloading for all compatible services
6872
`
6973

7074
options = devOpts
@@ -88,9 +92,13 @@ export class DevCommand extends Command<Args, Opts> {
8892
return {}
8993
}
9094

91-
const hotReloadServiceNames = opts["hot-reload"] || []
95+
const hotReloadServiceNames = await getHotReloadServiceNames(opts["hot-reload"], graph)
9296
if (hotReloadServiceNames.length > 0) {
93-
await graph.getServices(hotReloadServiceNames) // validate the existence of these services
97+
const errMsg = await validateHotReloadServiceNames(hotReloadServiceNames, graph)
98+
if (errMsg) {
99+
log.error({ msg: errMsg })
100+
return { result: {} }
101+
}
94102
}
95103

96104
await garden.actions.prepareEnvironment({ log })
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Copyright (C) 2018 Garden Technologies, Inc. <info@garden.io>
3+
*
4+
* This Source Code Form is subject to the terms of the Mozilla Public
5+
* License, v. 2.0. If a copy of the MPL was not distributed with this
6+
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
7+
*/
8+
9+
import { ConfigGraph } from "../config-graph"
10+
import { Service } from "../types/service"
11+
12+
export async function getHotReloadServiceNames(
13+
namesFromOpt: string[] | undefined, configGraph: ConfigGraph,
14+
) {
15+
const names = namesFromOpt || []
16+
if (names[0] === "*") {
17+
return (await configGraph.getServices())
18+
.filter(s => supportsHotReloading(s))
19+
.map(s => s.name)
20+
} else {
21+
return names
22+
}
23+
}
24+
25+
/**
26+
* Returns an error message string if one or more serviceNames refers to a service that's not configured for
27+
* hot reloading, or if one or more of serviceNames referes to a non-existent service. Returns null otherwise.
28+
*/
29+
export async function validateHotReloadServiceNames(
30+
serviceNames: string[], configGraph: ConfigGraph,
31+
): Promise<string | null> {
32+
const services = await configGraph.getServices(serviceNames)
33+
const invalidNames = services
34+
.filter(s => !supportsHotReloading(s))
35+
.map(s => s.name)
36+
if (invalidNames.length > 0) {
37+
return `The following requested services are not configured for hot reloading: ${invalidNames.join(", ")}`
38+
} else {
39+
return null
40+
}
41+
}
42+
43+
// TODO: Add hotReload to baseModuleSpecSchema. It's bad form to dig into module type-specific fields
44+
// outside the scope of its plugins.
45+
function supportsHotReloading(service: Service) {
46+
return !!service.module.spec.hotReload
47+
}

0 commit comments

Comments
 (0)