Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .bumpy/cycle-with-schema-error.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"varlock": patch
---

A dependency cycle is now reported even when another item has a schema error, instead of the load stopping with "varlock stopped before the command finished"
7 changes: 4 additions & 3 deletions packages/varlock/src/env-graph/lib/env-graph.ts
Original file line number Diff line number Diff line change
Expand Up @@ -763,9 +763,8 @@ export class EnvGraph {
}
this.configItemsProcessed = true;

if (hasErrors) return;

// check for cycles in resolver dependencies
// check for cycles in resolver dependencies. This runs even when another item already has an error:
// an item on an unmarked cycle waits on itself forever when values are resolved
const cycles = findGraphCycles(this.graphAdjacencyList);
for (const cycleItemKeys of cycles) {
for (const itemKey of cycleItemKeys) {
Expand All @@ -779,6 +778,8 @@ export class EnvGraph {
);
}
}

if (hasErrors) return;
this.checkBootDynamicItems();

// now execute all root decorators
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, it, expect } from 'vitest';
import outdent from 'outdent';
import { EnvGraph } from '../index';
import { DotEnvFileDataSource } from '../lib/data-source';

describe('a dependency cycle next to an unrelated schema error', () => {
it('is still reported, and resolving finishes', async () => {
const g = new EnvGraph();
await g.setRootDataSource(new DotEnvFileDataSource('.env.schema', {
overrideContents: outdent`
B=$B
C=$Z
`,
}));
await g.finishLoad();
// without the cycle error on B, this promise never settles
await g.resolveEnvValues();
expect(g.configSchema.B.errors.map((e) => e.message)).toContain('Item cannot have dependency on itself');
expect(g.configSchema.C.errors.map((e) => e.message)).toContain('ref(): invalid dependency: Z');
}, 5000);
});
Loading