Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: remove "foundation docs" fast output collection mode #271

Merged
merged 2 commits into from
Feb 5, 2024
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
61 changes: 6 additions & 55 deletions src/docs/PlatformDocumentationGenerator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import { DocumentationRepository } from "./DocumentationRepository.ts";
import { MarkdownUtils } from "../model/MarkdownUtils.ts";
import { ComplianceControlRepository } from "../compliance/ComplianceControlRepository.ts";
import {
RunAllPlatformModuleOutputCollector,
RunIndividualPlatformModuleOutputCollector,
} from "./PlatformModuleOutputCollector.ts";

Expand Down Expand Up @@ -80,8 +79,12 @@ export class PlatformDocumentationGenerator {
this.logger,
);

const platformModuleDocumentation = await this
.buildPlatformModuleOutputCollector(dependencies.platform);
const platformModuleDocumentation =
new RunIndividualPlatformModuleOutputCollector(
this.repo,
this.terragrunt,
this.logger,
);

// as a fallback process modules serially, unfortunately this is the only "safe" way to collect output
// see https://github.com/meshcloud/collie-cli/issues/265
Expand All @@ -99,58 +102,6 @@ export class PlatformDocumentationGenerator {
platformProgress.done();
}

private async buildPlatformModuleOutputCollector(platform: PlatformConfig) {
const platformHclPath = this.foundation.resolvePlatformPath(
platform,
"platform.hcl",
);

const platformHcl = await Deno.readTextFile(platformHclPath);

const fastModeIdentifier =
"--- BEGIN COLLIE PLATFORM MODULE OUTPUT: ${path_relative_to_include()} ---";

this.logger.verbose(
(fmt) =>
`detecting if fast output collection is supported in ${
fmt.kitPath(
platformHclPath,
)
} by looking for a before_hook emitting "${fastModeIdentifier}"`,
);
const enableFastMode = platformHcl.includes(fastModeIdentifier);
this.logger.verbose(
(_) => "fast output collection is supported: " + enableFastMode,
);

if (enableFastMode) {
const platformPath = this.foundation.resolvePlatformPath(platform);
const collector = new RunAllPlatformModuleOutputCollector(
this.terragrunt,
this.logger,
);

await collector.initialize(platformPath);

return collector;
} else {
this.logger.tip(
(f) =>
`Enable fast output collection for collie in ${
f.kitPath(
platformHclPath,
)
}`,
);

return new RunIndividualPlatformModuleOutputCollector(
this.repo,
this.terragrunt,
this.logger,
);
}
}

private async generatePlatformModuleDocumentation(
dep: KitModuleDependency,
documentationMd: string,
Expand Down
21 changes: 0 additions & 21 deletions src/docs/PlatformModuleOutputCollector.test.ts

This file was deleted.

90 changes: 17 additions & 73 deletions src/docs/PlatformModuleOutputCollector.ts
Original file line number Diff line number Diff line change
@@ -1,87 +1,31 @@
import * as path from "std/path";
import { chunk } from "std/collections/chunk";
import { TerragruntCliFacade } from "../api/terragrunt/TerragruntCliFacade.ts";
import { KitModuleDependency } from "../kit/KitDependencyAnalyzer.ts";
import { CollieRepository } from "../model/CollieRepository.ts";
import { Logger } from "../cli/Logger.ts";
import { MeshError } from "../errors.ts";

/**
* Note:
* For a great UX/DX it's important that running "collie foundation docs" is fast.
*
* We have therefore tried speeding it up by collecting output from platform modules in parallel.
* Unfortunately, it appears that terragrunt does not offer us a good way to reliably get all the outputs from all
* platform modules, see https://github.com/meshcloud/collie-cli/issues/267
*
* This "fast mode" detection also caused other bugs like https://github.com/meshcloud/collie-cli/issues/269
*
* In the future, we should maybe investigate cachingas an alternative to parallelization, because usually an engineer
* would re-run "collie foundation docs" only after changing a specific platform module
*/

export interface PlatformModuleOutputCollector {
getOutput(dep: KitModuleDependency): Promise<string>;
}

interface PlatformModuleOutput {
module: string;
output: string;
}

export class RunAllPlatformModuleOutputCollector
implements PlatformModuleOutputCollector {
private modules: PlatformModuleOutput[] = [];

constructor(
private readonly terragrunt: TerragruntCliFacade,
private readonly logger: Logger,
) {}

async initialize(platformPath: string) {
const result = await this.terragrunt.collectOutputs(
platformPath,
"documentation_md",
);

if (!result.status.success) {
this.logger.error(
(fmt) =>
`Failed to collect output "documentation_md" from platform ${
fmt.kitPath(
platformPath,
)
}`,
);
this.logger.error(result.stderr);

throw new MeshError(
"Failed to collect documentation output from platform modules",
);
}

this.modules = RunAllPlatformModuleOutputCollector.parseTerragrunt(
result.stdout,
);
}

// deno-lint-ignore require-await
async getOutput(dep: KitModuleDependency): Promise<string> {
const platformModulePath = path.dirname(dep.sourcePath);
const module = this.modules.find((x) =>
platformModulePath.endsWith(x.module)
);

if (!module) {
throw new MeshError(
"Failed to find documentation output from platform module " +
platformModulePath,
);
}
return module?.output;
}

public static parseTerragrunt(stdout: string): PlatformModuleOutput[] {
const regex = /^--- BEGIN COLLIE PLATFORM MODULE OUTPUT: (.+) ---$/gm;

const sections = stdout.split(regex);
const cleanedSections = sections
.map((x) => x.trim())
.filter((x) => x !== "");

return chunk(cleanedSections, 2).map(([module, output]) => ({
module,
output,
}));
}
}

/**
* Collects platform module output by running each platform module individually in series.
*/
export class RunIndividualPlatformModuleOutputCollector
implements PlatformModuleOutputCollector {
constructor(
Expand Down
Loading