mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-03-24 16:18:39 +08:00
Compare commits
193 Commits
v0.26.0-be
...
311ed7f6e1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
311ed7f6e1 | ||
|
|
ffa3ff9d7f | ||
|
|
f47ee2bc8a | ||
|
|
bcf2a51d41 | ||
|
|
6a93566422 | ||
|
|
7ac8b14b65 | ||
|
|
16a8f17717 | ||
|
|
1ffb8c922c | ||
|
|
daf536f77a | ||
|
|
0d2d4bb6a1 | ||
|
|
cb9897d493 | ||
|
|
8ca8333cd6 | ||
|
|
3bf2503f55 | ||
|
|
59fd942f40 | ||
|
|
d6d5ae6182 | ||
|
|
c1a09b951f | ||
|
|
4ce68d74f1 | ||
|
|
fbfcc01d14 | ||
|
|
1112a06623 | ||
|
|
bbcb7e69fe | ||
|
|
cc2f23339e | ||
|
|
31101a69e7 | ||
|
|
0b1a44863f | ||
|
|
8406f9656e | ||
|
|
121c0d172d | ||
|
|
8f03090780 | ||
|
|
8125cc0e75 | ||
|
|
f537a75f01 | ||
|
|
9456a07889 | ||
|
|
8f571ddc30 | ||
|
|
13ad1beb10 | ||
|
|
9844ca4d54 | ||
|
|
d7d67841b8 | ||
|
|
29a27b561b | ||
|
|
02744cec00 | ||
|
|
6d710f3bdc | ||
|
|
0b47f92134 | ||
|
|
9c55edeb62 | ||
|
|
9742e9735e | ||
|
|
86d65b2f64 | ||
|
|
f34e25e122 | ||
|
|
b5d5b71f95 | ||
|
|
09fa1a8e4e | ||
|
|
c249011238 | ||
|
|
7f5f7e79df | ||
|
|
fff04395bc | ||
|
|
bbc01533d7 | ||
|
|
e31cca3354 | ||
|
|
11bc333714 | ||
|
|
99b07c2ee1 | ||
|
|
fc9b99cd17 | ||
|
|
2137f68871 | ||
|
|
75efa854bf | ||
|
|
c0139abf79 | ||
|
|
5a38e765bd | ||
|
|
d3dcdd47ee | ||
|
|
727c9d6d71 | ||
|
|
274f491e49 | ||
|
|
478138493a | ||
|
|
5464d1a9ce | ||
|
|
4c40dcacd9 | ||
|
|
76d28aaa38 | ||
|
|
86f48240ce | ||
|
|
c5d622531c | ||
|
|
60acd81d4b | ||
|
|
78f567a178 | ||
|
|
784382cfb1 | ||
|
|
342451be1b | ||
|
|
2b6146727b | ||
|
|
d5245a3273 | ||
|
|
fff63562b1 | ||
|
|
4136abdd97 | ||
|
|
e249e2e884 | ||
|
|
2e95d91093 | ||
|
|
2cb171f553 | ||
|
|
a4e2242b8d | ||
|
|
c90f173821 | ||
|
|
e1e0ac2345 | ||
|
|
bdccf4e9fd | ||
|
|
11cf1928b5 | ||
|
|
5215c73166 | ||
|
|
895e774569 | ||
|
|
79460072bb | ||
|
|
41b3b0e82e | ||
|
|
9c99293c92 | ||
|
|
6aba4350ac | ||
|
|
046e126054 | ||
|
|
c2c7dde06c | ||
|
|
5fb1c11a96 | ||
|
|
3e39dbb298 | ||
|
|
e617740974 | ||
|
|
744c78abbb | ||
|
|
91c5869053 | ||
|
|
6d805b302c | ||
|
|
fb9f49b948 | ||
|
|
ef6717e59a | ||
|
|
ad988dbd1e | ||
|
|
3d01766f55 | ||
|
|
2414aa5848 | ||
|
|
0de1bd0da8 | ||
|
|
186ec5431d | ||
|
|
da57bfe8e7 | ||
|
|
c9bffc13b5 | ||
|
|
d8cc0acdd0 | ||
|
|
35e1411407 | ||
|
|
8f833388eb | ||
|
|
850e646ab9 | ||
|
|
728e02cab7 | ||
|
|
792164edd1 | ||
|
|
e3177e6837 | ||
|
|
42f2d2b337 | ||
|
|
9d7f4acaf1 | ||
|
|
9a1f600fc9 | ||
|
|
0f906ad623 | ||
|
|
09aa65c52a | ||
|
|
25227a09f7 | ||
|
|
c0694c589b | ||
|
|
819402d9f1 | ||
|
|
33bc3e2fe9 | ||
|
|
2b71b3f345 | ||
|
|
3bc28ba78c | ||
|
|
72df9cb457 | ||
|
|
98e5747fdc | ||
|
|
4460604dd3 | ||
|
|
b4be9118ad | ||
|
|
b46bf91575 | ||
|
|
3ad482351b | ||
|
|
03b1d15a8f | ||
|
|
52c7b04a01 | ||
|
|
1c0f873c9d | ||
|
|
8b68574820 | ||
|
|
bb01bb1aef | ||
|
|
8192a492d9 | ||
|
|
31e11b2563 | ||
|
|
5a36acea7b | ||
|
|
8ce620e2e6 | ||
|
|
7655c2b73e | ||
|
|
a33b4ad73d | ||
|
|
1a2410f541 | ||
|
|
a0cf5681c4 | ||
|
|
8c15df489b | ||
|
|
5a51d447fb | ||
|
|
b2a495e885 | ||
|
|
8d201cd1ad | ||
|
|
31f6f209e3 | ||
|
|
944fab36ac | ||
|
|
161eb302fd | ||
|
|
f494420509 | ||
|
|
9ba0d2eaf4 | ||
|
|
a655b79166 | ||
|
|
403f16b404 | ||
|
|
de29e8300a | ||
|
|
e2b26ffb0c | ||
|
|
12f0a9ae62 | ||
|
|
73d4da192d | ||
|
|
0b648f8613 | ||
|
|
516d72e83f | ||
|
|
a27f8b168a | ||
|
|
7040fe3e75 | ||
|
|
a8211b2e00 | ||
|
|
cce6122a63 | ||
|
|
40a2518ff9 | ||
|
|
345f45d327 | ||
|
|
1f94d7d1bc | ||
|
|
f1a6e409cb | ||
|
|
059d3aa04a | ||
|
|
948951d461 | ||
|
|
0f0bfb9f06 | ||
|
|
b778207af9 | ||
|
|
888f1f39db | ||
|
|
b49e48b467 | ||
|
|
759aa1b684 | ||
|
|
5041578768 | ||
|
|
b8f626513f | ||
|
|
3b4b0bad22 | ||
|
|
7d47cc52b6 | ||
|
|
27ed15a83e | ||
|
|
5498133627 | ||
|
|
ecc98573eb | ||
|
|
69907083f7 | ||
|
|
268eb1f7ba | ||
|
|
50507fc9bf | ||
|
|
09cc2dceda | ||
|
|
02449026b9 | ||
|
|
056f2c1161 | ||
|
|
94431df236 | ||
|
|
f373e08583 | ||
|
|
753b11deeb | ||
|
|
17f2ebc4de | ||
|
|
0da91e406e | ||
|
|
2c5559ed0b | ||
|
|
924d58603f | ||
|
|
d4581b839a |
@@ -19,3 +19,8 @@ rustflags = [
|
|||||||
# pthread_key_create() destructors and segfault after a DSO unloading
|
# pthread_key_create() destructors and segfault after a DSO unloading
|
||||||
[target.'cfg(all(target_env = "gnu", not(target_os = "windows")))']
|
[target.'cfg(all(target_env = "gnu", not(target_os = "windows")))']
|
||||||
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]
|
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]
|
||||||
|
|
||||||
|
# Temporary local llm_adapter override.
|
||||||
|
# Uncomment when verifying AFFiNE against the sibling llm_adapter workspace.
|
||||||
|
# [patch.crates-io]
|
||||||
|
# llm_adapter = { path = "../llm_adapter" }
|
||||||
|
|||||||
@@ -197,8 +197,8 @@
|
|||||||
"properties": {
|
"properties": {
|
||||||
"SMTP.name": {
|
"SMTP.name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Name of the email server (e.g. your domain name)\n@default \"AFFiNE Server\"\n@environment `MAILER_SERVERNAME`",
|
"description": "Hostname used for SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.\n@default \"\"\n@environment `MAILER_SERVERNAME`",
|
||||||
"default": "AFFiNE Server"
|
"default": ""
|
||||||
},
|
},
|
||||||
"SMTP.host": {
|
"SMTP.host": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -222,7 +222,7 @@
|
|||||||
},
|
},
|
||||||
"SMTP.sender": {
|
"SMTP.sender": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"AFFiNE Self Hosted <noreply@example.com>\"\n@environment `MAILER_SENDER`",
|
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"AFFiNE Self Hosted <noreply@example.com>\"\n@environment `MAILER_SENDER`",
|
||||||
"default": "AFFiNE Self Hosted <noreply@example.com>"
|
"default": "AFFiNE Self Hosted <noreply@example.com>"
|
||||||
},
|
},
|
||||||
"SMTP.ignoreTLS": {
|
"SMTP.ignoreTLS": {
|
||||||
@@ -237,8 +237,8 @@
|
|||||||
},
|
},
|
||||||
"fallbackSMTP.name": {
|
"fallbackSMTP.name": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Name of the fallback email server (e.g. your domain name)\n@default \"AFFiNE Server\"",
|
"description": "Hostname used for fallback SMTP HELO/EHLO (e.g. mail.example.com). Leave empty to use the system hostname.\n@default \"\"",
|
||||||
"default": "AFFiNE Server"
|
"default": ""
|
||||||
},
|
},
|
||||||
"fallbackSMTP.host": {
|
"fallbackSMTP.host": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
@@ -262,7 +262,7 @@
|
|||||||
},
|
},
|
||||||
"fallbackSMTP.sender": {
|
"fallbackSMTP.sender": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"\"",
|
"description": "Sender of all the emails (e.g. \"AFFiNE Self Hosted <noreply@example.com>\")\n@default \"\"",
|
||||||
"default": ""
|
"default": ""
|
||||||
},
|
},
|
||||||
"fallbackSMTP.ignoreTLS": {
|
"fallbackSMTP.ignoreTLS": {
|
||||||
@@ -337,8 +337,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -348,6 +382,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -369,8 +406,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -380,6 +451,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -458,8 +532,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -469,6 +577,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -490,8 +601,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -501,6 +646,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -634,6 +782,45 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"telemetry": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Configuration for telemetry module",
|
||||||
|
"properties": {
|
||||||
|
"allowedOrigin": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "Allowed origins for telemetry collection.\n@default [\"localhost\",\"127.0.0.1\"]",
|
||||||
|
"default": [
|
||||||
|
"localhost",
|
||||||
|
"127.0.0.1"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"ga4.measurementId": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "GA4 Measurement ID for Measurement Protocol.\n@default \"\"\n@environment `GA4_MEASUREMENT_ID`",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"ga4.apiSecret": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "GA4 API secret for Measurement Protocol.\n@default \"\"\n@environment `GA4_API_SECRET`",
|
||||||
|
"default": ""
|
||||||
|
},
|
||||||
|
"dedupe.ttlHours": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Telemetry dedupe TTL in hours.\n@default 24",
|
||||||
|
"default": 24
|
||||||
|
},
|
||||||
|
"dedupe.maxEntries": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Telemetry dedupe max entries.\n@default 100000",
|
||||||
|
"default": 100000
|
||||||
|
},
|
||||||
|
"batch.maxEvents": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Max events per telemetry batch.\n@default 25",
|
||||||
|
"default": 25
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"client": {
|
"client": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Configuration for client module",
|
"description": "Configuration for client module",
|
||||||
@@ -645,8 +832,8 @@
|
|||||||
},
|
},
|
||||||
"versionControl.requiredVersion": {
|
"versionControl.requiredVersion": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"description": "Allowed version range of the app that allowed to access the server. Requires 'client/versionControl.enabled' to be true to take effect.\n@default \">=0.20.0\"",
|
"description": "Allowed version range of the app that allowed to access the server. Requires 'client/versionControl.enabled' to be true to take effect.\n@default \">=0.25.0\"",
|
||||||
"default": ">=0.20.0"
|
"default": ">=0.25.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -681,6 +868,72 @@
|
|||||||
"externalWebhookUrl": "",
|
"externalWebhookUrl": "",
|
||||||
"webhookVerificationToken": ""
|
"webhookVerificationToken": ""
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"caldav": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "CalDAV integration config\n@default {\"enabled\":false,\"allowCustomProvider\":false,\"providers\":[],\"allowInsecureHttp\":false,\"allowedHosts\":[],\"blockPrivateNetwork\":true,\"requestTimeoutMs\":10000,\"maxRedirects\":5}",
|
||||||
|
"properties": {
|
||||||
|
"enabled": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"allowCustomProvider": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"providers": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"label": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"serverUrl": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"authType": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"requiresAppPassword": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"docsUrl": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"allowInsecureHttp": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"allowedHosts": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"blockPrivateNetwork": {
|
||||||
|
"type": "boolean"
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number"
|
||||||
|
},
|
||||||
|
"maxRedirects": {
|
||||||
|
"type": "number"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"default": {
|
||||||
|
"enabled": false,
|
||||||
|
"allowCustomProvider": false,
|
||||||
|
"providers": [],
|
||||||
|
"allowInsecureHttp": false,
|
||||||
|
"allowedHosts": [],
|
||||||
|
"blockPrivateNetwork": true,
|
||||||
|
"requestTimeoutMs": 10000,
|
||||||
|
"maxRedirects": 5
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -718,7 +971,7 @@
|
|||||||
},
|
},
|
||||||
"scenarios": {
|
"scenarios": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "Use custom models in scenarios and override default settings.\n@default {\"override_enabled\":false,\"scenarios\":{\"audio_transcribing\":\"gemini-2.5-flash\",\"chat\":\"gemini-2.5-flash\",\"embedding\":\"gemini-embedding-001\",\"image\":\"gpt-image-1\",\"rerank\":\"gpt-4.1\",\"coding\":\"claude-sonnet-4-5@20250929\",\"complex_text_generation\":\"gpt-4o-2024-08-06\",\"quick_decision_making\":\"gpt-5-mini\",\"quick_text_generation\":\"gemini-2.5-flash\",\"polish_and_summarize\":\"gemini-2.5-flash\"}}",
|
"description": "Use custom models in scenarios and override default settings.\n@default {\"override_enabled\":false,\"scenarios\":{\"audio_transcribing\":\"gemini-2.5-flash\",\"chat\":\"gemini-2.5-flash\",\"embedding\":\"gemini-embedding-001\",\"image\":\"gpt-image-1\",\"coding\":\"claude-sonnet-4-5@20250929\",\"complex_text_generation\":\"gpt-5-mini\",\"quick_decision_making\":\"gpt-5-mini\",\"quick_text_generation\":\"gemini-2.5-flash\",\"polish_and_summarize\":\"gemini-2.5-flash\"}}",
|
||||||
"default": {
|
"default": {
|
||||||
"override_enabled": false,
|
"override_enabled": false,
|
||||||
"scenarios": {
|
"scenarios": {
|
||||||
@@ -726,15 +979,24 @@
|
|||||||
"chat": "gemini-2.5-flash",
|
"chat": "gemini-2.5-flash",
|
||||||
"embedding": "gemini-embedding-001",
|
"embedding": "gemini-embedding-001",
|
||||||
"image": "gpt-image-1",
|
"image": "gpt-image-1",
|
||||||
"rerank": "gpt-4.1",
|
|
||||||
"coding": "claude-sonnet-4-5@20250929",
|
"coding": "claude-sonnet-4-5@20250929",
|
||||||
"complex_text_generation": "gpt-4o-2024-08-06",
|
"complex_text_generation": "gpt-5-mini",
|
||||||
"quick_decision_making": "gpt-5-mini",
|
"quick_decision_making": "gpt-5-mini",
|
||||||
"quick_text_generation": "gemini-2.5-flash",
|
"quick_text_generation": "gemini-2.5-flash",
|
||||||
"polish_and_summarize": "gemini-2.5-flash"
|
"polish_and_summarize": "gemini-2.5-flash"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"providers.profiles": {
|
||||||
|
"type": "array",
|
||||||
|
"description": "The profile list for copilot providers.\n@default []",
|
||||||
|
"default": []
|
||||||
|
},
|
||||||
|
"providers.defaults": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "The default provider ids for model output types and global fallback.\n@default {}",
|
||||||
|
"default": {}
|
||||||
|
},
|
||||||
"providers.openai": {
|
"providers.openai": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the openai provider.\n@default {\"apiKey\":\"\",\"baseURL\":\"https://api.openai.com/v1\"}\n@link https://github.com/openai/openai-node",
|
"description": "The config for the openai provider.\n@default {\"apiKey\":\"\",\"baseURL\":\"https://api.openai.com/v1\"}\n@link https://github.com/openai/openai-node",
|
||||||
@@ -902,8 +1164,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -913,6 +1209,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -934,8 +1233,42 @@
|
|||||||
},
|
},
|
||||||
"config": {
|
"config": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The config for the s3 compatible storage provider. directly passed to aws-sdk client.\n@link https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html",
|
"description": "The config for the S3 compatible storage provider.",
|
||||||
"properties": {
|
"properties": {
|
||||||
|
"endpoint": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The S3 compatible endpoint. Example: \"https://s3.us-east-1.amazonaws.com\" or \"https://<account>.r2.cloudflarestorage.com\"."
|
||||||
|
},
|
||||||
|
"region": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "The region for the storage provider. Example: \"us-east-1\" or \"auto\" for R2."
|
||||||
|
},
|
||||||
|
"forcePathStyle": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to use path-style bucket addressing."
|
||||||
|
},
|
||||||
|
"requestTimeoutMs": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Request timeout in milliseconds."
|
||||||
|
},
|
||||||
|
"minPartSize": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Minimum multipart part size in bytes."
|
||||||
|
},
|
||||||
|
"presign": {
|
||||||
|
"type": "object",
|
||||||
|
"description": "Presigned URL behavior configuration.",
|
||||||
|
"properties": {
|
||||||
|
"expiresInSeconds": {
|
||||||
|
"type": "number",
|
||||||
|
"description": "Expiration time in seconds for presigned URLs."
|
||||||
|
},
|
||||||
|
"signContentTypeForPut": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Whether to sign Content-Type for presigned PUT."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"credentials": {
|
"credentials": {
|
||||||
"type": "object",
|
"type": "object",
|
||||||
"description": "The credentials for the s3 compatible storage provider.",
|
"description": "The credentials for the s3 compatible storage provider.",
|
||||||
@@ -945,6 +1278,9 @@
|
|||||||
},
|
},
|
||||||
"secretAccessKey": {
|
"secretAccessKey": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
},
|
||||||
|
"sessionToken": {
|
||||||
|
"type": "string"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
26
.dockerignore
Normal file
26
.dockerignore
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
.git
|
||||||
|
.github/**/*.md
|
||||||
|
.gitignore
|
||||||
|
|
||||||
|
# Local dependency/build artifacts
|
||||||
|
/node_modules
|
||||||
|
/target
|
||||||
|
|
||||||
|
# Yarn v4 artifacts (not needed for image packaging)
|
||||||
|
/.yarn/cache
|
||||||
|
/.yarn/unplugged
|
||||||
|
/.yarn/install-state.gz
|
||||||
|
/.pnp.*
|
||||||
|
|
||||||
|
# Test artifacts
|
||||||
|
/test-results
|
||||||
|
/playwright-report
|
||||||
|
/coverage
|
||||||
|
/.coverage
|
||||||
|
|
||||||
|
# OS noise
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Sourcemaps (keep server sourcemap for backend stacktraces)
|
||||||
|
**/*.map
|
||||||
|
!packages/backend/server/dist/main.js.map
|
||||||
1
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
1
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
@@ -2,7 +2,6 @@ name: Feature Request
|
|||||||
description: Suggest a feature or improvement
|
description: Suggest a feature or improvement
|
||||||
title: '[Feature Request]: '
|
title: '[Feature Request]: '
|
||||||
labels: ['feat', 'story']
|
labels: ['feat', 'story']
|
||||||
assignees: ['hwangdev97']
|
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
attributes:
|
attributes:
|
||||||
|
|||||||
4
.github/ISSUE_TEMPLATE/config.yml
vendored
4
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -3,6 +3,6 @@ contact_links:
|
|||||||
- name: Something else?
|
- name: Something else?
|
||||||
url: https://github.com/toeverything/AFFiNE/discussions
|
url: https://github.com/toeverything/AFFiNE/discussions
|
||||||
about: Feel free to ask and answer questions over in GitHub Discussions
|
about: Feel free to ask and answer questions over in GitHub Discussions
|
||||||
- name: AFFiNE Community Support
|
- name: AFFiNE Community Support (Discord)
|
||||||
url: https://community.affine.pro
|
url: https://affine.pro/redirect/discord
|
||||||
about: AFFiNE Community - a place to ask, learn and engage with others
|
about: AFFiNE Community - a place to ask, learn and engage with others
|
||||||
|
|||||||
20
.github/actionlint.yaml
vendored
Normal file
20
.github/actionlint.yaml
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
self-hosted-runner:
|
||||||
|
# Labels of self-hosted runner in array of strings.
|
||||||
|
labels:
|
||||||
|
- win-signer
|
||||||
|
|
||||||
|
# Configuration variables in array of strings defined in your repository or
|
||||||
|
# organization. `null` means disabling configuration variables check.
|
||||||
|
# Empty array means no configuration variable is allowed.
|
||||||
|
config-variables: null
|
||||||
|
|
||||||
|
# Configuration for file paths. The keys are glob patterns to match to file
|
||||||
|
# paths relative to the repository root. The values are the configurations for
|
||||||
|
# the file paths. Note that the path separator is always '/'.
|
||||||
|
# The following configurations are available.
|
||||||
|
#
|
||||||
|
# "ignore" is an array of regular expression patterns. Matched error messages
|
||||||
|
# are ignored. This is similar to the "-ignore" command line option.
|
||||||
|
paths:
|
||||||
|
# .github/workflows/**/*.yml:
|
||||||
|
# ignore: []
|
||||||
10
.github/actions/build-rust/action.yml
vendored
10
.github/actions/build-rust/action.yml
vendored
@@ -50,8 +50,14 @@ runs:
|
|||||||
# https://github.com/tree-sitter/tree-sitter/issues/4186
|
# https://github.com/tree-sitter/tree-sitter/issues/4186
|
||||||
# pass -D_BSD_SOURCE to clang to fix the tree-sitter build issue
|
# pass -D_BSD_SOURCE to clang to fix the tree-sitter build issue
|
||||||
run: |
|
run: |
|
||||||
echo "CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
if [[ "${{ inputs.target }}" == "aarch64-unknown-linux-gnu" ]]; then
|
||||||
echo "TARGET_CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
# napi cross-toolchain 1.0.3 headers miss AT_HWCAP2 in elf.h
|
||||||
|
echo "CC=clang -D_BSD_SOURCE -DAT_HWCAP2=26" >> "$GITHUB_ENV"
|
||||||
|
echo "TARGET_CC=clang -D_BSD_SOURCE -DAT_HWCAP2=26" >> "$GITHUB_ENV"
|
||||||
|
else
|
||||||
|
echo "CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
||||||
|
echo "TARGET_CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Cache cargo
|
- name: Cache cargo
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: Swatinem/rust-cache@v2
|
||||||
|
|||||||
99
.github/actions/deploy/deploy.mjs
vendored
99
.github/actions/deploy/deploy.mjs
vendored
@@ -25,47 +25,30 @@ const buildType = BUILD_TYPE || 'canary';
|
|||||||
|
|
||||||
const isProduction = buildType === 'stable';
|
const isProduction = buildType === 'stable';
|
||||||
const isBeta = buildType === 'beta';
|
const isBeta = buildType === 'beta';
|
||||||
|
const isCanary = buildType === 'canary';
|
||||||
const isInternal = buildType === 'internal';
|
const isInternal = buildType === 'internal';
|
||||||
|
const isSpotEnabled = isBeta || isCanary;
|
||||||
|
|
||||||
const replicaConfig = {
|
const replicaConfig = {
|
||||||
stable: {
|
stable: {
|
||||||
web: 2,
|
front: Number(process.env.PRODUCTION_FRONT_REPLICA) || 2,
|
||||||
graphql: Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 2,
|
graphql: Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 2,
|
||||||
sync: Number(process.env.PRODUCTION_SYNC_REPLICA) || 2,
|
|
||||||
renderer: Number(process.env.PRODUCTION_RENDERER_REPLICA) || 2,
|
|
||||||
doc: Number(process.env.PRODUCTION_DOC_REPLICA) || 2,
|
|
||||||
},
|
},
|
||||||
beta: {
|
beta: {
|
||||||
web: 1,
|
front: Number(process.env.BETA_FRONT_REPLICA) || 1,
|
||||||
graphql: Number(process.env.BETA_GRAPHQL_REPLICA) || 1,
|
graphql: Number(process.env.BETA_GRAPHQL_REPLICA) || 1,
|
||||||
sync: Number(process.env.BETA_SYNC_REPLICA) || 1,
|
|
||||||
renderer: Number(process.env.BETA_RENDERER_REPLICA) || 1,
|
|
||||||
doc: Number(process.env.BETA_DOC_REPLICA) || 1,
|
|
||||||
},
|
|
||||||
canary: {
|
|
||||||
web: 1,
|
|
||||||
graphql: 1,
|
|
||||||
sync: 1,
|
|
||||||
renderer: 1,
|
|
||||||
doc: 1,
|
|
||||||
},
|
},
|
||||||
|
canary: { front: 1, graphql: 1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
const cpuConfig = {
|
const cpuConfig = {
|
||||||
beta: {
|
beta: { front: '1', graphql: '1' },
|
||||||
web: '300m',
|
canary: { front: '500m', graphql: '1' },
|
||||||
graphql: '1',
|
};
|
||||||
sync: '1',
|
|
||||||
doc: '1',
|
const memoryConfig = {
|
||||||
renderer: '300m',
|
beta: { front: '2Gi', graphql: '1Gi' },
|
||||||
},
|
canary: { front: '512Mi', graphql: '512Mi' },
|
||||||
canary: {
|
|
||||||
web: '300m',
|
|
||||||
graphql: '1',
|
|
||||||
sync: '1',
|
|
||||||
doc: '1',
|
|
||||||
renderer: '300m',
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const createHelmCommand = ({ isDryRun }) => {
|
const createHelmCommand = ({ isDryRun }) => {
|
||||||
@@ -89,33 +72,48 @@ const createHelmCommand = ({ isDryRun }) => {
|
|||||||
`--set-string global.indexer.endpoint="${AFFINE_INDEXER_SEARCH_ENDPOINT}"`,
|
`--set-string global.indexer.endpoint="${AFFINE_INDEXER_SEARCH_ENDPOINT}"`,
|
||||||
`--set-string global.indexer.apiKey="${AFFINE_INDEXER_SEARCH_API_KEY}"`,
|
`--set-string global.indexer.apiKey="${AFFINE_INDEXER_SEARCH_API_KEY}"`,
|
||||||
];
|
];
|
||||||
|
const cloudSqlNodeSelector = isBeta
|
||||||
|
? `{ \\"iam.gke.io/gke-metadata-server-enabled\\": \\"true\\", \\"cloud.google.com/gke-spot\\": \\"true\\" }`
|
||||||
|
: `{ \\"iam.gke.io/gke-metadata-server-enabled\\": \\"true\\" }`;
|
||||||
const serviceAnnotations = [
|
const serviceAnnotations = [
|
||||||
`--set-json web.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
`--set-json front.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
||||||
`--set-json graphql.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
`--set-json graphql.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
||||||
`--set-json sync.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
|
||||||
`--set-json doc.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
|
||||||
].concat(
|
].concat(
|
||||||
isProduction || isBeta || isInternal
|
isProduction || isBeta || isInternal
|
||||||
? [
|
? [
|
||||||
`--set-json web.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
`--set-json front.services.web.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
||||||
|
`--set-json front.services.sync.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
||||||
|
`--set-json front.services.renderer.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
||||||
`--set-json graphql.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
`--set-json graphql.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
||||||
`--set-json sync.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
|
||||||
`--set-json cloud-sql-proxy.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${CLOUD_SQL_IAM_ACCOUNT}\\" }"`,
|
`--set-json cloud-sql-proxy.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${CLOUD_SQL_IAM_ACCOUNT}\\" }"`,
|
||||||
`--set-json cloud-sql-proxy.nodeSelector="{ \\"iam.gke.io/gke-metadata-server-enabled\\": \\"true\\" }"`,
|
`--set-json cloud-sql-proxy.nodeSelector="${cloudSqlNodeSelector}"`,
|
||||||
]
|
]
|
||||||
: []
|
: []
|
||||||
);
|
);
|
||||||
|
const spotNodeSelector = `{ \\"cloud.google.com/gke-spot\\": \\"true\\" }`;
|
||||||
const cpu = cpuConfig[buildType];
|
const spotScheduling = isSpotEnabled
|
||||||
const resources = cpu
|
|
||||||
? [
|
? [
|
||||||
`--set web.resources.requests.cpu="${cpu.web}"`,
|
`--set-json front.nodeSelector="${spotNodeSelector}"`,
|
||||||
`--set graphql.resources.requests.cpu="${cpu.graphql}"`,
|
`--set-json graphql.nodeSelector="${spotNodeSelector}"`,
|
||||||
`--set sync.resources.requests.cpu="${cpu.sync}"`,
|
|
||||||
`--set doc.resources.requests.cpu="${cpu.doc}"`,
|
|
||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
|
|
||||||
|
const cpu = cpuConfig[buildType];
|
||||||
|
const memory = memoryConfig[buildType];
|
||||||
|
let resources = [];
|
||||||
|
if (cpu) {
|
||||||
|
resources = resources.concat([
|
||||||
|
`--set front.resources.requests.cpu="${cpu.front}"`,
|
||||||
|
`--set graphql.resources.requests.cpu="${cpu.graphql}"`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
if (memory) {
|
||||||
|
resources = resources.concat([
|
||||||
|
`--set front.resources.requests.memory="${memory.front}"`,
|
||||||
|
`--set graphql.resources.requests.memory="${memory.graphql}"`,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
const replica = replicaConfig[buildType] || replicaConfig.canary;
|
const replica = replicaConfig[buildType] || replicaConfig.canary;
|
||||||
|
|
||||||
const namespace = isProduction
|
const namespace = isProduction
|
||||||
@@ -130,6 +128,7 @@ const createHelmCommand = ({ isDryRun }) => {
|
|||||||
.split(',')
|
.split(',')
|
||||||
.map(host => host.trim())
|
.map(host => host.trim())
|
||||||
.filter(host => host);
|
.filter(host => host);
|
||||||
|
const primaryHost = hosts[0] || '0.0.0.0';
|
||||||
const deployCommand = [
|
const deployCommand = [
|
||||||
`helm upgrade --install affine .github/helm/affine`,
|
`helm upgrade --install affine .github/helm/affine`,
|
||||||
`--namespace ${namespace}`,
|
`--namespace ${namespace}`,
|
||||||
@@ -144,20 +143,14 @@ const createHelmCommand = ({ isDryRun }) => {
|
|||||||
`--set-string global.version="${APP_VERSION}"`,
|
`--set-string global.version="${APP_VERSION}"`,
|
||||||
...redisAndPostgres,
|
...redisAndPostgres,
|
||||||
...indexerOptions,
|
...indexerOptions,
|
||||||
`--set web.replicaCount=${replica.web}`,
|
`--set front.replicaCount=${replica.front}`,
|
||||||
`--set-string web.image.tag="${imageTag}"`,
|
`--set-string front.image.tag="${imageTag}"`,
|
||||||
|
`--set-string front.app.host="${primaryHost}"`,
|
||||||
`--set graphql.replicaCount=${replica.graphql}`,
|
`--set graphql.replicaCount=${replica.graphql}`,
|
||||||
`--set-string graphql.image.tag="${imageTag}"`,
|
`--set-string graphql.image.tag="${imageTag}"`,
|
||||||
`--set graphql.app.host=${hosts[0]}`,
|
`--set-string graphql.app.host="${primaryHost}"`,
|
||||||
`--set sync.replicaCount=${replica.sync}`,
|
|
||||||
`--set-string sync.image.tag="${imageTag}"`,
|
|
||||||
`--set-string renderer.image.tag="${imageTag}"`,
|
|
||||||
`--set renderer.app.host=${hosts[0]}`,
|
|
||||||
`--set renderer.replicaCount=${replica.renderer}`,
|
|
||||||
`--set-string doc.image.tag="${imageTag}"`,
|
|
||||||
`--set doc.app.host=${hosts[0]}`,
|
|
||||||
`--set doc.replicaCount=${replica.doc}`,
|
|
||||||
...serviceAnnotations,
|
...serviceAnnotations,
|
||||||
|
...spotScheduling,
|
||||||
...resources,
|
...resources,
|
||||||
`--timeout 10m`,
|
`--timeout 10m`,
|
||||||
flag,
|
flag,
|
||||||
|
|||||||
14
.github/actions/setup-node/action.yml
vendored
14
.github/actions/setup-node/action.yml
vendored
@@ -53,7 +53,7 @@ runs:
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
registry-url: https://npm.pkg.github.com
|
registry-url: https://npm.pkg.github.com
|
||||||
@@ -93,7 +93,7 @@ runs:
|
|||||||
run: node -e "const p = $(yarn config cacheFolder --json).effective; console.log('yarn_global_cache=' + p)" >> $GITHUB_OUTPUT
|
run: node -e "const p = $(yarn config cacheFolder --json).effective; console.log('yarn_global_cache=' + p)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Cache non-full yarn cache on Linux
|
- name: Cache non-full yarn cache on Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
if: ${{ inputs.full-cache != 'true' && runner.os == 'Linux' }}
|
if: ${{ inputs.full-cache != 'true' && runner.os == 'Linux' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -105,7 +105,7 @@ runs:
|
|||||||
# and the decompression performance on Windows is very terrible
|
# and the decompression performance on Windows is very terrible
|
||||||
# so we reduce the number of cached files on non-Linux systems by remove node_modules from cache path.
|
# so we reduce the number of cached files on non-Linux systems by remove node_modules from cache path.
|
||||||
- name: Cache non-full yarn cache on non-Linux
|
- name: Cache non-full yarn cache on non-Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
if: ${{ inputs.full-cache != 'true' && runner.os != 'Linux' }}
|
if: ${{ inputs.full-cache != 'true' && runner.os != 'Linux' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -113,7 +113,7 @@ runs:
|
|||||||
key: node_modules-cache-${{ github.job }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-${{ github.job }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
||||||
|
|
||||||
- name: Cache full yarn cache on Linux
|
- name: Cache full yarn cache on Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
if: ${{ inputs.full-cache == 'true' && runner.os == 'Linux' }}
|
if: ${{ inputs.full-cache == 'true' && runner.os == 'Linux' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -122,7 +122,7 @@ runs:
|
|||||||
key: node_modules-cache-full-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-full-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
||||||
|
|
||||||
- name: Cache full yarn cache on non-Linux
|
- name: Cache full yarn cache on non-Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v5
|
||||||
if: ${{ inputs.full-cache == 'true' && runner.os != 'Linux' }}
|
if: ${{ inputs.full-cache == 'true' && runner.os != 'Linux' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
@@ -154,7 +154,7 @@ runs:
|
|||||||
# Note: Playwright's cache directory is hard coded because that's what it
|
# Note: Playwright's cache directory is hard coded because that's what it
|
||||||
# says to do in the docs. There doesn't appear to be a command that prints
|
# says to do in the docs. There doesn't appear to be a command that prints
|
||||||
# it out for us.
|
# it out for us.
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v5
|
||||||
id: playwright-cache
|
id: playwright-cache
|
||||||
if: ${{ inputs.playwright-install == 'true' }}
|
if: ${{ inputs.playwright-install == 'true' }}
|
||||||
with:
|
with:
|
||||||
@@ -189,7 +189,7 @@ runs:
|
|||||||
run: |
|
run: |
|
||||||
echo "version=$(yarn why --json electron | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
echo "version=$(yarn why --json electron | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- uses: actions/cache@v4
|
- uses: actions/cache@v5
|
||||||
id: electron-cache
|
id: electron-cache
|
||||||
if: ${{ inputs.electron-install == 'true' }}
|
if: ${{ inputs.electron-install == 'true' }}
|
||||||
with:
|
with:
|
||||||
|
|||||||
1
.github/actions/setup-version/action.yml
vendored
1
.github/actions/setup-version/action.yml
vendored
@@ -7,7 +7,6 @@ inputs:
|
|||||||
ios-app-version:
|
ios-app-version:
|
||||||
description: 'iOS App Store Version (Optional, use App version if empty)'
|
description: 'iOS App Store Version (Optional, use App version if empty)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
|
||||||
runs:
|
runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
13
.github/deployment/front/Dockerfile
vendored
13
.github/deployment/front/Dockerfile
vendored
@@ -1,13 +0,0 @@
|
|||||||
FROM openresty/openresty:1.27.1.1-0-buster
|
|
||||||
WORKDIR /app
|
|
||||||
COPY ./packages/frontend/apps/web/dist ./dist
|
|
||||||
COPY ./packages/frontend/admin/dist ./admin
|
|
||||||
COPY ./packages/frontend/apps/mobile/dist ./mobile
|
|
||||||
COPY ./.github/deployment/front/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
|
|
||||||
COPY ./.github/deployment/front/affine.nginx.conf /etc/nginx/conf.d/affine.nginx.conf
|
|
||||||
|
|
||||||
RUN mkdir -p /var/log/nginx && \
|
|
||||||
rm /etc/nginx/conf.d/default.conf
|
|
||||||
|
|
||||||
EXPOSE 8080
|
|
||||||
CMD ["/usr/local/openresty/bin/openresty", "-g", "daemon off;"]
|
|
||||||
42
.github/deployment/front/affine.nginx.conf
vendored
42
.github/deployment/front/affine.nginx.conf
vendored
@@ -1,42 +0,0 @@
|
|||||||
server {
|
|
||||||
listen 8080;
|
|
||||||
location /admin {
|
|
||||||
root /app/;
|
|
||||||
index index.html;
|
|
||||||
try_files $uri/index.html $uri/ $uri /admin/index.html;
|
|
||||||
}
|
|
||||||
|
|
||||||
set $app_root_path /app/dist/;
|
|
||||||
set $mobile_root /app/dist/;
|
|
||||||
set_by_lua $affine_env 'return os.getenv("AFFINE_ENV")';
|
|
||||||
|
|
||||||
if ($affine_env = "dev") {
|
|
||||||
set $mobile_root /app/mobile/;
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://gist.github.com/mariusom/6683dc52b1cad1a1f372e908bdb209d0
|
|
||||||
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
|
|
||||||
set $app_root_path $mobile_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
|
|
||||||
set $app_root_path $mobile_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ ^/(_plugin|assets|imgs|js|plugins|static)/ {
|
|
||||||
root $app_root_path;
|
|
||||||
try_files $uri $uri/ =404;
|
|
||||||
}
|
|
||||||
|
|
||||||
location / {
|
|
||||||
root $app_root_path;
|
|
||||||
index index.html;
|
|
||||||
try_files $uri $uri/ /index.html;
|
|
||||||
add_header Cache-Control "private, no-cache, no-store, max-age=0, must-revalidate";
|
|
||||||
}
|
|
||||||
|
|
||||||
error_page 404 /404.html;
|
|
||||||
location = /404.html {
|
|
||||||
internal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
.github/deployment/front/nginx.conf
vendored
15
.github/deployment/front/nginx.conf
vendored
@@ -1,15 +0,0 @@
|
|||||||
worker_processes 4;
|
|
||||||
error_log /var/log/nginx/error.log warn;
|
|
||||||
pcre_jit on;
|
|
||||||
env AFFINE_ENV;
|
|
||||||
events {
|
|
||||||
worker_connections 1024;
|
|
||||||
}
|
|
||||||
http {
|
|
||||||
include mime.types;
|
|
||||||
log_format main '$remote_addr [$time_local] "$request" '
|
|
||||||
'$status $body_bytes_sent "$http_referer" '
|
|
||||||
'"$http_user_agent" "$http_x_forwarded_for"';
|
|
||||||
access_log /var/log/nginx/access.log main;
|
|
||||||
include /etc/nginx/conf.d/*.conf;
|
|
||||||
}
|
|
||||||
21
.github/deployment/node/Dockerfile
vendored
21
.github/deployment/node/Dockerfile
vendored
@@ -1,11 +1,28 @@
|
|||||||
FROM node:22-bookworm-slim
|
# syntax=docker/dockerfile:1.7
|
||||||
|
|
||||||
|
FROM node:22-bookworm-slim AS assets
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
COPY ./packages/backend/server /app
|
COPY ./packages/backend/server /app
|
||||||
COPY ./packages/frontend/apps/web/dist /app/static
|
COPY ./packages/frontend/apps/web/dist /app/static
|
||||||
COPY ./packages/frontend/admin/dist /app/static/admin
|
COPY ./packages/frontend/admin/dist /app/static/admin
|
||||||
COPY ./packages/frontend/apps/mobile/dist /app/static/mobile
|
COPY ./packages/frontend/apps/mobile/dist /app/static/mobile
|
||||||
|
|
||||||
|
# Keep server sourcemap for stacktraces, but don't ship frontend/node_modules sourcemaps.
|
||||||
|
ARG TARGETARCH
|
||||||
|
ARG TARGETVARIANT
|
||||||
|
# Needed for Prisma engine resolution (and potential engine download during cleanup).
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends openssl ca-certificates && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN AFFINE_DOCKER_CLEAN=1 TARGETARCH="${TARGETARCH}" TARGETVARIANT="${TARGETVARIANT}" node ./scripts/docker-clean.mjs
|
||||||
|
|
||||||
|
FROM node:22-bookworm-slim
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
COPY --from=assets /app /app
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y --no-install-recommends openssl libjemalloc2 && \
|
apt-get install -y --no-install-recommends openssl libjemalloc2 && \
|
||||||
rm -rf /var/lib/apt/lists/*
|
rm -rf /var/lib/apt/lists/*
|
||||||
@@ -13,4 +30,6 @@ RUN apt-get update && \
|
|||||||
# Enable jemalloc by preloading the library
|
# Enable jemalloc by preloading the library
|
||||||
ENV LD_PRELOAD=libjemalloc.so.2
|
ENV LD_PRELOAD=libjemalloc.so.2
|
||||||
|
|
||||||
|
EXPOSE 3010
|
||||||
|
|
||||||
CMD ["node", "./dist/main.js"]
|
CMD ["node", "./dist/main.js"]
|
||||||
|
|||||||
2
.github/helm/affine/Chart.yaml
vendored
2
.github/helm/affine/Chart.yaml
vendored
@@ -3,4 +3,4 @@ name: affine
|
|||||||
description: AFFiNE cloud chart
|
description: AFFiNE cloud chart
|
||||||
type: application
|
type: application
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
appVersion: "0.26.0"
|
appVersion: "0.26.3"
|
||||||
|
|||||||
2
.github/helm/affine/charts/doc/Chart.yaml
vendored
2
.github/helm/affine/charts/doc/Chart.yaml
vendored
@@ -3,7 +3,7 @@ name: doc
|
|||||||
description: AFFiNE doc server
|
description: AFFiNE doc server
|
||||||
type: application
|
type: application
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
appVersion: "0.26.0"
|
appVersion: "0.26.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: gcloud-sql-proxy
|
- name: gcloud-sql-proxy
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "doc.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "doc.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "doc.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "doc.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "doc.chart" . }}
|
|
||||||
{{ include "doc.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
monitoring: enabled
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "doc.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "doc.fullname" .) .Values.global.docService.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.global.docService.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "doc.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "doc.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "doc.serviceAccountName" . }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_PRIVATE_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.global.secret.secretName }}"
|
|
||||||
key: key
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: "{{ .Values.env }}"
|
|
||||||
- name: NODE_OPTIONS
|
|
||||||
value: "--max-old-space-size=4096"
|
|
||||||
- name: NO_COLOR
|
|
||||||
value: "1"
|
|
||||||
- name: DEPLOYMENT_TYPE
|
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
|
||||||
value: "doc"
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pg-postgresql
|
|
||||||
key: postgres-password
|
|
||||||
- name: DATABASE_URL
|
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
|
||||||
- name: REDIS_SERVER_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: REDIS_SERVER_HOST
|
|
||||||
value: "{{ .Values.global.redis.host }}"
|
|
||||||
- name: REDIS_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.redis.port }}"
|
|
||||||
- name: REDIS_SERVER_USER
|
|
||||||
value: "{{ .Values.global.redis.username }}"
|
|
||||||
- name: REDIS_SERVER_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis
|
|
||||||
key: redis-password
|
|
||||||
- name: REDIS_SERVER_DATABASE
|
|
||||||
value: "{{ .Values.global.redis.database }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: indexer
|
|
||||||
key: indexer-apiKey
|
|
||||||
- name: AFFINE_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.docService.port }}"
|
|
||||||
- name: AFFINE_SERVER_SUB_PATH
|
|
||||||
value: "{{ .Values.app.path }}"
|
|
||||||
- name: AFFINE_SERVER_HOST
|
|
||||||
value: "{{ .Values.app.host }}"
|
|
||||||
- name: AFFINE_SERVER_HTTPS
|
|
||||||
value: "{{ .Values.app.https }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.global.docService.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "doc.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "doc.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "doc.fullname" . }}:{{ .Values.global.docService.port }}']
|
|
||||||
restartPolicy: Never
|
|
||||||
5
.github/helm/affine/charts/doc/values.yaml
vendored
5
.github/helm/affine/charts/doc/values.yaml
vendored
@@ -30,9 +30,12 @@ podSecurityContext:
|
|||||||
fsGroup: 2000
|
fsGroup: 2000
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
limits:
|
||||||
cpu: '1'
|
cpu: '1'
|
||||||
memory: 4Gi
|
memory: 4Gi
|
||||||
|
requests:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 2Gi
|
||||||
|
|
||||||
probe:
|
probe:
|
||||||
initialDelaySeconds: 20
|
initialDelaySeconds: 20
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
apiVersion: v2
|
apiVersion: v2
|
||||||
name: sync
|
name: front
|
||||||
description: AFFiNE Sync Server
|
description: AFFiNE front server
|
||||||
type: application
|
type: application
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
appVersion: "0.26.0"
|
appVersion: "0.26.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: gcloud-sql-proxy
|
- name: gcloud-sql-proxy
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
1. Get the application URL by running these commands:
|
1. Get the application URL by running these commands:
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
{{- if contains "NodePort" .Values.services.sync.type }}
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "web.fullname" . }})
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ .Values.services.sync.name }})
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
echo http://$NODE_IP:$NODE_PORT
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
{{- else if contains "LoadBalancer" .Values.services.sync.type }}
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "web.fullname" . }}'
|
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ .Values.services.sync.name }}'
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "web.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ .Values.services.sync.name }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
echo http://$SERVICE_IP:{{ .Values.services.sync.port }}
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
{{- else if contains "ClusterIP" .Values.services.sync.type }}
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "web.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "front.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
echo "Visit http://127.0.0.1:8080 to use your application"
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{{/*
|
{{/*
|
||||||
Expand the name of the chart.
|
Expand the name of the chart.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.name" -}}
|
{{- define "front.name" -}}
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ Create a default fully qualified app name.
|
|||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||||
If release name contains chart name it will be used as a full name.
|
If release name contains chart name it will be used as a full name.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.fullname" -}}
|
{{- define "front.fullname" -}}
|
||||||
{{- if .Values.fullnameOverride }}
|
{{- if .Values.fullnameOverride }}
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
@@ -26,16 +26,16 @@ If release name contains chart name it will be used as a full name.
|
|||||||
{{/*
|
{{/*
|
||||||
Create chart name and version as used by the chart label.
|
Create chart name and version as used by the chart label.
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.chart" -}}
|
{{- define "front.chart" -}}
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Common labels
|
Common labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.labels" -}}
|
{{- define "front.labels" -}}
|
||||||
helm.sh/chart: {{ include "web.chart" . }}
|
helm.sh/chart: {{ include "front.chart" . }}
|
||||||
{{ include "web.selectorLabels" . }}
|
{{ include "front.selectorLabels" . }}
|
||||||
{{- if .Chart.AppVersion }}
|
{{- if .Chart.AppVersion }}
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
@@ -46,17 +46,17 @@ monitoring: enabled
|
|||||||
{{/*
|
{{/*
|
||||||
Selector labels
|
Selector labels
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.selectorLabels" -}}
|
{{- define "front.selectorLabels" -}}
|
||||||
app.kubernetes.io/name: {{ include "web.name" . }}
|
app.kubernetes.io/name: {{ include "front.name" . }}
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
{{/*
|
{{/*
|
||||||
Create the name of the service account to use
|
Create the name of the service account to use
|
||||||
*/}}
|
*/}}
|
||||||
{{- define "web.serviceAccountName" -}}
|
{{- define "front.serviceAccountName" -}}
|
||||||
{{- if .Values.serviceAccount.create }}
|
{{- if .Values.serviceAccount.create }}
|
||||||
{{- default (include "web.fullname" .) .Values.serviceAccount.name }}
|
{{- default (include "front.fullname" .) .Values.serviceAccount.name }}
|
||||||
{{- else }}
|
{{- else }}
|
||||||
{{- default "default" .Values.serviceAccount.name }}
|
{{- default "default" .Values.serviceAccount.name }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
126
.github/helm/affine/charts/front/templates/deployment.yaml
vendored
Normal file
126
.github/helm/affine/charts/front/templates/deployment.yaml
vendored
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "front.fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "front.selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
{{- with .Values.podAnnotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
labels:
|
||||||
|
{{- include "front.selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
{{- with .Values.imagePullSecrets }}
|
||||||
|
imagePullSecrets:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
serviceAccountName: {{ include "front.serviceAccountName" . }}
|
||||||
|
securityContext:
|
||||||
|
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
env:
|
||||||
|
- name: AFFINE_PRIVATE_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.global.secret.secretName }}"
|
||||||
|
key: key
|
||||||
|
- name: NODE_ENV
|
||||||
|
value: "{{ .Values.env }}"
|
||||||
|
- name: NODE_OPTIONS
|
||||||
|
value: "{{ .Values.nodeOptions }}"
|
||||||
|
- name: NO_COLOR
|
||||||
|
value: "1"
|
||||||
|
- name: DEPLOYMENT_TYPE
|
||||||
|
value: "{{ .Values.global.deployment.type }}"
|
||||||
|
- name: DEPLOYMENT_PLATFORM
|
||||||
|
value: "{{ .Values.global.deployment.platform }}"
|
||||||
|
- name: SERVER_FLAVOR
|
||||||
|
value: "front"
|
||||||
|
- name: AFFINE_ENV
|
||||||
|
value: "{{ .Release.Namespace }}"
|
||||||
|
- name: DATABASE_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: pg-postgresql
|
||||||
|
key: postgres-password
|
||||||
|
- name: DATABASE_URL
|
||||||
|
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
||||||
|
- name: REDIS_SERVER_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: REDIS_SERVER_HOST
|
||||||
|
value: "{{ .Values.global.redis.host }}"
|
||||||
|
- name: REDIS_SERVER_PORT
|
||||||
|
value: "{{ .Values.global.redis.port }}"
|
||||||
|
- name: REDIS_SERVER_USER
|
||||||
|
value: "{{ .Values.global.redis.username }}"
|
||||||
|
- name: REDIS_SERVER_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: redis
|
||||||
|
key: redis-password
|
||||||
|
- name: REDIS_SERVER_DATABASE
|
||||||
|
value: "{{ .Values.global.redis.database }}"
|
||||||
|
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
||||||
|
value: "{{ .Values.global.indexer.provider }}"
|
||||||
|
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
||||||
|
value: "{{ .Values.global.indexer.endpoint }}"
|
||||||
|
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: indexer
|
||||||
|
key: indexer-apiKey
|
||||||
|
- name: AFFINE_SERVER_PORT
|
||||||
|
value: "{{ .Values.app.port }}"
|
||||||
|
- name: AFFINE_SERVER_SUB_PATH
|
||||||
|
value: "{{ .Values.app.path }}"
|
||||||
|
- name: AFFINE_SERVER_HOST
|
||||||
|
value: "{{ .Values.app.host }}"
|
||||||
|
- name: AFFINE_SERVER_HTTPS
|
||||||
|
value: "{{ .Values.app.https }}"
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.app.port }}
|
||||||
|
protocol: TCP
|
||||||
|
livenessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /info
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: {{ default .Values.probe.initialDelaySeconds .Values.probe.liveness.initialDelaySeconds }}
|
||||||
|
timeoutSeconds: {{ default .Values.probe.timeoutSeconds .Values.probe.liveness.timeoutSeconds }}
|
||||||
|
periodSeconds: {{ default .Values.probe.periodSeconds .Values.probe.liveness.periodSeconds }}
|
||||||
|
failureThreshold: {{ default .Values.probe.failureThreshold .Values.probe.liveness.failureThreshold }}
|
||||||
|
successThreshold: {{ default .Values.probe.successThreshold .Values.probe.liveness.successThreshold }}
|
||||||
|
readinessProbe:
|
||||||
|
httpGet:
|
||||||
|
path: /info
|
||||||
|
port: http
|
||||||
|
initialDelaySeconds: {{ default .Values.probe.initialDelaySeconds .Values.probe.readiness.initialDelaySeconds }}
|
||||||
|
timeoutSeconds: {{ default .Values.probe.timeoutSeconds .Values.probe.readiness.timeoutSeconds }}
|
||||||
|
periodSeconds: {{ default .Values.probe.periodSeconds .Values.probe.readiness.periodSeconds }}
|
||||||
|
failureThreshold: {{ default .Values.probe.failureThreshold .Values.probe.readiness.failureThreshold }}
|
||||||
|
successThreshold: {{ default .Values.probe.successThreshold .Values.probe.readiness.successThreshold }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml .Values.resources | nindent 12 }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
@@ -1,19 +1,19 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "doc.fullname" . }}
|
name: {{ .Values.global.docService.name }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
{{- with .Values.service.annotations }}
|
{{- with .Values.services.doc.annotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.services.doc.type }}
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .Values.global.docService.port }}
|
- port: {{ .Values.global.docService.port }}
|
||||||
targetPort: http
|
targetPort: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http
|
name: http
|
||||||
selector:
|
selector:
|
||||||
{{- include "doc.selectorLabels" . | nindent 4 }}
|
{{- include "front.selectorLabels" . | nindent 4 }}
|
||||||
19
.github/helm/affine/charts/front/templates/service-renderer.yaml
vendored
Normal file
19
.github/helm/affine/charts/front/templates/service-renderer.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.services.renderer.name }}
|
||||||
|
labels:
|
||||||
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.services.renderer.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.services.renderer.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.services.renderer.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "front.selectorLabels" . | nindent 4 }}
|
||||||
19
.github/helm/affine/charts/front/templates/service-sync.yaml
vendored
Normal file
19
.github/helm/affine/charts/front/templates/service-sync.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.services.sync.name }}
|
||||||
|
labels:
|
||||||
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.services.sync.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.services.sync.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.services.sync.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "front.selectorLabels" . | nindent 4 }}
|
||||||
19
.github/helm/affine/charts/front/templates/service-web.yaml
vendored
Normal file
19
.github/helm/affine/charts/front/templates/service-web.yaml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ .Values.services.web.name }}
|
||||||
|
labels:
|
||||||
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.services.web.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.services.web.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.services.web.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "front.selectorLabels" . | nindent 4 }}
|
||||||
@@ -2,9 +2,9 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "sync.serviceAccountName" . }}
|
name: {{ include "front.serviceAccountName" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "sync.labels" . | nindent 4 }}
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
{{- with .Values.serviceAccount.annotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
name: "{{ include "sync.fullname" . }}-test-connection"
|
name: "{{ include "front.fullname" . }}-test-connection"
|
||||||
labels:
|
labels:
|
||||||
{{- include "sync.labels" . | nindent 4 }}
|
{{- include "front.labels" . | nindent 4 }}
|
||||||
annotations:
|
annotations:
|
||||||
"helm.sh/hook": test
|
"helm.sh/hook": test
|
||||||
spec:
|
spec:
|
||||||
@@ -11,5 +11,5 @@ spec:
|
|||||||
- name: wget
|
- name: wget
|
||||||
image: busybox
|
image: busybox
|
||||||
command: ['wget']
|
command: ['wget']
|
||||||
args: ['{{ include "sync.fullname" . }}:{{ .Values.service.port }}']
|
args: ['{{ .Values.services.sync.name }}:{{ .Values.services.sync.port }}']
|
||||||
restartPolicy: Never
|
restartPolicy: Never
|
||||||
74
.github/helm/affine/charts/front/values.yaml
vendored
Normal file
74
.github/helm/affine/charts/front/values.yaml
vendored
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
replicaCount: 1
|
||||||
|
image:
|
||||||
|
repository: ghcr.io/toeverything/affine
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
tag: ''
|
||||||
|
|
||||||
|
imagePullSecrets: []
|
||||||
|
nameOverride: ''
|
||||||
|
fullnameOverride: ''
|
||||||
|
# map to NODE_ENV environment variable
|
||||||
|
env: 'production'
|
||||||
|
nodeOptions: '--max-old-space-size=3072'
|
||||||
|
app:
|
||||||
|
# AFFINE_SERVER_PORT
|
||||||
|
port: 3010
|
||||||
|
# AFFINE_SERVER_SUB_PATH
|
||||||
|
path: ''
|
||||||
|
# AFFINE_SERVER_HOST
|
||||||
|
host: '0.0.0.0'
|
||||||
|
https: true
|
||||||
|
serviceAccount:
|
||||||
|
create: true
|
||||||
|
annotations: {}
|
||||||
|
name: 'affine-front'
|
||||||
|
|
||||||
|
podAnnotations: {}
|
||||||
|
|
||||||
|
podSecurityContext:
|
||||||
|
fsGroup: 2000
|
||||||
|
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 6Gi
|
||||||
|
requests:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 4Gi
|
||||||
|
|
||||||
|
probe:
|
||||||
|
initialDelaySeconds: 20
|
||||||
|
timeoutSeconds: 5
|
||||||
|
periodSeconds: 10
|
||||||
|
failureThreshold: 6
|
||||||
|
successThreshold: 1
|
||||||
|
liveness:
|
||||||
|
initialDelaySeconds: 60
|
||||||
|
failureThreshold: 12
|
||||||
|
readiness: {}
|
||||||
|
|
||||||
|
services:
|
||||||
|
sync:
|
||||||
|
name: affine-sync
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3010
|
||||||
|
annotations:
|
||||||
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
|
renderer:
|
||||||
|
name: affine-renderer
|
||||||
|
type: ClusterIP
|
||||||
|
port: 3000
|
||||||
|
annotations:
|
||||||
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
|
web:
|
||||||
|
name: affine-web
|
||||||
|
type: ClusterIP
|
||||||
|
port: 8080
|
||||||
|
annotations: {}
|
||||||
|
doc:
|
||||||
|
type: ClusterIP
|
||||||
|
annotations: {}
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
tolerations: []
|
||||||
|
affinity: {}
|
||||||
@@ -3,7 +3,7 @@ name: graphql
|
|||||||
description: AFFiNE GraphQL server
|
description: AFFiNE GraphQL server
|
||||||
type: application
|
type: application
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
appVersion: "0.26.0"
|
appVersion: "0.26.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: gcloud-sql-proxy
|
- name: gcloud-sql-proxy
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
|||||||
@@ -27,8 +27,11 @@ podSecurityContext:
|
|||||||
fsGroup: 2000
|
fsGroup: 2000
|
||||||
|
|
||||||
resources:
|
resources:
|
||||||
|
limits:
|
||||||
|
cpu: '1'
|
||||||
|
memory: 4Gi
|
||||||
requests:
|
requests:
|
||||||
cpu: '2'
|
cpu: '1'
|
||||||
memory: 2Gi
|
memory: 2Gi
|
||||||
|
|
||||||
probe:
|
probe:
|
||||||
|
|||||||
11
.github/helm/affine/charts/renderer/Chart.yaml
vendored
11
.github/helm/affine/charts/renderer/Chart.yaml
vendored
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: renderer
|
|
||||||
description: AFFiNE renderer server
|
|
||||||
type: application
|
|
||||||
version: 0.0.0
|
|
||||||
appVersion: "0.26.0"
|
|
||||||
dependencies:
|
|
||||||
- name: gcloud-sql-proxy
|
|
||||||
version: 0.0.0
|
|
||||||
repository: "file://../gcloud-sql-proxy"
|
|
||||||
condition: .global.database.gcloud.enabled
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "renderer.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "renderer.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "renderer.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "renderer.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "renderer.chart" . }}
|
|
||||||
{{ include "renderer.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
monitoring: enabled
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "renderer.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "renderer.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.serviceAccount.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "renderer.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "renderer.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "renderer.serviceAccountName" . }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_PRIVATE_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.global.secret.secretName }}"
|
|
||||||
key: key
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: "{{ .Values.env }}"
|
|
||||||
- name: NODE_OPTIONS
|
|
||||||
value: "--max-old-space-size=2048"
|
|
||||||
- name: NO_COLOR
|
|
||||||
value: "1"
|
|
||||||
- name: DEPLOYMENT_TYPE
|
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
|
||||||
value: "renderer"
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pg-postgresql
|
|
||||||
key: postgres-password
|
|
||||||
- name: DATABASE_URL
|
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
|
||||||
- name: REDIS_SERVER_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: REDIS_SERVER_HOST
|
|
||||||
value: "{{ .Values.global.redis.host }}"
|
|
||||||
- name: REDIS_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.redis.port }}"
|
|
||||||
- name: REDIS_SERVER_USER
|
|
||||||
value: "{{ .Values.global.redis.username }}"
|
|
||||||
- name: REDIS_SERVER_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis
|
|
||||||
key: redis-password
|
|
||||||
- name: REDIS_SERVER_DATABASE
|
|
||||||
value: "{{ .Values.global.redis.database }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: indexer
|
|
||||||
key: indexer-apiKey
|
|
||||||
- name: AFFINE_SERVER_PORT
|
|
||||||
value: "{{ .Values.service.port }}"
|
|
||||||
- name: AFFINE_SERVER_SUB_PATH
|
|
||||||
value: "{{ .Values.app.path }}"
|
|
||||||
- name: AFFINE_SERVER_HOST
|
|
||||||
value: "{{ .Values.app.host }}"
|
|
||||||
- name: AFFINE_SERVER_HTTPS
|
|
||||||
value: "{{ .Values.app.https }}"
|
|
||||||
- name: DOC_SERVICE_ENDPOINT
|
|
||||||
value: "http://{{ .Values.global.docService.name }}:{{ .Values.global.docService.port }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "graphql.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "graphql.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "graphql.selectorLabels" . | nindent 4 }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "graphql.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "graphql.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "renderer.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "renderer.fullname" . }}:{{ .Values.service.port }}']
|
|
||||||
restartPolicy: Never
|
|
||||||
38
.github/helm/affine/charts/renderer/values.yaml
vendored
38
.github/helm/affine/charts/renderer/values.yaml
vendored
@@ -1,38 +0,0 @@
|
|||||||
replicaCount: 1
|
|
||||||
image:
|
|
||||||
repository: ghcr.io/toeverything/affine
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
tag: ''
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ''
|
|
||||||
fullnameOverride: ''
|
|
||||||
# map to NODE_ENV environment variable
|
|
||||||
env: 'production'
|
|
||||||
app:
|
|
||||||
# AFFINE_SERVER_SUB_PATH
|
|
||||||
path: ''
|
|
||||||
# AFFINE_SERVER_HOST
|
|
||||||
host: '0.0.0.0'
|
|
||||||
https: true
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
annotations: {}
|
|
||||||
name: 'affine-renderer'
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext:
|
|
||||||
fsGroup: 2000
|
|
||||||
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: '1'
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
probe:
|
|
||||||
initialDelaySeconds: 20
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
tolerations: []
|
|
||||||
affinity: {}
|
|
||||||
23
.github/helm/affine/charts/sync/.helmignore
vendored
23
.github/helm/affine/charts/sync/.helmignore
vendored
@@ -1,23 +0,0 @@
|
|||||||
# Patterns to ignore when building packages.
|
|
||||||
# This supports shell glob matching, relative path matching, and
|
|
||||||
# negation (prefixed with !). Only one pattern per line.
|
|
||||||
.DS_Store
|
|
||||||
# Common VCS dirs
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
.bzr/
|
|
||||||
.bzrignore
|
|
||||||
.hg/
|
|
||||||
.hgignore
|
|
||||||
.svn/
|
|
||||||
# Common backup files
|
|
||||||
*.swp
|
|
||||||
*.bak
|
|
||||||
*.tmp
|
|
||||||
*.orig
|
|
||||||
*~
|
|
||||||
# Various IDEs
|
|
||||||
.project
|
|
||||||
.idea/
|
|
||||||
*.tmproj
|
|
||||||
.vscode/
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "sync.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "sync.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "sync.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "sync.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "sync.chart" . }}
|
|
||||||
{{ include "sync.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
monitoring: enabled
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "sync.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "sync.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "sync.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.serviceAccount.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,112 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "sync.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "sync.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "sync.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "sync.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "sync.serviceAccountName" . }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.podSecurityContext | nindent 8 }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
securityContext:
|
|
||||||
{{- toYaml .Values.securityContext | nindent 12 }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_PRIVATE_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.global.secret.secretName }}"
|
|
||||||
key: key
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: "{{ .Values.env }}"
|
|
||||||
- name: NO_COLOR
|
|
||||||
value: "1"
|
|
||||||
- name: DEPLOYMENT_TYPE
|
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
|
||||||
value: "sync"
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pg-postgresql
|
|
||||||
key: postgres-password
|
|
||||||
- name: DATABASE_URL
|
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
|
||||||
- name: REDIS_SERVER_HOST
|
|
||||||
value: "{{ .Values.global.redis.host }}"
|
|
||||||
- name: REDIS_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.redis.port }}"
|
|
||||||
- name: REDIS_SERVER_USER
|
|
||||||
value: "{{ .Values.global.redis.username }}"
|
|
||||||
- name: REDIS_SERVER_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis
|
|
||||||
key: redis-password
|
|
||||||
- name: REDIS_SERVER_DATABASE
|
|
||||||
value: "{{ .Values.global.redis.database }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: indexer
|
|
||||||
key: indexer-apiKey
|
|
||||||
- name: AFFINE_SERVER_PORT
|
|
||||||
value: "{{ .Values.service.port }}"
|
|
||||||
- name: AFFINE_SERVER_HOST
|
|
||||||
value: "{{ .Values.app.host }}"
|
|
||||||
- name: DOC_SERVICE_ENDPOINT
|
|
||||||
value: "http://{{ .Values.global.docService.name }}:{{ .Values.global.docService.port }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
tcpSocket:
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
tcpSocket:
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "sync.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "sync.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "sync.selectorLabels" . | nindent 4 }}
|
|
||||||
38
.github/helm/affine/charts/sync/values.yaml
vendored
38
.github/helm/affine/charts/sync/values.yaml
vendored
@@ -1,38 +0,0 @@
|
|||||||
replicaCount: 1
|
|
||||||
image:
|
|
||||||
repository: ghcr.io/toeverything/affine
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
tag: ''
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ''
|
|
||||||
fullnameOverride: ''
|
|
||||||
# map to NODE_ENV environment variable
|
|
||||||
env: 'production'
|
|
||||||
app:
|
|
||||||
# AFFINE_SERVER_HOST
|
|
||||||
host: '0.0.0.0'
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
annotations: {}
|
|
||||||
name: 'affine-sync'
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext:
|
|
||||||
fsGroup: 2000
|
|
||||||
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: '2'
|
|
||||||
memory: 4Gi
|
|
||||||
requests:
|
|
||||||
cpu: '1'
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
probe:
|
|
||||||
initialDelaySeconds: 20
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
tolerations: []
|
|
||||||
affinity: {}
|
|
||||||
23
.github/helm/affine/charts/web/.helmignore
vendored
23
.github/helm/affine/charts/web/.helmignore
vendored
@@ -1,23 +0,0 @@
|
|||||||
# Patterns to ignore when building packages.
|
|
||||||
# This supports shell glob matching, relative path matching, and
|
|
||||||
# negation (prefixed with !). Only one pattern per line.
|
|
||||||
.DS_Store
|
|
||||||
# Common VCS dirs
|
|
||||||
.git/
|
|
||||||
.gitignore
|
|
||||||
.bzr/
|
|
||||||
.bzrignore
|
|
||||||
.hg/
|
|
||||||
.hgignore
|
|
||||||
.svn/
|
|
||||||
# Common backup files
|
|
||||||
*.swp
|
|
||||||
*.bak
|
|
||||||
*.tmp
|
|
||||||
*.orig
|
|
||||||
*~
|
|
||||||
# Various IDEs
|
|
||||||
.project
|
|
||||||
.idea/
|
|
||||||
*.tmproj
|
|
||||||
.vscode/
|
|
||||||
6
.github/helm/affine/charts/web/Chart.yaml
vendored
6
.github/helm/affine/charts/web/Chart.yaml
vendored
@@ -1,6 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: web
|
|
||||||
description: A Helm chart for Kubernetes
|
|
||||||
type: application
|
|
||||||
version: 0.0.0
|
|
||||||
appVersion: "0.7.0-canary.18"
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "web.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "web.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "web.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "web.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "web.serviceAccountName" . }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "web.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "web.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "web.selectorLabels" . | nindent 4 }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "web.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "web.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "web.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "web.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "web.fullname" . }}:{{ .Values.service.port }}']
|
|
||||||
restartPolicy: Never
|
|
||||||
37
.github/helm/affine/charts/web/values.yaml
vendored
37
.github/helm/affine/charts/web/values.yaml
vendored
@@ -1,37 +0,0 @@
|
|||||||
replicaCount: 1
|
|
||||||
|
|
||||||
image:
|
|
||||||
repository: ghcr.io/toeverything/affine-front
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
tag: ""
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ""
|
|
||||||
fullnameOverride: ""
|
|
||||||
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
annotations: {}
|
|
||||||
name: "affine-web"
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext:
|
|
||||||
fsGroup: 2000
|
|
||||||
|
|
||||||
resources:
|
|
||||||
limits:
|
|
||||||
cpu: '500m'
|
|
||||||
memory: 2Gi
|
|
||||||
requests:
|
|
||||||
cpu: '500m'
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
|
|
||||||
tolerations: []
|
|
||||||
|
|
||||||
affinity: {}
|
|
||||||
|
|
||||||
probe:
|
|
||||||
initialDelaySeconds: 1
|
|
||||||
12
.github/helm/affine/templates/ingress.yaml
vendored
12
.github/helm/affine/templates/ingress.yaml
vendored
@@ -44,9 +44,9 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: affine-sync
|
name: {{ $.Values.front.services.sync.name }}
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.sync.service.port }}
|
number: {{ $.Values.front.services.sync.port }}
|
||||||
- path: /graphql
|
- path: /graphql
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
@@ -65,15 +65,15 @@ spec:
|
|||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: affine-renderer
|
name: {{ $.Values.front.services.renderer.name }}
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.renderer.service.port }}
|
number: {{ $.Values.front.services.renderer.port }}
|
||||||
- path: /
|
- path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: affine-web
|
name: {{ $.Values.front.services.web.name }}
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.web.service.port }}
|
number: {{ $.Values.front.services.web.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
46
.github/helm/affine/values.yaml
vendored
46
.github/helm/affine/values.yaml
vendored
@@ -47,27 +47,25 @@ graphql:
|
|||||||
annotations:
|
annotations:
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
|
|
||||||
sync:
|
front:
|
||||||
service:
|
services:
|
||||||
type: ClusterIP
|
sync:
|
||||||
port: 3010
|
name: affine-sync
|
||||||
annotations:
|
type: ClusterIP
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
port: 3010
|
||||||
|
annotations:
|
||||||
renderer:
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
service:
|
renderer:
|
||||||
type: ClusterIP
|
name: affine-renderer
|
||||||
port: 3000
|
type: ClusterIP
|
||||||
annotations:
|
port: 3000
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
annotations:
|
||||||
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
doc:
|
web:
|
||||||
service:
|
name: affine-web
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
annotations:
|
port: 8080
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
doc:
|
||||||
|
type: ClusterIP
|
||||||
web:
|
annotations:
|
||||||
service:
|
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
||||||
type: ClusterIP
|
|
||||||
port: 8080
|
|
||||||
|
|||||||
4
.github/renovate.json
vendored
4
.github/renovate.json
vendored
@@ -63,7 +63,7 @@
|
|||||||
"groupName": "opentelemetry",
|
"groupName": "opentelemetry",
|
||||||
"matchPackageNames": [
|
"matchPackageNames": [
|
||||||
"/^@opentelemetry/",
|
"/^@opentelemetry/",
|
||||||
"/^@google-cloud\/opentelemetry-/"
|
"/^@google-cloud/opentelemetry-/"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -79,7 +79,7 @@
|
|||||||
"customManagers": [
|
"customManagers": [
|
||||||
{
|
{
|
||||||
"customType": "regex",
|
"customType": "regex",
|
||||||
"fileMatch": ["^rust-toolchain\\.toml?$"],
|
"managerFilePatterns": ["/^rust-toolchain\\.toml?$/"],
|
||||||
"matchStrings": [
|
"matchStrings": [
|
||||||
"channel\\s*=\\s*\"(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)\""
|
"channel\\s*=\\s*\"(?<currentValue>\\d+\\.\\d+(\\.\\d+)?)\""
|
||||||
],
|
],
|
||||||
|
|||||||
10
.github/workflows/auto-labeler.yml
vendored
10
.github/workflows/auto-labeler.yml
vendored
@@ -1,6 +1,10 @@
|
|||||||
name: 'Pull Request Labeler'
|
name: 'Pull Request Labeler'
|
||||||
on:
|
on:
|
||||||
- pull_request_target
|
pull_request_target:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
- reopened
|
||||||
|
- synchronize
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
triage:
|
triage:
|
||||||
@@ -9,5 +13,5 @@ jobs:
|
|||||||
pull-requests: write
|
pull-requests: write
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: actions/labeler@v5
|
- uses: actions/labeler@v6
|
||||||
|
|||||||
35
.github/workflows/build-images.yml
vendored
35
.github/workflows/build-images.yml
vendored
@@ -24,7 +24,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -45,8 +45,6 @@ jobs:
|
|||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
- name: Upload web artifact
|
- name: Upload web artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -59,7 +57,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -79,8 +77,6 @@ jobs:
|
|||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
- name: Upload admin artifact
|
- name: Upload admin artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -93,7 +89,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -113,8 +109,6 @@ jobs:
|
|||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
- name: Upload mobile artifact
|
- name: Upload mobile artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -124,7 +118,7 @@ jobs:
|
|||||||
|
|
||||||
build-server-native:
|
build-server-native:
|
||||||
name: Build Server native - ${{ matrix.targets.name }}
|
name: Build Server native - ${{ matrix.targets.name }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-22.04
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
@@ -138,7 +132,7 @@ jobs:
|
|||||||
file: server-native.armv7.node
|
file: server-native.armv7.node
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -172,7 +166,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -208,7 +202,7 @@ jobs:
|
|||||||
- build-mobile
|
- build-mobile
|
||||||
- build-admin
|
- build-admin
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Download server dist
|
- name: Download server dist
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -228,7 +222,7 @@ jobs:
|
|||||||
# setup node without cache configuration
|
# setup node without cache configuration
|
||||||
# Prisma cache is not compatible with docker build cache
|
# Prisma cache is not compatible with docker build cache
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
registry-url: https://npm.pkg.github.com
|
registry-url: https://npm.pkg.github.com
|
||||||
@@ -269,18 +263,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
app-version: ${{ inputs.app-version }}
|
app-version: ${{ inputs.app-version }}
|
||||||
|
|
||||||
- name: Build front Dockerfile
|
- name: Build backend Dockerfile
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
pull: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
provenance: true
|
|
||||||
file: .github/deployment/front/Dockerfile
|
|
||||||
tags: ghcr.io/toeverything/affine-front:${{inputs.build-type}}-${{ inputs.git-short-hash }}
|
|
||||||
|
|
||||||
- name: Build graphql Dockerfile
|
|
||||||
uses: docker/build-push-action@v6
|
uses: docker/build-push-action@v6
|
||||||
with:
|
with:
|
||||||
context: .
|
context: .
|
||||||
|
|||||||
471
.github/workflows/build-test.yml
vendored
471
.github/workflows/build-test.yml
vendored
@@ -46,7 +46,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
uses: github/codeql-action/init@v3
|
uses: github/codeql-action/init@v3
|
||||||
@@ -67,10 +67,27 @@ jobs:
|
|||||||
name: Lint
|
name: Lint
|
||||||
runs-on: ubuntu-24.04-arm
|
runs-on: ubuntu-24.04-arm
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
- name: Setup Go (for actionlint)
|
||||||
|
uses: actions/setup-go@v6
|
||||||
|
with:
|
||||||
|
go-version: 'stable'
|
||||||
|
- name: Install actionlint
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
go install github.com/rhysd/actionlint/cmd/actionlint@v1.7.11
|
||||||
|
- name: Run actionlint
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
"$(go env GOPATH)/bin/actionlint"
|
||||||
- name: Run oxlint
|
- name: Run oxlint
|
||||||
# oxlint is fast, so wrong code will fail quickly
|
# oxlint is fast, so wrong code will fail quickly
|
||||||
run: yarn dlx $(node -e "console.log(require('./package.json').scripts['lint:ox'].replace('oxlint', 'oxlint@' + require('./package.json').devDependencies.oxlint))")
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
oxlint_version="$(node -e "console.log(require('./package.json').devDependencies.oxlint)")"
|
||||||
|
yarn dlx "oxlint@${oxlint_version}" --deny-warnings
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -94,7 +111,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
NODE_OPTIONS: --max-old-space-size=14384
|
NODE_OPTIONS: --max-old-space-size=14384
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -108,20 +125,45 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
yarn affine bs-docs build
|
yarn affine bs-docs build
|
||||||
git checkout packages/frontend/i18n/src/i18n-completenesses.json
|
git checkout packages/frontend/i18n/src/i18n-completenesses.json
|
||||||
git status --porcelain | grep . && {
|
if git status --porcelain | grep -q .; then
|
||||||
echo "Run 'yarn typecheck && yarn affine bs-docs build' and make sure all changes are submitted"
|
echo "Run 'yarn typecheck && yarn affine bs-docs build' and make sure all changes are submitted"
|
||||||
exit 1
|
exit 1
|
||||||
} || {
|
else
|
||||||
echo "All changes are submitted"
|
echo "All changes are submitted"
|
||||||
}
|
fi
|
||||||
|
|
||||||
|
rust-test-filter:
|
||||||
|
name: Rust test filter
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
run-rust: ${{ steps.rust-filter.outputs.rust }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v3
|
||||||
|
id: rust-filter
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
rust:
|
||||||
|
- '**/*.rs'
|
||||||
|
- '**/Cargo.toml'
|
||||||
|
- '**/Cargo.lock'
|
||||||
|
- '.cargo/**'
|
||||||
|
- 'rust-toolchain*'
|
||||||
|
- '.github/actions/build-rust/**'
|
||||||
|
|
||||||
lint-rust:
|
lint-rust:
|
||||||
name: Lint Rust
|
name: Lint Rust
|
||||||
|
if: ${{ needs.rust-test-filter.outputs.run-rust == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- rust-test-filter
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: ./.github/actions/build-rust
|
- uses: ./.github/actions/build-rust
|
||||||
with:
|
with:
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
package: 'affine'
|
||||||
no-build: 'true'
|
no-build: 'true'
|
||||||
- name: fmt check
|
- name: fmt check
|
||||||
run: |
|
run: |
|
||||||
@@ -140,7 +182,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -159,21 +201,23 @@ jobs:
|
|||||||
yarn affine i18n build
|
yarn affine i18n build
|
||||||
yarn affine server genconfig
|
yarn affine server genconfig
|
||||||
git checkout packages/frontend/i18n/src/i18n-completenesses.json
|
git checkout packages/frontend/i18n/src/i18n-completenesses.json
|
||||||
git status --porcelain | grep . && {
|
if git status --porcelain | grep -q .; then
|
||||||
echo "Run 'yarn affine init && yarn affine gql build && yarn affine i18n build && yarn affine server genconfig' and make sure all changes are submitted"
|
echo "Run 'yarn affine init && yarn affine gql build && yarn affine i18n build && yarn affine server genconfig' and make sure all changes are submitted"
|
||||||
exit 1
|
exit 1
|
||||||
} || {
|
else
|
||||||
echo "All changes are submitted"
|
echo "All changes are submitted"
|
||||||
}
|
fi
|
||||||
|
|
||||||
check-yarn-binary:
|
check-yarn-binary:
|
||||||
name: Check yarn binary
|
name: Check yarn binary
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Run check
|
- name: Run check
|
||||||
run: |
|
run: |
|
||||||
yarn set version $(node -e "console.log(require('./package.json').packageManager.split('@')[1])")
|
set -euo pipefail
|
||||||
|
yarn_version="$(node -e "console.log(require('./package.json').packageManager.split('@')[1])")"
|
||||||
|
yarn set version "$yarn_version"
|
||||||
git diff --exit-code
|
git diff --exit-code
|
||||||
|
|
||||||
e2e-blocksuite-test:
|
e2e-blocksuite-test:
|
||||||
@@ -182,12 +226,13 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
shard: [1, 2, 3, 4, 5]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/blocksuite @blocksuite/playground @blocksuite/integration-test
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
playwright-platform: 'chromium'
|
playwright-platform: 'chromium'
|
||||||
electron-install: false
|
electron-install: false
|
||||||
@@ -210,34 +255,33 @@ jobs:
|
|||||||
e2e-blocksuite-cross-browser-test:
|
e2e-blocksuite-cross-browser-test:
|
||||||
name: E2E BlockSuite Cross Browser Test
|
name: E2E BlockSuite Cross Browser Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
shard: [1, 2]
|
|
||||||
browser: ['chromium', 'firefox', 'webkit']
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/blocksuite @blocksuite/playground @blocksuite/integration-test
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
playwright-platform: ${{ matrix.browser }}
|
playwright-platform: 'chromium,firefox,webkit'
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
- name: Run playground build
|
- name: Run playground build
|
||||||
run: yarn workspace @blocksuite/playground build
|
run: yarn workspace @blocksuite/playground build
|
||||||
|
|
||||||
- name: Run playwright tests
|
- name: Run integration browser tests
|
||||||
env:
|
timeout-minutes: 10
|
||||||
BROWSER: ${{ matrix.browser }}
|
run: yarn workspace @blocksuite/integration-test test:unit
|
||||||
run: yarn workspace @affine-test/blocksuite test "cross-platform/" --forbid-only --shard=${{ matrix.shard }}/${{ strategy.job-total }}
|
|
||||||
|
- name: Run cross-platform playwright tests
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: yarn workspace @affine-test/blocksuite test "cross-platform/" --forbid-only
|
||||||
|
|
||||||
- name: Upload test results
|
- name: Upload test results
|
||||||
if: always()
|
if: always()
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: test-results-e2e-bs-cross-browser-${{ matrix.browser }}-${{ matrix.shard }}
|
name: test-results-e2e-bs-cross-browser
|
||||||
path: ./test-results
|
path: ./test-results
|
||||||
if-no-files-found: ignore
|
if-no-files-found: ignore
|
||||||
|
|
||||||
@@ -251,12 +295,13 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
shard: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
shard: [1, 2, 3, 4, 5]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/affine-local @affine/web @affine/server
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
playwright-platform: 'chromium'
|
playwright-platform: 'chromium'
|
||||||
electron-install: false
|
electron-install: false
|
||||||
@@ -282,12 +327,13 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
shard: [1, 2, 3, 4, 5]
|
shard: [1, 2]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/affine-mobile @affine/mobile
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
@@ -307,7 +353,7 @@ jobs:
|
|||||||
name: Unit Test
|
name: Unit Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- build-native
|
- build-native-linux
|
||||||
env:
|
env:
|
||||||
DISTRIBUTION: web
|
DISTRIBUTION: web
|
||||||
strategy:
|
strategy:
|
||||||
@@ -315,12 +361,13 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
shard: [1, 2, 3, 4, 5]
|
shard: [1, 2, 3, 4, 5]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
electron-install: true
|
electron-install: true
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
|
playwright-platform: 'chromium,firefox,webkit'
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
- name: Download affine.linux-x64-gnu.node
|
- name: Download affine.linux-x64-gnu.node
|
||||||
@@ -341,21 +388,13 @@ jobs:
|
|||||||
name: affine
|
name: affine
|
||||||
fail_ci_if_error: false
|
fail_ci_if_error: false
|
||||||
|
|
||||||
build-native:
|
build-native-linux:
|
||||||
name: Build AFFiNE native (${{ matrix.spec.target }})
|
name: Build AFFiNE native (x86_64-unknown-linux-gnu)
|
||||||
runs-on: ${{ matrix.spec.os }}
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
spec:
|
|
||||||
- { os: ubuntu-latest, target: x86_64-unknown-linux-gnu }
|
|
||||||
- { os: macos-latest, target: x86_64-apple-darwin }
|
|
||||||
- { os: macos-latest, target: aarch64-apple-darwin }
|
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -366,7 +405,46 @@ jobs:
|
|||||||
working-directory: ${{ github.workspace }}
|
working-directory: ${{ github.workspace }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
|
PLATFORM_ARCH_ABI="$(node -e "console.log(require('@napi-rs/cli').parseTriple('x86_64-unknown-linux-gnu').platformArchABI)")"
|
||||||
|
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
||||||
|
- name: Build AFFiNE native
|
||||||
|
uses: ./.github/actions/build-rust
|
||||||
|
with:
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
|
package: '@affine/native'
|
||||||
|
- name: Upload ${{ steps.filename.outputs.filename }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
if: always()
|
||||||
|
with:
|
||||||
|
name: ${{ steps.filename.outputs.filename }}
|
||||||
|
path: ${{ github.workspace }}/packages/frontend/native/${{ steps.filename.outputs.filename }}
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-native-macos:
|
||||||
|
name: Build AFFiNE native (${{ matrix.spec.target }})
|
||||||
|
runs-on: ${{ matrix.spec.os }}
|
||||||
|
env:
|
||||||
|
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
spec:
|
||||||
|
- { os: macos-latest, target: x86_64-apple-darwin }
|
||||||
|
- { os: macos-latest, target: aarch64-apple-darwin }
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/native
|
||||||
|
electron-install: false
|
||||||
|
- name: Setup filename
|
||||||
|
id: filename
|
||||||
|
working-directory: ${{ github.workspace }}
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
PLATFORM_ARCH_ABI="$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")"
|
||||||
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
||||||
- name: Build AFFiNE native
|
- name: Build AFFiNE native
|
||||||
uses: ./.github/actions/build-rust
|
uses: ./.github/actions/build-rust
|
||||||
@@ -383,7 +461,7 @@ jobs:
|
|||||||
|
|
||||||
# Split Windows build because it's too slow
|
# Split Windows build because it's too slow
|
||||||
# and other ci jobs required linux native
|
# and other ci jobs required linux native
|
||||||
build-windows-native:
|
build-native-windows:
|
||||||
name: Build AFFiNE native (${{ matrix.spec.target }})
|
name: Build AFFiNE native (${{ matrix.spec.target }})
|
||||||
runs-on: ${{ matrix.spec.os }}
|
runs-on: ${{ matrix.spec.os }}
|
||||||
env:
|
env:
|
||||||
@@ -396,7 +474,7 @@ jobs:
|
|||||||
- { os: windows-latest, target: aarch64-pc-windows-msvc }
|
- { os: windows-latest, target: aarch64-pc-windows-msvc }
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- uses: samypr100/setup-dev-drive@v3
|
- uses: samypr100/setup-dev-drive@v3
|
||||||
with:
|
with:
|
||||||
workspace-copy: true
|
workspace-copy: true
|
||||||
@@ -415,7 +493,7 @@ jobs:
|
|||||||
working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
|
working-directory: ${{ env.DEV_DRIVE_WORKSPACE }}
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
|
PLATFORM_ARCH_ABI="$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")"
|
||||||
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
||||||
- name: Build AFFiNE native
|
- name: Build AFFiNE native
|
||||||
uses: ./.github/actions/build-rust
|
uses: ./.github/actions/build-rust
|
||||||
@@ -436,7 +514,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -459,10 +537,11 @@ jobs:
|
|||||||
name: Build @affine/electron renderer
|
name: Build @affine/electron renderer
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine/electron-renderer @affine/nbstore @toeverything/infra
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
- name: Build Electron renderer
|
- name: Build Electron renderer
|
||||||
@@ -483,9 +562,9 @@ jobs:
|
|||||||
name: Native Unit Test
|
name: Native Unit Test
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- build-native
|
- build-native-linux
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -507,8 +586,8 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
node_index: [0, 1, 2, 3, 4, 5, 6, 7]
|
node_index: [0, 1, 2, 3]
|
||||||
total_nodes: [8]
|
total_nodes: [4]
|
||||||
env:
|
env:
|
||||||
NODE_ENV: test
|
NODE_ENV: test
|
||||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||||
@@ -539,11 +618,12 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine/server
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
@@ -577,8 +657,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
env:
|
env:
|
||||||
NODE_ENV: test
|
NODE_ENV: test
|
||||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||||
@@ -621,11 +699,12 @@ jobs:
|
|||||||
stack-version: 9.0.1
|
stack-version: 9.0.1
|
||||||
security-enabled: false
|
security-enabled: false
|
||||||
|
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine/server
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
@@ -642,8 +721,6 @@ jobs:
|
|||||||
run: yarn affine @affine/server test:coverage "**/*/*elasticsearch.spec.ts" --forbid-only
|
run: yarn affine @affine/server test:coverage "**/*/*elasticsearch.spec.ts" --forbid-only
|
||||||
env:
|
env:
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
||||||
CI_NODE_INDEX: ${{ matrix.node_index }}
|
|
||||||
CI_NODE_TOTAL: ${{ matrix.total_nodes }}
|
|
||||||
|
|
||||||
- name: Upload server test coverage results
|
- name: Upload server test coverage results
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
@@ -685,11 +762,12 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine/server
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
@@ -716,13 +794,16 @@ jobs:
|
|||||||
|
|
||||||
miri:
|
miri:
|
||||||
name: miri code check
|
name: miri code check
|
||||||
|
if: ${{ needs.rust-test-filter.outputs.run-rust == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- rust-test-filter
|
||||||
env:
|
env:
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
MIRIFLAGS: -Zmiri-backtrace=full -Zmiri-tree-borrows
|
MIRIFLAGS: -Zmiri-backtrace=full -Zmiri-tree-borrows
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -741,13 +822,16 @@ jobs:
|
|||||||
|
|
||||||
loom:
|
loom:
|
||||||
name: loom thread test
|
name: loom thread test
|
||||||
|
if: ${{ needs.rust-test-filter.outputs.run-rust == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- rust-test-filter
|
||||||
env:
|
env:
|
||||||
RUSTFLAGS: --cfg loom
|
RUSTFLAGS: --cfg loom
|
||||||
RUST_BACKTRACE: full
|
RUST_BACKTRACE: full
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -764,11 +848,14 @@ jobs:
|
|||||||
|
|
||||||
fuzzing:
|
fuzzing:
|
||||||
name: fuzzing
|
name: fuzzing
|
||||||
|
if: ${{ needs.rust-test-filter.outputs.run-rust == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- rust-test-filter
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
@@ -800,14 +887,18 @@ jobs:
|
|||||||
|
|
||||||
rust-test:
|
rust-test:
|
||||||
name: Run native tests
|
name: Run native tests
|
||||||
|
if: ${{ needs.rust-test-filter.outputs.run-rust == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- rust-test-filter
|
||||||
env:
|
env:
|
||||||
CARGO_TERM_COLOR: always
|
CARGO_TERM_COLOR: always
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: ./.github/actions/build-rust
|
uses: ./.github/actions/build-rust
|
||||||
with:
|
with:
|
||||||
|
target: x86_64-unknown-linux-gnu
|
||||||
package: 'affine'
|
package: 'affine'
|
||||||
no-build: 'true'
|
no-build: 'true'
|
||||||
|
|
||||||
@@ -819,11 +910,51 @@ jobs:
|
|||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo nextest run --workspace --exclude affine_server_native --features use-as-lib --release --no-fail-fast
|
run: cargo nextest run --workspace --exclude affine_server_native --features use-as-lib --release --no-fail-fast
|
||||||
|
|
||||||
|
copilot-test-filter:
|
||||||
|
name: Copilot test filter
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
outputs:
|
||||||
|
run-api: ${{ steps.decision.outputs.run_api }}
|
||||||
|
run-e2e: ${{ steps.decision.outputs.run_e2e }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
|
- uses: dorny/paths-filter@v3
|
||||||
|
id: copilot-filter
|
||||||
|
with:
|
||||||
|
filters: |
|
||||||
|
api:
|
||||||
|
- 'packages/backend/server/src/plugins/copilot/**'
|
||||||
|
- 'packages/backend/server/tests/copilot.*'
|
||||||
|
e2e:
|
||||||
|
- 'packages/backend/server/src/plugins/copilot/**'
|
||||||
|
- 'packages/backend/server/tests/copilot.*'
|
||||||
|
- 'packages/frontend/core/src/blocksuite/ai/**'
|
||||||
|
- 'packages/frontend/core/src/modules/workspace-indexer-embedding/**'
|
||||||
|
- 'tests/affine-cloud-copilot/**'
|
||||||
|
|
||||||
|
- name: Decide test scope
|
||||||
|
id: decision
|
||||||
|
run: |
|
||||||
|
if [[ "${{ steps.copilot-filter.outputs.api }}" == "true" ]]; then
|
||||||
|
echo "run_api=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "run_api=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ "${{ steps.copilot-filter.outputs.e2e }}" == "true" ]]; then
|
||||||
|
echo "run_e2e=true" >> "$GITHUB_OUTPUT"
|
||||||
|
else
|
||||||
|
echo "run_e2e=false" >> "$GITHUB_OUTPUT"
|
||||||
|
fi
|
||||||
|
|
||||||
copilot-api-test:
|
copilot-api-test:
|
||||||
name: Server Copilot Api Test
|
name: Server Copilot Api Test
|
||||||
|
if: ${{ needs.copilot-test-filter.outputs.run-api == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
|
- copilot-test-filter
|
||||||
env:
|
env:
|
||||||
NODE_ENV: test
|
NODE_ENV: test
|
||||||
DISTRIBUTION: web
|
DISTRIBUTION: web
|
||||||
@@ -855,55 +986,32 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Check blocksuite update
|
|
||||||
id: check-blocksuite-update
|
|
||||||
env:
|
|
||||||
BASE_REF: ${{ github.base_ref }}
|
|
||||||
run: |
|
|
||||||
if node ./scripts/detect-blocksuite-update.mjs "$BASE_REF"; then
|
|
||||||
echo "skip=false" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "skip=true" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- uses: dorny/paths-filter@v3
|
|
||||||
id: apifilter
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
changed:
|
|
||||||
- 'packages/backend/server/src/plugins/copilot/**'
|
|
||||||
- 'packages/backend/server/tests/copilot.*'
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine/server
|
||||||
electron-install: false
|
electron-install: false
|
||||||
full-cache: true
|
full-cache: true
|
||||||
|
|
||||||
- name: Download server-native.node
|
- name: Download server-native.node
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: server-native.node
|
name: server-native.node
|
||||||
path: ./packages/backend/native
|
path: ./packages/backend/native
|
||||||
|
|
||||||
- name: Prepare Server Test Environment
|
- name: Prepare Server Test Environment
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
|
||||||
env:
|
env:
|
||||||
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
||||||
uses: ./.github/actions/server-test-env
|
uses: ./.github/actions/server-test-env
|
||||||
|
|
||||||
- name: Run server tests
|
- name: Run server tests
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
|
||||||
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
||||||
env:
|
env:
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
||||||
|
|
||||||
- name: Upload server test coverage results
|
- name: Upload server test coverage results
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
|
|
||||||
uses: codecov/codecov-action@v5
|
uses: codecov/codecov-action@v5
|
||||||
with:
|
with:
|
||||||
token: ${{ secrets.CODECOV_TOKEN }}
|
token: ${{ secrets.CODECOV_TOKEN }}
|
||||||
@@ -914,6 +1022,7 @@ jobs:
|
|||||||
|
|
||||||
copilot-e2e-test:
|
copilot-e2e-test:
|
||||||
name: Frontend Copilot E2E Test
|
name: Frontend Copilot E2E Test
|
||||||
|
if: ${{ needs.copilot-test-filter.outputs.run-e2e == 'true' }}
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
env:
|
||||||
DISTRIBUTION: web
|
DISTRIBUTION: web
|
||||||
@@ -924,10 +1033,11 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
shardIndex: [1, 2, 3, 4, 5]
|
||||||
shardTotal: [10]
|
shardTotal: [5]
|
||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
|
- copilot-test-filter
|
||||||
services:
|
services:
|
||||||
postgres:
|
postgres:
|
||||||
image: pgvector/pgvector:pg16
|
image: pgvector/pgvector:pg16
|
||||||
@@ -949,54 +1059,29 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Check blocksuite update
|
|
||||||
id: check-blocksuite-update
|
|
||||||
env:
|
|
||||||
BASE_REF: ${{ github.base_ref }}
|
|
||||||
run: |
|
|
||||||
if node ./scripts/detect-blocksuite-update.mjs "$BASE_REF"; then
|
|
||||||
echo "skip=false" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "skip=true" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- uses: dorny/paths-filter@v3
|
|
||||||
id: e2efilter
|
|
||||||
with:
|
|
||||||
filters: |
|
|
||||||
changed:
|
|
||||||
- 'packages/backend/server/src/plugins/copilot/**'
|
|
||||||
- 'packages/backend/server/tests/copilot.*'
|
|
||||||
- 'packages/frontend/core/src/blocksuite/ai/**'
|
|
||||||
- 'packages/frontend/core/src/modules/workspace-indexer-embedding/**'
|
|
||||||
- 'tests/affine-cloud-copilot/**'
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/affine-cloud-copilot @affine/web @affine/server
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
playwright-platform: 'chromium'
|
playwright-platform: 'chromium'
|
||||||
electron-install: false
|
electron-install: false
|
||||||
hard-link-nm: false
|
hard-link-nm: false
|
||||||
|
|
||||||
- name: Download server-native.node
|
- name: Download server-native.node
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: server-native.node
|
name: server-native.node
|
||||||
path: ./packages/backend/native
|
path: ./packages/backend/native
|
||||||
|
|
||||||
- name: Prepare Server Test Environment
|
- name: Prepare Server Test Environment
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
|
||||||
env:
|
env:
|
||||||
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
||||||
uses: ./.github/actions/server-test-env
|
uses: ./.github/actions/server-test-env
|
||||||
|
|
||||||
- name: Run Copilot E2E Test ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
- name: Run Copilot E2E Test ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
|
|
||||||
uses: ./.github/actions/copilot-test
|
uses: ./.github/actions/copilot-test
|
||||||
with:
|
with:
|
||||||
script: yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
script: yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
||||||
@@ -1006,7 +1091,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs:
|
needs:
|
||||||
- build-server-native
|
- build-server-native
|
||||||
- build-native
|
- build-native-linux
|
||||||
env:
|
env:
|
||||||
DISTRIBUTION: web
|
DISTRIBUTION: web
|
||||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
||||||
@@ -1016,36 +1101,12 @@ jobs:
|
|||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
tests:
|
tests:
|
||||||
- name: 'Cloud E2E Test 1/10'
|
- name: 'Cloud E2E Test 1/2'
|
||||||
shard: 1
|
shard: 1
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=1/10
|
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=1/2
|
||||||
- name: 'Cloud E2E Test 2/10'
|
- name: 'Cloud E2E Test 2/2'
|
||||||
shard: 2
|
shard: 2
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=2/10
|
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=2/2
|
||||||
- name: 'Cloud E2E Test 3/10'
|
|
||||||
shard: 3
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=3/10
|
|
||||||
- name: 'Cloud E2E Test 4/10'
|
|
||||||
shard: 4
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=4/10
|
|
||||||
- name: 'Cloud E2E Test 5/10'
|
|
||||||
shard: 5
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=5/10
|
|
||||||
- name: 'Cloud E2E Test 6/10'
|
|
||||||
shard: 6
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=6/10
|
|
||||||
- name: 'Cloud E2E Test 7/10'
|
|
||||||
shard: 7
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=7/10
|
|
||||||
- name: 'Cloud E2E Test 8/10'
|
|
||||||
shard: 8
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=8/10
|
|
||||||
- name: 'Cloud E2E Test 9/10'
|
|
||||||
shard: 9
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=9/10
|
|
||||||
- name: 'Cloud E2E Test 10/10'
|
|
||||||
shard: 10
|
|
||||||
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=10/10
|
|
||||||
- name: 'Cloud Desktop E2E Test'
|
- name: 'Cloud Desktop E2E Test'
|
||||||
shard: desktop
|
shard: desktop
|
||||||
script: |
|
script: |
|
||||||
@@ -1081,12 +1142,15 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
|
extra-flags: workspaces focus @affine/monorepo @affine-test/affine-cloud @affine-test/affine-desktop-cloud @affine/web @affine/server @affine/electron @affine/electron-renderer @affine/nbstore @toeverything/infra
|
||||||
playwright-install: true
|
playwright-install: true
|
||||||
|
playwright-platform: 'chromium'
|
||||||
|
electron-install: ${{ matrix.tests.shard == 'desktop' && 'true' || 'false' }}
|
||||||
hard-link-nm: false
|
hard-link-nm: false
|
||||||
|
|
||||||
- name: Download server-native.node
|
- name: Download server-native.node
|
||||||
@@ -1123,7 +1187,9 @@ jobs:
|
|||||||
runs-on: ${{ matrix.spec.os }}
|
runs-on: ${{ matrix.spec.os }}
|
||||||
needs:
|
needs:
|
||||||
- build-electron-renderer
|
- build-electron-renderer
|
||||||
- build-native
|
- build-native-linux
|
||||||
|
- build-native-macos
|
||||||
|
- build-native-windows
|
||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
@@ -1157,13 +1223,14 @@ jobs:
|
|||||||
test: true,
|
test: true,
|
||||||
}
|
}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
with:
|
with:
|
||||||
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine-test/affine-desktop @affine/nbstore @toeverything/infra
|
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine-test/affine-desktop @affine/nbstore @toeverything/infra
|
||||||
playwright-install: true
|
playwright-install: ${{ matrix.spec.test && 'true' || 'false' }}
|
||||||
|
playwright-platform: 'chromium'
|
||||||
hard-link-nm: false
|
hard-link-nm: false
|
||||||
enableScripts: false
|
enableScripts: false
|
||||||
|
|
||||||
@@ -1171,7 +1238,7 @@ jobs:
|
|||||||
id: filename
|
id: filename
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
|
PLATFORM_ARCH_ABI="$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")"
|
||||||
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
||||||
|
|
||||||
- name: Download ${{ steps.filename.outputs.filename }}
|
- name: Download ${{ steps.filename.outputs.filename }}
|
||||||
@@ -1206,84 +1273,6 @@ jobs:
|
|||||||
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
|
if: ${{ matrix.spec.test && matrix.spec.os != 'ubuntu-latest' }}
|
||||||
run: yarn affine @affine-test/affine-desktop e2e
|
run: yarn affine @affine-test/affine-desktop e2e
|
||||||
|
|
||||||
- name: Upload test results
|
|
||||||
if: always()
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: test-results-e2e-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
|
|
||||||
path: ./test-results
|
|
||||||
if-no-files-found: ignore
|
|
||||||
|
|
||||||
desktop-bundle-check:
|
|
||||||
name: Desktop bundle check (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }})
|
|
||||||
runs-on: ${{ matrix.spec.os }}
|
|
||||||
needs:
|
|
||||||
- build-electron-renderer
|
|
||||||
- build-native
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
spec:
|
|
||||||
- {
|
|
||||||
os: macos-latest,
|
|
||||||
platform: macos,
|
|
||||||
arch: x64,
|
|
||||||
target: x86_64-apple-darwin,
|
|
||||||
test: false,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: macos-latest,
|
|
||||||
platform: macos,
|
|
||||||
arch: arm64,
|
|
||||||
target: aarch64-apple-darwin,
|
|
||||||
test: true,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: ubuntu-latest,
|
|
||||||
platform: linux,
|
|
||||||
arch: x64,
|
|
||||||
target: x86_64-unknown-linux-gnu,
|
|
||||||
test: true,
|
|
||||||
}
|
|
||||||
- {
|
|
||||||
os: windows-latest,
|
|
||||||
platform: windows,
|
|
||||||
arch: x64,
|
|
||||||
target: x86_64-pc-windows-msvc,
|
|
||||||
test: true,
|
|
||||||
}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
timeout-minutes: 10
|
|
||||||
with:
|
|
||||||
extra-flags: workspaces focus @affine/electron @affine/monorepo @affine-test/affine-desktop @affine/nbstore @toeverything/infra
|
|
||||||
playwright-install: true
|
|
||||||
hard-link-nm: false
|
|
||||||
enableScripts: false
|
|
||||||
|
|
||||||
- name: Setup filename
|
|
||||||
id: filename
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
export PLATFORM_ARCH_ABI=$(node -e "console.log(require('@napi-rs/cli').parseTriple('${{ matrix.spec.target }}').platformArchABI)")
|
|
||||||
echo "filename=affine.$PLATFORM_ARCH_ABI.node" >> "$GITHUB_OUTPUT"
|
|
||||||
|
|
||||||
- name: Download ${{ steps.filename.outputs.filename }}
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: ${{ steps.filename.outputs.filename }}
|
|
||||||
path: ./packages/frontend/native
|
|
||||||
|
|
||||||
- name: Download web artifact
|
|
||||||
uses: ./.github/actions/download-web
|
|
||||||
with:
|
|
||||||
path: packages/frontend/apps/electron/resources/web-static
|
|
||||||
|
|
||||||
- name: Build Desktop Layers
|
|
||||||
run: yarn affine @affine/electron build
|
|
||||||
|
|
||||||
- name: Make bundle (macOS)
|
- name: Make bundle (macOS)
|
||||||
if: ${{ matrix.spec.target == 'aarch64-apple-darwin' }}
|
if: ${{ matrix.spec.target == 'aarch64-apple-darwin' }}
|
||||||
env:
|
env:
|
||||||
@@ -1323,6 +1312,14 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
yarn affine @affine/electron node ./scripts/macos-arm64-output-check.ts
|
yarn affine @affine/electron node ./scripts/macos-arm64-output-check.ts
|
||||||
|
|
||||||
|
- name: Upload test results
|
||||||
|
if: always()
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: test-results-e2e-${{ matrix.spec.os }}-${{ matrix.spec.arch }}
|
||||||
|
path: ./test-results
|
||||||
|
if-no-files-found: ignore
|
||||||
|
|
||||||
test-done:
|
test-done:
|
||||||
needs:
|
needs:
|
||||||
- analyze
|
- analyze
|
||||||
@@ -1336,8 +1333,9 @@ jobs:
|
|||||||
- e2e-blocksuite-cross-browser-test
|
- e2e-blocksuite-cross-browser-test
|
||||||
- e2e-mobile-test
|
- e2e-mobile-test
|
||||||
- unit-test
|
- unit-test
|
||||||
- build-native
|
- build-native-linux
|
||||||
- build-windows-native
|
- build-native-macos
|
||||||
|
- build-native-windows
|
||||||
- build-server-native
|
- build-server-native
|
||||||
- build-electron-renderer
|
- build-electron-renderer
|
||||||
- native-unit-test
|
- native-unit-test
|
||||||
@@ -1347,10 +1345,11 @@ jobs:
|
|||||||
- server-test
|
- server-test
|
||||||
- server-e2e-test
|
- server-e2e-test
|
||||||
- rust-test
|
- rust-test
|
||||||
|
- rust-test-filter
|
||||||
|
- copilot-test-filter
|
||||||
- copilot-api-test
|
- copilot-api-test
|
||||||
- copilot-e2e-test
|
- copilot-e2e-test
|
||||||
- desktop-test
|
- desktop-test
|
||||||
- desktop-bundle-check
|
|
||||||
- cloud-e2e-test
|
- cloud-e2e-test
|
||||||
if: always()
|
if: always()
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
8
.github/workflows/copilot-test.yml
vendored
8
.github/workflows/copilot-test.yml
vendored
@@ -10,7 +10,7 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
with:
|
with:
|
||||||
@@ -64,7 +64,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
@@ -134,7 +134,7 @@ jobs:
|
|||||||
ports:
|
ports:
|
||||||
- 9308:9308
|
- 9308:9308
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
@@ -167,7 +167,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
name: Post test result message
|
name: Post test result message
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
|
|||||||
5
.github/workflows/pr-title-lint.yml
vendored
5
.github/workflows/pr-title-lint.yml
vendored
@@ -16,10 +16,11 @@ jobs:
|
|||||||
check-pull-request-title:
|
check-pull-request-title:
|
||||||
name: Check pull request title
|
name: Check pull request title
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
if: ${{ github.event.action != 'edited' || github.event.changes.title != null }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
cache: 'yarn'
|
cache: 'yarn'
|
||||||
node-version-file: '.nvmrc'
|
node-version-file: '.nvmrc'
|
||||||
|
|||||||
2
.github/workflows/release-cloud.yml
vendored
2
.github/workflows/release-cloud.yml
vendored
@@ -35,7 +35,7 @@ jobs:
|
|||||||
- build-images
|
- build-images
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Deploy to ${{ inputs.build-type }}
|
- name: Deploy to ${{ inputs.build-type }}
|
||||||
uses: ./.github/actions/deploy
|
uses: ./.github/actions/deploy
|
||||||
with:
|
with:
|
||||||
|
|||||||
12
.github/workflows/release-desktop-platform.yml
vendored
12
.github/workflows/release-desktop-platform.yml
vendored
@@ -68,10 +68,8 @@ jobs:
|
|||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
SENTRY_RELEASE: ${{ inputs.app_version }}
|
SENTRY_RELEASE: ${{ inputs.app_version }}
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
|
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
@@ -103,7 +101,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Signing By Apple Developer ID
|
- name: Signing By Apple Developer ID
|
||||||
if: ${{ inputs.platform == 'darwin' && inputs.apple_codesign }}
|
if: ${{ inputs.platform == 'darwin' && inputs.apple_codesign }}
|
||||||
uses: apple-actions/import-codesign-certs@v5
|
uses: apple-actions/import-codesign-certs@v6
|
||||||
with:
|
with:
|
||||||
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
p12-file-base64: ${{ secrets.CERTIFICATES_P12 }}
|
||||||
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
p12-password: ${{ secrets.CERTIFICATES_P12_PASSWORD }}
|
||||||
@@ -176,18 +174,18 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir -p builds
|
mkdir -p builds
|
||||||
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ inputs.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.zip
|
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ inputs.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.zip
|
||||||
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.appimage
|
mv packages/frontend/apps/electron/out/*/make/AppImage/${{ inputs.arch }}/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.appimage
|
||||||
mv packages/frontend/apps/electron/out/*/make/deb/${{ inputs.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.deb
|
mv packages/frontend/apps/electron/out/*/make/deb/${{ inputs.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.deb
|
||||||
mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.flatpak
|
mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ inputs.arch }}.flatpak
|
||||||
|
|
||||||
- uses: actions/attest-build-provenance@v2
|
- uses: actions/attest-build-provenance@v4
|
||||||
if: ${{ inputs.platform == 'darwin' }}
|
if: ${{ inputs.platform == 'darwin' }}
|
||||||
with:
|
with:
|
||||||
subject-path: |
|
subject-path: |
|
||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.zip
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.zip
|
||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.dmg
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ inputs.arch }}.dmg
|
||||||
|
|
||||||
- uses: actions/attest-build-provenance@v2
|
- uses: actions/attest-build-provenance@v4
|
||||||
if: ${{ inputs.platform == 'linux' }}
|
if: ${{ inputs.platform == 'linux' }}
|
||||||
with:
|
with:
|
||||||
subject-path: |
|
subject-path: |
|
||||||
|
|||||||
90
.github/workflows/release-desktop.yml
vendored
90
.github/workflows/release-desktop.yml
vendored
@@ -48,7 +48,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -66,8 +66,6 @@ jobs:
|
|||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
SENTRY_RELEASE: ${{ inputs.app-version }}
|
SENTRY_RELEASE: ${{ inputs.app-version }}
|
||||||
RELEASE_VERSION: ${{ inputs.app-version }}
|
RELEASE_VERSION: ${{ inputs.app-version }}
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
|
|
||||||
- name: Upload web artifact
|
- name: Upload web artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -189,7 +187,7 @@ jobs:
|
|||||||
FILES_TO_BE_SIGNED_x64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_x64 }}
|
FILES_TO_BE_SIGNED_x64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_x64 }}
|
||||||
FILES_TO_BE_SIGNED_arm64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_arm64 }}
|
FILES_TO_BE_SIGNED_arm64: ${{ steps.get_files_to_be_signed.outputs.FILES_TO_BE_SIGNED_arm64 }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -203,13 +201,44 @@ jobs:
|
|||||||
nmHoistingLimits: workspaces
|
nmHoistingLimits: workspaces
|
||||||
env:
|
env:
|
||||||
npm_config_arch: ${{ matrix.spec.arch }}
|
npm_config_arch: ${{ matrix.spec.arch }}
|
||||||
- name: Download and overwrite packaged artifacts
|
- name: Download packaged artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: packaged-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
||||||
|
path: packaged-unsigned
|
||||||
|
- name: unzip packaged artifacts
|
||||||
|
run: Expand-Archive -Path packaged-unsigned/archive.zip -DestinationPath packages/frontend/apps/electron/out
|
||||||
|
- name: Download signed packaged file diff
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: signed-packaged-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
name: signed-packaged-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
||||||
path: .
|
path: signed-packaged-diff
|
||||||
- name: unzip file
|
- name: Apply signed packaged file diff
|
||||||
run: Expand-Archive -Path signed.zip -DestinationPath packages/frontend/apps/electron/out
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$DiffRoot = 'signed-packaged-diff/files'
|
||||||
|
$TargetRoot = 'packages/frontend/apps/electron/out'
|
||||||
|
if (!(Test-Path -LiteralPath $DiffRoot)) {
|
||||||
|
throw "Signed diff directory not found: $DiffRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path (Join-Path $DiffRoot '*') -Destination $TargetRoot -Recurse -Force
|
||||||
|
|
||||||
|
$ManifestPath = 'signed-packaged-diff/manifest.json'
|
||||||
|
if (Test-Path -LiteralPath $ManifestPath) {
|
||||||
|
$ManifestEntries = @(Get-Content -LiteralPath $ManifestPath | ConvertFrom-Json)
|
||||||
|
foreach ($Entry in $ManifestEntries) {
|
||||||
|
$TargetPath = Join-Path $TargetRoot $Entry.path
|
||||||
|
if (!(Test-Path -LiteralPath $TargetPath -PathType Leaf)) {
|
||||||
|
throw "Applied signed file not found: $($Entry.path)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$TargetHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $TargetPath).Hash
|
||||||
|
if ($TargetHash -ne $Entry.sha256) {
|
||||||
|
throw "Signed file hash mismatch: $($Entry.path)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- name: Make squirrel.windows installer
|
- name: Make squirrel.windows installer
|
||||||
run: yarn affine @affine/electron make-squirrel --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
run: yarn affine @affine/electron make-squirrel --platform=${{ matrix.spec.platform }} --arch=${{ matrix.spec.arch }}
|
||||||
@@ -269,13 +298,44 @@ jobs:
|
|||||||
arch: arm64
|
arch: arm64
|
||||||
runs-on: ${{ matrix.spec.runner }}
|
runs-on: ${{ matrix.spec.runner }}
|
||||||
steps:
|
steps:
|
||||||
- name: Download and overwrite installer artifacts
|
- name: Download installer artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: installer-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
||||||
|
path: installer-unsigned
|
||||||
|
- name: unzip installer artifacts
|
||||||
|
run: Expand-Archive -Path installer-unsigned/archive.zip -DestinationPath packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make
|
||||||
|
- name: Download signed installer file diff
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: signed-installer-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
name: signed-installer-${{ matrix.spec.platform }}-${{ matrix.spec.arch }}
|
||||||
path: .
|
path: signed-installer-diff
|
||||||
- name: unzip file
|
- name: Apply signed installer file diff
|
||||||
run: Expand-Archive -Path signed.zip -DestinationPath packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make
|
shell: pwsh
|
||||||
|
run: |
|
||||||
|
$DiffRoot = 'signed-installer-diff/files'
|
||||||
|
$TargetRoot = 'packages/frontend/apps/electron/out/${{ env.BUILD_TYPE }}/make'
|
||||||
|
if (!(Test-Path -LiteralPath $DiffRoot)) {
|
||||||
|
throw "Signed diff directory not found: $DiffRoot"
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -Path (Join-Path $DiffRoot '*') -Destination $TargetRoot -Recurse -Force
|
||||||
|
|
||||||
|
$ManifestPath = 'signed-installer-diff/manifest.json'
|
||||||
|
if (Test-Path -LiteralPath $ManifestPath) {
|
||||||
|
$ManifestEntries = @(Get-Content -LiteralPath $ManifestPath | ConvertFrom-Json)
|
||||||
|
foreach ($Entry in $ManifestEntries) {
|
||||||
|
$TargetPath = Join-Path $TargetRoot $Entry.path
|
||||||
|
if (!(Test-Path -LiteralPath $TargetPath -PathType Leaf)) {
|
||||||
|
throw "Applied signed file not found: $($Entry.path)"
|
||||||
|
}
|
||||||
|
|
||||||
|
$TargetHash = (Get-FileHash -Algorithm SHA256 -LiteralPath $TargetPath).Hash
|
||||||
|
if ($TargetHash -ne $Entry.sha256) {
|
||||||
|
throw "Signed file hash mismatch: $($Entry.path)"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- name: Save artifacts
|
- name: Save artifacts
|
||||||
run: |
|
run: |
|
||||||
@@ -284,7 +344,7 @@ jobs:
|
|||||||
mv packages/frontend/apps/electron/out/*/make/squirrel.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe
|
mv packages/frontend/apps/electron/out/*/make/squirrel.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe
|
||||||
mv packages/frontend/apps/electron/out/*/make/nsis.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
|
mv packages/frontend/apps/electron/out/*/make/nsis.windows/${{ matrix.spec.arch }}/*.exe ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
|
||||||
|
|
||||||
- uses: actions/attest-build-provenance@v2
|
- uses: actions/attest-build-provenance@v4
|
||||||
with:
|
with:
|
||||||
subject-path: |
|
subject-path: |
|
||||||
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
|
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
|
||||||
@@ -309,7 +369,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Download Artifacts (macos-x64)
|
- name: Download Artifacts (macos-x64)
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
@@ -335,7 +395,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
name: affine-linux-x64-builds
|
name: affine-linux-x64-builds
|
||||||
path: ./release
|
path: ./release
|
||||||
- uses: actions/setup-node@v4
|
- uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: 20
|
node-version: 20
|
||||||
- name: Copy Selfhost Release Files
|
- name: Copy Selfhost Release Files
|
||||||
|
|||||||
30
.github/workflows/release-mobile.yml
vendored
30
.github/workflows/release-mobile.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
environment: ${{ inputs.build-type }}
|
environment: ${{ inputs.build-type }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -39,8 +39,6 @@ jobs:
|
|||||||
run: yarn affine @affine/ios build
|
run: yarn affine @affine/ios build
|
||||||
env:
|
env:
|
||||||
PUBLIC_PATH: '/'
|
PUBLIC_PATH: '/'
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
SENTRY_PROJECT: 'affine'
|
SENTRY_PROJECT: 'affine'
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
@@ -56,7 +54,7 @@ jobs:
|
|||||||
build-android-web:
|
build-android-web:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -69,8 +67,6 @@ jobs:
|
|||||||
run: yarn affine @affine/android build
|
run: yarn affine @affine/android build
|
||||||
env:
|
env:
|
||||||
PUBLIC_PATH: '/'
|
PUBLIC_PATH: '/'
|
||||||
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
|
||||||
GA4_MEASUREMENT_ID: ${{ secrets.GA4_MEASUREMENT_ID }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
SENTRY_PROJECT: 'affine'
|
SENTRY_PROJECT: 'affine'
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
@@ -87,7 +83,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-ios-web
|
- build-ios-web
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -112,13 +108,13 @@ jobs:
|
|||||||
enableScripts: false
|
enableScripts: false
|
||||||
- uses: maxim-lobanov/setup-xcode@v1
|
- uses: maxim-lobanov/setup-xcode@v1
|
||||||
with:
|
with:
|
||||||
xcode-version: 16.4
|
xcode-version: 26.2
|
||||||
- name: Install Swiftformat
|
- name: Install Swiftformat
|
||||||
run: brew install swiftformat
|
run: brew install swiftformat
|
||||||
- name: Cap sync
|
- name: Cap sync
|
||||||
run: yarn workspace @affine/ios sync
|
run: yarn workspace @affine/ios sync
|
||||||
- name: Signing By Apple Developer ID
|
- name: Signing By Apple Developer ID
|
||||||
uses: apple-actions/import-codesign-certs@v5
|
uses: apple-actions/import-codesign-certs@v6
|
||||||
id: import-codesign-certs
|
id: import-codesign-certs
|
||||||
with:
|
with:
|
||||||
p12-file-base64: ${{ secrets.CERTIFICATES_P12_MOBILE }}
|
p12-file-base64: ${{ secrets.CERTIFICATES_P12_MOBILE }}
|
||||||
@@ -132,9 +128,9 @@ jobs:
|
|||||||
- name: Testflight
|
- name: Testflight
|
||||||
working-directory: packages/frontend/apps/ios/App
|
working-directory: packages/frontend/apps/ios/App
|
||||||
run: |
|
run: |
|
||||||
echo -n "${{ env.BUILD_PROVISION_PROFILE }}" | base64 --decode -o $PP_PATH
|
printf '%s' "$BUILD_PROVISION_PROFILE" | base64 --decode -o "$PP_PATH"
|
||||||
mkdir -p ~/Library/MobileDevice/Provisioning\ Profiles
|
mkdir -p "$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||||
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
|
cp "$PP_PATH" "$HOME/Library/MobileDevice/Provisioning Profiles"
|
||||||
fastlane beta
|
fastlane beta
|
||||||
env:
|
env:
|
||||||
BUILD_TARGET: distribution
|
BUILD_TARGET: distribution
|
||||||
@@ -151,7 +147,7 @@ jobs:
|
|||||||
needs:
|
needs:
|
||||||
- build-android-web
|
- build-android-web
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Setup Version
|
- name: Setup Version
|
||||||
uses: ./.github/actions/setup-version
|
uses: ./.github/actions/setup-version
|
||||||
with:
|
with:
|
||||||
@@ -164,7 +160,9 @@ jobs:
|
|||||||
- name: Load Google Service file
|
- name: Load Google Service file
|
||||||
env:
|
env:
|
||||||
DATA: ${{ secrets.FIREBASE_ANDROID_GOOGLE_SERVICE_JSON }}
|
DATA: ${{ secrets.FIREBASE_ANDROID_GOOGLE_SERVICE_JSON }}
|
||||||
run: echo $DATA | base64 -di > packages/frontend/apps/android/App/app/google-services.json
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
printf '%s' "$DATA" | base64 -di > packages/frontend/apps/android/App/app/google-services.json
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: ./.github/actions/setup-node
|
uses: ./.github/actions/setup-node
|
||||||
timeout-minutes: 10
|
timeout-minutes: 10
|
||||||
@@ -182,7 +180,7 @@ jobs:
|
|||||||
no-build: 'true'
|
no-build: 'true'
|
||||||
- name: Cap sync
|
- name: Cap sync
|
||||||
run: yarn workspace @affine/android cap sync
|
run: yarn workspace @affine/android cap sync
|
||||||
- uses: actions/setup-python@v5
|
- uses: actions/setup-python@v6
|
||||||
with:
|
with:
|
||||||
python-version: '3.13'
|
python-version: '3.13'
|
||||||
- name: Auth gcloud
|
- name: Auth gcloud
|
||||||
@@ -194,7 +192,7 @@ jobs:
|
|||||||
token_format: 'access_token'
|
token_format: 'access_token'
|
||||||
project_id: '${{ secrets.GCP_PROJECT_ID }}'
|
project_id: '${{ secrets.GCP_PROJECT_ID }}'
|
||||||
access_token_scopes: 'https://www.googleapis.com/auth/androidpublisher'
|
access_token_scopes: 'https://www.googleapis.com/auth/androidpublisher'
|
||||||
- uses: actions/setup-java@v4
|
- uses: actions/setup-java@v5
|
||||||
with:
|
with:
|
||||||
distribution: 'temurin'
|
distribution: 'temurin'
|
||||||
java-version: '21'
|
java-version: '21'
|
||||||
|
|||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -55,7 +55,7 @@ jobs:
|
|||||||
GIT_SHORT_HASH: ${{ steps.prepare.outputs.GIT_SHORT_HASH }}
|
GIT_SHORT_HASH: ${{ steps.prepare.outputs.GIT_SHORT_HASH }}
|
||||||
BUILD_TYPE: ${{ steps.prepare.outputs.BUILD_TYPE }}
|
BUILD_TYPE: ${{ steps.prepare.outputs.BUILD_TYPE }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v6
|
||||||
- name: Prepare Release
|
- name: Prepare Release
|
||||||
id: prepare
|
id: prepare
|
||||||
uses: ./.github/actions/prepare-release
|
uses: ./.github/actions/prepare-release
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- name: Decide whether to release
|
- name: Decide whether to release
|
||||||
id: decide
|
id: decide
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v8
|
||||||
with:
|
with:
|
||||||
script: |
|
script: |
|
||||||
const buildType = '${{ needs.prepare.outputs.BUILD_TYPE }}'
|
const buildType = '${{ needs.prepare.outputs.BUILD_TYPE }}'
|
||||||
@@ -148,7 +148,7 @@ jobs:
|
|||||||
name: Wait for approval
|
name: Wait for approval
|
||||||
with:
|
with:
|
||||||
secret: ${{ secrets.GITHUB_TOKEN }}
|
secret: ${{ secrets.GITHUB_TOKEN }}
|
||||||
approvers: darkskygit,pengx17,L-Sun,EYHN
|
approvers: darkskygit
|
||||||
minimum-approvals: 1
|
minimum-approvals: 1
|
||||||
fail-on-denial: true
|
fail-on-denial: true
|
||||||
issue-title: Please confirm to release docker image
|
issue-title: Please confirm to release docker image
|
||||||
|
|||||||
72
.github/workflows/sync-i18n.yml
vendored
72
.github/workflows/sync-i18n.yml
vendored
@@ -1,72 +0,0 @@
|
|||||||
name: Sync I18n with Crowdin
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- canary
|
|
||||||
paths:
|
|
||||||
- 'packages/frontend/i18n/**'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
synchronize-with-crowdin:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Crowdin action
|
|
||||||
id: crowdin
|
|
||||||
uses: crowdin/github-action@v2
|
|
||||||
with:
|
|
||||||
upload_sources: true
|
|
||||||
upload_translations: false
|
|
||||||
download_translations: true
|
|
||||||
auto_approve_imported: true
|
|
||||||
import_eq_suggestions: true
|
|
||||||
export_only_approved: true
|
|
||||||
skip_untranslated_strings: true
|
|
||||||
localization_branch_name: l10n_crowdin_translations
|
|
||||||
create_pull_request: true
|
|
||||||
pull_request_title: 'chore(i18n): sync translations'
|
|
||||||
pull_request_body: 'New Crowdin translations by [Crowdin GH Action](https://github.com/crowdin/github-action)'
|
|
||||||
pull_request_base_branch_name: 'canary'
|
|
||||||
config: packages/frontend/i18n/crowdin.yml
|
|
||||||
env:
|
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
CROWDIN_PROJECT_ID: ${{ secrets.CROWDIN_PROJECT_ID }}
|
|
||||||
CROWDIN_PERSONAL_TOKEN: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
|
||||||
i18n-codegen:
|
|
||||||
needs: synchronize-with-crowdin
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: write
|
|
||||||
pull-requests: write
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
ref: l10n_crowdin_translations
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
electron-install: false
|
|
||||||
full-cache: true
|
|
||||||
|
|
||||||
- name: Run i18n codegen
|
|
||||||
run: yarn affine @affine/i18n build
|
|
||||||
|
|
||||||
- name: Commit changes
|
|
||||||
run: |
|
|
||||||
git config user.name "github-actions[bot]"
|
|
||||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
||||||
git add .
|
|
||||||
git commit -m "chore(i18n): i18n codegen"
|
|
||||||
git push origin l10n_crowdin_translations
|
|
||||||
40
.github/workflows/windows-signer.yml
vendored
40
.github/workflows/windows-signer.yml
vendored
@@ -30,13 +30,43 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd ${{ env.ARCHIVE_DIR }}/out
|
cd ${{ env.ARCHIVE_DIR }}/out
|
||||||
signtool sign /tr http://timestamp.globalsign.com/tsa/r6advanced1 /td sha256 /fd sha256 /a ${{ inputs.files }}
|
signtool sign /tr http://timestamp.globalsign.com/tsa/r6advanced1 /td sha256 /fd sha256 /a ${{ inputs.files }}
|
||||||
- name: zip file
|
- name: collect signed file diff
|
||||||
shell: cmd
|
shell: powershell -NoProfile -NonInteractive -ExecutionPolicy Bypass -File {0}
|
||||||
run: |
|
run: |
|
||||||
cd ${{ env.ARCHIVE_DIR }}
|
$OutDir = Join-Path '${{ env.ARCHIVE_DIR }}' 'out'
|
||||||
7za a signed.zip .\out\*
|
$DiffDir = Join-Path '${{ env.ARCHIVE_DIR }}' 'signed-diff'
|
||||||
|
$FilesDir = Join-Path $DiffDir 'files'
|
||||||
|
New-Item -ItemType Directory -Path $FilesDir -Force | Out-Null
|
||||||
|
|
||||||
|
$SignedFiles = [regex]::Matches('${{ inputs.files }}', '"([^"]+)"') | ForEach-Object { $_.Groups[1].Value }
|
||||||
|
if ($SignedFiles.Count -eq 0) {
|
||||||
|
throw 'No files to sign were provided.'
|
||||||
|
}
|
||||||
|
|
||||||
|
$Manifest = @()
|
||||||
|
foreach ($RelativePath in $SignedFiles) {
|
||||||
|
$SourcePath = Join-Path $OutDir $RelativePath
|
||||||
|
if (!(Test-Path -LiteralPath $SourcePath -PathType Leaf)) {
|
||||||
|
throw "Signed file not found: $RelativePath"
|
||||||
|
}
|
||||||
|
|
||||||
|
$TargetPath = Join-Path $FilesDir $RelativePath
|
||||||
|
$TargetDir = Split-Path -Parent $TargetPath
|
||||||
|
if ($TargetDir) {
|
||||||
|
New-Item -ItemType Directory -Path $TargetDir -Force | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Copy-Item -LiteralPath $SourcePath -Destination $TargetPath -Force
|
||||||
|
$Manifest += [PSCustomObject]@{
|
||||||
|
path = $RelativePath
|
||||||
|
sha256 = (Get-FileHash -Algorithm SHA256 -LiteralPath $TargetPath).Hash
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$Manifest | ConvertTo-Json -Depth 4 | Out-File -FilePath (Join-Path $DiffDir 'manifest.json') -Encoding utf8
|
||||||
|
Write-Host "Collected $($SignedFiles.Count) signed files."
|
||||||
- name: upload
|
- name: upload
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: signed-${{ inputs.artifact-name }}
|
name: signed-${{ inputs.artifact-name }}
|
||||||
path: ${{ env.ARCHIVE_DIR }}/signed.zip
|
path: ${{ env.ARCHIVE_DIR }}/signed-diff
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -47,8 +47,8 @@ testem.log
|
|||||||
.pnpm-debug.log
|
.pnpm-debug.log
|
||||||
/typings
|
/typings
|
||||||
tsconfig.tsbuildinfo
|
tsconfig.tsbuildinfo
|
||||||
rfc*.md
|
.context
|
||||||
todo.md
|
/*.md
|
||||||
|
|
||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|||||||
@@ -5,6 +5,10 @@
|
|||||||
"correctness": "error",
|
"correctness": "error",
|
||||||
"perf": "error"
|
"perf": "error"
|
||||||
},
|
},
|
||||||
|
"env": {
|
||||||
|
"builtin": true,
|
||||||
|
"es2026": true
|
||||||
|
},
|
||||||
"ignorePatterns": [
|
"ignorePatterns": [
|
||||||
"**/node_modules",
|
"**/node_modules",
|
||||||
".yarn",
|
".yarn",
|
||||||
@@ -44,6 +48,34 @@
|
|||||||
"**/test-blocks.json"
|
"**/test-blocks.json"
|
||||||
],
|
],
|
||||||
"rules": {
|
"rules": {
|
||||||
|
"no-empty-static-block": "error",
|
||||||
|
"no-misleading-character-class": "error",
|
||||||
|
"no-new-native-nonconstructor": "error",
|
||||||
|
"no-unused-private-class-members": "error",
|
||||||
|
"no-useless-backreference": "error",
|
||||||
|
"react/display-name": "error",
|
||||||
|
"react/rules-of-hooks": "error",
|
||||||
|
"react/exhaustive-deps": "warn",
|
||||||
|
"@typescript-eslint/prefer-for-of": "error",
|
||||||
|
"@typescript-eslint/no-unsafe-function-type": "error",
|
||||||
|
"@typescript-eslint/no-wrapper-object-types": "error",
|
||||||
|
"no-restricted-imports": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"patterns": [
|
||||||
|
{
|
||||||
|
"group": ["**/dist"],
|
||||||
|
"message": "Don't import from dist",
|
||||||
|
"allowTypeImports": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"group": ["**/src"],
|
||||||
|
"message": "Don't import from src",
|
||||||
|
"allowTypeImports": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
"no-await-in-loop": "allow",
|
"no-await-in-loop": "allow",
|
||||||
"no-redeclare": "allow",
|
"no-redeclare": "allow",
|
||||||
"promise/no-callback-in-promise": "allow",
|
"promise/no-callback-in-promise": "allow",
|
||||||
@@ -70,6 +102,14 @@
|
|||||||
"no-func-assign": "error",
|
"no-func-assign": "error",
|
||||||
"no-global-assign": "error",
|
"no-global-assign": "error",
|
||||||
"no-unused-vars": "error",
|
"no-unused-vars": "error",
|
||||||
|
"no-unused-expressions": [
|
||||||
|
"error",
|
||||||
|
{
|
||||||
|
"allowShortCircuit": true,
|
||||||
|
"allowTernary": true,
|
||||||
|
"allowTaggedTemplates": true
|
||||||
|
}
|
||||||
|
],
|
||||||
"no-ex-assign": "error",
|
"no-ex-assign": "error",
|
||||||
"no-loss-of-precision": "error",
|
"no-loss-of-precision": "error",
|
||||||
"no-fallthrough": "error",
|
"no-fallthrough": "error",
|
||||||
@@ -126,6 +166,7 @@
|
|||||||
"react/no-render-return-value": "error",
|
"react/no-render-return-value": "error",
|
||||||
"react/jsx-no-target-blank": "error",
|
"react/jsx-no-target-blank": "error",
|
||||||
"react/jsx-no-comment-textnodes": "error",
|
"react/jsx-no-comment-textnodes": "error",
|
||||||
|
"react/no-array-index-key": "off",
|
||||||
"typescript/consistent-type-imports": "error",
|
"typescript/consistent-type-imports": "error",
|
||||||
"typescript/no-non-null-assertion": "error",
|
"typescript/no-non-null-assertion": "error",
|
||||||
"typescript/triple-slash-reference": "error",
|
"typescript/triple-slash-reference": "error",
|
||||||
@@ -241,6 +282,42 @@
|
|||||||
"typescript/consistent-type-imports": "off",
|
"typescript/consistent-type-imports": "off",
|
||||||
"import/no-cycle": "off"
|
"import/no-cycle": "off"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"packages/**/*.{ts,tsx}",
|
||||||
|
"tools/**/*.{ts,tsx}",
|
||||||
|
"blocksuite/**/*.{ts,tsx}"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"react/exhaustive-deps": [
|
||||||
|
"warn",
|
||||||
|
{
|
||||||
|
"additionalHooks": "(useAsyncCallback|useCatchEventCallback|useDraggable|useDropTarget|useRefEffect)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"**/__tests__/**/*",
|
||||||
|
"**/*.stories.tsx",
|
||||||
|
"**/*.spec.ts",
|
||||||
|
"**/tests/**/*",
|
||||||
|
"scripts/**/*",
|
||||||
|
"**/benchmark/**/*",
|
||||||
|
"**/__debug__/**/*",
|
||||||
|
"**/e2e/**/*"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"no-restricted-imports": "off"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"files": ["**/*.{ts,js,mjs}"],
|
||||||
|
"rules": {
|
||||||
|
"react/rules-of-hooks": "off"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
13
.vscode/settings.template.json
vendored
13
.vscode/settings.template.json
vendored
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"eslint.packageManager": "yarn",
|
"prisma.pinToPrisma6": true,
|
||||||
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
"editor.defaultFormatter": "esbenp.prettier-vscode",
|
||||||
"editor.formatOnSave": true,
|
"editor.formatOnSave": true,
|
||||||
"editor.formatOnSaveMode": "file",
|
"editor.formatOnSaveMode": "file",
|
||||||
@@ -14,11 +14,13 @@
|
|||||||
"testid",
|
"testid",
|
||||||
"schemars"
|
"schemars"
|
||||||
],
|
],
|
||||||
|
"explorer.fileNesting.enabled": true,
|
||||||
"explorer.fileNesting.patterns": {
|
"explorer.fileNesting.patterns": {
|
||||||
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.d.ts.map",
|
"*.js": "${capture}.js.map, ${capture}.min.js, ${capture}.d.ts, ${capture}.d.ts.map",
|
||||||
"package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lighthouserc.*, .lintstagedrc*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, api-extractor.json, apollo.config.*, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, crowdin*, cypress.*, dangerfile*, dlint.json, dprint.json, firebase.json, grunt*, gulp*, histoire.config.*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lighthouserc.*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, package.nls*.json, phpcs.xml, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, pyrightconfig.json, release-tasks.sh, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, vitest.config.*, webpack*, workspace.json, xo.config.*, yarn*, babel.*, .babelrc, project.json",
|
"package.json": ".browserslist*, .circleci*, .codecov, .commitlint*, .cz-config.js, .czrc, .dlint.json, .dprint.json, .editorconfig, .eslint*, eslint.*, .firebase*, .flowconfig, .github*, .gitlab*, .gitpod*, .huskyrc*, .jslint*, .lighthouserc.*, .lintstagedrc*, .markdownlint*, .mocha*, .node-version, .nodemon*, .npm*, .nvmrc, .pm2*, .pnp.*, .pnpm*, .prettier*, .releaserc*, .sentry*, .stackblitz*, .styleci*, .stylelint*, .tazerc*, .textlint*, .tool-versions, .travis*, .versionrc*, .vscode*, .watchman*, .xo-config*, .yamllint*, .yarnrc*, Procfile, api-extractor.json, apollo.config.*, appveyor*, ava.config.*, azure-pipelines*, bower.json, build.config.*, commitlint*, dangerfile*, dlint.json, dprint.json, firebase.json, grunt*, gulp*, histoire.config.*, jasmine.*, jenkins*, jest.config.*, jsconfig.*, karma*, lerna*, lighthouserc.*, lint-staged*, nest-cli.*, netlify*, nodemon*, nx.*, package-lock.json, package.nls*.json, phpcs.xml, playwright.config.*, pm2.*, pnpm*, prettier*, pullapprove*, puppeteer.config.*, pyrightconfig.json, release-tasks.sh, renovate*, rollup.config.*, stylelint*, tsconfig.*, tsdoc.*, tslint*, tsup.config.*, turbo*, typedoc*, unlighthouse*, vercel*, vetur.config.*, vitest.*, webpack*, workspace.json, xo.config.*, yarn*, babel.*, .babelrc, project.json, .oxlintrc.json, oxlint.json, nyc.config.*",
|
||||||
"Cargo.toml": "Cargo.lock",
|
"Cargo.toml": "Cargo.lock, rust-toolchain*, rustfmt.toml, .taplo.toml",
|
||||||
"README.md": "LICENSE, CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md"
|
"README.md": "LICENSE*, CHANGELOG.md, CODE_OF_CONDUCT.md, CONTRIBUTING.md, SECURITY.md, README.*",
|
||||||
|
".gitignore": ".gitattributes, .dockerignore, .eslintignore, .prettierignore, .stylelintignore, .tslintignore, .yarnignore"
|
||||||
},
|
},
|
||||||
"[rust]": {
|
"[rust]": {
|
||||||
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
"editor.defaultFormatter": "rust-lang.rust-analyzer"
|
||||||
@@ -32,5 +34,6 @@
|
|||||||
"vitest.include": ["packages/**/*.spec.ts", "packages/**/*.spec.tsx"],
|
"vitest.include": ["packages/**/*.spec.ts", "packages/**/*.spec.tsx"],
|
||||||
"rust-analyzer.check.extraEnv": {
|
"rust-analyzer.check.extraEnv": {
|
||||||
"DATABASE_URL": "sqlite:affine.db"
|
"DATABASE_URL": "sqlite:affine.db"
|
||||||
}
|
},
|
||||||
|
"typescript.tsdk": "node_modules/typescript/lib"
|
||||||
}
|
}
|
||||||
|
|||||||
942
.yarn/releases/yarn-4.12.0.cjs
vendored
942
.yarn/releases/yarn-4.12.0.cjs
vendored
File diff suppressed because one or more lines are too long
940
.yarn/releases/yarn-4.13.0.cjs
vendored
Executable file
940
.yarn/releases/yarn-4.13.0.cjs
vendored
Executable file
File diff suppressed because one or more lines are too long
@@ -12,4 +12,4 @@ npmPublishAccess: public
|
|||||||
|
|
||||||
npmRegistryServer: "https://registry.npmjs.org"
|
npmRegistryServer: "https://registry.npmjs.org"
|
||||||
|
|
||||||
yarnPath: .yarn/releases/yarn-4.12.0.cjs
|
yarnPath: .yarn/releases/yarn-4.13.0.cjs
|
||||||
|
|||||||
3083
Cargo.lock
generated
3083
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
25
Cargo.toml
25
Cargo.toml
@@ -36,17 +36,30 @@ resolver = "3"
|
|||||||
criterion2 = { version = "3", default-features = false }
|
criterion2 = { version = "3", default-features = false }
|
||||||
crossbeam-channel = "0.5"
|
crossbeam-channel = "0.5"
|
||||||
dispatch2 = "0.3"
|
dispatch2 = "0.3"
|
||||||
docx-parser = { git = "https://github.com/toeverything/docx-parser" }
|
docx-parser = { git = "https://github.com/toeverything/docx-parser", rev = "380beea" }
|
||||||
dotenvy = "0.15"
|
dotenvy = "0.15"
|
||||||
file-format = { version = "0.28", features = ["reader"] }
|
file-format = { version = "0.28", features = ["reader"] }
|
||||||
homedir = "0.3"
|
homedir = "0.3"
|
||||||
|
image = { version = "0.25.9", default-features = false, features = [
|
||||||
|
"bmp",
|
||||||
|
"gif",
|
||||||
|
"jpeg",
|
||||||
|
"png",
|
||||||
|
"webp",
|
||||||
|
] }
|
||||||
infer = { version = "0.19.0" }
|
infer = { version = "0.19.0" }
|
||||||
lasso = { version = "0.7", features = ["multi-threaded"] }
|
lasso = { version = "0.7", features = ["multi-threaded"] }
|
||||||
lib0 = { version = "0.16", features = ["lib0-serde"] }
|
lib0 = { version = "0.16", features = ["lib0-serde"] }
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
libwebp-sys = "0.14.2"
|
||||||
|
little_exif = "0.6.23"
|
||||||
|
llm_adapter = { version = "0.1.3", default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
loom = { version = "0.7", features = ["checkpoint"] }
|
loom = { version = "0.7", features = ["checkpoint"] }
|
||||||
|
lru = "0.16"
|
||||||
|
matroska = "0.30"
|
||||||
memory-indexer = "0.3.0"
|
memory-indexer = "0.3.0"
|
||||||
|
mermaid-rs-renderer = { git = "https://github.com/toeverything/mermaid-rs-renderer", rev = "fba9097", default-features = false }
|
||||||
mimalloc = "0.1"
|
mimalloc = "0.1"
|
||||||
mp4parse = "0.17"
|
mp4parse = "0.17"
|
||||||
nanoid = "0.4"
|
nanoid = "0.4"
|
||||||
@@ -63,6 +76,7 @@ resolver = "3"
|
|||||||
notify = { version = "8", features = ["serde"] }
|
notify = { version = "8", features = ["serde"] }
|
||||||
objc2 = "0.6"
|
objc2 = "0.6"
|
||||||
objc2-foundation = "0.3"
|
objc2-foundation = "0.3"
|
||||||
|
ogg = "0.9"
|
||||||
once_cell = "1"
|
once_cell = "1"
|
||||||
ordered-float = "5"
|
ordered-float = "5"
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
@@ -71,6 +85,7 @@ resolver = "3"
|
|||||||
phf = { version = "0.11", features = ["macros"] }
|
phf = { version = "0.11", features = ["macros"] }
|
||||||
proptest = "1.3"
|
proptest = "1.3"
|
||||||
proptest-derive = "0.5"
|
proptest-derive = "0.5"
|
||||||
|
pulldown-cmark = "0.13"
|
||||||
rand = "0.9"
|
rand = "0.9"
|
||||||
rand_chacha = "0.9"
|
rand_chacha = "0.9"
|
||||||
rand_distr = "0.5"
|
rand_distr = "0.5"
|
||||||
@@ -109,6 +124,14 @@ resolver = "3"
|
|||||||
tree-sitter-rust = { version = "0.24" }
|
tree-sitter-rust = { version = "0.24" }
|
||||||
tree-sitter-scala = { version = "0.24" }
|
tree-sitter-scala = { version = "0.24" }
|
||||||
tree-sitter-typescript = { version = "0.23" }
|
tree-sitter-typescript = { version = "0.23" }
|
||||||
|
typst = "0.14.2"
|
||||||
|
typst-as-lib = { version = "0.15.4", default-features = false, features = [
|
||||||
|
"packages",
|
||||||
|
"typst-kit-embed-fonts",
|
||||||
|
"typst-kit-fonts",
|
||||||
|
"ureq",
|
||||||
|
] }
|
||||||
|
typst-svg = "0.14.2"
|
||||||
uniffi = "0.29"
|
uniffi = "0.29"
|
||||||
url = { version = "2.5" }
|
url = { version = "2.5" }
|
||||||
uuid = "1.8"
|
uuid = "1.8"
|
||||||
|
|||||||
49
README.md
49
README.md
@@ -21,23 +21,6 @@
|
|||||||
<br/>
|
<br/>
|
||||||
<br/>
|
<br/>
|
||||||
|
|
||||||
<div align="left" valign="middle">
|
|
||||||
<a href="https://runblaze.dev">
|
|
||||||
<picture>
|
|
||||||
<source media="(prefers-color-scheme: dark)" srcset="https://www.runblaze.dev/logo_dark.png">
|
|
||||||
<img align="right" src="https://www.runblaze.dev/logo_light.png" height="102px"/>
|
|
||||||
</picture>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<br style="display: none;"/>
|
|
||||||
|
|
||||||
_Special thanks to [Blaze](https://runblaze.dev) for their support of this project. They provide high-performance Apple Silicon macOS and Linux (AMD64 & ARM64) runners for GitHub Actions, greatly reducing our automated build times._
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<br/>
|
|
||||||
<br/>
|
|
||||||
|
|
||||||
<div align="center">
|
<div align="center">
|
||||||
<a href="https://affine.pro">Home Page</a> |
|
<a href="https://affine.pro">Home Page</a> |
|
||||||
<a href="https://affine.pro/redirect/discord">Discord</a> |
|
<a href="https://affine.pro/redirect/discord">Discord</a> |
|
||||||
@@ -107,10 +90,10 @@ Thanks for checking us out, we appreciate your interest and sincerely hope that
|
|||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
| Bug Reports | Feature Requests | Questions/Discussions | AFFiNE Community |
|
| Bug Reports | Feature Requests | Questions/Discussions | AFFiNE Community |
|
||||||
| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------- |
|
| --------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------- | ----------------------------------------------------------------- |
|
||||||
| [Create a bug report](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=bug%2Cproduct-review&template=BUG-REPORT.yml&title=TITLE) | [Submit a feature request](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=feat%2Cproduct-review&template=FEATURE-REQUEST.yml&title=TITLE) | [Check GitHub Discussion](https://github.com/toeverything/AFFiNE/discussions) | [Vist the AFFiNE Community](https://community.affine.pro) |
|
| [Create a bug report](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=bug%2Cproduct-review&template=BUG-REPORT.yml&title=TITLE) | [Submit a feature request](https://github.com/toeverything/AFFiNE/issues/new?assignees=&labels=feat%2Cproduct-review&template=FEATURE-REQUEST.yml&title=TITLE) | [Check GitHub Discussion](https://github.com/toeverything/AFFiNE/discussions) | [Visit the AFFiNE's Discord](https://affine.pro/redirect/discord) |
|
||||||
| Something isn't working as expected | An idea for a new feature, or improvements | Discuss and ask questions | A place to ask, learn and engage with others |
|
| Something isn't working as expected | An idea for a new feature, or improvements | Discuss and ask questions | A place to ask, learn and engage with others |
|
||||||
|
|
||||||
Calling all developers, testers, tech writers and more! Contributions of all types are more than welcome, you can read more in [docs/types-of-contributions.md](docs/types-of-contributions.md). If you are interested in contributing code, read our [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and feel free to check out our GitHub issues to get stuck in to show us what you’re made of.
|
Calling all developers, testers, tech writers and more! Contributions of all types are more than welcome, you can read more in [docs/types-of-contributions.md](docs/types-of-contributions.md). If you are interested in contributing code, read our [docs/CONTRIBUTING.md](docs/CONTRIBUTING.md) and feel free to check out our GitHub issues to get stuck in to show us what you’re made of.
|
||||||
|
|
||||||
@@ -118,11 +101,9 @@ Calling all developers, testers, tech writers and more! Contributions of all typ
|
|||||||
|
|
||||||
For **bug reports**, **feature requests** and other **suggestions** you can also [create a new issue](https://github.com/toeverything/AFFiNE/issues/new/choose) and choose the most appropriate template for your feedback.
|
For **bug reports**, **feature requests** and other **suggestions** you can also [create a new issue](https://github.com/toeverything/AFFiNE/issues/new/choose) and choose the most appropriate template for your feedback.
|
||||||
|
|
||||||
For **translation** and **language support** you can visit our [i18n General Space](https://community.affine.pro/c/i18n-general).
|
For **translation** and **language support** you can visit our [Discord](https://affine.pro/redirect/discord).
|
||||||
|
|
||||||
Looking for **other ways to contribute** and wondering where to start? Check out the [AFFiNE Ambassador program](https://community.affine.pro/c/start-here/affine-ambassador), we work closely with passionate community members and provide them with a wide range of support and resources.
|
If you have questions, you are welcome to contact us. One of the best places to get more info and learn more is in the [Discord](https://affine.pro/redirect/discord) where you can engage with other like-minded individuals.
|
||||||
|
|
||||||
If you have questions, you are welcome to contact us. One of the best places to get more info and learn more is in the [AFFiNE Community](https://community.affine.pro) where you can engage with other like-minded individuals.
|
|
||||||
|
|
||||||
## Templates
|
## Templates
|
||||||
|
|
||||||
@@ -169,8 +150,10 @@ Welcome to the AFFiNE blog section! Here, you’ll find the latest insights, tip
|
|||||||
We would also like to give thanks to open-source projects that make AFFiNE possible:
|
We would also like to give thanks to open-source projects that make AFFiNE possible:
|
||||||
|
|
||||||
- [Blocksuite](https://github.com/toeverything/BlockSuite) - 💠 BlockSuite is the open-source collaborative editor project behind AFFiNE.
|
- [Blocksuite](https://github.com/toeverything/BlockSuite) - 💠 BlockSuite is the open-source collaborative editor project behind AFFiNE.
|
||||||
|
- [y-octo](https://github.com/y-crdt/y-octo) - 🐙 y-octo is a native, high-performance, thread-safe YJS CRDT implementation, serving as the core engine enabling the AFFiNE Client/Server to achieve "local-first" functionality.
|
||||||
- [OctoBase](https://github.com/toeverything/OctoBase) - 🐙 OctoBase is the open-source database behind AFFiNE, local-first, yet collaborative. A light-weight, scalable, data engine written in Rust.
|
- [OctoBase](https://github.com/toeverything/OctoBase) - 🐙 OctoBase is the open-source database behind AFFiNE, local-first, yet collaborative. A light-weight, scalable, data engine written in Rust.
|
||||||
- [yjs](https://github.com/yjs/yjs) - Fundamental support of CRDTs for our implementation on state management and data sync.
|
|
||||||
|
- [yjs](https://github.com/yjs/yjs) - Fundamental support of CRDTs for our implementation on state management and data sync on web.
|
||||||
- [electron](https://github.com/electron/electron) - Build cross-platform desktop apps with JavaScript, HTML, and CSS.
|
- [electron](https://github.com/electron/electron) - Build cross-platform desktop apps with JavaScript, HTML, and CSS.
|
||||||
- [React](https://github.com/facebook/react) - The library for web and native user interfaces.
|
- [React](https://github.com/facebook/react) - The library for web and native user interfaces.
|
||||||
- [napi-rs](https://github.com/napi-rs/napi-rs) - A framework for building compiled Node.js add-ons in Rust via Node-API.
|
- [napi-rs](https://github.com/napi-rs/napi-rs) - A framework for building compiled Node.js add-ons in Rust via Node-API.
|
||||||
@@ -197,20 +180,16 @@ Begin with Docker to deploy your own feature-rich, unrestricted version of AFFiN
|
|||||||
|
|
||||||
[](https://template.run.claw.cloud/?openapp=system-fastdeploy%3FtemplateName%3Daffine)
|
[](https://template.run.claw.cloud/?openapp=system-fastdeploy%3FtemplateName%3Daffine)
|
||||||
|
|
||||||
## Hiring
|
|
||||||
|
|
||||||
Some amazing companies, including AFFiNE, are looking for developers! Are you interested in joining AFFiNE or its partners? Check out our [Discord channel](https://affine.pro/redirect/discord) for some of the latest jobs available.
|
|
||||||
|
|
||||||
## Feature Request
|
## Feature Request
|
||||||
|
|
||||||
For feature requests, please see [community.affine.pro](https://community.affine.pro/c/feature-requests/).
|
For feature requests, please see [discussions](https://github.com/toeverything/AFFiNE/discussions/categories/ideas).
|
||||||
|
|
||||||
## Building
|
## Building
|
||||||
|
|
||||||
### Codespaces
|
### Codespaces
|
||||||
|
|
||||||
From the GitHub repo main page, click the green "Code" button and select "Create codespace on master". This will open a new Codespace with the (supposedly auto-forked
|
From the GitHub repo main page, click the green "Code" button and select "Create codespace on master". This will open a new Codespace with the (supposedly auto-forked
|
||||||
AFFiNE repo cloned, built, and ready to go.
|
AFFiNE repo cloned, built, and ready to go).
|
||||||
|
|
||||||
### Local
|
### Local
|
||||||
|
|
||||||
@@ -221,12 +200,6 @@ See [BUILDING.md] for instructions on how to build AFFiNE from source code.
|
|||||||
We welcome contributions from everyone.
|
We welcome contributions from everyone.
|
||||||
See [docs/contributing/tutorial.md](./docs/contributing/tutorial.md) for details.
|
See [docs/contributing/tutorial.md](./docs/contributing/tutorial.md) for details.
|
||||||
|
|
||||||
## Thanks
|
|
||||||
|
|
||||||
<a href="https://www.chromatic.com/"><img src="https://user-images.githubusercontent.com/321738/84662277-e3db4f80-af1b-11ea-88f5-91d67a5e59f6.png" width="153" height="30" alt="Chromatic" /></a>
|
|
||||||
|
|
||||||
Thanks to [Chromatic](https://www.chromatic.com/) for providing the visual testing platform that helps us review UI changes and catch visual regressions.
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
### Editions
|
### Editions
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ We recommend users to always use the latest major version. Security updates will
|
|||||||
|
|
||||||
| Version | Supported |
|
| Version | Supported |
|
||||||
| --------------- | ------------------ |
|
| --------------- | ------------------ |
|
||||||
| 0.25.x (stable) | :white_check_mark: |
|
| 0.26.x (stable) | :white_check_mark: |
|
||||||
| < 0.25.x | :x: |
|
| < 0.26.x | :x: |
|
||||||
|
|
||||||
## Reporting a Vulnerability
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
@@ -23,4 +23,6 @@ We welcome you to provide us with bug reports via and email at [security@toevery
|
|||||||
|
|
||||||
Since we are an open source project, we also welcome you to provide corresponding fix PRs, we will determine specific rewards based on the evaluation results.
|
Since we are an open source project, we also welcome you to provide corresponding fix PRs, we will determine specific rewards based on the evaluation results.
|
||||||
|
|
||||||
|
Due to limited resources, we do not accept and will not review any AI-generated security reports.
|
||||||
|
|
||||||
If the vulnerability is caused by a library we depend on, we encourage you to submit a security report to the corresponding dependent library at the same time to benefit more users.
|
If the vulnerability is caused by a library we depend on, we encourage you to submit a security report to the corresponding dependent library at the same time to benefit more users.
|
||||||
|
|||||||
@@ -296,10 +296,10 @@
|
|||||||
"!src/__tests__",
|
"!src/__tests__",
|
||||||
"!dist/__tests__"
|
"!dist/__tests__"
|
||||||
],
|
],
|
||||||
"version": "0.26.0",
|
"version": "0.26.3",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vanilla-extract/vite-plugin": "^5.0.0",
|
"@vanilla-extract/vite-plugin": "^5.0.0",
|
||||||
"msw": "^2.12.4",
|
"msw": "^2.12.4",
|
||||||
"vitest": "^3.2.4"
|
"vitest": "^4.0.18"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,94 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`snapshot to markdown > imports obsidian vault fixtures 1`] = `
|
||||||
|
{
|
||||||
|
"entry": {
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"children": [
|
||||||
|
{
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Panel
|
||||||
|
Body line",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"emoji": "💡",
|
||||||
|
"flavour": "affine:callout",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"flavour": "affine:attachment",
|
||||||
|
"name": "archive.zip",
|
||||||
|
"style": "horizontalThin",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"footnote": {
|
||||||
|
"label": "1",
|
||||||
|
"reference": {
|
||||||
|
"title": "reference body",
|
||||||
|
"type": "url",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"insert": " ",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"flavour": "affine:divider",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "after note",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": " ",
|
||||||
|
"reference": {
|
||||||
|
"page": "linked",
|
||||||
|
"type": "LinkedPage",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"type": "text",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"delta": [
|
||||||
|
{
|
||||||
|
"insert": "Sources",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:paragraph",
|
||||||
|
"type": "h6",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"flavour": "affine:bookmark",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:note",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
"flavour": "affine:page",
|
||||||
|
},
|
||||||
|
"titles": [
|
||||||
|
"entry",
|
||||||
|
"linked",
|
||||||
|
],
|
||||||
|
}
|
||||||
|
`;
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
> [!custom] Panel
|
||||||
|
> Body line
|
||||||
|
|
||||||
|
![[archive.zip]]
|
||||||
|
|
||||||
|
[^1]
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
after note
|
||||||
|
|
||||||
|
[[linked]]
|
||||||
|
|
||||||
|
[^1]: reference body
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
plain linked page
|
||||||
@@ -2101,6 +2101,157 @@ describe('html to snapshot', () => {
|
|||||||
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('paragraph with br should split into multiple blocks', async () => {
|
||||||
|
const html = template(`<p>aaa<br>bbb<br>ccc</p>`);
|
||||||
|
|
||||||
|
const blockSnapshot: BlockSnapshot = {
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[0]',
|
||||||
|
flavour: 'affine:note',
|
||||||
|
props: {
|
||||||
|
xywh: '[0,0,800,95]',
|
||||||
|
background: DefaultTheme.noteBackgrounColor,
|
||||||
|
index: 'a0',
|
||||||
|
hidden: false,
|
||||||
|
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[1]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [{ insert: 'aaa' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[2]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [{ insert: 'bbb' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[3]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [{ insert: 'ccc' }],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const htmlAdapter = new HtmlAdapter(createJob(), provider);
|
||||||
|
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
|
||||||
|
file: html,
|
||||||
|
});
|
||||||
|
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('paragraph with br should keep inline styles in each split line', async () => {
|
||||||
|
const html = template(
|
||||||
|
`<p><strong>aaa</strong><br><a href="https://www.google.com/">bbb</a><br><em>ccc</em></p>`
|
||||||
|
);
|
||||||
|
|
||||||
|
const blockSnapshot: BlockSnapshot = {
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[0]',
|
||||||
|
flavour: 'affine:note',
|
||||||
|
props: {
|
||||||
|
xywh: '[0,0,800,95]',
|
||||||
|
background: DefaultTheme.noteBackgrounColor,
|
||||||
|
index: 'a0',
|
||||||
|
hidden: false,
|
||||||
|
displayMode: NoteDisplayMode.DocAndEdgeless,
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[1]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [
|
||||||
|
{
|
||||||
|
insert: 'aaa',
|
||||||
|
attributes: {
|
||||||
|
bold: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[2]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [
|
||||||
|
{
|
||||||
|
insert: 'bbb',
|
||||||
|
attributes: {
|
||||||
|
link: 'https://www.google.com/',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'block',
|
||||||
|
id: 'matchesReplaceMap[3]',
|
||||||
|
flavour: 'affine:paragraph',
|
||||||
|
props: {
|
||||||
|
type: 'text',
|
||||||
|
text: {
|
||||||
|
'$blocksuite:internal:text$': true,
|
||||||
|
delta: [
|
||||||
|
{
|
||||||
|
insert: 'ccc',
|
||||||
|
attributes: {
|
||||||
|
italic: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
children: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const htmlAdapter = new HtmlAdapter(createJob(), provider);
|
||||||
|
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
|
||||||
|
file: html,
|
||||||
|
});
|
||||||
|
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
|
||||||
|
});
|
||||||
|
|
||||||
test('nested list', async () => {
|
test('nested list', async () => {
|
||||||
const html = template(`<ul><li>111<ul><li>222</li></ul></li></ul>`);
|
const html = template(`<ul><li>111<ul><li>222</li></ul></li></ul>`);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,10 @@
|
|||||||
import { MarkdownTransformer } from '@blocksuite/affine/widgets/linked-doc';
|
import { readFileSync } from 'node:fs';
|
||||||
|
import { basename, resolve } from 'node:path';
|
||||||
|
|
||||||
|
import {
|
||||||
|
MarkdownTransformer,
|
||||||
|
ObsidianTransformer,
|
||||||
|
} from '@blocksuite/affine/widgets/linked-doc';
|
||||||
import {
|
import {
|
||||||
DefaultTheme,
|
DefaultTheme,
|
||||||
NoteDisplayMode,
|
NoteDisplayMode,
|
||||||
@@ -8,13 +14,18 @@ import {
|
|||||||
CalloutAdmonitionType,
|
CalloutAdmonitionType,
|
||||||
CalloutExportStyle,
|
CalloutExportStyle,
|
||||||
calloutMarkdownExportMiddleware,
|
calloutMarkdownExportMiddleware,
|
||||||
|
docLinkBaseURLMiddleware,
|
||||||
embedSyncedDocMiddleware,
|
embedSyncedDocMiddleware,
|
||||||
MarkdownAdapter,
|
MarkdownAdapter,
|
||||||
|
titleMiddleware,
|
||||||
} from '@blocksuite/affine-shared/adapters';
|
} from '@blocksuite/affine-shared/adapters';
|
||||||
|
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||||
import type {
|
import type {
|
||||||
BlockSnapshot,
|
BlockSnapshot,
|
||||||
|
DeltaInsert,
|
||||||
DocSnapshot,
|
DocSnapshot,
|
||||||
SliceSnapshot,
|
SliceSnapshot,
|
||||||
|
Store,
|
||||||
TransformerMiddleware,
|
TransformerMiddleware,
|
||||||
} from '@blocksuite/store';
|
} from '@blocksuite/store';
|
||||||
import { AssetsManager, MemoryBlobCRUD, Schema } from '@blocksuite/store';
|
import { AssetsManager, MemoryBlobCRUD, Schema } from '@blocksuite/store';
|
||||||
@@ -29,6 +40,138 @@ import { testStoreExtensions } from '../utils/store.js';
|
|||||||
|
|
||||||
const provider = getProvider();
|
const provider = getProvider();
|
||||||
|
|
||||||
|
function withRelativePath(file: File, relativePath: string): File {
|
||||||
|
Object.defineProperty(file, 'webkitRelativePath', {
|
||||||
|
value: relativePath,
|
||||||
|
writable: false,
|
||||||
|
});
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
function markdownFixture(relativePath: string): File {
|
||||||
|
return withRelativePath(
|
||||||
|
new File(
|
||||||
|
[
|
||||||
|
readFileSync(
|
||||||
|
resolve(import.meta.dirname, 'fixtures/obsidian', relativePath),
|
||||||
|
'utf8'
|
||||||
|
),
|
||||||
|
],
|
||||||
|
basename(relativePath),
|
||||||
|
{ type: 'text/markdown' }
|
||||||
|
),
|
||||||
|
`vault/${relativePath}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportSnapshot(doc: Store): DocSnapshot {
|
||||||
|
const job = doc.getTransformer([
|
||||||
|
docLinkBaseURLMiddleware(doc.workspace.id),
|
||||||
|
titleMiddleware(doc.workspace.meta.docMetas),
|
||||||
|
]);
|
||||||
|
const snapshot = job.docToSnapshot(doc);
|
||||||
|
expect(snapshot).toBeTruthy();
|
||||||
|
return snapshot!;
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeDeltaForSnapshot(
|
||||||
|
delta: DeltaInsert<AffineTextAttributes>[],
|
||||||
|
titleById: ReadonlyMap<string, string>
|
||||||
|
) {
|
||||||
|
return delta.map(item => {
|
||||||
|
const normalized: Record<string, unknown> = {
|
||||||
|
insert: item.insert,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (item.attributes?.link) {
|
||||||
|
normalized.link = item.attributes.link;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.attributes?.reference?.type === 'LinkedPage') {
|
||||||
|
normalized.reference = {
|
||||||
|
type: 'LinkedPage',
|
||||||
|
page: titleById.get(item.attributes.reference.pageId) ?? '<missing>',
|
||||||
|
...(item.attributes.reference.title
|
||||||
|
? { title: item.attributes.reference.title }
|
||||||
|
: {}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.attributes?.footnote) {
|
||||||
|
const reference = item.attributes.footnote.reference;
|
||||||
|
normalized.footnote = {
|
||||||
|
label: item.attributes.footnote.label,
|
||||||
|
reference:
|
||||||
|
reference.type === 'doc'
|
||||||
|
? {
|
||||||
|
type: 'doc',
|
||||||
|
page: reference.docId
|
||||||
|
? (titleById.get(reference.docId) ?? '<missing>')
|
||||||
|
: '<missing>',
|
||||||
|
}
|
||||||
|
: {
|
||||||
|
type: reference.type,
|
||||||
|
...(reference.title ? { title: reference.title } : {}),
|
||||||
|
...(reference.fileName ? { fileName: reference.fileName } : {}),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return normalized;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function simplifyBlockForSnapshot(
|
||||||
|
block: BlockSnapshot,
|
||||||
|
titleById: ReadonlyMap<string, string>
|
||||||
|
): Record<string, unknown> {
|
||||||
|
const simplified: Record<string, unknown> = {
|
||||||
|
flavour: block.flavour,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (block.flavour === 'affine:paragraph' || block.flavour === 'affine:list') {
|
||||||
|
simplified.type = block.props.type;
|
||||||
|
const text = block.props.text as
|
||||||
|
| { delta?: DeltaInsert<AffineTextAttributes>[] }
|
||||||
|
| undefined;
|
||||||
|
simplified.delta = normalizeDeltaForSnapshot(text?.delta ?? [], titleById);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.flavour === 'affine:callout') {
|
||||||
|
simplified.emoji = block.props.emoji;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.flavour === 'affine:attachment') {
|
||||||
|
simplified.name = block.props.name;
|
||||||
|
simplified.style = block.props.style;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (block.flavour === 'affine:image') {
|
||||||
|
simplified.sourceId = '<asset>';
|
||||||
|
}
|
||||||
|
|
||||||
|
const children = (block.children ?? [])
|
||||||
|
.filter(child => child.flavour !== 'affine:surface')
|
||||||
|
.map(child => simplifyBlockForSnapshot(child, titleById));
|
||||||
|
if (children.length) {
|
||||||
|
simplified.children = children;
|
||||||
|
}
|
||||||
|
|
||||||
|
return simplified;
|
||||||
|
}
|
||||||
|
|
||||||
|
function snapshotDocByTitle(
|
||||||
|
collection: TestWorkspace,
|
||||||
|
title: string,
|
||||||
|
titleById: ReadonlyMap<string, string>
|
||||||
|
) {
|
||||||
|
const meta = collection.meta.docMetas.find(meta => meta.title === title);
|
||||||
|
expect(meta).toBeTruthy();
|
||||||
|
const doc = collection.getDoc(meta!.id)?.getStore({ id: meta!.id });
|
||||||
|
expect(doc).toBeTruthy();
|
||||||
|
return simplifyBlockForSnapshot(exportSnapshot(doc!).blocks, titleById);
|
||||||
|
}
|
||||||
|
|
||||||
describe('snapshot to markdown', () => {
|
describe('snapshot to markdown', () => {
|
||||||
test('code', async () => {
|
test('code', async () => {
|
||||||
const blockSnapshot: BlockSnapshot = {
|
const blockSnapshot: BlockSnapshot = {
|
||||||
@@ -127,6 +270,46 @@ Hello world
|
|||||||
expect(meta?.tags).toEqual(['a', 'b']);
|
expect(meta?.tags).toEqual(['a', 'b']);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('imports obsidian vault fixtures', async () => {
|
||||||
|
const schema = new Schema().register(AffineSchemas);
|
||||||
|
const collection = new TestWorkspace();
|
||||||
|
collection.storeExtensions = testStoreExtensions;
|
||||||
|
collection.meta.initialize();
|
||||||
|
|
||||||
|
const attachment = withRelativePath(
|
||||||
|
new File([new Uint8Array([80, 75, 3, 4])], 'archive.zip', {
|
||||||
|
type: 'application/zip',
|
||||||
|
}),
|
||||||
|
'vault/archive.zip'
|
||||||
|
);
|
||||||
|
|
||||||
|
const { docIds } = await ObsidianTransformer.importObsidianVault({
|
||||||
|
collection,
|
||||||
|
schema,
|
||||||
|
importedFiles: [
|
||||||
|
markdownFixture('entry.md'),
|
||||||
|
markdownFixture('linked.md'),
|
||||||
|
attachment,
|
||||||
|
],
|
||||||
|
extensions: testStoreExtensions,
|
||||||
|
});
|
||||||
|
expect(docIds).toHaveLength(2);
|
||||||
|
|
||||||
|
const titleById = new Map(
|
||||||
|
collection.meta.docMetas.map(meta => [
|
||||||
|
meta.id,
|
||||||
|
meta.title ?? '<untitled>',
|
||||||
|
])
|
||||||
|
);
|
||||||
|
|
||||||
|
expect({
|
||||||
|
titles: collection.meta.docMetas
|
||||||
|
.map(meta => meta.title)
|
||||||
|
.sort((a, b) => (a ?? '').localeCompare(b ?? '')),
|
||||||
|
entry: snapshotDocByTitle(collection, 'entry', titleById),
|
||||||
|
}).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
test('paragraph', async () => {
|
test('paragraph', async () => {
|
||||||
const blockSnapshot: BlockSnapshot = {
|
const blockSnapshot: BlockSnapshot = {
|
||||||
type: 'block',
|
type: 'block',
|
||||||
|
|||||||
@@ -0,0 +1,95 @@
|
|||||||
|
import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
||||||
|
import { describe, expect, test } from 'vitest';
|
||||||
|
|
||||||
|
import { insertUrlTextSegments } from '../../../../blocks/database/src/properties/paste-url.js';
|
||||||
|
|
||||||
|
type InsertCall = {
|
||||||
|
range: {
|
||||||
|
index: number;
|
||||||
|
length: number;
|
||||||
|
};
|
||||||
|
text: string;
|
||||||
|
attributes?: AffineTextAttributes;
|
||||||
|
};
|
||||||
|
|
||||||
|
describe('insertUrlTextSegments', () => {
|
||||||
|
test('should replace selected text on first insert and append remaining segments', () => {
|
||||||
|
const insertCalls: InsertCall[] = [];
|
||||||
|
const selectionCalls: Array<{ index: number; length: number } | null> = [];
|
||||||
|
const inlineEditor = {
|
||||||
|
insertText: (
|
||||||
|
range: { index: number; length: number },
|
||||||
|
text: string,
|
||||||
|
attributes?: AffineTextAttributes
|
||||||
|
) => {
|
||||||
|
insertCalls.push({ range, text, attributes });
|
||||||
|
},
|
||||||
|
setInlineRange: (range: { index: number; length: number } | null) => {
|
||||||
|
selectionCalls.push(range);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const inlineRange = { index: 4, length: 6 };
|
||||||
|
const segments = [
|
||||||
|
{ text: 'hi - ' },
|
||||||
|
{ text: 'https://google.com', link: 'https://google.com' },
|
||||||
|
];
|
||||||
|
|
||||||
|
insertUrlTextSegments(inlineEditor, inlineRange, segments);
|
||||||
|
|
||||||
|
expect(insertCalls).toEqual([
|
||||||
|
{
|
||||||
|
range: { index: 4, length: 6 },
|
||||||
|
text: 'hi - ',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
range: { index: 9, length: 0 },
|
||||||
|
text: 'https://google.com',
|
||||||
|
attributes: {
|
||||||
|
link: 'https://google.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(selectionCalls).toEqual([{ index: 27, length: 0 }]);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('should keep insertion range length zero when there is no selected text', () => {
|
||||||
|
const insertCalls: InsertCall[] = [];
|
||||||
|
const selectionCalls: Array<{ index: number; length: number } | null> = [];
|
||||||
|
const inlineEditor = {
|
||||||
|
insertText: (
|
||||||
|
range: { index: number; length: number },
|
||||||
|
text: string,
|
||||||
|
attributes?: AffineTextAttributes
|
||||||
|
) => {
|
||||||
|
insertCalls.push({ range, text, attributes });
|
||||||
|
},
|
||||||
|
setInlineRange: (range: { index: number; length: number } | null) => {
|
||||||
|
selectionCalls.push(range);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const inlineRange = { index: 2, length: 0 };
|
||||||
|
const segments = [
|
||||||
|
{ text: 'prefix ' },
|
||||||
|
{ text: 'https://a.com', link: 'https://a.com' },
|
||||||
|
];
|
||||||
|
|
||||||
|
insertUrlTextSegments(inlineEditor, inlineRange, segments);
|
||||||
|
|
||||||
|
expect(insertCalls).toEqual([
|
||||||
|
{
|
||||||
|
range: { index: 2, length: 0 },
|
||||||
|
text: 'prefix ',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
range: { index: 9, length: 0 },
|
||||||
|
text: 'https://a.com',
|
||||||
|
attributes: {
|
||||||
|
link: 'https://a.com',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
expect(selectionCalls).toEqual([{ index: 22, length: 0 }]);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -11,7 +11,7 @@ export default defineConfig({
|
|||||||
include: ['src/__tests__/**/*.unit.spec.ts'],
|
include: ['src/__tests__/**/*.unit.spec.ts'],
|
||||||
testTimeout: 1000,
|
testTimeout: 1000,
|
||||||
coverage: {
|
coverage: {
|
||||||
provider: 'istanbul', // or 'c8'
|
provider: 'istanbul',
|
||||||
reporter: ['lcov'],
|
reporter: ['lcov'],
|
||||||
reportsDirectory: '../../../.coverage/blocksuite-affine',
|
reportsDirectory: '../../../.coverage/blocksuite-affine',
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -26,7 +26,6 @@
|
|||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
"file-type": "^21.0.0",
|
"file-type": "^21.0.0",
|
||||||
"lit": "^3.2.0",
|
"lit": "^3.2.0",
|
||||||
"minimatch": "^10.1.1",
|
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
@@ -41,5 +40,5 @@
|
|||||||
"!src/__tests__",
|
"!src/__tests__",
|
||||||
"!dist/__tests__"
|
"!dist/__tests__"
|
||||||
],
|
],
|
||||||
"version": "0.26.0"
|
"version": "0.26.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
BlockMarkdownAdapterExtension,
|
BlockMarkdownAdapterExtension,
|
||||||
type BlockMarkdownAdapterMatcher,
|
type BlockMarkdownAdapterMatcher,
|
||||||
|
createAttachmentBlockSnapshot,
|
||||||
FOOTNOTE_DEFINITION_PREFIX,
|
FOOTNOTE_DEFINITION_PREFIX,
|
||||||
getFootnoteDefinitionText,
|
getFootnoteDefinitionText,
|
||||||
isFootnoteDefinitionNode,
|
isFootnoteDefinitionNode,
|
||||||
@@ -56,18 +57,15 @@ export const attachmentBlockMarkdownAdapterMatcher: BlockMarkdownAdapterMatcher
|
|||||||
}
|
}
|
||||||
walkerContext
|
walkerContext
|
||||||
.openNode(
|
.openNode(
|
||||||
{
|
createAttachmentBlockSnapshot({
|
||||||
type: 'block',
|
|
||||||
id: nanoid(),
|
id: nanoid(),
|
||||||
flavour: AttachmentBlockSchema.model.flavour,
|
|
||||||
props: {
|
props: {
|
||||||
name: fileName,
|
name: fileName,
|
||||||
sourceId: blobId,
|
sourceId: blobId,
|
||||||
footnoteIdentifier,
|
footnoteIdentifier,
|
||||||
style: 'citation',
|
style: 'citation',
|
||||||
},
|
},
|
||||||
children: [],
|
}),
|
||||||
},
|
|
||||||
'children'
|
'children'
|
||||||
)
|
)
|
||||||
.closeNode();
|
.closeNode();
|
||||||
|
|||||||
@@ -26,13 +26,14 @@
|
|||||||
"@preact/signals-core": "^1.8.0",
|
"@preact/signals-core": "^1.8.0",
|
||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
"lit": "^3.2.0",
|
"lit": "^3.2.0",
|
||||||
"minimatch": "^10.1.1",
|
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"yjs": "^13.6.27",
|
"yjs": "^13.6.27",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"vitest": "^3.2.4"
|
"@vitest/browser-playwright": "^4.0.18",
|
||||||
|
"playwright": "=1.58.2",
|
||||||
|
"vitest": "^4.0.18"
|
||||||
},
|
},
|
||||||
"exports": {
|
"exports": {
|
||||||
".": "./src/index.ts",
|
".": "./src/index.ts",
|
||||||
@@ -45,5 +46,5 @@
|
|||||||
"!src/__tests__",
|
"!src/__tests__",
|
||||||
"!dist/__tests__"
|
"!dist/__tests__"
|
||||||
],
|
],
|
||||||
"version": "0.26.0"
|
"version": "0.26.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -108,7 +108,9 @@ export class BookmarkBlockComponent extends CaptionedBlockComponent<BookmarkBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
open = () => {
|
open = () => {
|
||||||
window.open(this.link, '_blank');
|
const link = this.link;
|
||||||
|
if (!link) return;
|
||||||
|
window.open(link, '_blank', 'noopener,noreferrer');
|
||||||
};
|
};
|
||||||
|
|
||||||
refreshData = () => {
|
refreshData = () => {
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { playwright } from '@vitest/browser-playwright';
|
||||||
import { defineConfig } from 'vitest/config';
|
import { defineConfig } from 'vitest/config';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
@@ -8,10 +9,9 @@ export default defineConfig({
|
|||||||
browser: {
|
browser: {
|
||||||
enabled: true,
|
enabled: true,
|
||||||
headless: true,
|
headless: true,
|
||||||
name: 'chromium',
|
instances: [{ browser: 'chromium' }],
|
||||||
provider: 'playwright',
|
provider: playwright(),
|
||||||
isolate: false,
|
isolate: false,
|
||||||
providerOptions: {},
|
|
||||||
},
|
},
|
||||||
include: ['src/__tests__/**/*.unit.spec.ts'],
|
include: ['src/__tests__/**/*.unit.spec.ts'],
|
||||||
testTimeout: 500,
|
testTimeout: 500,
|
||||||
|
|||||||
@@ -30,7 +30,6 @@
|
|||||||
"@types/mdast": "^4.0.4",
|
"@types/mdast": "^4.0.4",
|
||||||
"emoji-mart": "^5.6.0",
|
"emoji-mart": "^5.6.0",
|
||||||
"lit": "^3.2.0",
|
"lit": "^3.2.0",
|
||||||
"minimatch": "^10.1.1",
|
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
},
|
},
|
||||||
@@ -45,5 +44,5 @@
|
|||||||
"!src/__tests__",
|
"!src/__tests__",
|
||||||
"!dist/__tests__"
|
"!dist/__tests__"
|
||||||
],
|
],
|
||||||
"version": "0.26.0"
|
"version": "0.26.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -216,9 +216,13 @@ export class CalloutBlockComponent extends CaptionedBlockComponent<CalloutBlockM
|
|||||||
override renderBlock() {
|
override renderBlock() {
|
||||||
const icon = this.model.props.icon$.value;
|
const icon = this.model.props.icon$.value;
|
||||||
const backgroundColorName = this.model.props.backgroundColorName$.value;
|
const backgroundColorName = this.model.props.backgroundColorName$.value;
|
||||||
|
const normalizedBackgroundName =
|
||||||
|
backgroundColorName === 'default' || backgroundColorName === ''
|
||||||
|
? 'grey'
|
||||||
|
: backgroundColorName;
|
||||||
const backgroundColor = (
|
const backgroundColor = (
|
||||||
cssVarV2.block.callout.background as Record<string, string>
|
cssVarV2.block.callout.background as Record<string, string>
|
||||||
)[backgroundColorName ?? ''];
|
)[normalizedBackgroundName ?? 'grey'];
|
||||||
|
|
||||||
const iconContent = getIcon(icon);
|
const iconContent = getIcon(icon);
|
||||||
|
|
||||||
|
|||||||
@@ -68,14 +68,14 @@ const backgroundColorAction = {
|
|||||||
${repeat(colors, color => {
|
${repeat(colors, color => {
|
||||||
const isDefault = color === 'default';
|
const isDefault = color === 'default';
|
||||||
const value = isDefault
|
const value = isDefault
|
||||||
? null
|
? cssVarV2.block.callout.background.grey
|
||||||
: `var(--affine-text-highlight-${color})`;
|
: `var(--affine-text-highlight-${color})`;
|
||||||
const displayName = `${color} Background`;
|
const displayName = `${color} Background`;
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<editor-menu-action
|
<editor-menu-action
|
||||||
data-testid="background-${color}"
|
data-testid="background-${color}"
|
||||||
@click=${() => updateBackground(color)}
|
@click=${() => updateBackground(isDefault ? 'grey' : color)}
|
||||||
>
|
>
|
||||||
<affine-text-duotone-icon
|
<affine-text-duotone-icon
|
||||||
style=${styleMap({
|
style=${styleMap({
|
||||||
|
|||||||
@@ -31,7 +31,6 @@
|
|||||||
"@toeverything/theme": "^1.1.23",
|
"@toeverything/theme": "^1.1.23",
|
||||||
"@types/mdast": "^4.0.4",
|
"@types/mdast": "^4.0.4",
|
||||||
"lit": "^3.2.0",
|
"lit": "^3.2.0",
|
||||||
"minimatch": "^10.1.1",
|
|
||||||
"rxjs": "^7.8.2",
|
"rxjs": "^7.8.2",
|
||||||
"shiki": "^3.19.0",
|
"shiki": "^3.19.0",
|
||||||
"zod": "^3.25.76"
|
"zod": "^3.25.76"
|
||||||
@@ -48,5 +47,5 @@
|
|||||||
"!src/__tests__",
|
"!src/__tests__",
|
||||||
"!dist/__tests__"
|
"!dist/__tests__"
|
||||||
],
|
],
|
||||||
"version": "0.26.0"
|
"version": "0.26.3"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -45,8 +45,10 @@ export class AffineCodeUnit extends ShadowlessElement {
|
|||||||
if (!codeBlock || !vElement) return plainContent;
|
if (!codeBlock || !vElement) return plainContent;
|
||||||
const tokens = codeBlock.highlightTokens$.value;
|
const tokens = codeBlock.highlightTokens$.value;
|
||||||
if (tokens.length === 0) return plainContent;
|
if (tokens.length === 0) return plainContent;
|
||||||
|
const line = tokens[vElement.lineIndex];
|
||||||
|
if (!line) return plainContent;
|
||||||
// copy the tokens to avoid modifying the original tokens
|
// copy the tokens to avoid modifying the original tokens
|
||||||
const lineTokens = structuredClone(tokens[vElement.lineIndex]);
|
const lineTokens = structuredClone(line);
|
||||||
if (lineTokens.length === 0) return plainContent;
|
if (lineTokens.length === 0) return plainContent;
|
||||||
|
|
||||||
const startOffset = vElement.startOffset;
|
const startOffset = vElement.startOffset;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user