Skip to content

Commit 8105d30

Browse files
authored
Merge branch 'main' into graham/fix-chat-reconnect-seq
2 parents 177cd53 + b939045 commit 8105d30

80 files changed

Lines changed: 1012 additions & 521 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@trigger.dev/core": patch
3+
---
4+
5+
Unrelated runs are no longer merged into a single trace in your external observability tool when they happen to execute on the same warm worker process.

.github/workflows/e2e-webapp-auth-full.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,10 @@ jobs:
9999
run: echo "DockerHub login skipped because secrets are not available."
100100

101101
- name: 🐳 Pre-pull testcontainer images
102-
if: ${{ env.DOCKERHUB_USERNAME }}
103102
run: |
104103
docker pull postgres:14
105104
docker pull redis:7.2
106-
docker pull testcontainers/ryuk:0.11.0
105+
docker pull testcontainers/ryuk:0.14.0
107106
108107
- name: 📥 Download deps
109108
run: pnpm install --frozen-lockfile

.github/workflows/e2e-webapp.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,11 @@ jobs:
7474
run: echo "DockerHub login skipped because secrets are not available."
7575

7676
- name: 🐳 Pre-pull testcontainer images
77-
if: ${{ env.DOCKERHUB_USERNAME }}
7877
run: |
7978
echo "Pre-pulling Docker images with authenticated session..."
8079
docker pull postgres:14
8180
docker pull redis:7.2
82-
docker pull testcontainers/ryuk:0.11.0
81+
docker pull testcontainers/ryuk:0.14.0
8382
docker pull ghcr.io/s2-streamstore/s2:0.40.0@sha256:b26249e2ede0949755f5af8028185dc2bcfc3aa2db21eb9610543d144eb6ee9d
8483
docker pull minio/minio:latest
8584
echo "Image pre-pull complete"

.github/workflows/unit-tests-internal.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ jobs:
7878
run: echo "DockerHub login skipped because secrets are not available."
7979

8080
- name: 🐳 Pre-pull testcontainer images
81-
if: ${{ env.DOCKERHUB_USERNAME }}
8281
run: |
8382
# Retry each pull - DockerHub registry timeouts are a recurring transient CI flake.
8483
pull() {
@@ -96,7 +95,6 @@ jobs:
9695
pull clickhouse/clickhouse-server:26.2.19.43-alpine@sha256:c6ad6a7eb2fb5999df3adfb8b69a0c7222c68fa9b8f6b04a088564ebbc959251
9796
pull redis:7.2
9897
pull testcontainers/ryuk:0.14.0
99-
pull electricsql/electric:1.2.4
10098
echo "Image pre-pull complete"
10199
102100
- name: 📥 Download deps

.github/workflows/unit-tests-packages.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ jobs:
8181
run: echo "DockerHub login skipped because secrets are not available."
8282

8383
- name: 🐳 Pre-pull testcontainer images
84-
if: ${{ env.DOCKERHUB_USERNAME }}
8584
run: |
8685
# Retry each pull - DockerHub registry timeouts are a recurring transient CI flake.
8786
pull() {
@@ -98,7 +97,6 @@ jobs:
9897
pull clickhouse/clickhouse-server:26.2.19.43-alpine@sha256:c6ad6a7eb2fb5999df3adfb8b69a0c7222c68fa9b8f6b04a088564ebbc959251
9998
pull redis:7.2
10099
pull testcontainers/ryuk:0.14.0
101-
pull electricsql/electric:1.2.4
102100
pull otel/opentelemetry-collector-k8s:0.158.0@sha256:c09130a633196a5becee164411473a0932ecf223f94fda6dab5f22798ff9f376
103101
echo "Image pre-pull complete"
104102

.github/workflows/unit-tests-webapp.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,6 @@ jobs:
8686
run: echo "DockerHub login skipped because secrets are not available."
8787

8888
- name: 🐳 Pre-pull testcontainer images
89-
if: ${{ env.DOCKERHUB_USERNAME }}
9089
run: |
9190
# Retry each pull - DockerHub registry timeouts are a recurring transient CI flake.
9291
pull() {
@@ -100,10 +99,11 @@ jobs:
10099
}
101100
echo "Pre-pulling Docker images with authenticated session..."
102101
pull postgres:14
102+
pull postgres:17
103103
pull clickhouse/clickhouse-server:26.2.19.43-alpine@sha256:c6ad6a7eb2fb5999df3adfb8b69a0c7222c68fa9b8f6b04a088564ebbc959251
104104
pull redis:7.2
105105
pull testcontainers/ryuk:0.14.0
106-
pull electricsql/electric:1.2.4
106+
pull electricsql/electric:1.2.4@sha256:20da3d0b0e74926c5623392db67fd56698b9e374c4aeb6cb5cadeb8fea171c36
107107
pull minio/minio:latest
108108
echo "Image pre-pull complete"
109109

.oxlintrc.json

Lines changed: 77 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"categories": {
44
"correctness": "error"
55
},
6-
"plugins": ["typescript", "import", "react"],
6+
"plugins": ["typescript", "import", "react", "jsx-a11y"],
77
"jsPlugins": [
88
"./oxlint-plugins/no-thrown-unawaited-redirect.mjs",
99
"./oxlint-plugins/runops-residency.mjs",
@@ -34,7 +34,7 @@
3434
],
3535
"no-empty-pattern": "off",
3636
"no-control-regex": "off",
37-
"typescript/no-non-null-asserted-optional-chain": "off",
37+
"typescript/no-non-null-asserted-optional-chain": "error",
3838
"no-unused-expressions": [
3939
"error",
4040
{
@@ -47,6 +47,66 @@
4747
"import/namespace": "off",
4848
"react-hooks/exhaustive-deps": "off",
4949
"react-hooks/rules-of-hooks": "off",
50+
"guard-for-in": "error",
51+
"symbol-description": "error",
52+
"no-unneeded-ternary": "error",
53+
"prefer-object-has-own": "error",
54+
"no-redeclare": "error",
55+
"no-multi-assign": "error",
56+
"prefer-object-spread": "error",
57+
"react/jsx-no-target-blank": "error",
58+
"react/jsx-fragments": "error",
59+
"react/self-closing-comp": "error",
60+
"react/jsx-no-constructed-context-values": "error",
61+
"react/no-children-prop": "error",
62+
"react/no-danger-with-children": "error",
63+
"react/no-direct-mutation-state": "error",
64+
"react/no-find-dom-node": "error",
65+
"react/no-is-mounted": "error",
66+
"react/no-render-return-value": "error",
67+
"react/no-string-refs": "error",
68+
"react/no-unsafe": "error",
69+
"react/no-will-update-set-state": "error",
70+
"react/require-render-return": "error",
71+
"react/style-prop-object": "error",
72+
"react/void-dom-elements-no-children": "error",
73+
"react/checked-requires-onchange-or-readonly": "error",
74+
"react/forward-ref-uses-ref": "error",
75+
"react/iframe-missing-sandbox": "error",
76+
"react/no-unknown-property": "error",
77+
"jsx-a11y/alt-text": "off",
78+
"jsx-a11y/aria-role": "off",
79+
"jsx-a11y/click-events-have-key-events": "off",
80+
"jsx-a11y/control-has-associated-label": "off",
81+
"jsx-a11y/label-has-associated-control": "off",
82+
"jsx-a11y/no-autofocus": "off",
83+
"jsx-a11y/no-noninteractive-element-interactions": "off",
84+
"jsx-a11y/no-static-element-interactions": "off",
85+
"jsx-a11y/prefer-tag-over-role": "off",
86+
"jsx-a11y/anchor-ambiguous-text": "error",
87+
"jsx-a11y/anchor-has-content": "error",
88+
"jsx-a11y/anchor-is-valid": "error",
89+
"jsx-a11y/aria-activedescendant-has-tabindex": "error",
90+
"jsx-a11y/aria-props": "error",
91+
"jsx-a11y/aria-proptypes": "error",
92+
"jsx-a11y/aria-unsupported-elements": "error",
93+
"jsx-a11y/autocomplete-valid": "error",
94+
"jsx-a11y/heading-has-content": "error",
95+
"jsx-a11y/html-has-lang": "error",
96+
"jsx-a11y/iframe-has-title": "error",
97+
"jsx-a11y/img-redundant-alt": "error",
98+
"jsx-a11y/media-has-caption": "error",
99+
"jsx-a11y/no-access-key": "error",
100+
"jsx-a11y/no-aria-hidden-on-focusable": "error",
101+
"jsx-a11y/no-distracting-elements": "error",
102+
"jsx-a11y/no-redundant-roles": "error",
103+
"jsx-a11y/role-has-required-aria-props": "error",
104+
"jsx-a11y/role-supports-aria-props": "error",
105+
"jsx-a11y/scope": "error",
106+
"jsx-a11y/tabindex-no-positive": "error",
107+
"no-lone-blocks": "error",
108+
"typescript/prefer-function-type": "error",
109+
"typescript/prefer-for-of": "error",
50110
"trigger/no-thrown-unawaited-redirect": "error",
51111
"trigger-prisma/no-unbounded-list-filter": "error",
52112
"trigger-prisma/no-unbounded-list-filter-in-args-helper": "error"
@@ -72,6 +132,21 @@
72132
"trigger-prisma/no-unbounded-list-filter": "off",
73133
"trigger-prisma/no-unbounded-list-filter-in-args-helper": "off"
74134
}
135+
},
136+
{
137+
"files": ["internal-packages/tsql/**"],
138+
"rules": {
139+
"prefer-object-has-own": "off"
140+
}
141+
},
142+
{
143+
"files": [
144+
"apps/webapp/app/components/primitives/charts/Chart.tsx",
145+
"apps/webapp/app/components/primitives/Timeline.tsx"
146+
],
147+
"rules": {
148+
"react/jsx-no-constructed-context-values": "off"
149+
}
75150
}
76151
]
77152
}

apps/supervisor/src/env.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ export const Env = z
187187
KUBERNETES_STRIP_IMAGE_DIGEST: BoolEnv.default(false),
188188
KUBERNETES_IMAGE_REGISTRY_REWRITE_FROM: z.string().optional(),
189189
KUBERNETES_IMAGE_REGISTRY_REWRITE_TO: z.string().optional(),
190+
KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME: z.string().optional(),
190191
KUBERNETES_CPU_REQUEST_MIN_CORES: z.coerce.number().min(0).default(0),
191192
KUBERNETES_CPU_REQUEST_RATIO: z.coerce.number().min(0).max(1).default(0.75), // Ratio of CPU limit, so 0.75 = 75% of CPU limit
192193
KUBERNETES_MEMORY_REQUEST_MIN_GB: z.coerce.number().min(0).default(0),
@@ -220,6 +221,8 @@ export const Env = z
220221
KUBERNETES_RUNNER_SECCOMP_PROFILE_RUNTIMES: z
221222
.enum(["none", "node-24-plus", "all"])
222223
.default("node-24-plus"),
224+
KUBERNETES_RUNNER_SECURITY_CONTEXT: z.enum(["off", "baseline", "restricted"]).default("off"),
225+
KUBERNETES_RUNNER_RUN_AS_USER: z.coerce.number().int().min(1).default(1000),
223226

224227
// Pod DNS config — override the cluster default ndots to `KUBERNETES_POD_DNS_NDOTS`.
225228
// Default k8s ndots is 5: any name with fewer than 5 dots (e.g. `api.example.com`, 2 dots) is first walked

apps/supervisor/src/workloadManager/kubernetes.test.ts

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import { describe, expect, it } from "vitest";
22
import {
33
nodetypeNodeSelector,
44
runPodTolerations,
5+
runnerSecurityContext,
56
withRunnerSeccompProfile,
67
withNodeSelector,
78
} from "./kubernetesPodSpec.js";
@@ -153,3 +154,35 @@ describe("withRunnerSeccompProfile", () => {
153154
}
154155
});
155156
});
157+
158+
describe("runnerSecurityContext", () => {
159+
it("sets nothing when off", () => {
160+
expect(runnerSecurityContext("off", 1000, "node-24")).toBeUndefined();
161+
});
162+
163+
it("drops all capabilities and blocks escalation at baseline", () => {
164+
expect(runnerSecurityContext("baseline", 1000, "node-24")).toEqual({
165+
allowPrivilegeEscalation: false,
166+
capabilities: { drop: ["ALL"] },
167+
});
168+
});
169+
170+
it("pins the configured uid when restricted", () => {
171+
expect(runnerSecurityContext("restricted", 1000, "node-24")).toEqual({
172+
allowPrivilegeEscalation: false,
173+
capabilities: { drop: ["ALL"] },
174+
runAsNonRoot: true,
175+
runAsUser: 1000,
176+
});
177+
});
178+
179+
it("pins bun's own uid, which differs from node's", () => {
180+
expect(runnerSecurityContext("restricted", 1000, "bun")?.runAsUser).toBe(1001);
181+
});
182+
183+
it("falls back to the configured uid when the runtime is unknown", () => {
184+
for (const runtime of [undefined, null, "", "node", "node-22", "node-26"]) {
185+
expect(runnerSecurityContext("restricted", 1000, runtime)?.runAsUser).toBe(1000);
186+
}
187+
});
188+
});

apps/supervisor/src/workloadManager/kubernetes.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import { getRunnerId } from "../util.js";
1717
import {
1818
nodetypeNodeSelector,
1919
runPodTolerations,
20+
runnerSecurityContext,
2021
withRunnerSeccompProfile,
2122
withNodeSelector,
2223
} from "./kubernetesPodSpec.js";
@@ -175,6 +176,11 @@ export class KubernetesWorkloadManager implements WorkloadManager {
175176
},
176177
],
177178
resources: this.#getResourcesForMachine(opts.machine),
179+
securityContext: runnerSecurityContext(
180+
env.KUBERNETES_RUNNER_SECURITY_CONTEXT,
181+
env.KUBERNETES_RUNNER_RUN_AS_USER,
182+
opts.runtime
183+
),
178184
env: [
179185
{
180186
name: "TRIGGER_DEQUEUED_AT_MS",
@@ -365,6 +371,11 @@ export class KubernetesWorkloadManager implements WorkloadManager {
365371
schedulerName: env.KUBERNETES_SCHEDULER_NAME,
366372
}
367373
: {}),
374+
...(env.KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME
375+
? {
376+
priorityClassName: env.KUBERNETES_RUN_POD_PRIORITY_CLASS_NAME,
377+
}
378+
: {}),
368379
...nodetypeNodeSelector(env.KUBERNETES_WORKER_NODETYPE_LABEL),
369380
...(env.KUBERNETES_POD_DNS_NDOTS_OVERRIDE_ENABLED
370381
? {

0 commit comments

Comments
 (0)