Skip to content

Commit

Permalink
Merge branch 'main' into bt-packlist
Browse files Browse the repository at this point in the history
  • Loading branch information
tylerbutler committed Oct 21, 2024
2 parents b361b0f + 0ef059c commit 8142a99
Show file tree
Hide file tree
Showing 31 changed files with 119 additions and 309 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -105,27 +105,6 @@ function findScript(json: Readonly<PackageJson>, command: string): string | unde
return bestScript.script;
}

/**
* Find the script name for the tsc-multi command in a npm package.json
*
* @param json - the package.json content to search script in
* @param config - the tsc-multi config to check for
* @returns first script name found to match the command
*
* @remarks
*/
function findTscMultiScript(json: PackageJson, config: string): string | undefined {
for (const [script, scriptCommands] of Object.entries(json.scripts)) {
if (scriptCommands === undefined) {
continue;
}

if (scriptCommands.startsWith("tsc-multi") && scriptCommands.includes(config)) {
return script;
}
}
}

/**
* Find the script name for the fluid-tsc command in a package.json
*
Expand Down Expand Up @@ -171,12 +150,9 @@ function findTscScript(json: Readonly<PackageJson>, project: string): string | u
if (project === "./tsconfig.json") {
addIfDefined(findScript(json, "tsc"));
addIfDefined(findFluidTscScript(json, undefined));
addIfDefined(findTscMultiScript(json, "tsc-multi.cjs.json"));
addIfDefined(findTscMultiScript(json, "tsc-multi.node16.cjs.json"));
}
addIfDefined(findScript(json, `tsc --project ${project}`));
addIfDefined(findFluidTscScript(json, project));
addIfDefined(findTscMultiScript(json, project));
if (tscScripts.length === 1) {
return tscScripts[0];
}
Expand Down Expand Up @@ -715,7 +691,6 @@ export const handlers: Handler[] = [
match,
handler: async (file: string, root: string): Promise<string | undefined> => {
const projectMap = new Map<string, string>();
// Note: this does not check tsc-multi commands which do very likely reuse project files
return buildDepsHandler(
file,
root,
Expand Down
4 changes: 0 additions & 4 deletions build-tools/packages/build-tools/packlist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,6 @@ dist/fluidBuild/tasks/leaf/prettierTask.d.ts
dist/fluidBuild/tasks/leaf/prettierTask.d.ts.map
dist/fluidBuild/tasks/leaf/prettierTask.js
dist/fluidBuild/tasks/leaf/prettierTask.js.map
dist/fluidBuild/tasks/leaf/renamerTask.d.ts
dist/fluidBuild/tasks/leaf/renamerTask.d.ts.map
dist/fluidBuild/tasks/leaf/renamerTask.js
dist/fluidBuild/tasks/leaf/renamerTask.js.map
dist/fluidBuild/tasks/leaf/ts2EsmTask.d.ts
dist/fluidBuild/tasks/leaf/ts2EsmTask.d.ts.map
dist/fluidBuild/tasks/leaf/ts2EsmTask.js
Expand Down
8 changes: 1 addition & 7 deletions build-tools/packages/build-tools/src/common/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,7 @@ function printExecError(
? `${errorPrefix}: ${ret.stdout}\n${ret.stderr}`
: `${errorPrefix}: ${ret.stderr}`,
);
} else if (
warning &&
ret.stderr &&
// tsc-multi writes to stderr even when there are no errors, so this condition excludes that case as a workaround.
// Otherwise fluid-build spams warnings for all tsc-multi tasks.
!ret.stderr.includes("Found 0 errors")
) {
} else if (warning && ret.stderr) {
// no error code but still error messages, treat them is non fatal warnings
console.warn(`${errorPrefix}: warning during command ${command}`);
console.warn(`${errorPrefix}: ${ret.stderr}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -190,12 +190,7 @@ export abstract class LeafTask extends Task {
console.error(this.getExecErrors(ret));
return this.execDone(startTime, BuildResult.Failed);
}
if (
ret.stderr &&
// tsc-multi writes to stderr even when there are no errors, so this condition excludes that case as a workaround.
// Otherwise fluid-build spams warnings for all tsc-multi tasks.
!ret.stderr.includes("Found 0 errors")
) {
if (ret.stderr) {
// no error code but still error messages, treat them is non fatal warnings
console.warn(`${this.node.pkg.nameColored}: warning during command '${this.command}'`);
console.warn(this.getExecErrors(ret));
Expand Down

This file was deleted.

122 changes: 1 addition & 121 deletions build-tools/packages/build-tools/src/fluidBuild/tasks/leaf/tscTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import isEqual from "lodash.isequal";
import * as tsTypes from "typescript";

import { TscUtil, getTscUtils } from "../../tscUtils";
import { getInstalledPackageVersion, getRecursiveFiles } from "../taskUtils";
import { getInstalledPackageVersion } from "../taskUtils";
import { LeafTask, LeafWithDoneFileTask } from "./leafTask";

interface ITsBuildInfo {
Expand Down Expand Up @@ -512,123 +512,3 @@ export abstract class TscDependentTask extends LeafWithDoneFileTask {
protected abstract get configFileFullPaths(): string[];
protected abstract getToolVersion(): Promise<string>;
}

interface TscMultiConfig {
targets: {
extName?: string;
packageOverrides?: Record<string, unknown>;
}[];
projects: string[];
}

// This function is mimiced from tsc-multi.
function configKeyForPackageOverrides(overrides: Record<string, unknown> | undefined) {
if (overrides === undefined) return "";

const str = JSON.stringify(overrides);

// An implementation of DJB2 string hashing algorithm
let hash = 5381;
for (let i = 0; i < str.length; i++) {
hash = (hash << 5) + hash + str.charCodeAt(i); // hash * 33 + c
hash |= 0; // Convert to 32bit integer
}
return `.${hash}`;
}

/**
* A fluid-build task definition for tsc-multi.
*
* This implementation is a hack. It primarily uses the contents of the tsbuildinfo files created by the tsc-multi
* processes, and duplicates their content into the doneFile. It's duplicative but seems to be the simplest way to get
* basic incremental support in fluid-build.
*
* Source files are also considered for incremental purposes. However, config files outside the package (e.g. shared
* config files) are not considered. Thus, changes to those files will not trigger a rebuild of downstream packages.
*
* Jason-Ha observes that caching is only effective after the second build. But since tsc-multi is just orchestrating
* tsc, this should be able to derive from {@link TscTask} and override to get to the right config and tsbuildinfo.
*/
export class TscMultiTask extends LeafWithDoneFileTask {
protected async getToolVersion() {
return getInstalledPackageVersion("tsc-multi", this.node.pkg.directory);
}

protected async getDoneFileContent(): Promise<string | undefined> {
const command = this.command;

try {
const commandArgs = command.split(/\s+/);
const configArg = commandArgs.findIndex((arg) => arg === "--config");
if (configArg === -1) {
throw new Error(`no --config argument for tsc-multi command: ${command}`);
}
const tscMultiConfigFile = path.resolve(
this.package.directory,
commandArgs[configArg + 1],
);
commandArgs.splice(configArg, 2);
commandArgs.shift(); // Remove "tsc-multi" from the command
// Assume that the remaining arguments are project paths
const tscMultiProjects = commandArgs.filter((arg) => !arg.startsWith("-"));
const tscMultiConfig = JSON.parse(
await readFile(tscMultiConfigFile, "utf-8"),
) as TscMultiConfig;

// Command line projects replace any in config projects
if (tscMultiProjects.length > 0) {
tscMultiConfig.projects = tscMultiProjects;
}

if (tscMultiConfig.projects.length !== 1) {
throw new Error(
`TscMultiTask does not support ${command} that does not have exactly one project.`,
);
}

if (tscMultiConfig.targets.length !== 1) {
throw new Error(
`TscMultiTask does not support ${tscMultiConfigFile} that does not have exactly one target.`,
);
}

const project = tscMultiConfig.projects[0];
const projectExt = path.extname(project);
const target = tscMultiConfig.targets[0];
const relTsBuildInfoPath = `${project.substring(0, project.length - projectExt.length)}${
target.extName ?? ""
}${configKeyForPackageOverrides(target.packageOverrides)}.tsbuildinfo`;
const tsbuildinfoPath = this.getPackageFileFullPath(relTsBuildInfoPath);
if (!existsSync(tsbuildinfoPath)) {
// No tsbuildinfo file, so we need to build
throw new Error(`no tsbuildinfo file found: ${tsbuildinfoPath}`);
}

const files = [tscMultiConfigFile, path.resolve(this.package.directory, project)];

// Add src files
files.push(...(await getRecursiveFiles(path.resolve(this.package.directory, "src"))));

// Calculate hashes of all the files; only the hashes will be stored in the donefile.
const hashesP = files.map(async (name) => {
const hash = await this.node.context.fileHashCache.getFileHash(
this.getPackageFileFullPath(name),
);
return { name, hash };
});

const buildInfo = (await readFile(tsbuildinfoPath)).toString();
const version = await getInstalledPackageVersion("tsc-multi", this.node.pkg.directory);
const hashes = await Promise.all(hashesP);
const result = JSON.stringify({
version,
buildInfo,
hashes,
});
return result;
} catch (e) {
this.traceError(`error generating done file content: ${e}`);
}
return undefined;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,8 @@ import {
TypeValidationTask,
} from "./leaf/miscTasks";
import { PrettierTask } from "./leaf/prettierTask";
import { RenameTypesTask } from "./leaf/renamerTask";
import { Ts2EsmTask } from "./leaf/ts2EsmTask";
import { TscMultiTask, TscTask } from "./leaf/tscTask";
import { TscTask } from "./leaf/tscTask";
import { WebpackTask } from "./leaf/webpackTask";
import { Task } from "./task";
import { type TaskHandler, isConstructorFunction } from "./taskHandlers";
Expand All @@ -38,7 +37,6 @@ const executableToLeafTask: {
"ts2esm": Ts2EsmTask,
"tsc": TscTask,
"fluid-tsc": TscTask,
"tsc-multi": TscMultiTask,
"tslint": TsLintTask,
"eslint": EsLintTask,
"webpack": WebpackTask,
Expand Down Expand Up @@ -67,11 +65,6 @@ const executableToLeafTask: {
"flub list server": FlubListTask,
"flub list gitrest": FlubListTask,
"flub list historian": FlubListTask,

// Note that this assumes that "renamer" is ONLY used for renaming types. If it is used in a different task in the
// pipeline then this mapping will have to be updated.
"renamer": RenameTypesTask,
"flub rename-types": RenameTypesTask,
} as const;

/**
Expand Down
1 change: 0 additions & 1 deletion fluidBuild.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ module.exports = {
["nyc", "nyc"],
["oclif", "oclif"],
["prettier", "prettier"],
["renamer", "renamer"],
["rimraf", "rimraf"],
["tinylicious", "tinylicious"],
["ts2esm", "ts2esm"],
Expand Down
Loading

0 comments on commit 8142a99

Please sign in to comment.