diff --git a/core/src/commands/get/get-debug-info.ts b/core/src/commands/get/get-debug-info.ts index 2fcda6a435..9cbd8ec6e9 100644 --- a/core/src/commands/get/get-debug-info.ts +++ b/core/src/commands/get/get-debug-info.ts @@ -74,8 +74,8 @@ export async function collectBasicDebugInfo(root: string, gardenDirPath: string, ignoreFile: projectConfig.dotIgnoreFile || defaultDotIgnoreFile, cache, }) - const include = projectConfig.modules && projectConfig.modules.include - const exclude = projectConfig.modules && projectConfig.modules.exclude + const include = projectConfig.scan && projectConfig.scan.include + const exclude = projectConfig.scan && projectConfig.scan.exclude const paths = await findConfigPathsInPath({ vcs, dir: root, include, exclude, log }) // Copy all the service configuration files diff --git a/core/src/config/base.ts b/core/src/config/base.ts index 29445febf4..33290880ef 100644 --- a/core/src/config/base.ts +++ b/core/src/config/base.ts @@ -256,10 +256,10 @@ export function prepareResource({ } } -// TODO: remove this function in 0.14 -export function prepareProjectResource(log: Log, spec: any): ProjectResource { - const projectSpec = spec +// TODO (start): remove these deprecation handlers in 0.14 +type DeprecatedConfigHandler = (log: Log, spec: ProjectResource) => ProjectResource +function handleDotIgnoreFiles(log: Log, projectSpec: ProjectResource) { // If the project config has an explicitly defined `dotIgnoreFile` field, // it means the config has already been updated to 0.13 format. if (!!projectSpec.dotIgnoreFile) { @@ -290,11 +290,34 @@ export function prepareProjectResource(log: Log, spec: any): ProjectResource { ", " )}]`, { - spec, + projectSpec, } ) } +function handleProjectModules(log: Log, projectSpec: ProjectResource): ProjectResource { + // Field 'modules' was intentionally removed from the internal interface `ProjectResource`, + // but it still can be presented in the runtime if the old config format is used. + if (projectSpec["modules"]) { + emitNonRepeatableWarning( + log, + "Project configuration field `modules` is deprecated in 0.13 and will be removed in 0.14. Please use the `scan` field instead." + ) + } + + return projectSpec +} + +const bonsaiDeprecatedConfigHandlers: DeprecatedConfigHandler[] = [handleDotIgnoreFiles, handleProjectModules] + +export function prepareProjectResource(log: Log, spec: any): ProjectResource { + let projectSpec = spec + for (const handler of bonsaiDeprecatedConfigHandlers) { + projectSpec = handler(log, projectSpec) + } + return projectSpec +} + export function prepareModuleResource(spec: any, configPath: string, projectRoot: string): ModuleConfig { // We allow specifying modules by name only as a shorthand: // dependencies: diff --git a/core/src/config/common.ts b/core/src/config/common.ts index 2b162499e0..8d1bde8a1c 100644 --- a/core/src/config/common.ts +++ b/core/src/config/common.ts @@ -487,6 +487,7 @@ export interface CreateSchemaParams { meta?: MetadataKeys allowUnknown?: boolean required?: boolean + rename?: [string, string][] or?: string[] xor?: string[] } @@ -559,6 +560,11 @@ export function createSchema(spec: CreateSchemaParams): CreateSchemaOutput { if (spec.required) { schema = schema.required() } + if (spec.rename) { + for (const r of spec.rename) { + schema = schema.rename(r[0], r[1]) + } + } if (spec.or) { schema = schema.or(...spec.or) } diff --git a/core/src/config/project.ts b/core/src/config/project.ts index f8968f3e2f..2ae10a5156 100644 --- a/core/src/config/project.ts +++ b/core/src/config/project.ts @@ -187,7 +187,7 @@ export interface ProjectConfig { dotIgnoreFile: string dotIgnoreFiles?: string[] environments: EnvironmentConfig[] - modules?: { + scan?: { include?: string[] exclude?: string[] } @@ -207,15 +207,15 @@ export const projectNameSchema = () => export const projectRootSchema = () => joi.string().description("The path to the project root.") -const projectModulesSchema = createSchema({ - name: "project-modules", +const projectScanSchema = createSchema({ + name: "project-scan", keys: () => ({ include: joi .array() .items(joi.posixPath().allowGlobs().subPathOnly()) .description( dedent` - Specify a list of POSIX-style paths or globs that should be scanned for Garden modules. + Specify a list of POSIX-style paths or globs that should be scanned for Garden configuration files. Note that you can also _exclude_ path using the \`exclude\` field or by placing \`.gardenignore\` files in your source tree, which use the same format as \`.gitignore\` files. See the [Configuration Files guide](${includeGuideLink}) for details. @@ -229,7 +229,7 @@ const projectModulesSchema = createSchema({ .items(joi.posixPath().allowGlobs().subPathOnly()) .description( dedent` - Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for modules. + Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for configuration files. The filters here also affect which files and directories are watched for changes. So if you have a large number of directories in your project that should not be watched, you should specify them here. @@ -347,7 +347,7 @@ export const projectSchema = createSchema({ ) .example(["127.0.0.1"]), }), - modules: projectModulesSchema().description("Control where to scan for modules in the project."), + scan: projectScanSchema().description("Control where to scan for configuration files in the project."), outputs: joiSparseArray(projectOutputSchema()) .unique("name") .description( @@ -383,6 +383,7 @@ export const projectSchema = createSchema({ "Key/value map of variables to configure for all environments. " + joiVariablesDescription ), }), + rename: [["modules", "scan"]], }) export function getDefaultEnvironmentName(defaultName: string, config: ProjectConfig): string { diff --git a/core/src/garden.ts b/core/src/garden.ts index 1b325ec157..8afebce736 100644 --- a/core/src/garden.ts +++ b/core/src/garden.ts @@ -1707,7 +1707,7 @@ export const resolveGardenParams = profileAsync(async function _resolveGardenPar // We always exclude the garden dir const gardenDirExcludePattern = `${relative(projectRoot, gardenDirPath)}/**/*` const moduleExcludePatterns = [ - ...((config.modules || {}).exclude || []), + ...((config.scan || {}).exclude || []), gardenDirExcludePattern, ...fixedProjectExcludes, ] @@ -1754,7 +1754,7 @@ export const resolveGardenParams = profileAsync(async function _resolveGardenPar dotIgnoreFile: config.dotIgnoreFile, proxy, log, - moduleIncludePatterns: (config.modules || {}).include, + moduleIncludePatterns: (config.scan || {}).include, username: _username, forceRefresh: opts.forceRefresh, cloudApi, diff --git a/core/test/data/test-project-watch/garden.yml b/core/test/data/test-project-watch/garden.yml index ddb1767189..da034aa43c 100644 --- a/core/test/data/test-project-watch/garden.yml +++ b/core/test/data/test-project-watch/garden.yml @@ -1,6 +1,6 @@ kind: Project name: test-project-a -modules: +scan: exclude: [module-a/project-excluded.txt] environments: - name: local diff --git a/core/test/data/test-projects/huge-project/garden.yml b/core/test/data/test-projects/huge-project/garden.yml index 4b0ce98574..6287be707d 100644 --- a/core/test/data/test-projects/huge-project/garden.yml +++ b/core/test/data/test-projects/huge-project/garden.yml @@ -3,5 +3,5 @@ name: huge-project dotIgnoreFile: .gardenignore environments: - name: local -modules: +scan: exclude: [dir0/**/*, dir1/**/*, dir2/**/*, dir3/**/*, dir4/**/*, dir5/**/*, dir6/**/*, dir7/**/*, dir8/**/*] diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/garden.yml b/core/test/data/test-projects/project-include-exclude-old-syntax/garden.yml new file mode 100644 index 0000000000..8d1a44f89a --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/garden.yml @@ -0,0 +1,11 @@ +kind: Project +name: include-exclude-old-syntax +environments: + - name: local +providers: + - name: test-plugin +modules: + include: + - module*/**/* + exclude: + - module-c/**/* diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/garden.yml b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/garden.yml new file mode 100644 index 0000000000..506273076e --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/garden.yml @@ -0,0 +1,4 @@ +kind: Module +name: module-a +type: test +include: ["yes.txt"] diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/nope.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/nope.txt new file mode 100644 index 0000000000..c5cfed716a --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/nope.txt @@ -0,0 +1 @@ +Go away! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/yes.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/yes.txt new file mode 100644 index 0000000000..80cccdde3b --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-a/yes.txt @@ -0,0 +1 @@ +Oh hai! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/garden.yml b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/garden.yml new file mode 100644 index 0000000000..e552dd782f --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/garden.yml @@ -0,0 +1,4 @@ +kind: Module +name: module-b +type: test +exclude: ["nope.*"] diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/nope.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/nope.txt new file mode 100644 index 0000000000..c5cfed716a --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/nope.txt @@ -0,0 +1 @@ +Go away! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/yes.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/yes.txt new file mode 100644 index 0000000000..80cccdde3b --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-b/yes.txt @@ -0,0 +1 @@ +Oh hai! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/foo b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/foo new file mode 100644 index 0000000000..ba0e162e1c --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/foo @@ -0,0 +1 @@ +bar \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/garden.yml b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/garden.yml new file mode 100644 index 0000000000..43768df0a8 --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/garden.yml @@ -0,0 +1,5 @@ +kind: Module +name: module-c +type: test +include: ["*.txt"] +exclude: ["nope.*"] diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/nope.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/nope.txt new file mode 100644 index 0000000000..c5cfed716a --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/nope.txt @@ -0,0 +1 @@ +Go away! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/yes.txt b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/yes.txt new file mode 100644 index 0000000000..80cccdde3b --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/module-c/yes.txt @@ -0,0 +1 @@ +Oh hai! \ No newline at end of file diff --git a/core/test/data/test-projects/project-include-exclude-old-syntax/nope/garden.yml b/core/test/data/test-projects/project-include-exclude-old-syntax/nope/garden.yml new file mode 100644 index 0000000000..65f1b4b096 --- /dev/null +++ b/core/test/data/test-projects/project-include-exclude-old-syntax/nope/garden.yml @@ -0,0 +1,3 @@ +kind: Module +name: nope +type: test diff --git a/core/test/data/test-projects/project-include-exclude/garden.yml b/core/test/data/test-projects/project-include-exclude/garden.yml index 47d616ae1a..94b7b78e3e 100644 --- a/core/test/data/test-projects/project-include-exclude/garden.yml +++ b/core/test/data/test-projects/project-include-exclude/garden.yml @@ -4,7 +4,7 @@ environments: - name: local providers: - name: test-plugin -modules: +scan: include: - module*/**/* exclude: diff --git a/core/test/unit/src/config/base.ts b/core/test/unit/src/config/base.ts index 3237339499..17b13e168f 100644 --- a/core/test/unit/src/config/base.ts +++ b/core/test/unit/src/config/base.ts @@ -32,7 +32,7 @@ const modulePathAMultiple = resolve(projectPathMultipleModules, "module-a") const projectPathDuplicateProjects = getDataDir("test-project-duplicate-project-config") const log = getRootLogger().createLog() -// TODO: remove this describe block in 0.14 +// TODO-0.14: remove this describe block in 0.14 describe("prepareProjectResource", () => { const projectResourceTemplate = { apiVersion: DEFAULT_API_VERSION, diff --git a/core/test/unit/src/docs/config.ts b/core/test/unit/src/docs/config.ts index efb7cc4131..0053f4fed0 100644 --- a/core/test/unit/src/docs/config.ts +++ b/core/test/unit/src/docs/config.ts @@ -63,7 +63,7 @@ describe("docs config module", () => { # Example: # # \`\`\`yaml - # modules: + # scan: # exclude: # - node_modules/**/* # - vendor/**/* @@ -75,7 +75,7 @@ describe("docs config module", () => { # Example: # # \`\`\`javascript - # modules: + # scan: # exclude: # - node_modules/**/* # - vendor/**/* @@ -87,7 +87,7 @@ describe("docs config module", () => { # Example: # # \`\`\` - # modules: + # scan: # exclude: # - node_modules/**/* # - vendor/**/* @@ -98,7 +98,7 @@ describe("docs config module", () => { const expected = dedent` # Example: # - # modules: + # scan: # exclude: # - node_modules/**/* # - vendor/**/* diff --git a/core/test/unit/src/garden.ts b/core/test/unit/src/garden.ts index b5d46a9d4b..43a36e60a7 100644 --- a/core/test/unit/src/garden.ts +++ b/core/test/unit/src/garden.ts @@ -53,6 +53,9 @@ import { convertExecModule } from "../../../src/plugins/exec/convert" import { getLogMessages } from "../../../src/util/testing" import { TreeCache } from "../../../src/cache" import { omitUndefined } from "../../../src/util/objects" +import { prepareProjectResource } from "../../../src/config/base" +import { CoreLog } from "../../../src/logger/log-entry" +import { Logger, LogLevel } from "../../../src/logger/logger" // TODO-G2: change all module config based tests to be action-based. @@ -2544,6 +2547,25 @@ describe("Garden", () => { expect(getNames(modules).sort()).to.eql(["module-a", "module-b"]) }) + // TODO-0.14: remove this and core/test/data/test-projects/project-include-exclude-old-syntax directory + it("should respect the modules.include and modules.exclude fields, if specified", async () => { + const projectRoot = getDataDir("test-projects", "project-include-exclude-old-syntax") + const garden = await makeTestGarden(projectRoot) + const modules = await garden.resolveModules({ log: garden.log }) + + // Should NOT include "nope" and "module-c" + expect(getNames(modules).sort()).to.eql(["module-a", "module-b"]) + }) + + it("should respect the scan.include and scan.exclude fields, if specified", async () => { + const projectRoot = getDataDir("test-projects", "project-include-exclude") + const garden = await makeTestGarden(projectRoot) + const modules = await garden.resolveModules({ log: garden.log }) + + // Should NOT include "nope" and "module-c" + expect(getNames(modules).sort()).to.eql(["module-a", "module-b"]) + }) + it("should respect .gitignore and .gardenignore files", async () => { const projectRoot = getDataDir("test-projects", "dotignore") const garden = await makeTestGarden(projectRoot) @@ -2555,7 +2577,7 @@ describe("Garden", () => { it("should respect custom dotignore files", async () => { // In this project we have custom dotIgnoreFile: .customignore which overrides the default .gardenignore. // Thus, all exclusions from .gardenignore will be skipped. - // TODO: amend the config core/test/data/test-projects/dotignore-custom/garden.yml in 0.14 + // TODO-0.14: amend the config core/test/data/test-projects/dotignore-custom/garden.yml const projectRoot = getDataDir("test-projects", "dotignore-custom") const garden = await makeTestGarden(projectRoot) const modules = await garden.resolveModules({ log: garden.log }) @@ -2565,7 +2587,7 @@ describe("Garden", () => { expect(getNames(modules).sort()).to.eql(["module-a", "module-c"]) }) - // TODO: Delete this context AND core/test/data/test-projects/dotignore-custom-legacy directory oin 0.14 + // TODO-0.14: Delete this context AND core/test/data/test-projects/dotignore-custom-legacy directory in 0.14 context("dotignore files migration to 0.13", async () => { it("should remap singleton array `dotIgnoreFiles` to scalar `dotIgnoreFile`", async () => { // In this project we have custom dotIgnoreFile: .customignore which overrides the default .gardenignore. diff --git a/docs/reference/project-config.md b/docs/reference/project-config.md index 9c556bea88..55fdcfeb2c 100644 --- a/docs/reference/project-config.md +++ b/docs/reference/project-config.md @@ -107,9 +107,9 @@ proxy: # Note that the `GARDEN_PROXY_DEFAULT_ADDRESS` environment variable takes precedence over this value. hostname: localhost -# Control where to scan for modules in the project. -modules: - # Specify a list of POSIX-style paths or globs that should be scanned for Garden modules. +# Control where to scan for configuration files in the project. +scan: + # Specify a list of POSIX-style paths or globs that should be scanned for Garden configuration files. # # Note that you can also _exclude_ path using the `exclude` field or by placing `.gardenignore` files in your source # tree, which use the same format as `.gitignore` files. See the [Configuration Files @@ -123,7 +123,8 @@ modules: # Also note that specifying an empty list here means _no paths_ should be included. include: - # Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for modules. + # Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for configuration + # files. # # The filters here also affect which files and directories are watched for changes. So if you have a large number of # directories in your project that should not be watched, you should specify them here. @@ -464,19 +465,19 @@ proxy: hostname: - 127.0.0.1 ``` -### `modules` +### `scan` -Control where to scan for modules in the project. +Control where to scan for configuration files in the project. | Type | Required | | -------- | -------- | | `object` | No | -### `modules.include[]` +### `scan.include[]` -[modules](#modules) > include +[scan](#scan) > include -Specify a list of POSIX-style paths or globs that should be scanned for Garden modules. +Specify a list of POSIX-style paths or globs that should be scanned for Garden configuration files. Note that you can also _exclude_ path using the `exclude` field or by placing `.gardenignore` files in your source tree, which use the same format as `.gitignore` files. See the [Configuration Files guide](https://docs.garden.io/using-garden/configuration-overview#including-excluding-files-and-directories) for details. @@ -491,17 +492,17 @@ Also note that specifying an empty list here means _no paths_ should be included Example: ```yaml -modules: +scan: ... include: - modules/**/* ``` -### `modules.exclude[]` +### `scan.exclude[]` -[modules](#modules) > exclude +[scan](#scan) > exclude -Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for modules. +Specify a list of POSIX-style paths or glob patterns that should be excluded when scanning for configuration files. The filters here also affect which files and directories are watched for changes. So if you have a large number of directories in your project that should not be watched, you should specify them here. @@ -520,7 +521,7 @@ See the [Configuration Files guide](https://docs.garden.io/using-garden/configur Example: ```yaml -modules: +scan: ... exclude: - public/**/*