Skip to content

Support ignoring test/spec files inside trigger dirs (fixes #1593) #1596

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

Merged
merged 2 commits into from
Jan 10, 2025
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
5 changes: 5 additions & 0 deletions .changeset/famous-grapes-film.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---

Support ignoring test/spec files inside trigger dirs (fixes #1593)
27 changes: 27 additions & 0 deletions docs/config/config-file.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,33 @@ The config file handles a lot of things, like:
imports used inside build config with be tree-shaken out.
</Note>

## Dirs

You can specify the directories where your tasks are located using the `dirs` option:

```ts trigger.config.ts
import { defineConfig } from "@trigger.dev/sdk/v3";

export default defineConfig({
project: "<project ref>",
dirs: ["./trigger"],
});
```

If you omit the `dirs` option, we will automatically detect directories that are named `trigger` in your project, but we recommend specifying the directories explicitly. The `dirs` option is an array of strings, so you can specify multiple directories if you have tasks in multiple locations.

We will search for TypeScript and JavaScript files in the specified directories and include them in the build process. We automatically exclude files that have `.test` or `.spec` in the name, but you can customize this by specifying glob patterns in the `ignorePatterns` option:

```ts trigger.config.ts
import { defineConfig } from "@trigger.dev/sdk/v3";

export default defineConfig({
project: "<project ref>",
dirs: ["./trigger"],
ignorePatterns: ["**/*.my-test.ts"],
});
```

## Lifecycle functions

You can add lifecycle functions to get notified when any task starts, succeeds, or fails using `onStart`, `onSuccess` and `onFailure`:
Expand Down
64 changes: 50 additions & 14 deletions docs/mint.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
{
"$schema": "https://mintlify.com/schema.json",
"name": "Trigger.dev",
"openapi": ["/openapi.yml", "/v3-openapi.yaml"],
"openapi": [
"/openapi.yml",
"/v3-openapi.yaml"
],
"api": {
"playground": {
"mode": "simple"
Expand Down Expand Up @@ -128,7 +131,6 @@
"quick-start",
"video-walkthrough",
"how-it-works",
"upgrading-beta",
"limits"
]
},
Expand All @@ -137,20 +139,30 @@
"pages": [
{
"group": "Tasks",
"pages": ["tasks/overview", "tasks/schemaTask", "tasks/scheduled"]
"pages": [
"tasks/overview",
"tasks/schemaTask",
"tasks/scheduled"
]
},
"triggering",
"runs",
"apikeys",
{
"group": "Configuration",
"pages": ["config/config-file", "config/extensions/overview"]
"pages": [
"config/config-file",
"config/extensions/overview"
]
}
]
},
{
"group": "Development",
"pages": ["cli-dev", "run-tests"]
"pages": [
"cli-dev",
"run-tests"
]
},
{
"group": "Deployment",
Expand All @@ -160,7 +172,9 @@
"github-actions",
{
"group": "Deployment integrations",
"pages": ["vercel-integration"]
"pages": [
"vercel-integration"
]
}
]
},
Expand All @@ -172,7 +186,13 @@
"errors-retrying",
{
"group": "Wait",
"pages": ["wait", "wait-for", "wait-until", "wait-for-event", "wait-for-request"]
"pages": [
"wait",
"wait-for",
"wait-until",
"wait-for-event",
"wait-for-request"
]
},
"queue-concurrency",
"versioning",
Expand Down Expand Up @@ -217,7 +237,10 @@
"management/overview",
{
"group": "Tasks API",
"pages": ["management/tasks/trigger", "management/tasks/batch-trigger"]
"pages": [
"management/tasks/trigger",
"management/tasks/batch-trigger"
]
},
{
"group": "Runs API",
Expand Down Expand Up @@ -256,7 +279,9 @@
},
{
"group": "Projects API",
"pages": ["management/projects/runs"]
"pages": [
"management/projects/runs"
]
}
]
},
Expand Down Expand Up @@ -294,6 +319,7 @@
"pages": [
"troubleshooting",
"upgrading-packages",
"upgrading-beta",
"troubleshooting-alerts",
"troubleshooting-uptime-status",
"troubleshooting-github-issues",
Expand All @@ -302,11 +328,17 @@
},
{
"group": "Help",
"pages": ["community", "help-slack", "help-email"]
"pages": [
"community",
"help-slack",
"help-email"
]
},
{
"group": "",
"pages": ["guides/introduction"]
"pages": [
"guides/introduction"
]
},
{
"group": "Frameworks",
Expand Down Expand Up @@ -380,16 +412,20 @@
},
{
"group": "Dashboard",
"pages": ["guides/dashboard/creating-a-project"]
"pages": [
"guides/dashboard/creating-a-project"
]
},
{
"group": "Migrations",
"pages": ["guides/use-cases/upgrading-from-v2"]
"pages": [
"guides/use-cases/upgrading-from-v2"
]
}
],
"footerSocials": {
"twitter": "https://twitter.com/triggerdotdev",
"github": "https://github.com/triggerdotdev",
"linkedin": "https://www.linkedin.com/company/triggerdotdev"
}
}
}
2 changes: 2 additions & 0 deletions packages/cli-v3/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@
"@trigger.dev/core": "workspace:3.3.9",
"c12": "^1.11.1",
"chalk": "^5.2.0",
"chokidar": "^3.6.0",
"cli-table3": "^0.6.3",
"commander": "^9.4.1",
"defu": "^6.1.4",
Expand Down Expand Up @@ -119,6 +120,7 @@
"terminal-link": "^3.0.0",
"tiny-invariant": "^1.2.0",
"tinyexec": "^0.3.1",
"tinyglobby": "^0.2.2",
"ws": "^8.18.0",
"xdg-app-paths": "^8.3.0",
"zod": "3.23.8",
Expand Down
128 changes: 83 additions & 45 deletions packages/cli-v3/src/build/bundle.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
telemetryEntryPoint,
} from "./packageModules.js";
import { buildPlugins } from "./plugins.js";
import { createEntryPointManager } from "./entryPoints.js";

export interface BundleOptions {
target: BuildTarget;
Expand Down Expand Up @@ -45,12 +46,30 @@ export type BundleResult = {
export async function bundleWorker(options: BundleOptions): Promise<BundleResult> {
const { resolvedConfig } = options;

// We need to add the package entry points here somehow
// Then we need to get them out of the build result into the build manifest
// taskhero/dist/esm/workers/dev.js
// taskhero/dist/esm/telemetry/loader.js
const entryPoints = await getEntryPoints(options.target, resolvedConfig);
const $buildPlugins = await buildPlugins(options.target, resolvedConfig);
let currentContext: esbuild.BuildContext | undefined;

const entryPointManager = await createEntryPointManager(
resolvedConfig.dirs,
resolvedConfig,
options.target,
typeof options.watch === "boolean" ? options.watch : false,
async (newEntryPoints) => {
if (currentContext) {
// Rebuild with new entry points
await currentContext.cancel();
await currentContext.dispose();
const buildOptions = await createBuildOptions({
...options,
entryPoints: newEntryPoints,
});

logger.debug("Rebuilding worker with options", buildOptions);

currentContext = await esbuild.context(buildOptions);
await currentContext.watch();
}
}
);

let initialBuildResult: (result: esbuild.BuildResult) => void;
const initialBuildResultPromise = new Promise<esbuild.BuildResult>(
Expand All @@ -63,12 +82,63 @@ export async function bundleWorker(options: BundleOptions): Promise<BundleResult
},
};

const buildOptions = await createBuildOptions({
...options,
entryPoints: entryPointManager.entryPoints,
buildResultPlugin,
});

let result: esbuild.BuildResult<typeof buildOptions>;
let stop: BundleResult["stop"];

logger.debug("Building worker with options", buildOptions);

if (options.watch) {
currentContext = await esbuild.context(buildOptions);
await currentContext.watch();
result = await initialBuildResultPromise;
if (result.errors.length > 0) {
throw new Error("Failed to build");
}

stop = async function () {
await entryPointManager.stop();
await currentContext?.dispose();
};
} else {
result = await esbuild.build(buildOptions);

stop = async function () {
await entryPointManager.stop();
};
}

const bundleResult = await getBundleResultFromBuild(
options.target,
options.cwd,
options.resolvedConfig,
result
);

if (!bundleResult) {
throw new Error("Failed to get bundle result");
}

return { ...bundleResult, stop };
}

// Helper function to create build options
async function createBuildOptions(
options: BundleOptions & { entryPoints: string[]; buildResultPlugin?: esbuild.Plugin }
): Promise<esbuild.BuildOptions & { metafile: true }> {
const customConditions = options.resolvedConfig.build?.conditions ?? [];

const conditions = [...customConditions, "trigger.dev", "module", "node"];

const buildOptions: esbuild.BuildOptions & { metafile: true } = {
entryPoints,
const $buildPlugins = await buildPlugins(options.target, options.resolvedConfig);

return {
entryPoints: options.entryPoints,
outdir: options.destination,
absWorkingDir: options.cwd,
bundle: true,
Expand All @@ -93,50 +163,18 @@ export async function bundleWorker(options: BundleOptions): Promise<BundleResult
inject: [...shims], // TODO: copy this into the working dir to work with Yarn PnP
jsx: options.jsxAutomatic ? "automatic" : undefined,
jsxDev: options.jsxAutomatic && options.target === "dev" ? true : undefined,
plugins: [...$buildPlugins, ...(options.plugins ?? []), buildResultPlugin],
plugins: [
...$buildPlugins,
...(options.plugins ?? []),
...(options.buildResultPlugin ? [options.buildResultPlugin] : []),
],
...(options.jsxFactory && { jsxFactory: options.jsxFactory }),
...(options.jsxFragment && { jsxFragment: options.jsxFragment }),
logLevel: "silent",
logOverride: {
"empty-glob": "silent",
},
};

let result: esbuild.BuildResult<typeof buildOptions>;
let stop: BundleResult["stop"];

logger.debug("Building worker with options", buildOptions);

if (options.watch) {
const ctx = await esbuild.context(buildOptions);
await ctx.watch();
result = await initialBuildResultPromise;
if (result.errors.length > 0) {
throw new Error("Failed to build");
}

stop = async function () {
await ctx.dispose();
};
} else {
result = await esbuild.build(buildOptions);
// Even when we're not watching, we still want some way of cleaning up the
// temporary directory when we don't need it anymore
stop = async function () {};
}

const bundleResult = await getBundleResultFromBuild(
options.target,
options.cwd,
options.resolvedConfig,
result
);

if (!bundleResult) {
throw new Error("Failed to get bundle result");
}

return { ...bundleResult, stop };
}

export async function getBundleResultFromBuild(
Expand Down
Loading
Loading