diff --git a/garden-service/src/config/module.ts b/garden-service/src/config/module.ts index be2bdc05e3..20e7fbfbb1 100644 --- a/garden-service/src/config/module.ts +++ b/garden-service/src/config/module.ts @@ -219,7 +219,7 @@ export const moduleConfigSchema = baseModuleSpecSchema .description("The configuration for a module.") .unknown(false) -export function serializeConfig(moduleConfig: ModuleConfig) { +export function serializeConfig(moduleConfig: Partial) { return stableStringify(moduleConfig) } diff --git a/garden-service/src/vcs/vcs.ts b/garden-service/src/vcs/vcs.ts index 2fd4d7d896..bbfcc55ef1 100644 --- a/garden-service/src/vcs/vcs.ts +++ b/garden-service/src/vcs/vcs.ts @@ -237,7 +237,8 @@ export function getVersionString(moduleConfig: ModuleConfig, treeVersions: Named * The versions argument should consist of moduleConfig's tree version, and the tree versions of its dependencies. */ export function hashVersions(moduleConfig: ModuleConfig, versions: NamedTreeVersion[]) { - const configString = serializeConfig(moduleConfig) + // We omit the configPath, path, and outputs fields as these can between users and runtimes + const configString = serializeConfig(omit(moduleConfig, ["configPath", "path", "outputs"])) const versionStrings = sortBy(versions, "name").map((v) => `${v.name}_${v.contentHash}`) return hashStrings([configString, ...versionStrings]) } diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-1/garden.yml new file mode 100644 index 0000000000..4a108f6468 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/garden.yml @@ -0,0 +1,10 @@ +kind: Project +name: test-project-fixed-version-hashes-1 +environments: + - name: local + providers: + - name: test-plugin + - name: test-plugin-b + - name: other +variables: + some: variable diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/garden.yml new file mode 100644 index 0000000000..25d72e1334 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/garden.yml @@ -0,0 +1,24 @@ +kind: Module +name: module-a +type: test +services: + - name: service-a + env: + TEST_LOCAL_ENV: ${local.env.MODULE_A_TEST_ENV_VAR} + TEST_ENV: ${var.some} +build: + command: [echo, A] +tests: + - name: unit + command: [echo, OK] + - name: integration + command: [echo, OK] +tasks: + - name: task-a-1 + command: [echo, task-a-1] + - name: task-a-2 + command: [echo, task-a-2] + dependencies: + - task-a-1 + env: + TASK_OUTPUT: ${runtime.tasks.task-a-1.outputs.log} \ No newline at end of file diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/hello.txt new file mode 100644 index 0000000000..845d2016fe --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-a/hello.txt @@ -0,0 +1 @@ +hello module-a diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/garden.yml new file mode 100644 index 0000000000..f09543ae96 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/garden.yml @@ -0,0 +1,17 @@ +kind: Module +name: module-b +type: test +services: + - name: service-b + dependencies: + - service-a +build: + command: [echo, B] + dependencies: + - module-a +tests: + - name: unit + command: [echo, OK] +tasks: + - name: task-b + command: [echo, OK] diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/hello.txt new file mode 100644 index 0000000000..15d8098c2f --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-b/hello.txt @@ -0,0 +1 @@ +hello module-b diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/garden.yml new file mode 100644 index 0000000000..0ff5a5ca02 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/garden.yml @@ -0,0 +1,16 @@ +kind: Module +name: module-c +type: test +services: + - name: service-c +build: + dependencies: + - module-b +tests: + - name: unit + command: [echo, OK] + - name: integ + command: [echo, OK] +tasks: + - name: task-c + command: [echo, OK] diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/hello.txt new file mode 100644 index 0000000000..45c058d59e --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-1/module-c/hello.txt @@ -0,0 +1 @@ +hello module-c diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-2/garden.yml new file mode 100644 index 0000000000..cad6c6c642 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/garden.yml @@ -0,0 +1,10 @@ +kind: Project +name: test-project-fixed-version-hashes-2 +environments: + - name: env-name-that-is-different-from-fixed-version-hashes-1 + providers: + - name: test-plugin + - name: test-plugin-b + - name: other +variables: + some: variable diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/garden.yml new file mode 100644 index 0000000000..25d72e1334 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/garden.yml @@ -0,0 +1,24 @@ +kind: Module +name: module-a +type: test +services: + - name: service-a + env: + TEST_LOCAL_ENV: ${local.env.MODULE_A_TEST_ENV_VAR} + TEST_ENV: ${var.some} +build: + command: [echo, A] +tests: + - name: unit + command: [echo, OK] + - name: integration + command: [echo, OK] +tasks: + - name: task-a-1 + command: [echo, task-a-1] + - name: task-a-2 + command: [echo, task-a-2] + dependencies: + - task-a-1 + env: + TASK_OUTPUT: ${runtime.tasks.task-a-1.outputs.log} \ No newline at end of file diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/hello.txt new file mode 100644 index 0000000000..845d2016fe --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-a/hello.txt @@ -0,0 +1 @@ +hello module-a diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/garden.yml new file mode 100644 index 0000000000..f09543ae96 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/garden.yml @@ -0,0 +1,17 @@ +kind: Module +name: module-b +type: test +services: + - name: service-b + dependencies: + - service-a +build: + command: [echo, B] + dependencies: + - module-a +tests: + - name: unit + command: [echo, OK] +tasks: + - name: task-b + command: [echo, OK] diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/hello.txt new file mode 100644 index 0000000000..15d8098c2f --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-b/hello.txt @@ -0,0 +1 @@ +hello module-b diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/garden.yml b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/garden.yml new file mode 100644 index 0000000000..0ff5a5ca02 --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/garden.yml @@ -0,0 +1,16 @@ +kind: Module +name: module-c +type: test +services: + - name: service-c +build: + dependencies: + - module-b +tests: + - name: unit + command: [echo, OK] + - name: integ + command: [echo, OK] +tasks: + - name: task-c + command: [echo, OK] diff --git a/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/hello.txt b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/hello.txt new file mode 100644 index 0000000000..45c058d59e --- /dev/null +++ b/garden-service/test/data/test-projects/fixed-version-hashes-2/module-c/hello.txt @@ -0,0 +1 @@ +hello module-c diff --git a/garden-service/test/unit/src/garden.ts b/garden-service/test/unit/src/garden.ts index 2b06292bf3..48fddd69e8 100644 --- a/garden-service/test/unit/src/garden.ts +++ b/garden-service/test/unit/src/garden.ts @@ -3065,6 +3065,63 @@ describe("Garden", () => { expect(result).to.not.eql(version) }) + + context("test against fixed version hashes", async () => { + const moduleAVersionString = "v-0cf3cb04c0" + const moduleBVersionString = "v-db85090197" + const moduleCVersionString = "v-18ffe09ae4" + + it("should return the same module versions between runtimes", async () => { + const projectRoot = getDataDir("test-projects", "fixed-version-hashes-1") + + process.env.MODULE_A_TEST_ENV_VAR = "foo" + + const garden = await makeTestGarden(projectRoot) + const graph = await garden.getConfigGraph(garden.log) + const moduleA = await graph.getModule("module-a") + const moduleB = await graph.getModule("module-b") + const moduleC = await graph.getModule("module-c") + expect(moduleA.version.versionString).to.equal(moduleAVersionString) + expect(moduleB.version.versionString).to.equal(moduleBVersionString) + expect(moduleC.version.versionString).to.equal(moduleCVersionString) + + delete process.env.TEST_ENV_VAR + }) + + it("should return the same module versions for identiclal modules in different projects", async () => { + const projectRoot = getDataDir("test-projects", "fixed-version-hashes-2") + + process.env.MODULE_A_TEST_ENV_VAR = "foo" + + const garden = await makeTestGarden(projectRoot) + const graph = await garden.getConfigGraph(garden.log) + const moduleA = await graph.getModule("module-a") + const moduleB = await graph.getModule("module-b") + const moduleC = await graph.getModule("module-c") + expect(moduleA.version.versionString).to.equal(moduleAVersionString) + expect(moduleB.version.versionString).to.equal(moduleBVersionString) + expect(moduleC.version.versionString).to.equal(moduleCVersionString) + + delete process.env.MODULE_A_TEST_ENV_VAR + }) + + it("should not return the same module versions if templated variables change", async () => { + const projectRoot = getDataDir("test-projects", "fixed-version-hashes-1") + + process.env.MODULE_A_TEST_ENV_VAR = "bar" + + const garden = await makeTestGarden(projectRoot) + const graph = await garden.getConfigGraph(garden.log) + const moduleA = await graph.getModule("module-a") + const moduleB = await graph.getModule("module-b") + const moduleC = await graph.getModule("module-c") + expect(moduleA.version.versionString).to.not.equal(moduleAVersionString) + expect(moduleB.version.versionString).to.equal(moduleBVersionString) + expect(moduleC.version.versionString).to.equal(moduleCVersionString) + + delete process.env.MODULE_A_TEST_ENV_VAR + }) + }) }) describe("loadExtSourcePath", () => { diff --git a/garden-service/test/unit/src/vcs/vcs.ts b/garden-service/test/unit/src/vcs/vcs.ts index dbe9cbdb9b..bf594a0b70 100644 --- a/garden-service/test/unit/src/vcs/vcs.ts +++ b/garden-service/test/unit/src/vcs/vcs.ts @@ -261,6 +261,21 @@ describe("VcsHandler", () => { getVersionString(config, [namedVersionB, namedVersionA, namedVersionC]) ) }) + + it("should be stable between runtimes", async () => { + const projectRoot = getDataDir("test-projects", "fixed-version-hashes-1") + + // fixed-version-hashes-1 expects this var to be set + process.env.MODULE_A_TEST_ENV_VAR = "foo" + + const garden = await makeTestGarden(projectRoot) + const config = await garden.resolveModuleConfig(garden.log, "module-a") + + const fixedVersionString = "v-72ab6d8477" + expect(getVersionString(config, [namedVersionA, namedVersionB, namedVersionC])).to.eql(fixedVersionString) + + delete process.env.TEST_ENV_VAR + }) }) })