Skip to content

Commit 930816f

Browse files
authored
fix: locate Terraform entrypoint file (#16753)
Fixes: #16360
1 parent e27953d commit 930816f

File tree

4 files changed

+158
-6
lines changed

4 files changed

+158
-6
lines changed

site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.test.tsx

Lines changed: 128 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,12 @@ import {
2222
waitForLoaderToBeRemoved,
2323
} from "testHelpers/renderHelpers";
2424
import { server } from "testHelpers/server";
25+
import type { FileTree } from "utils/filetree";
2526
import type { MonacoEditorProps } from "./MonacoEditor";
2627
import { Language } from "./PublishTemplateVersionDialog";
27-
import TemplateVersionEditorPage from "./TemplateVersionEditorPage";
28+
import TemplateVersionEditorPage, {
29+
findEntrypointFile,
30+
} from "./TemplateVersionEditorPage";
2831

2932
const { API } = apiModule;
3033

@@ -409,3 +412,127 @@ function renderEditorPage(queryClient: QueryClient) {
409412
</AppProviders>,
410413
);
411414
}
415+
416+
describe("Find entrypoint", () => {
417+
it("empty tree", () => {
418+
const ft: FileTree = {};
419+
const mainFile = findEntrypointFile(ft);
420+
expect(mainFile).toBeUndefined();
421+
});
422+
it("flat structure, main.tf in root", () => {
423+
const ft: FileTree = {
424+
"aaa.tf": "hello",
425+
"bbb.tf": "world",
426+
"main.tf": "foobar",
427+
"nnn.tf": "foobaz",
428+
};
429+
430+
const mainFile = findEntrypointFile(ft);
431+
expect(mainFile).toBe("main.tf");
432+
});
433+
it("flat structure, no main.tf", () => {
434+
const ft: FileTree = {
435+
"aaa.tf": "hello",
436+
"bbb.tf": "world",
437+
"ccc.tf": "foobaz",
438+
"nnn.tf": "foobaz",
439+
};
440+
441+
const mainFile = findEntrypointFile(ft);
442+
expect(mainFile).toBe("nnn.tf");
443+
});
444+
it("with dirs, single main.tf", () => {
445+
const ft: FileTree = {
446+
"aaa-dir": {
447+
"aaa.tf": "hello",
448+
"bbb.tf": "world",
449+
},
450+
"bbb-dir": {
451+
"aaa.tf": "hello",
452+
"bbb.tf": "world",
453+
},
454+
"main.tf": "foobar",
455+
"nnn.tf": "foobaz",
456+
};
457+
458+
const mainFile = findEntrypointFile(ft);
459+
expect(mainFile).toBe("main.tf");
460+
});
461+
it("with dirs, multiple main.tf's", () => {
462+
const ft: FileTree = {
463+
"aaa-dir": {
464+
"aaa.tf": "hello",
465+
"bbb.tf": "world",
466+
"main.tf": "foobar",
467+
},
468+
"bbb-dir": {
469+
"aaa.tf": "hello",
470+
"bbb.tf": "world",
471+
"main.tf": "foobar",
472+
},
473+
"ccc-dir": {
474+
"aaa.tf": "hello",
475+
"bbb.tf": "world",
476+
},
477+
"main.tf": "foobar",
478+
"nnn.tf": "foobaz",
479+
"zzz-dir": {
480+
"aaa.tf": "hello",
481+
"bbb.tf": "world",
482+
"main.tf": "foobar",
483+
},
484+
};
485+
486+
const mainFile = findEntrypointFile(ft);
487+
expect(mainFile).toBe("main.tf");
488+
});
489+
it("with dirs, multiple main.tf, no main.tf in root", () => {
490+
const ft: FileTree = {
491+
"aaa-dir": {
492+
"aaa.tf": "hello",
493+
"bbb.tf": "world",
494+
"main.tf": "foobar",
495+
},
496+
"bbb-dir": {
497+
"aaa.tf": "hello",
498+
"bbb.tf": "world",
499+
"main.tf": "foobar",
500+
},
501+
"ccc-dir": {
502+
"aaa.tf": "hello",
503+
"bbb.tf": "world",
504+
},
505+
"nnn.tf": "foobaz",
506+
"zzz-dir": {
507+
"aaa.tf": "hello",
508+
"bbb.tf": "world",
509+
"main.tf": "foobar",
510+
},
511+
};
512+
513+
const mainFile = findEntrypointFile(ft);
514+
expect(mainFile).toBe("aaa-dir/main.tf");
515+
});
516+
it("with dirs, multiple main.tf, unordered file tree", () => {
517+
const ft: FileTree = {
518+
"ccc-dir": {
519+
"aaa.tf": "hello",
520+
"bbb.tf": "world",
521+
"main.tf": "foobar",
522+
},
523+
"aaa-dir": {
524+
"aaa.tf": "hello",
525+
"bbb.tf": "world",
526+
"main.tf": "foobar",
527+
},
528+
"zzz-dir": {
529+
"aaa.tf": "hello",
530+
"bbb.tf": "world",
531+
"main.tf": "foobar",
532+
},
533+
};
534+
535+
const mainFile = findEntrypointFile(ft);
536+
expect(mainFile).toBe("aaa-dir/main.tf");
537+
});
538+
});

site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.tsx

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ export const TemplateVersionEditorPage: FC = () => {
9090
// File navigation
9191
// It can be undefined when a selected file is deleted
9292
const activePath: string | undefined =
93-
searchParams.get("path") ?? findInitialFile(fileTree ?? {});
93+
searchParams.get("path") ?? findEntrypointFile(fileTree ?? {});
9494
const onActivePathChange = (path: string | undefined) => {
9595
if (path) {
9696
searchParams.set("path", path);
@@ -357,10 +357,33 @@ const publishVersion = async (options: {
357357
return Promise.all(publishActions);
358358
};
359359

360-
const findInitialFile = (fileTree: FileTree): string | undefined => {
360+
const defaultMainTerraformFile = "main.tf";
361+
362+
// findEntrypointFile function locates the entrypoint file to open in the Editor.
363+
// It browses the filetree following these steps:
364+
// 1. If "main.tf" exists in root, return it.
365+
// 2. Traverse through sub-directories.
366+
// 3. If "main.tf" exists in a sub-directory, skip further browsing, and return the path.
367+
// 4. If "main.tf" was not found, return the last reviewed "".tf" file.
368+
export const findEntrypointFile = (fileTree: FileTree): string | undefined => {
361369
let initialFile: string | undefined;
362370

363-
traverse(fileTree, (content, filename, path) => {
371+
if (Object.keys(fileTree).find((key) => key === defaultMainTerraformFile)) {
372+
return defaultMainTerraformFile;
373+
}
374+
375+
let skip = false;
376+
traverse(fileTree, (_, filename, path) => {
377+
if (skip) {
378+
return;
379+
}
380+
381+
if (filename === defaultMainTerraformFile) {
382+
initialFile = path;
383+
skip = true;
384+
return;
385+
}
386+
364387
if (filename.endsWith(".tf")) {
365388
initialFile = path;
366389
}

site/src/utils/filetree.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,6 @@ test("traverse() go trough all the file tree files", () => {
122122
traverse(fileTree, (_content, _filename, fullPath) => {
123123
filePaths.push(fullPath);
124124
});
125-
const expectedFilePaths = ["main.tf", "images", "images/java.Dockerfile"];
125+
const expectedFilePaths = ["images", "images/java.Dockerfile", "main.tf"];
126126
expect(filePaths).toEqual(expectedFilePaths);
127127
});

site/src/utils/filetree.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,9 @@ export const traverse = (
9696
) => void,
9797
parent?: string,
9898
) => {
99-
for (const [filename, content] of Object.entries(fileTree)) {
99+
for (const [filename, content] of Object.entries(fileTree).sort(([a], [b]) =>
100+
a.localeCompare(b),
101+
)) {
100102
const fullPath = parent ? `${parent}/${filename}` : filename;
101103
callback(content, filename, fullPath);
102104
if (typeof content === "object") {

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy