Compare commits

...

431 Commits

Author SHA1 Message Date
Eric Allam e85fc501a6 Fix pnpm lock file 2024-04-23 17:03:53 +01:00
github-actions[bot] 0bfeb0816f chore: Update version for release (beta) (#1054)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-23 16:58:48 +01:00
nicktrn b207601732 v3: semi-automatic package update command (#1052)
* fix package manager detection

* fix cli update check while in beta

* add update command and warn on mismatches

* update fixes and better integration with dev and deploy

* fix for ci

* update docs

* changeset

* be more specific about prompts before updates

* fail on version mismatch during ci

* update github actions docs

* fix package manager copypasta

* remove ncu

* ignore companyicons

* improve warnings and errors
2024-04-23 16:08:46 +01:00
Matt Aitken 3913e57ef4 Trace view fixes and improvements (#1046)
* Query param for span using history.replaceState is working

* When clicking again on a node, don’t collapse it

* Close the span view using the same replacing of the search param

* Conditional rendering of the resize panels was causing the tree view re-rendering and collapsing…

* Live reloading moved to where the parent label is

* Span action bar is now deeper

* WIP on trace view navigation changes with shortcuts

* Shortcuts for expanding and collapsing en masse

* Number keys expand/collapse levels

* Changed duration toggle to a shortcut key

* Option + click expands/collapse at that level

* Option/alt left/right expands/collapse at that level

* Removed unused imports

* Link from the runs table to the specific span

* Latest lockfile

* Sorted imports

* When doing a test link directly to a span

* Replay links to the span

* CLI log links go directly to a span

* Keyboard shortcuts are in a popover if the width is narrow

* If holding alt only collapse level

* Don’t expand the individual node if you’re holding alt
2024-04-22 13:46:08 +01:00
James Ritchie 26f310397a Fixed the grid layout for v2 runs page 2024-04-22 13:06:56 +01:00
github-actions[bot] 0a845767a0 chore: Update version for release (beta) (#1049)
* chore: Update version for release (beta)

* update lockfile

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2024-04-21 15:07:11 +01:00
nicktrn ed2a26c865 v3: fix additionalFiles, uncaught exceptions, and improve errors (#1048)
* fix additionalFiles for paths up the tree

* warn if additionalFiles pattern produced no matches

* improve deploy warnings and errors, fail early

* changeset
2024-04-21 15:03:00 +01:00
Eric Allam 4a68e71583 Fix pnpm lock file 2024-04-19 19:20:01 +01:00
github-actions[bot] b657eb6555 chore: Update version for release (beta) (#1044)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-19 19:19:11 +01:00
Eric Allam 62c9a5b712 Fix restoring after waiting for task/batch 2024-04-19 18:59:02 +01:00
Matt Aitken f339b41ef3 Added some basic Defer migration details for CRON 2024-04-19 18:30:58 +01:00
Eric Allam ae40ce3995 Fix the management file 2024-04-19 16:14:57 +01:00
Eric Allam 374edef020 Updates the trigger, batchTrigger and their *AndWait variants to use the first parameter for the payload/items, and the second parameter for options (#1045)
Also always returns a `TaskRunResult` object from `triggerAndWait` instead of rethrowing subtask errors in the parent
2024-04-19 14:51:51 +01:00
Eric Allam b82db67b81 Add additional logging around cleaning up dev workers, and always kill them after 5 seconds if they haven't already exited 2024-04-19 11:14:20 +01:00
Eric Allam 26093896d2 v3: Fixes for using (batch)triggerAndWait with idempotency keys (#1043)
* Fixes various issues with triggerAndWait and batchTriggerAndWait

When using idempotency keys, triggerAndWait and batchTriggerAndWait will still work even if the existing runs have already been completed (or even partially completed, in the case of batchTriggerAndWait)

- TaskRunExecutionResult.id is now the run friendlyId, not the attempt friendlyId
- A single TaskRun can now have many batchItems, in the case of batchTriggerAndWait while using idempotency keys
- A run’s idempotencyKey is now added to the ctx as well as the TaskEvent and displayed in the span view
- When resolving batchTriggerAndWait, the runtimes no longer reject promises, leading to an error in the parent task

* Remove the default queue concurrency limit as we now have env and org concurrency limits

* Use the run friendlyId in the completion result id

* Added some error logging
2024-04-19 10:54:43 +01:00
github-actions[bot] e7bd1ee676 chore: Update version for release (beta) (#1042)
* chore: Update version for release (beta)

* update lockfile

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2024-04-18 17:53:33 +01:00
nicktrn 584c7da5df v3: prod worker graceful shutdown (#1034)
* graceful exit with timeout

* handle and display graceful timeout errors

* fix for very long waits

* changeset

* increase termination grace period to an hour
2024-04-18 15:46:14 +01:00
nicktrn c9e1a3e9c5 v3: fix dependency trigger and wait (#1030)
* fix dev dependecy resumes

* add catalog entry with multiple trigger waits

* update docker provider lifecycle command

* switch to x for clearing run filters

* Revert "fix dev dependecy resumes"

This reverts commit b4061f2ae71f21889adcf061928e2e77c436f0ed.

* fix dependency resumes, properly this time

* add catalog entry for dependency waits in loops

* advice in docs re parallel dependency waits

* fix link from v3 to v2 docs

* move lifecycle command logging to debug only

* Removed batchOptions from the trigger options and the docs

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-04-18 14:48:43 +01:00
nicktrn 2f5b4a8471 v3: fix raw queries for custom schemas (#1033)
* add custom validation to db url env vars

* extract schema from db url and use in all raw queries

* use qualified names in scheduling raw queries

* cook a few raw queries

* Added missing raw query schema specifier to DeploymentListPresenter

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-04-18 12:01:38 +01:00
Eric Allam 69f6891687 Fixed rebalancing when message is acked
I’ve also added a “rebalancer worker” that will periodically rebalance parent queues, in case have been any issues with rebalancing (basically a “sweeper of entropy” process)
2024-04-17 21:00:39 +01:00
Matt Aitken acd7681e58 Scheduled task docs (#1039)
* Scheduled docs v1

* Improved copy

* Rejigged the docs some more. Added a dynamic section
2024-04-17 17:41:16 +01:00
Eric Allam 180a5ef01d Fix pnpm lock file 2024-04-17 16:34:14 +01:00
github-actions[bot] 62544d3234 chore: Update version for release (beta) (#1038)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-17 16:33:23 +01:00
Eric Allam 9b045071d8 Better errors when trying to delete a schedule that doesn’t exist 2024-04-17 16:05:51 +01:00
Eric Allam 618d2207c6 Fixed the deployed scheduled task check by looking at the slug, not the task.id 2024-04-17 15:38:39 +01:00
Eric Allam 36d8bee14a Don’t delete task runs if the attached task schedule or instance is deleted 2024-04-17 15:26:35 +01:00
Eric Allam 44e1b87547 v3: various schedule fixes (#1040)
* Improve the SDK function types and expose a new APIError instead of the APIResult type

* Skip triggering scheduled tasks if the task isn’t found in the current deployment

Also fixes an issue when editing the environments of a schedule
2024-04-17 15:10:23 +01:00
Matt Aitken 71b0ef8f77 Don’t allow editing the Deduplication key when updating a schedule 2024-04-17 14:42:18 +01:00
Matt Aitken f66543c9c7 When updating a schedule in the UI, it now says “Schedule updated” 2024-04-17 14:33:11 +01:00
Matt Aitken 03b104a3d5 Added JSDocs to the schedule options in the SDK 2024-04-17 14:25:40 +01:00
Eric Allam fde939a30e Fixed empty strings making their way into schedule externalId 2024-04-17 11:59:29 +01:00
Matt Aitken 4986bfda2e Scheduled tasks (#1036)
* Database schema and migrations for schedules

* Added schedules to the side menu

* The pagination can optionally hide the page numbers for a compactive mode

* Filters for the schedule page

* Added triggerSource (“STANDARD”, “SCHEDULED”) to BackgroundWorkerTask

* Added the ability to disabled a LinkButton

* Started work on the schedule page

* Environment buttons

* The new schedule form styles

* Added a cxouple of extra fields

* Allow a checkbox to have a rich label

* Added cronstrue package to the webapp

* WIP creating tasks using the form

* Improved the form styling

* Creating schedules is working in the UI

* Minor improvements

* Basic schedule table is displaying

* Creating tasks with triggerSource = scheduled. Refactored how task metadata is stored and accessed to be cleaner

* Resource route

* Fixes in the form

* Added a gap between the environments

* WIP on OpenAI generating CRON expressions

* AI generated CRON expressions is working

* Fix for the CRON field being uneditable after an AI generation

* Improvements

* Table padding

* useThrottle now behaves correctly

* Added filtering to the schedules list

* Improved the layout and fixed CRON search

* Fixed pagination for the schedules list. Just use a regular Prisma query

* Page size of 20

* Added links to the schedule rows

* Get rid of the Last run column for now

* Implement triggered scheduled tasks

Also implemented superjson payloads and dev runtime environment “presence” with RuntimeEnvironmentSession

* Move CronPattern and CreateSchedule into a common client-accessible file

* Latest UI changes

* Fix for creating a task schedule with a blank dedup key

* Refactor the human to cron stuff into a separate file and use json_object OpenAI response format

* Fix for trying to use a hook on the server-side…

* A couple of fixes to the new schedule form

* WIP on viewing a scheduled run

* Make the filters all optional

* Use the RunListPresenter from the schedule presenter

* Display a table of runs… the wrong runs but still

* Runs from the schedule

* Deleting schedules from the UI

* Tidied imports and fixed name of options object

* Disabling a schedule

* Editing schedules

* Tidied imports

* Added icons to the task list, needs some design love

* Added a tooltip for CRON pattersn

* Show the last run in the schedules table

* Some tweaks

* Added a placeholder to the CRON AI field

* Improved the trigger source icon

* Dim out disabled schedules

* Scheduled tasks have the correct icon in a run

* Added the task source icon to the test task list

* Added the date field component to storybook

* Style improvements to the date field

* Implement Task Schedule API

* added a medium sized variant to the date field

* Fixed replay run for superjson payload types

Also now linking from the replaying run to the original run (using span links)

Also added a project metrics prometheus endpoint to detect the state of the queues

* WIP on allowing different forms for testing

* If you pass a string to prettyPrintPacket which is json or superjson, safeParse it first

* Test page, deal json and superjson. Started splitting UI for schedules

* WIP on schedule form

* Removed the Label from the DateField

* WIP on test schedule form

* Fix for the runs page showing the wrong message when there are no runs from time filtering

* Removed labels from the DateField

* Fixes for the form

* Test runs are working for schedules

* Fix for nextScheduledTimestamps in triggerScheduledTask

* Implement idempotency key support and fix issue with cancelled runs causing concurrency usage

* Added API documentation for the schedule API

* Remove log

* Removed console log from runs page

* Transform the recent runs test data on the server

* Fix for hydration mismatch

* Current date as the default for the test form

* Recent payloads working

* Delete schedule modal

* Deal with empty strings from the form

* Set the initial value for the scheduled test form

* Add option to print console logs in the dev CLI locally (issue #1014)

* Export queue from the SDK

* Fix for schedules list when you have no schedule tasks

* Blank states improved

* Make task schedules more generic, to support additional schedule generators in the future

* Removed log from maqrs

* Removed “v3/schedules” export from the SDK

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2024-04-17 11:14:23 +01:00
Matt Aitken a3abe4ca08 Documentation edits made through Mintlify web editor 2024-04-17 09:08:08 +01:00
Matt Aitken fad32a79dd Documentation edits made through Mintlify web editor 2024-04-17 09:07:16 +01:00
Matt Aitken 9d843caf83 Documentation edits made through Mintlify web editor 2024-04-16 14:33:07 +01:00
nicktrn 5eaf7bca34 don't require git for build 2024-04-12 19:02:38 +01:00
nicktrn 4a0368dec3 lockfile 2024-04-12 18:18:49 +01:00
github-actions[bot] f10f120e55 chore: Update version for release (beta) (#1028)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-12 18:18:03 +01:00
nicktrn d3a18fbdf6 v3: cli and misc fixes for windows (#1027)
* fix: otlp-importer script

* update pluginPath

* Refactor script to ensure compatibility with both Windows and Unix platforms

* Revert command changes

* Fix: Init command was failing on Windows because of bad template paths

* Removed resolveInternalFilePath

* Path fixes for the dev command

* Fix for the import paths being wrong on Windows because the contain backslashes

* The metaOutputKey should have forward slashes in it

* Print the banner immediately, otherwise with bad internet you get a blank console for a long time

* Try normalizing the trigger.config import path

* Allow tsx and jsx files

* Improved task file names and paths

* Removed closing bracket for the upgrade message

* Log out the metafile outputs for debugging

* Log out the entryPointContents before esbuild

* Log the metafile out

* ballmerize the cli

* replace npm-watch with plain old nodemon

* fix text inputs on windows

* changeset

---------

Co-authored-by: Kritik Jiyaviya <kritikjiyaviya07@gmail.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-04-12 18:12:01 +01:00
nicktrn b82a07ad1c add missing ca certs to prod worker 2024-04-12 18:07:54 +01:00
Eric Allam fa81bf356a Fix pnpm lock file 2024-04-12 12:34:32 +01:00
github-actions[bot] fec4dc3bef chore: Update version for release (beta) (#1025)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-12 12:34:02 +01:00
Eric Allam a80089c88f Fix the package version of trigger.dev with the rest of the @trigger.dev/* packages 2024-04-12 11:19:04 +01:00
nicktrn 63a643b7c9 v3: fix digest extraction (#1024)
* fix image digest extraction

* fix project ref cli arg override

* Create late-steaks-behave.md

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2024-04-12 11:10:52 +01:00
nicktrn efd970a901 v3: correctly handle triggering tasks prior to deploy (#1019)
* add waiting for deploy status

* sort tasks filter

* marqs: optional timestamp on enqueue

* add new status to consts

* detect and execute tasks waiting for deploy

* display runs list even without any deploys

* ensure we only execute after the run creation tx has completed

* ensure correct execution order after waiting for deploy
2024-04-12 11:03:22 +01:00
Eric Allam 89a5e9f7da Move gc to it’s own admin endpoint 2024-04-11 16:24:40 +01:00
James Ritchie 404931e224 Made the message when you’re in a developer preview project punchier 2024-04-11 14:34:45 +01:00
Eric Allam 57bf98307a Run gc before taking heapsnapshot 2024-04-11 13:53:14 +01:00
Eric Allam 7551adfeb6 Add ability to disable tracing to test if it’s the cause of the memory leak 2024-04-11 13:14:02 +01:00
Matt Aitken 69117e8ba1 Re-arrange the mint.json file so the v3 docs become the default 2024-04-11 11:22:18 +01:00
Eric Allam b580d53b59 Better identifiy heap snapshots 2024-04-11 11:13:36 +01:00
Eric Allam d81e21d2ec Remove admin config endpoint 2024-04-11 10:44:26 +01:00
Matt Aitken 826a64fe6f If your dev run hasn’t started, display an info panel saying you need to run the CLI 2024-04-11 10:36:44 +01:00
Eric Allam d1849b0ea9 Adding admin config endpoint (temp) 2024-04-11 10:30:45 +01:00
Eric Allam 3aa634d2b8 Add a metric for number of event repo subscribers and project subscribers 2024-04-11 10:30:37 +01:00
Matt Aitken 7de3fb01c7 Added more docs for replaying a run 2024-04-10 18:35:43 +01:00
github-actions[bot] 4ae9a3feac chore: Update version for release (beta) (#1023)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-10 18:04:20 +01:00
Matt Aitken 5b18298fef Multiple machine CLI support (#1022)
* If a cli PAT exists, associate the authorization code with it

* Improved the error messages
2024-04-10 17:59:21 +01:00
nicktrn 7a9bd18ba2 v3: stop swallowing deployment errors and display them better (#1020)
* exit worker with code 111 for handled errors

* task monitor will ignore previously handled errors

* fix logging of index errors

* deployment error component

* changeset
2024-04-10 17:58:51 +01:00
Matt Aitken 03af44e545 Improved the title of one of the debugger scripts 2024-04-10 11:23:17 +01:00
Matt Aitken 5776257663 Changed the Discord link to use the trigger.dev one. Mainly to bump the GitHub action 2024-04-10 11:08:56 +01:00
Matt Aitken d3997c9fc6 Merge branch 'main' into changeset-release/main 2024-04-10 10:20:56 +01:00
github-actions[bot] 0676ea9668 chore: Update version for release (beta) (#1013)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-10 10:14:00 +01:00
github-actions[bot] 7a4721e122 chore: Update version for release (beta) 2024-04-09 16:44:12 +00:00
Eric Allam a5aed0d139 Fix memory leak by calling punsubscribe instead of unsubscribe
Also adding a /metrics endpoint with a few custom metrics and the built-in prom-client ones
2024-04-09 17:42:28 +01:00
Eric Allam f1480595d5 Stop swallowing webapp logs when the span isn’t being recorded 2024-04-09 17:11:09 +01:00
Eric Allam 328947dbfd Use the dashboard url instead of the API url for the View logs link 2024-04-09 15:15:16 +01:00
Eric Allam 279717b092 v3: pnpm deploy & various fixes for dependency resolution (#1012)
* Don’t swallow some error messages when deploying

* Try and resolve dependency versions using pnpm/npm/yarn

* Adding some debug logs around dependency resolution

* Use npm list instead of npm show to resolve deps

* Improve the dependency resolution
2024-04-09 15:03:31 +01:00
Matt Aitken 702d198445 Latest lockfile 2024-04-09 09:25:28 +01:00
github-actions[bot] 803f3c15ab chore: Update version for release (beta) (#1010)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-09 09:24:46 +01:00
nicktrn 1c24348f7d v3: add openssl to prod image and fix deploy command auth via env var (#1011)
* add openssl to prod worker

* make deploy command accept auth token via env var
2024-04-08 19:28:35 +01:00
Matt Aitken f854cb90eb Replay\Cancel a run (v3) (#1006)
* WIP on replaying a task from the run page

* Don’t pass the existing runs idempotency key, it will cause the replay to always return the original run

* Replay from the run list

* Don’t use fetchers in the replay/cancel dialogs

* API endpoint for replaying a run

* REST API docs (mostly coming soon) but added replay run

* replayRun function added to the SDK

* Cancel run added to the SDK

* v3-catalog file to test canceling and replaying

* Changed the SDK to be runs.replay and runs.cancel

* Removed comment

* Latest lockfile
2024-04-08 19:08:44 +01:00
github-actions[bot] 7268f17b00 chore: Update version for release (beta) (#1009)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-08 14:11:17 +01:00
nicktrn 624ddce32f v3: fix prod worker node_modules permissions (#1008)
* set node user prior to npm install

* changeset

* add ffmpeg and ffprobe catalog entries
2024-04-08 14:05:05 +01:00
Matt Aitken 9be1557bb7 CLI v3 binary changed from trigger.dev to trigger.dev, to fix a Windows issues (#1007)
* Changed the v3 CLI binary name from trigger.dev to triggerdev to fix a Windows issue

* Changed the exec to triggerdev
2024-04-08 14:03:12 +01:00
nicktrn 6ce6f8e3ad fix lockfile 2024-04-05 16:51:10 +01:00
github-actions[bot] d462b7a51b chore: Update version for release (beta) (#1001)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-05 16:45:38 +01:00
nicktrn f2894c177a switch to busybox and only call post start hook for restore (#1005) 2024-04-05 15:47:58 +01:00
Matt Aitken e35f29764a We want retrying enabled in dev by default, it’s confusing otherwise (#1004) 2024-04-05 14:45:19 +01:00
nicktrn 1207efbbad v3: prod image upgrade and fixes (#1003)
🚢 Publish Infra Images / build (coordinator) (push) Has been cancelled
🚢 Publish Infra Images / build (kubernetes-provider) (push) Has been cancelled
* fix shutdown after final attempt

* fix workdir permissions

* correctly handle self-hosted deploy errors

* switch to node:20-bookworm-slim

* add binaries catalog file

* changeset

* skip recommended packages

* post start hook retries

* comment and improve lifecycle retry
2024-04-05 13:09:07 +01:00
nicktrn 7ea8532cce v3: crash observability (#1002)
* indexing resource limits

* refactor and storage limits

* handle and display worker crashes

* enable prod cancellation

* fix reconnect delay

* improve crash messages

* log and display crash events

* changeset
2024-04-05 13:00:20 +01:00
Eric Allam 6642228f26 Fixing the dev & shared queue consumer telemetry so we can see what’s going on 2024-04-04 17:54:33 +01:00
Matt Aitken d39145d810 Defer migration guide: string not a date in the payload 2024-04-04 17:03:22 +01:00
Matt Aitken 8886bb76e0 Defer migration guide v1 2024-04-04 17:02:15 +01:00
Matt Aitken 4b72726078 defer.run migration guide 2024-04-04 17:02:15 +01:00
Eric Allam 6dcfeadaca v3: pnpm support (#1000)
* WIP fixing pnpm nested install strat

* Add changeset

* Pass (and log) cwd during background worker initialization

* Log out the env

* manually add the .pnpm/node_modules to NODE_PATH if in a pnpm repo

* Remove supports color dep
2024-04-04 16:13:04 +01:00
Matt Aitken ae839ebe11 Renamed Limits to “Limits & Performance” 2024-04-04 11:17:02 +01:00
Matt Aitken 5d0d71c2ae Added a section on upgrading your project 2024-04-04 11:17:02 +01:00
James Ritchie 1239a3ceb9 V3 project labels (#998)
* Added a side menu label to indicate your project version

* Added a link to request access to v3

* Toggle password visiblility of the env var inputs
2024-04-04 09:53:59 +01:00
Matt Aitken dd31b1e668 Fix for absolute URL from card 2024-04-04 09:23:40 +01:00
James Ritchie a707446989 Fixed Triggers pages not scrolling (#999) 2024-04-04 09:18:18 +01:00
Matt Aitken eb050f6730 Fix for typo on triggering page. “yourTask.batchTriggerAndWait” -> “yourTask.batchTrigger” 2024-04-04 09:12:29 +01:00
Matt Aitken 56d9bf7c67 Started the v2 -> v3 docs 2024-04-03 19:40:19 +01:00
Matt Aitken 73e469daf5 Added a known issues page to the docs 2024-04-03 14:30:43 +01:00
Matt Aitken 0382cf8719 Fix for bad tests link 2024-04-03 14:16:46 +01:00
Matt Aitken 0fe835492d Added more to the feature matrix 2024-04-02 19:47:55 +01:00
James Ritchie 29b69160e1 Fix for run page not scrolling the full runs content 2024-04-02 19:02:35 +01:00
Eric Allam ae9efe3d8b Added an error property to the problem JSON response 2024-04-02 17:46:40 +01:00
Eric Allam 3feb5ffb5f whitelist more api paths in the rate limiter 2024-04-02 17:29:53 +01:00
Eric Allam 7fb482de64 Allow OPTIONS requests in the rate limiter 2024-04-02 17:08:43 +01:00
Matt Aitken 6f11584aaa Remove our PostHog analytics from the docs 2024-04-02 15:35:36 +01:00
Matt Aitken 43e240cd50 Absolute link to v3 docs from v2 docs home, to fix nav issue 2024-04-02 15:30:44 +01:00
Matt Aitken afe7f410c7 v3 docs improvements (#993)
* WIP on adding versioning to the docs to make it less confusing

* Link to v3 from v2 and vice versa. Also added a warning to the v2 docs

* Make v3 the default

* Trigger config docs about bundling

* Next stpe to triggering guide from tasks overview

* Server actions guidance for triggering

* Moved the trigger.config docs to the end of fundamentals
2024-04-02 14:32:28 +01:00
nicktrn 28837f39b3 Prevent crash on upgrade errors 2024-04-02 13:58:40 +01:00
Eric Allam 5c64cefaf0 Fix pnpm lock file 2024-04-02 13:25:05 +01:00
github-actions[bot] dc5ed0a0cd chore: Update version for release (beta) (#995)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-02 13:24:32 +01:00
Eric Allam e7e7397ed9 Force CLI change 2024-04-02 13:20:26 +01:00
Eric Allam 49184c7189 Add trigger.dev changeset 2024-04-02 13:03:37 +01:00
Eric Allam eb60126284 Fixed batched otel in dev and made prod configurable to be batched as well 2024-04-02 12:58:56 +01:00
Eric Allam d876c358d2 Update the default env var concurrency limit and set them when orgs and envs are created 2024-04-02 11:55:00 +01:00
Eric Allam 6e9c8ab555 Fix pnpm lock file 2024-04-02 11:13:31 +01:00
github-actions[bot] 9a3eb289cd chore: Update version for release (beta) (#992)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-02 11:12:56 +01:00
nicktrn 51315fc3c8 v3: shared queue pool (#994)
* configurable retry delay checkpoint threshold

* shared queue consumer pool

* add more attributes to marqs spans

* inject trace context into queued messages
2024-04-02 10:22:52 +01:00
Eric Allam 4047f00562 Allow each service to define their own name 2024-04-01 22:01:36 +01:00
Matt Aitken 545f85b44e Fix for shared queryKey between useRunDetails and useRunStatuses 2024-04-01 13:20:39 +01:00
Eric Allam abe202e7b7 Fix pnpm lock file 2024-04-01 10:54:29 +01:00
github-actions[bot] ae27fd83af chore: Update version for release (beta) (#987)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-04-01 10:53:45 +01:00
Eric Allam c702d6a9ca v3: better task metadata errors (#991)
* v3: better handle task metadata parse errors, and display nicely formatted errors (dev, deploy, UI)

* Add changeset
2024-03-31 21:47:05 +01:00
Eric Allam 9af2570da6 Retry 429, 500, and connection error API requests to the trigger.dev server 2024-03-31 16:06:12 +01:00
Eric Allam a946797d95 v3: Upgrades to MarQS (#989)
* Upgrades to MarQS

- It’s “queue choosing” algorithm is now MUCH better (pretty much didn’t work before) and should be performant even when we have a bunch of prod queues
- There are now concurrency limits at the environment and organization level, as well as the task/queue level. So if any of them are at capacity the message won’t be dequeued. This means we can have an org wide concurrency limit, as well as different limits for dev/prod/staging
- I’ve added an admin API that can be used to update the org/env concurrency limits

* More MarQS upgrades

- Extract the queue priortity choosing strategy into an interface
- Implement a much better weighted average strategy
- “Slide the window” of queue candidates if the parent queue sends all at-capacity queues (so we won’t get stuck attempting to choose the same 12 full queues)
- Added some unit tests for the priority stuff
- Added some ideas for expanding the priority choosing strategy with more dynamic features

* Fixes an issue with the shared queue consumer relying on the queue name to get the env id
2024-03-31 15:58:00 +01:00
Eric Allam 8c4df326cc v3: Better dev/deploy errors and handle image build errors (#988)
* Better error output when an ESM only package is required

* Add better errors for npm package errors, and bring deploy errors to the dev CLI

* Handle depot build errors and write out a temporary file to view the build logs

* Add changeset
2024-03-29 12:46:11 +00:00
Eric Allam 11b997d2bf Make env var value input fields passwords 2024-03-29 09:05:53 +00:00
Eric Allam 8694e573f5 Fix CLI logout and add list-profiles command 2024-03-28 22:18:15 +00:00
Eric Allam b271742dca v3: implement configurable log levels via config file and env var (#985)
* v3: implement configurable log levels via config file and TRIGGER_LOG_LEVEL

Also, test runs automatically set the TRIGGER_LOG_LEVEL to debug

* Fix type error and changeset

* Added a Node.js runtime check for the CLI dev command
2024-03-28 22:00:38 +00:00
Eric Allam 6f9f25481e Update pnpm lock file 2024-03-28 19:55:14 +00:00
github-actions[bot] 67aaffb6fc chore: Update version for release (beta) (#984)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-28 19:54:21 +00:00
Eric Allam e3cf456c69 v3: fix string and non-standard outputs (#983)
* Fixed string outputs missing and incorrectly formatted

* Handle non-serializable outputs like a function

* Add changeset
2024-03-28 19:51:29 +00:00
Matt Aitken bf7827e7b8 Fix for the test latest runs showing other environments 2024-03-28 18:14:47 +00:00
Eric Allam bc020a3ffe Get the internal telemetry ready for test/prod 2024-03-28 18:12:01 +00:00
Eric Allam b361afbfe4 Update pnpm lock file 2024-03-28 16:29:17 +00:00
github-actions[bot] a3d809740d chore: Update version for release (beta) (#979)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-28 16:28:41 +00:00
Eric Allam f93eae300e v3: superjson dynamic import and deploy fixes (#982)
* v3: Dynamically import superjson and fix some bundling issues

* Added changeset

* Better error handling in the registry proxy and catch uncaught exceptions and unhandled promise rejections instead of crashing the server

* Await the prettyPrintPackage
2024-03-28 16:22:00 +00:00
Matt Aitken a2365e406d Fixed v3 docs link in the sidebar 2024-03-28 14:46:47 +00:00
Eric Allam 42d319c2d1 Remove all the v3-catalog code for triggering in code 2024-03-28 14:33:01 +00:00
nicktrn b66d5525ef v3: machine config (#978)
* add and use machine config

* assign tasks to worker nodes only

* add secure flag to zod connection

* changeset

* add pre stop hook

* don't use secure connection by default

* pass more identifiers to provider and apply labels
2024-03-28 14:21:49 +00:00
Eric Allam 719c0a0b94 v3: better clock management for spans/logs in CRIU envs (#980)
* durable clock WIP

* Fixed incorrect span timings around checkpoints by implementing a precise wall clock that resets after restores

* Add changeset
2024-03-28 14:20:44 +00:00
Matt Aitken f1c768a255 Docs for API keys, fixed links to docs from app (#981)
* Add missing API keys docs and link from the web app to them. Renamed Server API keys to Secret keys

* Correct link to env var docs

* Duplicate image fixed on environment variables docs
2024-03-28 14:00:42 +00:00
Matt Aitken d9c9e80bc4 Changed "Worker" to "Version" in the CLI dev command key 2024-03-28 12:13:58 +00:00
Matt Aitken d39932ebf7 Changed the throttle so the function fires at the end of the period, not immediately when first called 2024-03-28 12:05:48 +00:00
Matt Aitken 9bcb8cb42a Ignore the DEBUG env var when deploying 2024-03-28 11:28:34 +00:00
nicktrn 2374f8e8ac fix docs for shopify scopes 2024-03-28 09:57:04 +00:00
github-actions[bot] a22b5869e4 chore: Update version for release (beta) (#977)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-27 19:43:19 +00:00
Eric Allam f1571cbfab Fixed an issue where the trigger.dev package was not being built before publishing to npm 2024-03-27 19:39:18 +00:00
Eric Allam 222dfed4d2 Fixed pnpm lock file 2024-03-27 18:56:10 +00:00
github-actions[bot] 89c0e68fb5 chore: Update version for release (beta) (#975)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-03-27 18:54:28 +00:00
Eric Allam 5b745dc1a4 Improved the dev CLI output 2024-03-27 18:36:52 +00:00
Eric Allam 2dea8dec35 Implement simple 7 day log retention and blank states (#976) 2024-03-27 17:22:16 +00:00
Matt Aitken 252f5b3967 Fix for janky scrolling on the run page 2024-03-27 16:55:03 +00:00
Eric Allam 014d233339 Couple changes to better test the output/payload offloading 2024-03-27 16:27:45 +00:00
Eric Allam e398bdf859 Only use 16vcpu on e2e 2024-03-27 16:27:28 +00:00
Matt Aitken 426316aa3c There was an error about a div being in a paragraph 2024-03-27 16:23:11 +00:00
Matt Aitken 4f9b8d6721 Task that logs a lot 2024-03-27 16:22:29 +00:00
Matt Aitken a345ad2d57 Fix for the large JSON generator 2024-03-27 15:49:46 +00:00
Matt Aitken e2b67400ea TRIGGER_API_URL defaults to https://api.trigger.dev 2024-03-27 15:18:40 +00:00
Eric Allam c4dc2849af Remove changesets from the pre.json (accidentially added) 2024-03-27 15:17:42 +00:00
Eric Allam a8263dec86 Include core-apps in trigger.dev typecheck tsconfig file 2024-03-27 15:01:02 +00:00
Eric Allam 53054d0146 Enter into changesets “beta” tag for packages 2024-03-27 14:55:14 +00:00
Eric Allam 74236ae7c1 Fix changeset workflow (thought I’d already fixed this?) 2024-03-27 14:47:42 +00:00
Eric Allam 055d468b38 Setup socket.io redis adapter and fix deployment builds for superjson error 2024-03-27 14:42:10 +00:00
Matt Aitken fc473105e3 Better error messages if you haven’t set the API URL or SECRET for the v3 client 2024-03-27 14:08:13 +00:00
Matt Aitken 3a35d60091 Change the npm tag from "latest" to "beta" in docs/cli/onboarding (#974)
* The v3 init command defaults to the “@v3” tag

* Change it to beta

* Updated the docs and in-app docs

* Updated GitHub action
2024-03-27 13:39:53 +00:00
Eric Allam f11c0f991b Log out the headers and url when no key is found 2024-03-27 13:30:47 +00:00
Eric Allam 1cf181fd02 Control api rate limiter logging through env vars 2024-03-27 12:42:05 +00:00
Eric Allam 412d0149d5 Fixed release workflow 2024-03-27 12:37:23 +00:00
Eric Allam d614c8d2ca More CI fixes for node 20/pnpm 8 2024-03-27 12:33:24 +00:00
Eric Allam 4329d1130a Attempt to fix typecheck 2024-03-27 12:30:54 +00:00
Eric Allam 17f9fc8273 Upgrade to pnpm 8.15.5 to fix ERR_INVALID_THIS issue
https://github.com/pnpm/pnpm/issues/6424
2024-03-27 12:27:19 +00:00
James Ritchie db611bebba Text truncation fixes (#973)
* Span titles and code blocks truncate when window is small

* Tree view toggle arrow doesn’t have red hover state if row is an error
2024-03-27 12:16:20 +00:00
Eric Allam 215b60c742 v3: superjson output support (#971)
* superjson output support

* Better support for superjson in the task events, limiting output attributes

* Offload large outputs to object store (r2)

* Finishing up the offloading of large outputs/payloads to an object store
2024-03-27 11:57:22 +00:00
Matt Aitken 9c89ab40aa Throttle the live streaming of the run to 1 second updates (#972) 2024-03-26 14:20:10 +00:00
Matt Aitken b342e06583 Fix for scrolling with long run traces 2024-03-26 11:30:05 +00:00
Eric Allam 4418de515b Whitelist api endpoints that don’t use an authorization endpoint from the rate limiter 2024-03-25 21:18:05 +00:00
Eric Allam 0d2a71c5cf handle when traces/logs don’t have traceIds/spanIds 2024-03-25 21:10:31 +00:00
Eric Allam 9e02b45808 Fixed export 2024-03-25 17:24:23 +00:00
Eric Allam 395abe1b92 v3: Various fixes to support papermark use-case (#970)
* Adding a changeset for v3

* Add a version field to @trigger.dev/core-apps package.json

* Build trigger.dev when doing a prerelease

* bundle @trigger.dev/core-apps with trigger.dev cli

* Fix the init command config template

* Don’t use * for the @trigger.dev/core dep version specifier

* strip workspace: from the package version before installing it

* Added dependenciesToBundle config option to bundle ESM only packages

* Added logging around resolving dependency paths

* Try again

* Resolve dependencies based on the project dir first

* flip the bundled default

* Adding some logs around dev task completion notifications

* Adding some additional logs

* Add more logs

* Write out the log using process.stdout

* Store pending completion notifications and resume them when awaited (fixes race condition)

* Cleanup some of the logs

* Copy over the postinstall step from the projects package.json

* Add support for including additional files when deploying (e.g. prisma schema)

* Don’t run scripts when resolving deps

* copy all the files just in case anything is needed in postinstall

* Remove duplicate option

* Use the tag when outputting the dev command

* Remove the postinstall script

* add the trigger dir to the config if the default is not chosen

* Remove the “hud” display in the dev command

* trigger file names with dashes now work

* Better file watching in dev

* Much better duplicate ID experience now

* Much better “Project not found” error

* Export the handleError function types from sdk

* Add support for configuring instrumentation

* Upgrade and unify @opentelemetry/* packages (and remove storybook from the webapp)

* Fix typescript error in react package

* Upgrade react types in webapp

* Allow span icons to be determined based on the span name (e.g. prisma:)

* Ignore built-in env vars when checking for env vars, and allow continuing the deployment even if missing env vars were detected

* Improve the retry.fetch default behavior and option structure

* Fixed typescript errors with packages/email react types

* Update the retry.fetch docs
2024-03-25 17:02:49 +00:00
Matt Aitken b35eebb666 Rate limit API requests and changed SQS reading speed (#969)
* Trying to use the @upstash/ratelimit package with ioredis…

* WIP using the redis package instead

* Revert the action back

* Removed redis

* Started refactoring

* SQS setting for the poll interval. Set the default queue reading to be slower

* API rate limiter as Express middleware

* Organise imports

* Fixed spelling mistake “limitter”

* No authorization header response is problem+json
2024-03-25 16:39:20 +00:00
nicktrn 9ecf07731a v3: small features and fixes for prod infra (#968)
* add checkpoint restore events

* fix retries.enabledInDev

* fix tsconfig paths

* fix provider build and dev

* update kubernetes provider and fix builds again

* upgrade prod base to node 20

* update infra publish workflow

* rethrow k8s errors after logging

* shorten index container names

* fix error type assertion

* rename type assertion

* remove resource limits for now

* add missing run id on create

* add push to deploy command for self-hosting

* checkpointing fixes

* update coordinator image

* ensure valid registry login

* delete checkpoint archive after successful push

* log options on error

* structured logs for socket connections

* fix structured log merge

* exit process after checkpointing

* update restore pull secret name

* append shortcode to restore names

* log handler payload

* disable post start lifecycle hook

* pass in coordinator host via volume

* replace dapi with taskinfo

* add missing restore label

* don't restart restored containers

* remove init container from create

* atomic post-completion checkpoints

* switch to run id for container names

* improve wait accuracy

* measure basic checkpoint perf

* always log disconnect reason

* use system clock to end wait spans

* checkpoint readiness and cancel signals

* restore from checkpoint events and fix statuses

* remove attempt id env var

* restore dependencies from events

* reconnect wip

* lifecycle hooks are back

* fix hooks and improve reconnect

* make docker send postStart hook

* only checkpoint for retry if large delay

* fix a few more resume issues

* lifecycle hook fixes

* skip connection handler when waiting for post start hook

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2024-03-25 16:28:56 +00:00
Matt Aitken b890a64046 The in-progress stripes are much more subtle 2024-03-25 16:20:51 +00:00
Matt Aitken 4266b308e7 Link from trigger() to a run. Link back to the triggering run. (#967)
* Schema for SpanMessagingEvents

* RunFilters status map was missing the key

* Link from a trigger to the run

* Two-way links working
2024-03-25 11:28:35 +00:00
Matt Aitken 67c62f7d25 v3 is restricted to approved orgs (#965)
* v3 projects can only be created if the org has permissions to do it

* Admin page

* Removed unused classes

* Admin org page, with links between user and org pages

* Set v3 enabled or not
2024-03-25 11:28:21 +00:00
Matt Aitken c6d6a9191c Hide show.actions from the properties panel (#964) 2024-03-22 19:53:28 +00:00
Eugene Yaroslavtsev cd8f6b9af0 fix: [nestjs integration] fastify HTTP adapter detection now works correctly for response headers (#938)
* fix: [nestjs integration] fastify HTTP adapter detection now works correctly for response headers

- fixed a bug where Fastify responses were incorrectly processed as Express due to overlapping method names.
- introduced type guards to differentiate between Express and Fastify response objects.
- bumping @trigger.dev/nestjs patch version to 2.3.19

* fix TS type check build error
2024-03-22 14:41:21 +00:00
Kritik Jiyaviya a49b659701 feat: Ability to revoke an invite to an org (#902)
* feat: Ability to revoke an invite to an org

* Resolve a conflict with main

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-03-22 14:35:49 +00:00
Edward Fu 61c9a7c7d6 Fix opanai code example in docs (#961) 2024-03-22 14:17:37 +00:00
Matt Aitken de302858f8 v3 docs (#929)
* Started building out the docs navigation

* Drafted out a lot of the docs pages. With just titles and descriptions with a coming soon message for now.

* A ton more scaffolded pages with titles, descriptions, coming soon/incomplete docs messages

* Created the remaining page stubs

* Introduction page improvements

* Lots of docs changes, mostly the task overview page

* Moved some bits around

* Task overview fleshed out

* Triggering docs page

* Regular task page

* CLi dev docs

* Docs for debugging locally

* Environment variables docs

* Added env var images

* Deployment guides

* Updated the title of “Integrations” to “Deployment integrations” to make it less confusing

* Lots more docs pages

* Changed the language to JavaScript

* Fixed typos about queues and added a simple code sample

* Moved the local debugger docs into the CLI dev page

* Added the CLI deploy options

* Delete the local debugger page

* Updated the logging page with structured logging

* Added the new CLI deploy options

* Change to h4 for one of the options

* Errors page

* WIP on retrying

* Retrying guide

* Wait docs pages

* Queuing docs simplified, partial written

* Queuing and concurrency docs

* Run tests docs

* New combined error and retrying page

* Errors and retrying page updated

* More docs

* Added a possible configurations coming soon table

* Created a limits page

* Added warnings about how you need to get early access

* Minor fixes for the docs
2024-03-22 14:09:27 +00:00
Matt Aitken cf9d466b9e Basic JSDocs for the v3 SDK (#963)
* task(), retry and queue

* Added machine JSDocs

* Add JSdocs for the run function params
2024-03-22 14:09:06 +00:00
Eric Allam 7b3ffe040b v3: config file is now ts by default and uses named exports (#962)
* A bunch of changes to the config file:

- No more default export, the config is exported via the `config` named export
- `handleError` is moved to a separate named export
- Added the ability to include additional packages (e.g. wrangler) that aren’t included by default (think CLI usage)
- More reliably install packages in dev
- The config is now built first instead of directly imported, meaning we can now support typescript config files (`trigger.config.ts`)

* Update to trigger.config.ts in `trigger.dev init`
2024-03-21 10:40:44 +00:00
Eric Allam 737ff9928c When cancelling a run in the UI make sure the task run status is cancelled not interrupted 2024-03-20 13:22:50 +00:00
Eric Allam fc4b95d69e A bunch of deployment fixes (#960)
- Time out deployments to prevent never-ending building/deploying
- Use the CURRENT worker deployment when determining which version to execute
- Fix some of the deployment error handling logic
2024-03-20 13:15:48 +00:00
James Ritchie 6c546936f3 Improved v3 feedback button (#959)
* Removed feedback button from PageHeader

* Show a different feedback button in the side menu for v3 projects

* Fixed issue with button wrapping on smaller width browser
2024-03-20 12:16:20 +00:00
James Ritchie 08e4fc002f V3 UI improvements (#958)
* Adding a v3 feedback button top-right

* Changed paused to frozen for attempts

* Reordered and renamed run statuses

* Dropdown status menu shows tool tips on hover

* Added a new DP feedback button in the header

* Created a more useful feedback sheet

* Added loading bar animation to storybook

* Switch the integration page to point at the “feature” help instead of “integration” which has been removed

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-03-19 20:36:04 +00:00
Eric Allam 0e347b001b Don’t override TRIGGER_SECRET_KEY and TRIGGER_API_URL with local env vars 2024-03-19 16:04:31 +00:00
Matt Aitken 2e56af9742 Tasks page live-reloads with new tasks (#957)
* DevPubSub: use the schema that’s already been defined

* Publish a message to projectPubSub when a new DEV worker is created

* Live reloading of the tasks table (for dev tasks)

* Live notifications for deployed workers as well as local workers
2024-03-19 15:42:57 +00:00
Eric Allam dc5eb68a0b Fix typecheck errors because of resolveJsonModule 2024-03-19 15:33:09 +00:00
Eric Allam 891278ab1f Enable loading package.json inside of core 2024-03-19 15:24:01 +00:00
Eric Allam 41e1ac9e0b v3: nanosecond precision task events and immediate mode for dev events (#956)
* Store startTime in nanoseconds since epoch, ensure logs using nanosecond precision for their timestamp (so they are not out of order)

* export task events immediately in dev
2024-03-19 15:06:47 +00:00
Matt Aitken c5aaabdb4e The run timeline updates on the client if there's no new data (#955)
* Use “@v3” instead of “@latest” for the npx commands for v3

* Split the Timeline into a component so it can live refresh without re-rendering everything

* Timeline now live refreshes on the client every 500ms when run is executing

* The timeline bars now animate their position/width when it changes

* Export some more types from TreeView
2024-03-19 12:13:48 +00:00
Eric Allam affa3f25ee Trying beefier buildjet machines for CI 2024-03-19 11:38:48 +00:00
Eric Allam 86c24afb44 Support json traces and logs in the otel endpoints (#954) 2024-03-19 10:59:50 +00:00
Eric Allam 6afda40c35 Add depot setup action 2024-03-19 09:24:33 +00:00
nicktrn b585d1f2c5 v3: checkpoint restore events (#951)
* add checkpoint restore events

* fix retries.enabledInDev

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2024-03-19 09:02:56 +00:00
Eric Allam f26ba9a5cd Use depot.dev for docker builds (remove publishing to latest for now) 2024-03-18 20:52:08 +00:00
Eric Allam ba0ffacb15 Set the OTEL_EXPORTER_OTLP_ENDPOINT env var on dev workers 2024-03-18 20:16:25 +00:00
Eric Allam e55ca0279b Adding profile support to the v3 CLI (#953) 2024-03-18 17:35:29 +00:00
Matt Aitken 9304c447be Test, output and canceling improvements (#952)
* The vertical lines in the run tree view are now brighter

* Blank state when you click a task with no runs

* Canceling from the runs table

* Fix for styles coming through incorrectly to properties

* Fix for the OTEL output column having a $output prefix if it’s an object
2024-03-18 17:27:52 +00:00
Eric Allam ebec14093d Add healthcheck endpoint outside of remix if remix routes are disabled 2024-03-18 17:19:56 +00:00
Eric Allam 67cac97b26 Add DEPLOY_REGISTRY_HOST to allow configuring the deploy registry via the server 2024-03-18 15:56:28 +00:00
Eric Allam 0f32dee0eb Prevent depot command from displaying update message 2024-03-18 15:32:26 +00:00
Eric Allam 479d355b7b Setting DASHBOARD_AND_API_DISABLED=true will now disable the remix routes 2024-03-18 14:59:21 +00:00
Eric Allam 49e9dd8cb2 Disable fetch experimental warning and detect process resources (#950) 2024-03-18 13:46:24 +00:00
Matt Aitken cae3298564 Cancel run confirmation modal (#949)
* Tasks get the SHOW_ACTIONS property

* Override properties with the passed in ones in eventRepository

* Link from deployments to environment variables page, no need to link to docs

* “Show parent items” keeps the selected item selected

* LinkButton can accept onMouseDown, onMouseEnter and onMouseLeave

* “Show parent items” keeps any items focused and has a keyboard shortcut

* Action bar with focus button

* Canceling is working

* Nicer layout and button loading and disabled state

* US english spelling “Cancelling” -> “Canceling”

* Added a confirm modal to canceling

* Copy tweaks

* Fix for bad import

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2024-03-18 12:22:06 +00:00
nicktrn 1f190fe680 v3: fix dependency resume (#946)
* fix basic resume mechanics

* fix dependency resume

* fix deploy page sort

* remove task list console log

* checkpoint restore between attempts

* add checkpoint requirement checks to docker provider

* switch to raw execa for long statements

* catch and report pre-connection index errors

* graceful worker shutdown after completion

* fix final completion

* use same task process for each attempt

* update retry catalog entry

* add immediate return task

---------

Co-authored-by: Eric Allam <eric@trigger.dev>
2024-03-18 12:21:40 +00:00
Matt Aitken 85ec1af198 Don’t add proj_ to the front of the project ref 2024-03-18 11:05:09 +00:00
Eric Allam 52c364d691 v3: cli init command + CLI telemetry (#948)
* Adding telemetry to the deploy command

* Add ability to opt-out of telemetry in the CLI

* Remove log

* Unifying some telemetry stuff and adding it to the login command

* init command

* Remove extra trigger dirs

* Couple tweaks to the init CLI

* Don’t use npm init -y to create the package.json file
2024-03-18 10:12:11 +00:00
Matt Aitken a5d83971aa Cancel a run from the span view (#947)
* Tasks get the SHOW_ACTIONS property

* Override properties with the passed in ones in eventRepository

* Link from deployments to environment variables page, no need to link to docs

* “Show parent items” keeps the selected item selected

* LinkButton can accept onMouseDown, onMouseEnter and onMouseLeave

* “Show parent items” keeps any items focused and has a keyboard shortcut

* Action bar with focus button

* Canceling is working

* Nicer layout and button loading and disabled state

* US english spelling “Cancelling” -> “Canceling”
2024-03-17 11:42:30 +00:00
Matt Aitken 5b9c67aeef v3 deployments page (#945)
* Set the “current” deployment in WorkerDeploymentPromotion when a new deployment is completed

* Deployments page added to sidenav

* Basic deployments page working

* Pagination for deployments

* Right-align the pagination controls

* Improved the blank state

* Selected deployment panel

* Improved the side panel
2024-03-15 16:04:01 +00:00
Matt Aitken 1c98eb2b61 Use TaskRunStatus (instead of TaskRunAttemptStatus) (#944)
* Using the new run status instead of run attempt status

* The test page now uses the TaskRunStatus as well

* Organized imports

* Use TaskRun icons instead of attempt ones

* 10x zoom on the run timeline
2024-03-15 10:32:07 +00:00
Eric Allam f424c81086 No staging by default, and project external refs now are prefixed with proj_ 2024-03-14 15:11:31 +00:00
Eric Allam 0a33bf7206 v3: handle errors and customizing retrying (#943)
* Add the ability to handle errors at the task and project level

* Cancel in progress runs when disconnecting the dev CLI (in between attempts)

* unify the task executor across dev & prod
2024-03-14 14:38:13 +00:00
Matt Aitken 819b663ad7 Test page environment selection (#942)
* useLinkStatus hook

* Now you can customize the appearance of InlineCode

* Created <TaskFunctionName/>

* The test page now has an environment selector at the top
2024-03-14 13:54:47 +00:00
Eric Allam 478ce006cb v3: task run status and canceling runs (#941)
* WIP task run status, revamped resuming task dependencies

* Don’t select a span when toggling collapsing

* Cancel runs and attempts, in prod and dev
2024-03-13 15:51:43 +00:00
Eric Allam fe9435f63f Allow alternate config file names and skipping using a config file by passing —project-ref (#940) 2024-03-11 21:31:15 +00:00
Eric Allam d7cc2c9d6c v3: task payload refactor and configurable default retries (#939)
* Make the payload parameter the first argument to the task functions

* Allow configuring default retry behavior, and disabling in dev
2024-03-11 20:30:29 +00:00
Eric Allam 851b1769cb v3: use structured logging in a few places 2024-03-11 15:53:24 +00:00
Eric Allam e8381d5341 v3: Correctly handle tasks that have no output when resuming 2024-03-11 15:43:45 +00:00
nicktrn 20aa1cbe9b v3: checkpoint and restore with sim for local dev (#933)
* zod ipc connection with acks

* pass sender through to ipc handlers

* bits and bobs

* add host networking back in

* disable verbose logs

* restore after tasks and batches.. almost

* restore and resume all the things

* fix for systems without checkpoint support

* Get deployment indexing errors to work with the new ZodIpc stuff

---------

Co-authored-by: Eric Allam <eallam@icloud.com>
2024-03-11 15:20:33 +00:00
Eric Allam 883feab257 v3: various deploy improvements (#936)
* Cache the dependency resolution step of deploys

* Better deploy output and fixed an issue with deleting env vars
2024-03-11 14:31:55 +00:00
Eric Allam 83304f86f8 Capture uncaugh exceptions during indexing and fail deploys, with error output (#934) 2024-03-10 20:57:46 +00:00
Eric Allam 5d78bba5e3 Edit env var panel submit button Edit -> Save 2024-03-08 14:55:41 +00:00
Eric Allam e87a0cba1d v3: cli deploy improvements (#932)
* Add support for deploying to staging and prod

* Abort deployment if environment variables are missing

* Actually do typechecking

* Remove the build command and add a —self-hosted option to the deploy command
2024-03-08 14:52:46 +00:00
James Ritchie 8852d5b388 Callouts can handle inline children elements 2024-03-08 14:47:37 +00:00
James Ritchie 79ea8edc7c Table rows have a specified group class to fix conflicts with nested groups 2024-03-08 14:47:01 +00:00
James Ritchie 553370a9e5 secure clipboard fields show fixed number of “•••” 2024-03-08 14:45:53 +00:00
Eric Allam 47c18d9146 Fixed trigger.dev dev command 2024-03-08 11:16:56 +00:00
Eric Allam c385db63be v3: cli deploy command (#931)
* WIP proxy/deploy

* WIP, registry proxy in express working

* A couple of notes, preparing for indexing

* Move the changes to prod-worker into the new file

* Deploy command working with indexing and runs (docker provider only for now)

* Removed ts-expect-error directive

* Fixed build command
2024-03-08 10:49:42 +00:00
James Ritchie 86b2674e68 Updated login page (#928)
* WIP new login page

* Remix meta v2 implemented on the root page

* Added a spinner colour that works on our primary green

* Added new company logos

* Improvements to the login page

* Updated the meta function so the login page is responsive

* Fixed issue with the new logos not colouring correctly

* Login page now nicely responsive

* font size fix

* Spacing improvement

* Improved style of the relative time  dropdown

* Fixed viewport meta on login pages

* oranised imports

* improved the Sheet and feedback form

* Text area style update

* Feedback form tweak

* New project copy change: Project type -> Project version

* Runs filters use the correct variant

* Improved the select style

* Inputs now styled like Selects

* Removed login form from storybook

* Popover style tweak

* Popover looks like other filters

* Removed gap from filters and organized imports

* Cleanup

* Organized imports

* Made the inline code block smaller

* Fixed active badge label not being readable

* Fixed hero icon inside the button in the welcome page

* Fixed the filter button variants on the v2 runs page

* Fixed the select styles on the v3 runs page

* Improved the switch

* Fixed the filter styles on the events page

* Run page summary panels look good

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-03-07 10:35:52 +00:00
James Ritchie 161b2b3323 V3 style improvements (#926)
* Added more clipboard variants to storybook and improved styling

* Improvements to the clipboard components

* Code blocks match the design

* Improved the code block styles

* Dialog modal improvements

* Improved the free plan usage bar

* Better alignment of the shortcut icon in the button

* Side menu displays ‘v3’ next to the project header

* Page header improvements

* Project dropdown displays a badge if it’s a v3 project

* billing page now shows message

* Added the v3 badge to the project list page

* version 3 projects skip the select plan onboarding

* Added a new blank state to the runs page

* Conditionally set the blank state on the runs page

* Button padding tweak

* Updated the task and attempt icons

* Added a new blank state to the runs page

* Added more buttons variants to the button storybook

* Added new blank onboarding state for the tasks page

* Added a blank state to the test page

* Fix for bad svg attribute in TaskIcon

* Onboarding tweaks

* Add the projectRef to the init command

* Task icon is blue

* Added a v3 Project settings page

* Fix for typecheck error

* Added the new CodeBlocks with rowTitles to the span panel

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-03-06 18:06:20 +00:00
nicktrn 9b6f8f9238 v3: provider and coordinator updates (#927)
* add zod socket

* start using zod socket

* use zod socket for shared queue

* use shared provider shell

* update k8s provider task ops

* set otlp endpoint

* update docker actions and fix builds

* remove unused types

* update injected secret key env var name

* complete socket.io types to schemas migration

* update env example to new v3 key var

* fix coordinator build

* set task run label

* ensure attempt id is always set

* increase prod worker timeout

* set otlp endpoint for on runs

* pass otlp env var to prod worker

* auto-remove completed index jobs
2024-03-06 16:01:59 +00:00
Matt Aitken f50cee66d9 Upgraded to the latest Resend package 2024-03-06 15:18:56 +00:00
Matt Aitken 44d443a048 v3 live run reloading and minor style improvements (#925)
* Initial work creating the Redis publishing and subscribing

* Live view is working

* Show the live reloading status on the page

* Fixed some style issues on the run page with James

* Fix for invalid JSX attributes in the ExitIcon svg

* Some sexy shit

* The end line is now correctly coloured

* millisecondsToNanoseconds exported from core/v3 and imported correctly

* Fix for e2e tests, we changed the h1 to an h2

* Tidied imports

* Removed unused hook
2024-03-06 09:48:00 +00:00
Matt Aitken 2a1273b683 Major v3 web app update (#924)
* Added the new colours to the Tailwind config

* Fixed Tsailwind compile errors

* WIP Geist working in the app

* WIP Storybook

* Storybook is working again… ouch

* Use Geist mono for CodeMirror

* Some find/replace class changes

* Resizable colours improved

* WIP on primary button

* Minor style improvements

* Improve the side menu header styling

* Improved v2 breadcrumbs

* Account side menu tweaks

* The page now works with the NavBar and UpgradePrompt

* Removed unused import

* Refactored the buttons to be dry-er

* Removed the breadcrumbs

* WIP on nav bar

* WIP updating the button styles

* Fix for the old test page

* Fix for type errors

* Removed console.log

* Colour change in the resizable handle

* New loading bar divider

* Removed the design plugin

* Creating our own storybook pages

* Added some “storybook” pages

* Added DetailCell storybook

* WIP new animation for the loading page

* Added the new loading divider

* Fix for the time frame filter having a green border

* Style improvements to the new test page

* Small style improvements

* Improvements to the list pagination components

* Nav bar back button improved

* Improvements to the run page

* Lots of v2 style improvements

* Help looks better

* Improvements to the regenerate API key modal

* More general improvements

* Added section titles to our storybook

* Added form stories

* Fix for missing key prop

* Loading bar is working

* Fixed button submitting state

* Fix for the test button icon

* Code bg improved

* Improved oauth buttons

* Integration page header fix

* Various improvements, mainly changing button variants

* Segmented control style updates

* Added an outline of 3px for the segment control

* Fixes for the billing pages

* More pricing improvements

* Added dialog to storybook

* Typography now in storybook

* Free usage bar added to storybook

* Added inline clode to storybook

* Separated menu types into a sub section in storybook

* NamedIcon now in storybook

* Added page header to storybook

* Added pricing callout to storybook

* Added radio groups to storybook

* Added segmented controllers to storybook

* Added shortcuts to storybook

* Added switches to storybook

* Added toast to storybook

* Added tooltips to storybook

* Added tree view to storybook

* Added usage charts to storybook

* Tarted up the environment variables page

* Fix for the FreePlanUsage panel bg colours

* Added new badge variants

* Added the <TaskPath /> to the tasks table

* Span header improvements

* Started work on the timeline

* Started work on the timeline

* Fix for the run page header

* Timeline tick marks are working

* Timeline working

* Got the durations showing on hover

* Button improvements

* Experimenting with how the duration should be shown

* Lots of refinements to the timeline

* Much nicer API for the Timeline

* The switch is now purple to match the design, with inverted thumb when on

* Removed old stuff

* Export the props

* Added the span with duration back in

* Simplified more and fixed the span durations

* Put in some decent dummy data

* Rendering defaults

* Wip with the mouse cursor

* Improvements to the story

* Added Slider primitive

* Integrated the icons into the slider

* Lots of layout improvements

* Cleaned up imports

* “Root” indicator

* Animated background on partials

* Pull the styles through to the spans and log dots

* Fixed some bugs in the TreeView when nodes get created or destroyed

* Fix for incorrect parentTask reference

* Added run streaming endpoint for live refreshing

* Added the tabs to Storybook

* Fix for status font size mismatch

* Fix for the misaligned run filter status

* Set a minimum duration on the timeline

* The TreeView now re-calculates if the number of nodes has changed

* Partials now render to the end

* Improved the durations gutter

* The duration is calculated using the current time if there are partial events

* Added the environment label to storybook

* Improved the environment label style

* Removed bottom margin from badge

* Button style improvements

* Callouts style fits the new design better

* Got the scrollbars to appear on the tree/timeline

* Added scroll support

* Synced scrolling working

* Close button and exit icon for the detail panel

* secure field shows start of env

* Clipboard improvements

* Latest lockfile

* Fix for the durations wrapping

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2024-03-04 17:33:53 +00:00
Eric Allam 64401ee8ec TRIGGER_API_KEY -> TRIGGER_SECRET_KEY in v3 2024-03-04 15:47:58 +00:00
Eric Allam b7845685eb v3: no bundle builds for the dev CLI (#923)
* WIP no bundling

* Convert dev CLI to use an unbundled build process to support otel instrumentation

* Fix pnpm lock file

* A couple of fixes to get typechecking to work
2024-03-04 15:36:09 +00:00
nicktrn 52c9d485f8 v3: cli build command, prod runs, checkpoints (#919)
* fix trailing slash in api url

* add maybe platform down error

* shorten config path

* extend protobuf compiler install instructions

* build command and image model

* new image triggers task indexing

* index support for prod builds

* shorten example provider secret

* multi-stage task prod build

* lock prod tasks to node 18 image

* extract shared build and dev command libs

* pull out more shared deps

* add coordinator and providers

* fix core-apps build

* add dev builds for new apps

* fix cwd

* enable corepack

* some build fixes

* enable buildkit for old docker versions

* coordinator image fixes

* update provider containerfile

* build dev images in parallel

* upgrade pgadmin

* fix prod facade build

* prod runs

* fix merge

* don't knock out platform on invalid attempt id

* fix prod facade

* rename to build.ts

* fix prod builds

* set to executing after fetching payload

* make prod worker listen on random port if in use

* remove experimental warnings in dev

* prod resume

* prevent execution after completion

* exit prod worker after completion

* always restart otel collector

* docker checkpoints and prod runtime messaging

* don't retry indexing without chance of success

* make platform checkpoint aware

* deploy with existing hash sets latest worker

* log restore requests

* only try to checkpoint long waits

* tidying up

* lockfile

* fix build

* prod worker merge fixes

* fix prod complete and cancel

* fix lua nil checks

* socket namespace abstraction

* cleanup

* make all build args optional

* add build script

* don't require env vars for dev

* fix schema

* prod merge

* small fix

* bind correct logger

* fix v3 ref catalog entry

* resume prod batch

* pass socket to error and disconnect handlers

* fix non-batch resume

* fix batch resume

* send connection env vars when not in dev

* create worker via socket

* move api client back into v3 cli

* fix lockfile

* fix resume with failures

* marqs replace message

* typecheck prior to build

* don't define api url in prod builds

* support prod retries after resume

* skip typecheck option
2024-03-04 13:10:07 +00:00
Eric Allam ca47e6bdcd v3: cli cancel improvements and add back in deprecating background workers (#918)
* Show runs as cancelled when killing the dev CLI

* Fixed error when waiting for a task

* Deprecated workers will no longer be able to run unlocked task runs

* Fixed selecting the latest background worker version in test list

* Don’t propogate trace context when triggering an async task

Also add batch id to the context and the task events
2024-02-29 15:34:00 +00:00
Eric Allam 933cf0f119 v3: run.isTest now propagates through child tasks and the trace (#917)
* run.isTest now propagates through child tasks and the trace

* Try to fix the pr checks docker hub rate limit error
2024-02-28 17:01:31 +00:00
Eric Allam b6517af522 v3: Cancel dev runs when the dev CLI exits (#916)
* Cancel dev runs when the dev CLI exits

* Clear out in progress attempts after cancelling them
2024-02-28 16:00:39 +00:00
Matt Aitken 479445f741 V3 Test feature (#915)
* Added isTest to TaskRun

* TriggerTaskService now accepts isTest and adds it to TaskRun if set

* Set the cliVersion and sdkVersion when indexing

* Added a test page

* Radio buttons are now circles and accept a ReactNode

* The background of the code editor is now darker

* WIP on the test task page

* Improvements to the test page

* Testing is working

* Fix typo

* Show the real isTest value in the runs table

* Added a key to the outlet so it correctly resets all the state on the sub-route
2024-02-28 15:52:24 +00:00
Eric Allam 1fabcf68fa Override local env vars with env vars in the server (#914) 2024-02-27 15:44:55 +00:00
Matt Aitken d7c79ee651 V3 API keys page and Environment Variables (#907)
* New API keys page working

* Added EnvironmentVariable and EnvironmentVariableValue tables

* Environment variables presenter and repository started

* Icon now accepts a ReactNode as well

* The create form is working

* Improvements to validation

* Getting all the environment variables is working

* Editing an env var working

* Fix for deleting a value from an env var

* Separate route for adding new env vars. Works with “Save and add another”

* Editing is working properly, and revealing all values

* Deleting env vars

* Get environment variables with the environment id

* Added th env vars count to the Environment variables page

* Removed the commented out old Env & API keys side menu item

* Fix imports in ClipboardField

* Added a storybook page for all the variants of input fields

* Upgraded Tailwind for the :has selector

* Fix for the edit button not filling the width

* Reworked the input fields so they work with a variable width icon on the left

* Improvements to the new env var modal

* Improve the style of the edit environment variable panel

* Fix for when Input is type=“text”

* Icon now works with FunctionComponents and ComponentTypes properly

* Removed a console log

* Removed unused imports

* Use a const schema for SecretValue

* Added friendlyId to EnvironmentVariable
2024-02-27 14:35:43 +00:00
Eric Allam 8d6e710dc2 V3: retry utilities (#913)
* WIP

* retry.fetch w/intercepting to test

* Fixed the incorrect renaming of limit to maxAttempts in v2

* Fixed source map support in dev

* Cleanup background worker files once they close
2024-02-27 13:54:51 +00:00
Eric Allam 90a302f9f7 v3: batch trigger (#908)
* Support for batch triggers

* Various trace fixes and improvements

* Moved trace into the logger, fixed span cardinality issues with waits and triggers

* Add support for attaching a debugger in dev with —debugger flag
2024-02-26 11:21:06 +00:00
Matt Aitken 07efef405d v3 span details (#906)
* WIP on saving the resized state in a cookie

* Progress on remembering the panel width

* The resizable panel now remembers even when closed

* Improvements to the span panel

* Hide integrations in the v3 side menu

* Added “UTC” to the times

* WIP changing how styles work

* Reference unflattenAttributes from the package

* Unflatten now correctly unflattens arrays

* Unflatten typecheck fix

* Improvements to the spans and UI for them

* Added the “events” to a span, including special styling for errors

* Unflatten doesn’t work on an array of Attributes
2024-02-23 09:54:01 +00:00
Eric Allam dd63fe6e9f v3: Implemented in-process task retries in dev w/cache support (#905)
* Implemented in-process task retries in dev w/cache support

* Improve the stack trace correction
2024-02-22 10:12:23 +00:00
Matt Aitken d8c645a3f0 Fix for projectVersion input name change 2024-02-22 09:18:52 +00:00
Eric Allam 24600d2c01 Fixed unFlattenAttributes import 2024-02-21 20:15:06 +00:00
Matt Aitken 584936fa29 Early v3 project UI (#904)
* Added ProjectVersion to projects, defaults to V2

* Moved v3Enabled to the existing feature flags

* Update to using the v3Enabled feature flag

* Allow people to choose v3 when creating a new project

* Added version to the ProjectPresenter

* v2 project and v3 project redirecting

* .env.example for the v3-catalog

* Added sdkVersion and cliVersion columns to the BackgroundWorker table

* Added additional classes for environments

* First draft of the Tasks table

* Link to the task page

* V3 side menu project items

* Moved the ListPagination component into the components folder

* Moved the TaskListPresenter to a v3 folder

* Bare bones task page with tabs

* Task page, we’re going to delete this though

* Bare bones runs table working

* Rejigged the columns

* The run table status

* Environment and status filtering working

* Added time filters

* Cursor and direction is working… I think it’s tricky to know for sure

* Added TaskRun numbers

* Selecting a task now links to the runs page with filters turned on

* Added support for the enqueued status

* Reworked the task table

* Link to the task and environment runs

* The run page is rendering a tree of the events

* Change the task table column to “Created at"

* WIP on making the run tree view look good

* Improvements to the run tree

* Removed the janky scroll bar flash

* Change the title of the task logs to just the task ID

* Live timer when a span is running

* Added “Show parent items” link

* Fixed the bug jumping to parent items

* Style improvements to the run

* Added the resizable handle to the run page

* Moved formatDuration to core/v3

* Wait for now has nice log messages

* The run detail panel is working with just a title for now

* Navigating to a span and persisting between page reloads is working

* The run detail timeline

* Wrap log dates in a paragraph

* Latest span detail view

* Scrolling in the right-hand panel

* Tweak default resizable layout for the run page

* Attempted improvements to stop a recursive issue on TreeView

* TreeView useReducer WIP

* Changed the change callback

* Add changes to the state

* Use the new onSelectedIdChanged in the app

* Don’t update the state from the outside

* Filtering fix, although navigation doesn’t work nicely

* Filtering working when changing the content and clearing it

* Don’t allow the same selectedId callback to be called twice…

* useDebounce hook

* Switch from using defer to just typedjson for now

* Latest attempt at span navigation

* Removed log

* Turn off filtering for now, it’s causing the Links to break somehow

* Fix for page height issue

* Added (Developer Preview) to the v3 project select box

* Revert "Filtering working when changing the content and clearing it"

This reverts commit 20d9fbe36ded619e9d3eb0b23d4ed0568a88a615.

# Conflicts:
#	apps/webapp/app/components/primitives/TreeView/TreeView.tsx

* Switch to using the old filtering

* Added useThrottle hook

* Instantly close the panel when deselecting a node, use debounce when navigating to a span

* Better spacing in the right hand panel

* Comment out the v3 side menu pages that don’t exist yet

* Fix for typecheck fail

* Clear the statuses too
2024-02-21 18:42:12 +00:00
Eric Allam a54bdb23bf Fixed the Docker build (error in generate-protos.mjs) 2024-02-20 13:31:16 +00:00
Eric Allam 07f7c65054 v3 queue system (#903)
* Introducing Modular Asynchronous Reliable Queueing System (MarQS). Works in dev

* Convert MarQS to using lua and dealing with concurrency

* Simplified the timeout queue and current concurrency is now a set instead of a flat value (to support idempotency)

* Implement task heartbeating and reconnect the background workers CLI when the websocket connection reconnects

* Start adding internal telemetry support for the server

* Get env vars to work in dev and implement prisma tracing in webapp

* Cleanup telemetry and implement it in the consumer

* Implement dequeuing a message from a parent shared queue

* Implement a custom logger exporter instead of using console log exporter

* Use node instead of shell for generating protocol buffer code

* Propogate trace context into debug logs, and allow turning off logger exporter through env vars

* Switch to using baselime for internal otel data

* Make orgMember optional to fix type issues

* Provide the CLI dev env vars through the CLI, don’t build dotenv into facade

* Removed the logger import

* Address Matt’s comments

* Addressing more of Matt’s comments

* Handle sending an execution after a websocket connection closes

* Remove auth from the env attributes to prevent obfuscation
2024-02-20 12:16:41 +00:00
Matt Aitken d04c8e89f6 Added a “repo-token” to the Install Protoc GitHub action steps
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-02-19 14:15:15 +00:00
Matt Aitken b69902dd84 Deduplicate integrations in the JobListPresenter (#901)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 6s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 1s
🚀 Publish Trigger.dev Docker / units (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-02-19 13:13:28 +00:00
Eric Allam 2aabb994cf Install the protobuf compiler in the docker builder stage 2024-02-12 16:58:57 +00:00
Matt Aitken 310d51bac0 Tree view component (#900)
* WIP creating a TreeView component

* Very simple tree displaying

* WIP on TreeView types

* The state is computing properly

* Improved the state and types

* Virtualized rendering

* Added state inside the useTreeState hook

* Selection working

* Deselecting nodes

* Toggle selection

* Expanding/collapsing nodes

* Get notifications when changes are made

* Only try show the visible items

* Experiment to try getting cell animations working

* Renamed hook to useTree

* Keyboard navigation is working

* Proper focus support

* Nice selection of the parent by pressing left

* End selects the last visible node

* Showing how the TreeView can accept a selected id and expanded ids from the outside

* The useTree hook now uses selectedId and collapsedIds to make it easier to use

* Check the inputs are valid before applying them, ignore if they’re not

* Don’t allow a selected node to be hidden by collapsed parents

* Nicer API for the onChange callback

* Supports animated collapsing of the tree view

* Nice smooth scrolling

* Removed logs

* Removed unused key

* Remove intricate estimation

* StandardTreeView has lots of good defaults baked in

* Allow passing of parent class name in

* Work on scrolling to the node… needs a bit of a reshuffle

* Just make the TreeView better rather than adding StandardTreeView

* Renamed rowVirtualizer to virtualizer

* Move the virrtualizer into the hook

* Scrolling to selection is working

* Added filtering
2024-02-12 16:43:47 +00:00
Eric Allam 6be1099a12 Don’t git submodule in docker 2024-02-12 14:53:03 +00:00
Eric Allam baf3a84cda v3 dev cli command + more (#894) 2024-02-12 14:24:32 +00:00
Matt Aitken 70f9bd0d70 Latest lockfile 2024-02-12 13:11:14 +00:00
github-actions[bot] a1860dbaae chore: Update version for release (#899)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-02-12 13:00:14 +00:00
Matt Aitken d69e4e712d OpenAI integration: retry 400 status code because OpenAI returns this sometimes for no reason (#898) 2024-02-12 12:48:48 +00:00
Matt Aitken 7fae67c47d Fix/autoyield canceled run (#890)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / units (push) Failing after 16s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 20s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Todo for the fix

* If the run has been canceled during execution, don’t do any further processing of the run
2024-02-09 11:06:19 +00:00
Matt Aitken 9ae0ca64af Fix edge cases with deleting last org/project (#892)
* If you have an org with no projects, it displays in the project dropdown with a “New project” button

* When creating a new org disable the button whilst it’s doing the request

* If an org already had any deleted projects it couldn’t be deleted…

* When selecting the best project, factor in deleted ones

* Don’t show the cancel button when creating a new org if there are no non-deleted projects

* If a project has already been deleted just return
2024-02-09 11:05:28 +00:00
Matt Aitken da69fa0613 Fixes #886. Removed “public” schema from the JobListPresenter query
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 20s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-02-07 16:48:18 +00:00
Matt Aitken 336029b842 Organization renaming, deleting and one-click email unsubscribe (#885)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / units (push) Failing after 10s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Added the org settings page to the sidebar

* Added loading states when renaming/deleting projects

* Don’t show deleted orgs in the app

* The actual db migration file

* The Org settings page with the actions working

* Don’t remove org members, just leave them

* Don’t show invites from orgs that are deleted

* Allow disabling IntegrationConnections

* Don’t refresh IntegrationConnections that are disabled

* Set all the integrations as disabled

* Updated the unsubscribe checkbox text

* Unsubscribe route

* Use the magic link secret, not the encryption key. Also make the error message more vague

* Only members of the org or project can rename them

* Don’t throw an error if the connection can’t be refreshed, return undefined instead
2024-02-07 10:52:50 +00:00
Matt Aitken 29edcd3df9 Rename and delete projects (#880)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Side menu: selector title changed to project. Changed section headers and made it Slack + Discord

* Added project settings page. Renaming is working

* Added project.deletedAt column

* Deleting projects WIP

* Allow clearing the project from the session

* Don’t load projects that are deleted

* Improved the project selection logic

* Clear the session project id when deleting a project

* Deleting the last project in an org now works. The new project page doesn’t have the sidebar anymore.

* Removed false code comment

* Added the JobRun index back in, using Prisma. Otherwise it tries to remove it on each migration

* Only return environments where the project isn’t deleted. This will block API calls

* Do the project deletedAt check in code, not SQL

* Made it clearer what the code does with a comment and applied the same logic to the public api key
2024-02-05 13:14:33 +00:00
Matt Aitken a9ff32418e Fix for when there are no jobs…
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-01-30 17:35:04 +00:00
Matt Aitken 7358fcb891 Latest lockfile 2024-01-30 17:07:24 +00:00
Matt Aitken 28052daad9 Faster jobs page (#879)
* Optional next/previous with the list pagination

* Defer the loading of the runs table

* Only return the latest run in a separate query, then do a join in code

* Added a composite index to speed up getting the latest run from a job id
2024-01-30 17:02:04 +00:00
github-actions[bot] 364c8c5f7f chore: Update version for release (#876)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-30 13:36:36 +00:00
Matt Aitken 4b3b418abb Set endpoint URLs to null, instead of deleting them (#878)
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Added Endpoint deletedAt column

* Only show endpoints where they’re not deleted

* Don’t delete Endpoints, set the deletedAt and change their slug name

* Only perform indexing if the endpoint isn’t deleted

* Have a nullable URL for endpoints

* Deal with null URLs throughout the app

* Re-running and retrying behaves properly when there’s no endpoint URL

* Remove console.log

* Better error message when doing a run
2024-01-30 10:45:12 +00:00
Matt Aitken 2e354d342c Deleting endpoint working (#875) 2024-01-29 11:57:25 +00:00
Matt Aitken dd879c8e4a Fix api run statuses (#874)
* Added a subtask for testing

* Make it easier to run the CLI from the nextjs reference project

* Copies of the run and statuses endpoints, but without simplifying the run statuses

* Use the new v2 endpoints that give the full run statuses

* Removed unused import

* v2 events endpoint with the full run status info

* Changeset
2024-01-29 11:42:19 +00:00
Matt Aitken af485b9180 Fix custom oauth client (#872)
* A checkbox can now be readonly and not be checkable, with correct styling

* Use readOnly for the hasCustomClient checkbox, not disabled

* Better styling of the disabled state

* The update oauth form too
2024-01-26 17:25:15 +00:00
Matt Aitken a739ebaa88 Tweaked the layout of the usage runs charts so the daily runs are in the box with other run charts 2024-01-26 15:05:52 +00:00
Kritik Jiyaviya 3ebc2578e0 feat: Add daily runs graph (#865)
* feat: Add daily runs graph

* Merge branch 'main' into feat/daily-runs-graph

* update DayRunsChart

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-26 15:00:30 +00:00
Kritik Jiyaviya 0b657b33f9 Allow retrying a job run with an invalid payload (#869) 2024-01-26 12:39:23 +00:00
Erin Allison 7ac942dc0e Address unintended type coercion in PageInfoPropertyComponent (#861)
Fixes triggerdotdev/trigger.dev#858

Signed-off-by: Erin Allison <erin@eallison.us>
2024-01-26 09:44:55 +00:00
Matt Aitken 9b12016428 Improved SQL reads for some dashboard pages (#868)
* Pass subscription status into the usage bar

* Page navigation spinner is now blue (was a bit subtle before)

* Better logging of db queries, this will be commented out before the PR is merged

* Select only the required fields

* We don’t need the member count for each org

* WIP redirecting with projectId in session

* Switching projects is now working, without duplicating the project query

* Removed logs in revalidate function

* Removes some unused imports

* ProjectPresenter: removed lots of unused db selects

* Root use defaultShouldRevalidate, not just true

* Simplified the job list query and separated the deleting job modal query

* Use requireUserId instead of requireUser wherever possible

* EventListPresenter query simplified

* Simplified the RunListPresenter query

* Disable query logging

* Use the latest updated version for the job list table

* We need to use the org presenter on the select plan page
2024-01-26 09:41:11 +00:00
Matt Aitken d6b44de4ba Defer the loading of the usage data (#866)
🚀 Publish Trigger.dev Docker / units (push) Failing after 10s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 20s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Updated to the latest remix-typedjson package

* Throw an error if the org isn’t found

* Use defer. Doesn’t work because Date isn’t deserialized correctly

* Use regular defer, typeddefer isn’t working properly…

* Don’t update remix-typedjson, wasn’t needed

* Organize imports
2024-01-22 10:26:33 +00:00
Matt Aitken 17df4839d7 Latest lockfile
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 5s
🚀 Publish Trigger.dev Docker / units (push) Failing after 21s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-01-21 17:30:21 +00:00
github-actions[bot] e3f78178f7 chore: Update version for release (#864)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-21 17:29:23 +00:00
Kritik Jiyaviya da90ee13c3 fix: Resend integration example comment (#860) 2024-01-21 17:16:26 +00:00
Matt Aitken 583da458ec Changed the minimum interval time period from 60s to 20s (with changeset) 2024-01-21 17:06:09 +00:00
Matt Aitken dcf95c4eb2 Revert "Changeset: Changed the minimum interval time from 60s to 20s"
This reverts commit c272e38de2.
2024-01-21 17:04:11 +00:00
Matt Aitken 32cf5790cb Revert "Changed the minimum interval time from 60s to 20s"
This reverts commit ca78ddc2c2.
2024-01-21 17:04:11 +00:00
Matt Aitken c272e38de2 Changeset: Changed the minimum interval time from 60s to 20s 2024-01-21 16:29:54 +00:00
Matt Aitken ca78ddc2c2 Changed the minimum interval time from 60s to 20s 2024-01-21 16:28:28 +00:00
Matt Aitken 07ed8c346a Fix for enabled env var in docs 2024-01-20 14:01:56 +00:00
Matt Aitken d4391f2e2d Fixed link in io.logger to the run log 2024-01-20 12:54:11 +00:00
Eric Allam 2c328ba93d Fix pnmp lock file again 2024-01-17 14:50:04 +00:00
github-actions[bot] 68dbc07ee8 chore: Update version for release (#854)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-17 14:49:19 +00:00
Eric Allam 58448243af Fix pnpm i 2024-01-17 14:41:51 +00:00
Eric Allam 6c4047cf21 Fix an issue where runs were stuck executing when a child task failed and the parent task retried 2024-01-17 14:39:06 +00:00
github-actions[bot] 831860eace chore: Update version for release (#853)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-17 14:13:34 +00:00
Matt Aitken db46f2a69a Add explicit return type to deprecated sendEmail function because tsup was complaining 2024-01-17 14:07:45 +00:00
Kritik Jiyaviya 4dd6cf18dc feat: Add support for the new Resend audience API endpoints (#850)
* feat: Add support for the new Resend audience API endpoints

* update pnpm-lock.yaml

* update pnpm-lock.yaml

* Merge branch 'main' into feat/support-for-resend-audience-api

* latest pnpm-lock.yaml

* Create lovely-items-end.md

* Update pnpm-lock.yaml

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-17 14:06:45 +00:00
Eric Allam adf66d23b8 Update pnpm lock file
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / units (push) Failing after 15s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-01-17 11:15:30 +00:00
github-actions[bot] 5c42831a60 chore: Update version for release (#846)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-17 11:14:52 +00:00
Eric Allam 26f5e7774d Fix yalt.dev connection timeouts by increasing timeout from 1s to 5s (#851)
* Increase the yalt tunnel connection timeout to 5 seconds

* Add changeset
2024-01-17 10:27:57 +00:00
Matt Aitken f209a3b364 Ability to disable organization runs + more obvious if you're over the free limit (#848)
* Fix for typo in error when a Job invoke fails

* Can disable runs for an Organization

* Don’t perform runs if runsEnabled === false for an Org

* Exceeded runs messages made into errors, they were very subtle

* Return the runsEnabled property for each org

* More obvious message if you’re over the free run limit

* Added a red border to the free usage panel if you’re over your run limit

* Added missing property to Storybook for the FreePlanUsage component
2024-01-17 09:42:58 +00:00
Son Yen Nguyen a93b554f8b Feat: Update cron parser human readable string (#847)
* Update cron parser human readable string

* Create hot-cobras-flow.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-16 17:22:35 +00:00
Matt Aitken 0f342cd1be Don't show duplicate Job warning if it's an internal job 2024-01-16 15:54:20 +00:00
Matt Aitken 7df2f85a1f Latest lockfile 2024-01-16 15:22:21 +00:00
Matt Aitken f14180d13c Also hide "dev.trigger.scheduled" events from the event list 2024-01-16 15:21:45 +00:00
github-actions[bot] ab6b9514cd chore: Update version for release (#844)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-16 15:00:28 +00:00
Matt Aitken 98345d67d9 Allow unchecked array access in the CLI tsconfig. This matches the other packages… 2024-01-16 14:46:31 +00:00
Matt Aitken 38f5a90399 Auto-yielding is skipped for tasks that are no-ops and subtasks 2024-01-16 14:01:05 +00:00
Matt Aitken 1b2635ae4a Don’t show “trigger.scheduled” events in the list 2024-01-16 12:14:08 +00:00
Matt Aitken 129f023d11 EventTrigger source wasn’t getting passed through to the class 2024-01-16 12:07:11 +00:00
Matt Aitken 795e637dec caniuse-lite updated, it was logging out an annoying message 2024-01-16 11:52:08 +00:00
Matt Aitken 5238c424fc Absolute date filtering (#845)
* WIP on absolute date filtering for runs

* Use the date hook instead

* Reworked the date field again so the state behaves nicely

* Way better date filtering

* Setting the absolute date is working well, also clearing filters

* Reverse date format

* Turn off the guide

* Added time filtering and clearing to the events page
2024-01-16 11:44:15 +00:00
Matt Aitken 1bbd7e6dc3 V3 CLI started, with Personal Access Tokens and Who Am I (#841)
* Initial CLI commit

* Hooked up the CLI so it actually shows stuff…

* Totally reworked the v3 CLI to be based on our existing CLI (Commander)

* WIP on PersonalAccessTokens and AuthorizationCodes

* WIP creating a Personal Access Tokens page. Created a new sidenav for account pages

* Creating tokens is working but the form is broken

* Tokens are created in the UI

* Creating and revoking access tokens from the UI is working

* Improved the create form and copy

* Tokens are a bit shorter and only lowercase

* API endpoint for creating AuthorizationCodes and the web page users hit to create PATs from them

* V3_ENABLED env var and hook that can be used in the UI to show/hide things

* API route to get a PAT (within 10 mins of creating an auth code). Moved some code to core

* Start to build the login command

* Nicer banner when starting the CLI

* Nicer update checking

* Update command style improved

* Removed the template step

* Login command options are now working

* The new CLI is logging in using the Personal Access TOken. But I need to save it still

* Logging in and saving the token is working

* Deal with already being logged in

* Who Am I working with PAT

* Deleted old account side menu header

* Improved the copy on the Auth code page

* Added docs for the login and whoami commands

* Added readme instructions for the update command

* Removed some unused things

* Remove fetchUseProxy for now
2024-01-15 14:45:41 +00:00
Kritik Jiyaviya 3bb82ed9a5 feat: runs filtering by relative timeframe (#832)
* feat: runs filtering by relative timeframe

* improve logic

* Used formatDateTime

* fix: logic of  determineTimeFrame() function

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-15 14:13:20 +00:00
Abhimanyu Yadav ff4ff869ab feat(logger): accepting Error objects as parameters in io.logger.error() (#797)
* feat(logger): accepting Error objects as parameters in io.logger.error()

* Allow errors for any log level

* Create silent-ties-vanish.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-15 14:02:41 +00:00
Matt Aitken 1dcee2b338 Changed docs analytics to PostHog EU 2024-01-15 13:51:02 +00:00
Aditya Tripathi 0a798446c8 feat: managed cloud check for search indexing (#825)
* feat: managed cloud check for search indexing

* fix: vice versa on the robots meta tag

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-15 09:35:43 +00:00
Kritik Jiyaviya 209942a63d fix: integrations list scrollbar (#829) 2024-01-15 09:29:42 +00:00
Manthan Mallikarjun 57a9b35870 Fix typo in deployment-automatic docs (#842)
Env var is wrong
2024-01-15 09:28:37 +00:00
Fabian B a16b65f666 docs: fix syntax error (#839) 2024-01-14 16:55:01 +00:00
Matt Aitken 5871745a92 Latest lockfile 2024-01-12 14:13:32 +00:00
github-actions[bot] 87b5dfbf11 chore: Update version for release (#837)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-12 14:10:42 +00:00
Michelle Rosenberger 5af2003516 Fix Stripe integration webhook validation (#836)
The SubtleCryptoProvider cannot be used in a synchronous context. This
is a problem for non-node environments where the Stripe client falls
back to SubtleCryptoProvider.

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-12 14:05:33 +00:00
Matt Aitken 85ce729bf2 Latest lockfile 2024-01-12 13:55:03 +00:00
Matt Aitken 5701d1da42 Reference the —https flag in the instructions if your endpoint isn’t found 2024-01-12 13:54:36 +00:00
Chigala bc61d83764 feat: updates CLI to use https flag (#814)
* feat: updates CLI to use https flag

* added changeset

* Added yalt to the changeset

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-12 13:53:43 +00:00
nicktrn 5bf125be0d Fix: helm chart and docs (#827)
* Improve helm chart and docs

* Minor docs changes

* Add alternative commands to specify values
2024-01-11 13:54:22 +00:00
Eric Allam babe1c0e54 Fix pnpm lock file 2024-01-10 10:58:07 +00:00
github-actions[bot] 1224fceb18 chore: Update version for release (#831)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-10 10:57:32 +00:00
Eric Allam 8277f4d249 Use correct overload param when invoking a job outside of a run (fixes #802) 2024-01-10 10:50:12 +00:00
Eric Allam 73cb8839a5 Fixed invoke inferred payload types (fix #830) 2024-01-10 10:44:35 +00:00
Matt Aitken 5d0a731cf6 Event page tweaks (#826)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 1s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 3s
🚀 Publish Trigger.dev Docker / units (push) Failing after 10s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Don’t show internal events

* Show the cancelled time

* Made the Pagination component accept any compatible list type

* Changed some wording on the event detail page
2024-01-05 12:39:27 +00:00
Kritik Jiyaviya 25a152517e feat: Events list page (#824)
* feat: add events list

* Changed the Events icon in the sidemenu

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-05 12:04:31 +00:00
Matt Aitken d1092fcd2c Run filtering now works on the job runs page too (#823)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 3s
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Run filtering is now shared: runs page and job runs page

* Use optimistic location

* Improved the type in the run status filter dropdown

* Organize imports
2024-01-03 15:50:45 +00:00
Matt Aitken 61d33ed1b8 Latest lockfile 2024-01-03 14:23:21 +00:00
github-actions[bot] 7a51612fc8 chore: Update version for release (#822)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2024-01-03 13:48:31 +00:00
Abhimanyu Yadav 4d380173c8 feat:runs filtering by status and environment (#800)
* feat: view teammates' job runs on dev env

* fix typechecks

* feat: add filter functionality on task run page

* feat:adding filter functionality on run task page

* changes filter from csr to ssr

* changing filter functionality from csr to ssr

* adding url.string() for navigation purpose

* improving state management in filtering

* When setting a filter, delete the cursor and direction

* Some design improvements for the "All" options

---------

Co-authored-by: hmacr <hmac.devo@gmail.com>
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-03 13:37:50 +00:00
Hemachandar 8880d8afe2 feat: view teammates' dev env job runs (#708)
* feat: view teammates' job runs on dev env

* fix typechecks

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-03 13:11:22 +00:00
Jan Henning ef037af457 Add a comment explaining that JSON parse middlewares need to come after the Trigger middleware (#773)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 3s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 20s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2024-01-03 11:19:34 +00:00
Dan 390ac6101e Added new http-endpoint examples, changed examples links in the docs (#775)
* updated companyicons package

* Changed custom help so it doesn’t show code examples

* Added Asana / Instagram / Salesforce / Segment / Square / Svix / Snyk / Todoist & Zapier http endpoint examples to the integration page

* Commented out some of the apis we dont have code examples for

* Uncommented raycast and reddit

* Updated the blank state copy

* Changed the copy so it works better on examples with and without code

* Added Brex / Discoed / Google Sheets, Docs, Drive / Gmail / PagerDuty / YouTube endpoint examples

* Added more examples

* Change the top tab to ‘Examples’ and updated /examples links to point to trigger.dev/apis

* Update package.json

* Updated pnpm-lock file

* Updated pnpm-lock file

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-03 11:18:44 +00:00
Dan aa97bf4a52 Changed posthog to eu (#772)
* Updated posthog url and key

* Create clean-plums-happen.md

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-03 10:43:14 +00:00
Matt Aitken 86d6e102a4 Added documentation for cancelRunsForJob 2024-01-03 10:38:23 +00:00
Matt Aitken adf497bc3e Example in the job-catalog of canceling all runs for a Job 2024-01-03 10:31:56 +00:00
Kritik Jiyaviya f7bf25f03f feat: Add ability to cancel all runs for job from SDK (#819)
* feat: Add ability to cancel all runs for job from SDK

* Create nine-trainers-vanish.md

* Cancel runs that are executing and waiting

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-03 10:30:19 +00:00
GuyBorderless f8cab96fa2 use --env cli flag for deno (#820)
* --env cli flag

* Update hono.mdx

* Update hono.mdx
2024-01-03 10:27:39 +00:00
nicktrn 225614fea3 Feature: ARM builds (#821)
* Add native ARM runner

* Switch to arch-agnostic manifest digest

* Set correct latest tag
2024-01-02 15:48:53 +00:00
Yash Khokhaneshiya 740b7b2385 feat: Add $not to eventFilters (#815)
* feat: Add  to eventFilters

* not filter test case added for false evaluation

* Added a patch changeset for @trigger.dev/core

---------

Co-authored-by: Matt Aitken <matt@mattaitken.com>
2024-01-02 15:43:02 +00:00
Matt Aitken 26d223ab36 Latest lockfile 2023-12-22 15:50:13 +00:00
github-actions[bot] 0c4fd9a631 chore: Update version for release (#813)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-22 15:43:15 +00:00
Matt Aitken 5060eec01b Update Octokit to account for CVE-2023-50728 (#812) 2023-12-22 15:35:47 +00:00
Matt Aitken aaea064208 Added “graphile” to the logs when they zodWorker starts, to make it easier for self hosters to debug 2023-12-22 10:46:05 +00:00
Matt Aitken 9346e4358d Latest lockfile 2023-12-22 10:43:33 +00:00
github-actions[bot] 3aafd0480b chore: Update version for release (#798)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-22 10:40:55 +00:00
Matt Aitken 771feb5395 Awaiting completion with threads/runs now works with the "requires_action" status 2023-12-22 10:13:44 +00:00
Matt Aitken 03703af682 Only append a search param if the value is defined 2023-12-20 11:06:40 +00:00
Eric Allam 5359af1242 Add logpush true to yalt wrangler 2023-12-18 10:58:30 +00:00
Eric Allam dfa47b6201 Don't proxy certain headers across the Yalt boundary as it can mess-up proxied local requests 2023-12-18 10:52:31 +00:00
Eric Allam c01138b56e Fix pnpm lock file for release 2023-12-14 17:27:45 +00:00
github-actions[bot] 70fdedcea5 chore: Update version for release (#796)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-14 17:27:08 +00:00
Matt Aitken 49ca4c4430 Fix for #731, integrations getting stuck if OAuth then moved to API key (#732)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 1s
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-14 15:58:50 +00:00
Eric Allam 812b5afe6f Add support for the built-in Trigger.dev tunnel for local development (#795)
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 3s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 13s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Add support for the built-in Trigger.dev tunnel for local development

* Remove the test script from yalt

* Add to the README

* Improve the outdated packages warning
2023-12-14 15:33:56 +00:00
Matt Aitken 922520cefb Fix for the overage estimation on the usage page always being zero
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-13 18:57:14 +00:00
Matt Aitken 4bd1786ae5 Billing (#789)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 5s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Initial commit - started work on new billing components

* Added a slider component

* Added features to the pricing tiers

* Small pricing tier margin tweaks

* WIP on a concurrecy chart

* Reworked the pricing tiers to include a segmented controller and tooltips

* Renamed the charts storybook page

* Made the way data is added more flexible and added some definition tool tips

* Term definitions are used properly in the tiers

* Callouts can now have an optional CTA on the right hand side

* Alignment fix for the callouts

* organize imports

* Definition tooltip now its own component

* renamed the storybook story

* WIP new volume discount table and usage sliders

* Added pricing calculator sliders

* Fixed alignment of the legend

* Breadcrumb now has an upgrade prompt and button

* New Join our Slack button in the side menu

* New progress meter in the side menu

* Use the highest of 2 values to show progress

* An attempt to fix the step count in the calculator slider

* WIP usage progress bar

* Added the 4 progress bars

* More examples of the usage bar

* Better way to include the percentage in the free plan progress meter

* The usage bar now works with the extra runs over the free limit

* Pricing calculator has better slider logic

* Moved the free plan usage bar into it’s own component and added it to storybook

* Usage bar chart now supports a paying customer option and optional billing limit. Also added more usage examples to storybook

* Added more examples of usage to storybook

* tooltip takes classname

* Format numbers nicely

* Added a tooltip to show the precise numbers in the chart

* small improvements to the billing calculator

* New onboarding choose plan page

* pricing tiers better fill the size of their container

* Removed unused code

* Usage bars animate

* Wording tweak

* Callouts fit the button size better

* Added new routes for the 2 new billing pages

* import cleanup

* Added meta info in the header for bill price, plan type and billing period

* made free a noun

* Added pricing calculator to the plans page

* Fixed some illegal markup when using tooltips

* Added container query support

* Added new concurrency chart to the usage page

* billing now has a green theme

* Simplified the plan summary info int the header

* Fixed padding alignment

* Use a custom lable for the concurrent runs chart

* Removed the Job runs table

* Latest lockfile

* Show a message if you haven’t done runs yet

* Added a layoutId to the pageTabs

* Show a message callout if you’ve exceeeded 10k runs on the free plan

* Added a callout on the plans page if you’re over the runs limit

* Fixed button inside button bug

* Removed the background gradients from the app

* The billing package is importing properly

* Getting the curent plan for an org

* Reading the current plan and usage

* Hooked up the free plan bar

* Render basic billing details

* vol discount table has optional values

* Added a new page to show new subscribers

* Created a new hook for confetti on the subscribed page

* Toast styling updated

* The Invoice and Manage card details links are working

* Meta appEnv data optional

* Data for the plans page

* Format the billing period duration in days

* Switch to 20 icons

* URL for the subscribed page now includes the org path

* New pathBuilder path for the subscribed page

* Plans are upgraded/downgraded successfully

* Fixed badly named paths

* Improved some of the display

* Deal with when the user has canceled so they can re-upgrade

* Subscribing from Stripe is working, and canceling

* Tidied up some bits, latest billing package

* The tiers are now rendering using the real data

* The onboarding screen is hooked up, but not linked to yet

* Onboarding price selection working

* Pricing slider working

* Price estimation working

* Pricing calculator working on the select a plan page

* Button copy change

* Improved the layout of the run calculator marker

* Fix for the period end when you’ve canceled

* Improved the formatting in the calculator

* Pricing table tooltip uses the vol discount pricing table

* Remove the vertical lines from the calculator

* Contact us button in Enterprise tier opens the contact us form

* Added composite index to triggerdotdev_events.run_executions for event_time and organization_id

* Concurrent run chart data

* Improves styling, fix for React error with Enterprise contact button

* Show warning box when you’ve hit the concurrency in the past 30 days

* Lots of work o the usage page

* Improvements to the usage page

* Show 31 days of data, fix for not showing the current date…

* Stripe portal links are generated when the user clicks through

* Better alignment of the reference line and x-axis label

* Readme update

* Fixed pricing button loading buttons

* Show warnings about concurrency and runs on the plans page

* Removed some storybook stories

* Join Slack channel shows if you’re subscribed with instructions

* Added a gap between the runs charts

* Improved the definitions

* Added some margin to the page loading spinner

* A wider, cleaner feedback panel

* Modal backgrounds match the Sheet style

* Fixed menu item text being clipped

* Improved icons for execution time and exclusion count

* Concurrency chart now renders the dates nicely

* Fix for plans data on the plans page

* The healthcheck doesn’t need to do a HEAD request to /

* Better disabled states and fixed the disabled hover state issue

* Improved the segmented controller style

* loading spinner now centered inside the button

* Redirect to the project page when selecting the free plan

* Fix for “Runs” and added real date to upgrade warning

* DeCAPITALIZED some things

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-12-13 12:48:26 +00:00
github-actions[bot] daae6df428 chore: Update version for release (#794)
* chore: Update version for release

* Update lockfile

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2023-12-13 10:23:36 +00:00
nicktrn fc31c6c07a Fix: Test package run isolation (#793)
* Fix link

* Move paths to compiler options

* Add failing test case

* Fix test isolation

* Add changeset
2023-12-13 09:49:52 +00:00
Eric Allam 6d4676f204 Auto update endpoint URL on redirect (#791) 2023-12-12 13:14:25 +00:00
Andreas Thomas 0a51ef3a06 fix: typo (#788) 2023-12-10 22:24:01 +00:00
Eric Allam 772f1b41a0 Fix pnpm lock file 2023-12-08 10:20:32 +00:00
github-actions[bot] d42ba80108 chore: Update version for release (#785)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-08 10:19:57 +00:00
Eric Allam 6a3c563f14 Fixed Job.attachToClient 2023-12-08 10:15:06 +00:00
Eric Allam c04cdfde8c Fix pnpm lock file 2023-12-07 13:00:32 +00:00
github-actions[bot] 750c1ff1e3 chore: Update version for release (#783)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-07 12:59:53 +00:00
Eric Allam 0f9f010206 @trigger.dev/airtable: Removed named imports (#782) 2023-12-07 12:53:58 +00:00
Eric Allam 11f8ff1bb4 Fixing endless retrying of non-successful run executions
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-06 21:01:41 +00:00
Eric Allam 85b3352764 Fix pnpm lock file 2023-12-06 20:05:49 +00:00
github-actions[bot] 9fb8dceef4 chore: Update version for release (#781)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-06 20:05:29 +00:00
Eric Allam 0c14e4cdfe Stop importing subpaths in @trigger.dev/airtable (#780) 2023-12-06 20:02:37 +00:00
D-K-P 2099c6308e Latest lock file 2023-12-06 15:45:43 +00:00
github-actions[bot] 08e6cad28a chore: Update version for release (#779)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-06 15:42:36 +00:00
Eric Allam f3efcc0c28 Moved Logger to core-backend, no longer importing node:buffer in core/react (#778) 2023-12-06 15:37:50 +00:00
Eric Allam 37ef335b66 Resolve pnpm lock file 2023-12-06 11:29:58 +00:00
github-actions[bot] 33d555d00e chore: Update version for release (#776)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-12-06 11:28:06 +00:00
Eric Allam 17f6f29d05 Feature: Support multiple runtimes other than Node.js (#774)
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 5s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-06 10:23:37 +00:00
Eric Allam 08f7c639ef Maximum background fetch timeout is now 5 minutes
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 1s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-04 15:02:15 +00:00
github-actions[bot] 1567239718 chore: Update version for release (#771)
* chore: Update version for release

* Release lockfile

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: nicktrn <55853254+nicktrn@users.noreply.github.com>
2023-12-04 14:14:41 +00:00
nicktrn de652c1dfb Fix: Shopify tasks and KV get() return types (#770)
* Improve KV get types

* Fix shopify find and all task return types

* Add changeset
2023-12-04 12:37:55 +00:00
Eric Allam 1f3733b70f Fix resuming timed out or auto-yielded executions
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / units (push) Failing after 21s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 21s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-12-04 09:20:40 +00:00
Dan b5aea6c534 Replaced showcase links -> api (#764)
* Updated the examples section with new links / changed showcase link to project showcase

* Added links to the api pages for all of our integrations

* Deleted card from the airtable tasks page
2023-12-01 17:35:54 +00:00
Eric Allam 0769dc4315 Fixed the event names for stripe docs 2023-12-01 08:42:05 +00:00
Eric Allam 5d00fc7cdb Update pnpm lock file for release 2023-11-30 21:54:43 +00:00
github-actions[bot] 00b0c3e02e chore: Update version for release (#765)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-30 21:54:13 +00:00
Eric Allam 7e3a82ef47 Issue #747: Add Stripe invoice triggers 2023-11-30 21:48:45 +00:00
James Ritchie 5dda6cd16c Added the border to the page header on the Runs page
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 3s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 21s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-11-30 10:32:38 +00:00
Matt Aitken 76b7fb2337 The status API endpoints return only the original set of statuses 2023-11-30 10:31:27 +00:00
Matt Aitken 68cbfd8d23 Log out the run status 2023-11-30 10:29:48 +00:00
Eric Allam 41a49f6bb2 Make the run list query more efficient
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 4s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-11-29 19:28:15 +00:00
Eric Allam 2f755158b4 Updated pnpm lock file 2023-11-29 11:25:27 +00:00
github-actions[bot] 419b93809d chore: Update version for release (#757)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-29 11:24:58 +00:00
Eric Allam bd4bc51daa Update plain (#762)
* updated the plain SDK

* Updated the action to support the new Threads SDK

* latest lock file

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-11-29 10:58:06 +00:00
Eric Allam ff540c9e4a Revert "Update plain (#761)"
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 3s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 5s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
This reverts commit 3f217ff3e0.
2023-11-29 10:51:13 +00:00
Eric Allam 3f217ff3e0 Update plain (#761)
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 5s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* updated the plain SDK

* Updated the action to support the new Threads SDK

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-11-29 10:49:37 +00:00
Eric Allam 9cb39bf7d7 Added Redis example env vars 2023-11-29 10:34:54 +00:00
Eric Allam ca05d5f603 @trigger.dev/openai: Adding additional assistant tasks 2023-11-28 22:48:31 +00:00
Hemachandar 4dc46cbbe4 fix: transform Headers object to Record type (#760) 2023-11-28 18:42:50 +00:00
nicktrn 1dcd87a2aa URI encode keys (#758) 2023-11-28 18:05:15 +00:00
Eric Allam c4cb98af5c Clarified the run execution limits 2023-11-28 16:23:35 +00:00
Eric Allam 6ebd435e81 Feature: Run execution concurrency limits (#750)
* WIP execution concurrency controls implemented via Redis

- Split up resuming a run and executing a run
- Added some new statuses to better show what is going on in a run
- Removed preprocessing runs

* WIP

* Convert to using ZSETs and adding env vars

* Removed unused import

* Improve run number generation using advistory locks, and only on start

* More execution concurrency stuff

* Add support for job concurrency limits and concurrency limit groups

* Create wild-swans-battle.md

* Increase slots refresh timeout to 10s

* Try to fix Redis connection issues

* Don’t be so strict about the APP_ENV

* Add the blank tls option to the normal redis client as well

* Add docs
2023-11-28 16:21:06 +00:00
Eric Allam caf203c084 Made webhook index stats optional
🚀 Publish Trigger.dev Docker / units (push) Failing after 4s
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 4s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 19s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
2023-11-28 15:04:24 +00:00
Eric Allam dbc2e3f713 Refreshed pnpm lock 2023-11-28 14:53:37 +00:00
github-actions[bot] a5b49cb61f chore: Update version for release (#753)
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2023-11-28 14:53:06 +00:00
nicktrn 096151c014 Fix: Shopify subpath imports, enhance docs (#755)
🚀 Publish Trigger.dev Docker / typecheck (push) Failing after 0s
🚀 Publish Trigger.dev Docker / units (push) Failing after 0s
🚀 Publish Trigger.dev Docker / e2e (push) Failing after 0s
🚀 Publish Trigger.dev Docker / publish (push) Has been skipped
* Fix invalid subpath imports

* Remove @trigger.dev/tsup dep

* Update lockfile

* Small github docs fix

* Pull runtime adaptor import out of integration

* Fix io.store docs examples

* Add sendEvents to task library

* Add KV to task library and small fixes

* Suppress duplicate http endpoint warnings

* Changeset

* Add task returns
2023-11-27 16:03:03 +00:00
Dan 5d28f1a3d6 Update github-triggers.mdx 2023-11-27 10:32:21 +00:00
Eric Allam 56ae0ed0d3 Only tag v.docker tags with the latest tag 2023-11-24 16:46:06 +00:00
Eric Allam a2f5dc8bc6 Only attempt to login to Docker if the workflow event is a push 2023-11-24 14:16:41 +00:00
Eric Allam d56b2eded5 Features: new login page (#754)
* Initial commit and WIP new login page

* added wrapper to fix layout

* Improved the layout and style of the page

* Added a new extra-large button style (and added it to storybook)

* Moved the cusom onboarding style tooltip to the Tooltip component

* Populated the bento grid with items

* Imrpoved the quote styling

* Tooltip doesn’t stay if you mouse over it

* Added more content including a list of quote that cycle on page load

* New quote mark positioning

* Added the rest of the content to the tooltips

* Made the bento grid responsive

* Moved the login page layout to a seaparte component

* Login pages now use the new layout component

* Extra large button style tweak

* Match the large input style with the large button style

* Cleaned up imports and made the Ts & Cs text the same for magic links

* Layout fix

* Quotes don’t push content off the screen as much

* Added openai integration to the grid

* Make the quote fit if the screen height is narrower

* Style update to the magic link sent state

* Icon colour updates

* fixed text centering on mobile

* Icons are more responsive

* removed unnecessary w-fulls

* Added 2 onboarding questions

* Revalidate form on submit, not input

* Typo fixes

* Name field focuses by default

* Added conform to the employees question

* Update pnpm lock file

* Implement referral source and company size on managed cloud

* Fixed some type errors

---------

Co-authored-by: James Ritchie <james@jamesritchie.co.uk>
2023-11-24 14:08:50 +00:00
nicktrn 0ae9adafbf Fix: Shopify build and webhook indexing (#752)
* Revert to old tsup config

* Make webhooks index optional
2023-11-24 11:45:33 +00:00
Eric Allam 03403ad9cb Fix for pull request workflow (#751)
* Allow PRs that have /publish-docker in the body to cause docker images to be published

* Also ignore mdx file changes

* pr_checks now uses pull_request instead of pull_request_target
2023-11-24 11:19:06 +00:00
nicktrn 067e19fec9 Feature: New Webhook Triggers, KV Store, and Shopify integration (#745)
* Attach webhook to http endpoint

* Create internal webhook handler job

* Fix delivery

* Add webhook trigger

* Index webhooks

* Fix webhook connect

* Webhook activation

* Rename to TriggerWebhook

* Save webhooks to index

* Extend register payload

* Revert attachSource

* Add update webhook helper

* Use crud interface for registration

* Remove filter from params

* Destructure options

* Missing ohash dep

* Chainable trigger filter

* Optional request verification

* Handler call with context

* Update config on register success

* Rename to webhookData

* Add basic key-value store

* Improve kv store

* Webhook trigger UI

* Webhook delivery UI

* Some fixes

* Airtable experiments

* Fix tabs transitions

* Only run register if config differs

* Use subtasks for delivery

* Missing dep

* Error handing and fixes

* Namespace cursor

* Fix hmac verification

* Gut Airtable

* Lockfile

* Template optional api key

* Template event sources and icons

* Template remove filter from params

* Fix models template

* Template fixme

* Fix webhook trigger header

* Actually send params for registration..

* Add back oauthed client

* Verify signature header encoding param

* Fix delivery context

* Webhook create retry with prior delete

* Webhook source type fixes

* Webhook config merge

* Update webhook icon

* Verify webhook task options

* Rename handler to generateEvents

* Send event icons

* Shopify with webhooks

* Shopify job-catalog entry

* Lockfile

* Add webhook migration

* Better icons

* Type fixes

* Make param type optional

* Scope type

* More examples

* More schemas

* Trigger catalog

* Bump versions

* Just a few more events they said

* Simplify session and config

* Typed serializer

* Fix payload type

* Remove unused getters

* Reduce logging output

* Rest resource tasks

* Lockfile

* Bump version

* Remaining triggers

* Fix event types

* Fix import

* Link from webhook trigger to http endpoint

* Use rest resource tasks for crud

* Fix rest save type

* Improve KV types

* Improve attach webhook logging

* Make header schema more lenient

* Fix save type again

* Final error callback

* Shorten keys

* Remove ohash diff

* Disable Airtable webhooks

* Webhook environments

* Fix shopify error import

* Link to integration and http endpoint

* Integration catalog entry

* Disable oauth

* Require api key, simplify client secret

* Move trigger types

* Update catalog example

* Small KV endpoint refactor

* Fix custom migration

* Webhook environment migration

* Improve crud types

* Remove unused schema

* Fix crud context type

* KV limits and HTTP verbs

* KV improvements

* Jobless webhook delivery

* Airtable delivery fixes

* Make deliveries sexy again

* Some docs

* Fix payload types.. again

* Final payload pass

* Schema cleanup

* Refactor handler service

* Remove more stale schemas

* registerJobNamespace import

* Expose KV on TriggerClient

* Remove dummy click handler

* Remove unused components

* Fix delivery pagination

* Enable registration rerun button

* Comment out registration route action handler

* Rename KV as not tied to IO anymore

* Swap api with trigger client

* Disabled fields param

* KV docs

* Changeset

* Shopify docs fixes
2023-11-24 10:22:12 +00:00
nicktrn 2cce68b5f7 Revert "Remove the pg listen code to see if it’s causing DB issues" (#749)
This reverts commit e8e7c116d1.
2023-11-24 09:30:48 +00:00
Dan e3c3aa91e1 Added Clerk / Cal.com / HubSpot / Hugging Face / Mailgun / Novu / WhatsApp HTTP endpoint examples (#748)
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-11-23 16:11:34 +00:00
Marius Vilholm 5c0ca83852 Fix wrong import in example for useRunDetails (#744)
Thanks @mariusvilholm
2023-11-23 15:35:33 +00:00
Marius Vilholm 2b24104c97 Fix wrong import in example of useEventRunDetails (#743) 2023-11-23 15:35:02 +00:00
Marius Vilholm 5977a5aa51 Fix spelling in OpenAI Assistants (#742)
Co-authored-by: Matt Aitken <matt@mattaitken.com>
2023-11-23 15:34:30 +00:00
Eric Allam 131d0dbea4 Adding an example of using OpenAI GPT 4 Vision 2023-11-21 10:23:11 +00:00
1480 changed files with 111872 additions and 21369 deletions
+9
View File
@@ -0,0 +1,9 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
- Fix additionalFiles that aren't decendants
- Stop swallowing uncaught exceptions in prod
- Improve warnings and errors, fail early on critical warnings
- New arg to --save-logs even for successful builds
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
v3 CLI update command and package manager detection fix
+6
View File
@@ -0,0 +1,6 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
better handle task metadata parse errors, and display nicely formatted errors
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Vastly improved dev command output
+8
View File
@@ -0,0 +1,8 @@
---
"@trigger.dev/sdk": patch
"@trigger.dev/core-apps": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
add machine config and secure zod connection
+8 -2
View File
@@ -4,7 +4,8 @@
"commit": false,
"fixed": [
[
"@trigger.dev/*"
"@trigger.dev/*",
"trigger.dev"
]
],
"linked": [],
@@ -14,7 +15,12 @@
"ignore": [
"webapp",
"emails",
"@trigger.dev/database"
"proxy",
"yalt",
"@trigger.dev/database",
"coordinator",
"docker-provider",
"kubernetes-provider"
],
"___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
"onlyUpdatePeerDependentsWhenOutOfRange": true
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Configurable log levels in the config file and via env var
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Dont swallow some error messages when deploying
+6
View File
@@ -0,0 +1,6 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
Add option to print console logs in the dev CLI locally (issue #1014)
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---
Fixed batch otel flushing
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Fix permissions inside node_modules
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/react": patch
---
Fix for shared queryKey between useRunDetails and useRunStatuses
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---
Retry 429, 500, and connection error API requests to the trigger.dev server
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
Export queue from the SDK
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/core-apps": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Display errors for runs and deployments
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
v3: fix digest extraction
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/nestjs": patch
---
fix: [nestjs integration] fastify HTTP adapter detection now works correctly for response headers
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Changed "Worker" to "Version" in the dev command key
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Correctly handle self-hosted deploy command errors
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Default to retrying enabled in dev when running init
+6
View File
@@ -0,0 +1,6 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
Handle string and non-stringifiable outputs like functions
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Improve error messages during dev/deploy and handle deploy image build issues
+6
View File
@@ -0,0 +1,6 @@
---
"@trigger.dev/sdk": patch
"@trigger.dev/core": patch
---
Added replayRun function to the SDK
+6
View File
@@ -0,0 +1,6 @@
---
"@trigger.dev/sdk": patch
"@trigger.dev/core": patch
---
Improve the SDK function types and expose a new APIError instead of the APIResult type
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Added a Node.js runtime check for the CLI
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Fix post start hooks
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Use the dashboard url instead of the API url for the View logs link
+98
View File
@@ -0,0 +1,98 @@
{
"mode": "pre",
"tag": "beta",
"initialVersions": {
"coordinator": "0.0.1",
"docker-provider": "0.0.1",
"kubernetes-provider": "0.0.1",
"proxy": "0.0.11",
"webapp": "1.0.0",
"yalt": "0.0.1",
"@trigger.dev/airtable": "2.3.18",
"@trigger.dev/github": "2.3.18",
"@trigger.dev/linear": "2.3.18",
"@trigger.dev/openai": "2.3.18",
"@trigger.dev/plain": "2.3.18",
"@trigger.dev/replicate": "2.3.18",
"@trigger.dev/resend": "2.3.18",
"@trigger.dev/sendgrid": "2.3.18",
"@trigger.dev/shopify": "2.3.18",
"@trigger.dev/slack": "2.3.18",
"@trigger.dev/stripe": "2.3.18",
"@trigger.dev/supabase": "2.3.18",
"@trigger.dev/typeform": "2.3.18",
"@trigger.dev/astro": "2.3.18",
"@trigger.dev/cli": "2.3.18",
"trigger.dev": "2.3.18",
"@trigger.dev/core": "2.3.18",
"@trigger.dev/core-apps": "0.0.0",
"@trigger.dev/core-backend": "2.3.18",
"@trigger.dev/database": "0.0.1",
"emails": "1.0.0",
"@trigger.dev/eslint-plugin": "2.3.18",
"@trigger.dev/express": "2.3.18",
"@trigger.dev/hono": "2.3.18",
"@trigger.dev/integration-kit": "2.3.18",
"@trigger.dev/nestjs": "2.3.18",
"@trigger.dev/nextjs": "2.3.18",
"@trigger.dev/otlp-importer": "2.3.11",
"@trigger.dev/react": "2.3.18",
"@trigger.dev/remix": "2.3.18",
"@trigger.dev/sveltekit": "2.3.18",
"@trigger.dev/testing": "2.3.18",
"@trigger.dev/sdk": "2.3.18",
"@trigger.dev/yalt": "2.3.18"
},
"changesets": [
"angry-eagles-trade",
"beige-pens-dance",
"breezy-gorillas-mate",
"chilled-hornets-move",
"clean-pianos-listen",
"cool-glasses-bake",
"cuddly-feet-approve",
"dry-walls-check",
"eight-pumas-float",
"few-students-share",
"green-bags-wink",
"khaki-apricots-design",
"khaki-poems-lay",
"late-icons-lie",
"late-steaks-behave",
"lemon-jobs-repair",
"light-bulldogs-press",
"light-dragons-complain",
"loud-actors-remember",
"many-ligers-pump",
"mighty-camels-joke",
"new-rivers-tell",
"ninety-pets-travel",
"odd-poets-own",
"polite-ducks-switch",
"poor-flowers-cross",
"rare-roses-float",
"real-planets-stare",
"rotten-dryers-exercise",
"shaggy-spoons-taste",
"sharp-emus-compare",
"sharp-zebras-serve",
"shiny-coats-cry",
"silly-suits-switch",
"smart-needles-move",
"smart-olives-eat",
"spicy-lamps-smoke",
"strange-ghosts-matter",
"strong-lemons-add",
"stupid-bulldogs-applaud",
"sweet-lizards-press",
"swift-dragons-peel",
"tall-bees-wave",
"tame-guests-know",
"tender-oranges-rhyme",
"tidy-balloons-suffer",
"tidy-dryers-sleep",
"tiny-doors-type",
"tiny-elephants-scream",
"tricky-bulldogs-heal"
]
}
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Add openssl to prod worker image and allow passing auth token via env var for deploy
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Fixed incorrect span timings around checkpoints by implementing a precise wall clock that resets after restores
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Adding task with a triggerSource of schedule
+56
View File
@@ -0,0 +1,56 @@
---
"@trigger.dev/sdk": patch
"@trigger.dev/core": patch
---
Updates the `trigger`, `batchTrigger` and their `*AndWait` variants to use the first parameter for the payload/items, and the second parameter for options.
Before:
```ts
await yourTask.trigger({ payload: { foo: "bar" }, options: { idempotencyKey: "key_1234" } });
await yourTask.triggerAndWait({ payload: { foo: "bar" }, options: { idempotencyKey: "key_1234" } });
await yourTask.batchTrigger({ items: [{ payload: { foo: "bar" } }, { payload: { foo: "baz" } }] });
await yourTask.batchTriggerAndWait({ items: [{ payload: { foo: "bar" } }, { payload: { foo: "baz" } }] });
```
After:
```ts
await yourTask.trigger({ foo: "bar" }, { idempotencyKey: "key_1234" });
await yourTask.triggerAndWait({ foo: "bar" }, { idempotencyKey: "key_1234" });
await yourTask.batchTrigger([{ payload: { foo: "bar" } }, { payload: { foo: "baz" } }]);
await yourTask.batchTriggerAndWait([{ payload: { foo: "bar" } }, { payload: { foo: "baz" } }]);
```
We've also changed the API of the `triggerAndWait` result. Before, if the subtask that was triggered finished with an error, we would automatically "rethrow" the error in the parent task.
Now instead we're returning a `TaskRunResult` object that allows you to discriminate between successful and failed runs in the subtask:
Before:
```ts
try {
const result = await yourTask.triggerAndWait({ foo: "bar" });
// result is the output of your task
console.log("result", result);
} catch (error) {
// handle subtask errors here
}
```
After:
```ts
const result = await yourTask.triggerAndWait({ foo: "bar" });
if (result.ok) {
console.log(`Run ${result.id} succeeded with output`, result.output);
} else {
console.log(`Run ${result.id} failed with error`, result.error);
}
```
+13
View File
@@ -0,0 +1,13 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
When using idempotency keys, triggerAndWait and batchTriggerAndWait will still work even if the existing runs have already been completed (or even partially completed, in the case of batchTriggerAndWait)
- TaskRunExecutionResult.id is now the run friendlyId, not the attempt friendlyId
- A single TaskRun can now have many batchItems, in the case of batchTriggerAndWait while using idempotency keys
- A runs idempotencyKey is now added to the ctx as well as the TaskEvent and displayed in the span view
- When resolving batchTriggerAndWait, the runtimes no longer reject promises, leading to an error in the parent task
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Update trigger.dev CLI for new batch otel support
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Add additional logging around cleaning up dev workers, and always kill them after 5 seconds if they haven't already exited
+6
View File
@@ -0,0 +1,6 @@
---
"@trigger.dev/otlp-importer": patch
"trigger.dev": patch
---
Fix package builds and CLI commands on Windows
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/sdk": patch
---
Remove unimplemented batchOptions
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Fix CLI logout and add list-profiles command
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Fixing an issue with bundling @trigger.dev/core/v3 in dev when using pnpm
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Added DEBUG to the ignored env vars
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---
Make optional schedule object fields nullish
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Fixed an issue where the trigger.dev package was not being built before publishing to npm
+8
View File
@@ -0,0 +1,8 @@
---
"trigger.dev": major
"@trigger.dev/core": major
"@trigger.dev/otlp-importer": major
"@trigger.dev/sdk": major
---
Updates to support Trigger.dev v3
+5
View File
@@ -0,0 +1,5 @@
---
"@trigger.dev/core": patch
---
Added JSDocs to the schedule SDK types
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Dynamically import superjson and fix some bundling issues
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Changed the binary name from trigger.dev to triggerdev to fix a Windows issue
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Stop swallowing deployment errors and display them better
+5
View File
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---
Init command was failing on Windows because of bad template paths
+10
View File
@@ -0,0 +1,10 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
Fixes an issue that caused failed tasks when resuming after calling `triggerAndWait` or `batchTriggerAndWait` in prod/staging (this doesn't effect dev).
The version of Node.js we use for deployed workers (latest 20) would crash with an out-of-memory error when the checkpoint was restored. This crash does not happen on Node 18x or Node21x, so we've decided to upgrade the worker version to Node.js21x, to mitigate this issue.
You'll need to re-deploy to production to fix the issue.
+6
View File
@@ -0,0 +1,6 @@
---
"@trigger.dev/sdk": patch
"@trigger.dev/core": patch
---
Added cancelRun to the SDK
+7
View File
@@ -0,0 +1,7 @@
---
"trigger.dev": patch
"@trigger.dev/core": patch
---
- Add graceful exit for prod workers
- Prevent overflow in long waits
+7
View File
@@ -0,0 +1,7 @@
---
"@trigger.dev/sdk": patch
"trigger.dev": patch
"@trigger.dev/core": patch
---
Added a new global - Task Catalog - to better handle task metadata
+36 -1
View File
@@ -12,6 +12,11 @@ APP_ENV=development
APP_ORIGIN=http://localhost:3030
NODE_ENV=development
# Redis is used for concurrency control
# REDIS_HOST="localhost"
# REDIS_PORT="6379"
# REDIS_TLS_DISABLED="true"
# OPTIONAL VARIABLES
# This is used for validating emails that are allowed to log in. Every email that do not match this regex will be rejected.
# WHITELISTED_EMAILS="authorized@yahoo\.com|authorized@gmail\.com"
@@ -26,6 +31,9 @@ NODE_ENV=development
# FROM_EMAIL=
# REPLY_TO_EMAIL=
# Remove the following line to enable logging telemetry traces to the console
LOG_TELEMETRY="false"
# CLOUD VARIABLES
POSTHOG_PROJECT_KEY=
PLAIN_API_KEY=
@@ -37,4 +45,31 @@ CLOUD_LINEAR_CLIENT_ID=
CLOUD_LINEAR_CLIENT_SECRET=
CLOUD_SLACK_APP_HOST=
CLOUD_SLACK_CLIENT_ID=
CLOUD_SLACK_CLIENT_SECRET=
CLOUD_SLACK_CLIENT_SECRET=
# v3 variables
PROVIDER_SECRET=provider-secret # generate the actual secret with `openssl rand -hex 32`
COORDINATOR_SECRET=coordinator-secret # generate the actual secret with `openssl rand -hex 32`
# Uncomment the following line to enable the registry proxy
# ENABLE_REGISTRY_PROXY=true
# DEPOT_TOKEN=<Depot org token>
# DEPOT_PROJECT_ID=<Depot project id>
# DEPLOY_REGISTRY_HOST=${APP_ORIGIN} # This is the host that the deploy CLI will use to push images to the registry
# CONTAINER_REGISTRY_ORIGIN=<Container registry origin e.g. https://registry.digitalocean.com>
# CONTAINER_REGISTRY_USERNAME=<Container registry username e.g. Digital ocean email address>
# CONTAINER_REGISTRY_PASSWORD=<Container registry password e.g. Digital ocean PAT>
# DEV_OTEL_EXPORTER_OTLP_ENDPOINT="http://0.0.0.0:4318"
# These are needed for the object store (for handling large payloads/outputs)
# OBJECT_STORE_BASE_URL="https://{bucket}.{accountId}.r2.cloudflarestorage.com"
# OBJECT_STORE_ACCESS_KEY_ID=
# OBJECT_STORE_SECRET_ACCESS_KEY=
# RUNTIME_WAIT_THRESHOLD_IN_MS=10000
# These control the server-side internal telemetry
# INTERNAL_OTEL_TRACE_EXPORTER_URL=<URL to send traces to>
# INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_NAME=<Header name for the auth token>
# INTERNAL_OTEL_TRACE_EXPORTER_AUTH_HEADER_VALUE=<Auth token value>
# INTERNAL_OTEL_TRACE_LOGGING_ENABLED=1
# INTERNAL_OTEL_TRACE_SAMPING_RATE=20 # this means 1/20 traces or 5% of traces will be sampled (sampled = recorded)
# INTERNAL_OTEL_TRACE_INSTRUMENT_PRISMA_ENABLED=0,
@@ -0,0 +1,21 @@
name: OpenTelemetry Auto-Instrumentation Request
description: Suggest an SDK that you'd like to be auto-instrumented in the Run log view
title: "auto-instrumentation: "
labels: ["🌟 enhancement"]
body:
- type: textarea
attributes:
label: What API or SDK would you to have automatic spans for?
description: A clear description of which API or SDK you'd like, and links to it.
validations:
required: true
- type: textarea
attributes:
label: Is there an existing OpenTelemetry auto-instrumentation package?
description: You can search for existing ones https://opentelemetry.io/ecosystem/registry/?component=instrumentation&language=js
validations:
required: true
- type: textarea
attributes:
label: Additional information
description: Add any other information related to the feature here. If your feature request is related to any issues or discussions, link them here.
+14 -5
View File
@@ -4,30 +4,36 @@ on:
jobs:
e2e:
name: "🧪 E2E Tests"
runs-on: buildjet-4vcpu-ubuntu-2204
runs-on: buildjet-16vcpu-ubuntu-2204
steps:
- name: 🐳 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
username: ${{ secrets.DOCKERHUB_USERNAME || vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN || vars.DOCKERHUB_TOKEN }}
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
fetch-depth: 0
submodules: recursive
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
version: 8.15.5
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
node-version: 20.11.1
cache: "pnpm"
- name: Install Protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
@@ -42,7 +48,10 @@ jobs:
# Build packages
pnpm run build --filter @references/nextjs-test^...
cd apps/webapp && pnpm run build:server
cd ../..
pnpm --filter @trigger.dev/database generate
pnpm --filter @trigger.dev/otlp-importer generate
# Move trigger-cli bin to correct place
pnpm install --frozen-lockfile
+2 -1
View File
@@ -1,11 +1,12 @@
name: 🤖 PR Checks
on:
pull_request_target:
pull_request:
branches:
- main
paths-ignore:
- "**.md"
- "**.mdx"
- ".github/CODEOWNERS"
- ".github/ISSUE_TEMPLATE/**"
+59
View File
@@ -0,0 +1,59 @@
name: "🐳 Publish Docker"
on:
workflow_call:
jobs:
publish:
runs-on: ubuntu-latest
outputs:
version: ${{ steps.get_version.outputs.version }}
short_sha: ${{ steps.get_commit.outputs.sha_short }}
steps:
- name: Setup Depot CLI
uses: depot/setup-action@v1
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
with:
submodules: recursive
- name: 🆚 Get the version
id: get_version
run: |
IMAGE_TAG="${GITHUB_REF#refs/tags/}"
if [[ $GITHUB_REF == refs/tags/* ]]; then
if [[ $IMAGE_TAG == v.docker.* ]]; then
ORIGINAL_VERSION="${IMAGE_TAG#v.docker.}"
IMAGE_TAG="v${ORIGINAL_VERSION}"
elif [[ $IMAGE_TAG == build-* ]]; then
IMAGE_TAG="${IMAGE_TAG#build-}"
fi
echo "IMAGE_TAG=${IMAGE_TAG}"
elif [[ $GITHUB_REF == refs/heads/main ]]; then
# Handle main branch specifically
IMAGE_TAG="main"
echo "IMAGE_TAG=${IMAGE_TAG}"
else
echo "Invalid reference: ${GITHUB_REF}"
exit 1
fi
echo "::set-output name=version::${IMAGE_TAG}"
- name: 🔢 Get the commit hash
id: get_commit
run: |
echo ::set-output name=sha_short::$(echo ${{ github.sha }} | cut -c1-7)
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐳 Build image and push to GitHub Container Registry
uses: depot/build-push-action@v1
with:
file: ./docker/Dockerfile
platforms: linux/amd64,linux/arm64
tags: |
ghcr.io/triggerdotdev/trigger.dev:${{ steps.get_version.outputs.version }}
push: true
+94
View File
@@ -0,0 +1,94 @@
name: "🚢 Publish Infra Images"
on:
push:
tags:
- "infra-dev-*"
- "infra-test-*"
- "infra-prod-*"
paths:
- ".github/workflows/publish.yml"
- "packages/**"
- "!packages/**/*.md"
- "!packages/**/*.eslintrc"
- "apps/**"
- "!apps/**/*.md"
- "!apps/**/*.eslintrc"
- "integrations/**"
- "!integrations/**/*.md"
- "!integrations/**/*.eslintrc"
- "pnpm-lock.yaml"
- "pnpm-workspace.yaml"
- "turbo.json"
- "docker/Dockerfile"
- "docker/scripts/**"
- "tests/**"
permissions:
id-token: write
packages: write
contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
env:
AWS_REGION: us-east-1
jobs:
build:
strategy:
matrix:
package: [coordinator, kubernetes-provider]
runs-on: buildjet-16vcpu-ubuntu-2204
env:
DOCKER_BUILDKIT: "1"
steps:
- uses: actions/checkout@v4
- name: Generate image reference
id: prep
# WARNING: This step expects the workflow to have been triggered by a specific tag format of: infra-${env}-*
run: |
env=$(echo ${{ github.ref_name }} | cut -d- -f2)
sha=${GITHUB_SHA::7}
ts=$(date +%s)
if [[ "${{ matrix.package }}" == *-provider ]]; then
provider_type=$(echo ${{ matrix.package }} | cut -d- -f1)
repository=provider/${provider_type}
else
repository=${{ matrix.package }}
fi
echo "IMAGE_TAG=${env}-${sha}-${ts}" >> "$GITHUB_OUTPUT"
echo "REPOSITORY=${repository}" >> "$GITHUB_OUTPUT"
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
# ..to avoid rate limits when pulling images
- name: Login to DockerHub
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: 🚢 Build Container Image
run: |
docker build -t infra_image -f ./apps/${{ matrix.package }}/Containerfile .
# ..to push image
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐙 Push to GitHub Container Registry
run: |
docker tag infra_image $REGISTRY/$REPOSITORY:$IMAGE_TAG
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: ${{ steps.prep.outputs.REPOSITORY }}
IMAGE_TAG: ${{ steps.prep.outputs.IMAGE_TAG }}
+7 -69
View File
@@ -4,11 +4,15 @@ on:
push:
branches:
- main
- improvements/*
tags:
- "v.docker.*"
- "build-*"
paths:
- ".github/workflows/publish.yml"
- ".github/workflows/typecheck.yml"
- ".github/workflows/unit-tests.yml"
- ".github/workflows/e2e.yml"
- ".github/workflows/publish-docker.yml"
- "packages/**"
- "!packages/**/*.md"
- "!packages/**/*.eslintrc"
@@ -51,71 +55,5 @@ jobs:
publish:
needs: [typecheck, units, e2e]
runs-on: buildjet-4vcpu-ubuntu-2204
outputs:
version: ${{ steps.get_version.outputs.version }}
short_sha: ${{ steps.get_commit.outputs.sha_short }}
steps:
- name: 🐳 Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
- name: 🆚 Get the version
id: get_version
run: |
IMAGE_TAG="${GITHUB_REF#refs/tags/}"
if [[ $GITHUB_REF == refs/tags/* ]]; then
if [[ $IMAGE_TAG == v.docker.* ]]; then
ORIGINAL_VERSION="${IMAGE_TAG#v.docker.}"
IMAGE_TAG="v${ORIGINAL_VERSION}"
fi
echo "IMAGE_TAG=${IMAGE_TAG}"
elif [[ $GITHUB_REF == refs/heads/improvements/* ]]; then
ORIGINAL_VERSION="${GITHUB_REF#refs/heads/improvements/}"
IMAGE_TAG="${ORIGINAL_VERSION}.rc"
echo "IMAGE_TAG=${IMAGE_TAG}"
elif [[ $GITHUB_REF == refs/heads/* ]]; then
IMAGE_TAG="${GITHUB_REF#refs/heads/}"
echo "IMAGE_TAG=${IMAGE_TAG}"
else
echo "Invalid reference: ${GITHUB_REF}"
exit 1
fi
echo "::set-output name=version::${IMAGE_TAG}"
- name: 🔢 Get the commit hash
id: get_commit
run: |
echo ::set-output name=sha_short::$(echo ${{ github.sha }} | cut -c1-7)
- name: 🐳 Build Docker Image
run: |
docker build -t release_build_image -f ./docker/Dockerfile .
- name: 🐙 Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: 🐙 Push to GitHub Container Registry
run: |
docker tag release_build_image $REGISTRY/$REPOSITORY:$IMAGE_TAG
docker push $REGISTRY/$REPOSITORY:$IMAGE_TAG
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: trigger.dev
IMAGE_TAG: ${{ steps.get_version.outputs.version }}
- name: 🐙 Push 'latest' to GitHub Container Registry
if: startsWith(github.ref, 'refs/tags/')
run: |
docker tag release_build_image $REGISTRY/$REPOSITORY:latest
docker push $REGISTRY/$REPOSITORY:latest
env:
REGISTRY: ghcr.io/triggerdotdev
REPOSITORY: trigger.dev
uses: ./.github/workflows/publish-docker.yml
secrets: inherit
+9 -5
View File
@@ -8,12 +8,11 @@ on:
- "**.md"
- ".github/CODEOWNERS"
- ".github/ISSUE_TEMPLATE/**"
jobs:
release:
name: 🦋 Changesets Release
runs-on: buildjet-4vcpu-ubuntu-2204
runs-on: buildjet-8vcpu-ubuntu-2204
if: |
github.repository == 'triggerdotdev/trigger.dev'
outputs:
@@ -31,14 +30,19 @@ jobs:
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
version: 8.15.5
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
node-version: 20.11.1
cache: "pnpm"
- name: Install Protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
@@ -46,7 +50,7 @@ jobs:
run: pnpm run generate
- name: 🔎 Type check
run: pnpm run typecheck
run: pnpm run typecheck --filter "@trigger.dev/*" --filter "trigger.dev"
- name: 🔐 Setup npm auth
run: |
+8 -3
View File
@@ -3,7 +3,7 @@ on:
workflow_call:
jobs:
typecheck:
runs-on: buildjet-4vcpu-ubuntu-2204
runs-on: buildjet-8vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
@@ -14,14 +14,19 @@ jobs:
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
version: 8.15.5
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
node-version: 20.11.1
cache: "pnpm"
- name: Install Protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
+18 -3
View File
@@ -4,7 +4,7 @@ on:
jobs:
unitTests:
name: "🧪 Unit Tests"
runs-on: buildjet-4vcpu-ubuntu-2204
runs-on: buildjet-8vcpu-ubuntu-2204
steps:
- name: ⬇️ Checkout repo
uses: actions/checkout@v3
@@ -14,14 +14,29 @@ jobs:
- name: ⎔ Setup pnpm
uses: pnpm/action-setup@v2.2.4
with:
version: 7.18
version: 8.15.5
- name: ⎔ Setup node
uses: buildjet/setup-node@v3
with:
node-version: 18
node-version: 20.11.1
cache: "pnpm"
- name: Install Protoc
uses: arduino/setup-protoc@v3
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- name: ⎔ Setup Deno
uses: denoland/setup-deno@v1
with:
deno-version: v1.x
- name: ⎔ Setup bun
uses: oven-sh/setup-bun@v1
with:
bun-version: "1.0.15"
- name: 📥 Download deps
run: pnpm install --frozen-lockfile
+2 -1
View File
@@ -53,4 +53,5 @@ apps/**/public/build
/playwright-report/
/playwright/.cache/
.cosine
.cosine
.trigger/
+3
View File
@@ -0,0 +1,3 @@
[submodule "packages/otlp-importer/protos"]
path = packages/otlp-importer/protos
url = https://github.com/open-telemetry/opentelemetry-proto.git
+1 -1
View File
@@ -1 +1 @@
v18.18.0
v20.11.1
+26 -2
View File
@@ -9,7 +9,7 @@
"request": "launch",
"name": "Debug WebApp",
"command": "pnpm run dev --filter webapp",
"envFile": "${workspaceFolder}/apps/webapp/.env",
"envFile": "${workspaceFolder}/.env",
"cwd": "${workspaceFolder}",
"sourceMaps": true
},
@@ -23,11 +23,35 @@
{
"type": "node-terminal",
"request": "launch",
"name": "Debug BYO Auth",
"name": "Debug v2 job catalog",
"command": "pnpm run byo-auth",
"envFile": "${workspaceFolder}/references/job-catalog/.env",
"cwd": "${workspaceFolder}/references/job-catalog",
"sourceMaps": true
},
{
"type": "node-terminal",
"request": "launch",
"name": "Debug V3 Dev CLI",
"command": "pnpm exec triggerdev dev --log-level debug",
"cwd": "${workspaceFolder}/references/v3-catalog",
"sourceMaps": true
},
{
"type": "node-terminal",
"request": "launch",
"name": "Debug V3 Deploy CLI",
"command": "pnpm exec triggerdev deploy",
"cwd": "${workspaceFolder}/references/v3-catalog",
"sourceMaps": true
},
{
"type": "node",
"request": "attach",
"name": "Attach to Trigger.dev CLI (v3)",
"port": 9229,
"restart": true,
"skipFiles": ["<node_internals>/**"]
}
]
}
+1 -1
View File
@@ -1,4 +1,4 @@
{
"deno.enablePaths": ["references/deno-reference"],
"deno.enablePaths": ["references/deno-reference", "runtime_tests/tests/deno"],
"debug.toolBarLocation": "commandCenter"
}
+1 -1
View File
@@ -47,7 +47,7 @@ pnpm exec changeset version --snapshot prerelease
3. Build the packages:
```sh
pnpm run build --filter "@trigger.dev/*"
pnpm run build --filter "@trigger.dev/*" --filter "trigger.dev"
```
4. Publish the snapshot (replace "dev" with your tag)
+1 -1
View File
@@ -7,7 +7,7 @@
### The open source background jobs framework
[Discord](https://discord.gg/JtBAxBr2m3) | [Website](https://trigger.dev) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Docs](https://trigger.dev/docs)
[Discord](https://trigger.dev/discord) | [Website](https://trigger.dev) | [Issues](https://github.com/triggerdotdev/trigger.dev/issues) | [Docs](https://trigger.dev/docs)
[![Twitter](https://img.shields.io/twitter/url/https/twitter.com/triggerdotdev.svg?style=social&label=Follow%20%40trigger.dev)](https://twitter.com/triggerdotdev)
[![GitHub Repo stars](https://img.shields.io/github/stars/triggerdotdev/trigger.dev?style=social)](https://github.com/triggerdotdev/trigger.dev)
+4
View File
@@ -0,0 +1,4 @@
HTTP_SERVER_PORT=8020
PLATFORM_ENABLED=true
PLATFORM_WS_PORT=3030
SECURE_CONNECTION=false
+3
View File
@@ -0,0 +1,3 @@
dist/
node_modules/
.env
+60
View File
@@ -0,0 +1,60 @@
# syntax=docker/dockerfile:labs
FROM node:18-bullseye-slim@sha256:a4edd54dcfdcacc8a4100fee71498e8671d99556a1acf5614539214a70092426 AS node-18
WORKDIR /app
FROM node-18 AS pruner
COPY --chown=node:node . .
RUN npx -q turbo@1.10.9 prune --scope=coordinator --docker
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
FROM node-18 AS base
RUN apt-get update \
&& apt-get install -y buildah ca-certificates dumb-init \
&& rm -rf /var/lib/apt/lists/*
COPY --chown=node:node .gitignore .gitignore
COPY --from=pruner --chown=node:node /app/out/json/ .
COPY --from=pruner --chown=node:node /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=pruner --chown=node:node /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml
FROM base AS dev-deps
RUN corepack enable
ENV NODE_ENV development
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --no-frozen-lockfile
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --ignore-scripts --no-frozen-lockfile
FROM base AS builder
RUN corepack enable
COPY --from=pruner --chown=node:node /app/out/full/ .
COPY --from=dev-deps --chown=node:node /app/ .
COPY --chown=node:node turbo.json turbo.json
RUN pnpm run -r --filter coordinator build:bundle
FROM alpine AS cri-tools
WORKDIR /cri-tools
ARG CRICTL_VERSION=v1.29.0
ARG CRICTL_CHECKSUM=sha256:d16a1ffb3938f5a19d5c8f45d363bd091ef89c0bc4d44ad16b933eede32fdcbb
ADD --checksum=${CRICTL_CHECKSUM} \
https://github.com/kubernetes-sigs/cri-tools/releases/download/${CRICTL_VERSION}/crictl-${CRICTL_VERSION}-linux-amd64.tar.gz .
RUN tar zxvf crictl-${CRICTL_VERSION}-linux-amd64.tar.gz
FROM base AS runner
RUN corepack enable
ENV NODE_ENV production
COPY --from=cri-tools --chown=node:node /cri-tools/crictl /usr/local/bin
COPY --from=builder --chown=node:node /app/apps/coordinator/dist/index.mjs ./index.mjs
EXPOSE 8000
CMD [ "/usr/bin/dumb-init", "--", "/usr/local/bin/node", "./index.mjs" ]
+3
View File
@@ -0,0 +1,3 @@
# Coordinator
Sits between the platform and tasks. Facilitates communication and checkpointing, amongst other things.
+34
View File
@@ -0,0 +1,34 @@
{
"name": "coordinator",
"private": true,
"version": "0.0.1",
"description": "",
"main": "dist/index.cjs",
"scripts": {
"build": "npm run build:bundle",
"build:bundle": "esbuild src/index.ts --bundle --outfile=dist/index.mjs --platform=node --format=esm --target=esnext --banner:js=\"import { createRequire } from 'module';const require = createRequire(import.meta.url);\"",
"build:image": "docker build -f Containerfile . -t coordinator",
"dev": "tsx --no-warnings=ExperimentalWarning --require dotenv/config --watch src/index.ts",
"start": "tsx src/index.ts",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@trigger.dev/core": "workspace:*",
"@trigger.dev/core-apps": "workspace:*",
"execa": "^8.0.1",
"nanoid": "^5.0.6",
"prom-client": "^15.1.0",
"socket.io": "^4.7.4",
"socket.io-client": "^4.7.4"
},
"devDependencies": {
"@types/node": "^18",
"dotenv": "^16.4.2",
"esbuild": "^0.19.11",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
+983
View File
@@ -0,0 +1,983 @@
import { createServer } from "node:http";
import { $ } from "execa";
import { nanoid } from "nanoid";
import { Server } from "socket.io";
import {
CoordinatorToPlatformMessages,
CoordinatorToProdWorkerMessages,
PlatformToCoordinatorMessages,
ProdWorkerSocketData,
ProdWorkerToCoordinatorMessages,
ZodNamespace,
ZodSocketConnection,
} from "@trigger.dev/core/v3";
import { HttpReply, getTextBody, SimpleLogger } from "@trigger.dev/core-apps";
import { collectDefaultMetrics, register, Gauge } from "prom-client";
collectDefaultMetrics();
const HTTP_SERVER_PORT = Number(process.env.HTTP_SERVER_PORT || 8020);
const NODE_NAME = process.env.NODE_NAME || "coordinator";
const DEFAULT_RETRY_DELAY_THRESHOLD_IN_MS = 30_000;
const REGISTRY_HOST = process.env.REGISTRY_HOST || "localhost:5000";
const CHECKPOINT_PATH = process.env.CHECKPOINT_PATH || "/checkpoints";
const REGISTRY_TLS_VERIFY = process.env.REGISTRY_TLS_VERIFY === "false" ? "false" : "true";
const PLATFORM_ENABLED = ["1", "true"].includes(process.env.PLATFORM_ENABLED ?? "true");
const PLATFORM_HOST = process.env.PLATFORM_HOST || "127.0.0.1";
const PLATFORM_WS_PORT = process.env.PLATFORM_WS_PORT || 3030;
const PLATFORM_SECRET = process.env.PLATFORM_SECRET || "coordinator-secret";
const SECURE_CONNECTION = ["1", "true"].includes(process.env.SECURE_CONNECTION ?? "false");
const logger = new SimpleLogger(`[${NODE_NAME}]`);
type CheckpointerInitializeReturn = {
canCheckpoint: boolean;
willSimulate: boolean;
};
type CheckpointAndPushOptions = {
runId: string;
leaveRunning?: boolean;
projectRef: string;
deploymentVersion: string;
};
type CheckpointData = {
location: string;
docker: boolean;
};
class Checkpointer {
#initialized = false;
#canCheckpoint = false;
#dockerMode = !process.env.KUBERNETES_PORT;
#logger = new SimpleLogger("[checkptr]");
#abortControllers = new Map<string, AbortController>();
constructor(private opts = { forceSimulate: false }) {}
async initialize(): Promise<CheckpointerInitializeReturn> {
if (this.#initialized) {
return this.#getInitializeReturn();
}
this.#logger.log(`${this.#dockerMode ? "Docker" : "Kubernetes"} mode`);
if (this.#dockerMode) {
try {
await $`criu --version`;
} catch (error) {
this.#logger.error("No checkpoint support: Missing CRIU binary");
this.#logger.error("Will simulate instead");
this.#canCheckpoint = false;
this.#initialized = true;
return this.#getInitializeReturn();
}
try {
await $`docker checkpoint`;
} catch (error) {
this.#logger.error(
"No checkpoint support: Docker needs to have experimental features enabled"
);
this.#logger.error("Will simulate instead");
this.#canCheckpoint = false;
this.#initialized = true;
return this.#getInitializeReturn();
}
} else {
try {
await $`buildah login --get-login ${REGISTRY_HOST}`;
} catch (error) {
this.#logger.error(`No checkpoint support: Not logged in to registry ${REGISTRY_HOST}`);
this.#canCheckpoint = false;
this.#initialized = true;
return this.#getInitializeReturn();
}
}
this.#logger.log(
`Full checkpoint support${
this.#dockerMode && this.opts.forceSimulate ? " with forced simulation enabled." : "!"
}`
);
this.#initialized = true;
this.#canCheckpoint = true;
return this.#getInitializeReturn();
}
#getInitializeReturn(): CheckpointerInitializeReturn {
return {
canCheckpoint: this.#canCheckpoint,
willSimulate: this.#dockerMode && (!this.#canCheckpoint || this.opts.forceSimulate),
};
}
#getImageRef(projectRef: string, deploymentVersion: string, shortCode: string) {
return `${REGISTRY_HOST}/trigger/${projectRef}:${deploymentVersion}.prod-${shortCode}`;
}
#getExportLocation(projectRef: string, deploymentVersion: string, shortCode: string) {
const basename = `${projectRef}-${deploymentVersion}-${shortCode}`;
if (this.#dockerMode) {
return basename;
} else {
return `${CHECKPOINT_PATH}/${basename}.tar`;
}
}
async checkpointAndPush(opts: CheckpointAndPushOptions): Promise<CheckpointData | undefined> {
const start = performance.now();
logger.log(`checkpointAndPush() start`, { start, opts });
const result = await this.#checkpointAndPush(opts);
const end = performance.now();
logger.log(`checkpointAndPush() end`, {
start,
end,
diff: end - start,
opts,
success: !!result,
});
return result;
}
isCheckpointing(runId: string) {
return this.#abortControllers.has(runId);
}
cancelCheckpoint(runId: string) {
const controller = this.#abortControllers.get(runId);
if (!controller) {
logger.debug("Nothing to cancel", { runId });
return;
}
controller.abort("cancelCheckpointing()");
this.#abortControllers.delete(runId);
}
async #checkpointAndPush({
runId,
leaveRunning = true, // This mirrors kubernetes behaviour more accurately
projectRef,
deploymentVersion,
}: CheckpointAndPushOptions): Promise<CheckpointData | undefined> {
await this.initialize();
if (!this.#dockerMode && !this.#canCheckpoint) {
this.#logger.error("No checkpoint support. Simulation requires docker.");
return;
}
if (this.#abortControllers.has(runId)) {
logger.error("Checkpoint procedure already in progress", {
options: {
runId,
leaveRunning,
projectRef,
deploymentVersion,
},
});
return;
}
const controller = new AbortController();
this.#abortControllers.set(runId, controller);
const $$ = $({ signal: controller.signal });
try {
const shortCode = nanoid(8);
const imageRef = this.#getImageRef(projectRef, deploymentVersion, shortCode);
const exportLocation = this.#getExportLocation(projectRef, deploymentVersion, shortCode);
this.#logger.log("Checkpointing:", {
options: {
runId,
leaveRunning,
projectRef,
deploymentVersion,
},
});
const containterName = this.#getRunContainerName(runId);
// Create checkpoint (docker)
if (this.#dockerMode) {
try {
if (this.opts.forceSimulate || !this.#canCheckpoint) {
this.#logger.log("Simulating checkpoint");
this.#logger.debug(await $$`docker pause ${containterName}`);
} else {
if (leaveRunning) {
this.#logger.debug(
await $$`docker checkpoint create --leave-running ${containterName} ${exportLocation}`
);
} else {
this.#logger.debug(
await $$`docker checkpoint create ${containterName} ${exportLocation}`
);
}
}
} catch (error: any) {
this.#logger.error(error.stderr);
return;
}
this.#logger.log("checkpoint created:", {
runId,
location: exportLocation,
});
return {
location: exportLocation,
docker: true,
};
}
// Create checkpoint (CRI)
if (!this.#canCheckpoint) {
throw new Error("No checkpoint support in kubernetes mode.");
}
const containerId = this.#logger.debug(
// @ts-expect-error
await $$`crictl ps`
.pipeStdout($$({ stdin: "pipe" })`grep ${containterName}`)
.pipeStdout($$({ stdin: "pipe" })`cut -f1 ${"-d "}`)
);
if (!containerId.stdout) {
throw new Error("could not find container id");
}
this.#logger.debug(await $$`crictl checkpoint --export=${exportLocation} ${containerId}`);
// Create image from checkpoint
const container = this.#logger.debug(await $$`buildah from scratch`);
this.#logger.debug(await $$`buildah add ${container} ${exportLocation} /`);
this.#logger.debug(
await $$`buildah config --annotation=io.kubernetes.cri-o.annotations.checkpoint.name=counter ${container}`
);
this.#logger.debug(await $$`buildah commit ${container} ${imageRef}`);
this.#logger.debug(await $$`buildah rm ${container}`);
// Push checkpoint image
this.#logger.debug(await $$`buildah push --tls-verify=${REGISTRY_TLS_VERIFY} ${imageRef}`);
this.#logger.log("Checkpointed and pushed image to:", { location: imageRef });
try {
await $$`rm ${exportLocation}`;
this.#logger.log("Deleted checkpoint archive", { exportLocation });
// Disabled for now as this will increase restore time by having to pull the image again
// await $`buildah rmi ${imageRef}`;
// this.#logger.log("Deleted checkpoint image", { imageRef });
} catch (error) {
this.#logger.error("Failed during checkpoint cleanup", { exportLocation });
this.#logger.debug(error);
}
return {
location: imageRef,
docker: false,
};
} catch (error) {
this.#logger.error("checkpoint failed", {
options: {
runId,
leaveRunning,
projectRef,
deploymentVersion,
},
error,
});
return;
} finally {
this.#abortControllers.delete(runId);
}
}
#getRunContainerName(suffix: string) {
return `task-run-${suffix}`;
}
}
class TaskCoordinator {
#httpServer: ReturnType<typeof createServer>;
#checkpointer = new Checkpointer({ forceSimulate: true });
#prodWorkerNamespace: ZodNamespace<
typeof ProdWorkerToCoordinatorMessages,
typeof CoordinatorToProdWorkerMessages,
typeof ProdWorkerSocketData
>;
#platformSocket?: ZodSocketConnection<
typeof CoordinatorToPlatformMessages,
typeof PlatformToCoordinatorMessages
>;
#checkpointableTasks = new Map<
string,
{ resolve: (value: void) => void; reject: (err?: any) => void }
>();
#delayThresholdInMs: number;
constructor(
private port: number,
private host = "0.0.0.0"
) {
this.#httpServer = this.#createHttpServer();
this.#checkpointer.initialize();
this.#delayThresholdInMs = this.#getDelayThreshold();
if (process.env.DELAY_THRESHOLD_IN_MS) {
this.#delayThresholdInMs = this.#getDelayThreshold();
}
const io = new Server(this.#httpServer);
this.#prodWorkerNamespace = this.#createProdWorkerNamespace(io);
this.#platformSocket = this.#createPlatformSocket();
const connectedTasksTotal = new Gauge({
name: "daemon_connected_tasks_total", // don't change this without updating dashboard config
help: "The number of tasks currently connected.",
collect: () => {
connectedTasksTotal.set(this.#prodWorkerNamespace.namespace.sockets.size);
},
});
register.registerMetric(connectedTasksTotal);
}
#getDelayThreshold() {
if (!process.env.RETRY_DELAY_THRESHOLD_IN_MS) {
return DEFAULT_RETRY_DELAY_THRESHOLD_IN_MS;
}
const threshold = parseInt(process.env.RETRY_DELAY_THRESHOLD_IN_MS);
if (isNaN(threshold)) {
logger.log(
"RETRY_DELAY_THRESHOLD_IN_MS parses as NaN, must supply integer. Will use default instead.",
{
RETRY_DELAY_THRESHOLD_IN_MS: process.env.RETRY_DELAY_THRESHOLD_IN_MS,
DEFAULT_DELAY_THRESHOLD_IN_MS: DEFAULT_RETRY_DELAY_THRESHOLD_IN_MS,
}
);
return DEFAULT_RETRY_DELAY_THRESHOLD_IN_MS;
}
return threshold;
}
#createPlatformSocket() {
if (!PLATFORM_ENABLED) {
console.log("INFO: platform connection disabled");
return;
}
const platformConnection = new ZodSocketConnection({
namespace: "coordinator",
host: PLATFORM_HOST,
port: Number(PLATFORM_WS_PORT),
secure: SECURE_CONNECTION,
clientMessages: CoordinatorToPlatformMessages,
serverMessages: PlatformToCoordinatorMessages,
authToken: PLATFORM_SECRET,
handlers: {
RESUME_AFTER_DEPENDENCY: async (message) => {
const taskSocket = await this.#getAttemptSocket(message.attemptFriendlyId);
if (!taskSocket) {
logger.log("Socket for attempt not found", {
attemptFriendlyId: message.attemptFriendlyId,
});
return;
}
// In case the task resumed faster than we could checkpoint
this.#cancelCheckpoint(message.runId);
taskSocket.emit("RESUME_AFTER_DEPENDENCY", message);
},
RESUME_AFTER_DURATION: async (message) => {
const taskSocket = await this.#getAttemptSocket(message.attemptFriendlyId);
if (!taskSocket) {
logger.log("Socket for attempt not found", {
attemptFriendlyId: message.attemptFriendlyId,
});
return;
}
taskSocket.emit("RESUME_AFTER_DURATION", message);
},
REQUEST_ATTEMPT_CANCELLATION: async (message) => {
const taskSocket = await this.#getAttemptSocket(message.attemptFriendlyId);
if (!taskSocket) {
logger.log("Socket for attempt not found", {
attemptFriendlyId: message.attemptFriendlyId,
});
return;
}
taskSocket.emit("REQUEST_ATTEMPT_CANCELLATION", message);
},
READY_FOR_RETRY: async (message) => {
const taskSocket = await this.#getRunSocket(message.runId);
if (!taskSocket) {
logger.log("Socket for attempt not found", {
runId: message.runId,
});
return;
}
taskSocket.emit("READY_FOR_RETRY", message);
},
},
});
return platformConnection;
}
async #getRunSocket(runId: string) {
const sockets = await this.#prodWorkerNamespace.fetchSockets();
for (const socket of sockets) {
if (socket.data.runId === runId) {
return socket;
}
}
}
async #getAttemptSocket(attemptFriendlyId: string) {
const sockets = await this.#prodWorkerNamespace.fetchSockets();
for (const socket of sockets) {
if (socket.data.attemptFriendlyId === attemptFriendlyId) {
return socket;
}
}
}
#createProdWorkerNamespace(io: Server) {
const provider = new ZodNamespace({
io,
name: "prod-worker",
clientMessages: ProdWorkerToCoordinatorMessages,
serverMessages: CoordinatorToProdWorkerMessages,
socketData: ProdWorkerSocketData,
postAuth: async (socket, next, logger) => {
function setSocketDataFromHeader(
dataKey: keyof typeof socket.data,
headerName: string,
required: boolean = true
) {
const value = socket.handshake.headers[headerName];
if (value) {
socket.data[dataKey] = Array.isArray(value) ? value[0] : value;
return;
}
if (required) {
logger.error("missing required header", { headerName });
throw new Error("missing header");
}
}
try {
setSocketDataFromHeader("podName", "x-pod-name");
setSocketDataFromHeader("contentHash", "x-trigger-content-hash");
setSocketDataFromHeader("projectRef", "x-trigger-project-ref");
setSocketDataFromHeader("runId", "x-trigger-run-id");
setSocketDataFromHeader("attemptFriendlyId", "x-trigger-attempt-friendly-id", false);
setSocketDataFromHeader("envId", "x-trigger-env-id");
setSocketDataFromHeader("deploymentId", "x-trigger-deployment-id");
setSocketDataFromHeader("deploymentVersion", "x-trigger-deployment-version");
} catch (error) {
logger.error("setSocketDataFromHeader error", { error });
socket.disconnect(true);
return;
}
logger.debug("success", socket.data);
next();
},
onConnection: async (socket, handler, sender) => {
const logger = new SimpleLogger(`[prod-worker][${socket.id}]`);
const checkpointInProgress = () => {
return this.#checkpointableTasks.has(socket.data.runId);
};
const readyToCheckpoint = async (): Promise<
{ success: true } | { success: false; reason?: string }
> => {
if (checkpointInProgress()) {
return {
success: false,
reason: "checkpoint in progress",
};
}
const isCheckpointable = new Promise((resolve, reject) => {
// We set a reasonable timeout to prevent waiting forever
// TODO: We may also want to cancel the task as it's unlikely to recover
setTimeout(() => reject("timeout"), 10_000);
this.#checkpointableTasks.set(socket.data.runId, { resolve, reject });
});
try {
await isCheckpointable;
this.#checkpointableTasks.delete(socket.data.runId);
return {
success: true,
};
} catch (error) {
logger.error("Error while waiting for checkpointable state", { error });
return {
success: false,
reason: typeof error === "string" ? error : "unknown",
};
}
};
this.#platformSocket?.send("LOG", {
metadata: socket.data,
text: "connected",
});
socket.on("LOG", (message, callback) => {
logger.log("[LOG]", message.text);
callback();
this.#platformSocket?.send("LOG", {
version: "v1",
metadata: socket.data,
text: message.text,
});
});
socket.on("READY_FOR_EXECUTION", async (message) => {
logger.log("[READY_FOR_EXECUTION]", message);
try {
const executionAck = await this.#platformSocket?.sendWithAck(
"READY_FOR_EXECUTION",
message
);
if (!executionAck) {
logger.error("no execution ack", { runId: socket.data.runId });
socket.emit("REQUEST_EXIT", {
version: "v1",
});
return;
}
if (!executionAck.success) {
logger.error("failed to get execution payload", { runId: socket.data.runId });
socket.emit("REQUEST_EXIT", {
version: "v1",
});
return;
}
socket.emit("EXECUTE_TASK_RUN", {
version: "v1",
executionPayload: executionAck.payload,
});
socket.data.attemptFriendlyId = executionAck.payload.execution.attempt.id;
} catch (error) {
logger.error("Error", { error });
}
});
socket.on("READY_FOR_RESUME", async (message) => {
logger.log("[READY_FOR_RESUME]", message);
socket.data.attemptFriendlyId = message.attemptFriendlyId;
this.#platformSocket?.send("READY_FOR_RESUME", message);
});
socket.on("TASK_RUN_COMPLETED", async ({ completion, execution }, callback) => {
logger.log("completed task", { completionId: completion.id });
const completeWithoutCheckpoint = (shouldExit: boolean) => {
this.#platformSocket?.send("TASK_RUN_COMPLETED", {
version: "v1",
execution,
completion,
});
callback({ willCheckpointAndRestore: false, shouldExit });
};
if (completion.ok) {
completeWithoutCheckpoint(true);
return;
}
if (
completion.error.type === "INTERNAL_ERROR" &&
completion.error.code === "TASK_RUN_CANCELLED"
) {
completeWithoutCheckpoint(true);
return;
}
if (completion.retry === undefined) {
completeWithoutCheckpoint(true);
return;
}
if (completion.retry.delay < this.#delayThresholdInMs) {
completeWithoutCheckpoint(false);
return;
}
const { canCheckpoint, willSimulate } = await this.#checkpointer.initialize();
const willCheckpointAndRestore = canCheckpoint || willSimulate;
if (!willCheckpointAndRestore) {
completeWithoutCheckpoint(false);
return;
}
// The worker will then put itself in a checkpointable state
callback({ willCheckpointAndRestore: true, shouldExit: false });
const ready = await readyToCheckpoint();
if (!ready.success) {
logger.error("Failed to become checkpointable", {
runId: socket.data.runId,
reason: ready.reason,
});
return;
}
const checkpoint = await this.#checkpointer.checkpointAndPush({
runId: socket.data.runId,
projectRef: socket.data.projectRef,
deploymentVersion: socket.data.deploymentVersion,
});
if (!checkpoint) {
logger.error("Failed to checkpoint", { runId: socket.data.runId });
completeWithoutCheckpoint(false);
return;
}
this.#platformSocket?.send("TASK_RUN_COMPLETED", {
version: "v1",
execution,
completion,
checkpoint,
});
if (!checkpoint.docker || !willSimulate) {
socket.emit("REQUEST_EXIT", {
version: "v1",
});
}
});
socket.on("READY_FOR_CHECKPOINT", async (message) => {
logger.log("[READY_FOR_CHECKPOINT]", message);
const checkpointable = this.#checkpointableTasks.get(socket.data.runId);
if (!checkpointable) {
logger.error("No checkpoint scheduled", { runId: socket.data.runId });
return;
}
checkpointable.resolve();
});
socket.on("CANCEL_CHECKPOINT", async (message) => {
logger.log("[CANCEL_CHECKPOINT]", message);
this.#cancelCheckpoint(socket.data.runId);
});
socket.on("WAIT_FOR_DURATION", async (message, callback) => {
logger.log("[WAIT_FOR_DURATION]", message);
if (checkpointInProgress()) {
logger.error("Checkpoint already in progress", { runId: socket.data.runId });
callback({ willCheckpointAndRestore: false });
return;
}
const { canCheckpoint, willSimulate } = await this.#checkpointer.initialize();
const willCheckpointAndRestore = canCheckpoint || willSimulate;
callback({ willCheckpointAndRestore });
if (!willCheckpointAndRestore) {
return;
}
const ready = await readyToCheckpoint();
if (!ready.success) {
logger.error("Failed to become checkpointable", {
runId: socket.data.runId,
reason: ready.reason,
});
return;
}
const checkpoint = await this.#checkpointer.checkpointAndPush({
runId: socket.data.runId,
projectRef: socket.data.projectRef,
deploymentVersion: socket.data.deploymentVersion,
});
if (!checkpoint) {
// The task container will keep running until the wait duration has elapsed
logger.error("Failed to checkpoint", { runId: socket.data.runId });
return;
}
if (!checkpoint.docker || !willSimulate) {
socket.emit("REQUEST_EXIT", {
version: "v1",
});
}
this.#platformSocket?.send("CHECKPOINT_CREATED", {
version: "v1",
attemptFriendlyId: message.attemptFriendlyId,
docker: checkpoint.docker,
location: checkpoint.location,
reason: {
type: "WAIT_FOR_DURATION",
ms: message.ms,
now: message.now,
},
});
});
socket.on("WAIT_FOR_TASK", async (message, callback) => {
logger.log("[WAIT_FOR_TASK]", message);
const { canCheckpoint, willSimulate } = await this.#checkpointer.initialize();
const willCheckpointAndRestore = canCheckpoint || willSimulate;
callback({ willCheckpointAndRestore });
if (!willCheckpointAndRestore) {
return;
}
const checkpoint = await this.#checkpointer.checkpointAndPush({
runId: socket.data.runId,
projectRef: socket.data.projectRef,
deploymentVersion: socket.data.deploymentVersion,
});
if (!checkpoint) {
logger.error("Failed to checkpoint", { runId: socket.data.runId });
return;
}
if (!checkpoint.docker || !willSimulate) {
socket.emit("REQUEST_EXIT", {
version: "v1",
});
}
this.#platformSocket?.send("CHECKPOINT_CREATED", {
version: "v1",
attemptFriendlyId: message.attemptFriendlyId,
docker: checkpoint.docker,
location: checkpoint.location,
reason: {
type: "WAIT_FOR_TASK",
friendlyId: message.friendlyId,
},
});
});
socket.on("WAIT_FOR_BATCH", async (message, callback) => {
logger.log("[WAIT_FOR_BATCH]", message);
const { canCheckpoint, willSimulate } = await this.#checkpointer.initialize();
const willCheckpointAndRestore = canCheckpoint || willSimulate;
callback({ willCheckpointAndRestore });
if (!willCheckpointAndRestore) {
return;
}
const checkpoint = await this.#checkpointer.checkpointAndPush({
runId: socket.data.runId,
projectRef: socket.data.projectRef,
deploymentVersion: socket.data.deploymentVersion,
});
if (!checkpoint) {
logger.error("Failed to checkpoint", { runId: socket.data.runId });
return;
}
if (!checkpoint.docker || !willSimulate) {
socket.emit("REQUEST_EXIT", {
version: "v1",
});
}
this.#platformSocket?.send("CHECKPOINT_CREATED", {
version: "v1",
attemptFriendlyId: message.attemptFriendlyId,
docker: checkpoint.docker,
location: checkpoint.location,
reason: {
type: "WAIT_FOR_BATCH",
batchFriendlyId: message.batchFriendlyId,
runFriendlyIds: message.runFriendlyIds,
},
});
});
socket.on("INDEX_TASKS", async (message, callback) => {
logger.log("[INDEX_TASKS]", message);
const workerAck = await this.#platformSocket?.sendWithAck("CREATE_WORKER", {
version: "v1",
projectRef: socket.data.projectRef,
envId: socket.data.envId,
deploymentId: message.deploymentId,
metadata: {
contentHash: socket.data.contentHash,
packageVersion: message.packageVersion,
tasks: message.tasks,
},
});
if (!workerAck) {
logger.debug("no worker ack while indexing", message);
}
callback({ success: !!workerAck?.success });
});
socket.on("INDEXING_FAILED", async (message) => {
logger.log("[INDEXING_FAILED]", message);
this.#platformSocket?.send("INDEXING_FAILED", {
version: "v1",
deploymentId: message.deploymentId,
error: message.error,
});
});
},
onDisconnect: async (socket, handler, sender, logger) => {
this.#platformSocket?.send("LOG", {
metadata: socket.data,
text: "disconnect",
});
},
handlers: {
TASK_HEARTBEAT: async (message) => {
this.#platformSocket?.send("TASK_HEARTBEAT", message);
},
},
});
return provider;
}
#cancelCheckpoint(runId: string) {
const checkpointWait = this.#checkpointableTasks.get(runId);
if (checkpointWait) {
// Stop waiting for task to reach checkpointable state
checkpointWait.reject("Checkpoint cancelled");
}
// Cancel checkpointing procedure
this.#checkpointer.cancelCheckpoint(runId);
}
#createHttpServer() {
const httpServer = createServer(async (req, res) => {
logger.log(`[${req.method}]`, req.url);
const reply = new HttpReply(res);
switch (req.url) {
case "/health": {
return reply.text("ok");
}
case "/metrics": {
return reply.text(await register.metrics(), 200, register.contentType);
}
case "/whoami": {
return reply.text(NODE_NAME);
}
case "/checkpoint": {
const body = await getTextBody(req);
// await this.#checkpointer.checkpointAndPush(body);
return reply.text(`sent restore request: ${body}`);
}
default: {
return reply.empty(404);
}
}
});
httpServer.on("clientError", (err, socket) => {
socket.end("HTTP/1.1 400 Bad Request\r\n\r\n");
});
httpServer.on("listening", () => {
logger.log("server listening on port", HTTP_SERVER_PORT);
});
return httpServer;
}
listen() {
this.#httpServer.listen(this.port, this.host);
}
}
const coordinator = new TaskCoordinator(HTTP_SERVER_PORT);
coordinator.listen();
+19
View File
@@ -0,0 +1,19 @@
{
"include": ["./src/**/*.ts"],
"exclude": ["node_modules"],
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"resolveJsonModule": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"@trigger.dev/core/v3": ["../../packages/core/src/v3"],
"@trigger.dev/core/v3/*": ["../../packages/core/src/v3/*"],
"@trigger.dev/core-apps": ["../../packages/core-apps/src"],
"@trigger.dev/core-apps/*": ["../../packages/core-apps/src/*"]
}
}
}
+9
View File
@@ -0,0 +1,9 @@
HTTP_SERVER_PORT=8050
PLATFORM_WS_PORT=3030
PLATFORM_SECRET=provider-secret
SECURE_CONNECTION=false
# Use this if you are on macOS
# COORDINATOR_HOST="host.docker.internal"
# OTEL_EXPORTER_OTLP_ENDPOINT="http://host.docker.internal:4318"
+3
View File
@@ -0,0 +1,3 @@
dist/
node_modules/
.env
+16
View File
@@ -0,0 +1,16 @@
# syntax=docker/dockerfile:labs
FROM node:18-slim AS base
RUN apt-get update \
&& apt-get install -y dumb-init
FROM base
WORKDIR /app
COPY --chown=node dist/index.mjs /app/
EXPOSE 8000
ENTRYPOINT [ "/usr/bin/dumb-init", "--", "/usr/local/bin/node", "/app/index.mjs" ]
+3
View File
@@ -0,0 +1,3 @@
# Docker provider
The `docker-provider` allows the platform to be orchestrator-agnostic. The platform can perform actions such as `INDEX_TASKS` or `INVOKE_TASK` which the provider translates into Docker actions.
+31
View File
@@ -0,0 +1,31 @@
{
"name": "docker-provider",
"private": true,
"version": "0.0.1",
"description": "",
"main": "dist/index.cjs",
"scripts": {
"build": "npm run build:bundle",
"build:bundle": "esbuild src/index.ts --bundle --outfile=dist/index.mjs --platform=node --format=esm --target=esnext --banner:js=\"import { createRequire } from 'module';const require = createRequire(import.meta.url);\"",
"build:image": "docker build -f Containerfile . -t docker-provider",
"dev": "tsx --no-warnings=ExperimentalWarning --require dotenv/config --watch src/index.ts",
"start": "tsx src/index.ts",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@trigger.dev/core": "workspace:*",
"@trigger.dev/core-apps": "workspace:*",
"execa": "^8.0.1",
"socket.io-client": "^4.7.4"
},
"devDependencies": {
"@types/node": "^18.19.8",
"dotenv": "^16.4.2",
"esbuild": "^0.19.11",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
+302
View File
@@ -0,0 +1,302 @@
import { $, type ExecaChildProcess, execa } from "execa";
import {
SimpleLogger,
TaskOperations,
ProviderShell,
TaskOperationsRestoreOptions,
TaskOperationsCreateOptions,
TaskOperationsIndexOptions,
} from "@trigger.dev/core-apps";
import { setTimeout } from "node:timers/promises";
import { PostStartCauses, PreStopCauses } from "@trigger.dev/core/v3";
const MACHINE_NAME = process.env.MACHINE_NAME || "local";
const COORDINATOR_PORT = process.env.COORDINATOR_PORT || 8020;
const COORDINATOR_HOST = process.env.COORDINATOR_HOST || "127.0.0.1";
const OTEL_EXPORTER_OTLP_ENDPOINT =
process.env.OTEL_EXPORTER_OTLP_ENDPOINT || "http://0.0.0.0:4318";
const logger = new SimpleLogger(`[${MACHINE_NAME}]`);
type InitializeReturn = {
canCheckpoint: boolean;
willSimulate: boolean;
};
function isExecaChildProcess(maybeExeca: unknown): maybeExeca is Awaited<ExecaChildProcess> {
return typeof maybeExeca === "object" && maybeExeca !== null && "escapedCommand" in maybeExeca;
}
class DockerTaskOperations implements TaskOperations {
#initialized = false;
#canCheckpoint = false;
constructor(private opts = { forceSimulate: false }) {}
async #initialize(): Promise<InitializeReturn> {
if (this.#initialized) {
return this.#getInitializeReturn();
}
logger.log("Initializing task operations");
if (this.opts.forceSimulate) {
logger.log("Forced simulation enabled. Will simulate regardless of checkpoint support.");
}
try {
await $`criu --version`;
} catch (error) {
logger.error("No checkpoint support: Missing CRIU binary. Will simulate instead.");
this.#canCheckpoint = false;
this.#initialized = true;
return this.#getInitializeReturn();
}
try {
await $`docker checkpoint`;
} catch (error) {
logger.error("No checkpoint support: Docker needs to have experimental features enabled");
logger.error("Will simulate instead");
this.#canCheckpoint = false;
this.#initialized = true;
return this.#getInitializeReturn();
}
logger.log("Full checkpoint support!");
this.#initialized = true;
this.#canCheckpoint = true;
return this.#getInitializeReturn();
}
#getInitializeReturn(): InitializeReturn {
return {
canCheckpoint: this.#canCheckpoint,
willSimulate: !this.#canCheckpoint || this.opts.forceSimulate,
};
}
async index(opts: TaskOperationsIndexOptions) {
await this.#initialize();
const containerName = this.#getIndexContainerName(opts.shortCode);
logger.log(`Indexing task ${opts.imageRef}`, {
host: COORDINATOR_HOST,
port: COORDINATOR_PORT,
});
try {
logger.debug(
await execa("docker", [
"run",
"--network=host",
"--rm",
`--env=INDEX_TASKS=true`,
`--env=TRIGGER_SECRET_KEY=${opts.apiKey}`,
`--env=TRIGGER_API_URL=${opts.apiUrl}`,
`--env=TRIGGER_ENV_ID=${opts.envId}`,
`--env=OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT}`,
`--env=POD_NAME=${containerName}`,
`--env=COORDINATOR_HOST=${COORDINATOR_HOST}`,
`--env=COORDINATOR_PORT=${COORDINATOR_PORT}`,
`--name=${containerName}`,
`${opts.imageRef}`,
])
);
} catch (error: any) {
if (!isExecaChildProcess(error)) {
throw error;
}
logger.error("Index failed:", {
opts,
exitCode: error.exitCode,
escapedCommand: error.escapedCommand,
stdout: error.stdout,
stderr: error.stderr,
});
}
}
async create(opts: TaskOperationsCreateOptions) {
await this.#initialize();
const containerName = this.#getRunContainerName(opts.runId);
try {
logger.debug(
await execa("docker", [
"run",
"--network=host",
"--detach",
`--env=TRIGGER_ENV_ID=${opts.envId}`,
`--env=TRIGGER_RUN_ID=${opts.runId}`,
`--env=OTEL_EXPORTER_OTLP_ENDPOINT=${OTEL_EXPORTER_OTLP_ENDPOINT}`,
`--env=POD_NAME=${containerName}`,
`--env=COORDINATOR_HOST=${COORDINATOR_HOST}`,
`--env=COORDINATOR_PORT=${COORDINATOR_PORT}`,
`--name=${containerName}`,
`${opts.image}`,
])
);
} catch (error) {
if (!isExecaChildProcess(error)) {
throw error;
}
logger.error("Create failed:", {
opts,
exitCode: error.exitCode,
escapedCommand: error.escapedCommand,
stdout: error.stdout,
stderr: error.stderr,
});
}
}
async restore(opts: TaskOperationsRestoreOptions) {
await this.#initialize();
const containerName = this.#getRunContainerName(opts.runId);
if (!this.#canCheckpoint || this.opts.forceSimulate) {
logger.log("Simulating restore");
const unpause = logger.debug(await $`docker unpause ${containerName}`);
if (unpause.exitCode !== 0) {
throw new Error("docker unpause command failed");
}
await this.#sendPostStart(containerName);
return;
}
const { exitCode } = logger.debug(
await $`docker start --checkpoint=${opts.checkpointRef} ${containerName}`
);
if (exitCode !== 0) {
throw new Error("docker start command failed");
}
await this.#sendPostStart(containerName);
}
async delete(opts: { runId: string }) {
await this.#initialize();
const containerName = this.#getRunContainerName(opts.runId);
await this.#sendPreStop(containerName);
logger.log("noop: delete");
}
async get(opts: { runId: string }) {
await this.#initialize();
logger.log("noop: get");
}
#getIndexContainerName(suffix: string) {
return `task-index-${suffix}`;
}
#getRunContainerName(suffix: string) {
return `task-run-${suffix}`;
}
async #sendPostStart(containerName: string): Promise<void> {
try {
const port = await this.#getHttpServerPort(containerName);
logger.debug(await this.#runLifecycleCommand(containerName, port, "postStart", "restore"));
} catch (error) {
logger.error("postStart error", { error });
throw new Error("postStart command failed");
}
}
async #sendPreStop(containerName: string): Promise<void> {
try {
const port = await this.#getHttpServerPort(containerName);
logger.debug(await this.#runLifecycleCommand(containerName, port, "preStop", "terminate"));
} catch (error) {
logger.error("preStop error", { error });
throw new Error("preStop command failed");
}
}
async #getHttpServerPort(containerName: string): Promise<number> {
// We first get the correct port, which is random during dev as we run with host networking and need to avoid clashes
// FIXME: Skip this in prod
const logs = logger.debug(await $`docker logs ${containerName}`);
const matches = logs.stdout.match(/http server listening on port (?<port>[0-9]+)/);
const port = Number(matches?.groups?.port);
if (!port) {
throw new Error("failed to extract port from logs");
}
return port;
}
async #runLifecycleCommand<THookType extends "postStart" | "preStop">(
containerName: string,
port: number,
type: THookType,
cause: THookType extends "postStart" ? PostStartCauses : PreStopCauses,
retryCount = 0
): Promise<ExecaChildProcess> {
try {
return await execa("docker", [
"exec",
containerName,
"busybox",
"wget",
"-q",
"-O-",
`127.0.0.1:${port}/${type}?cause=${cause}`,
]);
} catch (error: any) {
if (type === "postStart" && retryCount < 6) {
logger.debug(`retriable ${type} error`, { retryCount, message: error?.message });
await setTimeout(exponentialBackoff(retryCount + 1, 2, 50, 1150, 50));
return this.#runLifecycleCommand(containerName, port, type, cause, retryCount + 1);
}
logger.error(`final ${type} error`, { message: error?.message });
throw new Error(`${type} command failed after ${retryCount - 1} retries`);
}
}
}
const provider = new ProviderShell({
tasks: new DockerTaskOperations({ forceSimulate: true }),
type: "docker",
});
provider.listen();
function exponentialBackoff(
retryCount: number,
exponential: number,
minDelay: number,
maxDelay: number,
jitter: number
): number {
// Calculate the delay using the exponential backoff formula
const delay = Math.min(Math.pow(exponential, retryCount) * minDelay, maxDelay);
// Calculate the jitter
const jitterValue = Math.random() * jitter;
// Return the calculated delay with jitter
return delay + jitterValue;
}
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"@trigger.dev/core/v3": ["../../packages/core/src/v3"],
"@trigger.dev/core/v3/*": ["../../packages/core/src/v3/*"],
"@trigger.dev/core-apps": ["../../packages/core-apps/src"],
"@trigger.dev/core-apps/*": ["../../packages/core-apps/src/*"]
}
}
}
+9
View File
@@ -0,0 +1,9 @@
HTTP_SERVER_PORT=8060
PLATFORM_WS_PORT=3030
PLATFORM_SECRET=provider-secret
SECURE_CONNECTION=false
# Use this if you are on macOS
# COORDINATOR_HOST="host.docker.internal"
# OTEL_EXPORTER_OTLP_ENDPOINT="http://host.docker.internal:4318"
+3
View File
@@ -0,0 +1,3 @@
dist/
node_modules/
.env
+47
View File
@@ -0,0 +1,47 @@
FROM node:18-alpine@sha256:ca9f6cb0466f9638e59e0c249d335a07c867cd50c429b5c7830dda1bed584649 AS node-18-alpine
WORKDIR /app
FROM node-18-alpine AS pruner
COPY --chown=node:node . .
RUN npx -q turbo@1.10.9 prune --scope=kubernetes-provider --docker
RUN find . -name "node_modules" -type d -prune -exec rm -rf '{}' +
FROM node-18-alpine AS base
RUN apk add --no-cache dumb-init
COPY --chown=node:node .gitignore .gitignore
COPY --from=pruner --chown=node:node /app/out/json/ .
COPY --from=pruner --chown=node:node /app/out/pnpm-lock.yaml ./pnpm-lock.yaml
COPY --from=pruner --chown=node:node /app/out/pnpm-workspace.yaml ./pnpm-workspace.yaml
FROM base AS dev-deps
RUN corepack enable
ENV NODE_ENV development
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm fetch --no-frozen-lockfile
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store pnpm install --ignore-scripts --no-frozen-lockfile
FROM base AS builder
RUN corepack enable
COPY --from=pruner --chown=node:node /app/out/full/ .
COPY --from=dev-deps --chown=node:node /app/ .
COPY --chown=node:node turbo.json turbo.json
RUN pnpm run -r --filter kubernetes-provider build:bundle
FROM base AS runner
RUN corepack enable
ENV NODE_ENV production
COPY --from=builder --chown=node:node /app/apps/kubernetes-provider/dist/index.mjs ./index.mjs
EXPOSE 8000
USER node
CMD [ "/usr/bin/dumb-init", "--", "/usr/local/bin/node", "./index.mjs" ]
+3
View File
@@ -0,0 +1,3 @@
# Kubernetes provider
The `kubernetes-provider` allows the platform to be orchestrator-agnostic. The platform can perform actions such as `INDEX_TASKS` or `INVOKE_TASK` which the provider translates into Kubernetes actions.
+31
View File
@@ -0,0 +1,31 @@
{
"name": "kubernetes-provider",
"private": true,
"version": "0.0.1",
"description": "",
"main": "dist/index.cjs",
"scripts": {
"build": "npm run build:bundle",
"build:bundle": "esbuild src/index.ts --bundle --outfile=dist/index.mjs --platform=node --format=esm --target=esnext --banner:js=\"import { createRequire } from 'module';const require = createRequire(import.meta.url);\"",
"build:image": "docker build -f Containerfile . -t kubernetes-provider",
"dev": "tsx --no-warnings=ExperimentalWarning --require dotenv/config --watch src/index.ts",
"start": "tsx src/index.ts",
"typecheck": "tsc --noEmit"
},
"keywords": [],
"author": "",
"license": "MIT",
"dependencies": {
"@kubernetes/client-node": "^0.20.0",
"@trigger.dev/core": "workspace:*",
"@trigger.dev/core-apps": "workspace:*",
"p-queue": "^8.0.1",
"socket.io-client": "^4.7.4"
},
"devDependencies": {
"dotenv": "^16.4.2",
"esbuild": "^0.19.11",
"tsx": "^4.7.0",
"typescript": "^5.3.3"
}
}
+544
View File
@@ -0,0 +1,544 @@
import * as k8s from "@kubernetes/client-node";
import {
ProviderShell,
SimpleLogger,
TaskOperations,
TaskOperationsCreateOptions,
TaskOperationsIndexOptions,
TaskOperationsRestoreOptions,
} from "@trigger.dev/core-apps";
import { Machine, PostStartCauses, PreStopCauses, EnvironmentType } from "@trigger.dev/core/v3";
import { randomUUID } from "crypto";
import { TaskMonitor } from "./taskMonitor";
const RUNTIME_ENV = process.env.KUBERNETES_PORT ? "kubernetes" : "local";
const NODE_NAME = process.env.NODE_NAME || "local";
const OTEL_EXPORTER_OTLP_ENDPOINT =
process.env.OTEL_EXPORTER_OTLP_ENDPOINT ?? "http://0.0.0.0:4318";
const logger = new SimpleLogger(`[${NODE_NAME}]`);
logger.log(`running in ${RUNTIME_ENV} mode`);
type Namespace = {
metadata: {
name: string;
};
};
type ComputeResources = {
[K in "cpu" | "memory" | "ephemeral-storage"]?: string;
};
class KubernetesTaskOperations implements TaskOperations {
#namespace: Namespace;
#k8sApi: {
core: k8s.CoreV1Api;
batch: k8s.BatchV1Api;
};
constructor(namespace = "default") {
this.#namespace = {
metadata: {
name: namespace,
},
};
this.#k8sApi = this.#createK8sApi();
}
async index(opts: TaskOperationsIndexOptions) {
await this.#createJob(
{
metadata: {
name: this.#getIndexContainerName(opts.shortCode),
namespace: this.#namespace.metadata.name,
},
spec: {
completions: 1,
backoffLimit: 0,
ttlSecondsAfterFinished: 300,
template: {
metadata: {
labels: {
...this.#getSharedLabels(opts),
app: "task-index",
"app.kubernetes.io/part-of": "trigger-worker",
"app.kubernetes.io/component": "index",
deployment: opts.deploymentId,
},
},
spec: {
...this.#defaultPodSpec,
containers: [
{
name: this.#getIndexContainerName(opts.shortCode),
image: opts.imageRef,
ports: [
{
containerPort: 8000,
},
],
resources: {
limits: {
cpu: "250m",
memory: "0.5G",
"ephemeral-storage": "2Gi",
},
},
lifecycle: {
preStop: {
exec: {
command: this.#getLifecycleCommand("preStop", "terminate"),
},
},
},
env: [
...this.#getSharedEnv(opts.envId),
{
name: "INDEX_TASKS",
value: "true",
},
{
name: "TRIGGER_SECRET_KEY",
value: opts.apiKey,
},
{
name: "TRIGGER_API_URL",
value: opts.apiUrl,
},
],
},
],
},
},
},
},
this.#namespace
);
}
async create(opts: TaskOperationsCreateOptions) {
await this.#createPod(
{
metadata: {
name: this.#getRunContainerName(opts.runId),
namespace: this.#namespace.metadata.name,
labels: {
...this.#getSharedLabels(opts),
app: "task-run",
"app.kubernetes.io/part-of": "trigger-worker",
"app.kubernetes.io/component": "create",
run: opts.runId,
},
},
spec: {
...this.#defaultPodSpec,
terminationGracePeriodSeconds: 60 * 60,
containers: [
{
name: this.#getRunContainerName(opts.runId),
image: opts.image,
ports: [
{
containerPort: 8000,
},
],
resources: {
requests: {
...this.#defaultResourceRequests,
},
limits: {
...this.#defaultResourceLimits,
...this.#getResourcesFromMachineConfig(opts.machine),
},
},
lifecycle: {
preStop: {
exec: {
command: this.#getLifecycleCommand("preStop", "terminate"),
},
},
},
env: [
...this.#getSharedEnv(opts.envId),
{
name: "TRIGGER_RUN_ID",
value: opts.runId,
},
],
volumeMounts: [
{
name: "taskinfo",
mountPath: "/etc/taskinfo",
},
],
},
],
volumes: [
{
name: "taskinfo",
emptyDir: {},
},
],
},
},
this.#namespace
);
}
async restore(opts: TaskOperationsRestoreOptions) {
await this.#createPod(
{
metadata: {
name: `${this.#getRunContainerName(opts.runId)}-${randomUUID().slice(0, 8)}`,
namespace: this.#namespace.metadata.name,
labels: {
...this.#getSharedLabels(opts),
app: "task-run",
"app.kubernetes.io/part-of": "trigger-worker",
"app.kubernetes.io/component": "restore",
run: opts.runId,
checkpoint: opts.checkpointId,
},
},
spec: {
...this.#defaultPodSpec,
initContainers: [
{
name: "pull-base-image",
image: opts.imageRef,
command: ["sleep", "0"],
},
{
name: "populate-taskinfo",
image: "busybox",
command: ["/bin/sh", "-c"],
args: ["printenv COORDINATOR_HOST | tee /etc/taskinfo/coordinator-host"],
env: [
{
name: "COORDINATOR_HOST",
valueFrom: {
fieldRef: {
fieldPath: "status.hostIP",
},
},
},
],
volumeMounts: [
{
name: "taskinfo",
mountPath: "/etc/taskinfo",
},
],
},
],
containers: [
{
name: this.#getRunContainerName(opts.runId),
image: opts.checkpointRef,
ports: [
{
containerPort: 8000,
},
],
resources: {
requests: {
...this.#defaultResourceRequests,
},
limits: {
...this.#defaultResourceLimits,
...this.#getResourcesFromMachineConfig(opts.machine),
},
},
lifecycle: {
postStart: {
exec: {
command: this.#getLifecycleCommand("postStart", "restore"),
},
},
preStop: {
exec: {
command: this.#getLifecycleCommand("preStop", "terminate"),
},
},
},
volumeMounts: [
{
name: "taskinfo",
mountPath: "/etc/taskinfo",
},
],
},
],
volumes: [
{
name: "taskinfo",
emptyDir: {},
},
],
},
},
this.#namespace
);
}
async delete(opts: { runId: string }) {
await this.#deletePod({
runId: opts.runId,
namespace: this.#namespace,
});
}
async get(opts: { runId: string }) {
await this.#getPod(opts.runId, this.#namespace);
}
#envTypeToLabelValue(type: EnvironmentType) {
switch (type) {
case "PRODUCTION":
return "prod";
case "STAGING":
return "stg";
case "DEVELOPMENT":
return "dev";
case "PREVIEW":
return "preview";
}
}
get #defaultPodSpec(): Omit<k8s.V1PodSpec, "containers"> {
return {
restartPolicy: "Never",
automountServiceAccountToken: false,
imagePullSecrets: [
{
name: "registry-trigger",
},
],
nodeSelector: {
nodetype: "worker",
},
};
}
get #defaultResourceRequests(): ComputeResources {
return {
"ephemeral-storage": "2Gi",
};
}
get #defaultResourceLimits(): ComputeResources {
return {
"ephemeral-storage": "10Gi",
};
}
#getSharedEnv(envId: string): k8s.V1EnvVar[] {
return [
{
name: "TRIGGER_ENV_ID",
value: envId,
},
{
name: "DEBUG",
value: process.env.DEBUG ? "1" : "0",
},
{
name: "HTTP_SERVER_PORT",
value: "8000",
},
{
name: "OTEL_EXPORTER_OTLP_ENDPOINT",
value: OTEL_EXPORTER_OTLP_ENDPOINT,
},
{
name: "POD_NAME",
valueFrom: {
fieldRef: {
fieldPath: "metadata.name",
},
},
},
{
name: "COORDINATOR_HOST",
valueFrom: {
fieldRef: {
fieldPath: "status.hostIP",
},
},
},
{
name: "MACHINE_NAME",
valueFrom: {
fieldRef: {
fieldPath: "spec.nodeName",
},
},
},
];
}
#getSharedLabels(
opts: TaskOperationsIndexOptions | TaskOperationsCreateOptions | TaskOperationsRestoreOptions
): Record<string, string> {
return {
env: opts.envId,
envtype: this.#envTypeToLabelValue(opts.envType),
org: opts.orgId,
project: opts.projectId,
};
}
#getResourcesFromMachineConfig(config: Machine): ComputeResources {
return {
cpu: `${config.cpu}`,
memory: `${config.memory}G`,
};
}
#getLifecycleCommand<THookType extends "postStart" | "preStop">(
type: THookType,
cause: THookType extends "postStart" ? PostStartCauses : PreStopCauses
) {
const retries = 5;
// This will retry sending the lifecycle hook up to `retries` times
// The sleep is required as this may start running before the HTTP server is up
const exec = [
"/bin/sh",
"-c",
`for i in $(seq ${retries}); do sleep 1; busybox wget -q -O- 127.0.0.1:8000/${type}?cause=${cause} && break; done`,
];
logger.debug("getLifecycleCommand()", { exec });
return exec;
}
#getIndexContainerName(suffix: string) {
return `task-index-${suffix}`;
}
#getRunContainerName(suffix: string) {
return `task-run-${suffix}`;
}
#createK8sApi() {
const kubeConfig = new k8s.KubeConfig();
if (RUNTIME_ENV === "local") {
kubeConfig.loadFromDefault();
} else if (RUNTIME_ENV === "kubernetes") {
kubeConfig.loadFromCluster();
} else {
throw new Error(`Unsupported runtime environment: ${RUNTIME_ENV}`);
}
return {
core: kubeConfig.makeApiClient(k8s.CoreV1Api),
batch: kubeConfig.makeApiClient(k8s.BatchV1Api),
};
}
async #createPod(pod: k8s.V1Pod, namespace: Namespace) {
try {
const res = await this.#k8sApi.core.createNamespacedPod(namespace.metadata.name, pod);
logger.debug(res.body);
} catch (err: unknown) {
this.#handleK8sError(err);
}
}
async #deletePod(opts: { runId: string; namespace: Namespace }) {
try {
const res = await this.#k8sApi.core.deleteNamespacedPod(
opts.runId,
opts.namespace.metadata.name
);
logger.debug(res.body);
} catch (err: unknown) {
this.#handleK8sError(err);
}
}
async #getPod(runId: string, namespace: Namespace) {
try {
const res = await this.#k8sApi.core.readNamespacedPod(runId, namespace.metadata.name);
logger.debug(res.body);
return res.body;
} catch (err: unknown) {
this.#handleK8sError(err);
}
}
async #createJob(job: k8s.V1Job, namespace: Namespace) {
try {
const res = await this.#k8sApi.batch.createNamespacedJob(namespace.metadata.name, job);
logger.debug(res.body);
} catch (err: unknown) {
this.#handleK8sError(err);
}
}
#throwUnlessRecord(candidate: unknown): asserts candidate is Record<string, unknown> {
if (typeof candidate !== "object" || candidate === null) {
throw candidate;
}
}
#handleK8sError(err: unknown) {
this.#throwUnlessRecord(err);
if ("body" in err && err.body) {
logger.error(err.body);
this.#throwUnlessRecord(err.body);
if (typeof err.body.message === "string") {
throw new Error(err.body?.message);
} else {
throw err.body;
}
} else {
logger.error(err);
throw err;
}
}
}
const provider = new ProviderShell({
tasks: new KubernetesTaskOperations(),
type: "kubernetes",
});
provider.listen();
const taskMonitor = new TaskMonitor({
runtimeEnv: RUNTIME_ENV,
onIndexFailure: async (deploymentId, failureInfo) => {
logger.log("Indexing failed", { deploymentId, failureInfo });
try {
provider.platformSocket.send("INDEXING_FAILED", {
deploymentId,
error: {
name: `Crashed with exit code ${failureInfo.exitCode}`,
message: failureInfo.reason,
stack: failureInfo.logs,
},
});
} catch (error) {
logger.error(error);
}
},
onRunFailure: async (runId, failureInfo) => {
logger.log("Run failed:", { runId, failureInfo });
try {
provider.platformSocket.send("WORKER_CRASHED", { runId, ...failureInfo });
} catch (error) {
logger.error(error);
}
},
});
taskMonitor.start();
+442
View File
@@ -0,0 +1,442 @@
import * as k8s from "@kubernetes/client-node";
import { SimpleLogger } from "@trigger.dev/core-apps";
import { setTimeout } from "timers/promises";
import PQueue from "p-queue";
type IndexFailureHandler = (
deploymentId: string,
failureInfo: {
exitCode: number;
reason: string;
logs: string;
}
) => Promise<any>;
type RunFailureHandler = (
runId: string,
failureInfo: {
exitCode: number;
reason: string;
logs: string;
}
) => Promise<any>;
type TaskMonitorOptions = {
runtimeEnv: "local" | "kubernetes";
onIndexFailure?: IndexFailureHandler;
onRunFailure?: RunFailureHandler;
namespace?: string;
};
export class TaskMonitor {
#enabled = false;
#logger = new SimpleLogger("[TaskMonitor]");
#taskInformer: ReturnType<typeof k8s.makeInformer<k8s.V1Pod>>;
#processedPods = new Map<string, number>();
#queue = new PQueue({ concurrency: 10 });
#k8sClient: {
core: k8s.CoreV1Api;
kubeConfig: k8s.KubeConfig;
};
private namespace = "default";
private fieldSelector = "status.phase=Failed";
private labelSelector = "app in (task-index, task-run)";
constructor(private opts: TaskMonitorOptions) {
this.#k8sClient = this.#createK8sClient();
this.#taskInformer = this.#createTaskInformer();
this.#taskInformer.on("connect", this.#onInformerConnected.bind(this));
this.#taskInformer.on("error", this.#onInformerError.bind(this));
this.#taskInformer.on("update", this.#enqueueOnPodUpdated.bind(this));
}
#createTaskInformer() {
const listTasks = () =>
this.#k8sClient.core.listNamespacedPod(
this.namespace,
undefined,
undefined,
undefined,
this.fieldSelector,
this.labelSelector
);
// Uses watch with local caching
// https://kubernetes.io/docs/reference/using-api/api-concepts/#efficient-detection-of-changes
const informer = k8s.makeInformer(
this.#k8sClient.kubeConfig,
`/api/v1/namespaces/${this.namespace}/pods`,
listTasks,
this.labelSelector,
this.fieldSelector
);
return informer;
}
async #onInformerConnected() {
this.#logger.log("Connected");
}
async #onInformerError(error: any) {
this.#logger.error("Error:", error);
// Automatic reconnect
await setTimeout(2_000);
this.#taskInformer.start();
}
#enqueueOnPodUpdated(pod: k8s.V1Pod) {
this.#queue.add(async () => {
try {
// It would be better to only pass the cache key, but the pod may already be removed from the cache by the time we process it
await this.#onPodUpdated(pod);
} catch (error) {
this.#logger.error("Caught onPodUpdated() error:", error);
}
});
}
async #onPodUpdated(pod: k8s.V1Pod) {
this.#logger.debug(`Updated: ${pod.metadata?.name}`);
this.#logger.debug("Updated", JSON.stringify(pod, null, 2));
// We only care about failures
if (pod.status?.phase !== "Failed") {
return;
}
const podName = pod.metadata?.name;
if (!podName) {
this.#logger.error("Pod is nameless", { pod });
return;
}
const containerStatus = pod.status.containerStatuses?.[0];
if (!containerStatus?.state) {
this.#logger.error("Pod failed, but container status doesn't have state", {
status: pod.status,
});
return;
}
if (this.#processedPods.has(podName)) {
this.#logger.debug("Pod update already processed", {
podName,
timestamp: this.#processedPods.get(podName),
});
return;
}
this.#processedPods.set(podName, Date.now());
const podStatus = this.#getPodStatusSummary(pod.status);
const containerState = this.#getContainerStateSummary(containerStatus.state);
const exitCode = containerState.exitCode ?? -1;
// We use this special exit code to signal any errors were already handled elsewhere
if (exitCode === 111) {
return;
}
const rawLogs = await this.#getLogTail(podName);
this.#logger.log(`${podName} failed with:`, {
podStatus,
containerState,
rawLogs,
});
const rawReason = podStatus.reason ?? containerState.reason ?? "";
const message = podStatus.message ?? containerState.message ?? "";
let reason = rawReason || "Unknown error";
let logs = rawLogs || "";
switch (rawReason) {
case "Error":
reason = "Unknown error.";
break;
case "Evicted":
if (message.startsWith("Pod ephemeral local storage usage")) {
reason = "Storage limit exceeded.";
} else if (message) {
reason = `Evicted: ${message}`;
} else {
reason = "Evicted for unknown reason.";
}
if (logs.startsWith("failed to try resolving symlinks")) {
logs = "";
}
break;
case "OOMKilled":
reason = "Out of memory! Try increasing the memory on this task.";
break;
default:
break;
}
const failureInfo = {
exitCode,
reason,
logs,
};
const app = pod.metadata?.labels?.app;
switch (app) {
case "task-index":
const deploymentId = pod.metadata?.labels?.deployment;
if (!deploymentId) {
this.#logger.error("Index is missing ID", { pod });
return;
}
if (this.opts.onIndexFailure) {
await this.opts.onIndexFailure(deploymentId, failureInfo);
}
break;
case "task-run":
const runId = pod.metadata?.labels?.run;
if (!runId) {
this.#logger.error("Run is missing ID", { pod });
return;
}
if (this.opts.onRunFailure) {
await this.opts.onRunFailure(runId, failureInfo);
}
break;
default:
this.#logger.error("Pod has invalid app label", { pod });
return;
}
await this.#deletePod(podName);
}
async #getLogTail(podName: string) {
try {
const logs = await this.#k8sClient.core.readNamespacedPodLog(
podName,
this.namespace,
undefined,
undefined,
undefined,
1024, // limitBytes
undefined,
undefined,
undefined,
20 // tailLines
);
const responseBody = logs.body ?? "";
if (responseBody.startsWith("unable to retrieve container logs")) {
return "";
}
// Type is wrong, body may be undefined
return responseBody;
} catch (error) {
this.#logger.error("Log tail error:", error instanceof Error ? error.message : "unknown");
return "";
}
}
#getPodStatusSummary(status: k8s.V1PodStatus) {
return {
reason: status.reason,
message: status.message,
};
}
#getContainerStateSummary(state: k8s.V1ContainerState) {
return {
reason: state.terminated?.reason,
exitCode: state.terminated?.exitCode,
message: state.terminated?.message,
};
}
#createK8sClient() {
const kubeConfig = new k8s.KubeConfig();
if (this.opts.runtimeEnv === "local") {
kubeConfig.loadFromDefault();
} else if (this.opts.runtimeEnv === "kubernetes") {
kubeConfig.loadFromCluster();
} else {
throw new Error(`Unsupported runtime environment: ${this.opts.runtimeEnv}`);
}
return {
core: kubeConfig.makeApiClient(k8s.CoreV1Api),
kubeConfig: kubeConfig,
};
}
#isRecord(candidate: unknown): candidate is Record<string, unknown> {
if (typeof candidate !== "object" || candidate === null) {
return false;
} else {
return true;
}
}
#logK8sError(err: unknown, debugOnly = false) {
if (debugOnly) {
this.#logger.debug("K8s API Error", err);
} else {
this.#logger.error("K8s API Error", err);
}
}
#handleK8sError(err: unknown) {
if (!this.#isRecord(err) || !this.#isRecord(err.body)) {
this.#logK8sError(err);
return;
}
this.#logK8sError(err, true);
if (typeof err.body.message === "string") {
this.#logK8sError({ message: err.body.message });
return;
}
this.#logK8sError({ body: err.body });
}
#printStats(includeMoreDetails = false) {
this.#logger.log("Stats:", {
cacheSize: this.#taskInformer.list().length,
totalProcessed: this.#processedPods.size,
...(includeMoreDetails && {
processedPods: this.#processedPods,
}),
});
}
async #deletePod(name: string) {
this.#logger.debug("Deleting pod:", name);
await this.#k8sClient.core
.deleteNamespacedPod(name, this.namespace)
.catch(this.#handleK8sError.bind(this));
}
async start() {
this.#enabled = true;
const interval = setInterval(() => {
if (!this.#enabled) {
clearInterval(interval);
return;
}
this.#printStats();
}, 300_000);
await this.#taskInformer.start();
// this.#launchTests();
}
async stop() {
if (!this.#enabled) {
return;
}
this.#enabled = false;
this.#logger.log("Shutting down..");
await this.#taskInformer.stop();
this.#printStats(true);
}
async #launchTests() {
const createPod = async (
container: k8s.V1Container,
name: string,
labels?: Record<string, string>
) => {
this.#logger.log("Creating pod:", name);
const pod = {
metadata: {
name,
labels,
},
spec: {
restartPolicy: "Never",
automountServiceAccountToken: false,
terminationGracePeriodSeconds: 1,
containers: [container],
},
} satisfies k8s.V1Pod;
await this.#k8sClient.core
.createNamespacedPod(this.namespace, pod)
.catch(this.#handleK8sError.bind(this));
};
const createOomPod = async (name: string, labels?: Record<string, string>) => {
const container = {
name,
image: "polinux/stress",
resources: {
limits: {
memory: "100Mi",
},
},
command: ["stress"],
args: ["--vm", "1", "--vm-bytes", "150M", "--vm-hang", "1"],
} satisfies k8s.V1Container;
await createPod(container, name, labels);
};
const createNonZeroExitPod = async (name: string, labels?: Record<string, string>) => {
const container = {
name,
image: "busybox",
command: ["sh"],
args: ["-c", "exit 1"],
} satisfies k8s.V1Container;
await createPod(container, name, labels);
};
const createOoDiskPod = async (name: string, labels?: Record<string, string>) => {
const container = {
name,
image: "busybox",
command: ["sh"],
args: [
"-c",
"echo creating huge-file..; head -c 1000m /dev/zero > huge-file; ls -lh huge-file; sleep infinity",
],
resources: {
limits: {
"ephemeral-storage": "500Mi",
},
},
} satisfies k8s.V1Container;
await createPod(container, name, labels);
};
await createNonZeroExitPod("non-zero-exit-task", { app: "task-run", run: "123" });
await createOomPod("oom-task", { app: "task-index", deployment: "456" });
await createOoDiskPod("ood-task", { app: "task-run", run: "abc" });
}
}
+17
View File
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"strict": true,
"skipLibCheck": true,
"paths": {
"@trigger.dev/core/v3": ["../../packages/core/src/v3"],
"@trigger.dev/core/v3/*": ["../../packages/core/src/v3/*"],
"@trigger.dev/core-apps": ["../../packages/core-apps/src"],
"@trigger.dev/core-apps/*": ["../../packages/core-apps/src/*"]
}
}
}
+64
View File
@@ -1,5 +1,69 @@
# proxy
## 0.0.11
### Patch Changes
- @trigger.dev/core@2.3.5
## 0.0.10
### Patch Changes
- @trigger.dev/core@2.3.4
## 0.0.9
### Patch Changes
- @trigger.dev/core@2.3.3
## 0.0.8
### Patch Changes
- @trigger.dev/core@2.3.2
## 0.0.7
### Patch Changes
- Updated dependencies [f3efcc0c]
- @trigger.dev/core@2.3.1
## 0.0.6
### Patch Changes
- Updated dependencies [17f6f29d]
- @trigger.dev/core@2.3.0
## 0.0.5
### Patch Changes
- @trigger.dev/core@2.2.11
## 0.0.4
### Patch Changes
- @trigger.dev/core@2.2.10
## 0.0.3
### Patch Changes
- Updated dependencies [6ebd435e]
- @trigger.dev/core@2.2.9
## 0.0.2
### Patch Changes
- Updated dependencies [067e19fe]
- @trigger.dev/core@2.2.8
## 0.0.1
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "proxy",
"version": "0.0.1",
"version": "0.0.11",
"private": true,
"scripts": {
"deploy": "wrangler deploy",
-49
View File
@@ -1,49 +0,0 @@
import type { StorybookConfig } from "@storybook/react-webpack5";
import path from "path";
const root = path.resolve(__dirname, "../app");
const config: StorybookConfig = {
webpackFinal: async (config) => {
return {
...config,
resolve: {
...config.resolve,
alias: {
...(config.resolve?.alias ?? {}),
"~": root,
},
extensions: [
...(config.resolve?.extensions ?? []),
...[".ts", ".tsx", ".js", ".jsx", ".mdx"],
],
},
};
},
stories: ["../app/**/stories/*.mdx", "../app/**/stories/*.stories.@(js|jsx|ts|tsx)"],
addons: [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"storybook-addon-variants",
"storybook-addon-designs",
"@storybook/addon-docs",
{
name: "@storybook/addon-styling",
options: {
// Check out https://github.com/storybookjs/addon-styling/blob/main/docs/api.md
// For more details on this addon's options.
postCss: true,
},
},
],
framework: {
name: "@storybook/react-webpack5",
options: {},
},
docs: {
autodocs: "tag",
},
staticDirs: [path.resolve("public")],
};
export default config;
-50
View File
@@ -1,50 +0,0 @@
import type { Preview } from "@storybook/react";
import "../app/tailwind.css";
import { createRemixStub } from "@remix-run/testing";
import React from "react";
import { LocaleContextProvider } from "../app/components/primitives/LocaleProvider";
import { OperatingSystemContextProvider } from "../app/components/primitives/OperatingSystemProvider";
const preview: Preview = {
parameters: {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
backgrounds: {
default: "App background",
values: [
{
name: "App background",
value: "#0B1018",
},
],
},
layout: "fullscreen",
},
decorators: [
(Story) => {
const RemixStub = createRemixStub([
{
path: "/*",
action: () => ({ redirect: "/" }),
loader: () => ({ redirect: "/" }),
Component: Story,
},
]);
return (
<OperatingSystemContextProvider platform="mac">
<LocaleContextProvider locales={window.navigator.languages as string[]}>
<RemixStub initialEntries={["/"]} />
</LocaleContextProvider>
</OperatingSystemContextProvider>
);
},
],
};
export default preview;
@@ -0,0 +1,53 @@
export function AISparkleIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M14.9806 0.803884C14.8871 0.33646 14.4767 0 14 0C13.5233 0 13.1129 0.33646 13.0194 0.803884L12.7809 1.99644C12.7017 2.3923 12.3923 2.70174 11.9964 2.78091L10.8039 3.01942C10.3365 3.1129 10 3.52332 10 4C10 4.47668 10.3365 4.8871 10.8039 4.98058L11.9964 5.21909C12.3923 5.29826 12.7017 5.6077 12.7809 6.00356L13.0194 7.19612C13.1129 7.66354 13.5233 8 14 8C14.4767 8 14.8871 7.66354 14.9806 7.19612L15.2191 6.00356C15.2983 5.6077 15.6077 5.29826 16.0036 5.21909L17.1961 4.98058C17.6635 4.8871 18 4.47668 18 4C18 3.52332 17.6635 3.1129 17.1961 3.01942L16.0036 2.78091C15.6077 2.70174 15.2983 2.3923 15.2191 1.99644L14.9806 0.803884Z"
fill="url(#paint0_linear_11402_36656)"
/>
<path
d="M5.94868 4.68377C5.81257 4.27543 5.43043 4 5 4C4.56957 4 4.18743 4.27543 4.05132 4.68377L3.36754 6.73509C3.26801 7.03369 3.03369 7.26801 2.73509 7.36754L0.683772 8.05132C0.27543 8.18743 0 8.56957 0 9C0 9.43043 0.27543 9.81257 0.683772 9.94868L2.73509 10.6325C3.03369 10.732 3.26801 10.9663 3.36754 11.2649L4.05132 13.3162C4.18743 13.7246 4.56957 14 5 14C5.43043 14 5.81257 13.7246 5.94868 13.3162L6.63246 11.2649C6.73199 10.9663 6.96631 10.732 7.26491 10.6325L9.31623 9.94868C9.72457 9.81257 10 9.43043 10 9C10 8.56957 9.72457 8.18743 9.31623 8.05132L7.26491 7.36754C6.96631 7.26801 6.73199 7.03369 6.63246 6.73509L5.94868 4.68377Z"
fill="url(#paint1_linear_11402_36656)"
/>
<path
d="M12.9487 12.6838C12.8126 12.2754 12.4304 12 12 12C11.5696 12 11.1874 12.2754 11.0513 12.6838L10.8675 13.2351C10.768 13.5337 10.5337 13.768 10.2351 13.8675L9.68377 14.0513C9.27543 14.1874 9 14.5696 9 15C9 15.4304 9.27543 15.8126 9.68377 15.9487L10.2351 16.1325C10.5337 16.232 10.768 16.4663 10.8675 16.7649L11.0513 17.3162C11.1874 17.7246 11.5696 18 12 18C12.4304 18 12.8126 17.7246 12.9487 17.3162L13.1325 16.7649C13.232 16.4663 13.4663 16.232 13.7649 16.1325L14.3162 15.9487C14.7246 15.8126 15 15.4304 15 15C15 14.5696 14.7246 14.1874 14.3162 14.0513L13.7649 13.8675C13.4663 13.768 13.232 13.5337 13.1325 13.2351L12.9487 12.6838Z"
fill="url(#paint2_linear_11402_36656)"
/>
<defs>
<linearGradient
id="paint0_linear_11402_36656"
x1="9"
y1="0"
x2="9"
y2="18"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#E543FF" />
<stop offset="1" stopColor="#286399" />
</linearGradient>
<linearGradient
id="paint1_linear_11402_36656"
x1="9"
y1="0"
x2="9"
y2="18"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#E543FF" />
<stop offset="1" stopColor="#286399" />
</linearGradient>
<linearGradient
id="paint2_linear_11402_36656"
x1="9"
y1="0"
x2="9"
y2="18"
gradientUnits="userSpaceOnUse"
>
<stop stopColor="#E543FF" />
<stop offset="1" stopColor="#286399" />
</linearGradient>
</defs>
</svg>
);
}
@@ -0,0 +1,29 @@
export function AttemptIcon({ className }: { className?: string }) {
return (
<svg
className={className}
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_9964_113464)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16 0H0V16H16V0ZM7.09906 4.4L4.53906 11.5H6.11906L6.63906 10H9.35906L9.87906 11.5H11.4591L8.89906 4.4H7.09906ZM7.99906 6L8.92906 8.73H7.06906L7.99906 6Z"
fill="currentColor"
/>
</g>
<defs>
<clipPath id="clip0_9964_113464">
<path
d="M0 2C0 0.895431 0.895431 0 2 0H14C15.1046 0 16 0.895431 16 2V14C16 15.1046 15.1046 16 14 16H2C0.895431 16 0 15.1046 0 14V2Z"
fill="white"
/>
</clipPath>
</defs>
</svg>
);
}
+14
View File
@@ -0,0 +1,14 @@
export function ExitIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<line x1="3.5" y1="8" x2="11.5" y2="8" stroke="currentColor" strokeLinecap="round" />
<line x1="15.5" y1="1.5" x2="15.5" y2="14.5" stroke="currentColor" strokeLinecap="round" />
<path
d="M8.5 4.5L12 8L8.5 11.5"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
);
}
@@ -0,0 +1,25 @@
export function ShowParentIcon({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M3.125 16H3.625H4.125V15H3.125H2C1.89733 15 1.8 14.9848 1.70919 14.9573L1.19765 14.8024L1.04267 14.2908C1.01515 14.2 1 14.1027 1 14V12.875V11.875H0V12.375V12.875V14C0 14.202 0.0299409 14.397 0.0856265 14.5808C0.135047 14.7439 0.204744 14.8982 0.291786 15.0407C0.363386 15.158 0.446722 15.2673 0.540161 15.3671C0.570065 15.399 0.601004 15.4299 0.632924 15.4598C0.732663 15.5533 0.841982 15.6366 0.95925 15.7082C1.10181 15.7953 1.25612 15.865 1.41923 15.9144C1.60303 15.9701 1.79802 16 2 16H3.125ZM10.125 15V16H9.625H9.125H6.875H6.375H5.875V15H6.875H9.125H10.125ZM15 5.875H16V6.375V6.875V9.125V9.625V10.125H15V9.125V6.875V5.875ZM5.875 1V0H6.375H6.875H9.125H9.625H10.125V1H9.125H6.875H5.875ZM1 10.125H0V9.625V9.125V6.875V6.375V5.875H1V6.875V9.125V10.125ZM0 3.625V4.125H1V3.125V2C1 1.89733 1.01515 1.8 1.04267 1.70919L1.19765 1.19765L1.70919 1.04267C1.8 1.01515 1.89733 1 2 1H3.125H4.125V0H3.625H3.125H2C1.79802 0 1.60303 0.0299409 1.41923 0.0856264C1.25612 0.135047 1.10181 0.204744 0.95925 0.291786C0.841983 0.363386 0.732663 0.446722 0.632924 0.540161C0.601004 0.570065 0.570065 0.601004 0.540161 0.632924C0.446722 0.732663 0.363386 0.841982 0.291786 0.95925C0.204744 1.10181 0.135047 1.25612 0.0856265 1.41923C0.0299409 1.60303 0 1.79802 0 2V3.125V3.625ZM12.375 0H11.875V1H12.875H14C14.1027 1 14.2 1.01515 14.2908 1.04267L14.8024 1.19765L14.9573 1.70919C14.9848 1.8 15 1.89733 15 2V3.125V4.125H16V3.625V3.125V2C16 1.79802 15.9701 1.60303 15.9144 1.41923C15.865 1.25612 15.7953 1.10181 15.7082 0.95925C15.6366 0.841982 15.5533 0.732663 15.4598 0.632924C15.4299 0.601004 15.399 0.570065 15.3671 0.540161C15.2673 0.446722 15.158 0.363386 15.0407 0.291786C14.8982 0.204744 14.7439 0.135047 14.5808 0.0856265C14.397 0.0299409 14.202 0 14 0H12.875H12.375ZM16 12.375V11.875H15V12.875V14C15 14.1027 14.9848 14.2 14.9573 14.2908L14.8024 14.8024L14.2908 14.9573C14.2 14.9848 14.1027 15 14 15H12.875H11.875V16H12.375H12.875H14C14.202 16 14.397 15.9701 14.5808 15.9144C14.7439 15.865 14.8982 15.7953 15.0407 15.7082C15.158 15.6366 15.2673 15.5533 15.3671 15.4598C15.399 15.4299 15.4299 15.399 15.4598 15.3671C15.5533 15.2673 15.6366 15.158 15.7082 15.0407C15.7953 14.8982 15.865 14.7439 15.9144 14.5808C15.9701 14.397 16 14.202 16 14V12.875V12.375ZM8.75 6.26758L10.4523 7.96991C10.7452 8.26281 11.2201 8.26281 11.513 7.96991C11.8059 7.67702 11.8059 7.20215 11.513 6.90925L8.59099 3.98725C8.43431 3.83057 8.22556 3.7577 8.02045 3.76865C7.81604 3.75834 7.60821 3.83124 7.45209 3.98736L4.53009 6.90937C4.23719 7.20226 4.23719 7.67713 4.53009 7.97003C4.82298 8.26292 5.29785 8.26292 5.59075 7.97003L7.25 6.31077L7.25 11.25C7.25 11.6642 7.58579 12 8 12C8.41421 12 8.75 11.6642 8.75 11.25L8.75 6.26758Z"
/>
</svg>
);
}
export function ShowParentIconSelected({ className }: { className?: string }) {
return (
<svg className={className} viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fill="currentColor"
fillRule="evenodd"
clipRule="evenodd"
d="M2 0C0.895431 0 0 0.895431 0 2V14C0 15.1046 0.895431 16 2 16H14C15.1046 16 16 15.1046 16 14V2C16 0.895431 15.1046 0 14 0H2ZM8.75 6.26758L10.4523 7.96991C10.7452 8.26281 11.2201 8.26281 11.513 7.96991C11.8059 7.67702 11.8059 7.20215 11.513 6.90925L8.59099 3.98725C8.43344 3.8297 8.22324 3.7569 8.01703 3.76884C7.8138 3.75958 7.60752 3.83254 7.45234 3.98773L4.53033 6.90973C4.23744 7.20263 4.23744 7.6775 4.53033 7.97039C4.82322 8.26329 5.2981 8.26329 5.59099 7.97039L7.25 6.31138L7.25 11.25C7.25 11.6642 7.58579 12 8 12C8.41421 12 8.75 11.6642 8.75 11.25L8.75 6.26758Z"
/>
</svg>
);
}
+29
View File
@@ -0,0 +1,29 @@
export function TaskIcon({ className }: { className?: string }) {
return (
<svg
className={className}
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clipPath="url(#clip0_9221_99732)">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M16 0H0V16H16V0ZM10.8901 5.73995V4.44995H5.11011V5.73995H7.23011V11.55H8.77011V5.73995H10.8901Z"
fill="currentColor"
/>
</g>
<defs>
<clipPath id="clip0_9221_99732">
<path
d="M0 2C0 0.895431 0.895431 0 2 0H14C15.1046 0 16 0.895431 16 2V14C16 15.1046 15.1046 16 14 16H2C0.895431 16 0 15.1046 0 14V2Z"
fill="white"
/>
</clipPath>
</defs>
</svg>
);
}

Some files were not shown because too many files have changed in this diff Show More