flagon-io/g1t

public

Where people and agents ship software together. The open-source git platform for the whole job: issues, agents, checks and deploys to the edge.

g1t/packages/contracts/src/events.ts

124 lines5,195 bytesCodeBlame
1/**
2 * Every state change in g1t is published as an event. Services react to
3 * each other through events rather than direct calls, and the same stream
4 * feeds timelines, webhooks and workflows.
5 *
6 * The envelope follows CloudEvents: `type` says what happened, `subject`
7 * says to what, `data` is the type-specific payload.
8 */
9
10import type { Verdict } from "./work";
11export type EventPayloads = {
12 "repo.created": { repoId: string; namespace: string; name: string; isPrivate: boolean };
13 "repo.forked": { repoId: string; sourceRepoId: string; pullId: string };
14 /**
15 * One branch moved by a push. `ref` is the full ref, `after` the commit it
16 * points to now, and `defaultBranch` whether it is the default branch.
17 */
18 "git.push": { repoId: string; ref: string; after: string; defaultBranch: boolean };
19 "issue.opened": { issueId: string; repoId: string; number: number; title: string };
20 "issue.updated": { issueId: string; repoId: string; number: number };
21 /** The people an issue is assigned to changed; `assignees` is the new set. */
22 "issue.assigned": { issueId: string; repoId: string; number: number; assignees: string[] };
23 /** `resolvedBy` is the number of the pull request whose merge closed it. */
24 "issue.closed": {
25 issueId: string;
26 repoId: string;
27 number: number;
28 reason: "completed" | "not_planned";
29 resolvedBy?: number;
30 };
31 "issue.reopened": { issueId: string; repoId: string; number: number };
32 /** `issue` is the number of the issue the pull request is for. */
33 "pull.opened": { pullId: string; repoId: string; number: number; issue?: number; agent: string };
34 "pull.ready": { pullId: string; repoId: string; number: number; issue?: number };
35 /** A push moved the head of a pull request that is ready for review. */
36 "pull.updated": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
37 /** A merge was asked for while the pull request was behind; it has to catch up first. */
38 "pull.merge_requested": { pullId: string; repoId: string; number: number; issue?: number };
39 "pull.closed": { pullId: string; repoId: string; number: number; issue?: number };
40 /**
41 * The pull request's head or its target moved and the files both changed
42 * overlap: a sandbox should find out whether it still merges cleanly.
43 * `commit` is its head.
44 */
45 "pull.mergecheck": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
46 /** Whether the pull request merges cleanly was settled. */
47 "pull.mergeability": { pullId: string; repoId: string; number: number; issue?: number };
48 /** Another agent asked the agent on a pull request, which was not at work, a question or handed it work. */
49 "agent.asked": { pullId: string; repoId: string; number: number; issue?: number };
50 "pull.merged": { pullId: string; repoId: string; number: number; issue?: number; commit: string };
51 /** A run of the acceptance checks finished. `commit` is what was checked. */
52 "checks.completed": {
53 pullId: string;
54 repoId: string;
55 number: number;
56 status: "passed" | "failed" | "errored";
57 commit: string;
58 };
59 /** A g1t agent finished reviewing a pull request; no verdict if it could not. */
60 "review.completed": {
61 pullId: string;
62 repoId: string;
63 number: number;
64 verdict?: "approve" | "request_changes";
65 };
66 /** A repository's merge queue gained, lost or settled an entry. */
67 "queue.changed": { repoId: string };
68 /** `number` is the issue or pull request commented on. */
69 "comment.created": {
70 commentId: string;
71 repoId: string;
72 number: number;
73 /** Set when the comment is on a pull request. */
74 pullId?: string;
75 /** Set when the comment is a review. */
76 verdict?: Verdict;
77 };
78 "session.appended": { pullId: string; repoId: string; number: number; count: number };
79 /**
80 * A workspace's slug changed from `from` to `to`. Services that store a
81 * slug move their rows to the workspace's *current* slug (see
82 * `currentWorkspaceSlug`), so a repeated or late delivery after a second
83 * rename still lands in the right place.
84 */
85 "workspace.renamed": { workspaceId: string; from: string; to: string };
86};
87
88export type EventType = keyof EventPayloads;
89
90export type G1tEvent<T extends EventType = EventType> = {
91 [K in T]: {
92 id: string;
93 type: K;
94 /** The service that published it. */
95 source: string;
96 /** RFC 3339. */
97 time: string;
98 /** The repo the event concerns, used to scope timelines and deliveries. */
99 repoId: string | null;
100 /** The user or agent that caused it, if any. */
101 actor: string | null;
102 data: EventPayloads[K];
103 };
104}[T];
105
106/** What a publisher supplies; the bus fills in `id` and `time`. */
107export type NewEvent<T extends EventType = EventType> = {
108 [K in T]: Omit<G1tEvent<K>, "id" | "time">;
109}[T];
110
111export type EventQuery = {
112 repoId?: string;
113 types?: EventType[];
114 /** Return events older than this event id. */
115 before?: string;
116 limit?: number;
117};
118
119/** The event bus and its durable log. */
120export interface EventsApi {
121 publish(events: NewEvent[]): Promise<void>;
122 /** Newest first. */
123 list(query: EventQuery): Promise<G1tEvent[]>;
124}