trigger.dev 3.0.0-beta.33 → 3.0.0-beta.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +694 -236
- package/dist/index.js.map +1 -1
- package/dist/workers/dev/worker-facade.js +12 -10
- package/dist/workers/dev/worker-setup.js +13 -12
- package/dist/workers/prod/entry-point.js +522 -193
- package/dist/workers/prod/worker-facade.js +3 -24
- package/dist/workers/prod/worker-setup.js +8 -5
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -799,7 +799,7 @@ import invariant from "tiny-invariant";
|
|
|
799
799
|
import { z as z4 } from "zod";
|
|
800
800
|
|
|
801
801
|
// package.json
|
|
802
|
-
var version = "3.0.0-beta.
|
|
802
|
+
var version = "3.0.0-beta.35";
|
|
803
803
|
var dependencies = {
|
|
804
804
|
"@anatine/esbuild-decorators": "^0.2.19",
|
|
805
805
|
"@clack/prompts": "^0.7.0",
|
|
@@ -816,7 +816,7 @@ var dependencies = {
|
|
|
816
816
|
"@opentelemetry/sdk-trace-base": "^1.22.0",
|
|
817
817
|
"@opentelemetry/sdk-trace-node": "^1.22.0",
|
|
818
818
|
"@opentelemetry/semantic-conventions": "^1.22.0",
|
|
819
|
-
"@trigger.dev/core": "workspace:3.0.0-beta.
|
|
819
|
+
"@trigger.dev/core": "workspace:3.0.0-beta.35",
|
|
820
820
|
"@types/degit": "^2.8.3",
|
|
821
821
|
chalk: "^5.2.0",
|
|
822
822
|
chokidar: "^3.5.3",
|
|
@@ -948,8 +948,12 @@ import {
|
|
|
948
948
|
InitializeDeploymentResponseBody,
|
|
949
949
|
GetDeploymentResponseBody,
|
|
950
950
|
GetProjectsResponseBody,
|
|
951
|
-
GetProjectResponseBody
|
|
951
|
+
GetProjectResponseBody,
|
|
952
|
+
EnvironmentVariableResponseBody,
|
|
953
|
+
TaskRunExecution,
|
|
954
|
+
APIError
|
|
952
955
|
} from "@trigger.dev/core/v3";
|
|
956
|
+
import { zodfetch } from "@trigger.dev/core/v3/zodfetch";
|
|
953
957
|
var CliApiClient = class {
|
|
954
958
|
constructor(apiURL, accessToken) {
|
|
955
959
|
this.accessToken = accessToken;
|
|
@@ -957,7 +961,7 @@ var CliApiClient = class {
|
|
|
957
961
|
}
|
|
958
962
|
apiURL;
|
|
959
963
|
async createAuthorizationCode() {
|
|
960
|
-
return
|
|
964
|
+
return wrapZodFetch(
|
|
961
965
|
CreateAuthorizationCodeResponseSchema,
|
|
962
966
|
`${this.apiURL}/api/v1/authorization-code`,
|
|
963
967
|
{
|
|
@@ -966,7 +970,7 @@ var CliApiClient = class {
|
|
|
966
970
|
);
|
|
967
971
|
}
|
|
968
972
|
async getPersonalAccessToken(authorizationCode) {
|
|
969
|
-
return
|
|
973
|
+
return wrapZodFetch(GetPersonalAccessTokenResponseSchema, `${this.apiURL}/api/v1/token`, {
|
|
970
974
|
method: "POST",
|
|
971
975
|
body: JSON.stringify({
|
|
972
976
|
authorizationCode
|
|
@@ -977,7 +981,7 @@ var CliApiClient = class {
|
|
|
977
981
|
if (!this.accessToken) {
|
|
978
982
|
throw new Error("whoAmI: No access token");
|
|
979
983
|
}
|
|
980
|
-
return
|
|
984
|
+
return wrapZodFetch(WhoAmIResponseSchema, `${this.apiURL}/api/v2/whoami`, {
|
|
981
985
|
headers: {
|
|
982
986
|
Authorization: `Bearer ${this.accessToken}`,
|
|
983
987
|
"Content-Type": "application/json"
|
|
@@ -988,7 +992,7 @@ var CliApiClient = class {
|
|
|
988
992
|
if (!this.accessToken) {
|
|
989
993
|
throw new Error("getProject: No access token");
|
|
990
994
|
}
|
|
991
|
-
return
|
|
995
|
+
return wrapZodFetch(GetProjectResponseBody, `${this.apiURL}/api/v1/projects/${projectRef}`, {
|
|
992
996
|
headers: {
|
|
993
997
|
Authorization: `Bearer ${this.accessToken}`,
|
|
994
998
|
"Content-Type": "application/json"
|
|
@@ -999,7 +1003,7 @@ var CliApiClient = class {
|
|
|
999
1003
|
if (!this.accessToken) {
|
|
1000
1004
|
throw new Error("getProjects: No access token");
|
|
1001
1005
|
}
|
|
1002
|
-
return
|
|
1006
|
+
return wrapZodFetch(GetProjectsResponseBody, `${this.apiURL}/api/v1/projects`, {
|
|
1003
1007
|
headers: {
|
|
1004
1008
|
Authorization: `Bearer ${this.accessToken}`,
|
|
1005
1009
|
"Content-Type": "application/json"
|
|
@@ -1010,7 +1014,7 @@ var CliApiClient = class {
|
|
|
1010
1014
|
if (!this.accessToken) {
|
|
1011
1015
|
throw new Error("createBackgroundWorker: No access token");
|
|
1012
1016
|
}
|
|
1013
|
-
return
|
|
1017
|
+
return wrapZodFetch(
|
|
1014
1018
|
CreateBackgroundWorkerResponse,
|
|
1015
1019
|
`${this.apiURL}/api/v1/projects/${projectRef}/background-workers`,
|
|
1016
1020
|
{
|
|
@@ -1023,6 +1027,18 @@ var CliApiClient = class {
|
|
|
1023
1027
|
}
|
|
1024
1028
|
);
|
|
1025
1029
|
}
|
|
1030
|
+
async createTaskRunAttempt(runFriendlyId) {
|
|
1031
|
+
if (!this.accessToken) {
|
|
1032
|
+
throw new Error("creatTaskRunAttempt: No access token");
|
|
1033
|
+
}
|
|
1034
|
+
return wrapZodFetch(TaskRunExecution, `${this.apiURL}/api/v1/runs/${runFriendlyId}/attempts`, {
|
|
1035
|
+
method: "POST",
|
|
1036
|
+
headers: {
|
|
1037
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
1038
|
+
"Content-Type": "application/json"
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
}
|
|
1026
1042
|
async getProjectEnv({
|
|
1027
1043
|
projectRef,
|
|
1028
1044
|
env
|
|
@@ -1030,18 +1046,22 @@ var CliApiClient = class {
|
|
|
1030
1046
|
if (!this.accessToken) {
|
|
1031
1047
|
throw new Error("getProjectDevEnv: No access token");
|
|
1032
1048
|
}
|
|
1033
|
-
return
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1049
|
+
return wrapZodFetch(
|
|
1050
|
+
GetProjectEnvResponse,
|
|
1051
|
+
`${this.apiURL}/api/v1/projects/${projectRef}/${env}`,
|
|
1052
|
+
{
|
|
1053
|
+
headers: {
|
|
1054
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
1055
|
+
"Content-Type": "application/json"
|
|
1056
|
+
}
|
|
1037
1057
|
}
|
|
1038
|
-
|
|
1058
|
+
);
|
|
1039
1059
|
}
|
|
1040
1060
|
async getEnvironmentVariables(projectRef) {
|
|
1041
1061
|
if (!this.accessToken) {
|
|
1042
1062
|
throw new Error("getEnvironmentVariables: No access token");
|
|
1043
1063
|
}
|
|
1044
|
-
return
|
|
1064
|
+
return wrapZodFetch(
|
|
1045
1065
|
GetEnvironmentVariablesResponseBody,
|
|
1046
1066
|
`${this.apiURL}/api/v1/projects/${projectRef}/envvars`,
|
|
1047
1067
|
{
|
|
@@ -1052,11 +1072,28 @@ var CliApiClient = class {
|
|
|
1052
1072
|
}
|
|
1053
1073
|
);
|
|
1054
1074
|
}
|
|
1075
|
+
async importEnvVars(projectRef, slug, params) {
|
|
1076
|
+
if (!this.accessToken) {
|
|
1077
|
+
throw new Error("importEnvVars: No access token");
|
|
1078
|
+
}
|
|
1079
|
+
return wrapZodFetch(
|
|
1080
|
+
EnvironmentVariableResponseBody,
|
|
1081
|
+
`${this.apiURL}/api/v1/projects/${projectRef}/envvars/${slug}/import`,
|
|
1082
|
+
{
|
|
1083
|
+
method: "POST",
|
|
1084
|
+
headers: {
|
|
1085
|
+
Authorization: `Bearer ${this.accessToken}`,
|
|
1086
|
+
"Content-Type": "application/json"
|
|
1087
|
+
},
|
|
1088
|
+
body: JSON.stringify(params)
|
|
1089
|
+
}
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1055
1092
|
async initializeDeployment(body) {
|
|
1056
1093
|
if (!this.accessToken) {
|
|
1057
1094
|
throw new Error("initializeDeployment: No access token");
|
|
1058
1095
|
}
|
|
1059
|
-
return
|
|
1096
|
+
return wrapZodFetch(InitializeDeploymentResponseBody, `${this.apiURL}/api/v1/deployments`, {
|
|
1060
1097
|
method: "POST",
|
|
1061
1098
|
headers: {
|
|
1062
1099
|
Authorization: `Bearer ${this.accessToken}`,
|
|
@@ -1069,7 +1106,7 @@ var CliApiClient = class {
|
|
|
1069
1106
|
if (!this.accessToken) {
|
|
1070
1107
|
throw new Error("startDeploymentIndexing: No access token");
|
|
1071
1108
|
}
|
|
1072
|
-
return
|
|
1109
|
+
return wrapZodFetch(
|
|
1073
1110
|
StartDeploymentIndexingResponseBody,
|
|
1074
1111
|
`${this.apiURL}/api/v1/deployments/${deploymentId}/start-indexing`,
|
|
1075
1112
|
{
|
|
@@ -1086,7 +1123,7 @@ var CliApiClient = class {
|
|
|
1086
1123
|
if (!this.accessToken) {
|
|
1087
1124
|
throw new Error("getDeployment: No access token");
|
|
1088
1125
|
}
|
|
1089
|
-
return
|
|
1126
|
+
return wrapZodFetch(
|
|
1090
1127
|
GetDeploymentResponseBody,
|
|
1091
1128
|
`${this.apiURL}/api/v1/deployments/${deploymentId}`,
|
|
1092
1129
|
{
|
|
@@ -1098,45 +1135,38 @@ var CliApiClient = class {
|
|
|
1098
1135
|
);
|
|
1099
1136
|
}
|
|
1100
1137
|
};
|
|
1101
|
-
async function
|
|
1138
|
+
async function wrapZodFetch(schema, url, requestInit) {
|
|
1102
1139
|
try {
|
|
1103
|
-
const response = await
|
|
1104
|
-
|
|
1140
|
+
const response = await zodfetch(schema, url, requestInit, {
|
|
1141
|
+
retry: {
|
|
1142
|
+
minTimeoutInMs: 500,
|
|
1143
|
+
maxTimeoutInMs: 5e3,
|
|
1144
|
+
maxAttempts: 3,
|
|
1145
|
+
factor: 2,
|
|
1146
|
+
randomize: false
|
|
1147
|
+
}
|
|
1148
|
+
});
|
|
1149
|
+
return {
|
|
1150
|
+
success: true,
|
|
1151
|
+
data: response
|
|
1152
|
+
};
|
|
1153
|
+
} catch (error) {
|
|
1154
|
+
if (error instanceof APIError) {
|
|
1105
1155
|
return {
|
|
1106
1156
|
success: false,
|
|
1107
|
-
error:
|
|
1157
|
+
error: error.message
|
|
1108
1158
|
};
|
|
1109
|
-
}
|
|
1110
|
-
if (response.status >= 400 && response.status < 500) {
|
|
1111
|
-
const body = await response.json();
|
|
1112
|
-
if (!body.error) {
|
|
1113
|
-
return { success: false, error: "Something went wrong" };
|
|
1114
|
-
}
|
|
1115
|
-
return { success: false, error: body.error };
|
|
1116
|
-
}
|
|
1117
|
-
if (response.status !== 200) {
|
|
1159
|
+
} else if (error instanceof Error) {
|
|
1118
1160
|
return {
|
|
1119
1161
|
success: false,
|
|
1120
|
-
error:
|
|
1162
|
+
error: error.message
|
|
1121
1163
|
};
|
|
1122
|
-
}
|
|
1123
|
-
const jsonBody = await response.json();
|
|
1124
|
-
const parsedResult = schema.safeParse(jsonBody);
|
|
1125
|
-
if (parsedResult.success) {
|
|
1126
|
-
return { success: true, data: parsedResult.data };
|
|
1127
|
-
}
|
|
1128
|
-
if ("error" in jsonBody) {
|
|
1164
|
+
} else {
|
|
1129
1165
|
return {
|
|
1130
1166
|
success: false,
|
|
1131
|
-
error:
|
|
1167
|
+
error: String(error)
|
|
1132
1168
|
};
|
|
1133
1169
|
}
|
|
1134
|
-
return { success: false, error: parsedResult.error.message };
|
|
1135
|
-
} catch (error) {
|
|
1136
|
-
return {
|
|
1137
|
-
success: false,
|
|
1138
|
-
error: error instanceof Error ? error.message : JSON.stringify(error)
|
|
1139
|
-
};
|
|
1140
1170
|
}
|
|
1141
1171
|
}
|
|
1142
1172
|
|
|
@@ -1710,7 +1740,15 @@ async function readConfig(dir, options) {
|
|
|
1710
1740
|
cwd: absoluteDir,
|
|
1711
1741
|
tsx: false,
|
|
1712
1742
|
force: false
|
|
1713
|
-
})
|
|
1743
|
+
}),
|
|
1744
|
+
{
|
|
1745
|
+
name: "native-node-modules",
|
|
1746
|
+
setup(build3) {
|
|
1747
|
+
const opts = build3.initialOptions;
|
|
1748
|
+
opts.loader = opts.loader || {};
|
|
1749
|
+
opts.loader[".node"] = "copy";
|
|
1750
|
+
}
|
|
1751
|
+
}
|
|
1714
1752
|
]
|
|
1715
1753
|
});
|
|
1716
1754
|
try {
|
|
@@ -1723,7 +1761,8 @@ async function readConfig(dir, options) {
|
|
|
1723
1761
|
return {
|
|
1724
1762
|
status: "file",
|
|
1725
1763
|
config: await resolveConfig(absoluteDir, config),
|
|
1726
|
-
path: configPath
|
|
1764
|
+
path: configPath,
|
|
1765
|
+
module: userConfigModule
|
|
1727
1766
|
};
|
|
1728
1767
|
} catch (error) {
|
|
1729
1768
|
return {
|
|
@@ -2302,14 +2341,14 @@ var baseOpen = async (options) => {
|
|
|
2302
2341
|
}
|
|
2303
2342
|
const subprocess = childProcess.spawn(command, cliArguments, childProcessOptions);
|
|
2304
2343
|
if (options.wait) {
|
|
2305
|
-
return new Promise((
|
|
2344
|
+
return new Promise((resolve6, reject) => {
|
|
2306
2345
|
subprocess.once("error", reject);
|
|
2307
2346
|
subprocess.once("close", (exitCode) => {
|
|
2308
2347
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
2309
2348
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
2310
2349
|
return;
|
|
2311
2350
|
}
|
|
2312
|
-
|
|
2351
|
+
resolve6(subprocess);
|
|
2313
2352
|
});
|
|
2314
2353
|
});
|
|
2315
2354
|
}
|
|
@@ -2426,7 +2465,7 @@ var decorateErrorWithCounts = (error, attemptNumber, options) => {
|
|
|
2426
2465
|
return error;
|
|
2427
2466
|
};
|
|
2428
2467
|
async function pRetry(input, options) {
|
|
2429
|
-
return new Promise((
|
|
2468
|
+
return new Promise((resolve6, reject) => {
|
|
2430
2469
|
options = {
|
|
2431
2470
|
onFailedAttempt() {
|
|
2432
2471
|
},
|
|
@@ -2449,7 +2488,7 @@ async function pRetry(input, options) {
|
|
|
2449
2488
|
try {
|
|
2450
2489
|
const result = await input(attemptNumber);
|
|
2451
2490
|
cleanUp();
|
|
2452
|
-
|
|
2491
|
+
resolve6(result);
|
|
2453
2492
|
} catch (error) {
|
|
2454
2493
|
try {
|
|
2455
2494
|
if (!(error instanceof Error)) {
|
|
@@ -2572,7 +2611,7 @@ async function whoAmI(options, embedded = false) {
|
|
|
2572
2611
|
loadingSpinner.stop(
|
|
2573
2612
|
`You must login first. Use \`trigger.dev login --profile ${options?.profile ?? "default"}\` to login.`
|
|
2574
2613
|
);
|
|
2575
|
-
outro2(
|
|
2614
|
+
outro2(`Whoami failed: ${authentication.error}`);
|
|
2576
2615
|
}
|
|
2577
2616
|
}
|
|
2578
2617
|
return {
|
|
@@ -3832,6 +3871,46 @@ async function getPackageJson(absoluteProjectPath) {
|
|
|
3832
3871
|
return { packageJson, readonlyPackageJson, packageJsonPath };
|
|
3833
3872
|
}
|
|
3834
3873
|
|
|
3874
|
+
// src/utilities/resolveEnvVars.ts
|
|
3875
|
+
async function callResolveEnvVars(configModule, env, environment, projectRef) {
|
|
3876
|
+
if (configModule && configModule.resolveEnvVars && typeof configModule.resolveEnvVars === "function") {
|
|
3877
|
+
let resolvedEnvVars2 = {};
|
|
3878
|
+
try {
|
|
3879
|
+
let result = await configModule.resolveEnvVars({
|
|
3880
|
+
projectRef,
|
|
3881
|
+
environment,
|
|
3882
|
+
env
|
|
3883
|
+
});
|
|
3884
|
+
if (!result) {
|
|
3885
|
+
return;
|
|
3886
|
+
}
|
|
3887
|
+
result = await result;
|
|
3888
|
+
if (typeof result === "object" && result !== null && "variables" in result) {
|
|
3889
|
+
const variables = result.variables;
|
|
3890
|
+
if (Array.isArray(variables)) {
|
|
3891
|
+
for (const item of variables) {
|
|
3892
|
+
if (typeof item === "object" && item !== null && "name" in item && "value" in item && typeof item.name === "string" && typeof item.value === "string") {
|
|
3893
|
+
resolvedEnvVars2[item.name] = item.value;
|
|
3894
|
+
}
|
|
3895
|
+
}
|
|
3896
|
+
} else if (typeof variables === "object") {
|
|
3897
|
+
for (const [key, value] of Object.entries(variables)) {
|
|
3898
|
+
if (typeof key === "string" && typeof value === "string") {
|
|
3899
|
+
resolvedEnvVars2[key] = value;
|
|
3900
|
+
}
|
|
3901
|
+
}
|
|
3902
|
+
}
|
|
3903
|
+
}
|
|
3904
|
+
return {
|
|
3905
|
+
variables: resolvedEnvVars2,
|
|
3906
|
+
override: result.override
|
|
3907
|
+
};
|
|
3908
|
+
} catch (error) {
|
|
3909
|
+
logger.error(error);
|
|
3910
|
+
}
|
|
3911
|
+
}
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3835
3914
|
// src/commands/deploy.ts
|
|
3836
3915
|
var DeployCommandOptions = CommonCommandOptions.extend({
|
|
3837
3916
|
skipTypecheck: z4.boolean().default(false),
|
|
@@ -3936,7 +4015,11 @@ async function _deployCommand(dir, options) {
|
|
|
3936
4015
|
`Failed to connect to ${authorization.auth?.apiUrl}. Are you sure it's the correct URL?`
|
|
3937
4016
|
);
|
|
3938
4017
|
} else {
|
|
3939
|
-
throw new Error(
|
|
4018
|
+
throw new Error(
|
|
4019
|
+
`You must login first. Use the \`login\` CLI command.
|
|
4020
|
+
|
|
4021
|
+
${authorization.error}`
|
|
4022
|
+
);
|
|
3940
4023
|
}
|
|
3941
4024
|
}
|
|
3942
4025
|
span?.setAttributes({
|
|
@@ -3981,6 +4064,7 @@ async function _deployCommand(dir, options) {
|
|
|
3981
4064
|
resolvedConfig.status === "file" ? resolvedConfig.path : void 0
|
|
3982
4065
|
);
|
|
3983
4066
|
logger.debug("Compilation result", { compilation });
|
|
4067
|
+
await resolveEnvironmentVariables(resolvedConfig, environmentClient, options);
|
|
3984
4068
|
const deploymentResponse = await environmentClient.initializeDeployment({
|
|
3985
4069
|
contentHash: compilation.contentHash,
|
|
3986
4070
|
userId: authorization.userId
|
|
@@ -4295,7 +4379,7 @@ async function failDeploy(shortCode, errorSummary, logs, deploymentSpinner, warn
|
|
|
4295
4379
|
outro5(`${chalkError("Error:")} ${errorSummary}.`);
|
|
4296
4380
|
}
|
|
4297
4381
|
}
|
|
4298
|
-
async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds =
|
|
4382
|
+
async function waitForDeploymentToFinish(deploymentId, client, timeoutInSeconds = 180) {
|
|
4299
4383
|
return tracer.startActiveSpan("waitForDeploymentToFinish", async (span) => {
|
|
4300
4384
|
try {
|
|
4301
4385
|
const start = Date.now();
|
|
@@ -4579,7 +4663,9 @@ async function compileProject(config, options, configPath) {
|
|
|
4579
4663
|
const workerSetupPath = join6(cliRootPath(), "workers", "prod", "worker-setup.js");
|
|
4580
4664
|
let workerContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
|
|
4581
4665
|
"__WORKER_SETUP__",
|
|
4582
|
-
`import { tracingSDK } from "${escapeImportPath(
|
|
4666
|
+
`import { tracingSDK, otelTracer, otelLogger } from "${escapeImportPath(
|
|
4667
|
+
workerSetupPath
|
|
4668
|
+
)}";`
|
|
4583
4669
|
);
|
|
4584
4670
|
if (configPath) {
|
|
4585
4671
|
logger.debug("Importing project config from", { configPath });
|
|
@@ -4794,6 +4880,68 @@ If this is unexpected you should check your ${terminalLink2(
|
|
|
4794
4880
|
}
|
|
4795
4881
|
});
|
|
4796
4882
|
}
|
|
4883
|
+
async function resolveEnvironmentVariables(config, apiClient2, options) {
|
|
4884
|
+
if (config.status !== "file") {
|
|
4885
|
+
return;
|
|
4886
|
+
}
|
|
4887
|
+
if (!config.module || typeof config.module.resolveEnvVars !== "function") {
|
|
4888
|
+
return;
|
|
4889
|
+
}
|
|
4890
|
+
const projectConfig = config.config;
|
|
4891
|
+
return await tracer.startActiveSpan("resolveEnvironmentVariables", async (span) => {
|
|
4892
|
+
try {
|
|
4893
|
+
const $spinner = spinner();
|
|
4894
|
+
$spinner.start("Resolving environment variables");
|
|
4895
|
+
let processEnv = {
|
|
4896
|
+
...process.env
|
|
4897
|
+
};
|
|
4898
|
+
const environmentVariables = await apiClient2.getEnvironmentVariables(projectConfig.project);
|
|
4899
|
+
if (environmentVariables.success) {
|
|
4900
|
+
processEnv = {
|
|
4901
|
+
...processEnv,
|
|
4902
|
+
...environmentVariables.data.variables
|
|
4903
|
+
};
|
|
4904
|
+
}
|
|
4905
|
+
logger.debug("Existing environment variables", {
|
|
4906
|
+
keys: Object.keys(processEnv)
|
|
4907
|
+
});
|
|
4908
|
+
const resolvedEnvVars2 = await callResolveEnvVars(
|
|
4909
|
+
config.module,
|
|
4910
|
+
processEnv,
|
|
4911
|
+
options.env,
|
|
4912
|
+
projectConfig.project
|
|
4913
|
+
);
|
|
4914
|
+
if (resolvedEnvVars2) {
|
|
4915
|
+
const total = Object.keys(resolvedEnvVars2.variables).length;
|
|
4916
|
+
logger.debug("Resolved env vars", {
|
|
4917
|
+
keys: Object.keys(resolvedEnvVars2.variables)
|
|
4918
|
+
});
|
|
4919
|
+
if (total > 0) {
|
|
4920
|
+
$spinner.message(
|
|
4921
|
+
`Syncing ${total} environment variable${total > 1 ? "s" : ""} with the server`
|
|
4922
|
+
);
|
|
4923
|
+
const uploadResult = await apiClient2.importEnvVars(projectConfig.project, options.env, {
|
|
4924
|
+
variables: resolvedEnvVars2.variables,
|
|
4925
|
+
override: typeof resolvedEnvVars2.override === "boolean" ? resolvedEnvVars2.override : true
|
|
4926
|
+
});
|
|
4927
|
+
if (uploadResult.success) {
|
|
4928
|
+
$spinner.stop(`${total} environment variable${total > 1 ? "s" : ""} synced`);
|
|
4929
|
+
} else {
|
|
4930
|
+
$spinner.stop("Failed to sync environment variables");
|
|
4931
|
+
throw new Error(uploadResult.error);
|
|
4932
|
+
}
|
|
4933
|
+
} else {
|
|
4934
|
+
$spinner.stop("No environment variables to sync");
|
|
4935
|
+
}
|
|
4936
|
+
}
|
|
4937
|
+
} catch (e) {
|
|
4938
|
+
recordSpanException5(span, e);
|
|
4939
|
+
throw e;
|
|
4940
|
+
} finally {
|
|
4941
|
+
span.end();
|
|
4942
|
+
}
|
|
4943
|
+
});
|
|
4944
|
+
}
|
|
4797
4945
|
async function resolveDependencies(projectDir, packageJsonContents, config, options) {
|
|
4798
4946
|
return await tracer.startActiveSpan("resolveDependencies", async (span) => {
|
|
4799
4947
|
const resolvingDepsSpinner = spinner();
|
|
@@ -4830,10 +4978,29 @@ async function resolveDependencies(projectDir, packageJsonContents, config, opti
|
|
|
4830
4978
|
});
|
|
4831
4979
|
logger.debug(`No cached package-lock.json found for ${digest}`);
|
|
4832
4980
|
try {
|
|
4833
|
-
|
|
4834
|
-
|
|
4835
|
-
|
|
4836
|
-
|
|
4981
|
+
if (logger.loggerLevel === "debug") {
|
|
4982
|
+
const childProcess2 = await execa2("npm", ["config", "list"], {
|
|
4983
|
+
cwd: projectDir,
|
|
4984
|
+
stdio: "inherit"
|
|
4985
|
+
});
|
|
4986
|
+
logger.debug("npm config list");
|
|
4987
|
+
console.log(childProcess2.stdout);
|
|
4988
|
+
}
|
|
4989
|
+
await execa2(
|
|
4990
|
+
"npm",
|
|
4991
|
+
[
|
|
4992
|
+
"install",
|
|
4993
|
+
"--package-lock-only",
|
|
4994
|
+
"--ignore-scripts",
|
|
4995
|
+
"--no-audit",
|
|
4996
|
+
"--legacy-peer-deps=false",
|
|
4997
|
+
"--strict-peer-deps=false"
|
|
4998
|
+
],
|
|
4999
|
+
{
|
|
5000
|
+
cwd: projectDir,
|
|
5001
|
+
stdio: logger.loggerLevel === "debug" ? "inherit" : "pipe"
|
|
5002
|
+
}
|
|
5003
|
+
);
|
|
4837
5004
|
const packageLockContents = await readFile2(join6(projectDir, "package-lock.json"), "utf-8");
|
|
4838
5005
|
logger.debug(`Writing package-lock.json to cache for ${digest}`);
|
|
4839
5006
|
await mkdir(cacheDir, { recursive: true });
|
|
@@ -4890,8 +5057,8 @@ async function typecheckProject(config, options) {
|
|
|
4890
5057
|
tscTypecheck.stdout?.on("data", (chunk) => stdouts.push(chunk.toString()));
|
|
4891
5058
|
tscTypecheck.stderr?.on("data", (chunk) => stderrs.push(chunk.toString()));
|
|
4892
5059
|
try {
|
|
4893
|
-
await new Promise((
|
|
4894
|
-
tscTypecheck.addListener("exit", (code) => code === 0 ?
|
|
5060
|
+
await new Promise((resolve6, reject) => {
|
|
5061
|
+
tscTypecheck.addListener("exit", (code) => code === 0 ? resolve6(code) : reject(code));
|
|
4895
5062
|
});
|
|
4896
5063
|
} catch (error) {
|
|
4897
5064
|
typecheckSpinner.stop(
|
|
@@ -5123,6 +5290,31 @@ var TaskMetadataParseError = class extends Error {
|
|
|
5123
5290
|
this.name = "TaskMetadataParseError";
|
|
5124
5291
|
}
|
|
5125
5292
|
};
|
|
5293
|
+
var UnexpectedExitError = class extends Error {
|
|
5294
|
+
constructor(code) {
|
|
5295
|
+
super(`Unexpected exit with code ${code}`);
|
|
5296
|
+
this.code = code;
|
|
5297
|
+
this.name = "UnexpectedExitError";
|
|
5298
|
+
}
|
|
5299
|
+
};
|
|
5300
|
+
var CleanupProcessError = class extends Error {
|
|
5301
|
+
constructor() {
|
|
5302
|
+
super("Cancelled");
|
|
5303
|
+
this.name = "CleanupProcessError";
|
|
5304
|
+
}
|
|
5305
|
+
};
|
|
5306
|
+
var CancelledProcessError = class extends Error {
|
|
5307
|
+
constructor() {
|
|
5308
|
+
super("Cancelled");
|
|
5309
|
+
this.name = "CancelledProcessError";
|
|
5310
|
+
}
|
|
5311
|
+
};
|
|
5312
|
+
var SigKillTimeoutProcessError = class extends Error {
|
|
5313
|
+
constructor() {
|
|
5314
|
+
super("Process kill timeout");
|
|
5315
|
+
this.name = "SigKillTimeoutProcessError";
|
|
5316
|
+
}
|
|
5317
|
+
};
|
|
5126
5318
|
|
|
5127
5319
|
// src/workers/dev/backgroundWorker.ts
|
|
5128
5320
|
import {
|
|
@@ -5137,28 +5329,36 @@ import { ZodMessageHandler, ZodMessageSender } from "@trigger.dev/core/v3/zodMes
|
|
|
5137
5329
|
import dotenv from "dotenv";
|
|
5138
5330
|
import { Evt } from "evt";
|
|
5139
5331
|
import { fork } from "node:child_process";
|
|
5140
|
-
import { dirname as dirname2, resolve as
|
|
5332
|
+
import { dirname as dirname2, resolve as resolve4 } from "node:path";
|
|
5141
5333
|
import terminalLink3 from "terminal-link";
|
|
5142
5334
|
var BackgroundWorkerCoordinator = class {
|
|
5143
5335
|
constructor(baseURL) {
|
|
5144
5336
|
this.baseURL = baseURL;
|
|
5145
|
-
this.onTaskCompleted.attach(async ({ completion
|
|
5337
|
+
this.onTaskCompleted.attach(async ({ completion }) => {
|
|
5146
5338
|
if (!completion.ok && typeof completion.retry !== "undefined") {
|
|
5147
5339
|
return;
|
|
5148
5340
|
}
|
|
5149
|
-
await this.#notifyWorkersOfTaskCompletion(completion
|
|
5341
|
+
await this.#notifyWorkersOfTaskCompletion(completion);
|
|
5342
|
+
});
|
|
5343
|
+
this.onTaskFailedToRun.attach(async ({ completion }) => {
|
|
5344
|
+
await this.#notifyWorkersOfTaskCompletion(completion);
|
|
5150
5345
|
});
|
|
5151
5346
|
}
|
|
5152
5347
|
onTaskCompleted = new Evt();
|
|
5348
|
+
onTaskFailedToRun = new Evt();
|
|
5153
5349
|
onWorkerRegistered = new Evt();
|
|
5350
|
+
/**
|
|
5351
|
+
* @deprecated use onWorkerTaskRunHeartbeat instead
|
|
5352
|
+
*/
|
|
5154
5353
|
onWorkerTaskHeartbeat = new Evt();
|
|
5354
|
+
onWorkerTaskRunHeartbeat = new Evt();
|
|
5155
5355
|
onWorkerDeprecated = new Evt();
|
|
5156
5356
|
_backgroundWorkers = /* @__PURE__ */ new Map();
|
|
5157
5357
|
_records = /* @__PURE__ */ new Map();
|
|
5158
5358
|
_deprecatedWorkers = /* @__PURE__ */ new Set();
|
|
5159
|
-
async #notifyWorkersOfTaskCompletion(completion
|
|
5359
|
+
async #notifyWorkersOfTaskCompletion(completion) {
|
|
5160
5360
|
for (const worker of this._backgroundWorkers.values()) {
|
|
5161
|
-
await worker.taskRunCompletedNotification(completion
|
|
5361
|
+
await worker.taskRunCompletedNotification(completion);
|
|
5162
5362
|
}
|
|
5163
5363
|
}
|
|
5164
5364
|
get currentWorkers() {
|
|
@@ -5183,6 +5383,9 @@ var BackgroundWorkerCoordinator = class {
|
|
|
5183
5383
|
worker.onTaskHeartbeat.attach((id) => {
|
|
5184
5384
|
this.onWorkerTaskHeartbeat.post({ id, backgroundWorkerId: record.id, worker });
|
|
5185
5385
|
});
|
|
5386
|
+
worker.onTaskRunHeartbeat.attach((id) => {
|
|
5387
|
+
this.onWorkerTaskRunHeartbeat.post({ id, backgroundWorkerId: record.id, worker });
|
|
5388
|
+
});
|
|
5186
5389
|
}
|
|
5187
5390
|
close() {
|
|
5188
5391
|
for (const worker of this._backgroundWorkers.values()) {
|
|
@@ -5205,10 +5408,14 @@ var BackgroundWorkerCoordinator = class {
|
|
|
5205
5408
|
return;
|
|
5206
5409
|
}
|
|
5207
5410
|
await worker.cancelRun(message.taskRunId);
|
|
5411
|
+
break;
|
|
5412
|
+
}
|
|
5413
|
+
case "EXECUTE_RUN_LAZY_ATTEMPT": {
|
|
5414
|
+
await this.#executeTaskRunLazyAttempt(id, message.payload);
|
|
5208
5415
|
}
|
|
5209
5416
|
}
|
|
5210
5417
|
}
|
|
5211
|
-
async #
|
|
5418
|
+
async #executeTaskRunLazyAttempt(id, payload) {
|
|
5212
5419
|
const worker = this._backgroundWorkers.get(id);
|
|
5213
5420
|
if (!worker) {
|
|
5214
5421
|
logger.error(`Could not find worker ${id}`);
|
|
@@ -5219,103 +5426,89 @@ var BackgroundWorkerCoordinator = class {
|
|
|
5219
5426
|
logger.error(`Could not find worker record ${id}`);
|
|
5220
5427
|
return;
|
|
5221
5428
|
}
|
|
5222
|
-
|
|
5223
|
-
|
|
5224
|
-
|
|
5225
|
-
|
|
5226
|
-
|
|
5227
|
-
|
|
5228
|
-
|
|
5229
|
-
|
|
5230
|
-
|
|
5231
|
-
|
|
5232
|
-
|
|
5233
|
-
|
|
5234
|
-
|
|
5235
|
-
|
|
5236
|
-
|
|
5237
|
-
|
|
5238
|
-
|
|
5239
|
-
|
|
5240
|
-
|
|
5241
|
-
|
|
5242
|
-
|
|
5243
|
-
|
|
5244
|
-
|
|
5245
|
-
|
|
5246
|
-
|
|
5247
|
-
|
|
5248
|
-
|
|
5249
|
-
|
|
5250
|
-
|
|
5251
|
-
|
|
5252
|
-
|
|
5253
|
-
|
|
5254
|
-
switch (error.type) {
|
|
5255
|
-
case "INTERNAL_ERROR": {
|
|
5256
|
-
return "";
|
|
5257
|
-
}
|
|
5258
|
-
case "STRING_ERROR": {
|
|
5259
|
-
return `
|
|
5260
|
-
|
|
5261
|
-
${chalkError("X Error:")} ${error.raw}
|
|
5262
|
-
`;
|
|
5263
|
-
}
|
|
5264
|
-
case "CUSTOM_ERROR": {
|
|
5265
|
-
return `
|
|
5266
|
-
|
|
5267
|
-
${chalkError("X Error:")} ${error.raw}
|
|
5268
|
-
`;
|
|
5269
|
-
}
|
|
5270
|
-
case "BUILT_IN_ERROR": {
|
|
5271
|
-
return `
|
|
5272
|
-
|
|
5273
|
-
${error.stackTrace.replace(/^Error: /, chalkError("X Error: "))}
|
|
5274
|
-
`;
|
|
5275
|
-
}
|
|
5429
|
+
try {
|
|
5430
|
+
const { completion, execution } = await worker.executeTaskRunLazyAttempt(
|
|
5431
|
+
payload,
|
|
5432
|
+
this.baseURL
|
|
5433
|
+
);
|
|
5434
|
+
this.onTaskCompleted.post({
|
|
5435
|
+
completion,
|
|
5436
|
+
execution,
|
|
5437
|
+
worker,
|
|
5438
|
+
backgroundWorkerId: id
|
|
5439
|
+
});
|
|
5440
|
+
} catch (error) {
|
|
5441
|
+
this.onTaskFailedToRun.post({
|
|
5442
|
+
backgroundWorkerId: id,
|
|
5443
|
+
worker,
|
|
5444
|
+
completion: {
|
|
5445
|
+
ok: false,
|
|
5446
|
+
id: payload.runId,
|
|
5447
|
+
retry: void 0,
|
|
5448
|
+
error: error instanceof Error ? {
|
|
5449
|
+
type: "BUILT_IN_ERROR",
|
|
5450
|
+
name: error.name,
|
|
5451
|
+
message: error.message,
|
|
5452
|
+
stackTrace: error.stack ?? ""
|
|
5453
|
+
} : {
|
|
5454
|
+
type: "BUILT_IN_ERROR",
|
|
5455
|
+
name: "UnknownError",
|
|
5456
|
+
message: String(error),
|
|
5457
|
+
stackTrace: ""
|
|
5458
|
+
}
|
|
5459
|
+
}
|
|
5460
|
+
});
|
|
5276
5461
|
}
|
|
5277
5462
|
}
|
|
5278
|
-
|
|
5279
|
-
|
|
5280
|
-
|
|
5281
|
-
|
|
5282
|
-
|
|
5283
|
-
|
|
5284
|
-
|
|
5285
|
-
|
|
5286
|
-
|
|
5287
|
-
|
|
5288
|
-
|
|
5289
|
-
|
|
5290
|
-
|
|
5291
|
-
|
|
5292
|
-
|
|
5293
|
-
|
|
5294
|
-
|
|
5295
|
-
|
|
5463
|
+
async #executeTaskRun(id, payload) {
|
|
5464
|
+
const worker = this._backgroundWorkers.get(id);
|
|
5465
|
+
if (!worker) {
|
|
5466
|
+
logger.error(`Could not find worker ${id}`);
|
|
5467
|
+
return;
|
|
5468
|
+
}
|
|
5469
|
+
const record = this._records.get(id);
|
|
5470
|
+
if (!record) {
|
|
5471
|
+
logger.error(`Could not find worker record ${id}`);
|
|
5472
|
+
return;
|
|
5473
|
+
}
|
|
5474
|
+
const completion = await worker.executeTaskRun(payload, this.baseURL);
|
|
5475
|
+
this.onTaskCompleted.post({
|
|
5476
|
+
completion,
|
|
5477
|
+
execution: payload.execution,
|
|
5478
|
+
worker,
|
|
5479
|
+
backgroundWorkerId: id
|
|
5480
|
+
});
|
|
5296
5481
|
}
|
|
5297
5482
|
};
|
|
5298
5483
|
var BackgroundWorker = class {
|
|
5299
|
-
constructor(path7, params) {
|
|
5484
|
+
constructor(path7, params, apiClient2) {
|
|
5300
5485
|
this.path = path7;
|
|
5301
5486
|
this.params = params;
|
|
5487
|
+
this.apiClient = apiClient2;
|
|
5302
5488
|
}
|
|
5303
5489
|
_initialized = false;
|
|
5304
5490
|
_handler = new ZodMessageHandler({
|
|
5305
5491
|
schema: childToWorkerMessages
|
|
5306
5492
|
});
|
|
5493
|
+
/**
|
|
5494
|
+
* @deprecated use onTaskRunHeartbeat instead
|
|
5495
|
+
*/
|
|
5307
5496
|
onTaskHeartbeat = new Evt();
|
|
5497
|
+
onTaskRunHeartbeat = new Evt();
|
|
5308
5498
|
_onClose = new Evt();
|
|
5309
5499
|
tasks = [];
|
|
5310
5500
|
metadata;
|
|
5311
5501
|
_taskRunProcesses = /* @__PURE__ */ new Map();
|
|
5502
|
+
_taskRunProcessesBeingKilled = /* @__PURE__ */ new Set();
|
|
5312
5503
|
_closed = false;
|
|
5504
|
+
_fullEnv = {};
|
|
5313
5505
|
close() {
|
|
5314
5506
|
if (this._closed) {
|
|
5315
5507
|
return;
|
|
5316
5508
|
}
|
|
5317
5509
|
this._closed = true;
|
|
5318
5510
|
this.onTaskHeartbeat.detach();
|
|
5511
|
+
this.onTaskRunHeartbeat.detach();
|
|
5319
5512
|
for (const taskRunProcess of this._taskRunProcesses.values()) {
|
|
5320
5513
|
taskRunProcess.cleanup(true);
|
|
5321
5514
|
}
|
|
@@ -5323,6 +5516,9 @@ var BackgroundWorker = class {
|
|
|
5323
5516
|
safeDeleteFileSync(this.path);
|
|
5324
5517
|
safeDeleteFileSync(`${this.path}.map`);
|
|
5325
5518
|
}
|
|
5519
|
+
get inProgressRuns() {
|
|
5520
|
+
return Array.from(this._taskRunProcesses.keys());
|
|
5521
|
+
}
|
|
5326
5522
|
async initialize() {
|
|
5327
5523
|
if (this._initialized) {
|
|
5328
5524
|
throw new Error("Worker already initialized");
|
|
@@ -5332,12 +5528,24 @@ var BackgroundWorker = class {
|
|
|
5332
5528
|
}
|
|
5333
5529
|
let resolved = false;
|
|
5334
5530
|
const cwd = dirname2(this.path);
|
|
5335
|
-
|
|
5531
|
+
this._fullEnv = {
|
|
5336
5532
|
...this.params.env,
|
|
5337
|
-
...this.#readEnvVars()
|
|
5533
|
+
...this.#readEnvVars(),
|
|
5534
|
+
...this.params.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
|
|
5338
5535
|
};
|
|
5339
|
-
|
|
5340
|
-
this.
|
|
5536
|
+
let resolvedEnvVars2 = {};
|
|
5537
|
+
if (this.params.resolveEnvVariables) {
|
|
5538
|
+
const resolvedEnv = await this.params.resolveEnvVariables(this._fullEnv, this);
|
|
5539
|
+
if (resolvedEnv) {
|
|
5540
|
+
resolvedEnvVars2 = resolvedEnv;
|
|
5541
|
+
}
|
|
5542
|
+
}
|
|
5543
|
+
this._fullEnv = {
|
|
5544
|
+
...this._fullEnv,
|
|
5545
|
+
...resolvedEnvVars2
|
|
5546
|
+
};
|
|
5547
|
+
logger.debug("Initializing worker", { path: this.path, cwd, fullEnv: this._fullEnv });
|
|
5548
|
+
this.tasks = await new Promise((resolve6, reject) => {
|
|
5341
5549
|
const child = fork(this.path, {
|
|
5342
5550
|
stdio: [
|
|
5343
5551
|
/*stdin*/
|
|
@@ -5349,7 +5557,7 @@ var BackgroundWorker = class {
|
|
|
5349
5557
|
"ipc"
|
|
5350
5558
|
],
|
|
5351
5559
|
cwd,
|
|
5352
|
-
env:
|
|
5560
|
+
env: this._fullEnv
|
|
5353
5561
|
});
|
|
5354
5562
|
const timeout = setTimeout(() => {
|
|
5355
5563
|
if (resolved) {
|
|
@@ -5364,7 +5572,7 @@ var BackgroundWorker = class {
|
|
|
5364
5572
|
if (message.type === "TASKS_READY" && !resolved) {
|
|
5365
5573
|
clearTimeout(timeout);
|
|
5366
5574
|
resolved = true;
|
|
5367
|
-
|
|
5575
|
+
resolve6(message.payload.tasks);
|
|
5368
5576
|
child.kill();
|
|
5369
5577
|
} else if (message.type === "UNCAUGHT_EXCEPTION") {
|
|
5370
5578
|
clearTimeout(timeout);
|
|
@@ -5393,37 +5601,105 @@ var BackgroundWorker = class {
|
|
|
5393
5601
|
}
|
|
5394
5602
|
// We need to notify all the task run processes that a task run has completed,
|
|
5395
5603
|
// in case they are waiting for it through triggerAndWait
|
|
5396
|
-
async taskRunCompletedNotification(completion
|
|
5604
|
+
async taskRunCompletedNotification(completion) {
|
|
5397
5605
|
for (const taskRunProcess of this._taskRunProcesses.values()) {
|
|
5398
|
-
taskRunProcess.taskRunCompletedNotification(completion
|
|
5606
|
+
taskRunProcess.taskRunCompletedNotification(completion);
|
|
5399
5607
|
}
|
|
5400
5608
|
}
|
|
5401
|
-
|
|
5609
|
+
#prefixedMessage(payload, message = "") {
|
|
5610
|
+
return `[${payload.execution.run.id}.${payload.execution.attempt.number}] ${message}`;
|
|
5611
|
+
}
|
|
5612
|
+
async #getFreshTaskRunProcess(payload, messageId) {
|
|
5613
|
+
logger.debug(this.#prefixedMessage(payload, "getFreshTaskRunProcess()"));
|
|
5402
5614
|
if (!this.metadata) {
|
|
5403
5615
|
throw new Error("Worker not registered");
|
|
5404
5616
|
}
|
|
5405
|
-
|
|
5406
|
-
|
|
5407
|
-
|
|
5408
|
-
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
5414
|
-
this.
|
|
5415
|
-
|
|
5416
|
-
|
|
5417
|
-
|
|
5617
|
+
this._closed = false;
|
|
5618
|
+
logger.debug(this.#prefixedMessage(payload, "killing current task run process before attempt"));
|
|
5619
|
+
await this.#killCurrentTaskRunProcessBeforeAttempt(payload.execution.run.id);
|
|
5620
|
+
logger.debug(this.#prefixedMessage(payload, "creating new task run process"));
|
|
5621
|
+
const taskRunProcess = new TaskRunProcess(
|
|
5622
|
+
payload.execution.run.id,
|
|
5623
|
+
payload.execution.run.isTest,
|
|
5624
|
+
this.path,
|
|
5625
|
+
{
|
|
5626
|
+
...this._fullEnv,
|
|
5627
|
+
...payload.environment ?? {},
|
|
5628
|
+
...this.#readEnvVars()
|
|
5629
|
+
},
|
|
5630
|
+
this.metadata,
|
|
5631
|
+
this.params,
|
|
5632
|
+
messageId
|
|
5633
|
+
);
|
|
5634
|
+
taskRunProcess.onExit.attach(({ pid }) => {
|
|
5635
|
+
logger.debug(this.#prefixedMessage(payload, "onExit()"), { pid });
|
|
5636
|
+
const taskRunProcess2 = this._taskRunProcesses.get(payload.execution.run.id);
|
|
5637
|
+
if (taskRunProcess2?.pid === pid) {
|
|
5418
5638
|
this._taskRunProcesses.delete(payload.execution.run.id);
|
|
5419
|
-
}
|
|
5420
|
-
|
|
5421
|
-
this.
|
|
5422
|
-
}
|
|
5423
|
-
|
|
5424
|
-
|
|
5639
|
+
}
|
|
5640
|
+
if (pid) {
|
|
5641
|
+
this._taskRunProcessesBeingKilled.delete(pid);
|
|
5642
|
+
}
|
|
5643
|
+
});
|
|
5644
|
+
taskRunProcess.onIsBeingKilled.attach((pid) => {
|
|
5645
|
+
if (pid) {
|
|
5646
|
+
this._taskRunProcessesBeingKilled.add(pid);
|
|
5647
|
+
}
|
|
5648
|
+
});
|
|
5649
|
+
taskRunProcess.onTaskHeartbeat.attach((id) => {
|
|
5650
|
+
this.onTaskHeartbeat.post(id);
|
|
5651
|
+
});
|
|
5652
|
+
taskRunProcess.onTaskRunHeartbeat.attach((id) => {
|
|
5653
|
+
this.onTaskRunHeartbeat.post(id);
|
|
5654
|
+
});
|
|
5655
|
+
await taskRunProcess.initialize();
|
|
5656
|
+
this._taskRunProcesses.set(payload.execution.run.id, taskRunProcess);
|
|
5657
|
+
return taskRunProcess;
|
|
5658
|
+
}
|
|
5659
|
+
async #killCurrentTaskRunProcessBeforeAttempt(runId) {
|
|
5660
|
+
const taskRunProcess = this._taskRunProcesses.get(runId);
|
|
5661
|
+
if (!taskRunProcess) {
|
|
5662
|
+
logger.debug(`[${runId}] no current task process to kill`);
|
|
5663
|
+
return;
|
|
5664
|
+
}
|
|
5665
|
+
logger.debug(`[${runId}] killing current task process`, {
|
|
5666
|
+
pid: taskRunProcess.pid
|
|
5667
|
+
});
|
|
5668
|
+
if (taskRunProcess.isBeingKilled) {
|
|
5669
|
+
if (this._taskRunProcessesBeingKilled.size > 1) {
|
|
5670
|
+
await this.#tryGracefulExit(taskRunProcess);
|
|
5671
|
+
} else {
|
|
5672
|
+
}
|
|
5673
|
+
} else {
|
|
5674
|
+
if (this._taskRunProcessesBeingKilled.size > 0) {
|
|
5675
|
+
await this.#tryGracefulExit(taskRunProcess);
|
|
5676
|
+
} else {
|
|
5677
|
+
taskRunProcess.kill("SIGTERM", 5e3).catch(() => {
|
|
5678
|
+
});
|
|
5679
|
+
}
|
|
5680
|
+
}
|
|
5681
|
+
}
|
|
5682
|
+
async #tryGracefulExit(taskRunProcess, kill = false, initialSignal = "SIGTERM") {
|
|
5683
|
+
try {
|
|
5684
|
+
const initialExit = taskRunProcess.onExit.waitFor(5e3);
|
|
5685
|
+
if (kill) {
|
|
5686
|
+
taskRunProcess.kill(initialSignal);
|
|
5687
|
+
}
|
|
5688
|
+
await initialExit;
|
|
5689
|
+
} catch (error) {
|
|
5690
|
+
logger.error("TaskRunProcess graceful kill timeout exceeded", error);
|
|
5691
|
+
this.#tryForcefulExit(taskRunProcess);
|
|
5692
|
+
}
|
|
5693
|
+
}
|
|
5694
|
+
async #tryForcefulExit(taskRunProcess) {
|
|
5695
|
+
try {
|
|
5696
|
+
const forcedKill = taskRunProcess.onExit.waitFor(5e3);
|
|
5697
|
+
taskRunProcess.kill("SIGKILL");
|
|
5698
|
+
await forcedKill;
|
|
5699
|
+
} catch (error) {
|
|
5700
|
+
logger.error("TaskRunProcess forced kill timeout exceeded", error);
|
|
5701
|
+
throw new SigKillTimeoutProcessError();
|
|
5425
5702
|
}
|
|
5426
|
-
return this._taskRunProcesses.get(payload.execution.run.id);
|
|
5427
5703
|
}
|
|
5428
5704
|
async cancelRun(taskRunId) {
|
|
5429
5705
|
const taskRunProcess = this._taskRunProcesses.get(taskRunId);
|
|
@@ -5432,12 +5708,66 @@ var BackgroundWorker = class {
|
|
|
5432
5708
|
}
|
|
5433
5709
|
await taskRunProcess.cancel();
|
|
5434
5710
|
}
|
|
5711
|
+
async executeTaskRunLazyAttempt(payload, baseURL) {
|
|
5712
|
+
const attemptResponse = await this.apiClient.createTaskRunAttempt(payload.runId);
|
|
5713
|
+
if (!attemptResponse.success) {
|
|
5714
|
+
throw new Error(`Failed to create task run attempt: ${attemptResponse.error}`);
|
|
5715
|
+
}
|
|
5716
|
+
const execution = attemptResponse.data;
|
|
5717
|
+
const completion = await this.executeTaskRun(
|
|
5718
|
+
{ execution, traceContext: payload.traceContext, environment: payload.environment },
|
|
5719
|
+
baseURL,
|
|
5720
|
+
payload.messageId
|
|
5721
|
+
);
|
|
5722
|
+
return { execution, completion };
|
|
5723
|
+
}
|
|
5435
5724
|
// We need to fork the process before we can execute any tasks
|
|
5436
|
-
async executeTaskRun(payload) {
|
|
5725
|
+
async executeTaskRun(payload, baseURL, messageId) {
|
|
5726
|
+
if (this._closed) {
|
|
5727
|
+
throw new Error("Worker is closed");
|
|
5728
|
+
}
|
|
5729
|
+
if (!this.metadata) {
|
|
5730
|
+
throw new Error("Worker not registered");
|
|
5731
|
+
}
|
|
5732
|
+
const { execution } = payload;
|
|
5733
|
+
const logsUrl = `${baseURL}/runs/${execution.run.id}`;
|
|
5734
|
+
const pipe = chalkGrey("|");
|
|
5735
|
+
const bullet = chalkGrey("\u25CB");
|
|
5736
|
+
const link = chalkLink(terminalLink3("View logs", logsUrl));
|
|
5737
|
+
let timestampPrefix = chalkGrey(prettyPrintDate(payload.execution.attempt.startedAt));
|
|
5738
|
+
const workerPrefix = chalkWorker(this.metadata.version);
|
|
5739
|
+
const taskPrefix = chalkTask(execution.task.id);
|
|
5740
|
+
const runId = chalkRun(`${execution.run.id}.${execution.attempt.number}`);
|
|
5741
|
+
logger.log(
|
|
5742
|
+
`${bullet} ${timestampPrefix} ${chalkGrey(
|
|
5743
|
+
"->"
|
|
5744
|
+
)} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId}`
|
|
5745
|
+
);
|
|
5746
|
+
const now = performance.now();
|
|
5747
|
+
const completion = await this.#doExecuteTaskRun(payload, messageId);
|
|
5748
|
+
const elapsed = performance.now() - now;
|
|
5749
|
+
const retryingText = chalkGrey(
|
|
5750
|
+
!completion.ok && completion.skippedRetrying ? " (retrying skipped)" : !completion.ok && completion.retry !== void 0 ? ` (retrying in ${completion.retry.delay}ms)` : ""
|
|
5751
|
+
);
|
|
5752
|
+
const resultText = !completion.ok ? completion.error.type === "INTERNAL_ERROR" && (completion.error.code === TaskRunErrorCodes.TASK_EXECUTION_ABORTED || completion.error.code === TaskRunErrorCodes.TASK_RUN_CANCELLED) ? chalkWarning("Cancelled") : `${chalkError("Error")}${retryingText}` : chalkSuccess("Success");
|
|
5753
|
+
const errorText = !completion.ok ? formatErrorLog(completion.error) : "retry" in completion ? `retry in ${completion.retry}ms` : "";
|
|
5754
|
+
const elapsedText = chalkGrey(`(${formatDurationMilliseconds(elapsed, { style: "short" })})`);
|
|
5755
|
+
timestampPrefix = chalkGrey(prettyPrintDate());
|
|
5756
|
+
logger.log(
|
|
5757
|
+
`${bullet} ${timestampPrefix} ${chalkGrey(
|
|
5758
|
+
"->"
|
|
5759
|
+
)} ${link} ${pipe} ${workerPrefix} ${pipe} ${taskPrefix} ${pipe} ${runId} ${pipe} ${resultText} ${elapsedText}${errorText}`
|
|
5760
|
+
);
|
|
5761
|
+
return completion;
|
|
5762
|
+
}
|
|
5763
|
+
async #doExecuteTaskRun(payload, messageId) {
|
|
5437
5764
|
try {
|
|
5438
|
-
const taskRunProcess = await this.#
|
|
5765
|
+
const taskRunProcess = await this.#getFreshTaskRunProcess(payload, messageId);
|
|
5766
|
+
logger.debug(this.#prefixedMessage(payload, "executing task run"), {
|
|
5767
|
+
pid: taskRunProcess.pid
|
|
5768
|
+
});
|
|
5439
5769
|
const result = await taskRunProcess.executeTaskRun(payload);
|
|
5440
|
-
await taskRunProcess.cleanup(
|
|
5770
|
+
await taskRunProcess.cleanup(true);
|
|
5441
5771
|
if (result.ok) {
|
|
5442
5772
|
return result;
|
|
5443
5773
|
}
|
|
@@ -5499,7 +5829,7 @@ var BackgroundWorker = class {
|
|
|
5499
5829
|
const result = {};
|
|
5500
5830
|
dotenv.config({
|
|
5501
5831
|
processEnv: result,
|
|
5502
|
-
path: [".env", ".env.local", ".env.development.local"].map((p) =>
|
|
5832
|
+
path: [".env", ".env.local", ".env.development.local"].map((p) => resolve4(process.cwd(), p))
|
|
5503
5833
|
});
|
|
5504
5834
|
process.env.TRIGGER_API_URL && (result.TRIGGER_API_URL = process.env.TRIGGER_API_URL);
|
|
5505
5835
|
delete result.TRIGGER_API_URL;
|
|
@@ -5514,12 +5844,14 @@ var BackgroundWorker = class {
|
|
|
5514
5844
|
}
|
|
5515
5845
|
};
|
|
5516
5846
|
var TaskRunProcess = class {
|
|
5517
|
-
constructor(
|
|
5518
|
-
this.
|
|
5847
|
+
constructor(runId, isTest, path7, env, metadata, worker, messageId) {
|
|
5848
|
+
this.runId = runId;
|
|
5849
|
+
this.isTest = isTest;
|
|
5519
5850
|
this.path = path7;
|
|
5520
5851
|
this.env = env;
|
|
5521
5852
|
this.metadata = metadata;
|
|
5522
5853
|
this.worker = worker;
|
|
5854
|
+
this.messageId = messageId;
|
|
5523
5855
|
this._sender = new ZodMessageSender({
|
|
5524
5856
|
schema: workerToChildMessages,
|
|
5525
5857
|
sender: async (message) => {
|
|
@@ -5534,20 +5866,26 @@ var TaskRunProcess = class {
|
|
|
5534
5866
|
});
|
|
5535
5867
|
_sender;
|
|
5536
5868
|
_child;
|
|
5869
|
+
_childPid;
|
|
5537
5870
|
_attemptPromises = /* @__PURE__ */ new Map();
|
|
5538
5871
|
_attemptStatuses = /* @__PURE__ */ new Map();
|
|
5539
5872
|
_currentExecution;
|
|
5540
5873
|
_isBeingKilled = false;
|
|
5541
5874
|
_isBeingCancelled = false;
|
|
5875
|
+
/**
|
|
5876
|
+
* @deprecated use onTaskRunHeartbeat instead
|
|
5877
|
+
*/
|
|
5542
5878
|
onTaskHeartbeat = new Evt();
|
|
5879
|
+
onTaskRunHeartbeat = new Evt();
|
|
5543
5880
|
onExit = new Evt();
|
|
5881
|
+
onIsBeingKilled = new Evt();
|
|
5544
5882
|
async cancel() {
|
|
5545
5883
|
this._isBeingCancelled = true;
|
|
5546
5884
|
await this.cleanup(true);
|
|
5547
5885
|
}
|
|
5548
5886
|
async initialize() {
|
|
5549
5887
|
const fullEnv = {
|
|
5550
|
-
...this.
|
|
5888
|
+
...this.isTest ? { TRIGGER_LOG_LEVEL: "debug" } : {},
|
|
5551
5889
|
...this.env,
|
|
5552
5890
|
OTEL_RESOURCE_ATTRIBUTES: JSON.stringify({
|
|
5553
5891
|
[SemanticInternalAttributes.PROJECT_DIR]: this.worker.projectConfig.projectDir
|
|
@@ -5556,7 +5894,7 @@ var TaskRunProcess = class {
|
|
|
5556
5894
|
...this.worker.debugOtel ? { OTEL_LOG_LEVEL: "debug" } : {}
|
|
5557
5895
|
};
|
|
5558
5896
|
const cwd = dirname2(this.path);
|
|
5559
|
-
logger.debug(`[${this.
|
|
5897
|
+
logger.debug(`[${this.runId}] initializing task run process`, {
|
|
5560
5898
|
env: fullEnv,
|
|
5561
5899
|
path: this.path,
|
|
5562
5900
|
cwd
|
|
@@ -5575,6 +5913,7 @@ var TaskRunProcess = class {
|
|
|
5575
5913
|
env: fullEnv,
|
|
5576
5914
|
execArgv: this.worker.debuggerOn ? ["--inspect-brk", "--trace-uncaught", "--no-warnings=ExperimentalWarning"] : ["--trace-uncaught", "--no-warnings=ExperimentalWarning"]
|
|
5577
5915
|
});
|
|
5916
|
+
this._childPid = this._child?.pid;
|
|
5578
5917
|
this._child.on("message", this.#handleMessage.bind(this));
|
|
5579
5918
|
this._child.on("exit", this.#handleExit.bind(this));
|
|
5580
5919
|
this._child.stdout?.on("data", this.#handleLog.bind(this));
|
|
@@ -5584,15 +5923,21 @@ var TaskRunProcess = class {
|
|
|
5584
5923
|
if (kill && this._isBeingKilled) {
|
|
5585
5924
|
return;
|
|
5586
5925
|
}
|
|
5587
|
-
|
|
5926
|
+
if (kill) {
|
|
5927
|
+
this._isBeingKilled = true;
|
|
5928
|
+
this.onIsBeingKilled.post(this._child?.pid);
|
|
5929
|
+
}
|
|
5930
|
+
logger.debug(`[${this.runId}] cleaning up task run process`, { kill, pid: this.pid });
|
|
5588
5931
|
await this._sender.send("CLEANUP", {
|
|
5589
5932
|
flush: true,
|
|
5590
5933
|
kill
|
|
5591
5934
|
});
|
|
5592
|
-
|
|
5935
|
+
if (!kill) {
|
|
5936
|
+
return;
|
|
5937
|
+
}
|
|
5593
5938
|
setTimeout(() => {
|
|
5594
5939
|
if (this._child && !this._child.killed) {
|
|
5595
|
-
logger.debug(`[${this.
|
|
5940
|
+
logger.debug(`[${this.runId}] killing task run process after timeout`, { pid: this.pid });
|
|
5596
5941
|
this._child.kill();
|
|
5597
5942
|
}
|
|
5598
5943
|
}, 5e3);
|
|
@@ -5600,8 +5945,8 @@ var TaskRunProcess = class {
|
|
|
5600
5945
|
async executeTaskRun(payload) {
|
|
5601
5946
|
let resolver;
|
|
5602
5947
|
let rejecter;
|
|
5603
|
-
const promise = new Promise((
|
|
5604
|
-
resolver =
|
|
5948
|
+
const promise = new Promise((resolve6, reject) => {
|
|
5949
|
+
resolver = resolve6;
|
|
5605
5950
|
rejecter = reject;
|
|
5606
5951
|
});
|
|
5607
5952
|
this._attemptStatuses.set(payload.execution.attempt.id, "PENDING");
|
|
@@ -5617,20 +5962,19 @@ var TaskRunProcess = class {
|
|
|
5617
5962
|
this._currentExecution = void 0;
|
|
5618
5963
|
return result;
|
|
5619
5964
|
}
|
|
5620
|
-
taskRunCompletedNotification(completion
|
|
5965
|
+
taskRunCompletedNotification(completion) {
|
|
5621
5966
|
if (!completion.ok && typeof completion.retry !== "undefined") {
|
|
5622
5967
|
return;
|
|
5623
5968
|
}
|
|
5624
|
-
if (
|
|
5969
|
+
if (completion.id === this.runId) {
|
|
5625
5970
|
return;
|
|
5626
5971
|
}
|
|
5627
|
-
logger.debug(`[${this.
|
|
5628
|
-
completion
|
|
5629
|
-
execution
|
|
5972
|
+
logger.debug(`[${this.runId}] task run completed notification`, {
|
|
5973
|
+
completion
|
|
5630
5974
|
});
|
|
5631
5975
|
this._sender.send("TASK_RUN_COMPLETED_NOTIFICATION", {
|
|
5632
|
-
|
|
5633
|
-
|
|
5976
|
+
version: "v2",
|
|
5977
|
+
completion
|
|
5634
5978
|
});
|
|
5635
5979
|
}
|
|
5636
5980
|
async #handleMessage(msg) {
|
|
@@ -5652,12 +5996,16 @@ var TaskRunProcess = class {
|
|
|
5652
5996
|
break;
|
|
5653
5997
|
}
|
|
5654
5998
|
case "READY_TO_DISPOSE": {
|
|
5655
|
-
logger.debug(`[${this.
|
|
5999
|
+
logger.debug(`[${this.runId}] task run process is ready to dispose`);
|
|
5656
6000
|
this.#kill();
|
|
5657
6001
|
break;
|
|
5658
6002
|
}
|
|
5659
6003
|
case "TASK_HEARTBEAT": {
|
|
5660
|
-
this.
|
|
6004
|
+
if (this.messageId) {
|
|
6005
|
+
this.onTaskRunHeartbeat.post(this.messageId);
|
|
6006
|
+
} else {
|
|
6007
|
+
this.onTaskHeartbeat.post(message.payload.id);
|
|
6008
|
+
}
|
|
5661
6009
|
break;
|
|
5662
6010
|
}
|
|
5663
6011
|
case "TASKS_READY": {
|
|
@@ -5665,8 +6013,8 @@ var TaskRunProcess = class {
|
|
|
5665
6013
|
}
|
|
5666
6014
|
}
|
|
5667
6015
|
}
|
|
5668
|
-
async #handleExit(code) {
|
|
5669
|
-
logger.debug(`[${this.
|
|
6016
|
+
async #handleExit(code, signal) {
|
|
6017
|
+
logger.debug(`[${this.runId}] handle task run process exit`, { code, signal, pid: this.pid });
|
|
5670
6018
|
for (const [id, status] of this._attemptStatuses.entries()) {
|
|
5671
6019
|
if (status === "PENDING") {
|
|
5672
6020
|
this._attemptStatuses.set(id, "REJECTED");
|
|
@@ -5680,11 +6028,11 @@ var TaskRunProcess = class {
|
|
|
5680
6028
|
} else if (this._isBeingKilled) {
|
|
5681
6029
|
rejecter(new CleanupProcessError());
|
|
5682
6030
|
} else {
|
|
5683
|
-
rejecter(new UnexpectedExitError(code));
|
|
6031
|
+
rejecter(new UnexpectedExitError(code ?? -1));
|
|
5684
6032
|
}
|
|
5685
6033
|
}
|
|
5686
6034
|
}
|
|
5687
|
-
this.onExit.post(code);
|
|
6035
|
+
this.onExit.post({ code, signal, pid: this.pid });
|
|
5688
6036
|
}
|
|
5689
6037
|
#handleLog(data) {
|
|
5690
6038
|
if (!this._currentExecution) {
|
|
@@ -5714,12 +6062,57 @@ var TaskRunProcess = class {
|
|
|
5714
6062
|
);
|
|
5715
6063
|
}
|
|
5716
6064
|
#kill() {
|
|
6065
|
+
logger.debug(`[${this.runId}] #kill()`, { pid: this.pid });
|
|
5717
6066
|
if (this._child && !this._child.killed) {
|
|
5718
|
-
logger.debug(`[${this.execution.run.id}] killing task run process`);
|
|
5719
6067
|
this._child?.kill();
|
|
5720
6068
|
}
|
|
5721
6069
|
}
|
|
6070
|
+
async kill(signal, timeoutInMs) {
|
|
6071
|
+
logger.debug(`[${this.runId}] killing task run process`, {
|
|
6072
|
+
signal,
|
|
6073
|
+
timeoutInMs,
|
|
6074
|
+
pid: this.pid
|
|
6075
|
+
});
|
|
6076
|
+
this._isBeingKilled = true;
|
|
6077
|
+
const killTimeout = this.onExit.waitFor(timeoutInMs);
|
|
6078
|
+
this.onIsBeingKilled.post(this._child?.pid);
|
|
6079
|
+
this._child?.kill(signal);
|
|
6080
|
+
if (timeoutInMs) {
|
|
6081
|
+
await killTimeout;
|
|
6082
|
+
}
|
|
6083
|
+
}
|
|
6084
|
+
get isBeingKilled() {
|
|
6085
|
+
return this._isBeingKilled || this._child?.killed;
|
|
6086
|
+
}
|
|
6087
|
+
get pid() {
|
|
6088
|
+
return this._childPid;
|
|
6089
|
+
}
|
|
5722
6090
|
};
|
|
6091
|
+
function formatErrorLog(error) {
|
|
6092
|
+
switch (error.type) {
|
|
6093
|
+
case "INTERNAL_ERROR": {
|
|
6094
|
+
return "";
|
|
6095
|
+
}
|
|
6096
|
+
case "STRING_ERROR": {
|
|
6097
|
+
return `
|
|
6098
|
+
|
|
6099
|
+
${chalkError("X Error:")} ${error.raw}
|
|
6100
|
+
`;
|
|
6101
|
+
}
|
|
6102
|
+
case "CUSTOM_ERROR": {
|
|
6103
|
+
return `
|
|
6104
|
+
|
|
6105
|
+
${chalkError("X Error:")} ${error.raw}
|
|
6106
|
+
`;
|
|
6107
|
+
}
|
|
6108
|
+
case "BUILT_IN_ERROR": {
|
|
6109
|
+
return `
|
|
6110
|
+
|
|
6111
|
+
${error.stackTrace.replace(/^Error: /, chalkError("X Error: "))}
|
|
6112
|
+
`;
|
|
6113
|
+
}
|
|
6114
|
+
}
|
|
6115
|
+
}
|
|
5723
6116
|
|
|
5724
6117
|
// src/utilities/runtimeCheck.ts
|
|
5725
6118
|
function runtimeCheck(minimumMajor, minimumMinor) {
|
|
@@ -5782,7 +6175,11 @@ async function devCommand(dir, options) {
|
|
|
5782
6175
|
)} Connecting to the server failed. Please check your internet connection or contact eric@trigger.dev for help.`
|
|
5783
6176
|
);
|
|
5784
6177
|
} else {
|
|
5785
|
-
logger.log(
|
|
6178
|
+
logger.log(
|
|
6179
|
+
`${chalkError("X Error:")} You must login first. Use the \`login\` CLI command.
|
|
6180
|
+
|
|
6181
|
+
${authorization.error}`
|
|
6182
|
+
);
|
|
5786
6183
|
}
|
|
5787
6184
|
process.exitCode = 1;
|
|
5788
6185
|
return;
|
|
@@ -5813,7 +6210,7 @@ async function startDev(dir, options, authorization, dashboardUrl) {
|
|
|
5813
6210
|
logger.error("Failed to read config", config.error);
|
|
5814
6211
|
process.exit(1);
|
|
5815
6212
|
}
|
|
5816
|
-
async function getDevReactElement(configParam, authorization2, configPath) {
|
|
6213
|
+
async function getDevReactElement(configParam, authorization2, configPath, configModule) {
|
|
5817
6214
|
const accessToken = authorization2.accessToken;
|
|
5818
6215
|
const apiUrl = authorization2.apiUrl;
|
|
5819
6216
|
apiClient = new CliApiClient(apiUrl, accessToken);
|
|
@@ -5845,7 +6242,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
|
|
|
5845
6242
|
projectName: devEnv.data.name,
|
|
5846
6243
|
debuggerOn: options.debugger,
|
|
5847
6244
|
debugOtel: options.debugOtel,
|
|
5848
|
-
configPath
|
|
6245
|
+
configPath,
|
|
6246
|
+
configModule
|
|
5849
6247
|
}
|
|
5850
6248
|
);
|
|
5851
6249
|
}
|
|
@@ -5853,7 +6251,8 @@ async function startDev(dir, options, authorization, dashboardUrl) {
|
|
|
5853
6251
|
await getDevReactElement(
|
|
5854
6252
|
config.config,
|
|
5855
6253
|
authorization,
|
|
5856
|
-
config.status === "file" ? config.path : void 0
|
|
6254
|
+
config.status === "file" ? config.path : void 0,
|
|
6255
|
+
config.status === "file" ? config.module : void 0
|
|
5857
6256
|
)
|
|
5858
6257
|
);
|
|
5859
6258
|
rerender = devReactElement.rerender;
|
|
@@ -5876,7 +6275,8 @@ function useDev({
|
|
|
5876
6275
|
projectName,
|
|
5877
6276
|
debuggerOn,
|
|
5878
6277
|
debugOtel,
|
|
5879
|
-
configPath
|
|
6278
|
+
configPath,
|
|
6279
|
+
configModule
|
|
5880
6280
|
}) {
|
|
5881
6281
|
useEffect(() => {
|
|
5882
6282
|
const websocketUrl = new URL(apiUrl);
|
|
@@ -5918,6 +6318,17 @@ function useDev({
|
|
|
5918
6318
|
});
|
|
5919
6319
|
}
|
|
5920
6320
|
);
|
|
6321
|
+
backgroundWorkerCoordinator.onWorkerTaskRunHeartbeat.attach(
|
|
6322
|
+
async ({ worker, backgroundWorkerId, id }) => {
|
|
6323
|
+
await sender.send("BACKGROUND_WORKER_MESSAGE", {
|
|
6324
|
+
backgroundWorkerId,
|
|
6325
|
+
data: {
|
|
6326
|
+
type: "TASK_RUN_HEARTBEAT",
|
|
6327
|
+
id
|
|
6328
|
+
}
|
|
6329
|
+
});
|
|
6330
|
+
}
|
|
6331
|
+
);
|
|
5921
6332
|
backgroundWorkerCoordinator.onTaskCompleted.attach(
|
|
5922
6333
|
async ({ backgroundWorkerId, completion, execution }) => {
|
|
5923
6334
|
await sender.send("BACKGROUND_WORKER_MESSAGE", {
|
|
@@ -5930,6 +6341,17 @@ function useDev({
|
|
|
5930
6341
|
});
|
|
5931
6342
|
}
|
|
5932
6343
|
);
|
|
6344
|
+
backgroundWorkerCoordinator.onTaskFailedToRun.attach(
|
|
6345
|
+
async ({ backgroundWorkerId, completion }) => {
|
|
6346
|
+
await sender.send("BACKGROUND_WORKER_MESSAGE", {
|
|
6347
|
+
backgroundWorkerId,
|
|
6348
|
+
data: {
|
|
6349
|
+
type: "TASK_RUN_FAILED_TO_RUN",
|
|
6350
|
+
completion
|
|
6351
|
+
}
|
|
6352
|
+
});
|
|
6353
|
+
}
|
|
6354
|
+
);
|
|
5933
6355
|
backgroundWorkerCoordinator.onWorkerRegistered.attach(async ({ id, worker, record }) => {
|
|
5934
6356
|
await sender.send("READY_FOR_TASKS", {
|
|
5935
6357
|
backgroundWorkerId: id
|
|
@@ -5950,7 +6372,8 @@ function useDev({
|
|
|
5950
6372
|
SERVER_READY: async (payload) => {
|
|
5951
6373
|
for (const worker of backgroundWorkerCoordinator.currentWorkers) {
|
|
5952
6374
|
await sender.send("READY_FOR_TASKS", {
|
|
5953
|
-
backgroundWorkerId: worker.id
|
|
6375
|
+
backgroundWorkerId: worker.id,
|
|
6376
|
+
inProgressRuns: worker.worker.inProgressRuns
|
|
5954
6377
|
});
|
|
5955
6378
|
}
|
|
5956
6379
|
},
|
|
@@ -5965,6 +6388,7 @@ function useDev({
|
|
|
5965
6388
|
await messageHandler.handleMessage(data);
|
|
5966
6389
|
});
|
|
5967
6390
|
let ctx;
|
|
6391
|
+
let firstBuild = true;
|
|
5968
6392
|
async function runBuild() {
|
|
5969
6393
|
if (ctx) {
|
|
5970
6394
|
await ctx.dispose();
|
|
@@ -5976,7 +6400,9 @@ function useDev({
|
|
|
5976
6400
|
const workerSetupPath = join7(cliRootPath(), "workers", "dev", "worker-setup.js");
|
|
5977
6401
|
let entryPointContents = workerFacade.replace("__TASKS__", createTaskFileImports(taskFiles)).replace(
|
|
5978
6402
|
"__WORKER_SETUP__",
|
|
5979
|
-
`import { tracingSDK, sender } from "${escapeImportPath(
|
|
6403
|
+
`import { tracingSDK, otelTracer, otelLogger, sender } from "${escapeImportPath(
|
|
6404
|
+
workerSetupPath
|
|
6405
|
+
)}";`
|
|
5980
6406
|
);
|
|
5981
6407
|
if (configPath) {
|
|
5982
6408
|
configPath = normalize(configPath);
|
|
@@ -5993,7 +6419,6 @@ function useDev({
|
|
|
5993
6419
|
`const importedConfig = undefined; const handleError = undefined;`
|
|
5994
6420
|
);
|
|
5995
6421
|
}
|
|
5996
|
-
let firstBuild = true;
|
|
5997
6422
|
logger.log(chalkGrey("\u25CB Building background worker\u2026"));
|
|
5998
6423
|
ctx = await context2({
|
|
5999
6424
|
stdin: {
|
|
@@ -6084,18 +6509,23 @@ function useDev({
|
|
|
6084
6509
|
}
|
|
6085
6510
|
const environmentVariablesResponse = await environmentClient.getEnvironmentVariables(config.project);
|
|
6086
6511
|
const processEnv = await gatherProcessEnv();
|
|
6087
|
-
const backgroundWorker = new BackgroundWorker(
|
|
6088
|
-
|
|
6089
|
-
|
|
6090
|
-
|
|
6091
|
-
|
|
6092
|
-
|
|
6093
|
-
|
|
6094
|
-
|
|
6512
|
+
const backgroundWorker = new BackgroundWorker(
|
|
6513
|
+
fullPath,
|
|
6514
|
+
{
|
|
6515
|
+
projectConfig: config,
|
|
6516
|
+
dependencies: dependencies2,
|
|
6517
|
+
env: {
|
|
6518
|
+
...processEnv,
|
|
6519
|
+
TRIGGER_API_URL: apiUrl,
|
|
6520
|
+
TRIGGER_SECRET_KEY: apiKey,
|
|
6521
|
+
...environmentVariablesResponse.success ? environmentVariablesResponse.data.variables : {}
|
|
6522
|
+
},
|
|
6523
|
+
debuggerOn,
|
|
6524
|
+
debugOtel,
|
|
6525
|
+
resolveEnvVariables: createResolveEnvironmentVariablesFunction(configModule)
|
|
6095
6526
|
},
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
});
|
|
6527
|
+
environmentClient
|
|
6528
|
+
);
|
|
6099
6529
|
try {
|
|
6100
6530
|
await backgroundWorker.initialize();
|
|
6101
6531
|
latestWorkerContentHash = contentHash;
|
|
@@ -6138,7 +6568,8 @@ function useDev({
|
|
|
6138
6568
|
cliPackageVersion: version,
|
|
6139
6569
|
tasks: taskResources,
|
|
6140
6570
|
contentHash
|
|
6141
|
-
}
|
|
6571
|
+
},
|
|
6572
|
+
supportsLazyAttempts: true
|
|
6142
6573
|
};
|
|
6143
6574
|
const backgroundWorkerRecord = await environmentClient.createBackgroundWorker(
|
|
6144
6575
|
config.project,
|
|
@@ -6326,18 +6757,9 @@ ${task.filePath} -> ${task.exportName}`).join("")}`;
|
|
|
6326
6757
|
}
|
|
6327
6758
|
async function gatherProcessEnv() {
|
|
6328
6759
|
const env = {
|
|
6760
|
+
...process.env,
|
|
6329
6761
|
NODE_ENV: process.env.NODE_ENV ?? "development",
|
|
6330
|
-
|
|
6331
|
-
USER: process.env.USER,
|
|
6332
|
-
SHELL: process.env.SHELL,
|
|
6333
|
-
NVM_INC: process.env.NVM_INC,
|
|
6334
|
-
NVM_DIR: process.env.NVM_DIR,
|
|
6335
|
-
NVM_BIN: process.env.NVM_BIN,
|
|
6336
|
-
LANG: process.env.LANG,
|
|
6337
|
-
TERM: process.env.TERM,
|
|
6338
|
-
NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH),
|
|
6339
|
-
HOME: process.env.HOME,
|
|
6340
|
-
BUN_INSTALL: process.env.BUN_INSTALL
|
|
6762
|
+
NODE_PATH: await amendNodePathWithPnpmNodeModules(process.env.NODE_PATH)
|
|
6341
6763
|
};
|
|
6342
6764
|
return Object.fromEntries(Object.entries(env).filter(([key, value]) => value !== void 0));
|
|
6343
6765
|
}
|
|
@@ -6366,6 +6788,26 @@ async function findPnpmNodeModulesPath() {
|
|
|
6366
6788
|
{ type: "directory" }
|
|
6367
6789
|
);
|
|
6368
6790
|
}
|
|
6791
|
+
var hasResolvedEnvVars = false;
|
|
6792
|
+
var resolvedEnvVars = {};
|
|
6793
|
+
function createResolveEnvironmentVariablesFunction(configModule) {
|
|
6794
|
+
return async (env, worker) => {
|
|
6795
|
+
if (hasResolvedEnvVars) {
|
|
6796
|
+
return resolvedEnvVars;
|
|
6797
|
+
}
|
|
6798
|
+
const $resolvedEnvVars = await callResolveEnvVars(
|
|
6799
|
+
configModule,
|
|
6800
|
+
env,
|
|
6801
|
+
"dev",
|
|
6802
|
+
worker.params.projectConfig.project
|
|
6803
|
+
);
|
|
6804
|
+
if ($resolvedEnvVars) {
|
|
6805
|
+
resolvedEnvVars = $resolvedEnvVars.variables;
|
|
6806
|
+
hasResolvedEnvVars = true;
|
|
6807
|
+
}
|
|
6808
|
+
return resolvedEnvVars;
|
|
6809
|
+
};
|
|
6810
|
+
}
|
|
6369
6811
|
|
|
6370
6812
|
// src/commands/init.ts
|
|
6371
6813
|
import { intro as intro5, isCancel as isCancel2, log as log6, outro as outro6, select as select2, text } from "@clack/prompts";
|
|
@@ -6374,9 +6816,9 @@ import { flattenAttributes as flattenAttributes4 } from "@trigger.dev/core/v3";
|
|
|
6374
6816
|
import { recordSpanException as recordSpanException6 } from "@trigger.dev/core/v3/workers";
|
|
6375
6817
|
import chalk5 from "chalk";
|
|
6376
6818
|
import { execa as execa3 } from "execa";
|
|
6377
|
-
import { applyEdits, modify } from "jsonc-parser";
|
|
6819
|
+
import { applyEdits, modify, findNodeAtLocation, parseTree, getNodeValue } from "jsonc-parser";
|
|
6378
6820
|
import { writeFile as writeFile3 } from "node:fs/promises";
|
|
6379
|
-
import { join as join8, relative as relative4, resolve as
|
|
6821
|
+
import { join as join8, relative as relative4, resolve as resolve5 } from "node:path";
|
|
6380
6822
|
import terminalLink4 from "terminal-link";
|
|
6381
6823
|
import { z as z6 } from "zod";
|
|
6382
6824
|
|
|
@@ -6541,7 +6983,7 @@ async function createTriggerDir(dir, options) {
|
|
|
6541
6983
|
if (isCancel2(location)) {
|
|
6542
6984
|
throw new OutroCommandError();
|
|
6543
6985
|
}
|
|
6544
|
-
const triggerDir =
|
|
6986
|
+
const triggerDir = resolve5(process.cwd(), location);
|
|
6545
6987
|
logger.debug({ triggerDir });
|
|
6546
6988
|
span.setAttributes({
|
|
6547
6989
|
"cli.triggerDir": triggerDir
|
|
@@ -6596,7 +7038,7 @@ async function createTriggerDir(dir, options) {
|
|
|
6596
7038
|
async function gitIgnoreDotTriggerDir(dir, options) {
|
|
6597
7039
|
return await tracer.startActiveSpan("gitIgnoreDotTriggerDir", async (span) => {
|
|
6598
7040
|
try {
|
|
6599
|
-
const projectDir =
|
|
7041
|
+
const projectDir = resolve5(process.cwd(), dir);
|
|
6600
7042
|
const gitIgnorePath = join8(projectDir, ".gitignore");
|
|
6601
7043
|
span.setAttributes({
|
|
6602
7044
|
"cli.projectDir": projectDir,
|
|
@@ -6630,14 +7072,30 @@ async function gitIgnoreDotTriggerDir(dir, options) {
|
|
|
6630
7072
|
async function addConfigFileToTsConfig(dir, options) {
|
|
6631
7073
|
return await tracer.startActiveSpan("createTriggerDir", async (span) => {
|
|
6632
7074
|
try {
|
|
6633
|
-
const projectDir =
|
|
7075
|
+
const projectDir = resolve5(process.cwd(), dir);
|
|
6634
7076
|
const tsconfigPath = join8(projectDir, "tsconfig.json");
|
|
6635
7077
|
span.setAttributes({
|
|
6636
7078
|
"cli.projectDir": projectDir,
|
|
6637
7079
|
"cli.tsconfigPath": tsconfigPath
|
|
6638
7080
|
});
|
|
6639
7081
|
const tsconfigContent = await readFile(tsconfigPath);
|
|
6640
|
-
const
|
|
7082
|
+
const tsconfigContentTree = parseTree(tsconfigContent, void 0);
|
|
7083
|
+
if (!tsconfigContentTree) {
|
|
7084
|
+
span.end();
|
|
7085
|
+
return;
|
|
7086
|
+
}
|
|
7087
|
+
const tsconfigIncludeOption = findNodeAtLocation(tsconfigContentTree, ["include"]);
|
|
7088
|
+
if (!tsconfigIncludeOption) {
|
|
7089
|
+
span.end();
|
|
7090
|
+
return;
|
|
7091
|
+
}
|
|
7092
|
+
const tsConfigFileName = "trigger.config.ts";
|
|
7093
|
+
const tsconfigIncludeOptionValue = getNodeValue(tsconfigIncludeOption);
|
|
7094
|
+
if (tsconfigIncludeOptionValue.includes(tsConfigFileName)) {
|
|
7095
|
+
span.end();
|
|
7096
|
+
return;
|
|
7097
|
+
}
|
|
7098
|
+
const edits = modify(tsconfigContent, ["include", -1], tsConfigFileName, {
|
|
6641
7099
|
isArrayInsertion: true,
|
|
6642
7100
|
formattingOptions: {
|
|
6643
7101
|
tabSize: 2,
|
|
@@ -6664,7 +7122,7 @@ async function installPackages2(dir, options) {
|
|
|
6664
7122
|
return await tracer.startActiveSpan("installPackages", async (span) => {
|
|
6665
7123
|
const installSpinner = spinner();
|
|
6666
7124
|
try {
|
|
6667
|
-
const projectDir =
|
|
7125
|
+
const projectDir = resolve5(process.cwd(), dir);
|
|
6668
7126
|
const pkgManager = await getUserPackageManager(projectDir);
|
|
6669
7127
|
span.setAttributes({
|
|
6670
7128
|
"cli.projectDir": projectDir,
|
|
@@ -6716,7 +7174,7 @@ async function writeConfigFile(dir, project, options, triggerDir) {
|
|
|
6716
7174
|
try {
|
|
6717
7175
|
const spnnr = spinner();
|
|
6718
7176
|
spnnr.start("Creating config file");
|
|
6719
|
-
const projectDir =
|
|
7177
|
+
const projectDir = resolve5(process.cwd(), dir);
|
|
6720
7178
|
const templatePath = join8(cliRootPath(), "templates", "trigger.config.ts.template");
|
|
6721
7179
|
const outputPath = join8(projectDir, "trigger.config.ts");
|
|
6722
7180
|
span.setAttributes({
|