adding sourcemaps when doing compile; adds shouldRun() capability on a per-target basis (#819)

* adding sourcemaps when doing compile

* sync version of shouldRun

* support async shouldRun checks

* wip!

* replaced the async being on the addTargetConfig side, but to the graph build time.

* Change files

* fixing format
This commit is contained in:
Kenneth Chau 2024-11-08 11:40:36 -08:00 коммит произвёл GitHub
Родитель 0b4047c7e5
Коммит 9b607e7123
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
18 изменённых файлов: 177 добавлений и 86 удалений

4
.swcrc
Просмотреть файл

@ -1,4 +1,5 @@
{
"$schema": "https://swc.rs/schema.json",
"jsc": {
"parser": {
"syntax": "typescript",
@ -10,5 +11,6 @@
"module": {
"type": "commonjs",
"ignoreDynamic": true
}
},
"sourceMaps": true
}

Просмотреть файл

@ -0,0 +1,25 @@
{
"changes": [
{
"type": "minor",
"comment": "add \"shouldRun()\" config to the target config",
"packageName": "@lage-run/cli",
"email": "kchau@microsoft.com",
"dependentChangeType": "patch"
},
{
"type": "minor",
"comment": "add \"shouldRun()\" config to the target config",
"packageName": "@lage-run/runners",
"email": "kchau@microsoft.com",
"dependentChangeType": "patch"
},
{
"type": "minor",
"comment": "add \"shouldRun()\" config to the target config",
"packageName": "@lage-run/target-graph",
"email": "kchau@microsoft.com",
"dependentChangeType": "patch"
}
]
}

Просмотреть файл

@ -90,7 +90,7 @@ export async function infoAction(options: InfoActionOptions, command: Command) {
const { tasks, taskArgs } = filterArgsForTasks(command.args);
const targetGraph = createTargetGraph({
const targetGraph = await createTargetGraph({
logger,
root,
dependencies: options.dependencies,

Просмотреть файл

@ -19,7 +19,7 @@ interface CreateTargetGraphOptions {
packageInfos: PackageInfos;
}
export function createTargetGraph(options: CreateTargetGraphOptions) {
export async function createTargetGraph(options: CreateTargetGraphOptions) {
const { logger, root, dependencies, dependents, since, scope, repoWideChanges, ignore, pipeline, outputs, tasks, packageInfos } = options;
const builder = new WorkspaceTargetGraphBuilder(root, packageInfos);
@ -49,5 +49,5 @@ export function createTargetGraph(options: CreateTargetGraphOptions) {
}
}
return builder.build(tasks, packages);
return await builder.build(tasks, packages);
}

Просмотреть файл

@ -49,7 +49,7 @@ export async function runAction(options: RunOptions, command: Command) {
const { tasks, taskArgs } = filterArgsForTasks(command.args);
const targetGraph = createTargetGraph({
const targetGraph = await createTargetGraph({
logger,
root,
dependencies: options.dependencies,

Просмотреть файл

@ -48,7 +48,7 @@ export async function watchAction(options: RunOptions, command: Command) {
const { tasks, taskArgs } = filterArgsForTasks(command.args);
const targetGraph = createTargetGraph({
const targetGraph = await createTargetGraph({
logger,
root,
dependencies: options.dependencies,

Просмотреть файл

@ -71,7 +71,7 @@ async function initialize({ cwd, logger, serverControls, nodeArg, taskArgs, maxW
const packageInfos = getPackageInfos(root);
const tasks = findAllTasks(pipeline);
const targetGraph = createTargetGraph({
const targetGraph = await createTargetGraph({
logger,
root,
dependencies: false,

Просмотреть файл

@ -48,7 +48,9 @@ export class NpmScriptRunner implements TargetRunner {
async shouldRun(target: Target) {
// By convention, do not run anything if there is no script for this task defined in package.json (counts as "success")
return await this.hasNpmScript(target);
const hasNpmScript = await this.hasNpmScript(target);
return hasNpmScript && (target.shouldRun ?? true);
}
async run(runOptions: TargetRunnerOptions) {

Просмотреть файл

@ -50,10 +50,10 @@ export class WorkerRunner implements TargetRunner {
const scriptModule = await this.getScriptModule(target);
if (typeof scriptModule.shouldRun === "function") {
return await scriptModule.shouldRun(target);
return (await scriptModule.shouldRun(target)) && (target.shouldRun ?? true);
}
return true;
return target.shouldRun ?? true;
}
async run(runOptions: TargetRunnerOptions) {

Просмотреть файл

@ -17,6 +17,7 @@
"lint": "monorepo-scripts lint"
},
"dependencies": {
"p-limit": "^3.1.0",
"workspace-tools": "0.37.0"
},
"devDependencies": {

Просмотреть файл

@ -67,6 +67,7 @@ export class TargetFactory {
environmentGlob,
weight: 1,
options,
shouldRun: true,
};
target.weight = getWeight(target, weight, maxWorkers);
@ -95,6 +96,7 @@ export class TargetFactory {
environmentGlob,
weight: 1,
options,
shouldRun: true,
};
target.weight = getWeight(target, weight, maxWorkers);

Просмотреть файл

@ -6,9 +6,11 @@ import path from "path";
import type { DependencyMap } from "workspace-tools/lib/graph/createDependencyMap.js";
import type { PackageInfos } from "workspace-tools";
import type { Target } from "./types/Target.js";
import type { TargetConfig } from "./types/TargetConfig.js";
import { TargetGraphBuilder } from "./TargetGraphBuilder.js";
import { TargetFactory } from "./TargetFactory.js";
import pLimit from "p-limit";
/**
* TargetGraphBuilder class provides a builder API for registering target configs. It exposes a method called `generateTargetGraph` to
@ -33,6 +35,8 @@ export class WorkspaceTargetGraphBuilder {
private hasRootTarget = false;
private targetConfigMap = new Map<string, TargetConfig>();
/**
* Initializes the builder with package infos
* @param root the root directory of the workspace
@ -60,26 +64,37 @@ export class WorkspaceTargetGraphBuilder {
* @param id
* @param targetDefinition
*/
addTargetConfig(id: string, config: TargetConfig = {}): void {
async addTargetConfig(id: string, config: TargetConfig = {}) {
// Generates a target definition from the target config
if (id.startsWith("//") || id.startsWith("#")) {
const target = this.targetFactory.createGlobalTarget(id, config);
this.graphBuilder.addTarget(target);
this.targetConfigMap.set(id, config);
this.hasRootTarget = true;
} else if (id.includes("#")) {
const { packageName, task } = getPackageAndTask(id);
const target = this.targetFactory.createPackageTarget(packageName!, task, config);
this.graphBuilder.addTarget(target);
this.targetConfigMap.set(id, config);
} else {
const packages = Object.keys(this.packageInfos);
for (const packageName of packages) {
const task = id;
const target = this.targetFactory.createPackageTarget(packageName!, task, config);
this.graphBuilder.addTarget(target);
this.targetConfigMap.set(id, config);
}
}
}
shouldRun(config: TargetConfig, target: Target) {
if (typeof config.shouldRun === "function") {
return config.shouldRun(target);
}
return true;
}
/**
* Builds a scoped target graph for given tasks and packages
*
@ -93,7 +108,7 @@ export class WorkspaceTargetGraphBuilder {
* @param scope
* @returns
*/
build(tasks: string[], scope?: string[]) {
async build(tasks: string[], scope?: string[]) {
// Expands the dependency specs from the target definitions
const fullDependencies = expandDepSpecs(this.graphBuilder.targets, this.dependencyMap);
@ -124,6 +139,21 @@ export class WorkspaceTargetGraphBuilder {
const subGraph = this.graphBuilder.subgraph(subGraphEntries);
const limit = pLimit(8);
const setShouldRunPromises: Promise<void>[] = [];
for (const target of subGraph.targets.values()) {
const config = this.targetConfigMap.get(target.id);
if (config) {
setShouldRunPromises.push(
limit(async () => {
target.shouldRun = await this.shouldRun(config, target);
})
);
}
}
await Promise.all(setShouldRunPromises);
return {
targets: subGraph.targets,
};

Просмотреть файл

@ -92,4 +92,9 @@ export interface Target {
* Whether the target should be displayed by reporters
*/
hidden?: boolean;
/**
* Whether the target should be run
*/
shouldRun?: boolean;
}

Просмотреть файл

@ -74,4 +74,6 @@ export interface TargetConfig {
* Run options for the Target Runner. (e.g. `{ env: ...process.env, colors: true, ... }`)
*/
options?: Record<string, any>;
shouldRun?: (target: Target) => boolean | Promise<boolean>;
}

Просмотреть файл

@ -1,6 +1,6 @@
import type { PackageInfos } from "workspace-tools";
import { WorkspaceTargetGraphBuilder } from "../src/WorkspaceTargetGraphBuilder";
import type { TargetGraph } from "../src/types/TargetGraph";
import { WorkspaceTargetGraphBuilder } from "../src/WorkspaceTargetGraphBuilder.js";
import type { TargetGraph } from "../src/types/TargetGraph.js";
function createPackageInfo(packages: { [id: string]: string[] }) {
const packageInfos: PackageInfos = {};
@ -30,7 +30,7 @@ function getGraphFromTargets(targetGraph: TargetGraph) {
}
describe("workspace target graph builder", () => {
it("should build a target based on a simple package graph and task graph", () => {
it("should build a target based on a simple package graph and task graph", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -43,7 +43,7 @@ describe("workspace target graph builder", () => {
dependsOn: ["^build"],
});
const targetGraph = builder.build(["build"]);
const targetGraph = await builder.build(["build"]);
// size is 3, because we also need to account for the root target node (start target ID)
expect(targetGraph.targets.size).toBe(3);
@ -66,7 +66,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should generate target graphs for tasks that do not depend on each other", () => {
it("should generate target graphs for tasks that do not depend on each other", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
a: ["b"],
@ -77,7 +77,7 @@ describe("workspace target graph builder", () => {
builder.addTargetConfig("test");
builder.addTargetConfig("lint");
const targetGraph = builder.build(["test", "lint"]);
const targetGraph = await builder.build(["test", "lint"]);
// includes the pseudo-target for the "start" target
expect(targetGraph.targets.size).toBe(5);
@ -103,7 +103,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should generate targetGraph with some specific package task target dependencies, running against all packages", () => {
it("should generate targetGraph with some specific package task target dependencies, running against all packages", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -122,7 +122,7 @@ describe("workspace target graph builder", () => {
dependsOn: [],
});
const targetGraph = builder.build(["build"]);
const targetGraph = await builder.build(["build"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
[
@ -145,7 +145,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should generate targetGraph with some specific package task target dependencies, running against a specific package", () => {
it("should generate targetGraph with some specific package task target dependencies, running against a specific package", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -164,7 +164,7 @@ describe("workspace target graph builder", () => {
dependsOn: [],
});
const targetGraph = builder.build(["build"], ["a", "b"]);
const targetGraph = await builder.build(["build"], ["a", "b"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
[
@ -179,7 +179,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should generate targetGraph with transitive dependencies", () => {
it("should generate targetGraph with transitive dependencies", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -196,7 +196,7 @@ describe("workspace target graph builder", () => {
builder.addTargetConfig("transpile");
const targetGraph = builder.build(["bundle"], ["a"]);
const targetGraph = await builder.build(["bundle"], ["a"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
[
@ -223,7 +223,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should generate target graph for a general task on a specific target", () => {
it("should generate target graph for a general task on a specific target", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -242,7 +242,7 @@ describe("workspace target graph builder", () => {
builder.addTargetConfig("common#copy");
builder.addTargetConfig("common#build");
const targetGraph = builder.build(["build"]);
const targetGraph = await builder.build(["build"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
[
@ -281,7 +281,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should build a target graph with global task as a dependency", () => {
it("should build a target graph with global task as a dependency", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -298,7 +298,7 @@ describe("workspace target graph builder", () => {
dependsOn: [],
});
const targetGraph = builder.build(["build"]);
const targetGraph = await builder.build(["build"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
@ -330,7 +330,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should build a target graph with global task on its own", () => {
it("should build a target graph with global task on its own", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -347,7 +347,7 @@ describe("workspace target graph builder", () => {
dependsOn: [],
});
const targetGraph = builder.build(["global:task"]);
const targetGraph = await builder.build(["global:task"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[
@ -359,7 +359,7 @@ describe("workspace target graph builder", () => {
`);
});
it("should build a target graph without including global task", () => {
it("should build a target graph without including global task", async () => {
const root = "/repos/a";
const packageInfos = createPackageInfo({
@ -376,7 +376,7 @@ describe("workspace target graph builder", () => {
dependsOn: [],
});
const targetGraph = builder.build(["build"]);
const targetGraph = await builder.build(["build"]);
expect(getGraphFromTargets(targetGraph)).toMatchInlineSnapshot(`
[

Просмотреть файл

@ -4,8 +4,8 @@
"private": true,
"bin": "bin/monorepo-scripts.js",
"dependencies": {
"@swc/core": "^1.3.14",
"@swc/jest": "^0.2.36",
"@swc/core": "^1.9.1",
"@swc/jest": "^0.2.37",
"@typescript-eslint/eslint-plugin": "^5.30.7",
"@typescript-eslint/parser": "^5.30.7",
"depcheck": "^1.4.7",

Просмотреть файл

@ -28,13 +28,23 @@ module.exports = async function transpile(data) {
if (entry.isDirectory() && entry.name !== "node_modules" && entry.name !== "lib" && entry.name !== "tests" && entry.name !== "dist") {
queue.push(fullPath);
} else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))) {
const swcOutput = await swc.transformFile(fullPath, swcOptions);
const dest = fullPath
.replace(/([/\\])src/, "$1lib")
.replace(".tsx", ".js")
.replace(".ts", ".js");
const swcOutput = await swc.transformFile(fullPath, {
...swcOptions,
sourceFileName: path.relative(path.dirname(dest), fullPath).replace(/\\/g, "/"),
});
const destMap = dest + ".map";
await fsPromises.mkdir(path.dirname(dest), { recursive: true });
await fsPromises.writeFile(dest, swcOutput.code);
if (swcOutput.map) {
await fsPromises.writeFile(destMap, swcOutput.map);
}
}
}
}

114
yarn.lock
Просмотреть файл

@ -1836,8 +1836,8 @@ __metadata:
version: 0.0.0-use.local
resolution: "@lage-run/monorepo-scripts@workspace:scripts"
dependencies:
"@swc/core": "npm:^1.3.14"
"@swc/jest": "npm:^0.2.36"
"@swc/core": "npm:^1.9.1"
"@swc/jest": "npm:^0.2.37"
"@typescript-eslint/eslint-plugin": "npm:^5.30.7"
"@typescript-eslint/parser": "npm:^5.30.7"
depcheck: "npm:^1.4.7"
@ -1922,6 +1922,7 @@ __metadata:
dependencies:
"@lage-run/monorepo-scripts": "npm:*"
jest-diff: "npm:^29.5.0"
p-limit: "npm:^3.1.0"
workspace-tools: "npm:0.37.0"
languageName: unknown
linkType: soft
@ -2037,92 +2038,94 @@ __metadata:
languageName: node
linkType: hard
"@swc/core-darwin-arm64@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-darwin-arm64@npm:1.3.56"
"@swc/core-darwin-arm64@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-darwin-arm64@npm:1.9.1"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@swc/core-darwin-x64@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-darwin-x64@npm:1.3.56"
"@swc/core-darwin-x64@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-darwin-x64@npm:1.9.1"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@swc/core-linux-arm-gnueabihf@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.3.56"
"@swc/core-linux-arm-gnueabihf@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.9.1"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@swc/core-linux-arm64-gnu@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-linux-arm64-gnu@npm:1.3.56"
"@swc/core-linux-arm64-gnu@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-linux-arm64-gnu@npm:1.9.1"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-arm64-musl@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-linux-arm64-musl@npm:1.3.56"
"@swc/core-linux-arm64-musl@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-linux-arm64-musl@npm:1.9.1"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@swc/core-linux-x64-gnu@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-linux-x64-gnu@npm:1.3.56"
"@swc/core-linux-x64-gnu@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-linux-x64-gnu@npm:1.9.1"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-x64-musl@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-linux-x64-musl@npm:1.3.56"
"@swc/core-linux-x64-musl@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-linux-x64-musl@npm:1.9.1"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@swc/core-win32-arm64-msvc@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-win32-arm64-msvc@npm:1.3.56"
"@swc/core-win32-arm64-msvc@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-win32-arm64-msvc@npm:1.9.1"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@swc/core-win32-ia32-msvc@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-win32-ia32-msvc@npm:1.3.56"
"@swc/core-win32-ia32-msvc@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-win32-ia32-msvc@npm:1.9.1"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@swc/core-win32-x64-msvc@npm:1.3.56":
version: 1.3.56
resolution: "@swc/core-win32-x64-msvc@npm:1.3.56"
"@swc/core-win32-x64-msvc@npm:1.9.1":
version: 1.9.1
resolution: "@swc/core-win32-x64-msvc@npm:1.9.1"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@swc/core@npm:^1.3.14":
version: 1.3.56
resolution: "@swc/core@npm:1.3.56"
"@swc/core@npm:^1.9.1":
version: 1.9.1
resolution: "@swc/core@npm:1.9.1"
dependencies:
"@swc/core-darwin-arm64": "npm:1.3.56"
"@swc/core-darwin-x64": "npm:1.3.56"
"@swc/core-linux-arm-gnueabihf": "npm:1.3.56"
"@swc/core-linux-arm64-gnu": "npm:1.3.56"
"@swc/core-linux-arm64-musl": "npm:1.3.56"
"@swc/core-linux-x64-gnu": "npm:1.3.56"
"@swc/core-linux-x64-musl": "npm:1.3.56"
"@swc/core-win32-arm64-msvc": "npm:1.3.56"
"@swc/core-win32-ia32-msvc": "npm:1.3.56"
"@swc/core-win32-x64-msvc": "npm:1.3.56"
"@swc/core-darwin-arm64": "npm:1.9.1"
"@swc/core-darwin-x64": "npm:1.9.1"
"@swc/core-linux-arm-gnueabihf": "npm:1.9.1"
"@swc/core-linux-arm64-gnu": "npm:1.9.1"
"@swc/core-linux-arm64-musl": "npm:1.9.1"
"@swc/core-linux-x64-gnu": "npm:1.9.1"
"@swc/core-linux-x64-musl": "npm:1.9.1"
"@swc/core-win32-arm64-msvc": "npm:1.9.1"
"@swc/core-win32-ia32-msvc": "npm:1.9.1"
"@swc/core-win32-x64-msvc": "npm:1.9.1"
"@swc/counter": "npm:^0.1.3"
"@swc/types": "npm:^0.1.14"
peerDependencies:
"@swc/helpers": ^0.5.0
"@swc/helpers": "*"
dependenciesMeta:
"@swc/core-darwin-arm64":
optional: true
@ -2147,7 +2150,7 @@ __metadata:
peerDependenciesMeta:
"@swc/helpers":
optional: true
checksum: 10c0/c468e281f0249742bc0ba4b7cd4076cdbf87bfc82b8bd5ad1ca8940d36372ca22754df80ab54b22613121680718eab26b92c48c8c9f5f3abb24434f05e5e1ea0
checksum: 10c0/7b9a3da9bdd95216b031739ebe35983e69f17284809a62706c93edfd30ede0732060d944db23007aca9aebbc49859eb5784454c8882ae6fd04eb8bd15ac6a247
languageName: node
linkType: hard
@ -2158,16 +2161,25 @@ __metadata:
languageName: node
linkType: hard
"@swc/jest@npm:^0.2.36":
version: 0.2.36
resolution: "@swc/jest@npm:0.2.36"
"@swc/jest@npm:^0.2.37":
version: 0.2.37
resolution: "@swc/jest@npm:0.2.37"
dependencies:
"@jest/create-cache-key-function": "npm:^29.7.0"
"@swc/counter": "npm:^0.1.3"
jsonc-parser: "npm:^3.2.0"
peerDependencies:
"@swc/core": "*"
checksum: 10c0/7f1993f9201420bb499c92ab28797352bcbf9e3a6c7b5a1806fdc34c9c3b46ea9e5b2f070c0e13fcf7f3c3fadbbc38777840baabb178f589bf1f67543763adb6
checksum: 10c0/abe10d87610bf7c172aa7ab14c64599a22e48c1f43a09d6e22733f85f25fb98e57cb4bb58b9554e60a3ac8629be559bd967d7a8601a3ceaacad618aecccebec2
languageName: node
linkType: hard
"@swc/types@npm:^0.1.14":
version: 0.1.14
resolution: "@swc/types@npm:0.1.14"
dependencies:
"@swc/counter": "npm:^0.1.3"
checksum: 10c0/5ab5a213f25fbb038e8b2fa001a20c64363f81c199319373ed0228f316c046a996758fbaf906ba84d297b35e37727082d27974266db320e534da594716626529
languageName: node
linkType: hard