Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: microsoft/lage
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0f5a0dc74f6515366af3b53113f893b9c5ca98e0
Choose a base ref
...
head repository: microsoft/lage
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 0c4208fff4f1d0f2c6345180254f2f4b7c283538
Choose a head ref
  • 3 commits
  • 12 files changed
  • 2 contributors

Commits on Feb 9, 2025

  1. Simulated transitive inputs (#849)

    * simulate transitives by doing our own hashing
    
    * Change files
    
    * revert executeRemotely.ts
    
    * fixing test
    
    * if we cannot clean the fixture, ignore the problem
    
    * skipping detached killing on windows in e2e
    
    * give it more time
    kenotron authored Feb 9, 2025
    Copy the full SHA
    fa307f4 View commit details
  2. newline

    kenotron committed Feb 9, 2025
    Copy the full SHA
    6a0360c View commit details
  3. fix publish

    kenotron committed Feb 9, 2025
    Copy the full SHA
    0c4208f View commit details
18 changes: 18 additions & 0 deletions change/change-e7aa3a3d-8172-4004-a3f4-de255b8a143c.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"changes": [
{
"type": "patch",
"comment": "simulate transitives by doing our own hashing",
"packageName": "@lage-run/cli",
"email": "kchau@microsoft.com",
"dependentChangeType": "patch"
},
{
"type": "patch",
"comment": "simulate transitives by doing our own hashing",
"packageName": "@lage-run/rpc",
"email": "kchau@microsoft.com",
"dependentChangeType": "patch"
}
]
}
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@lage-run/cli",
"version": "0.25.2",
"version": "0.25.3",
"description": "Command Line Interface for Lage",
"repository": {
"type": "git",
@@ -28,7 +28,7 @@
"@lage-run/hasher": "^1.6.9",
"@lage-run/logger": "^1.3.1",
"@lage-run/reporters": "^1.2.19",
"@lage-run/rpc": "^1.2.3",
"@lage-run/rpc": "^1.2.4",
"@lage-run/runners": "^1.2.1",
"@lage-run/scheduler": "^1.5.1",
"@lage-run/scheduler-types": "^0.3.23",
16 changes: 12 additions & 4 deletions packages/cli/src/commands/exec/simulateFileAccess.ts
Original file line number Diff line number Diff line change
@@ -12,15 +12,23 @@ export async function simulateFileAccess(logger: Logger, inputs: string[], outpu
// probe input files
let fd: number;
for (const input of inputs) {
fd = fs.openSync(path.join(root, input), "r");
fs.closeSync(fd);
try {
fd = fs.openSync(path.join(root, input), "r");
fs.closeSync(fd);
} catch (e) {
// ignore
}

inputDirectories.add(path.dirname(input));
}

for (const directory of inputDirectories) {
fd = fs.openSync(path.join(root, directory), "r");
fs.closeSync(fd);
try {
fd = fs.openSync(path.join(root, directory), "r");
fs.closeSync(fd);
} catch (e) {
// ignore
}
}

// touch output files
2 changes: 1 addition & 1 deletion packages/cli/src/commands/server/action.ts
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ export async function serverAction(options: WorkerOptions) {
cwd: process.cwd(),
serverControls: {
abortController,
countdownToShutdown: () => resetTimer(logger, timeout, abortController, server),
countdownToShutdown: () => resetTimer(logger, timeout, abortController, lageServer),
clearCountdown: clearTimer,
},
logger,
40 changes: 0 additions & 40 deletions packages/cli/src/commands/server/getTransitiveTargetInputs.ts

This file was deleted.

69 changes: 55 additions & 14 deletions packages/cli/src/commands/server/lageService.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
import { type ConfigOptions, getConfig, getConcurrency, getMaxWorkersPerTask } from "@lage-run/config";
import type { Logger } from "@lage-run/logger";
import type { ILageService } from "@lage-run/rpc";
import { ConnectError, Code, type ILageService } from "@lage-run/rpc";
import { getStartTargetId, getTargetId, type Target, type TargetGraph } from "@lage-run/target-graph";
import { type DependencyMap, getPackageInfos, getWorkspaceRoot } from "workspace-tools";
import { createTargetGraph } from "../run/createTargetGraph.js";
import { type Readable } from "stream";
import { type Pool, AggregatedPool } from "@lage-run/worker-threads-pool";
import { getInputFiles, PackageTree } from "@lage-run/hasher";
import { createDependencyMap } from "workspace-tools";
import { getInputFiles, type PackageTree, TargetHasher } from "@lage-run/hasher";
import { getOutputFiles } from "./getOutputFiles.js";
import { glob } from "@lage-run/globby";
import { MemoryStream } from "./MemoryStream.js";
import { runnerPickerOptions } from "../../runnerPickerOptions.js";
import { filterPipelineDefinitions } from "../run/filterPipelineDefinitions.js";
import type { TargetRun } from "@lage-run/scheduler-types";
import { formatDuration, hrToSeconds, hrtimeDiff } from "@lage-run/format-hrtime";
import { getTransitiveTargetInputs } from "./getTransitiveTargetInputs.js";
import path from "path";
import fs from "fs";

interface LageServiceContext {
config: ConfigOptions;
@@ -25,6 +25,7 @@ interface LageServiceContext {
root: string;
pool: Pool;
globalInputs: string[];
targetHasher: TargetHasher;
}

let initializedPromise: Promise<LageServiceContext> | undefined;
@@ -62,6 +63,7 @@ async function createInitializedPromise({ cwd, logger, serverControls, nodeArg,

const packageInfos = getPackageInfos(root);

logger.info("Initializing target graph");
const targetGraph = await createTargetGraph({
logger,
root,
@@ -78,15 +80,21 @@ async function createInitializedPromise({ cwd, logger, serverControls, nodeArg,
priorities: config.priorities,
});

const dependencyMap = createDependencyMap(packageInfos, { withDevDependencies: true, withPeerDependencies: false });
const packageTree = new PackageTree({
const targetHasher = new TargetHasher({
root,
packageInfos,
includeUntracked: true,
environmentGlob: config.cacheOptions?.environmentGlob ?? [],
logger,
cacheKey: config.cacheOptions?.cacheKey,
cliArgs: taskArgs,
});

logger.info("Initializing Package Tree");
await packageTree.initialize();
logger.info("Initializing hasher");
await targetHasher.initialize();

logger.info("Initializing dependency map");

const packageTree = targetHasher.packageTree!;
const dependencyMap = targetHasher.dependencyMap;

const filteredPipeline = filterPipelineDefinitions(targetGraph.targets.values(), config.pipeline);

@@ -132,7 +140,7 @@ async function createInitializedPromise({ cwd, logger, serverControls, nodeArg,
logger.info(`Environment glob inputs: \n${JSON.stringify(globalInputs)}\n-------`);

logger.info("done initializing");
return { config, targetGraph, packageTree, dependencyMap, root, pool, globalInputs };
return { config, targetGraph, packageTree, dependencyMap, root, pool, globalInputs, targetHasher };
}

/**
@@ -154,6 +162,10 @@ interface CreateLageServiceOptions {
tasks: string[];
}

function getHashFilePath(target: Target) {
return path.join(`node_modules/.lage/hash_${target.task}`);
}

export async function createLageService({
cwd,
serverControls,
@@ -176,7 +188,7 @@ export async function createLageService({
// THIS IS A BIG ASSUMPTION; TODO: memoize based on the parameters of the initialize() call
// The first request sets up the nodeArg and taskArgs - we are assuming that all requests to run this target are coming from the same
// `lage info` call
const { config, targetGraph, dependencyMap, packageTree, root, pool, globalInputs } = await initialize({
const { config, targetGraph, dependencyMap, packageTree, root, pool, globalInputs, targetHasher } = await initialize({
cwd,
logger,
nodeArg: request.nodeOptions,
@@ -199,6 +211,8 @@ export async function createLageService({
};
}

logger.info(`Running target: ${request.packageName}#${request.task}`);

const target = targetGraph.targets.get(id)!;
const task = {
target,
@@ -221,8 +235,6 @@ export async function createLageService({

const targetGlobalInputs = target.environmentGlob ? glob(target.environmentGlob, { cwd: root, gitignore: true }) : globalInputs;

const inputs = getTransitiveTargetInputs(target, targetGraph, dependencyMap, packageTree);

let results: {
packageName?: string;
task: string;
@@ -235,6 +247,30 @@ export async function createLageService({
globalInputs: string[];
};

const inputs = getInputFiles(target, dependencyMap, packageTree);

for (const dep of target.dependencies) {
if (dep === getStartTargetId()) {
continue;
}

const depTarget = targetGraph.targets.get(dep)!;
inputs.push(path.join(path.relative(root, depTarget.cwd), getHashFilePath(depTarget)).replace(/\\/g, "/"));
}

const targetHashFile = getHashFilePath(target);
const targetHashFullPath = path.join(target.cwd, targetHashFile);

try {
if (!fs.existsSync(path.dirname(targetHashFullPath))) {
fs.mkdirSync(path.dirname(targetHashFullPath), { recursive: true });
}

fs.writeFileSync(targetHashFullPath, await targetHasher.hash(target));
} catch (e) {
throw new ConnectError(`Error writing target hash file: ${targetHashFullPath}`, Code.Internal);
}

try {
await pool.exec(
task,
@@ -275,6 +311,7 @@ export async function createLageService({
);

const outputs = getOutputFiles(root, target, config.cacheOptions?.outputGlob, packageTree);
outputs.push(targetHashFile);

results = {
packageName: request.packageName,
@@ -289,6 +326,10 @@ export async function createLageService({
};
} catch (e) {
const outputs = getOutputFiles(root, target, config.cacheOptions?.outputGlob, packageTree);
outputs.push(targetHashFile);

targetRun.status = "failed";
targetRun.duration = hrtimeDiff(targetRun.startTime, process.hrtime());

results = {
packageName: request.packageName,
2 changes: 1 addition & 1 deletion packages/e2e-tests/package.json
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@
"lint": "monorepo-scripts lint"
},
"dependencies": {
"@lage-run/cli": "^0.25.2",
"@lage-run/cli": "^0.25.3",
"@lage-run/globby": "^14.2.0",
"@lage-run/monorepo-scripts": "*",
"@lage-run/scheduler-types": "^0.3.23",
Loading