@yeyo11/shipcast 0.0.0-stage → 0.3.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/LICENSE +21 -0
- package/README.md +41 -2
- package/dist/cli/shipcast.js +25240 -0
- package/dist/fonts/Fraunces-Roman.ttf +0 -0
- package/dist/fonts/Fraunces-WonkItalic.ttf +0 -0
- package/dist/fonts/InstrumentSans-Regular.ttf +0 -0
- package/dist/fonts/InstrumentSans-SemiBold.ttf +0 -0
- package/dist/fonts/OFL-Fraunces.txt +93 -0
- package/dist/fonts/OFL-InstrumentSans.txt +93 -0
- package/dist/fonts/README.md +14 -0
- package/drizzle/0000_registry.sql +54 -0
- package/drizzle/0001_post_model.sql +144 -0
- package/drizzle/0002_api_tokens.sql +9 -0
- package/drizzle/0003_jobs.sql +20 -0
- package/drizzle/0004_account_snapshots.sql +15 -0
- package/drizzle/0006_comments.sql +29 -0
- package/drizzle/0007_comments_paging.sql +2 -0
- package/drizzle/0008_assistant_sessions.sql +25 -0
- package/drizzle/0009_attention_dismissals.sql +4 -0
- package/drizzle/0010_comments_search.sql +4 -0
- package/drizzle/0011_launches_list.sql +3 -0
- package/drizzle/0012_telemetry.sql +40 -0
- package/drizzle/0013_publish_attempts.sql +18 -0
- package/drizzle/0014_secrets.sql +8 -0
- package/drizzle/0015_draft_snapshots.sql +13 -0
- package/drizzle/0016_metrics_checked_at.sql +1 -0
- package/drizzle/0017_metric_days.sql +25 -0
- package/drizzle/0018_launch_model.sql +124 -0
- package/drizzle/0019_launch_imports.sql +20 -0
- package/drizzle/0020_launch_deletions.sql +15 -0
- package/drizzle/0021_dedupe_key_backfill.sql +22 -0
- package/drizzle/0022_drop_draft_snapshots.sql +4 -0
- package/drizzle/0023_push_subscriptions.sql +14 -0
- package/drizzle/meta/0000_snapshot.json +400 -0
- package/drizzle/meta/0001_snapshot.json +537 -0
- package/drizzle/meta/0002_snapshot.json +604 -0
- package/drizzle/meta/0003_snapshot.json +732 -0
- package/drizzle/meta/0004_snapshot.json +816 -0
- package/drizzle/meta/0006_snapshot.json +1036 -0
- package/drizzle/meta/0007_snapshot.json +1084 -0
- package/drizzle/meta/0008_snapshot.json +1298 -0
- package/drizzle/meta/0009_snapshot.json +1324 -0
- package/drizzle/meta/0010_snapshot.json +1372 -0
- package/drizzle/meta/0011_snapshot.json +1448 -0
- package/drizzle/meta/0012_snapshot.json +1717 -0
- package/drizzle/meta/0013_snapshot.json +1844 -0
- package/drizzle/meta/0014_snapshot.json +1896 -0
- package/drizzle/meta/0015_snapshot.json +1978 -0
- package/drizzle/meta/0016_snapshot.json +1984 -0
- package/drizzle/meta/0017_snapshot.json +2112 -0
- package/drizzle/meta/0018_snapshot.json +3051 -0
- package/drizzle/meta/0019_snapshot.json +3198 -0
- package/drizzle/meta/0020_snapshot.json +3315 -0
- package/drizzle/meta/0021_snapshot.json +3315 -0
- package/drizzle/meta/0022_snapshot.json +3233 -0
- package/drizzle/meta/0023_snapshot.json +3333 -0
- package/drizzle/meta/_journal.json +167 -0
- package/package.json +62 -4
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2020 The Fraunces Project Authors (github.com/undercasetype/Fraunces) Fraunces-Italic[SOFT,WONK,opsz,wght].ttf: Copyright 2020 The Fraunces Project Authors (github.com/undercasetype/Fraunces)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans) InstrumentSans-Italic[wdth,wght].ttf: Copyright 2022 The Instrument Sans Project Authors (https://github.com/Instrument/instrument-sans)
|
|
2
|
+
|
|
3
|
+
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
|
4
|
+
This license is copied below, and is also available with a FAQ at:
|
|
5
|
+
http://scripts.sil.org/OFL
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
-----------------------------------------------------------
|
|
9
|
+
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
|
10
|
+
-----------------------------------------------------------
|
|
11
|
+
|
|
12
|
+
PREAMBLE
|
|
13
|
+
The goals of the Open Font License (OFL) are to stimulate worldwide
|
|
14
|
+
development of collaborative font projects, to support the font creation
|
|
15
|
+
efforts of academic and linguistic communities, and to provide a free and
|
|
16
|
+
open framework in which fonts may be shared and improved in partnership
|
|
17
|
+
with others.
|
|
18
|
+
|
|
19
|
+
The OFL allows the licensed fonts to be used, studied, modified and
|
|
20
|
+
redistributed freely as long as they are not sold by themselves. The
|
|
21
|
+
fonts, including any derivative works, can be bundled, embedded,
|
|
22
|
+
redistributed and/or sold with any software provided that any reserved
|
|
23
|
+
names are not used by derivative works. The fonts and derivatives,
|
|
24
|
+
however, cannot be released under any other type of license. The
|
|
25
|
+
requirement for fonts to remain under this license does not apply
|
|
26
|
+
to any document created using the fonts or their derivatives.
|
|
27
|
+
|
|
28
|
+
DEFINITIONS
|
|
29
|
+
"Font Software" refers to the set of files released by the Copyright
|
|
30
|
+
Holder(s) under this license and clearly marked as such. This may
|
|
31
|
+
include source files, build scripts and documentation.
|
|
32
|
+
|
|
33
|
+
"Reserved Font Name" refers to any names specified as such after the
|
|
34
|
+
copyright statement(s).
|
|
35
|
+
|
|
36
|
+
"Original Version" refers to the collection of Font Software components as
|
|
37
|
+
distributed by the Copyright Holder(s).
|
|
38
|
+
|
|
39
|
+
"Modified Version" refers to any derivative made by adding to, deleting,
|
|
40
|
+
or substituting -- in part or in whole -- any of the components of the
|
|
41
|
+
Original Version, by changing formats or by porting the Font Software to a
|
|
42
|
+
new environment.
|
|
43
|
+
|
|
44
|
+
"Author" refers to any designer, engineer, programmer, technical
|
|
45
|
+
writer or other person who contributed to the Font Software.
|
|
46
|
+
|
|
47
|
+
PERMISSION & CONDITIONS
|
|
48
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
49
|
+
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
|
50
|
+
redistribute, and sell modified and unmodified copies of the Font
|
|
51
|
+
Software, subject to the following conditions:
|
|
52
|
+
|
|
53
|
+
1) Neither the Font Software nor any of its individual components,
|
|
54
|
+
in Original or Modified Versions, may be sold by itself.
|
|
55
|
+
|
|
56
|
+
2) Original or Modified Versions of the Font Software may be bundled,
|
|
57
|
+
redistributed and/or sold with any software, provided that each copy
|
|
58
|
+
contains the above copyright notice and this license. These can be
|
|
59
|
+
included either as stand-alone text files, human-readable headers or
|
|
60
|
+
in the appropriate machine-readable metadata fields within text or
|
|
61
|
+
binary files as long as those fields can be easily viewed by the user.
|
|
62
|
+
|
|
63
|
+
3) No Modified Version of the Font Software may use the Reserved Font
|
|
64
|
+
Name(s) unless explicit written permission is granted by the corresponding
|
|
65
|
+
Copyright Holder. This restriction only applies to the primary font name as
|
|
66
|
+
presented to the users.
|
|
67
|
+
|
|
68
|
+
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
|
69
|
+
Software shall not be used to promote, endorse or advertise any
|
|
70
|
+
Modified Version, except to acknowledge the contribution(s) of the
|
|
71
|
+
Copyright Holder(s) and the Author(s) or with their explicit written
|
|
72
|
+
permission.
|
|
73
|
+
|
|
74
|
+
5) The Font Software, modified or unmodified, in part or in whole,
|
|
75
|
+
must be distributed entirely under this license, and must not be
|
|
76
|
+
distributed under any other license. The requirement for fonts to
|
|
77
|
+
remain under this license does not apply to any document created
|
|
78
|
+
using the Font Software.
|
|
79
|
+
|
|
80
|
+
TERMINATION
|
|
81
|
+
This license becomes null and void if any of the above conditions are
|
|
82
|
+
not met.
|
|
83
|
+
|
|
84
|
+
DISCLAIMER
|
|
85
|
+
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
86
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
|
87
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
|
88
|
+
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
|
89
|
+
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
90
|
+
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
|
91
|
+
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
|
92
|
+
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
|
93
|
+
OTHER DEALINGS IN THE FONT SOFTWARE.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Fonts for the launch image
|
|
2
|
+
|
|
3
|
+
Static instances of the variable fonts the personal site uses, because Satori reads neither variable
|
|
4
|
+
fonts nor WOFF2. Latin subset, cut from the Fontsource variable files with
|
|
5
|
+
`fonttools varLib.instancer`:
|
|
6
|
+
|
|
7
|
+
| File | Source | Axes |
|
|
8
|
+
| --- | --- | --- |
|
|
9
|
+
| `Fraunces-Roman.ttf` | Fraunces, full, normal | `wght=400 opsz=144 SOFT=30 WONK=1` (the site's headlines) |
|
|
10
|
+
| `Fraunces-WonkItalic.ttf` | Fraunces, full, italic | `wght=400 opsz=144 SOFT=100 WONK=1` (each headline word's first letter) |
|
|
11
|
+
| `InstrumentSans-Regular.ttf` | Instrument Sans, standard | `wght=400 wdth=100` |
|
|
12
|
+
| `InstrumentSans-SemiBold.ttf` | Instrument Sans, standard | `wght=600 wdth=100` |
|
|
13
|
+
|
|
14
|
+
Both families are under the SIL Open Font License 1.1 (`OFL-*.txt`), with no reserved font name.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
CREATE TABLE "accounts" (
|
|
2
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "accounts_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
3
|
+
"network" text NOT NULL,
|
|
4
|
+
"brand" text NOT NULL,
|
|
5
|
+
"label" text NOT NULL,
|
|
6
|
+
"settings" text DEFAULT '{}' NOT NULL,
|
|
7
|
+
"is_primary" integer DEFAULT 0 NOT NULL,
|
|
8
|
+
"status" text DEFAULT 'unchecked' NOT NULL,
|
|
9
|
+
"identity" text,
|
|
10
|
+
"problem" text,
|
|
11
|
+
"checked_at" text,
|
|
12
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
13
|
+
CONSTRAINT "accounts_network_brand_label_unique" UNIQUE("network","brand","label")
|
|
14
|
+
);
|
|
15
|
+
--> statement-breakpoint
|
|
16
|
+
CREATE TABLE "cursors" (
|
|
17
|
+
"key" text PRIMARY KEY NOT NULL,
|
|
18
|
+
"value" text NOT NULL
|
|
19
|
+
);
|
|
20
|
+
--> statement-breakpoint
|
|
21
|
+
CREATE TABLE "launches" (
|
|
22
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "launches_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
23
|
+
"repo" text NOT NULL,
|
|
24
|
+
"ref" text NOT NULL,
|
|
25
|
+
"trigger" text NOT NULL,
|
|
26
|
+
"kind" text NOT NULL,
|
|
27
|
+
"brand" text NOT NULL,
|
|
28
|
+
"status" text NOT NULL,
|
|
29
|
+
"detail" text,
|
|
30
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
31
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
32
|
+
CONSTRAINT "launches_repo_ref_unique" UNIQUE("repo","ref")
|
|
33
|
+
);
|
|
34
|
+
--> statement-breakpoint
|
|
35
|
+
CREATE TABLE "metrics" (
|
|
36
|
+
"launch_id" integer NOT NULL,
|
|
37
|
+
"source" text NOT NULL,
|
|
38
|
+
"name" text NOT NULL,
|
|
39
|
+
"value" double precision NOT NULL,
|
|
40
|
+
"taken_at" text NOT NULL
|
|
41
|
+
);
|
|
42
|
+
--> statement-breakpoint
|
|
43
|
+
CREATE TABLE "posts" (
|
|
44
|
+
"launch_id" integer NOT NULL,
|
|
45
|
+
"channel" text NOT NULL,
|
|
46
|
+
"url" text,
|
|
47
|
+
"external_id" text,
|
|
48
|
+
"published_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
49
|
+
CONSTRAINT "posts_launch_id_channel_pk" PRIMARY KEY("launch_id","channel")
|
|
50
|
+
);
|
|
51
|
+
--> statement-breakpoint
|
|
52
|
+
ALTER TABLE "metrics" ADD CONSTRAINT "metrics_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
53
|
+
ALTER TABLE "posts" ADD CONSTRAINT "posts_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
54
|
+
CREATE INDEX "metrics_by_launch" ON "metrics" USING btree ("launch_id","source","name","taken_at");
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
-- One row per published piece, typed settings, and the conversion of what an install already holds.
|
|
2
|
+
-- Drizzle's migrator runs a migration in one transaction, so a conversion that fails leaves the
|
|
3
|
+
-- registry as it was; every insert also skips what is already there, so a rerun of a statement
|
|
4
|
+
-- converts nothing twice. See docs/decisions/post-model.md
|
|
5
|
+
CREATE TABLE "settings" (
|
|
6
|
+
"key" text PRIMARY KEY NOT NULL,
|
|
7
|
+
"value" jsonb NOT NULL,
|
|
8
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL
|
|
9
|
+
);
|
|
10
|
+
--> statement-breakpoint
|
|
11
|
+
ALTER TABLE "posts" DROP CONSTRAINT "posts_launch_id_channel_pk";--> statement-breakpoint
|
|
12
|
+
ALTER TABLE "metrics" ADD COLUMN "post_id" integer;--> statement-breakpoint
|
|
13
|
+
ALTER TABLE "posts" ADD COLUMN "id" integer PRIMARY KEY NOT NULL GENERATED BY DEFAULT AS IDENTITY (sequence name "posts_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1);--> statement-breakpoint
|
|
14
|
+
ALTER TABLE "posts" ADD COLUMN "account_id" integer;--> statement-breakpoint
|
|
15
|
+
-- Null until the conversion below gives every old row its kind: a null kind marks an old row
|
|
16
|
+
ALTER TABLE "posts" ADD COLUMN "kind" text;--> statement-breakpoint
|
|
17
|
+
ALTER TABLE "posts" ADD COLUMN "status" text DEFAULT 'live' NOT NULL;--> statement-breakpoint
|
|
18
|
+
ALTER TABLE "posts" ADD COLUMN "content_hash" text;--> statement-breakpoint
|
|
19
|
+
ALTER TABLE "posts" ADD COLUMN "scheduled_at" text;--> statement-breakpoint
|
|
20
|
+
ALTER TABLE "posts" ADD COLUMN "updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL;--> statement-breakpoint
|
|
21
|
+
ALTER TABLE "metrics" ADD CONSTRAINT "metrics_post_id_posts_id_fk" FOREIGN KEY ("post_id") REFERENCES "public"."posts"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
22
|
+
ALTER TABLE "posts" ADD CONSTRAINT "posts_account_id_accounts_id_fk" FOREIGN KEY ("account_id") REFERENCES "public"."accounts"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
23
|
+
CREATE INDEX "metrics_by_post" ON "metrics" USING btree ("post_id");--> statement-breakpoint
|
|
24
|
+
-- Before the conversion, so its inserts can skip a piece already recorded. The old rows were one per
|
|
25
|
+
-- launch and channel, so with a null kind and no account they already satisfy it
|
|
26
|
+
ALTER TABLE "posts" ADD CONSTRAINT "posts_piece_unique" UNIQUE NULLS NOT DISTINCT("launch_id","channel","account_id","kind");--> statement-breakpoint
|
|
27
|
+
UPDATE "posts" SET "updated_at" = "published_at";--> statement-breakpoint
|
|
28
|
+
|
|
29
|
+
-- The blog: one article per language from `en:<slug>,es:<slug>`, at <origin of the old URL>/<lang>/<slug>/
|
|
30
|
+
INSERT INTO "posts" ("launch_id", "channel", "account_id", "kind", "external_id", "url", "status", "published_at", "updated_at")
|
|
31
|
+
SELECT p."launch_id", 'blog', NULL, 'article:' || m.part[1], m.part[2],
|
|
32
|
+
substring(p."url" from '^[a-z]+://[^/]+') || '/' || m.part[1] || '/' || m.part[2] || '/',
|
|
33
|
+
'live', p."published_at", p."published_at"
|
|
34
|
+
FROM "posts" p
|
|
35
|
+
CROSS JOIN LATERAL regexp_matches(p."external_id", '(?:^|,)(en|es):([^,]+)', 'g') AS m(part)
|
|
36
|
+
WHERE p."channel" = 'blog' AND p."kind" IS NULL AND substring(p."url" from '^[a-z]+://[^/]+') IS NOT NULL
|
|
37
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
38
|
+
-- An older blog row with one slug for both languages: its URL's language, and the other one at the
|
|
39
|
+
-- same slug, which is what the metrics assumed of it
|
|
40
|
+
INSERT INTO "posts" ("launch_id", "channel", "account_id", "kind", "external_id", "url", "status", "published_at", "updated_at")
|
|
41
|
+
SELECT p."launch_id", 'blog', NULL, 'article:' || v.lang, substring(v.url from '/([^/]+)/?$'), v.url, 'live', p."published_at", p."published_at"
|
|
42
|
+
FROM "posts" p
|
|
43
|
+
CROSS JOIN LATERAL (
|
|
44
|
+
VALUES (COALESCE(substring(p."url" from '^[a-z]+://[^/]+/(en|es)/'), 'en'), p."url"),
|
|
45
|
+
(CASE WHEN p."url" ~ '^[a-z]+://[^/]+/en/' THEN 'es' END, regexp_replace(p."url", '^([a-z]+://[^/]+)/en/', '\1/es/'))
|
|
46
|
+
) AS v(lang, url)
|
|
47
|
+
WHERE p."channel" = 'blog' AND p."kind" IS NULL AND p."url" IS NOT NULL AND v.lang IS NOT NULL
|
|
48
|
+
AND COALESCE(p."external_id", '') !~ '(^|,)(en|es):'
|
|
49
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
50
|
+
DELETE FROM "posts" p
|
|
51
|
+
WHERE p."channel" = 'blog' AND p."kind" IS NULL
|
|
52
|
+
AND EXISTS (SELECT 1 FROM "posts" a WHERE a."launch_id" = p."launch_id" AND a."channel" = 'blog' AND a."kind" LIKE 'article:%');--> statement-breakpoint
|
|
53
|
+
|
|
54
|
+
-- The newsletter: one issue per language, from the `newsletter-sent:<launch>:<lang>` cursors, which
|
|
55
|
+
-- hold each campaign's id and report URL, and which also record an issue whose sibling never went out
|
|
56
|
+
WITH "sent" AS (
|
|
57
|
+
SELECT split_part(c."key", ':', 2) AS launch, split_part(c."key", ':', 3) AS lang,
|
|
58
|
+
CASE WHEN c."value" IS JSON OBJECT THEN c."value"::jsonb END AS issue
|
|
59
|
+
FROM "cursors" c
|
|
60
|
+
WHERE c."key" ~ '^newsletter-sent:[0-9]+:(en|es)$'
|
|
61
|
+
)
|
|
62
|
+
INSERT INTO "posts" ("launch_id", "channel", "account_id", "kind", "external_id", "url", "status", "published_at", "updated_at")
|
|
63
|
+
SELECT l."id", 'newsletter',
|
|
64
|
+
(SELECT a."id" FROM "accounts" a WHERE a."network" = 'brevo' AND a."brand" = l."brand" AND a."is_primary" = 1 ORDER BY a."id" LIMIT 1),
|
|
65
|
+
'issue:' || s.lang, s.issue ->> 'externalId', s.issue ->> 'url', 'live',
|
|
66
|
+
COALESCE(p."published_at", to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')),
|
|
67
|
+
COALESCE(p."published_at", to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'))
|
|
68
|
+
FROM "sent" s
|
|
69
|
+
JOIN "launches" l ON l."id"::text = s.launch
|
|
70
|
+
LEFT JOIN "posts" p ON p."launch_id" = l."id" AND p."channel" = 'newsletter' AND p."kind" IS NULL
|
|
71
|
+
WHERE s.issue ->> 'externalId' IS NOT NULL
|
|
72
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
73
|
+
-- A newsletter row with no cursors left: its comma-joined ids in the order they were sent, English first
|
|
74
|
+
INSERT INTO "posts" ("launch_id", "channel", "account_id", "kind", "external_id", "url", "status", "published_at", "updated_at")
|
|
75
|
+
SELECT p."launch_id", 'newsletter',
|
|
76
|
+
(SELECT a."id" FROM "accounts" a JOIN "launches" l ON l."id" = p."launch_id"
|
|
77
|
+
WHERE a."network" = 'brevo' AND a."brand" = l."brand" AND a."is_primary" = 1 ORDER BY a."id" LIMIT 1),
|
|
78
|
+
'issue:' || (ARRAY['en', 'es'])[ids.n], ids.id,
|
|
79
|
+
CASE WHEN p."url" LIKE '%/' || split_part(p."external_id", ',', 1) THEN regexp_replace(p."url", '[^/]+$', ids.id)
|
|
80
|
+
WHEN ids.n = 1 THEN p."url" END,
|
|
81
|
+
'live', p."published_at", p."published_at"
|
|
82
|
+
FROM "posts" p
|
|
83
|
+
CROSS JOIN LATERAL unnest(string_to_array(p."external_id", ',')) WITH ORDINALITY AS ids(id, n)
|
|
84
|
+
WHERE p."channel" = 'newsletter' AND p."kind" IS NULL AND ids.n <= 2 AND ids.id <> ''
|
|
85
|
+
AND NOT EXISTS (SELECT 1 FROM "posts" i WHERE i."launch_id" = p."launch_id" AND i."channel" = 'newsletter' AND i."kind" LIKE 'issue:%')
|
|
86
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
87
|
+
DELETE FROM "posts" p
|
|
88
|
+
WHERE p."channel" = 'newsletter' AND p."kind" IS NULL
|
|
89
|
+
AND EXISTS (SELECT 1 FROM "posts" i WHERE i."launch_id" = p."launch_id" AND i."channel" = 'newsletter' AND i."kind" LIKE 'issue:%');--> statement-breakpoint
|
|
90
|
+
|
|
91
|
+
-- Instagram's story and comment, kept in `instagram-story:<launch>` and `instagram-comment:<launch>`,
|
|
92
|
+
-- dated as the post they followed
|
|
93
|
+
WITH "extra" AS (
|
|
94
|
+
SELECT split_part(c."key", ':', 2) AS launch, substring(c."key" from '^instagram-(story|comment):') AS what, c."value"
|
|
95
|
+
FROM "cursors" c
|
|
96
|
+
WHERE c."key" ~ '^instagram-(story|comment):[0-9]+$'
|
|
97
|
+
)
|
|
98
|
+
INSERT INTO "posts" ("launch_id", "channel", "account_id", "kind", "external_id", "url", "status", "published_at", "updated_at")
|
|
99
|
+
SELECT l."id", 'instagram',
|
|
100
|
+
(SELECT a."id" FROM "accounts" a WHERE a."network" = 'instagram' AND a."brand" = l."brand" AND a."is_primary" = 1 ORDER BY a."id" LIMIT 1),
|
|
101
|
+
e.what, e."value", NULL, 'live',
|
|
102
|
+
COALESCE(p."published_at", to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"')),
|
|
103
|
+
COALESCE(p."published_at", to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"'))
|
|
104
|
+
FROM "extra" e
|
|
105
|
+
JOIN "launches" l ON l."id"::text = e.launch
|
|
106
|
+
LEFT JOIN "posts" p ON p."launch_id" = l."id" AND p."channel" = 'instagram' AND (p."kind" IS NULL OR p."kind" = 'post')
|
|
107
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
108
|
+
|
|
109
|
+
-- Every other old row is a post, by the account that was primary for its network and brand
|
|
110
|
+
UPDATE "posts" p
|
|
111
|
+
SET "kind" = 'post',
|
|
112
|
+
"account_id" = (
|
|
113
|
+
SELECT a."id" FROM "accounts" a JOIN "launches" l ON l."id" = p."launch_id"
|
|
114
|
+
WHERE a."network" = CASE p."channel" WHEN 'newsletter' THEN 'brevo' ELSE p."channel" END
|
|
115
|
+
AND a."brand" = l."brand" AND a."is_primary" = 1 AND p."channel" <> 'blog'
|
|
116
|
+
ORDER BY a."id" LIMIT 1
|
|
117
|
+
)
|
|
118
|
+
WHERE p."kind" IS NULL;--> statement-breakpoint
|
|
119
|
+
ALTER TABLE "posts" ALTER COLUMN "kind" SET NOT NULL;--> statement-breakpoint
|
|
120
|
+
|
|
121
|
+
-- A channel's readings are its post's. The old newsletter readings stay with the launch: each is the
|
|
122
|
+
-- sum of both issues, so neither issue is theirs alone
|
|
123
|
+
UPDATE "metrics" m SET "post_id" = p."id"
|
|
124
|
+
FROM "posts" p
|
|
125
|
+
WHERE m."post_id" IS NULL AND p."launch_id" = m."launch_id" AND p."channel" = m."source" AND p."kind" = 'post'
|
|
126
|
+
AND m."source" NOT IN ('blog', 'newsletter');--> statement-breakpoint
|
|
127
|
+
|
|
128
|
+
-- The owner's automation choices, out of the cursors
|
|
129
|
+
INSERT INTO "settings" ("key", "value")
|
|
130
|
+
SELECT c."key", to_jsonb(c."value") FROM "cursors" c WHERE c."key" = 'automation:mode'
|
|
131
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
132
|
+
INSERT INTO "settings" ("key", "value")
|
|
133
|
+
SELECT c."key", to_jsonb(c."value"::numeric) FROM "cursors" c WHERE c."key" = 'automation:interval' AND c."value" ~ '^[0-9]{1,9}$'
|
|
134
|
+
ON CONFLICT DO NOTHING;--> statement-breakpoint
|
|
135
|
+
|
|
136
|
+
-- The cursors that became rows or settings, now that they are copied; anything not copied stays
|
|
137
|
+
DELETE FROM "cursors" c
|
|
138
|
+
WHERE (c."key" ~ '^newsletter-sent:[0-9]+:(en|es)$' AND EXISTS (
|
|
139
|
+
SELECT 1 FROM "posts" i WHERE i."launch_id"::text = split_part(c."key", ':', 2) AND i."channel" = 'newsletter'
|
|
140
|
+
AND i."kind" = 'issue:' || split_part(c."key", ':', 3)))
|
|
141
|
+
OR (c."key" ~ '^instagram-(story|comment):[0-9]+$' AND EXISTS (
|
|
142
|
+
SELECT 1 FROM "posts" x WHERE x."launch_id"::text = split_part(c."key", ':', 2) AND x."channel" = 'instagram'
|
|
143
|
+
AND x."kind" = substring(c."key" from '^instagram-(story|comment):')))
|
|
144
|
+
OR (c."key" IN ('automation:mode', 'automation:interval') AND EXISTS (SELECT 1 FROM "settings" s WHERE s."key" = c."key"));
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
CREATE TABLE "api_tokens" (
|
|
2
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "api_tokens_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
3
|
+
"name" text NOT NULL,
|
|
4
|
+
"hash" text NOT NULL,
|
|
5
|
+
"scopes" text[] NOT NULL,
|
|
6
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
7
|
+
"last_used_at" text,
|
|
8
|
+
"revoked_at" text
|
|
9
|
+
);
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
-- What the app shows of the queue's work: one row per pg-boss job, kept after it ends and across
|
|
2
|
+
-- restarts. pg-boss creates its own schema (pgboss) when it starts; nothing here touches it. See
|
|
3
|
+
-- docs/decisions/job-queue.md
|
|
4
|
+
CREATE TABLE "jobs" (
|
|
5
|
+
"id" text PRIMARY KEY NOT NULL,
|
|
6
|
+
"queue" text NOT NULL,
|
|
7
|
+
"title" text NOT NULL,
|
|
8
|
+
"launch_id" integer,
|
|
9
|
+
"state" text DEFAULT 'created' NOT NULL,
|
|
10
|
+
"attempts" integer DEFAULT 0 NOT NULL,
|
|
11
|
+
"log" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
|
12
|
+
"link" text,
|
|
13
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
14
|
+
"started_at" text,
|
|
15
|
+
"ended_at" text
|
|
16
|
+
);
|
|
17
|
+
--> statement-breakpoint
|
|
18
|
+
ALTER TABLE "jobs" ADD CONSTRAINT "jobs_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
19
|
+
CREATE INDEX "jobs_by_created" ON "jobs" USING btree ("created_at");--> statement-breakpoint
|
|
20
|
+
CREATE INDEX "jobs_by_launch" ON "jobs" USING btree ("launch_id");
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
-- Each account's followers, following and posts, one row a day from now on, and the picture the
|
|
2
|
+
-- last check found. Only adds: no existing row changes. See docs/decisions/account-snapshots.md
|
|
3
|
+
CREATE TABLE "account_snapshots" (
|
|
4
|
+
"account_id" integer NOT NULL,
|
|
5
|
+
"day" text NOT NULL,
|
|
6
|
+
"taken_at" text NOT NULL,
|
|
7
|
+
"followers" integer,
|
|
8
|
+
"following" integer,
|
|
9
|
+
"posts" integer,
|
|
10
|
+
"extra" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
11
|
+
CONSTRAINT "account_snapshots_account_day" PRIMARY KEY("account_id","day")
|
|
12
|
+
);
|
|
13
|
+
--> statement-breakpoint
|
|
14
|
+
ALTER TABLE "accounts" ADD COLUMN "avatar_url" text;--> statement-breakpoint
|
|
15
|
+
ALTER TABLE "account_snapshots" ADD CONSTRAINT "account_snapshots_account_id_accounts_id_fk" FOREIGN KEY ("account_id") REFERENCES "public"."accounts"("id") ON DELETE cascade ON UPDATE no action;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
CREATE TABLE "comments" (
|
|
2
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "comments_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
3
|
+
"post_id" integer NOT NULL,
|
|
4
|
+
"channel" text NOT NULL,
|
|
5
|
+
"external_id" text NOT NULL,
|
|
6
|
+
"author_handle" text NOT NULL,
|
|
7
|
+
"author_name" text,
|
|
8
|
+
"author_avatar_url" text,
|
|
9
|
+
"text" text NOT NULL,
|
|
10
|
+
"url" text,
|
|
11
|
+
"created_at" text NOT NULL,
|
|
12
|
+
"in_reply_to" text,
|
|
13
|
+
"own" boolean DEFAULT false NOT NULL,
|
|
14
|
+
"fetched_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
15
|
+
"status" text DEFAULT 'new' NOT NULL,
|
|
16
|
+
"classification" text,
|
|
17
|
+
"draft" text,
|
|
18
|
+
"note" text,
|
|
19
|
+
"problem" text,
|
|
20
|
+
"sent_external_id" text,
|
|
21
|
+
"sent_url" text,
|
|
22
|
+
"sent_at" text,
|
|
23
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
24
|
+
CONSTRAINT "comments_channel_external_unique" UNIQUE("channel","external_id")
|
|
25
|
+
);
|
|
26
|
+
--> statement-breakpoint
|
|
27
|
+
ALTER TABLE "comments" ADD CONSTRAINT "comments_post_id_posts_id_fk" FOREIGN KEY ("post_id") REFERENCES "public"."posts"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
28
|
+
CREATE INDEX "comments_by_post" ON "comments" USING btree ("post_id");--> statement-breakpoint
|
|
29
|
+
CREATE INDEX "comments_by_status" ON "comments" USING btree ("status","created_at");
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
CREATE TABLE "assistant_messages" (
|
|
2
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "assistant_messages_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
3
|
+
"session_id" integer NOT NULL,
|
|
4
|
+
"role" text NOT NULL,
|
|
5
|
+
"content" text NOT NULL,
|
|
6
|
+
"proposals" jsonb DEFAULT '[]'::jsonb NOT NULL,
|
|
7
|
+
"selection" jsonb,
|
|
8
|
+
"problem" text,
|
|
9
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL
|
|
10
|
+
);
|
|
11
|
+
--> statement-breakpoint
|
|
12
|
+
CREATE TABLE "assistant_sessions" (
|
|
13
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "assistant_sessions_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
14
|
+
"title" text NOT NULL,
|
|
15
|
+
"launch_id" integer,
|
|
16
|
+
"draft_path" text,
|
|
17
|
+
"draft_label" text,
|
|
18
|
+
"created_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
19
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL
|
|
20
|
+
);
|
|
21
|
+
--> statement-breakpoint
|
|
22
|
+
ALTER TABLE "assistant_messages" ADD CONSTRAINT "assistant_messages_session_id_assistant_sessions_id_fk" FOREIGN KEY ("session_id") REFERENCES "public"."assistant_sessions"("id") ON DELETE cascade ON UPDATE no action;--> statement-breakpoint
|
|
23
|
+
ALTER TABLE "assistant_sessions" ADD CONSTRAINT "assistant_sessions_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE set null ON UPDATE no action;--> statement-breakpoint
|
|
24
|
+
CREATE INDEX "assistant_messages_by_session" ON "assistant_messages" USING btree ("session_id","id");--> statement-breakpoint
|
|
25
|
+
CREATE INDEX "assistant_sessions_by_updated" ON "assistant_sessions" USING btree ("updated_at","id");
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
CREATE EXTENSION IF NOT EXISTS pg_trgm;--> statement-breakpoint
|
|
2
|
+
CREATE INDEX IF NOT EXISTS "comments_text_trgm" ON "comments" USING gin ("text" gin_trgm_ops);--> statement-breakpoint
|
|
3
|
+
CREATE INDEX IF NOT EXISTS "comments_author_handle_trgm" ON "comments" USING gin ("author_handle" gin_trgm_ops);--> statement-breakpoint
|
|
4
|
+
CREATE INDEX IF NOT EXISTS "comments_author_name_trgm" ON "comments" USING gin ("author_name" gin_trgm_ops);
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
CREATE INDEX "launches_by_newest" ON "launches" USING btree ("created_at" DESC NULLS LAST,"id" DESC NULLS LAST);--> statement-breakpoint
|
|
2
|
+
CREATE INDEX "launches_by_status" ON "launches" USING btree ("status","created_at" DESC NULLS LAST,"id" DESC NULLS LAST);--> statement-breakpoint
|
|
3
|
+
CREATE INDEX "launches_by_repo" ON "launches" USING btree ("repo","created_at" DESC NULLS LAST,"id" DESC NULLS LAST);
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
CREATE TABLE "checks" (
|
|
2
|
+
"id" integer PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY (sequence name "checks_id_seq" INCREMENT BY 1 MINVALUE 1 MAXVALUE 2147483647 START WITH 1 CACHE 1),
|
|
3
|
+
"taken_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
4
|
+
"name" text NOT NULL,
|
|
5
|
+
"ok" boolean NOT NULL,
|
|
6
|
+
"value" double precision NOT NULL,
|
|
7
|
+
"detail" jsonb DEFAULT '{}'::jsonb NOT NULL
|
|
8
|
+
);
|
|
9
|
+
--> statement-breakpoint
|
|
10
|
+
CREATE TABLE "provider_calls" (
|
|
11
|
+
"hour" text NOT NULL,
|
|
12
|
+
"process" text NOT NULL,
|
|
13
|
+
"origin" text NOT NULL,
|
|
14
|
+
"provider" text NOT NULL,
|
|
15
|
+
"method" text NOT NULL,
|
|
16
|
+
"endpoint" text NOT NULL,
|
|
17
|
+
"status" integer NOT NULL,
|
|
18
|
+
"calls" integer NOT NULL,
|
|
19
|
+
"total_ms" double precision NOT NULL,
|
|
20
|
+
"bytes" double precision DEFAULT 0 NOT NULL,
|
|
21
|
+
"latency" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
22
|
+
"quota_peak" double precision,
|
|
23
|
+
"quota_limit" integer,
|
|
24
|
+
CONSTRAINT "provider_calls_key" PRIMARY KEY("hour","process","origin","provider","method","endpoint","status")
|
|
25
|
+
);
|
|
26
|
+
--> statement-breakpoint
|
|
27
|
+
CREATE TABLE "timings" (
|
|
28
|
+
"hour" text NOT NULL,
|
|
29
|
+
"process" text NOT NULL,
|
|
30
|
+
"kind" text NOT NULL,
|
|
31
|
+
"name" text NOT NULL,
|
|
32
|
+
"outcome" text NOT NULL,
|
|
33
|
+
"count" integer NOT NULL,
|
|
34
|
+
"total_ms" double precision NOT NULL,
|
|
35
|
+
"max_ms" double precision NOT NULL,
|
|
36
|
+
"latency" jsonb DEFAULT '{}'::jsonb NOT NULL,
|
|
37
|
+
CONSTRAINT "timings_key" PRIMARY KEY("hour","process","kind","name","outcome")
|
|
38
|
+
);
|
|
39
|
+
--> statement-breakpoint
|
|
40
|
+
CREATE INDEX "checks_by_name" ON "checks" USING btree ("name","taken_at");
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
CREATE TABLE "publish_attempts" (
|
|
2
|
+
"launch_id" integer NOT NULL,
|
|
3
|
+
"channel" text NOT NULL,
|
|
4
|
+
"kind" text NOT NULL,
|
|
5
|
+
"state" text NOT NULL,
|
|
6
|
+
"attempts" integer DEFAULT 1 NOT NULL,
|
|
7
|
+
"lease_until" text,
|
|
8
|
+
"holder" text,
|
|
9
|
+
"error" text,
|
|
10
|
+
"external_id" text,
|
|
11
|
+
"url" text,
|
|
12
|
+
"started_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
13
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL,
|
|
14
|
+
CONSTRAINT "publish_attempts_piece" PRIMARY KEY("launch_id","channel","kind")
|
|
15
|
+
);
|
|
16
|
+
--> statement-breakpoint
|
|
17
|
+
ALTER TABLE "publish_attempts" ADD CONSTRAINT "publish_attempts_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE no action ON UPDATE no action;--> statement-breakpoint
|
|
18
|
+
CREATE INDEX "publish_attempts_by_state" ON "publish_attempts" USING btree ("state");
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
CREATE TABLE "secrets" (
|
|
2
|
+
"key" text PRIMARY KEY NOT NULL,
|
|
3
|
+
"label" text DEFAULT '' NOT NULL,
|
|
4
|
+
"sealed" text NOT NULL,
|
|
5
|
+
"sealed_key" text NOT NULL,
|
|
6
|
+
"version" integer DEFAULT 1 NOT NULL,
|
|
7
|
+
"updated_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL
|
|
8
|
+
);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
CREATE TABLE "draft_snapshots" (
|
|
2
|
+
"launch_id" integer PRIMARY KEY NOT NULL,
|
|
3
|
+
"pr_number" integer NOT NULL,
|
|
4
|
+
"url" text NOT NULL,
|
|
5
|
+
"branch" text NOT NULL,
|
|
6
|
+
"head_sha" text,
|
|
7
|
+
"state" text NOT NULL,
|
|
8
|
+
"launch_yml" text,
|
|
9
|
+
"files" jsonb NOT NULL,
|
|
10
|
+
"read_at" text DEFAULT to_char(statement_timestamp() AT TIME ZONE 'UTC', 'YYYY-MM-DD"T"HH24:MI:SS.MS"Z"') NOT NULL
|
|
11
|
+
);
|
|
12
|
+
--> statement-breakpoint
|
|
13
|
+
ALTER TABLE "draft_snapshots" ADD CONSTRAINT "draft_snapshots_launch_id_launches_id_fk" FOREIGN KEY ("launch_id") REFERENCES "public"."launches"("id") ON DELETE no action ON UPDATE no action;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
ALTER TABLE "metrics" ADD COLUMN "checked_at" text;
|