Skip to content

Commit

Permalink
Change the behavior of environment overlay.
Browse files Browse the repository at this point in the history
Now it applies as the last step in each seed before it executes, which is notionally equivalent to having
a let-multi at the top of each.

This allows seeds to be confident that their values are set by them and not accidentally by calling seeds.

Part of #38.
  • Loading branch information
jkomoros committed Jul 7, 2023
1 parent aceb6fa commit a4ae292
Show file tree
Hide file tree
Showing 3 changed files with 49 additions and 10 deletions.
4 changes: 1 addition & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -627,9 +627,7 @@ Environments are passed into the garden when it boots up, typically by overlayin
In some cases you want to set environment variables for seeds in a packet by default. Instead of having annoying, error-prone duplicated `let-multi` for each seed entrypoint, you can define an environment overlay at the top of the seed packet.
The actual environment used by any seed when it is first grown will be the garden's base environment, overlaid with the contents of the packet's environment.
Note that if a seed is grown as a sub-seed it will not use its own environment and instead use the environment that is passed down to it by its calling seed. (TODO: this behavior makes this functionality not useful for seeds used as sub-expressions in other packets, who expect a given amount of values being set)
The actual environment used by any seed when it is first grown will be the garden's base environment, overlaid with any `let`/`let-multi` overrides from seeds higher in the call stack, and finally have the packet's `environment` values overlaid. This creates behavior semantically similar to if every seed in the packet was wrapped in a `let-multi` with the packet's environment, and ensure that seeds have environment values set in a way they expect.
The environment can contain any number of values, but some are used for specific uses by the framework, documented below.
Expand Down
5 changes: 3 additions & 2 deletions src/seed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ export class Seed<D extends ExpandedSeedData = ExpandedSeedData> {
}

async grow(env? : Environment) : Promise<Value> {
if (!env) env = this.garden.environment.clone(this._environmentOverlay);
return grow(this, env);
if (!env) env = this.garden.environment;
const subEnv = env.clone(this._environmentOverlay);
return grow(this, subEnv);
}
}
50 changes: 45 additions & 5 deletions test/base/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -639,7 +639,7 @@ Suffix`;
assert.deepStrictEqual(actual, golden);
});

it ('environment overlay is ignored in sub-seed execution', async () => {
it ('environment overlay overrides parent seed let', async () => {
const garden = loadTestGarden();
const packet = seedPacket.parse({
version: 0,
Expand All @@ -656,20 +656,60 @@ Suffix`;
name: 'komoroske.com:test',
value: 5,
block: {
type: 'var',
name: 'komoroske.com:test'
id: 'env-test'
}
}
}
});
garden.plantSeedPacket('test/base/c_test.json', packet);
const seed = await garden.seed('other-test');
const actual = await seed.grow();
//The other-test should shadow the environment variable.
const golden = 5;
//The other-test value should be shadowed by the environment packet
const golden = 3;
assert.deepStrictEqual(actual, golden);
});

it ('environment overlay passed into sub-seed', async () => {
const garden = loadTestGarden();
const packet = seedPacket.parse({
version: 0,
environment: {
'komoroske.com:test': 3
},
seeds: {
'env-test': {
type: 'array',
items: [
{
type: 'var',
name: 'komoroske.com:test'
},
{
type: 'var',
name: 'komoroske.com:other'
}
]
},
'other-test': {
type: 'let',
name: 'komoroske.com:other',
value: 5,
block: {
id: 'env-test'
}
}
}
});
garden.plantSeedPacket('test/base/c_test.json', packet);
const seed = await garden.seed('other-test');
const actual = await seed.grow();
//The other value should make it through from the parent seed, and main
//value should not be affected.
const golden = [3, 5];
assert.deepStrictEqual(actual, golden);
});



});

Expand Down

0 comments on commit a4ae292

Please sign in to comment.