@sentry/junior-vercel 0.264.0 → 0.266.0
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/README.md +10 -0
- package/dist/{chunk-VXKYUJID.js → chunk-CUJQR3FA.js} +94 -73
- package/dist/events/deployment.d.ts +23 -4
- package/dist/index.js +10 -4
- package/dist/testing.js +1 -1
- package/dist/webhooks/events.d.ts +4 -1
- package/dist/webhooks/secret.d.ts +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -51,6 +51,16 @@ Supported scopes (`deployment` resource type):
|
|
|
51
51
|
- `<project-id>:production` for every production deployment
|
|
52
52
|
- `<project-id>:production:<sha>` for one commit-scoped deployment
|
|
53
53
|
|
|
54
|
+
Each event has the name of the Vercel webhook that it comes from:
|
|
55
|
+
|
|
56
|
+
- `deployment.succeeded`: the deployment is ready.
|
|
57
|
+
- `deployment.error`: the deployment failed. This is the same as GitHub `deployment.failed`, not GitHub `deployment.error`.
|
|
58
|
+
- `deployment.canceled`: the deployment was canceled.
|
|
59
|
+
|
|
60
|
+
All three events end a commit-scoped watch. Project and target watches stay active.
|
|
61
|
+
|
|
62
|
+
Each deployment event has trusted data: `deploymentId`, `target`, and `commitSha` when the deployment came from a Git commit. Watches and event automations can filter on `target` (`preview`, `production`, or `staging`) and `commitSha`.
|
|
63
|
+
|
|
54
64
|
Create the conversation watch or event automation before the terminal deployment event. A valid webhook delivery does not create a watch by itself, and unmatched deliveries are not replayed later.
|
|
55
65
|
|
|
56
66
|
## Auth model
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
// src/events/deployment.ts
|
|
2
|
+
import {
|
|
3
|
+
eventMatchFieldsSchema
|
|
4
|
+
} from "@sentry/junior-plugin-api";
|
|
2
5
|
var VERCEL_DEPLOYMENT_EVENTS = [
|
|
3
6
|
"deployment.succeeded",
|
|
4
7
|
"deployment.error",
|
|
@@ -9,15 +12,43 @@ var VERCEL_DEPLOYMENT_SUGGESTED_EVENTS = [
|
|
|
9
12
|
"deployment.error",
|
|
10
13
|
"deployment.canceled"
|
|
11
14
|
];
|
|
15
|
+
var VERCEL_DEPLOYMENT_TARGETS = [
|
|
16
|
+
"preview",
|
|
17
|
+
"production",
|
|
18
|
+
"staging"
|
|
19
|
+
];
|
|
20
|
+
var VERCEL_DEPLOYMENT_MATCH_FIELDS = eventMatchFieldsSchema.parse({
|
|
21
|
+
projectId: {
|
|
22
|
+
kind: "string",
|
|
23
|
+
description: "Vercel project id, such as prj_abc123",
|
|
24
|
+
events: [...VERCEL_DEPLOYMENT_EVENTS]
|
|
25
|
+
},
|
|
26
|
+
deploymentId: {
|
|
27
|
+
kind: "string",
|
|
28
|
+
description: "Vercel deployment id, such as dpl_abc123",
|
|
29
|
+
events: [...VERCEL_DEPLOYMENT_EVENTS]
|
|
30
|
+
},
|
|
31
|
+
target: {
|
|
32
|
+
kind: "string",
|
|
33
|
+
description: "where Vercel deployed: preview, production, or staging",
|
|
34
|
+
enum: [...VERCEL_DEPLOYMENT_TARGETS],
|
|
35
|
+
events: [...VERCEL_DEPLOYMENT_EVENTS]
|
|
36
|
+
},
|
|
37
|
+
commitSha: {
|
|
38
|
+
kind: "string",
|
|
39
|
+
description: "full lowercase Git commit SHA of the deployment, when it came from a Git commit",
|
|
40
|
+
events: [...VERCEL_DEPLOYMENT_EVENTS]
|
|
41
|
+
}
|
|
42
|
+
});
|
|
12
43
|
function vercelDeploymentResource(input) {
|
|
13
|
-
const
|
|
44
|
+
const commitSha = input.commitSha?.toLowerCase();
|
|
14
45
|
const target = input.target;
|
|
15
46
|
const parts = [input.projectId];
|
|
16
47
|
if (target) parts.push(target);
|
|
17
|
-
if (
|
|
48
|
+
if (commitSha) parts.push(commitSha);
|
|
18
49
|
let label;
|
|
19
|
-
if (target &&
|
|
20
|
-
label = `Vercel ${target} deployment for ${input.projectId} at ${
|
|
50
|
+
if (target && commitSha) {
|
|
51
|
+
label = `Vercel ${target} deployment for ${input.projectId} at ${commitSha.slice(0, 12)}`;
|
|
21
52
|
} else if (target) {
|
|
22
53
|
label = `Vercel ${target} deployments for ${input.projectId}`;
|
|
23
54
|
} else {
|
|
@@ -30,7 +61,7 @@ function vercelDeploymentResource(input) {
|
|
|
30
61
|
};
|
|
31
62
|
}
|
|
32
63
|
function vercelDeploymentSubscribable(input) {
|
|
33
|
-
if (!input.
|
|
64
|
+
if (!input.canSubscribe) return void 0;
|
|
34
65
|
if (input.commitSha && !input.target) return void 0;
|
|
35
66
|
return {
|
|
36
67
|
...vercelDeploymentResource(input),
|
|
@@ -40,11 +71,6 @@ function vercelDeploymentSubscribable(input) {
|
|
|
40
71
|
};
|
|
41
72
|
}
|
|
42
73
|
|
|
43
|
-
// src/webhooks/secret.ts
|
|
44
|
-
function vercelWebhookSecret() {
|
|
45
|
-
return process.env.VERCEL_WEBHOOK_SECRET?.trim() || void 0;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
74
|
// src/tools/deployment.ts
|
|
49
75
|
import {
|
|
50
76
|
definePluginTool,
|
|
@@ -127,17 +153,17 @@ function createVercelDeploymentTool(ctx) {
|
|
|
127
153
|
throw new Error(message);
|
|
128
154
|
}
|
|
129
155
|
const projectId = z2.object({ id: vercelProjectIdSchema }).parse(parsed).id;
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
const subscribable =
|
|
133
|
-
|
|
156
|
+
const commitSha = input.commitSha?.toLowerCase();
|
|
157
|
+
const deploymentTarget = input.target ?? (commitSha ? "production" : void 0);
|
|
158
|
+
const subscribable = vercelDeploymentSubscribable({
|
|
159
|
+
canSubscribe: ctx.events.canSubscribe,
|
|
160
|
+
commitSha,
|
|
134
161
|
projectId,
|
|
135
|
-
target:
|
|
136
|
-
|
|
137
|
-
}) : void 0;
|
|
162
|
+
target: deploymentTarget
|
|
163
|
+
});
|
|
138
164
|
const data = {
|
|
139
|
-
commitSha:
|
|
140
|
-
deploymentTarget:
|
|
165
|
+
commitSha: commitSha ?? null,
|
|
166
|
+
deploymentTarget: deploymentTarget ?? null,
|
|
141
167
|
projectId,
|
|
142
168
|
...subscribable ? { subscribable } : void 0
|
|
143
169
|
};
|
|
@@ -152,50 +178,49 @@ function createVercelDeploymentTool(ctx) {
|
|
|
152
178
|
// src/webhooks/events.ts
|
|
153
179
|
import { z as z3 } from "zod";
|
|
154
180
|
var deploymentIdSchema = z3.string().regex(/^dpl_[A-Za-z0-9]+$/);
|
|
155
|
-
var commitShaSchema2 = z3.string().regex(/^[0-9a-f]{40}$/i);
|
|
181
|
+
var commitShaSchema2 = z3.string().regex(/^[0-9a-f]{40}$/i).transform((sha) => sha.toLowerCase());
|
|
182
|
+
var deploymentTargetSchema = z3.string().nullable().transform((target) => target ?? "preview").pipe(z3.enum(VERCEL_DEPLOYMENT_TARGETS));
|
|
183
|
+
var metaCommitShaSchema = commitShaSchema2.optional().catch(void 0);
|
|
184
|
+
var deploymentMetaSchema = z3.object({
|
|
185
|
+
githubCommitSha: metaCommitShaSchema,
|
|
186
|
+
gitlabCommitSha: metaCommitShaSchema,
|
|
187
|
+
bitbucketCommitSha: metaCommitShaSchema,
|
|
188
|
+
gitCommitSha: metaCommitShaSchema
|
|
189
|
+
}).transform((meta) => ({
|
|
190
|
+
commitSha: meta.githubCommitSha ?? meta.gitlabCommitSha ?? meta.bitbucketCommitSha ?? meta.gitCommitSha
|
|
191
|
+
}));
|
|
156
192
|
var webhookEnvelopeSchema = z3.object({
|
|
157
193
|
createdAt: z3.number().finite(),
|
|
158
194
|
id: z3.string().min(1),
|
|
159
195
|
payload: z3.unknown(),
|
|
160
|
-
type: z3.
|
|
196
|
+
type: z3.enum(VERCEL_DEPLOYMENT_EVENTS)
|
|
161
197
|
});
|
|
162
198
|
var deploymentPayloadSchema = z3.object({
|
|
163
199
|
deployment: z3.object({
|
|
164
200
|
id: deploymentIdSchema,
|
|
165
|
-
meta:
|
|
201
|
+
meta: deploymentMetaSchema
|
|
166
202
|
}),
|
|
167
203
|
project: z3.object({
|
|
168
204
|
id: vercelProjectIdSchema
|
|
169
205
|
}),
|
|
170
|
-
target:
|
|
206
|
+
target: deploymentTargetSchema
|
|
171
207
|
}).transform((payload) => ({
|
|
172
|
-
commitSha:
|
|
208
|
+
commitSha: payload.deployment.meta.commitSha,
|
|
173
209
|
deploymentId: payload.deployment.id,
|
|
174
210
|
projectId: payload.project.id,
|
|
175
|
-
target:
|
|
211
|
+
target: payload.target
|
|
176
212
|
}));
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
]) {
|
|
189
|
-
const parsed = commitShaSchema2.safeParse(meta[key]);
|
|
190
|
-
if (parsed.success) return parsed.data.toLowerCase();
|
|
191
|
-
}
|
|
192
|
-
return void 0;
|
|
193
|
-
}
|
|
194
|
-
function isDeploymentEvent(value) {
|
|
195
|
-
return VERCEL_DEPLOYMENT_EVENTS.includes(
|
|
196
|
-
value
|
|
197
|
-
);
|
|
198
|
-
}
|
|
213
|
+
var deploymentEventDataSchema = z3.object({
|
|
214
|
+
projectId: vercelProjectIdSchema,
|
|
215
|
+
deploymentId: deploymentIdSchema,
|
|
216
|
+
target: z3.enum(VERCEL_DEPLOYMENT_TARGETS),
|
|
217
|
+
commitSha: commitShaSchema2.optional()
|
|
218
|
+
}).strict();
|
|
219
|
+
var DEPLOYMENT_OUTCOMES = {
|
|
220
|
+
"deployment.succeeded": "succeeded",
|
|
221
|
+
"deployment.error": "failed",
|
|
222
|
+
"deployment.canceled": "was canceled"
|
|
223
|
+
};
|
|
199
224
|
function deploymentTargets(input) {
|
|
200
225
|
const targets = [
|
|
201
226
|
{
|
|
@@ -226,33 +251,29 @@ function deploymentTargets(input) {
|
|
|
226
251
|
}
|
|
227
252
|
function normalizeVercelEvents(args) {
|
|
228
253
|
const envelope = webhookEnvelopeSchema.safeParse(args.body);
|
|
229
|
-
if (!envelope.success
|
|
254
|
+
if (!envelope.success) return [];
|
|
230
255
|
const payload = deploymentPayloadSchema.safeParse(envelope.data.payload);
|
|
231
256
|
if (!payload.success) return [];
|
|
232
|
-
const target = payload.data.target;
|
|
233
|
-
if (!target) return [];
|
|
234
257
|
const eventType = envelope.data.type;
|
|
235
|
-
const deploymentId = payload.data
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
untrustedText
|
|
255
|
-
}));
|
|
258
|
+
const { commitSha, deploymentId, projectId, target } = payload.data;
|
|
259
|
+
const data = deploymentEventDataSchema.parse({
|
|
260
|
+
projectId,
|
|
261
|
+
deploymentId,
|
|
262
|
+
target,
|
|
263
|
+
...commitSha ? { commitSha } : void 0
|
|
264
|
+
});
|
|
265
|
+
return deploymentTargets({ commitSha, projectId, target }).map(
|
|
266
|
+
({ completeOnTerminalEvent, resource }) => ({
|
|
267
|
+
data,
|
|
268
|
+
eventKey: `vercel:${envelope.data.id}:${eventType}`,
|
|
269
|
+
eventType,
|
|
270
|
+
identifier: resource.identifier,
|
|
271
|
+
objectType: "deployment",
|
|
272
|
+
occurredAtMs: envelope.data.createdAt,
|
|
273
|
+
...completeOnTerminalEvent ? { terminal: true } : void 0,
|
|
274
|
+
trustedSummary: `${resource.label} (${deploymentId}) ${DEPLOYMENT_OUTCOMES[eventType]}.`
|
|
275
|
+
})
|
|
276
|
+
);
|
|
256
277
|
}
|
|
257
278
|
|
|
258
279
|
// src/webhooks/handler.ts
|
|
@@ -288,7 +309,7 @@ function createVercelWebhookRoute(args) {
|
|
|
288
309
|
}
|
|
289
310
|
const events = normalizeVercelEvents({ body });
|
|
290
311
|
for (const event of events) {
|
|
291
|
-
await args.events.publish(
|
|
312
|
+
await args.events.publish(event);
|
|
292
313
|
}
|
|
293
314
|
return new Response(events.length ? "Accepted" : "Ignored", {
|
|
294
315
|
status: 202
|
|
@@ -300,7 +321,7 @@ function createVercelWebhookRoute(args) {
|
|
|
300
321
|
export {
|
|
301
322
|
VERCEL_DEPLOYMENT_EVENTS,
|
|
302
323
|
VERCEL_DEPLOYMENT_SUGGESTED_EVENTS,
|
|
303
|
-
|
|
324
|
+
VERCEL_DEPLOYMENT_MATCH_FIELDS,
|
|
304
325
|
createVercelDeploymentTool,
|
|
305
326
|
normalizeVercelEvents,
|
|
306
327
|
createVercelWebhookRoute
|
|
@@ -1,17 +1,36 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type SubscribableResource } from "@sentry/junior-plugin-api";
|
|
2
2
|
export declare const VERCEL_DEPLOYMENT_EVENTS: readonly ["deployment.succeeded", "deployment.error", "deployment.canceled"];
|
|
3
3
|
export declare const VERCEL_DEPLOYMENT_SUGGESTED_EVENTS: string[];
|
|
4
|
-
|
|
4
|
+
/** The deployment targets that Vercel webhooks report. */
|
|
5
|
+
export declare const VERCEL_DEPLOYMENT_TARGETS: readonly ["preview", "production", "staging"];
|
|
6
|
+
export type VercelDeploymentTarget = (typeof VERCEL_DEPLOYMENT_TARGETS)[number];
|
|
7
|
+
/**
|
|
8
|
+
* Trusted values that every Vercel deployment event sets. `commitSha` is left
|
|
9
|
+
* out when the deployment has no Git commit, so a filter on it does not match.
|
|
10
|
+
* Vercel ids keep the case that Vercel sends, the same as identifiers,
|
|
11
|
+
* because they are case-sensitive.
|
|
12
|
+
*/
|
|
13
|
+
export declare const VERCEL_DEPLOYMENT_MATCH_FIELDS: Record<string, {
|
|
14
|
+
kind: "boolean" | "number" | "string";
|
|
15
|
+
description: string;
|
|
16
|
+
enum?: string[] | undefined;
|
|
17
|
+
list?: true | undefined;
|
|
18
|
+
events?: string[] | undefined;
|
|
19
|
+
}>;
|
|
5
20
|
/** Build the stable deployment identity shared by tools and webhooks. */
|
|
6
21
|
export declare function vercelDeploymentResource(input: {
|
|
7
22
|
commitSha?: string;
|
|
8
23
|
projectId: string;
|
|
9
24
|
target?: VercelDeploymentTarget;
|
|
10
25
|
}): Pick<SubscribableResource, "label" | "namespace" | "identifier">;
|
|
11
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Describe a deployment resource that a conversation can watch.
|
|
28
|
+
* Return undefined when the host cannot create Watches.
|
|
29
|
+
*/
|
|
12
30
|
export declare function vercelDeploymentSubscribable(input: {
|
|
31
|
+
/** `ctx.events.canSubscribe` from the tool context. */
|
|
32
|
+
canSubscribe: boolean;
|
|
13
33
|
commitSha?: string;
|
|
14
34
|
projectId: string;
|
|
15
35
|
target?: VercelDeploymentTarget;
|
|
16
|
-
webhookSecret?: string;
|
|
17
36
|
}): SubscribableResource | undefined;
|
package/dist/index.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
VERCEL_DEPLOYMENT_EVENTS,
|
|
3
|
+
VERCEL_DEPLOYMENT_MATCH_FIELDS,
|
|
3
4
|
VERCEL_DEPLOYMENT_SUGGESTED_EVENTS,
|
|
4
5
|
createVercelDeploymentTool,
|
|
5
|
-
createVercelWebhookRoute
|
|
6
|
-
|
|
7
|
-
} from "./chunk-VXKYUJID.js";
|
|
6
|
+
createVercelWebhookRoute
|
|
7
|
+
} from "./chunk-CUJQR3FA.js";
|
|
8
8
|
|
|
9
9
|
// src/index.ts
|
|
10
10
|
import {
|
|
@@ -289,6 +289,11 @@ function createVercelActionTools(ctx) {
|
|
|
289
289
|
};
|
|
290
290
|
}
|
|
291
291
|
|
|
292
|
+
// src/webhooks/secret.ts
|
|
293
|
+
function vercelWebhookSecret() {
|
|
294
|
+
return process.env.VERCEL_WEBHOOK_SECRET?.trim() || void 0;
|
|
295
|
+
}
|
|
296
|
+
|
|
292
297
|
// src/index.ts
|
|
293
298
|
function vercelPlugin() {
|
|
294
299
|
return defineJuniorPlugin({
|
|
@@ -298,7 +303,8 @@ function vercelPlugin() {
|
|
|
298
303
|
{
|
|
299
304
|
type: "deployment",
|
|
300
305
|
supportedEvents: [...VERCEL_DEPLOYMENT_EVENTS],
|
|
301
|
-
suggestedEvents: [...VERCEL_DEPLOYMENT_SUGGESTED_EVENTS]
|
|
306
|
+
suggestedEvents: [...VERCEL_DEPLOYMENT_SUGGESTED_EVENTS],
|
|
307
|
+
matchFields: VERCEL_DEPLOYMENT_MATCH_FIELDS
|
|
302
308
|
}
|
|
303
309
|
],
|
|
304
310
|
isEnabled: () => Boolean(vercelWebhookSecret())
|
package/dist/testing.js
CHANGED
|
@@ -5,7 +5,10 @@
|
|
|
5
5
|
* and emits canonical events for project, target, and commit watches.
|
|
6
6
|
*/
|
|
7
7
|
import type { EventInput } from "@sentry/junior-plugin-api";
|
|
8
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
* Normalize one verified Vercel delivery into deployment events. Target,
|
|
10
|
+
* commit, and deployment id come from Vercel, so they go in trusted data.
|
|
11
|
+
*/
|
|
9
12
|
export declare function normalizeVercelEvents(args: {
|
|
10
13
|
body: unknown;
|
|
11
14
|
}): EventInput[];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
/** Read the normalized secret shared by
|
|
1
|
+
/** Read the normalized secret shared by plugin enablement and webhook ingress. */
|
|
2
2
|
export declare function vercelWebhookSecret(): string | undefined;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentry/junior-vercel",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.266.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
],
|
|
28
28
|
"dependencies": {
|
|
29
29
|
"zod": "^4.5.4",
|
|
30
|
-
"@sentry/junior-plugin-api": "0.
|
|
30
|
+
"@sentry/junior-plugin-api": "0.266.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@oxlint/plugins": "1.79.0",
|
|
@@ -35,7 +35,8 @@
|
|
|
35
35
|
"oxlint": "^1.79.0",
|
|
36
36
|
"tsup": "^8.5.1",
|
|
37
37
|
"typescript": "^7.0.2",
|
|
38
|
-
"vitest": "^4.1.12"
|
|
38
|
+
"vitest": "^4.1.12",
|
|
39
|
+
"@sentry/junior-testing": "0.0.0"
|
|
39
40
|
},
|
|
40
41
|
"scripts": {
|
|
41
42
|
"build": "tsup && tsc -p tsconfig.build.json --emitDeclarationOnly",
|