Skip to content

g1t/packages/contracts/src/webhooks.ts

142 lines3,999 bytesCodeBlame
1import type { User, Viewer } from "./identity";
2import type { RepoPath } from "./repos";
3import type { Result } from "./result";
4
5/**
6 * Events, delivered to the addresses a repository or a workspace registers.
7 * Mirrors `crates/contracts/src/webhooks.rs`.
8 */
9
10/** Every event a webhook can be sent, in the order people are shown them. */
11export const EVENT_TYPES = [
12 "git.push",
13 "branch.renamed",
14 "repo.created",
15 "repo.forked",
16 "repo.updated",
17 "repo.visibility_changed",
18 "repo.renamed",
19 "repo.transferred",
20 "repo.default_branch_changed",
21 "repo.archived",
22 "repo.unarchived",
23 "repo.deleted",
24 "repo.restored",
25 "repo.purged",
26 "repo.collaborator_added",
27 "repo.collaborator_removed",
28 "repo.collaborator_role_changed",
29 "team.created",
30 "team.edited",
31 "team.deleted",
32 "team.member_added",
33 "team.member_role_changed",
34 "team.member_removed",
35 "team.repo_added",
36 "team.repo_role_changed",
37 "team.repo_removed",
38 "issue.opened",
39 "issue.updated",
40 "issue.assigned",
41 "issue.labeled",
42 "issue.unlabeled",
43 "issue.milestoned",
44 "issue.demilestoned",
45 "issue.closed",
46 "issue.reopened",
47 "comment.created",
48 "pull.opened",
49 "pull.ready",
50 "pull.updated",
51 "pull.merge_requested",
52 "pull.merged",
53 "pull.closed",
54 "pull.assigned",
55 "pull.review_requested",
56 "pull.review_request_removed",
57 "pull.labeled",
58 "pull.unlabeled",
59 "pull.milestoned",
60 "pull.demilestoned",
61 "pull.base_changed",
62 "pull.stalled",
63 "pull.resumed",
64 "agent.asked",
65 "checks.completed",
66 "review.completed",
67 "workflow.completed",
68 "deployment.succeeded",
69 "deployment.failed",
70 "queue.changed",
71 "session.appended",
72 "package.published",
73 "package.version_deleted",
74 "package.deleted",
75 "package.visibility_changed",
76 "secret_scanning_alert.created",
77 "secret_scanning_alert.fixed",
78 "secret_scanning_alert.dismissed",
79 "secret_scanning_alert.reopened",
80 "secret_scanning.bypass_requested",
81 "secret_scanning.bypass_reviewed",
82 "code_scanning_alert.created",
83 "code_scanning_alert.fixed",
84 "code_scanning_alert.dismissed",
85 "code_scanning_alert.reopened",
86 "vulnerability_alert.created",
87 "vulnerability_alert.fixed",
88 "vulnerability_alert.dismissed",
89 "vulnerability_alert.reopened",
90] as const;
91
92export type Hook = {
93 id: string;
94 scope: "repo" | "workspace";
95 workspace: string;
96 /** For a repository's webhook: `owner/name`. */
97 repo: string | null;
98 url: string;
99 /** Event types, or `["*"]` for all. */
100 events: string[];
101 active: boolean;
102 secretHint: string;
103 createdBy: string;
104 createdAt: string;
105 lastStatus: "delivered" | "pending" | "failed" | null;
106 lastDeliveredAt: string | null;
107};
108
109export type HookDelivery = {
110 id: string;
111 hookId: string;
112 eventId: string;
113 event: string;
114 status: "pending" | "delivered" | "failed";
115 attempts: number;
116 responseStatus: number | null;
117 responseBody: string | null;
118 error: string | null;
119 durationMs: number | null;
120 /** The JSON that was sent. */
121 payload: string;
122 createdAt: string;
123 deliveredAt: string | null;
124 nextAttemptAt: string | null;
125};
126
127/** A repository's webhooks, or with `repo` left out, the workspace's own. */
128export type HookOwner = { workspace: string; repo?: RepoPath };
129
130export interface WebhooksApi {
131 list(viewer: Viewer, owner: HookOwner): Promise<Result<Hook[]>>;
132 create(
133 actor: User,
134 owner: HookOwner,
135 input: { url: string; events?: string[]; secret?: string },
136 ): Promise<Result<{ hook: Hook; secret: string | null }>>;
137 update(actor: User, owner: HookOwner, id: string, input: { url?: string; events?: string[]; active?: boolean }): Promise<Result<Hook>>;
138 delete(actor: User, owner: HookOwner, id: string): Promise<Result<boolean>>;
139 ping(actor: User, owner: HookOwner, id: string): Promise<Result<HookDelivery>>;
140 deliveries(viewer: Viewer, owner: HookOwner, id: string): Promise<Result<HookDelivery[]>>;
141 redeliver(actor: User, owner: HookOwner, deliveryId: string): Promise<Result<HookDelivery>>;
142}