Added GitHub Pull Request webhook support

This commit is contained in:
Matt Aitken
2023-01-19 09:46:13 -08:00
parent f9eabe3dfb
commit ef3ce5dbc2
6 changed files with 487 additions and 5 deletions
+3 -3
View File
@@ -18,12 +18,12 @@ new Trigger({
}).listen();
new Trigger({
id: "github-webhook-issue_comment",
name: "GitHub issue comment: triggerdotdev/trigger.dev-examples",
id: "github-webhook-pull_request",
name: "GitHub PR: triggerdotdev/trigger.dev-examples",
apiKey: "trigger_dev_zC25mKNn6c0q",
endpoint: "ws://localhost:8889/ws",
logLevel: "debug",
on: github.events.issueCommentEvent({
on: github.events.pullRequestEvent({
repo: "triggerdotdev/trigger.dev-examples",
}),
run: async (event, ctx) => {
@@ -56,3 +56,31 @@ export function issueCommentEvent(params: {
schema: github.schemas.issuesComments.issueCommentEventSchema,
};
}
export function pullRequestEvent(params: {
repo: string;
}): TriggerEvent<typeof github.schemas.pullRequest.pullRequestEventSchema> {
return {
metadata: {
type: "WEBHOOK",
service: "github",
name: "pull_request",
filter: {
service: ["github"],
payload: {
repository: {
full_name: [params.repo],
},
},
event: ["pull_request"],
},
source: github.schemas.WebhookSourceSchema.parse({
subresource: "repository",
scopes: ["repo"],
repo: params.repo,
events: ["pull_request"],
}),
},
schema: github.schemas.pullRequest.pullRequestEventSchema,
};
}
@@ -1,6 +1,7 @@
import { z } from "zod";
import * as issues from "./issues";
import * as issuesComments from "./issueComments";
import * as pullRequest from "./pullRequests";
export const WebhookRepoSourceSchema = z.object({
subresource: z.literal("repository"),
@@ -21,4 +22,4 @@ export const WebhookSourceSchema = z.union([
WebhookOrganizationSourceSchema,
]);
export { issues, issuesComments };
export { issues, issuesComments, pullRequest };
@@ -84,7 +84,7 @@ export const issueCommentEditedEventSchema = z.object({
organization: organizationSchema.optional(),
});
export const issueCommentEventSchema = z.union([
export const issueCommentEventSchema = z.discriminatedUnion("action", [
issueCommentCreatedEventSchema,
issueCommentDeletedEventSchema,
issueCommentEditedEventSchema,
@@ -0,0 +1,411 @@
import { z } from "zod";
import {
authorAssociationSchema,
installationLiteSchema,
labelSchema,
linkSchema,
milestoneSchema,
organizationSchema,
repositorySchema,
teamSchema,
userSchema,
} from "./shared";
export const pullRequestAutoMergeSchema = z.object({
enabled_by: userSchema,
merge_method: z.union([
z.literal("merge"),
z.literal("squash"),
z.literal("rebase"),
]),
commit_title: z.string(),
commit_message: z.string(),
});
export const pullRequestSchema = z.object({
url: z.string(),
id: z.number(),
node_id: z.string(),
html_url: z.string(),
diff_url: z.string(),
patch_url: z.string(),
issue_url: z.string(),
number: z.number(),
state: z.union([z.literal("open"), z.literal("closed")]),
locked: z.boolean(),
title: z.string(),
user: userSchema,
body: z.string().nullable(),
created_at: z.string(),
updated_at: z.string(),
closed_at: z.string().nullable(),
merged_at: z.string().nullable(),
merge_commit_sha: z.string().nullable(),
assignee: userSchema.nullable(),
assignees: z.array(userSchema),
requested_reviewers: z.array(z.union([userSchema, teamSchema])),
requested_teams: z.array(teamSchema),
labels: z.array(labelSchema),
milestone: milestoneSchema.nullable(),
commits_url: z.string(),
review_comments_url: z.string(),
review_comment_url: z.string(),
comments_url: z.string(),
statuses_url: z.string(),
head: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
base: z.object({
label: z.string(),
ref: z.string(),
sha: z.string(),
user: userSchema,
repo: repositorySchema,
}),
_links: z.object({
self: linkSchema,
html: linkSchema,
issue: linkSchema,
comments: linkSchema,
review_comments: linkSchema,
review_comment: linkSchema,
commits: linkSchema,
statuses: linkSchema,
}),
author_association: authorAssociationSchema,
auto_merge: pullRequestAutoMergeSchema.nullable(),
active_lock_reason: z
.union([
z.literal("resolved"),
z.literal("off-topic"),
z.literal("too heated"),
z.literal("spam"),
])
.nullable(),
draft: z.boolean(),
merged: z.boolean().nullable(),
mergeable: z.boolean().nullable(),
rebaseable: z.boolean().nullable(),
mergeable_state: z.string(),
merged_by: userSchema.nullable(),
comments: z.number(),
review_comments: z.number(),
maintainer_can_modify: z.boolean(),
commits: z.number(),
additions: z.number(),
deletions: z.number(),
changed_files: z.number(),
});
export const pullRequestAssignedEventSchema = z.object({
action: z.literal("assigned"),
number: z.number(),
pull_request: pullRequestSchema,
assignee: userSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestAutoMergeDisabledEventSchema = z.object({
action: z.literal("auto_merge_disabled"),
number: z.number(),
pull_request: pullRequestSchema,
reason: z.string(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestAutoMergeEnabledEventSchema = z.object({
action: z.literal("auto_merge_enabled"),
number: z.number(),
pull_request: pullRequestSchema,
reason: z.string(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestClosedEventSchema = z.object({
action: z.literal("closed"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("closed"),
closed_at: z.string(),
merged: z.boolean(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestConvertedToDraftEventSchema = z.object({
action: z.literal("converted_to_draft"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
closed_at: z.null(),
merged_at: z.null(),
draft: z.literal(true),
merged: z.literal(false),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestDequeuedEventSchema = z.object({
action: z.literal("dequeued"),
number: z.number(),
reason: z.string(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestEditedEventSchema = z.object({
action: z.literal("edited"),
number: z.number(),
changes: z.object({
body: z
.object({
from: z.string(),
})
.optional(),
title: z
.object({
from: z.string(),
})
.optional(),
base: z
.object({
ref: z.object({
from: z.string(),
}),
sha: z.object({
from: z.string(),
}),
})
.optional(),
}),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestLabeledEventSchema = z.object({
action: z.literal("labeled"),
number: z.number(),
pull_request: pullRequestSchema,
label: labelSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestLockedEventSchema = z.object({
action: z.literal("locked"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestOpenedEventSchema = z.object({
action: z.literal("opened"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
active_lock_reason: z.null(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestQueuedEventSchema = z.object({
action: z.literal("queued"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReadyForReviewEventSchema = z.object({
action: z.literal("ready_for_review"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
draft: z.literal(false),
merged: z.boolean(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReopenedEventSchema = z.object({
action: z.literal("reopened"),
number: z.number(),
pull_request: pullRequestSchema.and(
z.object({
state: z.literal("open"),
closed_at: z.null(),
merged_at: z.null(),
merged: z.boolean(),
merged_by: z.null(),
})
),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestSynchronizeEventSchema = z.object({
action: z.literal("synchronize"),
number: z.number(),
before: z.string(),
after: z.string(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnassignedEventSchema = z.object({
action: z.literal("unassigned"),
number: z.number(),
pull_request: pullRequestSchema,
assignee: userSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnlabeledEventSchema = z.object({
action: z.literal("unlabeled"),
number: z.number(),
pull_request: pullRequestSchema,
label: labelSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestUnlockedEventSchema = z.object({
action: z.literal("unlocked"),
number: z.number(),
pull_request: pullRequestSchema,
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewRequestRemovedEventSchema = z.object({
action: z.literal("review_request_removed"),
number: z.number(),
pull_request: pullRequestSchema,
requested_reviewer: userSchema.optional(),
requested_team: teamSchema.optional(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestReviewRequestedEventSchema = z.object({
action: z.literal("review_requested"),
number: z.number(),
pull_request: pullRequestSchema,
requested_reviewer: userSchema.optional(),
requested_team: teamSchema.optional(),
repository: repositorySchema,
installation: installationLiteSchema.optional(),
organization: organizationSchema.optional(),
sender: userSchema,
});
export const pullRequestEventSchema: z.ZodDiscriminatedUnion<
"action",
[
typeof pullRequestAssignedEventSchema,
typeof pullRequestAutoMergeDisabledEventSchema,
typeof pullRequestAutoMergeEnabledEventSchema,
typeof pullRequestClosedEventSchema,
typeof pullRequestConvertedToDraftEventSchema,
typeof pullRequestDequeuedEventSchema,
typeof pullRequestEditedEventSchema,
typeof pullRequestLabeledEventSchema,
typeof pullRequestLockedEventSchema,
typeof pullRequestOpenedEventSchema,
typeof pullRequestQueuedEventSchema,
typeof pullRequestReadyForReviewEventSchema,
typeof pullRequestReopenedEventSchema,
typeof pullRequestReviewRequestRemovedEventSchema,
typeof pullRequestReviewRequestedEventSchema,
typeof pullRequestSynchronizeEventSchema,
typeof pullRequestUnassignedEventSchema,
typeof pullRequestUnlabeledEventSchema,
typeof pullRequestUnlockedEventSchema
]
> = z.discriminatedUnion("action", [
pullRequestAssignedEventSchema,
pullRequestAutoMergeDisabledEventSchema,
pullRequestAutoMergeEnabledEventSchema,
pullRequestClosedEventSchema,
pullRequestConvertedToDraftEventSchema,
pullRequestDequeuedEventSchema,
pullRequestEditedEventSchema,
pullRequestLabeledEventSchema,
pullRequestLockedEventSchema,
pullRequestOpenedEventSchema,
pullRequestQueuedEventSchema,
pullRequestReadyForReviewEventSchema,
pullRequestReopenedEventSchema,
pullRequestReviewRequestRemovedEventSchema,
pullRequestReviewRequestedEventSchema,
pullRequestSynchronizeEventSchema,
pullRequestUnassignedEventSchema,
pullRequestUnlabeledEventSchema,
pullRequestUnlockedEventSchema,
]);
@@ -165,6 +165,48 @@ export const repositorySchema = z.object({
organization: z.string().optional(),
});
export const teamSchema = z.object({
name: z.string(),
id: z.number(),
node_id: z.string(),
slug: z.string(),
description: z.string().nullable(),
privacy: z.union([
z.literal("open"),
z.literal("closed"),
z.literal("secret"),
]),
url: z.string(),
html_url: z.string(),
members_url: z.string(),
repositories_url: z.string(),
permission: z.string(),
parent: z
.object({
name: z.string(),
id: z.number(),
node_id: z.string(),
slug: z.string(),
description: z.string().nullable(),
privacy: z.union([
z.literal("open"),
z.literal("closed"),
z.literal("secret"),
]),
url: z.string(),
html_url: z.string(),
members_url: z.string(),
repositories_url: z.string(),
permission: z.string(),
})
.optional()
.nullable(),
});
export const linkSchema = z.object({
href: z.string(),
});
export const appSchema = z.object({
id: z.number(),
slug: z.string().optional(),