Skip to content

A few small v4 fixes #2153

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/light-peas-melt.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"trigger.dev": patch
---

Fix update command version range handling
25 changes: 3 additions & 22 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ APP_ENV=development
APP_ORIGIN=http://localhost:3030
ELECTRIC_ORIGIN=http://localhost:3060
NODE_ENV=development
V3_ENABLED=true

# Redis is used for the v3 queuing and v2 concurrency control
REDIS_HOST="localhost"
Expand All @@ -22,6 +21,9 @@ REDIS_TLS_DISABLED="true"
DEV_OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:3030/otel"
DEV_OTEL_BATCH_PROCESSING_ENABLED="0"

# When the domain is set to `localhost` the CLI deploy command will only --load the image by default and not --push it
DEPLOY_REGISTRY_HOST=localhost:5000

# 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"
Expand Down Expand Up @@ -60,29 +62,11 @@ DEV_OTEL_BATCH_PROCESSING_ENABLED="0"
# 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=
CLOUD_AIRTABLE_CLIENT_ID=
CLOUD_AIRTABLE_CLIENT_SECRET=
CLOUD_GITHUB_CLIENT_ID=
CLOUD_GITHUB_CLIENT_SECRET=
CLOUD_LINEAR_CLIENT_ID=
CLOUD_LINEAR_CLIENT_SECRET=
CLOUD_SLACK_APP_HOST=
CLOUD_SLACK_CLIENT_ID=
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`

# DEPOT_ORG_ID=<Depot org id>
# DEPOT_TOKEN=<Depot org token>
DEPLOY_REGISTRY_HOST=localhost:5000 # This is the host that the deploy CLI will use to push images to the registry
# 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"
Expand All @@ -92,8 +76,5 @@ DEPLOY_REGISTRY_HOST=localhost:5000 # This is the host that the deploy CLI will

# 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,
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,15 @@ export function OrganizationSettingsSideMenu({
<div className="mb-1">
<SideMenuHeader title="Organization" />
</div>
<SideMenuItem
name="Usage"
icon={ChartBarIcon}
activeIconColor="text-indigo-500"
to={v3UsagePath(organization)}
data-action="usage"
/>
{isManagedCloud && (
<SideMenuItem
name="Usage"
icon={ChartBarIcon}
activeIconColor="text-indigo-500"
to={v3UsagePath(organization)}
data-action="usage"
/>
)}
{isManagedCloud && (
<SideMenuItem
name="Billing"
Expand Down
24 changes: 14 additions & 10 deletions apps/webapp/app/components/navigation/SideMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ import { SideMenuItem } from "./SideMenuItem";
import { SideMenuSection } from "./SideMenuSection";
import { BranchEnvironmentIconSmall } from "~/assets/icons/EnvironmentIcons";
import { V4Badge } from "../V4Badge";
import { useFeatures } from "~/hooks/useFeatures";

type SideMenuUser = Pick<User, "email" | "admin"> & { isImpersonating: boolean };
export type SideMenuProject = Pick<
Expand Down Expand Up @@ -342,6 +343,7 @@ function ProjectSelector({
const currentPlan = useCurrentPlan();
const [isOrgMenuOpen, setOrgMenuOpen] = useState(false);
const navigation = useNavigation();
const { isManagedCloud } = useFeatures();

let plan: string | undefined = undefined;
if (currentPlan?.v3Subscription?.isPaying === false) {
Expand Down Expand Up @@ -410,16 +412,18 @@ function ProjectSelector({
<CogIcon className="size-4 text-text-dimmed" />
<span className="text-text-bright">Settings</span>
</LinkButton>
<LinkButton
variant="secondary/small"
to={v3UsagePath(organization)}
fullWidth
iconSpacing="gap-1.5"
className="group-hover/button:border-charcoal-500"
>
<ChartBarIcon className="size-4 text-text-dimmed" />
<span className="text-text-bright">Usage</span>
</LinkButton>
{isManagedCloud && (
<LinkButton
variant="secondary/small"
to={v3UsagePath(organization)}
fullWidth
iconSpacing="gap-1.5"
className="group-hover/button:border-charcoal-500"
>
<ChartBarIcon className="size-4 text-text-dimmed" />
<span className="text-text-bright">Usage</span>
</LinkButton>
)}
</div>
</div>
<div className="flex flex-col gap-1 p-1">
Expand Down
57 changes: 3 additions & 54 deletions apps/webapp/app/env.server.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { z } from "zod";
import { SecretStoreOptionsSchema } from "./services/secrets/secretStoreOptionsSchema.server";
import { isValidDatabaseUrl } from "./utils/db";
import { isValidRegex } from "./utils/regex";
import { BoolEnv } from "./utils/boolEnv";
Expand Down Expand Up @@ -38,10 +37,7 @@ const EnvironmentSchema = z.object({
ELECTRIC_ORIGIN: z.string().default("http://localhost:3060"),
APP_ENV: z.string().default(process.env.NODE_ENV),
SERVICE_NAME: z.string().default("trigger.dev webapp"),
SECRET_STORE: SecretStoreOptionsSchema.default("DATABASE"),
POSTHOG_PROJECT_KEY: z.string().default("phc_LFH7kJiGhdIlnO22hTAKgHpaKhpM8gkzWAFvHmf5vfS"),
TELEMETRY_TRIGGER_API_KEY: z.string().optional(),
TELEMETRY_TRIGGER_API_URL: z.string().optional(),
TRIGGER_TELEMETRY_DISABLED: z.string().optional(),
AUTH_GITHUB_CLIENT_ID: z.string().optional(),
AUTH_GITHUB_CLIENT_SECRET: z.string().optional(),
Expand All @@ -56,30 +52,11 @@ const EnvironmentSchema = z.object({
SMTP_PASSWORD: z.string().optional(),

PLAIN_API_KEY: z.string().optional(),
RUNTIME_PLATFORM: z.enum(["docker-compose", "ecs", "local"]).default("local"),
WORKER_SCHEMA: z.string().default("graphile_worker"),
WORKER_CONCURRENCY: z.coerce.number().int().default(10),
WORKER_POLL_INTERVAL: z.coerce.number().int().default(1000),
/** The number of days a failed Graphile task should stay before getting cleaned up */
WORKER_CLEANUP_TTL_DAYS: z.coerce.number().int().default(3),
EXECUTION_WORKER_CONCURRENCY: z.coerce.number().int().default(10),
EXECUTION_WORKER_POLL_INTERVAL: z.coerce.number().int().default(1000),
WORKER_ENABLED: z.string().default("true"),
EXECUTION_WORKER_ENABLED: z.string().default("true"),
TASK_OPERATION_WORKER_ENABLED: z.string().default("true"),
TASK_OPERATION_WORKER_CONCURRENCY: z.coerce.number().int().default(10),
TASK_OPERATION_WORKER_POLL_INTERVAL: z.coerce.number().int().default(1000),
GRACEFUL_SHUTDOWN_TIMEOUT: z.coerce.number().int().default(60000),
/** Optional. Only used if you use the apps/proxy */
AWS_SQS_REGION: z.string().optional(),
/** Optional. Only used if you use the apps/proxy */
AWS_SQS_ACCESS_KEY_ID: z.string().optional(),
/** Optional. Only used if you use the apps/proxy */
AWS_SQS_SECRET_ACCESS_KEY: z.string().optional(),
/** Optional. Only used if you use the apps/proxy */
AWS_SQS_QUEUE_URL: z.string().optional(),
AWS_SQS_BATCH_SIZE: z.coerce.number().int().optional().default(1),
AWS_SQS_WAIT_TIME_MS: z.coerce.number().int().optional().default(100),
DISABLE_SSE: z.string().optional(),
OPENAI_API_KEY: z.string().optional(),

Expand Down Expand Up @@ -215,12 +192,9 @@ const EnvironmentSchema = z.object({
PUBSUB_REDIS_CLUSTER_MODE_ENABLED: z.string().default("0"),

DEFAULT_ENV_EXECUTION_CONCURRENCY_LIMIT: z.coerce.number().int().default(100),
DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT: z.coerce.number().int().default(100),
DEFAULT_ORG_EXECUTION_CONCURRENCY_LIMIT: z.coerce.number().int().default(300),
DEFAULT_DEV_ENV_EXECUTION_ATTEMPTS: z.coerce.number().int().positive().default(1),

TUNNEL_HOST: z.string().optional(),
TUNNEL_SECRET_KEY: z.string().optional(),

//API Rate limiting
/**
* @example "60s"
Expand All @@ -240,35 +214,16 @@ const EnvironmentSchema = z.object({
API_RATE_LIMIT_JWT_WINDOW: z.string().default("1m"),
API_RATE_LIMIT_JWT_TOKENS: z.coerce.number().int().default(60),

//Realtime rate limiting
/**
* @example "60s"
* @example "1m"
* @example "1h"
* @example "1d"
* @example "1000ms"
* @example "1000s"
*/
REALTIME_RATE_LIMIT_WINDOW: z.string().default("1m"),
REALTIME_RATE_LIMIT_TOKENS: z.coerce.number().int().default(100),
REALTIME_RATE_LIMIT_REQUEST_LOGS_ENABLED: z.string().default("0"),
REALTIME_RATE_LIMIT_REJECTION_LOGS_ENABLED: z.string().default("1"),
REALTIME_RATE_LIMIT_LIMITER_LOGS_ENABLED: z.string().default("0"),

//Ingesting event rate limit
INGEST_EVENT_RATE_LIMIT_WINDOW: z.string().default("60s"),
INGEST_EVENT_RATE_LIMIT_MAX: z.coerce.number().int().optional(),

//v3
PROVIDER_SECRET: z.string().default("provider-secret"),
COORDINATOR_SECRET: z.string().default("coordinator-secret"),
DEPOT_TOKEN: z.string().optional(),
DEPOT_ORG_ID: z.string().optional(),
DEPOT_REGION: z.string().default("us-east-1"),
DEPLOY_REGISTRY_HOST: z.string(),
DEPLOY_REGISTRY_HOST: z.string().min(1),
DEPLOY_REGISTRY_USERNAME: z.string().optional(),
DEPLOY_REGISTRY_PASSWORD: z.string().optional(),
DEPLOY_REGISTRY_NAMESPACE: z.string().default("trigger"),
DEPLOY_REGISTRY_NAMESPACE: z.string().min(1).default("trigger"),
DEPLOY_IMAGE_PLATFORM: z.string().default("linux/amd64"),
DEPLOY_TIMEOUT_MS: z.coerce
.number()
Expand Down Expand Up @@ -377,8 +332,6 @@ const EnvironmentSchema = z.object({
.default(process.env.REDIS_TLS_DISABLED ?? "false"),
ALERT_RATE_LIMITER_REDIS_CLUSTER_MODE_ENABLED: z.string().default("0"),

MAX_SEQUENTIAL_INDEX_FAILURE_COUNT: z.coerce.number().default(96),

LOOPS_API_KEY: z.string().optional(),
MARQS_DISABLE_REBALANCING: BoolEnv.default(false),
MARQS_VISIBILITY_TIMEOUT_MS: z.coerce
Expand Down Expand Up @@ -415,12 +368,8 @@ const EnvironmentSchema = z.object({
USAGE_EVENT_URL: z.string().optional(),
PROD_USAGE_HEARTBEAT_INTERVAL_MS: z.coerce.number().int().optional(),

CENTS_PER_VCPU_SECOND: z.coerce.number().default(0),
CENTS_PER_GB_RAM_SECOND: z.coerce.number().default(0),
CENTS_PER_RUN: z.coerce.number().default(0),

USAGE_OPEN_METER_API_KEY: z.string().optional(),
USAGE_OPEN_METER_BASE_URL: z.string().optional(),
EVENT_LOOP_MONITOR_ENABLED: z.string().default("1"),
MAXIMUM_LIVE_RELOADING_EVENTS: z.coerce.number().int().default(1000),
MAXIMUM_TRACE_SUMMARY_VIEW_COUNT: z.coerce.number().int().default(25_000),
Expand Down
3 changes: 2 additions & 1 deletion apps/webapp/app/services/email.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ const alertsClient = singleton(
transport: buildTransportOptions(true),
imagesBaseUrl: env.APP_ORIGIN,
from: env.ALERT_FROM_EMAIL ?? "noreply@alerts.trigger.dev",
replyTo: env.REPLY_TO_EMAIL ?? "help@email.trigger.dev",
// Fallback to `REPLY_TO_EMAIL` for backwards compat
replyTo: env.ALERT_REPLY_TO_EMAIL ?? env.REPLY_TO_EMAIL ?? "help@email.trigger.dev",
})
);

Expand Down
2 changes: 1 addition & 1 deletion apps/webapp/app/services/upsertBranch.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ export async function checkBranchLimit(
const count = newBranchName
? usedEnvs.filter((env) => env.branchName !== newBranchName).length
: usedEnvs.length;
const limit = await getLimit(organizationId, "branches", 50);
const limit = await getLimit(organizationId, "branches", 100_000_000);

return {
used: count,
Expand Down
1 change: 0 additions & 1 deletion docker/services-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ services:
REMIX_APP_PORT: 3030
PORT: 3030
WORKER_ENABLED: "false"
EXECUTION_WORKER_ENABLED: "false"
networks:
- app_network
worker:
Expand Down
8 changes: 7 additions & 1 deletion packages/cli-v3/src/commands/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,13 @@ export async function updateTriggerPackages(
}

const isDowngrade = mismatches.some((dep) => {
return semver.gt(dep.version, targetVersion);
const depMinVersion = semver.minVersion(dep.version);

if (!depMinVersion) {
return false;
}

return semver.gt(depMinVersion, targetVersion);
});

return {
Expand Down