Skip to content
Open
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
11 changes: 11 additions & 0 deletions change/change-e975674f-161c-4841-9fec-9751de3638dd.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"type": "minor",
"comment": "Support referencing files in a specific package or at the workspace level in inputs",
"packageName": "@lage-run/hasher",
"email": "dobes@formative.com",
"dependentChangeType": "patch"
}
]
}
6 changes: 5 additions & 1 deletion packages/hasher/src/PackageTree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ export class PackageTree {

getPackageFiles(packageName: string, patterns: string[]) {
const { root, packageInfos } = this.options;
const packagePath = path.relative(root, path.dirname(packageInfos[packageName].packageJsonPath)).replace(/\\/g, "/");
// Look up the directory of the specified package. If packageName is "", that means they want to find a file
// relative to the root workspace.
const packagePath = packageName
? path.relative(root, path.dirname(packageInfos[packageName].packageJsonPath)).replace(/\\/g, "/")
: "";

const packageFiles = this.#packageFiles[packagePath];

Expand Down
46 changes: 46 additions & 0 deletions packages/hasher/src/__tests__/TargetHasher.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,52 @@ describe("The main Hasher class", () => {
monorepo2.cleanup();
});

it("creates different hashes when a src file has changed for a specific package", async () => {
const monorepo1 = await setupFixture("monorepo");
const hasher = new TargetHasher({ root: monorepo1.root, environmentGlob: [] });
const target = createTarget(monorepo1.root, "package-a", "build");
target.inputs = ["**/*", "package-b#src/index.ts"];

const hash = await getHash(hasher, target);

const monorepo2 = await setupFixture("monorepo");
await monorepo2.commitFiles({ "packages/package-b/src/index.ts": "console.log('hello world');" });

const hasher2 = new TargetHasher({ root: monorepo2.root, environmentGlob: [] });
const target2 = createTarget(monorepo2.root, "package-a", "build");
target2.inputs = ["**/*", "package-b#src/index.ts"];

const hash2 = await getHash(hasher2, target2);

expect(hash).not.toEqual(hash2);

monorepo1.cleanup();
monorepo2.cleanup();
});

it("creates different hashes when a src file has changed in the root package", async () => {
const monorepo1 = await setupFixture("monorepo");
const hasher = new TargetHasher({ root: monorepo1.root, environmentGlob: [] });
const target = createTarget(monorepo1.root, "package-a", "build");
target.inputs = ["**/*", "#config.txt"];

const hash = await getHash(hasher, target);

const monorepo2 = await setupFixture("monorepo");
await monorepo2.commitFiles({ "config.txt": "hello" });

const hasher2 = new TargetHasher({ root: monorepo2.root, environmentGlob: [] });
const target2 = createTarget(monorepo2.root, "package-a", "build");
target2.inputs = ["**/*", "#config.txt"];

const hash2 = await getHash(hasher2, target2);

expect(hash).not.toEqual(hash2);

monorepo1.cleanup();
monorepo2.cleanup();
});

it("creates different hashes when the target has a different env glob", async () => {
const monorepo1 = await setupFixture("monorepo-with-global-files");
const hasher = new TargetHasher({ root: monorepo1.root, environmentGlob: [] });
Expand Down
9 changes: 8 additions & 1 deletion packages/hasher/src/expandInputPatterns.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { type Target } from "@lage-run/target-graph";
import { type DependencyMap } from "workspace-tools";

export function expandInputPatterns(patterns: string[], target: Target, dependencyMap: DependencyMap) {
export function expandInputPatterns(patterns: string[], target: Target, dependencyMap: DependencyMap): Record<string, string[]> {
const expandedPatterns: Record<string, string[]> = {};

for (const pattern of patterns) {
Expand Down Expand Up @@ -34,6 +34,13 @@ export function expandInputPatterns(patterns: string[], target: Target, dependen
}
}
}
} else if (pattern.includes("#")) {
// In this case they specified a specific package which an input file will be pulled from
// Note that if the path starts with '#' the pkg is caluclated as "" and the file is resolved
// relative to the root workspace
const [pkg, matchPattern] = pattern.split("#");
expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
expandedPatterns[pkg].push(matchPattern);
} else {
const pkg = target.packageName!;
expandedPatterns[pkg] = expandedPatterns[pkg] ?? [];
Expand Down