diff --git a/packages/cli-v3/src/build/plugins.ts b/packages/cli-v3/src/build/plugins.ts index 33babcfa3..c47889616 100644 --- a/packages/cli-v3/src/build/plugins.ts +++ b/packages/cli-v3/src/build/plugins.ts @@ -3,6 +3,7 @@ import { BuildTarget } from "@trigger.dev/core/v3/schemas"; import { ResolvedConfig } from "@trigger.dev/core/v3/build"; import { configPlugin } from "../config.js"; import { logger } from "../utilities/logger.js"; +import { bunPlugin } from "../runtimes/bun.js"; export async function buildPlugins( target: BuildTarget, @@ -20,6 +21,10 @@ export async function buildPlugins( plugins.push(polyshedPlugin()); + if (resolvedConfig.runtime === "bun") { + plugins.push(bunPlugin()); + } + return plugins; } diff --git a/packages/cli-v3/src/commands/deploy.ts b/packages/cli-v3/src/commands/deploy.ts index 82e5aa7cf..61b026e9b 100644 --- a/packages/cli-v3/src/commands/deploy.ts +++ b/packages/cli-v3/src/commands/deploy.ts @@ -358,6 +358,7 @@ async function _deployCommand(dir: string, options: DeployCommandOptions) { deploymentId: deployment.id, deploymentVersion: deployment.version, imageTag: deployment.imageTag, + loadImage: options.loadImage, contentHash: deployment.contentHash, externalBuildId: deployment.externalBuildData?.buildId, externalBuildToken: deployment.externalBuildData?.buildToken, diff --git a/packages/cli-v3/src/config.ts b/packages/cli-v3/src/config.ts index 21a561d81..8a54907a0 100644 --- a/packages/cli-v3/src/config.ts +++ b/packages/cli-v3/src/config.ts @@ -100,7 +100,7 @@ export function configPlugin(resolvedConfig: ResolvedConfig): esbuild.Plugin | u options.build = {}; // Remove export resolveEnvVars function as well - delete $mod.exports.resolveEnvVars; + $mod.exports.resolveEnvVars = undefined; const contents = generateCode($mod); diff --git a/packages/cli-v3/src/deploy/buildImage.ts b/packages/cli-v3/src/deploy/buildImage.ts index 3225ad9f8..f85f5856c 100644 --- a/packages/cli-v3/src/deploy/buildImage.ts +++ b/packages/cli-v3/src/deploy/buildImage.ts @@ -417,7 +417,90 @@ export async function generateContainerfile(buildManifest: BuildManifest) { } async function generateBunContainerfile(buildManifest: BuildManifest) { - return ""; + const buildArgs = Object.entries(buildManifest.build.env || {}) + .flatMap(([key]) => `ARG ${key}`) + .join("\n"); + + const buildEnvVars = Object.entries(buildManifest.build.env || {}) + .flatMap(([key]) => `ENV ${key}=$${key}`) + .join("\n"); + + const postInstallCommands = (buildManifest.build.commands || []) + .map((cmd) => `RUN ${cmd}`) + .join("\n"); + + return ` +FROM oven/bun:1 AS base +RUN apt-get update && apt-get --fix-broken install -y && apt-get install -y --no-install-recommends busybox ca-certificates dumb-init git openssl && apt-get clean && rm -rf /var/lib/apt/lists/* + +FROM base AS install + +USER bun +WORKDIR /app + +${buildArgs} + +${buildEnvVars} + +COPY --chown=bun:bun package.json ./ +RUN bun install --production --no-save + +# Now copy all the files +# IMPORTANT: Do this after running npm install because npm i will wipe out the node_modules directory +COPY --chown=bun:bun . . + +${postInstallCommands} + +from install as indexer + +USER bun +WORKDIR /app + +ARG TRIGGER_PROJECT_ID +ARG TRIGGER_DEPLOYMENT_ID +ARG TRIGGER_DEPLOYMENT_VERSION +ARG TRIGGER_CONTENT_HASH +ARG TRIGGER_PROJECT_REF +ARG NODE_EXTRA_CA_CERTS +ARG TRIGGER_SECRET_KEY +ARG TRIGGER_API_URL + +ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \ + TRIGGER_DEPLOYMENT_ID=\${TRIGGER_DEPLOYMENT_ID} \ + TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \ + TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \ + TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \ + TRIGGER_SECRET_KEY=\${TRIGGER_SECRET_KEY} \ + TRIGGER_API_URL=\${TRIGGER_API_URL} \ + NODE_EXTRA_CA_CERTS=\${NODE_EXTRA_CA_CERTS} \ + NODE_ENV=production + +# Run the indexer +RUN bun run ${buildManifest.indexerEntryPoint} + +# Development or production stage builds upon the base stage +FROM base AS final + +USER bun +WORKDIR /app + +ENV TRIGGER_PROJECT_ID=\${TRIGGER_PROJECT_ID} \ + TRIGGER_DEPLOYMENT_ID=\${TRIGGER_DEPLOYMENT_ID} \ + TRIGGER_DEPLOYMENT_VERSION=\${TRIGGER_DEPLOYMENT_VERSION} \ + TRIGGER_CONTENT_HASH=\${TRIGGER_CONTENT_HASH} \ + TRIGGER_PROJECT_REF=\${TRIGGER_PROJECT_REF} \ + NODE_EXTRA_CA_CERTS=\${NODE_EXTRA_CA_CERTS} \ + NODE_ENV=production + +# Copy the files from the install stage +COPY --from=install --chown=bun:bun /app ./ + +# Copy the index.json file from the indexer stage +COPY --from=indexer --chown=bun:bun /app/index.json ./ + +ENTRYPOINT [ "dumb-init", "bun", "run", "${buildManifest.workerEntryPoint}" ] +CMD [] + `; } async function generateNodeContainerfile(buildManifest: BuildManifest) { diff --git a/packages/cli-v3/src/dev/backgroundWorker.ts b/packages/cli-v3/src/dev/backgroundWorker.ts index 1d0fa796f..b259b06d5 100644 --- a/packages/cli-v3/src/dev/backgroundWorker.ts +++ b/packages/cli-v3/src/dev/backgroundWorker.ts @@ -708,6 +708,7 @@ class TaskRunProcess { cwd, env: fullEnv, execArgv: ["--trace-uncaught", "--no-warnings=ExperimentalWarning"], + execPath: execPathForRuntime(build.runtime), }); this._childPid = this._child?.pid; diff --git a/packages/cli-v3/src/runtimes/bun.ts b/packages/cli-v3/src/runtimes/bun.ts new file mode 100644 index 000000000..79cdb2ab4 --- /dev/null +++ b/packages/cli-v3/src/runtimes/bun.ts @@ -0,0 +1,12 @@ +import * as esbuild from "esbuild"; + +export function bunPlugin(): esbuild.Plugin { + return { + name: "bun", + setup(build) { + build.onResolve({ filter: /^bun:/ }, (args) => { + return { path: args.path, external: true }; + }); + }, + }; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 400f73df0..cefa9c012 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1321,6 +1321,22 @@ importers: specifier: ^5.5.4 version: 5.5.4 + references/bun-catalog: + dependencies: + '@trigger.dev/sdk': + specifier: workspace:* + version: link:../../packages/trigger-sdk + devDependencies: + '@types/bun': + specifier: ^1.1.6 + version: 1.1.6 + trigger.dev: + specifier: workspace:* + version: link:../../packages/cli-v3 + typescript: + specifier: ^5.5.4 + version: 5.5.4 + references/v3-catalog: dependencies: '@ffmpeg-installer/ffmpeg': @@ -12486,6 +12502,12 @@ packages: '@types/node': 18.19.20 dev: true + /@types/bun@1.1.6: + resolution: {integrity: sha512-uJgKjTdX0GkWEHZzQzFsJkWp5+43ZS7HC8sZPFnOwnSo1AsNl2q9o2bFeS23disNDqbggEgyFkKCHl/w8iZsMA==} + dependencies: + bun-types: 1.1.17 + dev: true + /@types/caseless@0.12.5: resolution: {integrity: sha512-hWtVTC2q7hc7xZ/RLbxapMvDMgUnDvKvMOpKal4DrMyfGBUfB1oKaZlIRr6mJL+If3bAP6sV/QneGzF6tJjZDg==} dev: false @@ -12814,6 +12836,12 @@ packages: undici-types: 5.26.5 dev: false + /@types/node@20.12.14: + resolution: {integrity: sha512-scnD59RpYD91xngrQQLGkE+6UrHUPzeKZWhhjBSa3HSkwjbQc38+q3RoIVEwxQGRw3M+j5hpNAM+lgV3cVormg==} + dependencies: + undici-types: 5.26.5 + dev: true + /@types/node@20.14.14: resolution: {integrity: sha512-d64f00982fS9YoOgJkAMolK7MN8Iq3TDdVjchbYHdEmjth/DHowx82GnoA+tVUAN+7vxfYUgAzi+JXbKNd2SDQ==} dependencies: @@ -13026,7 +13054,6 @@ packages: resolution: {integrity: sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==} dependencies: '@types/node': 18.19.20 - dev: false /@types/ws@8.5.4: resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==} @@ -14572,6 +14599,13 @@ packages: semver: 7.5.4 dev: true + /bun-types@1.1.17: + resolution: {integrity: sha512-Z4+OplcSd/YZq7ZsrfD00DKJeCwuNY96a1IDJyR73+cTBaFIS7SC6LhpY/W3AMEXO9iYq5NJ58WAwnwL1p5vKg==} + dependencies: + '@types/node': 20.12.14 + '@types/ws': 8.5.10 + dev: true + /bundle-name@4.1.0: resolution: {integrity: sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==} engines: {node: '>=18'} diff --git a/references/bun-catalog/.env.example b/references/bun-catalog/.env.example new file mode 100644 index 000000000..9001181b6 --- /dev/null +++ b/references/bun-catalog/.env.example @@ -0,0 +1,3 @@ +TRIGGER_SECRET_KEY= +TRIGGER_API_URL= +OPENAI_API_KEY="My API Key" \ No newline at end of file diff --git a/references/bun-catalog/.gitignore b/references/bun-catalog/.gitignore new file mode 100644 index 000000000..6524f048d --- /dev/null +++ b/references/bun-catalog/.gitignore @@ -0,0 +1 @@ +.trigger \ No newline at end of file diff --git a/references/bun-catalog/README.md b/references/bun-catalog/README.md new file mode 100644 index 000000000..37c0a04e9 --- /dev/null +++ b/references/bun-catalog/README.md @@ -0,0 +1,59 @@ +# The v3 catalog + +You can test v3 tasks from inside the app in this project. It's designed to be used for testing features and functionality of the v3 SDK. + +## One-time setup + +1. In Postgres go to the "Organizations" table and on your org set the `v3Enabled` column to `true`. + +2. Create a v3 project in the UI of the webapp, you should now be able to select it from the dropdown. + +3. In Postgres go to the "Projects" table and for the project you create change the `externalRef` to `yubjwjsfkxnylobaqvqz`. + +This is so the `trigger.config.ts` file inside the v3-catalog doesn't keep getting changed by people accidentally pushing this. + +## How to use + +1. Make sure you're running the main webapp + +```bash +pnpm run dev --filter webapp +``` + +2. Build the v3 CLI (this needs to be done everytime a code changes is made to the CLI if you're working on it) + +```bash +pnpm run build --filter trigger.dev +``` + +3. CD into the v3-catalog directory + +```bash +cd references/v3-catalog +``` + +4. If you've never logged in to the CLI you'll see an error telling you to login. Do this: + +```bash +pnpm exec triggerdev login -a http://localhost:3030 +``` + +If this fails because you already are logged in you can create a new profile: + +```bash +pnpm exec triggerdev login -a http://localhost:3030 --profile local +``` + +Note: if you use a profile then you'll need to append `--profile local` to all commands, like `dev`. + +5. Run the v3 CLI + +```bash +pnpm exec triggerdev dev +``` + +6. You should see the v3 dev command spitting out messages, including that it's started a background worker. + +7. Go to the webapp now and inside your project you should see some tasks on the "Tasks" page. + +8. Go to the "Test" page in the sidebar and select a task. Then enter a payload and click "Run test". You can tell what the payloads should be by looking at the relevant task file inside the `/references/v3-catalog/src/trigger` folder. Many of them accept an empty payload. diff --git a/references/bun-catalog/package.json b/references/bun-catalog/package.json new file mode 100644 index 000000000..412676d34 --- /dev/null +++ b/references/bun-catalog/package.json @@ -0,0 +1,17 @@ +{ + "name": "@references/bun-catalog", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "dev:trigger": "triggerdev dev" + }, + "dependencies": { + "@trigger.dev/sdk": "workspace:*" + }, + "devDependencies": { + "@types/bun": "^1.1.6", + "trigger.dev": "workspace:*", + "typescript": "^5.5.4" + } +} \ No newline at end of file diff --git a/references/bun-catalog/src/trigger/bun.ts b/references/bun-catalog/src/trigger/bun.ts new file mode 100644 index 000000000..aa34ec913 --- /dev/null +++ b/references/bun-catalog/src/trigger/bun.ts @@ -0,0 +1,15 @@ +import { Database } from "bun:sqlite"; +import { task } from "@trigger.dev/sdk/v3"; + +export const bunTask = task({ + id: "bun-task", + run: async (payload: { query: string }) => { + const db = new Database(":memory:"); + const query = db.query("select 'Hello world' as message;"); + console.log(query.get()); // => { message: "Hello world" } + + return { + message: "Query executed", + }; + }, +}); diff --git a/references/bun-catalog/trigger.config.ts b/references/bun-catalog/trigger.config.ts new file mode 100644 index 000000000..308216a8f --- /dev/null +++ b/references/bun-catalog/trigger.config.ts @@ -0,0 +1,25 @@ +import { defineConfig } from "@trigger.dev/sdk/v3"; + +export default defineConfig({ + runtime: "bun", + project: "proj_uxbxncnbsyamyxeqtucu", + machine: "small-2x", + retries: { + enabledInDev: true, + default: { + maxAttempts: 4, + minTimeoutInMs: 10000, + maxTimeoutInMs: 10000, + factor: 2, + randomize: true, + }, + }, + enableConsoleLogging: false, + logLevel: "info", + onStart: async (payload, { ctx }) => { + console.log(`Task ${ctx.task.id} started ${ctx.run.id}`); + }, + onFailure: async (payload, error, { ctx }) => { + console.log(`Task ${ctx.task.id} failed ${ctx.run.id}`); + }, +}); diff --git a/references/bun-catalog/tsconfig.json b/references/bun-catalog/tsconfig.json new file mode 100644 index 000000000..635ecdb76 --- /dev/null +++ b/references/bun-catalog/tsconfig.json @@ -0,0 +1,20 @@ +{ + "compilerOptions": { + "target": "esnext", + "module": "NodeNext", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "strict": true, + "outDir": "dist", + "skipLibCheck": true, + "customConditions": ["@triggerdotdev/source"], + "jsx": "preserve", + "emitDecoratorMetadata": true, + "experimentalDecorators": true, + "lib": ["DOM", "DOM.Iterable"], + "paths": { + "@/*": ["./src/*"] + } + }, + "include": ["./src/**/*.ts", "trigger.config.ts"] +} diff --git a/references/v3-catalog/package.json b/references/v3-catalog/package.json index 57c7005be..8e8968837 100644 --- a/references/v3-catalog/package.json +++ b/references/v3-catalog/package.json @@ -37,9 +37,9 @@ "server-only": "^0.0.1", "stripe": "^12.14.0", "typeorm": "^0.3.20", + "wrangler": "3.70.0", "yt-dlp-wrap": "^2.3.12", - "zod": "3.23.8", - "wrangler": "3.70.0" + "zod": "3.23.8" }, "devDependencies": { "@opentelemetry/api": "^1.8.0", diff --git a/references/v3-catalog/trigger.config.ts b/references/v3-catalog/trigger.config.ts index c7a8cd4d2..c34ad2388 100644 --- a/references/v3-catalog/trigger.config.ts +++ b/references/v3-catalog/trigger.config.ts @@ -31,7 +31,7 @@ export const resolveEnvVars: ResolveEnvironmentVariablesFunction = async (ctx) = }; export default defineConfig({ - runtime: "bun", + runtime: "node", project: "yubjwjsfkxnylobaqvqz", machine: "small-2x", instrumentations: [new OpenAIInstrumentation()],