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

fix(turbo-ignore): infer correct version of turbo for project #8363

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
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "test-app",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "vercel"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
// No pipeline or tasks
}
11 changes: 11 additions & 0 deletions packages/turbo-ignore/__fixtures__/no_turbo_deps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "test-app",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "vercel"
}
6 changes: 6 additions & 0 deletions packages/turbo-ignore/__fixtures__/no_turbo_deps/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
// A comment!
"tasks": {
"build": {}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"name": "test-app",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "vercel"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"pipeline": {
"build": {}
}
}
14 changes: 14 additions & 0 deletions packages/turbo-ignore/__fixtures__/turbo_in_deps/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"name": "test-app",
"private": true,
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "vercel",
"dependencies": {
"turbo": "^99"
}
}
5 changes: 5 additions & 0 deletions packages/turbo-ignore/__fixtures__/turbo_in_deps/turbo.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"tasks": {
"build": {}
}
}
69 changes: 69 additions & 0 deletions packages/turbo-ignore/__tests__/getTurboVersion.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { spyConsole, validateLogs } from "@turbo/test-utils";
import { getTurboVersion } from "../src/getTurboVersion";

describe("getWorkspace()", () => {
const mockConsole = spyConsole();
it("getTurboVersion returns turboVersion from arg", () => {
expect(
getTurboVersion(
{
turboVersion: "1.2.3",
},
"./__fixtures__/app"
)
).toEqual("1.2.3");
validateLogs(
['Using turbo version "1.2.3" from arguments'],
mockConsole.log,
{ prefix: "≫ " }
);
});

it("getTurboVersion returns version from package.json", () => {
expect(getTurboVersion({}, "./__fixtures__/turbo_in_deps")).toEqual("^99");
expect(mockConsole.log).toHaveBeenCalledWith(
"≫ ",
'Inferred turbo version "^99" from "package.json"'
);
});

it("getTurboVersion infers ^2 if tasks in turbo.json", () => {
expect(getTurboVersion({}, "./__fixtures__/no_turbo_deps")).toEqual("^2");
expect(mockConsole.log).toHaveBeenCalledWith(
"≫ ",
'Inferred turbo version ^2 based on "tasks" in "turbo.json"'
);
});

it("getTurboVersion infers ^1 if pipeline in turbo.json", () => {
expect(getTurboVersion({}, "./__fixtures__/no_turbo_deps_v1")).toEqual(
"^1"
);
expect(mockConsole.log).toHaveBeenCalledWith(
"≫ ",
'Inferred turbo version ^1 based on "pipeline" in "turbo.json"'
);
});

it("getTurboVersion return null if no turbo.json", () => {
expect(getTurboVersion({}, "./__fixtures__/app")).toEqual(null);
expect(mockConsole.error).toHaveBeenCalledWith(
"≫ ",
'"__fixtures__/app/turbo.json" could not be read. turbo-ignore turbo version inference failed'
);
});

it("getTurboVersion return null if no package.json", () => {
expect(getTurboVersion({}, "./__fixtures__/no-app")).toEqual(null);
expect(mockConsole.error).toHaveBeenCalledWith(
"≫ ",
'"__fixtures__/no-app/package.json" could not be read. turbo-ignore turbo version inference failed'
);
});

it("getTurboVersion return null if invalid JSON", () => {
expect(getTurboVersion({}, "./__fixtures__/invalid_turbo_json")).toEqual(
null
);
});
});
67 changes: 50 additions & 17 deletions packages/turbo-ignore/__tests__/ignore.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ describe("turboIgnore()", () => {
turboIgnore("test-workspace", { telemetry });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-workspace...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);
Expand Down Expand Up @@ -92,7 +92,7 @@ describe("turboIgnore()", () => {
turboIgnore("test-workspace", {});

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-workspace...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);
Expand Down Expand Up @@ -137,7 +137,7 @@ describe("turboIgnore()", () => {
turboIgnore("test-workspace", { telemetry });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-workspace...[too-far-back]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-workspace...[too-far-back]" --dry=json`,
expect.anything(),
expect.anything()
);
Expand Down Expand Up @@ -175,7 +175,7 @@ describe("turboIgnore()", () => {
turboIgnore("test-workspace", { fallback: "HEAD^" });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-workspace...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-workspace...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);
Expand Down Expand Up @@ -250,7 +250,7 @@ describe("turboIgnore()", () => {
process.env.VERCEL_GIT_COMMIT_REF = "my-branch";
turboIgnore("test-app", { directory: "__fixtures__/app" });
expect(mockConsole.log).toHaveBeenNthCalledWith(
4,
5,
"≫ ",
'No previous deployments found for "test-app" on branch "my-branch"'
);
Expand Down Expand Up @@ -283,9 +283,10 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
`Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"`,
'Analyzing results of `npx turbo run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`',
"This project and its dependencies are not affected",
() => expect.stringContaining("⏭ Ignoring the change"),
],
Expand Down Expand Up @@ -327,9 +328,10 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "workspace#build" as the task from the arguments',
'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"',
'Analyzing results of `npx turbo run "workspace#build" --filter="test-app...[last-deployed-sha]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run "workspace#build" --filter="test-app...[last-deployed-sha]" --dry=json`',
'This commit affects "test-app"',
() => expect.stringContaining("✓ Proceeding with deployment"),
],
Expand Down Expand Up @@ -368,9 +370,10 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"',
'Analyzing results of `npx turbo run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'This commit affects "test-app" and 1 dependency (ui)',
() => expect.stringContaining("✓ Proceeding with deployment"),
],
Expand Down Expand Up @@ -409,9 +412,10 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
'Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"',
'Analyzing results of `npx turbo run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'This commit affects "test-app" and 2 dependencies (ui, tsconfig)',
() => expect.stringContaining("✓ Proceeding with deployment"),
],
Expand Down Expand Up @@ -459,10 +463,11 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "workspace#build" as the task from the arguments',
'Previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch" is unreachable.',
"Falling back to ref HEAD^2",
'Analyzing results of `npx turbo run "workspace#build" --filter="test-app...[HEAD^2]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run "workspace#build" --filter="test-app...[HEAD^2]" --dry=json`',
'This commit affects "test-app"',
() => expect.stringContaining("✓ Proceeding with deployment"),
],
Expand All @@ -488,13 +493,13 @@ describe("turboIgnore()", () => {
turboIgnore(undefined, { directory: "__fixtures__/app" });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-app...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);
validateLogs(
[
'Failed to parse JSON output from `npx turbo run build --filter="test-app...[HEAD^]" --dry=json`.',
'Failed to parse JSON output from `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`.',
],
mockConsole.error,
{ prefix: "≫ " }
Expand All @@ -521,13 +526,13 @@ describe("turboIgnore()", () => {
turboIgnore(undefined, { directory: "__fixtures__/app" });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-app...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);
validateLogs(
[
'Failed to parse JSON output from `npx turbo run build --filter="test-app...[HEAD^]" --dry=json`.',
'Failed to parse JSON output from `npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`.',
],
mockConsole.error,
{ prefix: "≫ " }
Expand All @@ -547,6 +552,7 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
"Found commit message: [vercel skip]",
() => expect.stringContaining("⏭ Ignoring the change"),
Expand All @@ -568,6 +574,7 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
"Found commit message: [vercel deploy]",
() => expect.stringContaining("✓ Proceeding with deployment"),
Expand Down Expand Up @@ -608,10 +615,11 @@ describe("turboIgnore()", () => {
[
"Using Turborepo to determine if this project is affected by the commit...\n",
'Inferred "test-app" as workspace from "package.json"',
'Inferred turbo version ^2 based on "tasks" in "turbo.json"',
'Using "build" as the task as it was unspecified',
"Conflicting commit messages found: [vercel deploy] and [vercel skip]",
`Found previous deployment ("last-deployed-sha") for "test-app" on branch "my-branch"`,
'Analyzing results of `npx turbo run build --filter="test-app...[last-deployed-sha]" --dry=json`',
'Analyzing results of `npx -y turbo@^2 run build --filter="test-app...[last-deployed-sha]" --dry=json`',
"This project and its dependencies are not affected",
() => expect.stringContaining("⏭ Ignoring the change"),
],
Expand Down Expand Up @@ -641,7 +649,7 @@ describe("turboIgnore()", () => {
turboIgnore(undefined, { directory: "__fixtures__/app", maxBuffer: 1024 });

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-app...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`,
expect.objectContaining({ maxBuffer: 1024 }),
expect.anything()
);
Expand Down Expand Up @@ -670,7 +678,7 @@ describe("turboIgnore()", () => {
});

expect(mockExec).toHaveBeenCalledWith(
`npx turbo run build --filter="test-app...[HEAD^]" --dry=json`,
`npx -y turbo@^2 run build --filter="test-app...[HEAD^]" --dry=json`,
expect.objectContaining({ maxBuffer: 1024 }),
expect.anything()
);
Expand Down Expand Up @@ -699,4 +707,29 @@ describe("turboIgnore()", () => {
expectBuild(mockExit);
mockExec.mockRestore();
});

it("defaults to latest turbo if no hints for version", () => {
const mockExec = jest
.spyOn(child_process, "exec")
.mockImplementation((command, options, callback) => {
if (callback) {
return callback(
null,
'{"packages": [],"tasks":[]}',
"stderr"
) as unknown as ChildProcess;
}
return {} as unknown as ChildProcess;
});

turboIgnore(undefined, { directory: "__fixtures__/invalid_turbo_json" });

expect(mockExec).toHaveBeenCalledWith(
`npx -y turbo run build --filter="test-app...[HEAD^]" --dry=json`,
expect.anything(),
expect.anything()
);

mockExec.mockRestore();
});
});
3 changes: 3 additions & 0 deletions packages/turbo-ignore/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@
"check-types": "tsc --noEmit",
"lint:prettier": "prettier -c . --cache --ignore-path=../../.prettierignore"
},
"dependencies": {
"json5": "^2.2.3"
},
"devDependencies": {
"@turbo/eslint-config": "workspace:*",
"@turbo/telemetry": "workspace:*",
Expand Down
6 changes: 6 additions & 0 deletions packages/turbo-ignore/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ turboIgnoreCli
"The directory to run in (default: cwd)"
)
)
.addOption(
new Option(
"--turbo-version <version>",
"Explicitly set which version of turbo to invoke"
)
)
.addOption(
new Option(
"-b, --max-buffer <number>",
Expand Down
Loading
Loading