@pepys/source-github 0.0.1 → 0.1.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.
Files changed (51) hide show
  1. package/package.json +8 -5
  2. package/src/api/serve-api.ts +6 -35
  3. package/src/consumers/github-deploy.ts +199 -0
  4. package/src/consumers/github-pull-request.ts +96 -1
  5. package/src/consumers/github-ref.ts +88 -0
  6. package/src/consumers/github-release.ts +125 -0
  7. package/src/families/build-family-types.ts +16 -0
  8. package/src/families/deployment-family.ts +15 -0
  9. package/src/families/issue-family.ts +38 -0
  10. package/src/{pull-request-family.ts → families/pull-request-family.ts} +6 -5
  11. package/src/families/pull-request-review-family.ts +18 -0
  12. package/src/families/ref-family.ts +14 -0
  13. package/src/families/release-family.ts +28 -0
  14. package/src/families/workflow-run-family.ts +18 -0
  15. package/src/generated/github-deploy-boundary.ts +308 -0
  16. package/src/generated/github-deploy.sql +24 -0
  17. package/src/generated/github-pull-request-boundary.ts +21 -3
  18. package/src/generated/github-pull-request.sql +9 -0
  19. package/src/generated/github-ref-boundary.ts +149 -0
  20. package/src/generated/github-ref.sql +8 -0
  21. package/src/generated/github-release-boundary.ts +251 -0
  22. package/src/generated/github-release.sql +32 -0
  23. package/src/github-deploy-consumer.ts +40 -0
  24. package/src/github-plugin.ts +11 -22
  25. package/src/github-pull-request-consumer.ts +13 -1
  26. package/src/github-ref-consumer.ts +23 -0
  27. package/src/github-release-consumer.ts +43 -0
  28. package/src/github-settings.ts +15 -0
  29. package/src/github-source.ts +56 -0
  30. package/src/index.ts +10 -0
  31. package/src/ingest/build-github-fact.ts +55 -0
  32. package/src/ingest/github-app/build-app-jwt.ts +20 -0
  33. package/src/ingest/github-app/find-app-jwt.ts +17 -0
  34. package/src/ingest/github-app/github-api-url.ts +1 -0
  35. package/src/ingest/github-app/pick-pull-failure.ts +11 -0
  36. package/src/ingest/github-app/read-installation-token.ts +43 -0
  37. package/src/ingest/github-app/request-github-api.ts +75 -0
  38. package/src/ingest/github-event-rules.ts +324 -0
  39. package/src/ingest/read-github-delivery.ts +41 -0
  40. package/src/ingest/recovery/pull-failed-deliveries.ts +100 -0
  41. package/src/ingest/resync/collect-resync-targets.ts +33 -0
  42. package/src/ingest/resync/pull-marked-objects.ts +130 -0
  43. package/src/queries/github-delivery-consumers.ts +13 -0
  44. package/src/queries/pull-request-delivery-query.ts +49 -0
  45. package/src/queries/select-pull-request-delivery.ts +155 -0
  46. package/src/utils/build-body-hash.ts +34 -0
  47. package/src/utils/deploy-signals.ts +5 -0
  48. package/src/utils/find-field.ts +19 -0
  49. package/src/ingest/build-pull-request-fact.ts +0 -38
  50. package/src/ingest/pull-request-stream.ts +0 -4
  51. package/src/ingest/read-pull-request-delivery.ts +0 -44
@@ -1,7 +1,9 @@
1
1
  import { defineFactFamily } from '@pepys/kit';
2
2
  import { z } from 'zod';
3
+ import { buildFamilyTypes } from './build-family-types.ts';
3
4
 
4
- // The `action` values of GitHub's `pull_request` webhook event.
5
+ // The `action` values of GitHub's `pull_request` webhook event, and `resynced` for a pull request
6
+ // that the resync pull read from the API.
5
7
  const actions = [
6
8
  'assigned',
7
9
  'auto_merge_disabled',
@@ -18,6 +20,7 @@ const actions = [
18
20
  'opened',
19
21
  'ready_for_review',
20
22
  'reopened',
23
+ 'resynced',
21
24
  'review_request_removed',
22
25
  'review_requested',
23
26
  'synchronize',
@@ -26,7 +29,7 @@ const actions = [
26
29
  'unlocked',
27
30
  ] as const;
28
31
 
29
- const deliverySchema = z.looseObject({
32
+ const payloadSchema = z.looseObject({
30
33
  action: z.string(),
31
34
  pull_request: z.looseObject({ id: z.number().int(), updated_at: z.string() }),
32
35
  });
@@ -35,7 +38,5 @@ export const pullRequestFamily = defineFactFamily({
35
38
  stream: 'facts.github.pull_request',
36
39
  api: 'github/2022-11-28',
37
40
  entityKind: 'github:pull_request',
38
- types: Object.fromEntries(
39
- actions.map((action) => [`github.pull_request.${action}`, deliverySchema]),
40
- ),
41
+ types: buildFamilyTypes('pull_request', actions, payloadSchema),
41
42
  });
@@ -0,0 +1,18 @@
1
+ import { defineFactFamily } from '@pepys/kit';
2
+ import { z } from 'zod';
3
+ import { buildFamilyTypes } from './build-family-types.ts';
4
+
5
+ const actions = ['dismissed', 'edited', 'submitted'] as const;
6
+
7
+ const payloadSchema = z.looseObject({
8
+ action: z.string(),
9
+ review: z.looseObject({ id: z.number().int() }),
10
+ });
11
+
12
+ // Stored with no consumer.
13
+ export const pullRequestReviewFamily = defineFactFamily({
14
+ stream: 'facts.github.pull_request_review',
15
+ api: 'github/2022-11-28',
16
+ entityKind: 'github:pull_request_review',
17
+ types: buildFamilyTypes('pull_request_review', actions, payloadSchema),
18
+ });
@@ -0,0 +1,14 @@
1
+ import { defineFactFamily } from '@pepys/kit';
2
+ import { z } from 'zod';
3
+
4
+ const repositorySchema = z.looseObject({ id: z.number().int() });
5
+
6
+ // A push to the default branch or to a tag. The entity is `github:ref:<repository ID>:<ref>`.
7
+ export const refFamily = defineFactFamily({
8
+ stream: 'facts.github.ref',
9
+ api: 'github/2022-11-28',
10
+ entityKind: 'github:ref',
11
+ types: {
12
+ 'github.ref.pushed': z.looseObject({ ref: z.string(), repository: repositorySchema }),
13
+ },
14
+ });
@@ -0,0 +1,28 @@
1
+ import { defineFactFamily } from '@pepys/kit';
2
+ import { z } from 'zod';
3
+ import { buildFamilyTypes } from './build-family-types.ts';
4
+
5
+ // The `action` values of GitHub's `release` webhook event, and `resynced` for a release that the
6
+ // resync pull read from the API.
7
+ const actions = [
8
+ 'created',
9
+ 'deleted',
10
+ 'edited',
11
+ 'prereleased',
12
+ 'published',
13
+ 'released',
14
+ 'resynced',
15
+ 'unpublished',
16
+ ] as const;
17
+
18
+ const payloadSchema = z.looseObject({
19
+ action: z.string(),
20
+ release: z.looseObject({ id: z.number().int() }),
21
+ });
22
+
23
+ export const releaseFamily = defineFactFamily({
24
+ stream: 'facts.github.release',
25
+ api: 'github/2022-11-28',
26
+ entityKind: 'github:release',
27
+ types: buildFamilyTypes('release', actions, payloadSchema),
28
+ });
@@ -0,0 +1,18 @@
1
+ import { defineFactFamily } from '@pepys/kit';
2
+ import { z } from 'zod';
3
+ import { buildFamilyTypes } from './build-family-types.ts';
4
+
5
+ const actions = ['completed', 'in_progress', 'requested'] as const;
6
+
7
+ const payloadSchema = z.looseObject({
8
+ action: z.string(),
9
+ workflow_run: z.looseObject({ id: z.number().int() }),
10
+ });
11
+
12
+ // Stored with no consumer.
13
+ export const workflowRunFamily = defineFactFamily({
14
+ stream: 'facts.github.workflow_run',
15
+ api: 'github/2022-11-28',
16
+ entityKind: 'github:workflow_run',
17
+ types: buildFamilyTypes('workflow_run', actions, payloadSchema),
18
+ });
@@ -0,0 +1,308 @@
1
+ // Generated by `pepys build`. Do not edit.
2
+
3
+ declare const idTag: unique symbol;
4
+ declare const kindTag: unique symbol;
5
+
6
+ export type EntityID = string & { readonly [idTag]: 'EntityID' };
7
+
8
+ type KindedID<Kind extends string> = EntityID & { readonly [kindTag]: Kind };
9
+
10
+ export type GithubDeployID = KindedID<'github:deploy'>;
11
+
12
+ export function toGithubDeployID(id: string): GithubDeployID {
13
+ const text = 'github:deploy:' + id;
14
+
15
+ if (!isGithubDeployID(text)) {
16
+ throw new Error('an ID of the kind github:deploy is never empty');
17
+ }
18
+
19
+ return text;
20
+ }
21
+
22
+ export function parseGithubDeployID(text: string): GithubDeployID | undefined {
23
+ return isGithubDeployID(text) ? text : undefined;
24
+ }
25
+
26
+ function isGithubDeployID(text: string): text is GithubDeployID {
27
+ return text.length > 'github:deploy:'.length && text.startsWith('github:deploy:');
28
+ }
29
+
30
+ export type GithubDeploymentID = KindedID<'github:deployment'>;
31
+
32
+ export function toGithubDeploymentID(id: string): GithubDeploymentID {
33
+ const text = 'github:deployment:' + id;
34
+
35
+ if (!isGithubDeploymentID(text)) {
36
+ throw new Error('an ID of the kind github:deployment is never empty');
37
+ }
38
+
39
+ return text;
40
+ }
41
+
42
+ export function parseGithubDeploymentID(text: string): GithubDeploymentID | undefined {
43
+ return isGithubDeploymentID(text) ? text : undefined;
44
+ }
45
+
46
+ function isGithubDeploymentID(text: string): text is GithubDeploymentID {
47
+ return text.length > 'github:deployment:'.length && text.startsWith('github:deployment:');
48
+ }
49
+
50
+ export type GithubRefID = KindedID<'github:ref'>;
51
+
52
+ export function toGithubRefID(id: string): GithubRefID {
53
+ const text = 'github:ref:' + id;
54
+
55
+ if (!isGithubRefID(text)) {
56
+ throw new Error('an ID of the kind github:ref is never empty');
57
+ }
58
+
59
+ return text;
60
+ }
61
+
62
+ export function parseGithubRefID(text: string): GithubRefID | undefined {
63
+ return isGithubRefID(text) ? text : undefined;
64
+ }
65
+
66
+ function isGithubRefID(text: string): text is GithubRefID {
67
+ return text.length > 'github:ref:'.length && text.startsWith('github:ref:');
68
+ }
69
+
70
+ export const settings = {
71
+ "deployTagPattern": "deployed/<environment>"
72
+ } as const;
73
+
74
+ export interface GithubDeployModel {
75
+ input: string;
76
+ }
77
+
78
+ export type GithubDeployMessage = { kind: 'apply'; input: string } | { kind: 'reset' };
79
+
80
+ export function initGithubDeployModel(): GithubDeployModel {
81
+ return { input: '' };
82
+ }
83
+
84
+ export function updateGithubDeployModel(model: GithubDeployModel, message: GithubDeployMessage): GithubDeployModel {
85
+ return message.kind === 'reset' ? initGithubDeployModel() : { ...model, input: message.input };
86
+ }
87
+
88
+ export interface GithubRefPushedPayload {
89
+ ref: string;
90
+ repository: GithubRefPushedPayloadRepository;
91
+ }
92
+
93
+ export interface GithubRefPushedPayloadRepository {
94
+ id: number;
95
+ }
96
+
97
+ export interface GithubDeploymentPayload {
98
+ deployment: GithubDeploymentPayloadDeployment;
99
+ }
100
+
101
+ export interface GithubDeploymentPayloadDeployment {
102
+ id: number;
103
+ }
104
+
105
+ export type GithubDeployFact =
106
+ | { id: string; type: 'github.ref.pushed'; entity: string; at: string; payload: GithubRefPushedPayload }
107
+ | { id: string; type: 'github.deployment.created' | 'github.deployment.status_created'; entity: string; at: string; payload: GithubDeploymentPayload };
108
+
109
+ export function parseGithubDeployFact(factJSON: string): GithubDeployFact | undefined {
110
+ const parsed: unknown = JSON.parse(factJSON);
111
+
112
+ return decodeGithubDeployFact(parsed);
113
+ }
114
+
115
+ function decodeGithubDeployFact(value: unknown): GithubDeployFact | undefined {
116
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
117
+ return undefined;
118
+ }
119
+
120
+ const id = 'id' in value ? value.id : undefined;
121
+ const type = 'type' in value ? value.type : undefined;
122
+ const entity = 'entity' in value ? value.entity : undefined;
123
+ const at = 'at' in value ? value.at : undefined;
124
+ const payload = 'payload' in value ? value.payload : undefined;
125
+
126
+ if (typeof id !== 'string' || typeof entity !== 'string' || typeof at !== 'string') {
127
+ return undefined;
128
+ }
129
+
130
+ if (type === 'github.ref.pushed') {
131
+ const decoded = decodeGithubRefPushedPayload(payload);
132
+
133
+ if (decoded === undefined) {
134
+ return undefined;
135
+ }
136
+
137
+ return { id, type, entity, at, payload: decoded };
138
+ }
139
+
140
+ if (type === 'github.deployment.created' || type === 'github.deployment.status_created') {
141
+ const decoded = decodeGithubDeploymentPayload(payload);
142
+
143
+ if (decoded === undefined) {
144
+ return undefined;
145
+ }
146
+
147
+ return { id, type, entity, at, payload: decoded };
148
+ }
149
+
150
+ return undefined;
151
+ }
152
+
153
+ function decodeGithubRefPushedPayload(value: unknown): GithubRefPushedPayload | undefined {
154
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
155
+ return undefined;
156
+ }
157
+
158
+ const raw0 = 'ref' in value ? value.ref : undefined;
159
+ const field0 = typeof raw0 === 'string' ? raw0 : undefined;
160
+
161
+ if (field0 === undefined) {
162
+ return undefined;
163
+ }
164
+
165
+ const raw1 = 'repository' in value ? value.repository : undefined;
166
+ const field1 = decodeGithubRefPushedPayloadRepository(raw1);
167
+
168
+ if (field1 === undefined) {
169
+ return undefined;
170
+ }
171
+
172
+ return {
173
+ ref: field0,
174
+ repository: field1,
175
+ };
176
+ }
177
+
178
+ function decodeGithubRefPushedPayloadRepository(value: unknown): GithubRefPushedPayloadRepository | undefined {
179
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
180
+ return undefined;
181
+ }
182
+
183
+ const raw0 = 'id' in value ? value.id : undefined;
184
+ const field0 = typeof raw0 === 'number' ? raw0 : undefined;
185
+
186
+ if (field0 === undefined) {
187
+ return undefined;
188
+ }
189
+
190
+ return {
191
+ id: field0,
192
+ };
193
+ }
194
+
195
+ function decodeGithubDeploymentPayload(value: unknown): GithubDeploymentPayload | undefined {
196
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
197
+ return undefined;
198
+ }
199
+
200
+ const raw0 = 'deployment' in value ? value.deployment : undefined;
201
+ const field0 = decodeGithubDeploymentPayloadDeployment(raw0);
202
+
203
+ if (field0 === undefined) {
204
+ return undefined;
205
+ }
206
+
207
+ return {
208
+ deployment: field0,
209
+ };
210
+ }
211
+
212
+ function decodeGithubDeploymentPayloadDeployment(value: unknown): GithubDeploymentPayloadDeployment | undefined {
213
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
214
+ return undefined;
215
+ }
216
+
217
+ const raw0 = 'id' in value ? value.id : undefined;
218
+ const field0 = typeof raw0 === 'number' ? raw0 : undefined;
219
+
220
+ if (field0 === undefined) {
221
+ return undefined;
222
+ }
223
+
224
+ return {
225
+ id: field0,
226
+ };
227
+ }
228
+
229
+ export interface GithubDeployRow {
230
+ id: GithubDeployID;
231
+ repository_id: EntityID;
232
+ environment: string;
233
+ target: string | null;
234
+ sha: string;
235
+ signal: string;
236
+ deployed_at: string;
237
+ }
238
+
239
+ export interface GithubDeployKey {
240
+ id: GithubDeployID;
241
+ }
242
+
243
+ export type GithubDeployOperation =
244
+ | { upsert: { github_deploy: GithubDeployRow } }
245
+ | { delete: { github_deploy: GithubDeployKey } };
246
+
247
+ declare function readGithubDeployLength(key: string): number;
248
+ declare function readGithubDeployInto(key: string, row: Uint8Array): void;
249
+
250
+ export function readGithubDeployRow(key: string): GithubDeployRow | undefined {
251
+ const length = readGithubDeployLength(key);
252
+
253
+ if (length < 0) {
254
+ return undefined;
255
+ }
256
+
257
+ const row = new Uint8Array(length);
258
+
259
+ readGithubDeployInto(key, row);
260
+
261
+ const parsed: unknown = JSON.parse(new TextDecoder().decode(row));
262
+
263
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
264
+ return undefined;
265
+ }
266
+
267
+ if (!('id' in parsed) || (typeof parsed.id !== 'string' || !isGithubDeployID(parsed.id))) {
268
+ return undefined;
269
+ }
270
+
271
+ if (!('repository_id' in parsed) || (!isEntityID(parsed.repository_id))) {
272
+ return undefined;
273
+ }
274
+
275
+ if (!('environment' in parsed) || (typeof parsed.environment !== 'string')) {
276
+ return undefined;
277
+ }
278
+
279
+ if (!('target' in parsed) || (parsed.target !== null && (typeof parsed.target !== 'string'))) {
280
+ return undefined;
281
+ }
282
+
283
+ if (!('sha' in parsed) || (typeof parsed.sha !== 'string')) {
284
+ return undefined;
285
+ }
286
+
287
+ if (!('signal' in parsed) || (typeof parsed.signal !== 'string')) {
288
+ return undefined;
289
+ }
290
+
291
+ if (!('deployed_at' in parsed) || (typeof parsed.deployed_at !== 'string')) {
292
+ return undefined;
293
+ }
294
+
295
+ return {
296
+ id: parsed.id,
297
+ repository_id: parsed.repository_id,
298
+ environment: parsed.environment,
299
+ target: parsed.target,
300
+ sha: parsed.sha,
301
+ signal: parsed.signal,
302
+ deployed_at: parsed.deployed_at,
303
+ };
304
+ }
305
+
306
+ function isEntityID(value: unknown): value is EntityID {
307
+ return typeof value === 'string';
308
+ }
@@ -0,0 +1,24 @@
1
+ -- Generated by `pepys build`. Do not edit.
2
+
3
+ CREATE TABLE "github_deploy" (
4
+ "id" TEXT NOT NULL,
5
+ "repository_id" TEXT NOT NULL,
6
+ "environment" TEXT NOT NULL,
7
+ "target" TEXT,
8
+ "sha" TEXT NOT NULL,
9
+ "signal" TEXT NOT NULL,
10
+ "deployed_at" TEXT NOT NULL,
11
+ PRIMARY KEY ("id")
12
+ );
13
+
14
+ CREATE INDEX "github_deploy_repository_id_environment_idx" ON "github_deploy" ("repository_id", "environment");
15
+
16
+ CREATE VIEW "entity" AS
17
+ SELECT
18
+ "id" AS "id",
19
+ 'github:deploy' AS "kind",
20
+ "sha" AS "title",
21
+ NULL AS "url",
22
+ NULL AS "actor",
23
+ "deployed_at" AS "updated_at"
24
+ FROM "github_deploy";
@@ -27,6 +27,10 @@ function isGithubPullRequestID(text: string): text is GithubPullRequestID {
27
27
  return text.length > 'github:pull_request:'.length && text.startsWith('github:pull_request:');
28
28
  }
29
29
 
30
+ export const settings = {
31
+ "deployTagPattern": "deployed/<environment>"
32
+ } as const;
33
+
30
34
  export interface GithubPullRequestModel {
31
35
  input: string;
32
36
  }
@@ -52,7 +56,7 @@ export interface GithubPullRequestPayloadPullRequest {
52
56
  }
53
57
 
54
58
  export type GithubPullRequestFact =
55
- | { id: string; type: 'github.pull_request.assigned' | 'github.pull_request.auto_merge_disabled' | 'github.pull_request.auto_merge_enabled' | 'github.pull_request.closed' | 'github.pull_request.converted_to_draft' | 'github.pull_request.demilestoned' | 'github.pull_request.dequeued' | 'github.pull_request.edited' | 'github.pull_request.enqueued' | 'github.pull_request.labeled' | 'github.pull_request.locked' | 'github.pull_request.milestoned' | 'github.pull_request.opened' | 'github.pull_request.ready_for_review' | 'github.pull_request.reopened' | 'github.pull_request.review_request_removed' | 'github.pull_request.review_requested' | 'github.pull_request.synchronize' | 'github.pull_request.unassigned' | 'github.pull_request.unlabeled' | 'github.pull_request.unlocked'; entity: string; at: string; payload: GithubPullRequestPayload };
59
+ | { id: string; type: 'github.pull_request.assigned' | 'github.pull_request.auto_merge_disabled' | 'github.pull_request.auto_merge_enabled' | 'github.pull_request.closed' | 'github.pull_request.converted_to_draft' | 'github.pull_request.demilestoned' | 'github.pull_request.dequeued' | 'github.pull_request.edited' | 'github.pull_request.enqueued' | 'github.pull_request.labeled' | 'github.pull_request.locked' | 'github.pull_request.milestoned' | 'github.pull_request.opened' | 'github.pull_request.ready_for_review' | 'github.pull_request.reopened' | 'github.pull_request.resynced' | 'github.pull_request.review_request_removed' | 'github.pull_request.review_requested' | 'github.pull_request.synchronize' | 'github.pull_request.unassigned' | 'github.pull_request.unlabeled' | 'github.pull_request.unlocked'; entity: string; at: string; payload: GithubPullRequestPayload };
56
60
 
57
61
  export function parseGithubPullRequestFact(factJSON: string): GithubPullRequestFact | undefined {
58
62
  const parsed: unknown = JSON.parse(factJSON);
@@ -75,7 +79,7 @@ function decodeGithubPullRequestFact(value: unknown): GithubPullRequestFact | un
75
79
  return undefined;
76
80
  }
77
81
 
78
- if (type === 'github.pull_request.assigned' || type === 'github.pull_request.auto_merge_disabled' || type === 'github.pull_request.auto_merge_enabled' || type === 'github.pull_request.closed' || type === 'github.pull_request.converted_to_draft' || type === 'github.pull_request.demilestoned' || type === 'github.pull_request.dequeued' || type === 'github.pull_request.edited' || type === 'github.pull_request.enqueued' || type === 'github.pull_request.labeled' || type === 'github.pull_request.locked' || type === 'github.pull_request.milestoned' || type === 'github.pull_request.opened' || type === 'github.pull_request.ready_for_review' || type === 'github.pull_request.reopened' || type === 'github.pull_request.review_request_removed' || type === 'github.pull_request.review_requested' || type === 'github.pull_request.synchronize' || type === 'github.pull_request.unassigned' || type === 'github.pull_request.unlabeled' || type === 'github.pull_request.unlocked') {
82
+ if (type === 'github.pull_request.assigned' || type === 'github.pull_request.auto_merge_disabled' || type === 'github.pull_request.auto_merge_enabled' || type === 'github.pull_request.closed' || type === 'github.pull_request.converted_to_draft' || type === 'github.pull_request.demilestoned' || type === 'github.pull_request.dequeued' || type === 'github.pull_request.edited' || type === 'github.pull_request.enqueued' || type === 'github.pull_request.labeled' || type === 'github.pull_request.locked' || type === 'github.pull_request.milestoned' || type === 'github.pull_request.opened' || type === 'github.pull_request.ready_for_review' || type === 'github.pull_request.reopened' || type === 'github.pull_request.resynced' || type === 'github.pull_request.review_request_removed' || type === 'github.pull_request.review_requested' || type === 'github.pull_request.synchronize' || type === 'github.pull_request.unassigned' || type === 'github.pull_request.unlabeled' || type === 'github.pull_request.unlocked') {
79
83
  const decoded = decodeGithubPullRequestPayload(payload);
80
84
 
81
85
  if (decoded === undefined) {
@@ -156,13 +160,27 @@ export interface GithubPullRequestRow {
156
160
  payload: unknown;
157
161
  }
158
162
 
163
+ export interface GithubReleaseBumpRow {
164
+ pull_request_id: EntityID;
165
+ release_repository: string;
166
+ release_tag: string;
167
+ }
168
+
159
169
  export interface GithubPullRequestKey {
160
170
  id: GithubPullRequestID;
161
171
  }
162
172
 
173
+ export interface GithubReleaseBumpKey {
174
+ pull_request_id: EntityID;
175
+ release_repository: string;
176
+ release_tag: string;
177
+ }
178
+
163
179
  export type GithubPullRequestOperation =
164
180
  | { upsert: { github_pull_request: GithubPullRequestRow } }
165
- | { delete: { github_pull_request: GithubPullRequestKey } };
181
+ | { delete: { github_pull_request: GithubPullRequestKey } }
182
+ | { upsert: { github_release_bump: GithubReleaseBumpRow } }
183
+ | { delete: { github_release_bump: GithubReleaseBumpKey } };
166
184
 
167
185
  declare function readGithubPullRequestLength(key: string): number;
168
186
  declare function readGithubPullRequestInto(key: string, row: Uint8Array): void;
@@ -21,6 +21,15 @@ CREATE TABLE "github_pull_request" (
21
21
 
22
22
  CREATE INDEX "github_pull_request_repository_id_idx" ON "github_pull_request" ("repository_id");
23
23
 
24
+ CREATE TABLE "github_release_bump" (
25
+ "pull_request_id" TEXT NOT NULL,
26
+ "release_repository" TEXT NOT NULL,
27
+ "release_tag" TEXT NOT NULL,
28
+ PRIMARY KEY ("pull_request_id", "release_repository", "release_tag")
29
+ );
30
+
31
+ CREATE INDEX "github_release_bump_release_repository_release_tag_idx" ON "github_release_bump" ("release_repository", "release_tag");
32
+
24
33
  CREATE VIEW "entity" AS
25
34
  SELECT
26
35
  "id" AS "id",
@@ -0,0 +1,149 @@
1
+ // Generated by `pepys build`. Do not edit.
2
+
3
+ declare const idTag: unique symbol;
4
+ declare const kindTag: unique symbol;
5
+
6
+ export type EntityID = string & { readonly [idTag]: 'EntityID' };
7
+
8
+ type KindedID<Kind extends string> = EntityID & { readonly [kindTag]: Kind };
9
+
10
+ export type GithubRefID = KindedID<'github:ref'>;
11
+
12
+ export function toGithubRefID(id: string): GithubRefID {
13
+ const text = 'github:ref:' + id;
14
+
15
+ if (!isGithubRefID(text)) {
16
+ throw new Error('an ID of the kind github:ref is never empty');
17
+ }
18
+
19
+ return text;
20
+ }
21
+
22
+ export function parseGithubRefID(text: string): GithubRefID | undefined {
23
+ return isGithubRefID(text) ? text : undefined;
24
+ }
25
+
26
+ function isGithubRefID(text: string): text is GithubRefID {
27
+ return text.length > 'github:ref:'.length && text.startsWith('github:ref:');
28
+ }
29
+
30
+ export const settings = {
31
+ "deployTagPattern": "deployed/<environment>"
32
+ } as const;
33
+
34
+ export interface GithubRefModel {
35
+ input: string;
36
+ }
37
+
38
+ export type GithubRefMessage = { kind: 'apply'; input: string } | { kind: 'reset' };
39
+
40
+ export function initGithubRefModel(): GithubRefModel {
41
+ return { input: '' };
42
+ }
43
+
44
+ export function updateGithubRefModel(model: GithubRefModel, message: GithubRefMessage): GithubRefModel {
45
+ return message.kind === 'reset' ? initGithubRefModel() : { ...model, input: message.input };
46
+ }
47
+
48
+ export interface GithubRefPushedPayload {
49
+ ref: string;
50
+ repository: GithubRefPushedPayloadRepository;
51
+ }
52
+
53
+ export interface GithubRefPushedPayloadRepository {
54
+ id: number;
55
+ }
56
+
57
+ export type GithubRefFact =
58
+ | { id: string; type: 'github.ref.pushed'; entity: string; at: string; payload: GithubRefPushedPayload };
59
+
60
+ export function parseGithubRefFact(factJSON: string): GithubRefFact | undefined {
61
+ const parsed: unknown = JSON.parse(factJSON);
62
+
63
+ return decodeGithubRefFact(parsed);
64
+ }
65
+
66
+ function decodeGithubRefFact(value: unknown): GithubRefFact | undefined {
67
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
68
+ return undefined;
69
+ }
70
+
71
+ const id = 'id' in value ? value.id : undefined;
72
+ const type = 'type' in value ? value.type : undefined;
73
+ const entity = 'entity' in value ? value.entity : undefined;
74
+ const at = 'at' in value ? value.at : undefined;
75
+ const payload = 'payload' in value ? value.payload : undefined;
76
+
77
+ if (typeof id !== 'string' || typeof entity !== 'string' || typeof at !== 'string') {
78
+ return undefined;
79
+ }
80
+
81
+ if (type === 'github.ref.pushed') {
82
+ const decoded = decodeGithubRefPushedPayload(payload);
83
+
84
+ if (decoded === undefined) {
85
+ return undefined;
86
+ }
87
+
88
+ return { id, type, entity, at, payload: decoded };
89
+ }
90
+
91
+ return undefined;
92
+ }
93
+
94
+ function decodeGithubRefPushedPayload(value: unknown): GithubRefPushedPayload | undefined {
95
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
96
+ return undefined;
97
+ }
98
+
99
+ const raw0 = 'ref' in value ? value.ref : undefined;
100
+ const field0 = typeof raw0 === 'string' ? raw0 : undefined;
101
+
102
+ if (field0 === undefined) {
103
+ return undefined;
104
+ }
105
+
106
+ const raw1 = 'repository' in value ? value.repository : undefined;
107
+ const field1 = decodeGithubRefPushedPayloadRepository(raw1);
108
+
109
+ if (field1 === undefined) {
110
+ return undefined;
111
+ }
112
+
113
+ return {
114
+ ref: field0,
115
+ repository: field1,
116
+ };
117
+ }
118
+
119
+ function decodeGithubRefPushedPayloadRepository(value: unknown): GithubRefPushedPayloadRepository | undefined {
120
+ if (typeof value !== 'object' || value === null || Array.isArray(value)) {
121
+ return undefined;
122
+ }
123
+
124
+ const raw0 = 'id' in value ? value.id : undefined;
125
+ const field0 = typeof raw0 === 'number' ? raw0 : undefined;
126
+
127
+ if (field0 === undefined) {
128
+ return undefined;
129
+ }
130
+
131
+ return {
132
+ id: field0,
133
+ };
134
+ }
135
+
136
+ export interface GithubCommitRow {
137
+ repository_id: EntityID;
138
+ sha: string;
139
+ committed_at: string;
140
+ }
141
+
142
+ export interface GithubCommitKey {
143
+ repository_id: EntityID;
144
+ sha: string;
145
+ }
146
+
147
+ export type GithubRefOperation =
148
+ | { upsert: { github_commit: GithubCommitRow } }
149
+ | { delete: { github_commit: GithubCommitKey } };
@@ -0,0 +1,8 @@
1
+ -- Generated by `pepys build`. Do not edit.
2
+
3
+ CREATE TABLE "github_commit" (
4
+ "repository_id" TEXT NOT NULL,
5
+ "sha" TEXT NOT NULL,
6
+ "committed_at" TEXT NOT NULL,
7
+ PRIMARY KEY ("repository_id", "sha")
8
+ );