Compare commits

..

2 Commits

3695 changed files with 58495 additions and 172620 deletions
-1
View File
@@ -6,7 +6,6 @@ yarn install
# Build Server Dependencies # Build Server Dependencies
yarn affine @affine/server-native build yarn affine @affine/server-native build
yarn affine @affine/reader build
# Create database # Create database
yarn affine @affine/server prisma migrate reset -f yarn affine @affine/server prisma migrate reset -f
-15
View File
@@ -10,7 +10,6 @@ services:
environment: environment:
DATABASE_URL: postgresql://affine:affine@db:5432/affine DATABASE_URL: postgresql://affine:affine@db:5432/affine
REDIS_SERVER_HOST: redis REDIS_SERVER_HOST: redis
AFFINE_INDEXER_SEARCH_ENDPOINT: http://indexer:9308
db: db:
image: pgvector/pgvector:pg16 image: pgvector/pgvector:pg16
@@ -24,19 +23,5 @@ services:
redis: redis:
image: redis image: redis
indexer:
image: manticoresearch/manticore:${MANTICORE_VERSION:-10.1.0}
ulimits:
nproc: 65535
nofile:
soft: 65535
hard: 65535
memlock:
soft: -1
hard: -1
volumes:
- manticoresearch_data:/var/lib/manticore
volumes: volumes:
postgres-data: postgres-data:
manticoresearch_data:
+1 -10
View File
@@ -3,13 +3,4 @@ DB_VERSION=16
# database credentials # database credentials
DB_PASSWORD=affine DB_PASSWORD=affine
DB_USERNAME=affine DB_USERNAME=affine
DB_DATABASE_NAME=affine DB_DATABASE_NAME=affine
# elasticsearch env
# ELASTIC_VERSION=9.0.1
# enable for arm64, e.g.: macOS M1+
# ELASTIC_VERSION_ARM64=-arm64
# ELASTIC_PLATFORM=linux/arm64
# manticoresearch
MANTICORE_VERSION=10.1.0
+1 -4
View File
@@ -1,6 +1,3 @@
postgres postgres
.env .env
compose.yml compose.yml
certs/*
!certs/.gitkeep
nginx/conf.d/*
-21
View File
@@ -1,21 +0,0 @@
# Dev containers
## Develop with domain
> MacOs only, OrbStack only
### 1. Generate and install Root CA
```bash
# the root ca file will be located at `./.docker/dev/certs/ca`
yarn affine cert --install
```
### 2. Generate domain certs
```bash
# certificates will be located at `./.docker/dev/certs/${domain}`
yarn affine cert --domain affine.localhost
```
### 3. Enable nginx service in compose.yml
View File
+2 -70
View File
@@ -18,82 +18,14 @@ services:
ports: ports:
- 6379:6379 - 6379:6379
# https://mailpit.axllent.org/docs/install/docker/ mailhog:
mailpit: image: mailhog/mailhog:latest
image: axllent/mailpit:latest
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025
environment:
MP_MAX_MESSAGES: 5000
MP_DATABASE: /data/mailpit.db
MP_SMTP_AUTH_ACCEPT_ANY: 1
MP_SMTP_AUTH_ALLOW_INSECURE: 1
volumes:
- mailpit_data:/data
# https://manual.manticoresearch.com/Starting_the_server/Docker
manticoresearch:
image: manticoresearch/manticore:${MANTICORE_VERSION:-10.1.0}
ports:
- 9308:9308
ulimits:
nproc: 65535
nofile:
soft: 65535
hard: 65535
memlock:
soft: -1
hard: -1
volumes:
- manticoresearch_data:/var/lib/manticore
# elasticsearch:
# image: docker.elastic.co/elasticsearch/elasticsearch:${ELASTIC_VERSION:-9.0.1}${ELASTIC_VERSION_ARM64}
# platform: ${ELASTIC_PLATFORM}
# labels:
# co.elastic.logs/module: elasticsearch
# volumes:
# - elasticsearch_data:/usr/share/elasticsearch/data
# ports:
# - ${ES_PORT:-9200}:9200
# environment:
# - node.name=es01
# - cluster.name=affine-dev
# - discovery.type=single-node
# - bootstrap.memory_lock=true
# - xpack.security.enabled=false
# - xpack.security.http.ssl.enabled=false
# - xpack.security.transport.ssl.enabled=false
# - xpack.license.self_generated.type=basic
# mem_limit: ${ES_MEM_LIMIT:-1073741824}
# ulimits:
# memlock:
# soft: -1
# hard: -1
# healthcheck:
# test:
# [
# "CMD-SHELL",
# "curl -s http://localhost:9200 | grep -q 'affine-dev'",
# ]
# interval: 10s
# timeout: 10s
# retries: 120
# nginx:
# image: nginx:alpine
# volumes:
# - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
# - ./nginx/conf.d:/etc/nginx/conf.d:ro
# - ./certs:/etc/nginx/certs:ro
# network_mode: host
networks: networks:
dev: dev:
volumes: volumes:
postgres_data: postgres_data:
manticoresearch_data:
mailpit_data:
elasticsearch_data:
-28
View File
@@ -1,28 +0,0 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
types_hash_max_size 2048;
client_max_body_size 512M;
server_names_hash_bucket_size 128;
ssi on;
gzip on;
include "/etc/nginx/conf.d/*";
}
-27
View File
@@ -1,27 +0,0 @@
server {
listen 80;
server_name DEV_DOMAIN;
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl;
http2 on;
ssl_certificate /etc/nginx/certs/$host/crt;
ssl_certificate_key /etc/nginx/certs/$host/key;
server_name DEV_DOMAIN;
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
resolver 127.0.0.1;
}
}
-25
View File
@@ -1,25 +0,0 @@
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = US
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = MN
localityName = Locality Name (eg, city)
localityName_default = Minneapolis
organizationalUnitName = Organizational Unit Name (eg, section)
organizationalUnitName_default = Domain Control Validated
commonName = Internet Widgits Ltd
commonName_max = 64
[ v3_req ]
# Extensions to add to a certificate request
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = DEV_DOMAIN
DNS.2 = *.DEV_DOMAIN
+1 -1
View File
@@ -20,4 +20,4 @@ CONFIG_LOCATION=~/.affine/self-host/config
# database credentials # database credentials
DB_USERNAME=affine DB_USERNAME=affine
DB_PASSWORD= DB_PASSWORD=
DB_DATABASE=affine DB_DATABASE=affine
-1
View File
@@ -1 +0,0 @@
.env
+3 -5
View File
@@ -1,7 +1,7 @@
name: affine name: affine
services: services:
affine: affine:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable} image: ghcr.io/toeverything/affine-graphql:${AFFINE_REVISION:-stable}
container_name: affine_server container_name: affine_server
ports: ports:
- '${PORT:-3010}:3010' - '${PORT:-3010}:3010'
@@ -21,11 +21,10 @@ services:
environment: environment:
- REDIS_SERVER_HOST=redis - REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine} - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
restart: unless-stopped restart: unless-stopped
affine_migration: affine_migration:
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable} image: ghcr.io/toeverything/affine-graphql:${AFFINE_REVISION:-stable}
container_name: affine_migration_job container_name: affine_migration_job
volumes: volumes:
# custom configurations # custom configurations
@@ -37,7 +36,6 @@ services:
environment: environment:
- REDIS_SERVER_HOST=redis - REDIS_SERVER_HOST=redis
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine} - DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
- AFFINE_INDEXER_ENABLED=false
depends_on: depends_on:
postgres: postgres:
condition: service_healthy condition: service_healthy
@@ -55,7 +53,7 @@ services:
restart: unless-stopped restart: unless-stopped
postgres: postgres:
image: pgvector/pgvector:pg16 image: postgres:16
container_name: affine_postgres container_name: affine_postgres
volumes: volumes:
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data - ${DB_DATA_LOCATION}:/var/lib/postgresql/data
+36 -279
View File
@@ -31,13 +31,9 @@
"properties": { "properties": {
"queue": { "queue": {
"type": "object", "type": "object",
"description": "The config for job queues\n@default {\"attempts\":5,\"backoff\":{\"type\":\"exponential\",\"delay\":1000},\"removeOnComplete\":true,\"removeOnFail\":{\"age\":86400,\"count\":500}}\n@link https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html", "description": "The config for job queues\n@default {\"attempts\":5,\"removeOnComplete\":true,\"removeOnFail\":{\"age\":86400,\"count\":500}}\n@link https://api.docs.bullmq.io/interfaces/v5.QueueOptions.html",
"default": { "default": {
"attempts": 5, "attempts": 5,
"backoff": {
"type": "exponential",
"delay": 1000
},
"removeOnComplete": true, "removeOnComplete": true,
"removeOnFail": { "removeOnFail": {
"age": 86400, "age": 86400,
@@ -52,19 +48,7 @@
}, },
"queues.copilot": { "queues.copilot": {
"type": "object", "type": "object",
"description": "The config for copilot job queue\n@default {\"concurrency\":10}", "description": "The config for copilot job queue\n@default {\"concurrency\":1}",
"properties": {
"concurrency": {
"type": "number"
}
},
"default": {
"concurrency": 10
}
},
"queues.doc": {
"type": "object",
"description": "The config for doc job queue\n@default {\"concurrency\":1}",
"properties": { "properties": {
"concurrency": { "concurrency": {
"type": "number" "type": "number"
@@ -74,9 +58,9 @@
"concurrency": 1 "concurrency": 1
} }
}, },
"queues.indexer": { "queues.doc": {
"type": "object", "type": "object",
"description": "The config for indexer job queue\n@default {\"concurrency\":1}", "description": "The config for doc job queue\n@default {\"concurrency\":1}",
"properties": { "properties": {
"concurrency": { "concurrency": {
"type": "number" "type": "number"
@@ -139,6 +123,32 @@
} }
} }
}, },
"websocket": {
"type": "object",
"description": "Configuration for websocket module",
"properties": {
"transports": {
"type": "array",
"description": "The enabled transports for accepting websocket traffics.\n@default [\"websocket\",\"polling\"]\n@link https://docs.nestjs.com/websockets/gateways#transports",
"items": {
"type": "string",
"enum": [
"websocket",
"polling"
]
},
"default": [
"websocket",
"polling"
]
},
"maxHttpBufferSize": {
"type": "number",
"description": "How many bytes or characters a message can be, before closing the session (to avoid DoS).\n@default 100000000",
"default": 100000000
}
}
},
"auth": { "auth": {
"type": "object", "type": "object",
"description": "Configuration for auth module", "description": "Configuration for auth module",
@@ -219,41 +229,6 @@
"type": "boolean", "type": "boolean",
"description": "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.\n@default false\n@environment `MAILER_IGNORE_TLS`", "description": "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.\n@default false\n@environment `MAILER_IGNORE_TLS`",
"default": false "default": false
},
"fallbackDomains": {
"type": "array",
"description": "The emails from these domains are always sent using the fallback SMTP server.\n@default []",
"default": []
},
"fallbackSMTP.host": {
"type": "string",
"description": "Host of the email server (e.g. smtp.gmail.com)\n@default \"\"",
"default": ""
},
"fallbackSMTP.port": {
"type": "number",
"description": "Port of the email server (they commonly are 25, 465 or 587)\n@default 465",
"default": 465
},
"fallbackSMTP.username": {
"type": "string",
"description": "Username used to authenticate the email server\n@default \"\"",
"default": ""
},
"fallbackSMTP.password": {
"type": "string",
"description": "Password used to authenticate the email server\n@default \"\"",
"default": ""
},
"fallbackSMTP.sender": {
"type": "string",
"description": "Sender of all the emails (e.g. \"AFFiNE Team <noreply@affine.pro>\")\n@default \"\"",
"default": ""
},
"fallbackSMTP.ignoreTLS": {
"type": "boolean",
"description": "Whether ignore email server's TSL certification verification. Enable it for self-signed certificates.\n@default false",
"default": false
} }
} }
}, },
@@ -526,32 +501,6 @@
} }
} }
}, },
"websocket": {
"type": "object",
"description": "Configuration for websocket module",
"properties": {
"transports": {
"type": "array",
"description": "The enabled transports for accepting websocket traffics.\n@default [\"websocket\",\"polling\"]\n@link https://docs.nestjs.com/websockets/gateways#transports",
"items": {
"type": "string",
"enum": [
"websocket",
"polling"
]
},
"default": [
"websocket",
"polling"
]
},
"maxHttpBufferSize": {
"type": "number",
"description": "How many bytes or characters a message can be, before closing the session (to avoid DoS).\n@default 100000000",
"default": 100000000
}
}
},
"server": { "server": {
"type": "object", "type": "object",
"description": "Configuration for server module", "description": "Configuration for server module",
@@ -575,11 +524,6 @@
"description": "Where the server get deployed(FQDN).\n@default \"localhost\"\n@environment `AFFINE_SERVER_HOST`", "description": "Where the server get deployed(FQDN).\n@default \"localhost\"\n@environment `AFFINE_SERVER_HOST`",
"default": "localhost" "default": "localhost"
}, },
"hosts": {
"type": "array",
"description": "Multiple hosts the server will accept requests from.\n@default []",
"default": []
},
"port": { "port": {
"type": "number", "type": "number",
"description": "Which port the server will listen on.\n@default 3010\n@environment `AFFINE_SERVER_PORT`", "description": "Which port the server will listen on.\n@default 3010\n@environment `AFFINE_SERVER_PORT`",
@@ -600,11 +544,6 @@
"type": "boolean", "type": "boolean",
"description": "Only allow users with early access features to access the app\n@default false", "description": "Only allow users with early access features to access the app\n@default false",
"default": false "default": false
},
"allowGuestDemoWorkspace": {
"type": "boolean",
"description": "Whether allow guest users to create demo workspaces.\n@default true",
"default": true
} }
} }
}, },
@@ -664,34 +603,14 @@
"properties": { "properties": {
"enabled": { "enabled": {
"type": "boolean", "type": "boolean",
"description": "Whether to enable the copilot plugin. <br> Document: <a href=\"https://docs.affine.pro/self-host-affine/administer/ai\" target=\"_blank\">https://docs.affine.pro/self-host-affine/administer/ai</a>\n@default false", "description": "Whether to enable the copilot plugin.\n@default false",
"default": false "default": false
}, },
"scenarios": {
"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\":\"claude-sonnet-4@20250514\",\"embedding\":\"gemini-embedding-001\",\"image\":\"gpt-image-1\",\"rerank\":\"gpt-4.1\",\"coding\":\"claude-sonnet-4@20250514\",\"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\"}}",
"default": {
"override_enabled": false,
"scenarios": {
"audio_transcribing": "gemini-2.5-flash",
"chat": "claude-sonnet-4@20250514",
"embedding": "gemini-embedding-001",
"image": "gpt-image-1",
"rerank": "gpt-4.1",
"coding": "claude-sonnet-4@20250514",
"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"
}
}
},
"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\":\"\"}\n@link https://github.com/openai/openai-node",
"default": { "default": {
"apiKey": "", "apiKey": ""
"baseURL": "https://api.openai.com/v1"
} }
}, },
"providers.fal": { "providers.fal": {
@@ -703,47 +622,11 @@
}, },
"providers.gemini": { "providers.gemini": {
"type": "object", "type": "object",
"description": "The config for the gemini provider.\n@default {\"apiKey\":\"\",\"baseURL\":\"https://generativelanguage.googleapis.com/v1beta\"}", "description": "The config for the gemini provider.\n@default {\"apiKey\":\"\"}",
"default": { "default": {
"apiKey": "", "apiKey": ""
"baseURL": "https://generativelanguage.googleapis.com/v1beta"
} }
}, },
"providers.geminiVertex": {
"type": "object",
"description": "The config for the google vertex provider.\n@default {}",
"properties": {
"location": {
"type": "string",
"description": "The location of the google vertex provider."
},
"project": {
"type": "string",
"description": "The project name of the google vertex provider."
},
"googleAuthOptions": {
"type": "object",
"description": "The google auth options for the google vertex provider.",
"properties": {
"credentials": {
"type": "object",
"description": "The credentials for the google vertex provider.",
"properties": {
"client_email": {
"type": "string",
"description": "The client email for the google vertex provider."
},
"private_key": {
"type": "string",
"description": "The private key for the google vertex provider."
}
}
}
}
}
},
"default": {}
},
"providers.perplexity": { "providers.perplexity": {
"type": "object", "type": "object",
"description": "The config for the perplexity provider.\n@default {\"apiKey\":\"\"}", "description": "The config for the perplexity provider.\n@default {\"apiKey\":\"\"}",
@@ -751,54 +634,6 @@
"apiKey": "" "apiKey": ""
} }
}, },
"providers.anthropic": {
"type": "object",
"description": "The config for the anthropic provider.\n@default {\"apiKey\":\"\",\"baseURL\":\"https://api.anthropic.com/v1\"}",
"default": {
"apiKey": "",
"baseURL": "https://api.anthropic.com/v1"
}
},
"providers.anthropicVertex": {
"type": "object",
"description": "The config for the google vertex provider.\n@default {}",
"properties": {
"location": {
"type": "string",
"description": "The location of the google vertex provider."
},
"project": {
"type": "string",
"description": "The project name of the google vertex provider."
},
"googleAuthOptions": {
"type": "object",
"description": "The google auth options for the google vertex provider.",
"properties": {
"credentials": {
"type": "object",
"description": "The credentials for the google vertex provider.",
"properties": {
"client_email": {
"type": "string",
"description": "The client email for the google vertex provider."
},
"private_key": {
"type": "string",
"description": "The private key for the google vertex provider."
}
}
}
}
}
},
"default": {}
},
"providers.morph": {
"type": "object",
"description": "The config for the morph provider.\n@default {}",
"default": {}
},
"unsplash": { "unsplash": {
"type": "object", "type": "object",
"description": "The config for the unsplash key.\n@default {\"key\":\"\"}", "description": "The config for the unsplash key.\n@default {\"key\":\"\"}",
@@ -806,13 +641,6 @@
"key": "" "key": ""
} }
}, },
"exa": {
"type": "object",
"description": "The config for the exa web search key.\n@default {\"key\":\"\"}",
"default": {
"key": ""
}
},
"storage": { "storage": {
"type": "object", "type": "object",
"description": "The config for the storage provider.\n@default {\"provider\":\"fs\",\"bucket\":\"copilot\",\"config\":{\"path\":\"~/.affine/storage\"}}", "description": "The config for the storage provider.\n@default {\"provider\":\"fs\",\"bucket\":\"copilot\",\"config\":{\"path\":\"~/.affine/storage\"}}",
@@ -936,47 +764,6 @@
} }
} }
}, },
"indexer": {
"type": "object",
"description": "Configuration for indexer module",
"properties": {
"enabled": {
"type": "boolean",
"description": "Enable indexer plugin\n@default false\n@environment `AFFINE_INDEXER_ENABLED`",
"default": false
},
"provider.type": {
"type": "string",
"description": "Indexer search service provider name\n@default \"manticoresearch\"\n@environment `AFFINE_INDEXER_SEARCH_PROVIDER`",
"default": "manticoresearch"
},
"provider.endpoint": {
"type": "string",
"description": "Indexer search service endpoint\n@default \"http://localhost:9308\"\n@environment `AFFINE_INDEXER_SEARCH_ENDPOINT`",
"default": "http://localhost:9308"
},
"provider.apiKey": {
"type": "string",
"description": "Indexer search service api key. Optional for elasticsearch\n@default \"\"\n@environment `AFFINE_INDEXER_SEARCH_API_KEY`\n@link https://www.elastic.co/guide/server/current/api-key.html",
"default": ""
},
"provider.username": {
"type": "string",
"description": "Indexer search service auth username, if not set, basic auth will be disabled. Optional for elasticsearch\n@default \"\"\n@environment `AFFINE_INDEXER_SEARCH_USERNAME`\n@link https://www.elastic.co/guide/en/elasticsearch/reference/current/http-clients.html",
"default": ""
},
"provider.password": {
"type": "string",
"description": "Indexer search service auth password, if not set, basic auth will be disabled. Optional for elasticsearch\n@default \"\"\n@environment `AFFINE_INDEXER_SEARCH_PASSWORD`",
"default": ""
},
"autoIndex.batchSize": {
"type": "number",
"description": "Number of workspaces automatically indexed per batch\n@default 10",
"default": 10
}
}
},
"customerIo": { "customerIo": {
"type": "object", "type": "object",
"description": "Configuration for customerIo module", "description": "Configuration for customerIo module",
@@ -1037,43 +824,13 @@
}, },
"providers.oidc": { "providers.oidc": {
"type": "object", "type": "object",
"description": "OIDC OAuth provider config\n@default {\"clientId\":\"\",\"clientSecret\":\"\",\"issuer\":\"\",\"args\":{}}\n@link https://openid.net/specs/openid-connect-core-1_0.html", "description": "OIDC OAuth provider config\n@default {\"clientId\":\"\",\"clientSecret\":\"\",\"issuer\":\"\",\"args\":{}}",
"properties": {
"clientId": {
"type": "string"
},
"clientSecret": {
"type": "string"
},
"args": {
"type": "object"
}
},
"default": { "default": {
"clientId": "", "clientId": "",
"clientSecret": "", "clientSecret": "",
"issuer": "", "issuer": "",
"args": {} "args": {}
} }
},
"providers.apple": {
"type": "object",
"description": "Apple OAuth provider config\n@default {\"clientId\":\"\",\"clientSecret\":\"\"}\n@link https://developer.apple.com/documentation/sign_in_with_apple/sign_in_with_apple_js/implementing_sign_in_with_apple_in_your_app",
"properties": {
"clientId": {
"type": "string"
},
"clientSecret": {
"type": "string"
},
"args": {
"type": "object"
}
},
"default": {
"clientId": "",
"clientSecret": ""
}
} }
} }
}, },
+5
View File
@@ -1,6 +1,9 @@
name: 'Deploy to Cluster' name: 'Deploy to Cluster'
description: 'Deploy AFFiNE Cloud to cluster' description: 'Deploy AFFiNE Cloud to cluster'
inputs: inputs:
build-type:
description: 'Align with App build type, canary|beta|stable|internal'
default: 'canary'
gcp-project-number: gcp-project-number:
description: 'GCP project number' description: 'GCP project number'
required: true required: true
@@ -33,3 +36,5 @@ runs:
- name: Deploy - name: Deploy
shell: bash shell: bash
run: node ./.github/actions/deploy/deploy.mjs run: node ./.github/actions/deploy/deploy.mjs
env:
BUILD_TYPE: '${{ inputs.build-type }}'
+20 -34
View File
@@ -16,9 +16,6 @@ const {
REDIS_SERVER_HOST, REDIS_SERVER_HOST,
REDIS_SERVER_PASSWORD, REDIS_SERVER_PASSWORD,
STATIC_IP_NAME, STATIC_IP_NAME,
AFFINE_INDEXER_SEARCH_PROVIDER,
AFFINE_INDEXER_SEARCH_ENDPOINT,
AFFINE_INDEXER_SEARCH_API_KEY,
} = process.env; } = process.env;
const buildType = BUILD_TYPE || 'canary'; const buildType = BUILD_TYPE || 'canary';
@@ -29,25 +26,25 @@ const isInternal = buildType === 'internal';
const replicaConfig = { const replicaConfig = {
stable: { stable: {
web: 2, web: 3,
graphql: Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 2, graphql: Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 3,
sync: Number(process.env.PRODUCTION_SYNC_REPLICA) || 2, sync: Number(process.env.PRODUCTION_SYNC_REPLICA) || 3,
renderer: Number(process.env.PRODUCTION_RENDERER_REPLICA) || 2, renderer: Number(process.env.PRODUCTION_RENDERER_REPLICA) || 3,
doc: Number(process.env.PRODUCTION_DOC_REPLICA) || 2, doc: Number(process.env.PRODUCTION_DOC_REPLICA) || 3,
}, },
beta: { beta: {
web: 1, web: 2,
graphql: Number(process.env.BETA_GRAPHQL_REPLICA) || 1, graphql: Number(process.env.BETA_GRAPHQL_REPLICA) || 2,
sync: Number(process.env.BETA_SYNC_REPLICA) || 1, sync: Number(process.env.BETA_SYNC_REPLICA) || 2,
renderer: Number(process.env.BETA_RENDERER_REPLICA) || 1, renderer: Number(process.env.BETA_RENDERER_REPLICA) || 2,
doc: Number(process.env.BETA_DOC_REPLICA) || 1, doc: Number(process.env.BETA_DOC_REPLICA) || 2,
}, },
canary: { canary: {
web: 1, web: 2,
graphql: 1, graphql: 2,
sync: 1, sync: 2,
renderer: 1, renderer: 2,
doc: 1, doc: 2,
}, },
}; };
@@ -84,11 +81,6 @@ const createHelmCommand = ({ isDryRun }) => {
`--set-string global.redis.password="${REDIS_SERVER_PASSWORD}"`, `--set-string global.redis.password="${REDIS_SERVER_PASSWORD}"`,
] ]
: []; : [];
const indexerOptions = [
`--set-string global.indexer.provider="${AFFINE_INDEXER_SEARCH_PROVIDER}"`,
`--set-string global.indexer.endpoint="${AFFINE_INDEXER_SEARCH_ENDPOINT}"`,
`--set-string global.indexer.apiKey="${AFFINE_INDEXER_SEARCH_API_KEY}"`,
];
const serviceAnnotations = [ const serviceAnnotations = [
`--set-json web.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`, `--set-json web.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}\\" }"`,
@@ -126,10 +118,7 @@ const createHelmCommand = ({ isDryRun }) => {
? 'internal' ? 'internal'
: 'dev'; : 'dev';
const hosts = (DEPLOY_HOST || CANARY_DEPLOY_HOST) const host = DEPLOY_HOST || CANARY_DEPLOY_HOST;
.split(',')
.map(host => host.trim())
.filter(host => host);
const deployCommand = [ const deployCommand = [
`helm upgrade --install affine .github/helm/affine`, `helm upgrade --install affine .github/helm/affine`,
`--namespace ${namespace}`, `--namespace ${namespace}`,
@@ -138,24 +127,21 @@ const createHelmCommand = ({ isDryRun }) => {
`--set-string global.app.buildType="${buildType}"`, `--set-string global.app.buildType="${buildType}"`,
`--set global.ingress.enabled=true`, `--set global.ingress.enabled=true`,
`--set-json global.ingress.annotations="{ \\"kubernetes.io/ingress.class\\": \\"gce\\", \\"kubernetes.io/ingress.allow-http\\": \\"true\\", \\"kubernetes.io/ingress.global-static-ip-name\\": \\"${STATIC_IP_NAME}\\" }"`, `--set-json global.ingress.annotations="{ \\"kubernetes.io/ingress.class\\": \\"gce\\", \\"kubernetes.io/ingress.allow-http\\": \\"true\\", \\"kubernetes.io/ingress.global-static-ip-name\\": \\"${STATIC_IP_NAME}\\" }"`,
...hosts.map( `--set-string global.ingress.host="${host}"`,
(host, index) => `--set global.ingress.hosts[${index}]=${host}`
),
`--set-string global.version="${APP_VERSION}"`, `--set-string global.version="${APP_VERSION}"`,
...redisAndPostgres, ...redisAndPostgres,
...indexerOptions,
`--set web.replicaCount=${replica.web}`, `--set web.replicaCount=${replica.web}`,
`--set-string web.image.tag="${imageTag}"`, `--set-string web.image.tag="${imageTag}"`,
`--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 graphql.app.host=${host}`,
`--set sync.replicaCount=${replica.sync}`, `--set sync.replicaCount=${replica.sync}`,
`--set-string sync.image.tag="${imageTag}"`, `--set-string sync.image.tag="${imageTag}"`,
`--set-string renderer.image.tag="${imageTag}"`, `--set-string renderer.image.tag="${imageTag}"`,
`--set renderer.app.host=${hosts[0]}`, `--set renderer.app.host=${host}`,
`--set renderer.replicaCount=${replica.renderer}`, `--set renderer.replicaCount=${replica.renderer}`,
`--set-string doc.image.tag="${imageTag}"`, `--set-string doc.image.tag="${imageTag}"`,
`--set doc.app.host=${hosts[0]}`, `--set doc.app.host=${host}`,
`--set doc.replicaCount=${replica.doc}`, `--set doc.replicaCount=${replica.doc}`,
...serviceAnnotations, ...serviceAnnotations,
...resources, ...resources,
@@ -1,41 +0,0 @@
name: Prepare Release
description: 'Prepare Release'
outputs:
APP_VERSION:
description: 'App Version'
value: ${{ steps.get-version.outputs.APP_VERSION }}
GIT_SHORT_HASH:
description: 'Git Short Hash'
value: ${{ steps.get-version.outputs.GIT_SHORT_HASH }}
BUILD_TYPE:
description: 'Build Type'
value: ${{ steps.get-version.outputs.BUILD_TYPE }}
runs:
using: 'composite'
steps:
- name: Get Version
id: get-version
shell: bash
run: |
GIT_SHORT_HASH=$(git rev-parse --short HEAD)
if [ "${{ github.ref_type }}" == "tag" ]; then
APP_VERSION=$(echo "${{ github.ref_name }}" | sed 's/^v//')
else
APP_VERSION=$(date '+%Y.%-m.%-d-canary.%-H%M')
fi
if [[ "$APP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
BUILD_TYPE=stable
elif [[ "$APP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-beta\.[0-9]+$ ]]; then
BUILD_TYPE=beta
elif [[ "$APP_VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+-canary\.[0-9a-f]+$ ]]; then
BUILD_TYPE=canary
else
echo "Error: unsupported version string: $APP_VERSION" >&2
exit 1
fi
echo $APP_VERSION
echo $GIT_SHORT_HASH
echo $BUILD_TYPE
echo "APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
echo "GIT_SHORT_HASH=$GIT_SHORT_HASH" >> "$GITHUB_OUTPUT"
echo "BUILD_TYPE=$BUILD_TYPE" >> "$GITHUB_OUTPUT"
+7 -9
View File
@@ -4,11 +4,6 @@ description: 'Prepare Server Test Environment'
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- name: Bundle @affine/reader
shell: bash
run: |
yarn affine @affine/reader build
- name: Initialize database - name: Initialize database
shell: bash shell: bash
run: | run: |
@@ -26,10 +21,13 @@ runs:
yarn affine @affine/server prisma generate yarn affine @affine/server prisma generate
yarn affine @affine/server prisma migrate deploy yarn affine @affine/server prisma migrate deploy
yarn affine @affine/server data-migration run yarn affine @affine/server data-migration run
- name: Import config - name: Import config
shell: bash shell: bash
env:
DEFAULT_CONFIG: '{}'
run: | run: |
printf '%s\n' "${SERVER_CONFIG:-$DEFAULT_CONFIG}" > ./packages/backend/server/config.json printf '{"copilot":{"enabled":true,"providers.fal":{"apiKey":"%s"},"providers.gemini":{"apiKey":"%s"},"providers.openai":{"apiKey":"%s"},"providers.perplexity":{"apiKey":"%s"},"providers.anthropic":{"apiKey":"%s"},"exa":{"key":"%s"}}}' \
"$COPILOT_FAL_API_KEY" \
"$COPILOT_GOOGLE_API_KEY" \
"$COPILOT_OPENAI_API_KEY" \
"$COPILOT_PERPLEXITY_API_KEY" \
"$COPILOT_ANTHROPIC_API_KEY" \
"$COPILOT_EXA_API_KEY" > ./packages/backend/server/config.json
+16 -10
View File
@@ -1,18 +1,24 @@
name: Setup Version name: Setup Version
description: 'Setup Version' description: 'Setup Version'
inputs: outputs:
app-version: APP_VERSION:
description: 'App Version' description: 'App Version'
required: true value: ${{ steps.version.outputs.APP_VERSION }}
ios-app-version:
description: 'iOS App Store Version (Optional, use App version if empty)'
required: false
type: string
runs: runs:
using: 'composite' using: 'composite'
steps: steps:
- name: 'Write Version' - name: 'Write Version'
id: version
shell: bash shell: bash
env: run: |
IOS_APP_VERSION: ${{ inputs.ios-app-version }} if [ "${{ github.ref_type }}" == "tag" ]; then
run: ./scripts/set-version.sh ${{ inputs.app-version }} APP_VERSION=$(echo "${{ github.ref_name }}" | sed 's/^v//')
else
PACKAGE_VERSION=$(node -p "require('./package.json').version")
TIME_VERSION=$(date +%Y%m%d%H%M)
GIT_SHORT_HASH=$(git rev-parse --short HEAD)
APP_VERSION=$PACKAGE_VERSION-nightly-$GIT_SHORT_HASH
fi
echo $APP_VERSION
echo "APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
./scripts/set-version.sh $APP_VERSION
+1 -4
View File
@@ -7,10 +7,7 @@ COPY ./packages/frontend/apps/mobile/dist /app/static/mobile
WORKDIR /app WORKDIR /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 && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# Enable jemalloc by preloading the library
ENV LD_PRELOAD=libjemalloc.so.2
CMD ["node", "./dist/main.js"] CMD ["node", "./dist/main.js"]
+1 -1
View File
@@ -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.22.4" appVersion: "0.21.0"
+1 -1
View File
@@ -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.22.4" appVersion: "0.20.0"
dependencies: dependencies:
- name: gcloud-sql-proxy - name: gcloud-sql-proxy
version: 0.0.0 version: 0.0.0
@@ -69,15 +69,6 @@ spec:
key: redis-password key: redis-password
- name: REDIS_SERVER_DATABASE - name: REDIS_SERVER_DATABASE
value: "{{ .Values.global.redis.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 - name: AFFINE_SERVER_PORT
value: "{{ .Values.global.docService.port }}" value: "{{ .Values.global.docService.port }}"
- name: AFFINE_SERVER_SUB_PATH - name: AFFINE_SERVER_SUB_PATH
@@ -95,13 +86,11 @@ spec:
path: /info path: /info
port: http port: http
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }} initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
readinessProbe: readinessProbe:
httpGet: httpGet:
path: /info path: /info
port: http port: http
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }} initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
resources: resources:
{{- toYaml .Values.resources | nindent 12 }} {{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }} {{- with .Values.nodeSelector }}
+1 -2
View File
@@ -1,6 +1,6 @@
replicaCount: 1 replicaCount: 1
image: image:
repository: ghcr.io/toeverything/affine repository: ghcr.io/toeverything/affine-graphql
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: '' tag: ''
@@ -36,7 +36,6 @@ resources:
probe: probe:
initialDelaySeconds: 20 initialDelaySeconds: 20
timeoutSeconds: 5
nodeSelector: {} nodeSelector: {}
tolerations: [] tolerations: []
@@ -1,4 +1,4 @@
replicaCount: 2 replicaCount: 3
enabled: false enabled: false
database: database:
connectionName: "" connectionName: ""
@@ -33,11 +33,8 @@ service:
resources: resources:
limits: limits:
memory: "1Gi" memory: "4Gi"
cpu: "1" cpu: "2"
requests:
memory: "512Mi"
cpu: "100m"
volumes: [] volumes: []
volumeMounts: [] volumeMounts: []
@@ -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.22.4" appVersion: "0.21.0"
dependencies: dependencies:
- name: gcloud-sql-proxy - name: gcloud-sql-proxy
version: 0.0.0 version: 0.0.0
@@ -67,15 +67,6 @@ spec:
key: redis-password key: redis-password
- name: REDIS_SERVER_DATABASE - name: REDIS_SERVER_DATABASE
value: "{{ .Values.global.redis.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 - name: AFFINE_SERVER_PORT
value: "{{ .Values.service.port }}" value: "{{ .Values.service.port }}"
- name: AFFINE_SERVER_SUB_PATH - name: AFFINE_SERVER_SUB_PATH
@@ -44,15 +44,6 @@ spec:
secretKeyRef: secretKeyRef:
name: redis name: redis
key: redis-password key: redis-password
- 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
resources: resources:
requests: requests:
cpu: '100m' cpu: '100m'
@@ -1,6 +1,6 @@
replicaCount: 1 replicaCount: 1
image: image:
repository: ghcr.io/toeverything/affine repository: ghcr.io/toeverything/affine-graphql
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: '' tag: ''
@@ -3,7 +3,7 @@ name: renderer
description: AFFiNE renderer server description: AFFiNE renderer server
type: application type: application
version: 0.0.0 version: 0.0.0
appVersion: "0.22.4" appVersion: "0.16.0"
dependencies: dependencies:
- name: gcloud-sql-proxy - name: gcloud-sql-proxy
version: 0.0.0 version: 0.0.0
@@ -69,15 +69,6 @@ spec:
key: redis-password key: redis-password
- name: REDIS_SERVER_DATABASE - name: REDIS_SERVER_DATABASE
value: "{{ .Values.global.redis.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 - name: AFFINE_SERVER_PORT
value: "{{ .Values.service.port }}" value: "{{ .Values.service.port }}"
- name: AFFINE_SERVER_SUB_PATH - name: AFFINE_SERVER_SUB_PATH
@@ -1,6 +1,6 @@
replicaCount: 1 replicaCount: 1
image: image:
repository: ghcr.io/toeverything/affine repository: ghcr.io/toeverything/affine-graphql
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: '' tag: ''
+1 -1
View File
@@ -3,7 +3,7 @@ name: sync
description: AFFiNE Sync Server description: AFFiNE Sync Server
type: application type: application
version: 0.0.0 version: 0.0.0
appVersion: "0.22.4" appVersion: "0.21.0"
dependencies: dependencies:
- name: gcloud-sql-proxy - name: gcloud-sql-proxy
version: 0.0.0 version: 0.0.0
@@ -69,15 +69,6 @@ spec:
key: redis-password key: redis-password
- name: REDIS_SERVER_DATABASE - name: REDIS_SERVER_DATABASE
value: "{{ .Values.global.redis.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 - name: AFFINE_SERVER_PORT
value: "{{ .Values.service.port }}" value: "{{ .Values.service.port }}"
- name: AFFINE_SERVER_HOST - name: AFFINE_SERVER_HOST
+1 -1
View File
@@ -1,6 +1,6 @@
replicaCount: 1 replicaCount: 1
image: image:
repository: ghcr.io/toeverything/affine repository: ghcr.io/toeverything/affine-graphql
pullPolicy: IfNotPresent pullPolicy: IfNotPresent
tag: '' tag: ''
@@ -1,13 +0,0 @@
{{- if .Values.global.indexer.apiKey -}}
apiVersion: v1
kind: Secret
metadata:
name: indexer
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-2"
"helm.sh/hook-delete-policy": before-hook-creation
type: Opaque
data:
indexer-apiKey: {{ .Values.global.indexer.apiKey | b64enc }}
{{- end }}
+6 -8
View File
@@ -36,8 +36,7 @@ spec:
{{- end }} {{- end }}
{{- end }} {{- end }}
rules: rules:
{{- range .Values.global.ingress.hosts }} - host: "{{ .Values.global.ingress.host }}"
- host: {{ . | quote }}
http: http:
paths: paths:
- path: /socket.io - path: /socket.io
@@ -46,34 +45,33 @@ spec:
service: service:
name: affine-sync name: affine-sync
port: port:
number: {{ $.Values.sync.service.port }} number: {{ .Values.sync.service.port }}
- path: /graphql - path: /graphql
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: affine-graphql name: affine-graphql
port: port:
number: {{ $.Values.graphql.service.port }} number: {{ .Values.graphql.service.port }}
- path: /api - path: /api
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: affine-graphql name: affine-graphql
port: port:
number: {{ $.Values.graphql.service.port }} number: {{ .Values.graphql.service.port }}
- path: /workspace - path: /workspace
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: affine-renderer name: affine-renderer
port: port:
number: {{ $.Values.renderer.service.port }} number: {{ .Values.renderer.service.port }}
- path: / - path: /
pathType: Prefix pathType: Prefix
backend: backend:
service: service:
name: affine-web name: affine-web
port: port:
number: {{ $.Values.web.service.port }} number: {{ .Values.web.service.port }}
{{- end }}
{{- end }} {{- end }}
@@ -1,13 +0,0 @@
{{- if eq .Values.global.deployment.platform "gcp" -}}
apiVersion: monitoring.googleapis.com/v1
kind: PodMonitoring
metadata:
name: "{{ .Release.Name }}-monitoring"
spec:
selector:
matchLabels:
app.kubernetes.io/instance: {{ .Release.Name }}
endpoints:
- port: 9464
interval: 30s
{{- end }}
+1 -12
View File
@@ -4,13 +4,7 @@ global:
ingress: ingress:
enabled: false enabled: false
className: '' className: ''
# hosts for ingress rules host: affine.pro
# e.g.
# hosts:
# - affine.pro
# - www.affine.pro
hosts:
- affine.pro
tls: [] tls: []
secret: secret:
secretName: 'server-private-key' secretName: 'server-private-key'
@@ -27,11 +21,6 @@ global:
username: '' username: ''
password: '' password: ''
database: 0 database: 0
indexer:
provider: ''
endpoint: ''
username: ''
password: ''
docService: docService:
name: 'affine-doc' name: 'affine-doc'
port: 3020 port: 3020
+26 -37
View File
@@ -3,13 +3,7 @@ name: Build Images
on: on:
workflow_call: workflow_call:
inputs: inputs:
build-type: flavor:
type: string
required: true
app-version:
type: string
required: true
git-short-hash:
type: string type: string
required: true required: true
@@ -22,13 +16,12 @@ jobs:
build-web: build-web:
name: Build @affine/web name: Build @affine/web
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.flavor }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Build Core - name: Build Core
@@ -37,11 +30,11 @@ jobs:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
BUILD_TYPE: ${{ inputs.build-type }} BUILD_TYPE: ${{ github.event.inputs.flavor }}
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }} CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: 'affine-web' SENTRY_PROJECT: 'affine-web'
SENTRY_RELEASE: ${{ inputs.app-version }} SENTRY_RELEASE: ${{ steps.version.outputs.APP_VERSION }}
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 }}
@@ -56,13 +49,12 @@ jobs:
build-admin: build-admin:
name: Build @affine/admin name: Build @affine/admin
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.flavor }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Build Admin - name: Build Admin
@@ -71,7 +63,7 @@ jobs:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
BUILD_TYPE: ${{ inputs.build-type }} BUILD_TYPE: ${{ github.event.inputs.flavor }}
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }} CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: 'affine-admin' SENTRY_PROJECT: 'affine-admin'
@@ -89,13 +81,12 @@ jobs:
build-mobile: build-mobile:
name: Build @affine/mobile name: Build @affine/mobile
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.flavor }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Build Mobile - name: Build Mobile
@@ -104,7 +95,7 @@ jobs:
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }} R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }} R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }} R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
BUILD_TYPE: ${{ inputs.build-type }} BUILD_TYPE: ${{ github.event.inputs.flavor }}
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }} CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
SENTRY_ORG: ${{ secrets.SENTRY_ORG }} SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
SENTRY_PROJECT: 'affine-mobile' SENTRY_PROJECT: 'affine-mobile'
@@ -122,7 +113,6 @@ 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-latest
environment: ${{ inputs.build-type }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -137,9 +127,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
with: with:
@@ -147,9 +136,6 @@ jobs:
extra-flags: workspaces focus @affine/server-native extra-flags: workspaces focus @affine/server-native
- name: Build Rust - name: Build Rust
uses: ./.github/actions/build-rust uses: ./.github/actions/build-rust
env:
AFFINE_PRO_PUBLIC_KEY: ${{ secrets.AFFINE_PRO_PUBLIC_KEY }}
AFFINE_PRO_LICENSE_AES_KEY: ${{ secrets.AFFINE_PRO_LICENSE_AES_KEY }}
with: with:
target: ${{ matrix.targets.name }} target: ${{ matrix.targets.name }}
package: '@affine/server-native' package: '@affine/server-native'
@@ -171,9 +157,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
with: with:
@@ -187,8 +172,6 @@ jobs:
path: ./packages/backend/native path: ./packages/backend/native
- name: List server-native files - name: List server-native files
run: ls -alh ./packages/backend/native run: ls -alh ./packages/backend/native
- name: Build @affine/reader
run: yarn workspace @affine/reader build
- name: Build Server - name: Build Server
run: yarn workspace @affine/server build run: yarn workspace @affine/server build
- name: Upload server dist - name: Upload server dist
@@ -213,6 +196,16 @@ jobs:
with: with:
name: server-dist name: server-dist
path: ./packages/backend/server/dist path: ./packages/backend/server/dist
- name: Setup env
run: |
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
if [ -z "${{ inputs.flavor }}" ]
then
echo "RELEASE_FLAVOR=canary" >> "$GITHUB_ENV"
else
echo "RELEASE_FLAVOR=${{ inputs.flavor }}" >> "$GITHUB_ENV"
fi
- name: Login to GitHub Container Registry - name: Login to GitHub Container Registry
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
@@ -260,13 +253,9 @@ jobs:
- name: Generate Prisma client - name: Generate Prisma client
run: yarn workspace @affine/server prisma generate run: yarn workspace @affine/server prisma generate
- name: Mv node_modules
run: mv ./node_modules ./packages/backend/server
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Build front Dockerfile - name: Build front Dockerfile
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
@@ -277,7 +266,7 @@ jobs:
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
provenance: true provenance: true
file: .github/deployment/front/Dockerfile file: .github/deployment/front/Dockerfile
tags: ghcr.io/toeverything/affine-front:${{inputs.build-type}}-${{ inputs.git-short-hash }} tags: ghcr.io/toeverything/affine-front:${{env.RELEASE_FLAVOR}}-${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-front:${{env.RELEASE_FLAVOR}}
- name: Build graphql Dockerfile - name: Build graphql Dockerfile
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
@@ -288,4 +277,4 @@ jobs:
platforms: linux/amd64,linux/arm64,linux/arm/v7 platforms: linux/amd64,linux/arm64,linux/arm/v7
provenance: true provenance: true
file: .github/deployment/node/Dockerfile file: .github/deployment/node/Dockerfile
tags: ghcr.io/toeverything/affine:${{inputs.build-type}}-${{ inputs.git-short-hash }} tags: ghcr.io/toeverything/affine-graphql:${{env.RELEASE_FLAVOR}}-${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-graphql:${{env.RELEASE_FLAVOR}}
@@ -0,0 +1,25 @@
name: Build Selfhost Image
on:
workflow_dispatch:
inputs:
flavor:
description: 'Select distribution to build'
type: choice
default: canary
options:
- canary
- beta
- stable
permissions:
contents: 'write'
id-token: 'write'
packages: 'write'
jobs:
build-image:
name: Build Image
uses: ./.github/workflows/build-images.yml
with:
flavor: ${{ github.event.inputs.flavor }}
+117 -180
View File
@@ -11,7 +11,6 @@ on:
paths-ignore: paths-ignore:
- README.md - README.md
pull_request: pull_request:
merge_group:
env: env:
DEBUG: napi:* DEBUG: napi:*
@@ -21,18 +20,32 @@ env:
COVERAGE: true COVERAGE: true
MACOSX_DEPLOYMENT_TARGET: '10.13' MACOSX_DEPLOYMENT_TARGET: '10.13'
DEPLOYMENT_TYPE: affine DEPLOYMENT_TYPE: affine
AFFINE_INDEXER_ENABLED: true
concurrency: concurrency:
group: ${{ github.workflow }}-${{ github.ref }} group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true cancel-in-progress: true
jobs: jobs:
optimize_ci:
name: Optimize CI
runs-on: ubuntu-latest
outputs:
skip: ${{ steps.check_skip.outputs.skip }}
steps:
- uses: actions/checkout@v4
- name: Graphite CI Optimizer
uses: withgraphite/graphite-ci-action@main
id: check_skip
with:
graphite_token: ${{ secrets.GRAPHITE_CI_OPTIMIZER_TOKEN }}
analyze: analyze:
name: Analyze name: Analyze
runs-on: ubuntu-latest runs-on: ubuntu-latest
env: env:
NODE_OPTIONS: --max-old-space-size=14384 NODE_OPTIONS: --max-old-space-size=14384
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
permissions: permissions:
actions: read actions: read
contents: read contents: read
@@ -66,6 +79,9 @@ jobs:
lint: lint:
name: Lint name: Lint
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run oxlint - name: Run oxlint
@@ -91,6 +107,8 @@ jobs:
typecheck: typecheck:
name: Typecheck name: Typecheck
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
NODE_OPTIONS: --max-old-space-size=14384 NODE_OPTIONS: --max-old-space-size=14384
steps: steps:
@@ -107,7 +125,6 @@ jobs:
- name: Run BS Docs Build - name: Run BS Docs Build
run: | run: |
yarn affine bs-docs build yarn affine bs-docs build
git checkout packages/frontend/i18n/src/i18n-completenesses.json
git status --porcelain | grep . && { git status --porcelain | grep . && {
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
@@ -118,6 +135,8 @@ jobs:
lint-rust: lint-rust:
name: Lint Rust name: Lint Rust
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: ./.github/actions/build-rust - uses: ./.github/actions/build-rust
@@ -131,14 +150,14 @@ jobs:
- name: Clippy - name: Clippy
run: | run: |
rustup component add clippy rustup component add clippy
cargo clippy --workspace --exclude affine_server_native --all-targets --all-features -- -D warnings cargo clippy --all-targets --all-features -- -D warnings
cargo clippy -p affine_server_native --all-targets --all-features -- -D warnings
check-git-status: check-git-status:
name: Check Git Status name: Check Git Status
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- build-server-native - optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
@@ -146,26 +165,13 @@ jobs:
with: with:
full-cache: true full-cache: true
- name: Download server-native.node
uses: actions/download-artifact@v4
with:
name: server-native.node
path: ./packages/backend/native
- name: Bundle @affine/reader
shell: bash
run: |
yarn workspace @affine/reader build
- name: Run Check - name: Run Check
run: | run: |
yarn affine init yarn affine init
yarn affine gql build yarn affine gql build
yarn affine i18n build yarn affine i18n build
yarn affine server genconfig
git checkout packages/frontend/i18n/src/i18n-completenesses.json
git status --porcelain | grep . && { git status --porcelain | grep . && {
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' and make sure all changes are submitted"
exit 1 exit 1
} || { } || {
echo "All changes are submitted" echo "All changes are submitted"
@@ -174,6 +180,8 @@ jobs:
check-yarn-binary: check-yarn-binary:
name: Check yarn binary name: Check yarn binary
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Run check - name: Run check
@@ -184,6 +192,8 @@ jobs:
e2e-blocksuite-test: e2e-blocksuite-test:
name: E2E BlockSuite Test name: E2E BlockSuite Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -215,6 +225,8 @@ 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
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -249,6 +261,8 @@ jobs:
e2e-test: e2e-test:
name: E2E Test name: E2E Test
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
DISTRIBUTION: web DISTRIBUTION: web
IN_CI_TEST: true IN_CI_TEST: true
@@ -281,6 +295,8 @@ jobs:
e2e-mobile-test: e2e-mobile-test:
name: E2E Mobile Test name: E2E Mobile Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
DISTRIBUTION: mobile DISTRIBUTION: mobile
IN_CI_TEST: true IN_CI_TEST: true
@@ -312,7 +328,9 @@ jobs:
name: Unit Test name: Unit Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-native - build-native
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
DISTRIBUTION: web DISTRIBUTION: web
strategy: strategy:
@@ -349,6 +367,8 @@ jobs:
build-native: build-native:
name: Build AFFiNE native (${{ matrix.spec.target }}) name: Build AFFiNE native (${{ matrix.spec.target }})
runs-on: ${{ matrix.spec.os }} runs-on: ${{ matrix.spec.os }}
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
CARGO_PROFILE_RELEASE_DEBUG: '1' CARGO_PROFILE_RELEASE_DEBUG: '1'
strategy: strategy:
@@ -391,6 +411,8 @@ jobs:
build-windows-native: build-windows-native:
name: Build AFFiNE native (${{ matrix.spec.target }}) name: Build AFFiNE native (${{ matrix.spec.target }})
runs-on: ${{ matrix.spec.os }} runs-on: ${{ matrix.spec.os }}
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
CARGO_PROFILE_RELEASE_DEBUG: '1' CARGO_PROFILE_RELEASE_DEBUG: '1'
strategy: strategy:
@@ -438,6 +460,8 @@ jobs:
build-server-native: build-server-native:
name: Build Server native name: Build Server native
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
CARGO_PROFILE_RELEASE_DEBUG: '1' CARGO_PROFILE_RELEASE_DEBUG: '1'
steps: steps:
@@ -463,6 +487,8 @@ jobs:
build-electron-renderer: build-electron-renderer:
name: Build @affine/electron renderer name: Build @affine/electron renderer
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
@@ -488,7 +514,9 @@ jobs:
name: Native Unit Test name: Native Unit Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-native - build-native
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
@@ -508,7 +536,9 @@ jobs:
name: Server Test name: Server Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-server-native - build-server-native
if: needs.optimize_ci.outputs.skip == 'false'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -539,10 +569,6 @@ jobs:
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -577,94 +603,14 @@ jobs:
name: affine name: affine
fail_ci_if_error: false fail_ci_if_error: false
server-test-elasticsearch:
name: Server Test with Elasticsearch
runs-on: ubuntu-latest
needs:
- build-server-native
strategy:
fail-fast: false
env:
NODE_ENV: test
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
REDIS_SERVER_HOST: localhost
AFFINE_INDEXER_SEARCH_PROVIDER: elasticsearch
AFFINE_INDEXER_SEARCH_ENDPOINT: http://localhost:9200
services:
postgres:
image: pgvector/pgvector:pg16
env:
POSTGRES_PASSWORD: affine
options: >-
--health-cmd pg_isready
--health-interval 10s
--health-timeout 5s
--health-retries 5
ports:
- 5432:5432
redis:
image: redis
ports:
- 6379:6379
mailer:
image: mailhog/mailhog
ports:
- 1025:1025
- 8025:8025
steps:
# https://github.com/elastic/elastic-github-actions/blob/master/elasticsearch/README.md
- name: Configure sysctl limits for Elasticsearch
run: |
sudo swapoff -a
sudo sysctl -w vm.swappiness=1
sudo sysctl -w fs.file-max=262144
sudo sysctl -w vm.max_map_count=262144
- name: Runs Elasticsearch
uses: elastic/elastic-github-actions/elasticsearch@master
with:
stack-version: 9.0.1
security-enabled: false
- uses: actions/checkout@v4
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
electron-install: false
full-cache: true
- name: Download server-native.node
uses: actions/download-artifact@v4
with:
name: server-native.node
path: ./packages/backend/native
- name: Prepare Server Test Environment
uses: ./.github/actions/server-test-env
- name: Run server tests with elasticsearch only
run: yarn affine @affine/server test:coverage "**/*/*elasticsearch.spec.ts" --forbid-only
env:
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
CI_NODE_INDEX: ${{ matrix.node_index }}
CI_NODE_TOTAL: ${{ matrix.total_nodes }}
- name: Upload server test coverage results
uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: ./packages/backend/server/.coverage/lcov.info
flags: server-test
name: affine
fail_ci_if_error: false
server-e2e-test: server-e2e-test:
# the new version of server e2e test should be super fast, so sharding testing is not needed # the new version of server e2e test should be super fast, so sharding testing is not needed
name: Server E2E Test name: Server E2E Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-server-native - build-server-native
if: needs.optimize_ci.outputs.skip == '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
@@ -685,10 +631,6 @@ jobs:
image: redis image: redis
ports: ports:
- 6379:6379 - 6379:6379
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -722,6 +664,9 @@ jobs:
miri: miri:
name: miri code check name: miri code check
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
RUST_BACKTRACE: full RUST_BACKTRACE: full
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
@@ -735,9 +680,7 @@ jobs:
toolchain: nightly toolchain: nightly
components: miri components: miri
- name: Install latest nextest release - name: Install latest nextest release
uses: taiki-e/install-action@v2 uses: taiki-e/install-action@nextest
with:
tool: nextest@0.9.98
- name: Miri Code Check - name: Miri Code Check
continue-on-error: true continue-on-error: true
@@ -747,6 +690,9 @@ jobs:
loom: loom:
name: loom thread test name: loom thread test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
RUSTFLAGS: --cfg loom RUSTFLAGS: --cfg loom
RUST_BACKTRACE: full RUST_BACKTRACE: full
@@ -759,9 +705,7 @@ jobs:
with: with:
toolchain: stable toolchain: stable
- name: Install latest nextest release - name: Install latest nextest release
uses: taiki-e/install-action@v2 uses: taiki-e/install-action@nextest
with:
tool: nextest@0.9.98
- name: Loom Thread Test - name: Loom Thread Test
run: | run: |
@@ -770,7 +714,11 @@ jobs:
fuzzing: fuzzing:
name: fuzzing name: fuzzing
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs:
- optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
RUSTFLAGS: -D warnings
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -816,6 +764,9 @@ jobs:
- { target: 'aarch64-apple-darwin', os: 'macos-latest' } - { target: 'aarch64-apple-darwin', os: 'macos-latest' }
- { target: 'x86_64-pc-windows-msvc', os: 'windows-latest' } - { target: 'x86_64-pc-windows-msvc', os: 'windows-latest' }
- { target: 'aarch64-pc-windows-msvc', os: 'windows-11-arm' } - { target: 'aarch64-pc-windows-msvc', os: 'windows-11-arm' }
needs:
- optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
@@ -849,6 +800,8 @@ jobs:
rust-test: rust-test:
name: Run native tests name: Run native tests
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
CARGO_TERM_COLOR: always CARGO_TERM_COLOR: always
steps: steps:
@@ -860,18 +813,18 @@ jobs:
no-build: 'true' no-build: 'true'
- name: Install latest nextest release - name: Install latest nextest release
uses: taiki-e/install-action@v2 uses: taiki-e/install-action@nextest
with:
tool: nextest@0.9.98
- 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 --release --no-fail-fast
copilot-api-test: copilot-api-test:
name: Server Copilot Api Test name: Server Copilot Api Test
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-server-native - build-server-native
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
NODE_ENV: test NODE_ENV: test
DISTRIBUTION: web DISTRIBUTION: web
@@ -898,10 +851,6 @@ jobs:
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -941,7 +890,12 @@ jobs:
- name: Prepare Server Test Environment - name: Prepare Server Test Environment
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }} if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.apifilter.outputs.changed == 'true' }}
env: env:
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }} COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
COPILOT_ANTHROPIC_API_KEY: ${{ secrets.COPILOT_ANTHROPIC_API_KEY }}
COPILOT_EXA_API_KEY: ${{ secrets.COPILOT_EXA_API_KEY }}
uses: ./.github/actions/server-test-env uses: ./.github/actions/server-test-env
- name: Run server tests - name: Run server tests
@@ -972,8 +926,8 @@ 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, 6, 7, 8]
shardTotal: [10] shardTotal: [8]
needs: needs:
- build-server-native - build-server-native
services: services:
@@ -992,10 +946,6 @@ jobs:
image: redis image: redis
ports: ports:
- 6379:6379 - 6379:6379
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -1018,7 +968,6 @@ jobs:
- 'packages/backend/server/src/plugins/copilot/**' - 'packages/backend/server/src/plugins/copilot/**'
- 'packages/backend/server/tests/copilot.*' - 'packages/backend/server/tests/copilot.*'
- 'packages/frontend/core/src/blocksuite/ai/**' - 'packages/frontend/core/src/blocksuite/ai/**'
- 'packages/frontend/core/src/modules/workspace-indexer-embedding/**'
- 'tests/affine-cloud-copilot/**' - 'tests/affine-cloud-copilot/**'
- name: Setup Node.js - name: Setup Node.js
@@ -1040,7 +989,12 @@ jobs:
- name: Prepare Server Test Environment - name: Prepare Server Test Environment
if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }} if: ${{ steps.check-blocksuite-update.outputs.skip != 'true' || steps.e2efilter.outputs.changed == 'true' }}
env: env:
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }} COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
COPILOT_ANTHROPIC_API_KEY: ${{ secrets.COPILOT_ANTHROPIC_API_KEY }}
COPILOT_EXA_API_KEY: ${{ secrets.COPILOT_EXA_API_KEY }}
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 }}
@@ -1053,8 +1007,10 @@ jobs:
name: ${{ matrix.tests.name }} name: ${{ matrix.tests.name }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: needs:
- optimize_ci
- build-server-native - build-server-native
- build-native - build-native
if: needs.optimize_ci.outputs.skip == 'false'
env: env:
DISTRIBUTION: web DISTRIBUTION: web
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
@@ -1064,36 +1020,24 @@ jobs:
fail-fast: false fail-fast: false
matrix: matrix:
tests: tests:
- name: 'Cloud E2E Test 1/10' - name: 'Cloud E2E Test 1/6'
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/6
- name: 'Cloud E2E Test 2/10' - name: 'Cloud E2E Test 2/6'
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/6
- name: 'Cloud E2E Test 3/10' - name: 'Cloud E2E Test 3/6'
shard: 3 shard: 3
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=3/10 script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=3/6
- name: 'Cloud E2E Test 4/10' - name: 'Cloud E2E Test 4/6'
shard: 4 shard: 4
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=4/10 script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=4/6
- name: 'Cloud E2E Test 5/10' - name: 'Cloud E2E Test 5/6'
shard: 5 shard: 5
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=5/10 script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=5/6
- name: 'Cloud E2E Test 6/10' - name: 'Cloud E2E Test 6/6'
shard: 6 shard: 6
script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=6/10 script: yarn affine @affine-test/affine-cloud e2e --forbid-only --shard=6/6
- 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: |
@@ -1124,10 +1068,6 @@ jobs:
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -1170,8 +1110,10 @@ jobs:
name: Desktop Test (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }}) name: Desktop Test (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }})
runs-on: ${{ matrix.spec.os }} runs-on: ${{ matrix.spec.os }}
needs: needs:
- optimize_ci
- build-electron-renderer - build-electron-renderer
- build-native - build-native
if: needs.optimize_ci.outputs.skip == 'false'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -1266,8 +1208,10 @@ jobs:
name: Desktop bundle check (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }}) name: Desktop bundle check (${{ matrix.spec.os }}, ${{ matrix.spec.platform }}, ${{ matrix.spec.arch }}, ${{ matrix.spec.target }}, ${{ matrix.spec.test }})
runs-on: ${{ matrix.spec.os }} runs-on: ${{ matrix.spec.os }}
needs: needs:
- optimize_ci
- build-electron-renderer - build-electron-renderer
- build-native - build-native
if: needs.optimize_ci.outputs.skip == 'false'
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -1293,13 +1237,6 @@ jobs:
target: x86_64-unknown-linux-gnu, target: x86_64-unknown-linux-gnu,
test: true, test: true,
} }
- {
os: windows-latest,
platform: windows,
arch: x64,
target: x86_64-pc-windows-msvc,
test: true,
}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Node.js - name: Setup Node.js
@@ -1340,18 +1277,6 @@ jobs:
HOIST_NODE_MODULES: 1 HOIST_NODE_MODULES: 1
run: yarn affine @affine/electron package --platform=darwin --arch=arm64 run: yarn affine @affine/electron package --platform=darwin --arch=arm64
- name: Make Bundle (Windows)
if: ${{ matrix.spec.target == 'x86_64-pc-windows-msvc' }}
shell: bash
env:
SKIP_BUNDLE: true
SKIP_WEB_BUILD: true
HOIST_NODE_MODULES: 1
run: |
rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite/affine/node_modules
rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules
yarn affine @affine/electron package --platform=win32 --arch=x64
- name: Make Bundle (Linux) - name: Make Bundle (Linux)
run: | run: |
sudo add-apt-repository universe sudo add-apt-repository universe
@@ -1371,6 +1296,17 @@ 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
test-build-mobile-app:
uses: ./.github/workflows/release-mobile.yml
needs: optimize_ci
if: needs.optimize_ci.outputs.skip == 'false'
with:
build-type: canary
build-target: development
secrets: inherit
permissions:
id-token: 'write'
test-done: test-done:
needs: needs:
- analyze - analyze
@@ -1401,6 +1337,7 @@ jobs:
- desktop-test - desktop-test
- desktop-bundle-check - desktop-bundle-check
- cloud-e2e-test - cloud-e2e-test
- test-build-mobile-app
if: always() if: always()
runs-on: ubuntu-latest runs-on: ubuntu-latest
name: 3, 2, 1 Launch name: 3, 2, 1 Launch
+14 -12
View File
@@ -59,10 +59,6 @@ jobs:
ports: ports:
- 1025:1025 - 1025:1025
- 8025:8025 - 8025:8025
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -81,7 +77,12 @@ jobs:
- name: Prepare Server Test Environment - name: Prepare Server Test Environment
env: env:
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }} COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
COPILOT_ANTHROPIC_API_KEY: ${{ secrets.COPILOT_ANTHROPIC_API_KEY }}
COPILOT_EXA_API_KEY: ${{ secrets.COPILOT_EXA_API_KEY }}
uses: ./.github/actions/server-test-env uses: ./.github/actions/server-test-env
- name: Run server tests - name: Run server tests
@@ -109,8 +110,8 @@ 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, 6, 7, 8]
shardTotal: [10] shardTotal: [8]
needs: needs:
- build-server-native - build-server-native
services: services:
@@ -129,10 +130,6 @@ jobs:
image: redis image: redis
ports: ports:
- 6379:6379 - 6379:6379
indexer:
image: manticoresearch/manticore:10.1.0
ports:
- 9308:9308
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -151,7 +148,12 @@ jobs:
- name: Prepare Server Test Environment - name: Prepare Server Test Environment
env: env:
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }} COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
COPILOT_GOOGLE_API_KEY: ${{ secrets.COPILOT_GOOGLE_API_KEY }}
COPILOT_PERPLEXITY_API_KEY: ${{ secrets.COPILOT_PERPLEXITY_API_KEY }}
COPILOT_ANTHROPIC_API_KEY: ${{ secrets.COPILOT_ANTHROPIC_API_KEY }}
COPILOT_EXA_API_KEY: ${{ secrets.COPILOT_EXA_API_KEY }}
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 }}
@@ -0,0 +1,32 @@
name: Deploy Automatically
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-canary.[0-9]+'
schedule:
- cron: '0 9 * * *'
permissions:
contents: write
pull-requests: write
actions: write
jobs:
dispatch-deploy:
runs-on: ubuntu-latest
name: Setup Deploy
steps:
- name: dispatch deploy by tag
if: ${{ github.event_name == 'push' }}
uses: benc-uk/workflow-dispatch@v1
with:
workflow: deploy.yml
inputs: '{ "flavor": "canary" }'
- name: dispatch deploy by schedule
if: ${{ github.event_name == 'schedule' }}
uses: benc-uk/workflow-dispatch@v1
with:
workflow: deploy.yml
inputs: '{ "flavor": "canary" }'
ref: canary
+186
View File
@@ -0,0 +1,186 @@
name: Deploy
on:
workflow_dispatch:
inputs:
flavor:
description: 'Select what enverionment to deploy to'
type: choice
default: canary
options:
- canary
- beta
- stable
- internal
permissions:
contents: 'write'
id-token: 'write'
packages: 'write'
jobs:
output-prev-version:
name: Output previous version
runs-on: ubuntu-latest
environment: ${{ github.event.inputs.flavor }}
outputs:
prev: ${{ steps.print.outputs.version }}
namespace: ${{ steps.print.outputs.namespace }}
steps:
- uses: actions/checkout@v4
- name: Auth to Cluster
uses: './.github/actions/cluster-auth'
with:
gcp-project-number: ${{ secrets.GCP_PROJECT_NUMBER }}
gcp-project-id: ${{ secrets.GCP_PROJECT_ID }}
service-account: ${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}
cluster-name: ${{ secrets.GCP_CLUSTER_NAME }}
cluster-location: ${{ secrets.GCP_CLUSTER_LOCATION }}
- name: Output previous version
id: print
run: |
namespace=""
if [ "${{ github.event.inputs.flavor }}" = "canary" ]; then
namespace="dev"
elif [ "${{ github.event.inputs.flavor }}" = "beta" ]; then
namespace="beta"
elif [ "${{ github.event.inputs.flavor }}" = "stable" ]; then
namespace="production"
else
echo "Invalid flavor: ${{ github.event.inputs.flavor }}"
exit 1
fi
echo "Namespace set to: $namespace"
# Get the previous version from the deployment
prev_version=$(kubectl get deployment -n $namespace affine-graphql -o=jsonpath='{.spec.template.spec.containers[0].image}' | awk -F '-' '{print $3}')
echo "Previous version: $prev_version"
echo "version=$prev_version" >> $GITHUB_OUTPUT
echo "namesapce=$namespace" >> $GITHUB_OUTPUT
build-images:
name: Build Images
uses: ./.github/workflows/build-images.yml
secrets: inherit
with:
flavor: ${{ github.event.inputs.flavor }}
deploy:
name: Deploy to cluster
if: ${{ github.event_name == 'workflow_dispatch' }}
environment: ${{ github.event.inputs.flavor }}
needs:
- build-images
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Version
id: version
uses: ./.github/actions/setup-version
- name: Deploy to ${{ github.event.inputs.flavor }}
uses: ./.github/actions/deploy
with:
build-type: ${{ github.event.inputs.flavor }}
gcp-project-number: ${{ secrets.GCP_PROJECT_NUMBER }}
gcp-project-id: ${{ secrets.GCP_PROJECT_ID }}
service-account: ${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}
cluster-name: ${{ secrets.GCP_CLUSTER_NAME }}
cluster-location: ${{ secrets.GCP_CLUSTER_LOCATION }}
env:
APP_VERSION: ${{ steps.version.outputs.APP_VERSION }}
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
CANARY_DEPLOY_HOST: ${{ secrets.CANARY_DEPLOY_HOST }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
GCLOUD_CONNECTION_NAME: ${{ secrets.GCLOUD_CONNECTION_NAME }}
REDIS_SERVER_HOST: ${{ secrets.REDIS_SERVER_HOST }}
REDIS_SERVER_PASSWORD: ${{ secrets.REDIS_SERVER_PASSWORD }}
CLOUD_SQL_IAM_ACCOUNT: ${{ secrets.CLOUD_SQL_IAM_ACCOUNT }}
APP_IAM_ACCOUNT: ${{ secrets.APP_IAM_ACCOUNT }}
STATIC_IP_NAME: ${{ secrets.STATIC_IP_NAME }}
deploy-done:
needs:
- output-prev-version
- build-images
- deploy
if: always()
runs-on: ubuntu-latest
name: Post deploy message
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: actions/checkout@v4
with:
repository: toeverything/blocksuite
path: blocksuite
fetch-depth: 0
fetch-tags: true
- name: Setup Node.js
uses: ./.github/actions/setup-node
with:
extra-flags: 'workspaces focus @affine/changelog'
electron-install: false
- name: Output deployed info
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
id: set_info
run: |
if [ "${{ github.event.inputs.flavor }}" = "canary" ]; then
echo "deployed_url=https://affine.fail" >> $GITHUB_OUTPUT
elif [ "${{ github.event.inputs.flavor }}" = "beta" ]; then
echo "deployed_url=https://insider.affine.pro" >> $GITHUB_OUTPUT
elif [ "${{ github.event.inputs.flavor }}" = "stable" ]; then
echo "deployed_url=https://app.affine.pro" >> $GITHUB_OUTPUT
else
exit 1
fi
env:
GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}}
- name: Post Success event to a Slack channel
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
run: node ./tools/changelog/index.js
env:
CHANNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
DEPLOYED_URL: ${{ steps.set_info.outputs.deployed_url }}
PREV_VERSION: ${{ needs.output-prev-version.outputs.prev }}
NAMESPACE: ${{ needs.output-prev-version.outputs.namespace }}
DEPLOYMENT: 'SERVER'
FLAVOR: ${{ github.event.inputs.flavor }}
BLOCKSUITE_REPO_PATH: ${{ github.workspace }}/blocksuite
- name: Post Failed event to a Slack channel
id: failed-slack
uses: slackapi/slack-github-action@v2.0.0
if: ${{ always() && contains(needs.*.result, 'failure') }}
with:
method: chat.postMessage
token: ${{ secrets.SLACK_BOT_TOKEN }}
payload: |
channel: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
text: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy failed `${{ github.event.inputs.flavor }}`>"
blocks:
- type: section
text:
type: mrkdwn
text: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy failed `${{ github.event.inputs.flavor }}`>"
- name: Post Cancel event to a Slack channel
id: cancel-slack
uses: slackapi/slack-github-action@v2.0.0
if: ${{ always() && contains(needs.*.result, 'cancelled') && !contains(needs.*.result, 'failure') }}
with:
token: ${{ secrets.SLACK_BOT_TOKEN }}
method: chat.postMessage
payload: |
channel: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
text: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy cancelled `${{ github.event.inputs.flavor }}`>"
blocks:
- type: section
text:
type: mrkdwn
text: "<${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}|Backend deploy cancelled `${{ github.event.inputs.flavor }}`>"
+66
View File
@@ -0,0 +1,66 @@
name: Release Charts
on:
push:
branches: [canary]
paths:
- '.github/helm/**/Chart.yml'
jobs:
release:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Checkout Helm chart repo
uses: actions/checkout@v4
with:
repository: toeverything/helm-charts
path: .helm-chart-repo
ref: gh-pages
token: ${{ secrets.HELM_RELEASER_TOKEN }}
- name: Install Helm
uses: azure/setup-helm@v4
- name: Install chart releaser
run: |
set -e
arch="$(dpkg --print-architecture)"
curl -s https://api.github.com/repos/helm/chart-releaser/releases/latest \
| yq --indent 0 --no-colors --input-format json --unwrapScalar \
".assets[] | select(.name | test("\""^chart-releaser_.+_linux_${arch}\.tar\.gz$"\"")) | .browser_download_url" \
| xargs curl -SsL \
| tar zxf - -C /usr/local/bin
- name: Package charts
working-directory: .helm-chart-repo
run: |
mkdir -p .cr-index
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm dependencies build ../.github/helm/affine
helm dependencies build ../.github/helm/affine-cloud
cr package ../.github/helm/affine
cr package ../.github/helm/affine-cloud
- name: Publish charts
working-directory: .helm-chart-repo
run: |
set -ex
git config --local user.name "$GITHUB_ACTOR"
git config --local user.email "$GITHUB_ACTOR@users.noreply.github.com"
owner=$(cut -d '/' -f 1 <<< '${{ github.repository }}')
repo=helm-charts
git_hash=$(git rev-parse HEAD)
cr upload --commit "$git_hash" \
--git-repo "$repo" --owner "$owner" \
--token '${{ secrets.HELM_RELEASER_TOKEN }}' \
--skip-existing
cr index --git-repo "$repo" --owner "$owner" \
--token '${{ secrets.HELM_RELEASER_TOKEN }}' \
--index-path .cr-index --push
+19
View File
@@ -0,0 +1,19 @@
name: Label Checker
on:
pull_request:
types:
- opened
- labeled
- unlabeled
branches:
- canary
jobs:
check_labels:
name: PR should not have a blocked label
runs-on: ubuntu-latest
steps:
- uses: docker://agilepathway/pull-request-label-checker:latest
with:
none_of: blocked
repo_token: ${{ secrets.GITHUB_TOKEN }}
+12
View File
@@ -0,0 +1,12 @@
name: Pull request auto assign
# on: pull_request
on:
pull_request:
types: [opened, ready_for_review]
jobs:
add-reviews:
runs-on: ubuntu-latest
steps:
- uses: kentaro-m/auto-assign-action@v2.0.0
@@ -0,0 +1,38 @@
name: Release Desktop/Mobile Automatically
on:
push:
tags:
- 'v[0-9]+.[0-9]+.[0-9]+-canary.[0-9]+'
schedule:
- cron: '0 9 * * *'
permissions:
contents: write
pull-requests: write
actions: write
jobs:
dispatch-release-desktop:
runs-on: ubuntu-latest
name: Setup Release Desktop
steps:
- name: dispatch desktop release by tag
if: ${{ github.event_name == 'push' }}
uses: benc-uk/workflow-dispatch@v1
with:
workflow: release-desktop.yml
inputs: '{ "build-type": "canary", "is-draft": false, "is-pre-release": true }'
- name: dispatch desktop release by schedule
if: ${{ github.event_name == 'schedule' }}
uses: benc-uk/workflow-dispatch@v1
with:
workflow: release-desktop.yml
inputs: '{ "build-type": "canary", "is-draft": false, "is-pre-release": true }'
ref: canary
- name: dispatch desktop release by tag
uses: benc-uk/workflow-dispatch@v1
with:
workflow: release-mobile.yml
inputs: '{ "build-type": "canary", "build-target": "distribution" }'
-66
View File
@@ -1,66 +0,0 @@
name: Release Cloud
on:
workflow_call:
inputs:
build-type:
required: true
type: string
app-version:
required: true
type: string
git-short-hash:
required: true
type: string
permissions:
contents: 'write'
id-token: 'write'
packages: 'write'
jobs:
build-images:
name: Build Images
uses: ./.github/workflows/build-images.yml
secrets: inherit
with:
build-type: ${{ inputs.build-type }}
app-version: ${{ inputs.app-version }}
git-short-hash: ${{ inputs.git-short-hash }}
deploy:
name: Deploy to cluster
environment: ${{ inputs.build-type }}
needs:
- build-images
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy to ${{ inputs.build-type }}
uses: ./.github/actions/deploy
with:
gcp-project-number: ${{ secrets.GCP_PROJECT_NUMBER }}
gcp-project-id: ${{ secrets.GCP_PROJECT_ID }}
service-account: ${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}
cluster-name: ${{ secrets.GCP_CLUSTER_NAME }}
cluster-location: ${{ secrets.GCP_CLUSTER_LOCATION }}
env:
BUILD_TYPE: ${{ inputs.build-type }}
APP_VERSION: ${{ inputs.app-version }}
GIT_SHORT_HASH: ${{ inputs.git-short-hash }}
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
CANARY_DEPLOY_HOST: ${{ secrets.CANARY_DEPLOY_HOST }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
DATABASE_URL: ${{ secrets.DATABASE_URL }}
DATABASE_USERNAME: ${{ secrets.DATABASE_USERNAME }}
DATABASE_PASSWORD: ${{ secrets.DATABASE_PASSWORD }}
DATABASE_NAME: ${{ secrets.DATABASE_NAME }}
GCLOUD_CONNECTION_NAME: ${{ secrets.GCLOUD_CONNECTION_NAME }}
REDIS_SERVER_HOST: ${{ secrets.REDIS_SERVER_HOST }}
REDIS_SERVER_PASSWORD: ${{ secrets.REDIS_SERVER_PASSWORD }}
CLOUD_SQL_IAM_ACCOUNT: ${{ secrets.CLOUD_SQL_IAM_ACCOUNT }}
APP_IAM_ACCOUNT: ${{ secrets.APP_IAM_ACCOUNT }}
STATIC_IP_NAME: ${{ secrets.STATIC_IP_NAME }}
AFFINE_INDEXER_SEARCH_PROVIDER: ${{ secrets.AFFINE_INDEXER_SEARCH_PROVIDER }}
AFFINE_INDEXER_SEARCH_ENDPOINT: ${{ secrets.AFFINE_INDEXER_SEARCH_ENDPOINT }}
AFFINE_INDEXER_SEARCH_API_KEY: ${{ secrets.AFFINE_INDEXER_SEARCH_API_KEY }}
+77 -52
View File
@@ -1,17 +1,27 @@
name: Release Desktop name: Release Desktop App
on: on:
workflow_call: workflow_dispatch:
inputs: inputs:
build-type: build-type:
description: 'Build Type'
type: choice
required: true required: true
type: string default: canary
app-version: options:
- canary
- beta
- stable
is-draft:
description: 'Draft Release?'
type: boolean
required: true required: true
type: string default: true
git-short-hash: is-pre-release:
description: 'Pre Release? (labeled as "PreRelease")'
type: boolean
required: true required: true
type: string default: true
permissions: permissions:
actions: write actions: write
@@ -21,8 +31,7 @@ permissions:
attestations: write attestations: write
env: env:
BUILD_TYPE: ${{ inputs.build-type }} BUILD_TYPE: ${{ github.event.inputs.build-type }}
RELEASE_VERSION: ${{ inputs.app-version }}
DEBUG: 'affine:*,napi:*' DEBUG: 'affine:*,napi:*'
APP_NAME: affine APP_NAME: affine
MACOSX_DEPLOYMENT_TARGET: '10.13' MACOSX_DEPLOYMENT_TARGET: '10.13'
@@ -30,13 +39,14 @@ env:
jobs: jobs:
before-make: before-make:
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.build-type }}
outputs:
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Setup @sentry/cli - name: Setup @sentry/cli
@@ -48,14 +58,14 @@ jobs:
SENTRY_PROJECT: 'affine' SENTRY_PROJECT: 'affine'
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: ${{ steps.version.outputs.APP_VERSION }}
RELEASE_VERSION: ${{ inputs.app-version }} RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
- name: Upload web artifact - name: Upload web artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: desktop-web name: web
path: packages/frontend/apps/electron/resources/web-static path: packages/frontend/apps/electron/resources/web-static
make-distribution: make-distribution:
@@ -77,7 +87,7 @@ jobs:
target: x86_64-unknown-linux-gnu target: x86_64-unknown-linux-gnu
runs-on: ${{ matrix.spec.runner }} runs-on: ${{ matrix.spec.runner }}
needs: before-make needs: before-make
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.build-type }}
env: env:
APPLE_ID: ${{ secrets.APPLE_ID }} APPLE_ID: ${{ secrets.APPLE_ID }}
APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }}
@@ -87,14 +97,13 @@ jobs:
SENTRY_PROJECT: 'affine' SENTRY_PROJECT: 'affine'
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: ${{ needs.before-make.outputs.RELEASE_VERSION }}
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
timeout-minutes: 10 timeout-minutes: 10
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
@@ -110,7 +119,7 @@ jobs:
package: '@affine/native' package: '@affine/native'
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
with: with:
name: desktop-web name: web
path: packages/frontend/apps/electron/resources/web-static path: packages/frontend/apps/electron/resources/web-static
- name: Build Desktop Layers - name: Build Desktop Layers
@@ -156,31 +165,31 @@ jobs:
if: ${{ matrix.spec.platform == 'darwin' }} if: ${{ matrix.spec.platform == 'darwin' }}
run: | run: |
mkdir -p builds mkdir -p builds
mv packages/frontend/apps/electron/out/*/make/*.dmg ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg mv packages/frontend/apps/electron/out/*/make/*.dmg ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg
mv packages/frontend/apps/electron/out/*/make/zip/darwin/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip mv packages/frontend/apps/electron/out/*/make/zip/darwin/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip
- name: Save artifacts (linux) - name: Save artifacts (linux)
if: ${{ matrix.spec.platform == 'linux' }} if: ${{ matrix.spec.platform == 'linux' }}
run: | run: |
mkdir -p builds mkdir -p builds
mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip mv packages/frontend/apps/electron/out/*/make/zip/linux/${{ matrix.spec.arch }}/*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.zip
mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage mv packages/frontend/apps/electron/out/*/make/*.AppImage ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.appimage
mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb mv packages/frontend/apps/electron/out/*/make/deb/${{ matrix.spec.arch }}/*.deb ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.deb
mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak mv packages/frontend/apps/electron/out/*/make/flatpak/*/*.flatpak ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-${{ matrix.spec.arch }}.flatpak
- uses: actions/attest-build-provenance@v2 - uses: actions/attest-build-provenance@v2
if: ${{ matrix.spec.platform == 'darwin' }} if: ${{ matrix.spec.platform == 'darwin' }}
with: with:
subject-path: | subject-path: |
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.zip
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-macos-${{ matrix.spec.arch }}.dmg
- uses: actions/attest-build-provenance@v2 - uses: actions/attest-build-provenance@v2
if: ${{ matrix.spec.platform == 'linux' }} if: ${{ matrix.spec.platform == 'linux' }}
with: with:
subject-path: | subject-path: |
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.zip
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.appimage
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.deb ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-linux-x64.deb
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -188,7 +197,7 @@ jobs:
path: builds path: builds
package-distribution-windows: package-distribution-windows:
environment: ${{ inputs.build-type }} environment: ${{ github.event.inputs.build-type }}
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
@@ -212,14 +221,13 @@ jobs:
SENTRY_PROJECT: 'affine' SENTRY_PROJECT: 'affine'
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: ${{ needs.before-make.outputs.RELEASE_VERSION }}
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }} MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
timeout-minutes: 10 timeout-minutes: 10
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
@@ -234,7 +242,7 @@ jobs:
package: '@affine/native' package: '@affine/native'
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
with: with:
name: desktop-web name: web
path: packages/frontend/apps/electron/resources/web-static path: packages/frontend/apps/electron/resources/web-static
- name: Build Desktop Layers - name: Build Desktop Layers
@@ -244,7 +252,7 @@ jobs:
shell: bash shell: bash
# node_modules of nbstore is not needed for building, and it will make the build process out of memory # node_modules of nbstore is not needed for building, and it will make the build process out of memory
run: | run: |
rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite/affine/node_modules rm -rf packages/frontend/apps/electron/node_modules/@affine/nbstore/node_modules/@blocksuite
rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules rm -rf packages/frontend/apps/electron/node_modules/@affine/native/node_modules
- name: package - name: package
@@ -306,9 +314,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
timeout-minutes: 10 timeout-minutes: 10
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
@@ -392,16 +399,16 @@ jobs:
- name: Save artifacts - name: Save artifacts
run: | run: |
mkdir -p builds mkdir -p builds
mv packages/frontend/apps/electron/out/*/make/zip/win32/${{ matrix.spec.arch }}/AFFiNE*-win32-${{ matrix.spec.arch }}-*.zip ./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip mv packages/frontend/apps/electron/out/*/make/zip/win32/${{ matrix.spec.arch }}/AFFiNE*-win32-${{ matrix.spec.arch }}-*.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
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-${{ needs.before-make.outputs.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-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
- uses: actions/attest-build-provenance@v2 - uses: actions/attest-build-provenance@v2
with: with:
subject-path: | subject-path: |
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.zip
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.exe
./builds/affine-${{ env.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe ./builds/affine-${{ needs.before-make.outputs.RELEASE_VERSION }}-${{ env.BUILD_TYPE }}-windows-${{ matrix.spec.arch }}.nsis.exe
- name: Upload Artifact - name: Upload Artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
@@ -417,7 +424,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/download-artifact@v4 - uses: actions/download-artifact@v4
with: with:
name: desktop-web name: web
path: web-static path: web-static
- name: Zip web-static - name: Zip web-static
run: zip -r web-static.zip web-static run: zip -r web-static.zip web-static
@@ -458,14 +465,32 @@ jobs:
run: | run: |
node ./scripts/generate-release-yml.mjs node ./scripts/generate-release-yml.mjs
env: env:
RELEASE_VERSION: ${{ env.RELEASE_VERSION }} RELEASE_VERSION: ${{ needs.before-make.outputs.RELEASE_VERSION }}
- name: Create GitHub Release - name: Create Release Draft
if: ${{ github.ref_type == 'tag' }}
uses: softprops/action-gh-release@v2 uses: softprops/action-gh-release@v2
with: with:
name: ${{ env.RELEASE_VERSION }} name: ${{ needs.before-make.outputs.RELEASE_VERSION }}
draft: ${{ inputs.build-type == 'stable' }} body: ''
prerelease: ${{ inputs.build-type != 'stable' }} draft: ${{ github.event.inputs.is-draft }}
tag_name: v${{ env.RELEASE_VERSION}} prerelease: ${{ github.event.inputs.is-pre-release }}
files: |
./release/*
./release/.env.example
- name: Create Nightly Release Draft
if: ${{ github.ref_type == 'branch' }}
uses: softprops/action-gh-release@v2
env:
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
with:
# Temporarily, treat release from branch as nightly release, artifact saved to AFFiNE-Releases.
# Need to improve internal build and nightly release logic.
repository: 'toeverything/AFFiNE-Releases'
name: ${{ needs.before-make.outputs.RELEASE_VERSION }}
tag_name: ${{ needs.before-make.outputs.RELEASE_VERSION }}
body: ''
draft: false
prerelease: true
files: | files: |
./release/* ./release/*
./release/.env.example ./release/.env.example
+88 -36
View File
@@ -1,36 +1,68 @@
name: Release Mobile name: Release Mobile App
on: on:
workflow_call: workflow_call:
inputs: inputs:
app-version: build-target:
type: string description: 'Build Target'
required: true
git-short-hash:
type: string type: string
required: true required: true
build-type: build-type:
description: 'Build Type'
type: string type: string
required: true required: true
ios-app-version: workflow_dispatch:
type: string inputs:
required: false build-target:
description: 'Build Target'
type: choice
required: true
default: distribution
options:
- development
- distribution
build-type:
description: 'Build Type'
type: choice
required: true
default: canary
options:
- canary
- beta
- stable
env: env:
BUILD_TYPE: ${{ inputs.build-type }} BUILD_TYPE: ${{ inputs.build-type || github.event.inputs.build-type }}
BUILD_TARGET: ${{ inputs.build-target || github.event.inputs.build-target }}
DEBUG: napi:* DEBUG: napi:*
KEYCHAIN_NAME: ${{ github.workspace }}/signing_temp KEYCHAIN_NAME: ${{ github.workspace }}/signing_temp
jobs: jobs:
build-ios-web: output-env:
runs-on: ubuntu-latest runs-on: ubuntu-latest
environment: ${{ inputs.build-type }} outputs:
ENVIRONMENT: ${{ steps.env.outputs.ENVIRONMENT }}
steps:
- name: Output Environment
id: env
run: |
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
echo "ENVIRONMENT=${{ github.event.inputs.build-type }}" >> $GITHUB_OUTPUT
else
echo "ENVIRONMENT=" >> $GITHUB_OUTPUT
fi
build-ios-web:
needs:
- output-env
runs-on: ubuntu-24.04-arm
environment: ${{ needs.output-env.outputs.ENVIRONMENT }}
outputs:
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Setup @sentry/cli - name: Setup @sentry/cli
@@ -44,8 +76,8 @@ jobs:
SENTRY_PROJECT: 'affine' SENTRY_PROJECT: 'affine'
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: ${{ steps.version.outputs.APP_VERSION }}
RELEASE_VERSION: ${{ inputs.app-version }} RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
- name: Upload ios artifact - name: Upload ios artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
@@ -53,13 +85,17 @@ jobs:
path: packages/frontend/apps/ios/dist path: packages/frontend/apps/ios/dist
build-android-web: build-android-web:
runs-on: ubuntu-latest runs-on: ubuntu-24.04-arm
needs:
- output-env
environment: ${{ needs.output-env.outputs.ENVIRONMENT }}
outputs:
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Setup Node.js - name: Setup Node.js
uses: ./.github/actions/setup-node uses: ./.github/actions/setup-node
- name: Setup @sentry/cli - name: Setup @sentry/cli
@@ -73,27 +109,41 @@ jobs:
SENTRY_PROJECT: 'affine' SENTRY_PROJECT: 'affine'
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: ${{ steps.version.outputs.APP_VERSION }}
RELEASE_VERSION: ${{ steps.version.outputs.APP_VERSION }}
- name: Upload android artifact - name: Upload android artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: android name: android
path: packages/frontend/apps/android/dist path: packages/frontend/apps/android/dist
ios: determine-ios-runner:
runs-on: 'macos-15' runs-on: ubuntu-latest
needs: needs:
- build-ios-web - build-ios-web
outputs:
RUNNER: ${{ steps.runner.outputs.RUNNER }}
steps:
- name: Determine Runner
id: runner
# Randomly pick runner with 80% chance for blaze/macos-14 and 20% chance for namespace-profile-macos
# blaze/macos-14 is free but has limited concurrency
run: |
RANDOM_NUMBER=$(( $RANDOM % 100 + 1 ))
if [ $RANDOM_NUMBER -le 20 ]; then
echo "Selected namespace-profile-macos (20% probability)"
echo "RUNNER=namespace-profile-macos" >> $GITHUB_OUTPUT
else
echo "Selected blaze/macos-14 (80% probability)"
echo "RUNNER=blaze/macos-14" >> $GITHUB_OUTPUT
fi
ios:
runs-on: ${{ github.ref_name == 'canary' && 'macos-latest' || needs.determine-ios-runner.outputs.RUNNER }}
needs:
- determine-ios-runner
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version
uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
ios-app-version: ${{ inputs.ios-app-version }}
- name: 'Update Code Sign Identity'
shell: bash
run: ./packages/frontend/apps/ios/update_code_sign_identity.sh
- name: Download mobile artifact - name: Download mobile artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
@@ -110,7 +160,7 @@ 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: 16.2
- name: Install Swiftformat - name: Install Swiftformat
run: brew install swiftformat run: brew install swiftformat
- name: Cap sync - name: Cap sync
@@ -128,6 +178,7 @@ jobs:
package: 'affine_mobile_native' package: 'affine_mobile_native'
no-build: 'true' no-build: 'true'
- name: Testflight - name: Testflight
if: ${{ env.BUILD_TYPE != 'stable' }}
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 echo -n "${{ env.BUILD_PROVISION_PROFILE }}" | base64 --decode -o $PP_PATH
@@ -135,7 +186,6 @@ jobs:
cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles cp $PP_PATH ~/Library/MobileDevice/Provisioning\ Profiles
fastlane beta fastlane beta
env: env:
BUILD_TARGET: distribution
BUILD_PROVISION_PROFILE: ${{ secrets.BUILD_PROVISION_PROFILE }} BUILD_PROVISION_PROFILE: ${{ secrets.BUILD_PROVISION_PROFILE }}
PP_PATH: ${{ runner.temp }}/build_pp.mobileprovision PP_PATH: ${{ runner.temp }}/build_pp.mobileprovision
APPLE_STORE_CONNECT_API_KEY_ID: ${{ secrets.APPLE_STORE_CONNECT_API_KEY_ID }} APPLE_STORE_CONNECT_API_KEY_ID: ${{ secrets.APPLE_STORE_CONNECT_API_KEY_ID }}
@@ -151,9 +201,8 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- name: Setup Version - name: Setup Version
id: version
uses: ./.github/actions/setup-version uses: ./.github/actions/setup-version
with:
app-version: ${{ inputs.app-version }}
- name: Download mobile artifact - name: Download mobile artifact
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
@@ -186,6 +235,7 @@ jobs:
- name: Auth gcloud - name: Auth gcloud
id: auth id: auth
uses: google-github-actions/auth@v2 uses: google-github-actions/auth@v2
if: ${{ env.BUILD_TARGET == 'distribution' }}
with: with:
workload_identity_provider: 'projects/${{ secrets.GCP_PROJECT_NUMBER }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy' workload_identity_provider: 'projects/${{ secrets.GCP_PROJECT_NUMBER }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy'
service_account: '${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}' service_account: '${{ secrets.GCP_HELM_DEPLOY_SERVICE_ACCOUNT }}'
@@ -199,6 +249,7 @@ jobs:
cache: 'gradle' cache: 'gradle'
- name: Auto increment version code - name: Auto increment version code
id: bump id: bump
if: ${{ env.BUILD_TARGET == 'distribution' }}
run: yarn affine @affine/playstore-auto-bump bump run: yarn affine @affine/playstore-auto-bump bump
env: env:
GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.auth.outputs.credentials_file_path }} GOOGLE_APPLICATION_CREDENTIALS: ${{ steps.auth.outputs.credentials_file_path }}
@@ -210,13 +261,14 @@ jobs:
AFFINE_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_PASSWORD }} AFFINE_ANDROID_KEYSTORE_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_PASSWORD }}
AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD }} AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD: ${{ secrets.AFFINE_ANDROID_KEYSTORE_ALIAS_PASSWORD }}
AFFINE_ANDROID_SIGN_KEYSTORE: ${{ secrets.AFFINE_ANDROID_SIGN_KEYSTORE }} AFFINE_ANDROID_SIGN_KEYSTORE: ${{ secrets.AFFINE_ANDROID_SIGN_KEYSTORE }}
VERSION_NAME: ${{ inputs.app-version }} VERSION_NAME: ${{ steps.version.outputs.APP_VERSION }}
- name: Upload to Google Play - name: Upload to Google Play
uses: r0adkll/upload-google-play@v1 uses: r0adkll/upload-google-play@v1
if: ${{ env.BUILD_TARGET == 'distribution' }}
with: with:
serviceAccountJson: ${{ steps.auth.outputs.credentials_file_path }} serviceAccountJson: ${{ steps.auth.outputs.credentials_file_path }}
packageName: app.affine.pro packageName: app.affine.pro
releaseName: ${{ inputs.app-version }} releaseName: ${{ steps.version.outputs.APP_VERSION }}
releaseFiles: packages/frontend/apps/android/App/app/build/outputs/bundle/${{ env.BUILD_TYPE }}Release/app-${{ env.BUILD_TYPE }}-release-signed.aab releaseFiles: packages/frontend/apps/android/App/app/build/outputs/bundle/${{ env.BUILD_TYPE }}Release/app-${{ env.BUILD_TYPE }}-release-signed.aab
track: internal track: internal
status: draft status: draft
-126
View File
@@ -1,126 +0,0 @@
name: Release
on:
schedule:
- cron: '0 9 * * *'
workflow_dispatch:
inputs:
web:
description: 'Release Web?'
required: true
type: boolean
default: false
desktop:
description: 'Release Desktop?'
required: true
type: boolean
default: false
mobile:
description: 'Release Mobile?'
required: true
type: boolean
default: false
ios-app-version:
description: 'iOS App Store Version (Optional, use tag version if empty)'
required: false
type: string
permissions:
contents: write
pull-requests: write
actions: write
id-token: write
packages: write
security-events: write
attestations: write
issues: write
jobs:
prepare:
name: Prepare
runs-on: ubuntu-latest
outputs:
APP_VERSION: ${{ steps.prepare.outputs.APP_VERSION }}
GIT_SHORT_HASH: ${{ steps.prepare.outputs.GIT_SHORT_HASH }}
BUILD_TYPE: ${{ steps.prepare.outputs.BUILD_TYPE }}
steps:
- uses: actions/checkout@v4
- name: Prepare Release
id: prepare
uses: ./.github/actions/prepare-release
cloud:
name: Release Cloud
if: ${{ inputs.web || github.event_name != 'workflow_dispatch' }}
needs:
- prepare
uses: ./.github/workflows/release-cloud.yml
secrets: inherit
with:
build-type: ${{ needs.prepare.outputs.BUILD_TYPE }}
app-version: ${{ needs.prepare.outputs.APP_VERSION }}
git-short-hash: ${{ needs.prepare.outputs.GIT_SHORT_HASH }}
image:
name: Release Docker Image
runs-on: ubuntu-latest
needs:
- prepare
- cloud
steps:
- uses: trstringer/manual-approval@v1
if: ${{ needs.prepare.outputs.BUILD_TYPE == 'stable' }}
name: Wait for approval
with:
secret: ${{ secrets.GITHUB_TOKEN }}
approvers: forehalo,fengmk2,darkskygit
minimum-approvals: 1
fail-on-denial: true
issue-title: Please confirm to release docker image
issue-body: |
Env: ${{ needs.prepare.outputs.BUILD_TYPE }}
Candidate: ghcr.io/toeverything/affine:${{ needs.prepare.outputs.BUILD_TYPE }}-${{ needs.prepare.outputs.GIT_SHORT_HASH }}
Tag: ghcr.io/toeverything/affine:${{ needs.prepare.outputs.BUILD_TYPE }}
> comment with "approve", "approved", "lgtm", "yes" to approve
> comment with "deny", "denied", "no" to deny
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ghcr.io
logout: false
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Tag Image
run: |
docker buildx imagetools create --tag ghcr.io/toeverything/affine:${{needs.prepare.outputs.BUILD_TYPE}} ghcr.io/toeverything/affine:${{needs.prepare.outputs.BUILD_TYPE}}-${{needs.prepare.outputs.GIT_SHORT_HASH}}
docker buildx imagetools create --tag ghcr.io/toeverything/affine:${{needs.prepare.outputs.APP_VERSION}} ghcr.io/toeverything/affine:${{needs.prepare.outputs.BUILD_TYPE}}-${{needs.prepare.outputs.GIT_SHORT_HASH}}
desktop:
name: Release Desktop
if: ${{ inputs.desktop || github.event_name != 'workflow_dispatch' }}
needs:
- prepare
uses: ./.github/workflows/release-desktop.yml
secrets: inherit
with:
build-type: ${{ needs.prepare.outputs.BUILD_TYPE }}
app-version: ${{ needs.prepare.outputs.APP_VERSION }}
git-short-hash: ${{ needs.prepare.outputs.GIT_SHORT_HASH }}
mobile:
name: Release Mobile
if: ${{ inputs.mobile }}
needs:
- prepare
uses: ./.github/workflows/release-mobile.yml
secrets: inherit
with:
build-type: ${{ needs.prepare.outputs.BUILD_TYPE }}
app-version: ${{ needs.prepare.outputs.APP_VERSION }}
git-short-hash: ${{ needs.prepare.outputs.GIT_SHORT_HASH }}
ios-app-version: ${{ inputs.ios-app-version }}
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
shell: cmd shell: cmd
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.sectigo.com /td sha256 /fd sha256 /a ${{ inputs.files }}
- name: zip file - name: zip file
shell: cmd shell: cmd
run: | run: |
+1 -1
View File
@@ -1 +1 @@
22.16.0 22.15.0
-3
View File
@@ -2,7 +2,6 @@
**/node_modules **/node_modules
.yarn .yarn
.github/helm .github/helm
.git
.vscode .vscode
.yarnrc.yml .yarnrc.yml
.docker .docker
@@ -39,5 +38,3 @@ packages/frontend/apps/ios/App/**
tests/blocksuite/snapshots tests/blocksuite/snapshots
blocksuite/docs/api/** blocksuite/docs/api/**
packages/frontend/admin/src/config.json packages/frontend/admin/src/config.json
**/test-docs.json
**/test-blocks.json
Generated
+502 -833
View File
File diff suppressed because it is too large Load Diff
+8 -23
View File
@@ -28,14 +28,12 @@ base64-simd = "0.8"
bitvec = "1.0" bitvec = "1.0"
block2 = "0.6" block2 = "0.6"
byteorder = "1.5" byteorder = "1.5"
cpal = "0.15"
chrono = "0.4" chrono = "0.4"
clap = { version = "4.4", features = ["derive"] } clap = { version = "4.4", features = ["derive"] }
core-foundation = "0.10" core-foundation = "0.10"
coreaudio-rs = "0.12" coreaudio-rs = "0.12"
criterion = { version = "0.5", features = ["html_reports"] } criterion = { version = "0.5", features = ["html_reports"] }
criterion2 = { version = "3", default-features = false } criterion2 = { version = "3", default-features = false }
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" }
dotenvy = "0.15" dotenvy = "0.15"
@@ -49,9 +47,9 @@ log = "0.4"
loom = { version = "0.7", features = ["checkpoint"] } loom = { version = "0.7", features = ["checkpoint"] }
mimalloc = "0.1" mimalloc = "0.1"
nanoid = "0.4" nanoid = "0.4"
napi = { version = "3.0.0-beta.3", features = ["async", "chrono_date", "error_anyhow", "napi9", "serde"] } napi = { version = "3.0.0-alpha.31", features = ["async", "chrono_date", "error_anyhow", "napi9", "serde"] }
napi-build = { version = "2" } napi-build = { version = "2" }
napi-derive = { version = "3.0.0-beta.3" } napi-derive = { version = "3.0.0-alpha.28" }
nom = "8" nom = "8"
notify = { version = "8", features = ["serde"] } notify = { version = "8", features = ["serde"] }
objc2 = "0.6" objc2 = "0.6"
@@ -59,7 +57,7 @@ objc2-foundation = "0.3"
once_cell = "1" once_cell = "1"
ordered-float = "5" ordered-float = "5"
parking_lot = "0.12" parking_lot = "0.12"
path-ext = "0.1.2" path-ext = "0.1.1"
pdf-extract = { git = "https://github.com/toeverything/pdf-extract", branch = "darksky/improve-font-decoding" } pdf-extract = { git = "https://github.com/toeverything/pdf-extract", branch = "darksky/improve-font-decoding" }
phf = { version = "0.11", features = ["macros"] } phf = { version = "0.11", features = ["macros"] }
proptest = "1.3" proptest = "1.3"
@@ -79,12 +77,12 @@ smol_str = "0.3"
sqlx = { version = "0.8", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "tls-rustls"] } sqlx = { version = "0.8", default-features = false, features = ["chrono", "macros", "migrate", "runtime-tokio", "sqlite", "tls-rustls"] }
strum_macros = "0.27.0" strum_macros = "0.27.0"
symphonia = { version = "0.5", features = ["all", "opt-simd"] } symphonia = { version = "0.5", features = ["all", "opt-simd"] }
text-splitter = "0.27" text-splitter = "0.25"
thiserror = "2" thiserror = "2"
tiktoken-rs = "0.7" tiktoken-rs = "0.6"
tokio = "1.45" tokio = "1.37"
tree-sitter = { version = "0.25" } tree-sitter = { version = "0.25" }
tree-sitter-c = { version = "0.24" } tree-sitter-c = { version = "0.23" }
tree-sitter-c-sharp = { version = "0.23" } tree-sitter-c-sharp = { version = "0.23" }
tree-sitter-cpp = { version = "0.23" } tree-sitter-cpp = { version = "0.23" }
tree-sitter-go = { version = "0.23" } tree-sitter-go = { version = "0.23" }
@@ -93,25 +91,12 @@ tree-sitter-javascript = { version = "0.23" }
tree-sitter-kotlin-ng = { version = "1.1" } tree-sitter-kotlin-ng = { version = "1.1" }
tree-sitter-python = { version = "0.23" } tree-sitter-python = { version = "0.23" }
tree-sitter-rust = { version = "0.24" } tree-sitter-rust = { version = "0.24" }
tree-sitter-scala = { version = "0.24" } tree-sitter-scala = { version = "0.23" }
tree-sitter-typescript = { version = "0.23" } tree-sitter-typescript = { version = "0.23" }
uniffi = "0.29" uniffi = "0.29"
url = { version = "2.5" } url = { version = "2.5" }
uuid = "1.8" uuid = "1.8"
v_htmlescape = "0.15" v_htmlescape = "0.15"
windows = { version = "0.61", features = [
"Win32_Devices_FunctionDiscovery",
"Win32_UI_Shell_PropertiesSystem",
"Win32_Media_Audio",
"Win32_System_Variant",
"Win32_System_Com_StructuredStorage",
"Win32_System_Threading",
"Win32_System_ProcessStatus",
"Win32_Foundation",
"Win32_System_Com",
"Win32_System_Diagnostics_ToolHelp",
] }
windows-core = { version = "0.61" }
y-octo = { path = "./packages/common/y-octo/core" } y-octo = { path = "./packages/common/y-octo/core" }
y-sync = { version = "0.4" } y-sync = { version = "0.4" }
yrs = "0.23.0" yrs = "0.23.0"
+3 -5
View File
@@ -43,7 +43,7 @@ _Special thanks to [Blaze](https://runblaze.dev) for their support of this proje
<a href="https://affine.pro/redirect/discord">Discord</a> | <a href="https://affine.pro/redirect/discord">Discord</a> |
<a href="https://app.affine.pro">Live Demo</a> | <a href="https://app.affine.pro">Live Demo</a> |
<a href="https://affine.pro/blog/">Blog</a> | <a href="https://affine.pro/blog/">Blog</a> |
<a href="https://docs.affine.pro/">Documentation</a> <a href="https://docs.affine.pro/docs/">Documentation</a>
</div> </div>
<br/> <br/>
@@ -89,7 +89,7 @@ Star us, and you will receive all release notifications from GitHub without any
**Self-host & Shape your own AFFiNE** **Self-host & Shape your own AFFiNE**
- You have the freedom to manage, self-host, fork and build your own AFFiNE. Plugin community and third-party blocks are coming soon. More tractions on [Blocksuite](https://blocksuite.io). Check there to learn how to [self-host AFFiNE](https://docs.affine.pro/self-host-affine). - You have the freedom to manage, self-host, fork and build your own AFFiNE. Plugin community and third-party blocks are coming soon. More tractions on [Blocksuite](https://blocksuite.io). Check there to learn how to [self-host AFFiNE](https://docs.affine.pro/docs/self-host-affine).
## Acknowledgement ## Acknowledgement
@@ -191,9 +191,7 @@ We would like to express our gratitude to all the individuals who have already c
## Self-Host ## Self-Host
Begin with Docker to deploy your own feature-rich, unrestricted version of AFFiNE. Our team is diligently updating to the latest version. For more information on how to self-host AFFiNE, please refer to our [documentation](https://docs.affine.pro/self-host-affine). Begin with Docker to deploy your own feature-rich, unrestricted version of AFFiNE. Our team is diligently updating to the latest version. For more information on how to self-host AFFiNE, please refer to our [documentation](https://docs.affine.pro/docs/self-host-affine).
[![Run on ClawCloud](https://raw.githubusercontent.com/ClawCloud/Run-Template/refs/heads/main/Run-on-ClawCloud.svg)](https://template.run.claw.cloud/?openapp=system-fastdeploy%3FtemplateName%3Daffine)
## Hiring ## Hiring
+7 -32
View File
@@ -19,7 +19,6 @@
"@blocksuite/affine-block-divider": "workspace:*", "@blocksuite/affine-block-divider": "workspace:*",
"@blocksuite/affine-block-edgeless-text": "workspace:*", "@blocksuite/affine-block-edgeless-text": "workspace:*",
"@blocksuite/affine-block-embed": "workspace:*", "@blocksuite/affine-block-embed": "workspace:*",
"@blocksuite/affine-block-embed-doc": "workspace:*",
"@blocksuite/affine-block-frame": "workspace:*", "@blocksuite/affine-block-frame": "workspace:*",
"@blocksuite/affine-block-image": "workspace:*", "@blocksuite/affine-block-image": "workspace:*",
"@blocksuite/affine-block-latex": "workspace:*", "@blocksuite/affine-block-latex": "workspace:*",
@@ -33,7 +32,6 @@
"@blocksuite/affine-components": "workspace:*", "@blocksuite/affine-components": "workspace:*",
"@blocksuite/affine-ext-loader": "workspace:*", "@blocksuite/affine-ext-loader": "workspace:*",
"@blocksuite/affine-foundation": "workspace:*", "@blocksuite/affine-foundation": "workspace:*",
"@blocksuite/affine-fragment-adapter-panel": "workspace:*",
"@blocksuite/affine-fragment-doc-title": "workspace:*", "@blocksuite/affine-fragment-doc-title": "workspace:*",
"@blocksuite/affine-fragment-frame-panel": "workspace:*", "@blocksuite/affine-fragment-frame-panel": "workspace:*",
"@blocksuite/affine-fragment-outline": "workspace:*", "@blocksuite/affine-fragment-outline": "workspace:*",
@@ -48,7 +46,6 @@
"@blocksuite/affine-gfx-template": "workspace:*", "@blocksuite/affine-gfx-template": "workspace:*",
"@blocksuite/affine-gfx-text": "workspace:*", "@blocksuite/affine-gfx-text": "workspace:*",
"@blocksuite/affine-gfx-turbo-renderer": "workspace:*", "@blocksuite/affine-gfx-turbo-renderer": "workspace:*",
"@blocksuite/affine-inline-comment": "workspace:*",
"@blocksuite/affine-inline-footnote": "workspace:*", "@blocksuite/affine-inline-footnote": "workspace:*",
"@blocksuite/affine-inline-latex": "workspace:*", "@blocksuite/affine-inline-latex": "workspace:*",
"@blocksuite/affine-inline-link": "workspace:*", "@blocksuite/affine-inline-link": "workspace:*",
@@ -60,14 +57,11 @@
"@blocksuite/affine-shared": "workspace:*", "@blocksuite/affine-shared": "workspace:*",
"@blocksuite/affine-widget-drag-handle": "workspace:*", "@blocksuite/affine-widget-drag-handle": "workspace:*",
"@blocksuite/affine-widget-edgeless-auto-connect": "workspace:*", "@blocksuite/affine-widget-edgeless-auto-connect": "workspace:*",
"@blocksuite/affine-widget-edgeless-dragging-area": "workspace:*",
"@blocksuite/affine-widget-edgeless-selected-rect": "workspace:*",
"@blocksuite/affine-widget-edgeless-toolbar": "workspace:*", "@blocksuite/affine-widget-edgeless-toolbar": "workspace:*",
"@blocksuite/affine-widget-edgeless-zoom-toolbar": "workspace:*", "@blocksuite/affine-widget-edgeless-zoom-toolbar": "workspace:*",
"@blocksuite/affine-widget-frame-title": "workspace:*", "@blocksuite/affine-widget-frame-title": "workspace:*",
"@blocksuite/affine-widget-keyboard-toolbar": "workspace:*", "@blocksuite/affine-widget-keyboard-toolbar": "workspace:*",
"@blocksuite/affine-widget-linked-doc": "workspace:*", "@blocksuite/affine-widget-linked-doc": "workspace:*",
"@blocksuite/affine-widget-note-slicer": "workspace:*",
"@blocksuite/affine-widget-page-dragging-area": "workspace:*", "@blocksuite/affine-widget-page-dragging-area": "workspace:*",
"@blocksuite/affine-widget-remote-selection": "workspace:*", "@blocksuite/affine-widget-remote-selection": "workspace:*",
"@blocksuite/affine-widget-scroll-anchoring": "workspace:*", "@blocksuite/affine-widget-scroll-anchoring": "workspace:*",
@@ -127,9 +121,6 @@
"./blocks/embed": "./src/blocks/embed/index.ts", "./blocks/embed": "./src/blocks/embed/index.ts",
"./blocks/embed/store": "./src/blocks/embed/store.ts", "./blocks/embed/store": "./src/blocks/embed/store.ts",
"./blocks/embed/view": "./src/blocks/embed/view.ts", "./blocks/embed/view": "./src/blocks/embed/view.ts",
"./blocks/embed-doc": "./src/blocks/embed-doc/index.ts",
"./blocks/embed-doc/store": "./src/blocks/embed-doc/store.ts",
"./blocks/embed-doc/view": "./src/blocks/embed-doc/view.ts",
"./blocks/frame": "./src/blocks/frame/index.ts", "./blocks/frame": "./src/blocks/frame/index.ts",
"./blocks/frame/store": "./src/blocks/frame/store.ts", "./blocks/frame/store": "./src/blocks/frame/store.ts",
"./blocks/frame/view": "./src/blocks/frame/view.ts", "./blocks/frame/view": "./src/blocks/frame/view.ts",
@@ -148,9 +139,7 @@
"./blocks/paragraph": "./src/blocks/paragraph/index.ts", "./blocks/paragraph": "./src/blocks/paragraph/index.ts",
"./blocks/paragraph/store": "./src/blocks/paragraph/store.ts", "./blocks/paragraph/store": "./src/blocks/paragraph/store.ts",
"./blocks/paragraph/view": "./src/blocks/paragraph/view.ts", "./blocks/paragraph/view": "./src/blocks/paragraph/view.ts",
"./blocks/root": "./src/blocks/root/index.ts", "./blocks/root": "./src/blocks/root.ts",
"./blocks/root/store": "./src/blocks/root/store.ts",
"./blocks/root/view": "./src/blocks/root/view.ts",
"./blocks/surface": "./src/blocks/surface/index.ts", "./blocks/surface": "./src/blocks/surface/index.ts",
"./blocks/surface/store": "./src/blocks/surface/store.ts", "./blocks/surface/store": "./src/blocks/surface/store.ts",
"./blocks/surface/view": "./src/blocks/surface/view.ts", "./blocks/surface/view": "./src/blocks/surface/view.ts",
@@ -174,7 +163,6 @@
"./inlines/footnote": "./src/inlines/footnote/index.ts", "./inlines/footnote": "./src/inlines/footnote/index.ts",
"./inlines/footnote/view": "./src/inlines/footnote/view.ts", "./inlines/footnote/view": "./src/inlines/footnote/view.ts",
"./inlines/footnote/store": "./src/inlines/footnote/store.ts", "./inlines/footnote/store": "./src/inlines/footnote/store.ts",
"./inlines/comment": "./src/inlines/comment/index.ts",
"./inlines/latex": "./src/inlines/latex/index.ts", "./inlines/latex": "./src/inlines/latex/index.ts",
"./inlines/latex/store": "./src/inlines/latex/store.ts", "./inlines/latex/store": "./src/inlines/latex/store.ts",
"./inlines/latex/view": "./src/inlines/latex/view.ts", "./inlines/latex/view": "./src/inlines/latex/view.ts",
@@ -184,8 +172,6 @@
"./widgets/drag-handle/view": "./src/widgets/drag-handle/view.ts", "./widgets/drag-handle/view": "./src/widgets/drag-handle/view.ts",
"./widgets/edgeless-auto-connect": "./src/widgets/edgeless-auto-connect/index.ts", "./widgets/edgeless-auto-connect": "./src/widgets/edgeless-auto-connect/index.ts",
"./widgets/edgeless-auto-connect/view": "./src/widgets/edgeless-auto-connect/view.ts", "./widgets/edgeless-auto-connect/view": "./src/widgets/edgeless-auto-connect/view.ts",
"./widgets/edgeless-dragging-area": "./src/widgets/edgeless-dragging-area/index.ts",
"./widgets/edgeless-dragging-area/view": "./src/widgets/edgeless-dragging-area/view.ts",
"./widgets/edgeless-toolbar": "./src/widgets/edgeless-toolbar/index.ts", "./widgets/edgeless-toolbar": "./src/widgets/edgeless-toolbar/index.ts",
"./widgets/edgeless-toolbar/view": "./src/widgets/edgeless-toolbar/view.ts", "./widgets/edgeless-toolbar/view": "./src/widgets/edgeless-toolbar/view.ts",
"./widgets/frame-title": "./src/widgets/frame-title/index.ts", "./widgets/frame-title": "./src/widgets/frame-title/index.ts",
@@ -206,14 +192,9 @@
"./widgets/viewport-overlay/view": "./src/widgets/viewport-overlay/view.ts", "./widgets/viewport-overlay/view": "./src/widgets/viewport-overlay/view.ts",
"./widgets/page-dragging-area": "./src/widgets/page-dragging-area/index.ts", "./widgets/page-dragging-area": "./src/widgets/page-dragging-area/index.ts",
"./widgets/page-dragging-area/view": "./src/widgets/page-dragging-area/view.ts", "./widgets/page-dragging-area/view": "./src/widgets/page-dragging-area/view.ts",
"./fragments/doc-title": "./src/fragments/doc-title/index.ts", "./fragments/doc-title": "./src/fragments/doc-title.ts",
"./fragments/doc-title/view": "./src/fragments/doc-title/view.ts", "./fragments/frame-panel": "./src/fragments/frame-panel.ts",
"./fragments/frame-panel": "./src/fragments/frame-panel/index.ts", "./fragments/outline": "./src/fragments/outline.ts",
"./fragments/frame-panel/view": "./src/fragments/frame-panel/view.ts",
"./fragments/outline": "./src/fragments/outline/index.ts",
"./fragments/outline/view": "./src/fragments/outline/view.ts",
"./fragments/adapter-panel": "./src/fragments/adapter-panel/index.ts",
"./fragments/adapter-panel/view": "./src/fragments/adapter-panel/view.ts",
"./gfx/text": "./src/gfx/text/index.ts", "./gfx/text": "./src/gfx/text/index.ts",
"./gfx/text/store": "./src/gfx/text/store.ts", "./gfx/text/store": "./src/gfx/text/store.ts",
"./gfx/text/view": "./src/gfx/text/view.ts", "./gfx/text/view": "./src/gfx/text/view.ts",
@@ -266,10 +247,8 @@
"./components/toggle-button": "./src/components/toggle-button.ts", "./components/toggle-button": "./src/components/toggle-button.ts",
"./components/toggle-switch": "./src/components/toggle-switch.ts", "./components/toggle-switch": "./src/components/toggle-switch.ts",
"./components/toolbar": "./src/components/toolbar.ts", "./components/toolbar": "./src/components/toolbar.ts",
"./components/tooltip": "./src/components/tooltip.ts",
"./components/view-dropdown-menu": "./src/components/view-dropdown-menu.ts", "./components/view-dropdown-menu": "./src/components/view-dropdown-menu.ts",
"./components/tooltip-content-with-shortcut": "./src/components/tooltip-content-with-shortcut.ts", "./components/tooltip-content-with-shortcut": "./src/components/tooltip-content-with-shortcut.ts",
"./components/resource": "./src/components/resource.ts",
"./rich-text": "./src/rich-text/index.ts", "./rich-text": "./src/rich-text/index.ts",
"./rich-text/effects": "./src/rich-text/effects.ts", "./rich-text/effects": "./src/rich-text/effects.ts",
"./shared/adapters": "./src/shared/adapters.ts", "./shared/adapters": "./src/shared/adapters.ts",
@@ -285,10 +264,7 @@
"./model": "./src/model/index.ts", "./model": "./src/model/index.ts",
"./sync": "./src/sync/index.ts", "./sync": "./src/sync/index.ts",
"./extensions/store": "./src/extensions/store.ts", "./extensions/store": "./src/extensions/store.ts",
"./extensions/view": "./src/extensions/view.ts", "./extensions/view": "./src/extensions/view.ts"
"./foundation/clipboard": "./src/foundation/clipboard.ts",
"./foundation/store": "./src/foundation/store.ts",
"./foundation/view": "./src/foundation/view.ts"
}, },
"files": [ "files": [
"src", "src",
@@ -296,10 +272,9 @@
"!src/__tests__", "!src/__tests__",
"!dist/__tests__" "!dist/__tests__"
], ],
"version": "0.22.4", "version": "0.21.0",
"devDependencies": { "devDependencies": {
"@vanilla-extract/vite-plugin": "^5.0.0", "@vanilla-extract/vite-plugin": "^5.0.0",
"msw": "^2.8.4", "vitest": "3.1.1"
"vitest": "3.1.3"
} }
} }
@@ -2360,65 +2360,6 @@ describe('html to snapshot', () => {
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot); expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
test('should preserve space in p', async () => {
const html = template(
`<p>A <b>bold text</b> followed by a <i>italic text</i></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: 'A ',
},
{
insert: 'bold text',
attributes: {
bold: true,
},
},
{
insert: ' followed by a ',
},
{
insert: 'italic text',
attributes: {
italic: true,
},
},
],
},
},
children: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
test('span nested in p', async () => { test('span nested in p', async () => {
const html = template( const html = template(
`<p><span>aaa</span><span>bbb</span><span>ccc</span></p>` `<p><span>aaa</span><span>bbb</span><span>ccc</span></p>`
@@ -2697,335 +2638,4 @@ describe('html to snapshot', () => {
}); });
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot); expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
test('block level element in b should not be treated as inline', async () => {
const html = template(`<b><p><span>aaa</span></p></b>`);
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: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
describe('strong element', () => {
test('should not be bold when font-weight is normal', async () => {
const html = template(`<span style="font-weight: normal;">aaa</span>`);
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: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
test('should be bold when font-weight is bold or 500-900 ', async () => {
const html = template(
`<p><span style="font-weight: bold;">aaa</span><span style="font-weight: 100;">aaa</span><span style="font-weight: 500;">bbb</span><span style="font-weight: 200;">bbb</span><span style="font-weight: 600;">ccc</span><span style="font-weight: 300;">ccc</span><span style="font-weight: 700;">ddd</span></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: [
{
attributes: {
bold: true,
},
insert: 'aaa',
},
{
insert: 'aaa',
},
{
attributes: {
bold: true,
},
insert: 'bbb',
},
{
insert: 'bbb',
},
{
attributes: {
bold: true,
},
insert: 'ccc',
},
{
insert: 'ccc',
},
{
attributes: {
bold: true,
},
insert: 'ddd',
},
],
},
},
children: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
});
test('should be italic when tag is i or em or span with style font-style: italic', async () => {
const html = template(
`<p><i>aaa</i><span>aaa</span><em>bbb</em><span>bbb</span><span style="font-style: italic;">ccc</span></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: [
{
attributes: {
italic: true,
},
insert: 'aaa',
},
{
insert: 'aaa',
},
{
attributes: {
italic: true,
},
insert: 'bbb',
},
{
insert: 'bbb',
},
{
attributes: {
italic: true,
},
insert: 'ccc',
},
],
},
},
children: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
test('should be underline when tag is u or span with style text-decoration: underline', async () => {
const html = template(
`<p><u>aaa</u><span>aaa</span><span style="text-decoration: underline;">bbb</span></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: [
{
attributes: {
underline: true,
},
insert: 'aaa',
},
{
insert: 'aaa',
},
{
attributes: {
underline: true,
},
insert: 'bbb',
},
],
},
},
children: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
test('should be strike when tag is del or span with style text-decoration: line-through', async () => {
const html = template(
`<p><del>aaa</del><span>aaa</span><span style="text-decoration: line-through;">bbb</span></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: [
{
attributes: {
strike: true,
},
insert: 'aaa',
},
{
insert: 'aaa',
},
{
attributes: {
strike: true,
},
insert: 'bbb',
},
],
},
},
children: [],
},
],
};
const htmlAdapter = new HtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await htmlAdapter.toBlockSnapshot({
file: html,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
}); });
@@ -4,9 +4,6 @@ import {
TableModelFlavour, TableModelFlavour,
} from '@blocksuite/affine-model'; } from '@blocksuite/affine-model';
import { import {
CalloutAdmonitionType,
CalloutExportStyle,
calloutMarkdownExportMiddleware,
embedSyncedDocMiddleware, embedSyncedDocMiddleware,
MarkdownAdapter, MarkdownAdapter,
} from '@blocksuite/affine-shared/adapters'; } from '@blocksuite/affine-shared/adapters';
@@ -2451,290 +2448,6 @@ World!
}); });
expect(target.file).toBe(markdown); expect(target.file).toBe(markdown);
}); });
describe('callout', () => {
test('without export middleware', async () => {
const blockSnapshot: BlockSnapshot = {
type: 'block',
id: 'block:vu6SK6WJpW',
flavour: 'affine:page',
props: {
title: {
'$blocksuite:internal:text$': true,
delta: [],
},
},
children: [
{
type: 'block',
id: 'block:Tk4gSPocAt',
flavour: 'affine:surface',
props: {
elements: {},
},
children: [],
},
{
type: 'block',
id: 'block:WfnS5ZDCJT',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:callout',
props: {
emoji: '💡',
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [{ insert: 'First callout' }],
},
},
children: [],
},
],
},
{
type: 'block',
id: 'block:8hOLxadvdv',
flavour: 'affine:callout',
props: {
emoji: '',
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{ insert: 'Warning second callout without emoji' },
],
},
},
children: [],
},
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [{ insert: 'Text in second callout' }],
},
},
children: [],
},
],
},
],
},
],
};
const markdown = `> \\[!💡]
>
> First callout
> \\[!]
>
> Warning second callout without emoji
>
> Text in second callout
`;
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const target = await mdAdapter.fromBlockSnapshot({
snapshot: blockSnapshot,
});
expect(target.file).toBe(markdown);
});
test('with export middleware', async () => {
const blockSnapshot: BlockSnapshot = {
type: 'block',
id: 'block:vu6SK6WJpW',
flavour: 'affine:page',
props: {
title: {
'$blocksuite:internal:text$': true,
delta: [],
},
},
children: [
{
type: 'block',
id: 'block:Tk4gSPocAt',
flavour: 'affine:surface',
props: {
elements: {},
},
children: [],
},
{
type: 'block',
id: 'block:WfnS5ZDCJT',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
hidden: false,
displayMode: NoteDisplayMode.DocAndEdgeless,
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:callout',
props: {
emoji: '💡',
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{ insert: 'Callout that does not have a title' },
],
},
},
children: [],
},
],
},
{
type: 'block',
id: 'block:8hOLxadvdv',
flavour: 'affine:callout',
props: {
emoji: '',
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert:
'Warning callout with custom title and multiple paragraphs',
},
],
},
},
children: [],
},
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [{ insert: 'Text in second callout' }],
},
},
children: [],
},
],
},
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:callout',
props: {
emoji: '💡',
},
children: [
{
type: 'block',
id: 'block:8hOLxad5Fv',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{ insert: 'details' },
{ insert: ' ' },
{ insert: '\nText in details callout with new line' },
],
},
},
children: [],
},
],
},
],
},
],
};
const markdown = `::: info
Callout that does not have a title
:::
::: warning callout with custom title and multiple paragraphs
Text in second callout
:::
::: details
Text in details callout with new line
:::
`;
const mdAdapter = new MarkdownAdapter(
createJob([
calloutMarkdownExportMiddleware({
style: CalloutExportStyle.Admonitions,
admonitionType: CalloutAdmonitionType.Info,
}),
]),
provider
);
const target = await mdAdapter.fromBlockSnapshot({
snapshot: blockSnapshot,
});
expect(target.file).toBe(markdown);
});
});
}); });
describe('markdown to snapshot', () => { describe('markdown to snapshot', () => {
@@ -3875,7 +3588,7 @@ bbb
props: { props: {
xywh: '[0,0,800,95]', xywh: '[0,0,800,95]',
background: { background: {
dark: '#252525', dark: '#000000',
light: '#ffffff', light: '#ffffff',
}, },
index: 'a0', index: 'a0',
@@ -4393,61 +4106,6 @@ hhh
}, },
children: [], children: [],
}, },
{
type: 'block',
id: 'matchesReplaceMap[2]',
flavour: 'affine:paragraph',
props: {
type: 'h6',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'Sources',
},
],
},
collapsed: true,
},
children: [],
},
{
type: 'block',
id: 'matchesReplaceMap[3]',
flavour: 'affine:bookmark',
props: {
style: 'citation',
url,
title,
description,
icon: favicon,
footnoteIdentifier: '1',
},
children: [],
},
{
type: 'block',
id: 'matchesReplaceMap[4]',
flavour: 'affine:embed-linked-doc',
props: {
style: 'citation',
pageId: 'deadbeef',
footnoteIdentifier: '2',
},
children: [],
},
{
type: 'block',
id: 'matchesReplaceMap[5]',
flavour: 'affine:attachment',
props: {
name: 'test.txt',
sourceId: 'abcdefg',
footnoteIdentifier: '3',
style: 'citation',
},
children: [],
},
], ],
}; };
@@ -4472,101 +4130,6 @@ hhh
}); });
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot); expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
test('should handle footnote reference with url prefix', async () => {
const 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: 'https://example.com',
attributes: {
link: 'https://example.com',
},
},
{
insert: ' ',
},
{
insert: ' ',
attributes: {
footnote: {
label: '1',
reference: {
type: 'url',
url,
favicon,
title,
description,
},
},
},
},
],
},
},
children: [],
},
{
type: 'block',
id: 'matchesReplaceMap[2]',
flavour: 'affine:paragraph',
props: {
type: 'h6',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'Sources',
},
],
},
collapsed: true,
},
children: [],
},
{
type: 'block',
id: 'matchesReplaceMap[3]',
flavour: 'affine:bookmark',
props: {
style: 'citation',
url,
title,
description,
icon: favicon,
footnoteIdentifier: '1',
},
children: [],
},
],
};
const markdown = `https://example.com[^1]\n\n[^1]: {"type":"url","url":"${url}","favicon":"${favicon}","title":"${title}","description":"${description}"}\n`;
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
file: markdown,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
});
}); });
test('should not wrap url with angle brackets if it is not a url', async () => { test('should not wrap url with angle brackets if it is not a url', async () => {
@@ -4619,62 +4182,4 @@ hhh
}); });
expect(nanoidReplacement(rawSliceSnapshot!)).toEqual(sliceSnapshot); expect(nanoidReplacement(rawSliceSnapshot!)).toEqual(sliceSnapshot);
}); });
describe('callout', () => {
const calloutBlockSnapshot: 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:callout',
props: {
emoji: '💬',
},
children: [
{
type: 'block',
id: 'matchesReplaceMap[2]',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [{ insert: 'This is a callout' }],
},
},
children: [],
},
],
},
],
};
test('callout start with escape character', async () => {
const markdown = '> \\[!💬]\n> This is a callout';
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
file: markdown,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(calloutBlockSnapshot);
});
test('callout start without escape character', async () => {
const markdown = '> [!💬]\n> This is a callout';
const mdAdapter = new MarkdownAdapter(createJob(), provider);
const rawBlockSnapshot = await mdAdapter.toBlockSnapshot({
file: markdown,
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(calloutBlockSnapshot);
});
});
}); });
@@ -1,14 +1,11 @@
import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model'; import { DefaultTheme, NoteDisplayMode } from '@blocksuite/affine-model';
import { NotionHtmlAdapter } from '@blocksuite/affine-shared/adapters'; import { NotionHtmlAdapter } from '@blocksuite/affine-shared/adapters';
import { DEFAULT_IMAGE_PROXY_ENDPOINT } from '@blocksuite/affine-shared/consts';
import { import {
AssetsManager, AssetsManager,
type BlockSnapshot, type BlockSnapshot,
MemoryBlobCRUD, MemoryBlobCRUD,
} from '@blocksuite/store'; } from '@blocksuite/store';
import { http, HttpResponse } from 'msw'; import { describe, expect, test } from 'vitest';
import { setupServer } from 'msw/node';
import { afterAll, afterEach, beforeAll, describe, expect, test } from 'vitest';
import { createJob } from '../utils/create-job.js'; import { createJob } from '../utils/create-job.js';
import { getProvider } from '../utils/get-provider.js'; import { getProvider } from '../utils/get-provider.js';
@@ -1198,71 +1195,43 @@ describe('notion html to snapshot', () => {
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot); expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
describe('image', () => { test('image', async () => {
const originalUrl = const html = `<div class="page-body">
'https://raw.githubusercontent.com/toeverything/blocksuite/master/assets/logo.svg'; <figure id="ed3d2ae9-62f5-433a-9049-9ddbd1c81ac5" class="image"><a
href="https://raw.githubusercontent.com/toeverything/blocksuite/master/assets/logo.svg"><img src="https://raw.githubusercontent.com/toeverything/blocksuite/master/assets/logo.svg" /></a>
</figure>
</div>`;
const imageProxy = DEFAULT_IMAGE_PROXY_ENDPOINT; const blockSnapshot: BlockSnapshot = {
const imageUrl = `${imageProxy}?url=${encodeURIComponent(originalUrl)}`; type: 'block',
id: 'matchesReplaceMap[0]',
// Mock the image request flavour: 'affine:note',
const imageRequestHandlers = [ props: {
http.get(imageUrl.toString(), async () => { xywh: '[0,0,800,95]',
// Return a mock image blob background: DefaultTheme.noteBackgrounColor,
const mockImageBlob = new Blob(['mock image data'], { index: 'a0',
type: 'image/svg+xml', hidden: false,
}); displayMode: NoteDisplayMode.DocAndEdgeless,
return new HttpResponse(mockImageBlob, { },
headers: { children: [
'Content-Type': 'image/svg+xml', {
type: 'block',
id: 'matchesReplaceMap[1]',
flavour: 'affine:image',
props: {
sourceId: 'matchesReplaceMap[2]',
}, },
}); children: [],
}),
];
const server = setupServer(...imageRequestHandlers);
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }));
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
test('network image resource', async () => {
const html = `<div class="page-body">
<figure id="ed3d2ae9-62f5-433a-9049-9ddbd1c81ac5" class="image"><a
href="${originalUrl}"><img src="${originalUrl}" /></a>
</figure>
</div>`;
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:image',
props: {
sourceId: 'matchesReplaceMap[2]',
},
children: [],
},
],
};
const adapter = new NotionHtmlAdapter(createJob(), provider); const adapter = new NotionHtmlAdapter(createJob(), provider);
const rawBlockSnapshot = await adapter.toBlockSnapshot({ const rawBlockSnapshot = await adapter.toBlockSnapshot({
file: html, file: html,
assets: new AssetsManager({ blob: new MemoryBlobCRUD() }), assets: new AssetsManager({ blob: new MemoryBlobCRUD() }),
});
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
expect(nanoidReplacement(rawBlockSnapshot)).toEqual(blockSnapshot);
}); });
test('bookmark', async () => { test('bookmark', async () => {
@@ -106,65 +106,4 @@ describe('notion-text to snapshot', () => {
}); });
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot); expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
}); });
test('notion text with empty styles array', () => {
const notionText =
'{"blockType":"text","editing":[["a "],["bold text",[["b"]]],[" hello world"]],"selection":{"startIndex":0,"endIndex":23},"action":"copy"}';
const sliceSnapshot: SliceSnapshot = {
type: 'slice',
content: [
{
type: 'block',
id: 'matchesReplaceMap[0]',
flavour: 'affine:note',
props: {
xywh: '[0,0,800,95]',
background: DefaultTheme.noteBackgrounColor,
index: 'a0',
hidden: false,
displayMode: 'both',
},
children: [
{
type: 'block',
id: 'matchesReplaceMap[1]',
flavour: 'affine:paragraph',
props: {
type: 'text',
text: {
'$blocksuite:internal:text$': true,
delta: [
{
insert: 'a ',
},
{
insert: 'bold text',
attributes: {
bold: true,
},
},
{
insert: ' hello world',
},
],
},
},
children: [],
},
],
},
],
workspaceId: '',
pageId: '',
};
const ntAdapter = new NotionTextAdapter(createJob(), provider);
const target = ntAdapter.toSliceSnapshot({
file: notionText,
workspaceId: '',
pageId: '',
});
expect(nanoidReplacement(target!)).toEqual(sliceSnapshot);
});
}); });
@@ -0,0 +1,65 @@
import {
HtmlInlineToDeltaAdapterExtensions,
InlineDeltaToHtmlAdapterExtensions,
InlineDeltaToMarkdownAdapterExtensions,
MarkdownInlineToDeltaAdapterExtensions,
NotionHtmlInlineToDeltaAdapterExtensions,
} from '@blocksuite/affine-inline-preset';
import {
AttachmentAdapterFactoryExtension,
HtmlAdapterFactoryExtension,
ImageAdapterFactoryExtension,
MarkdownAdapterFactoryExtension,
MixTextAdapterFactoryExtension,
NotionHtmlAdapterFactoryExtension,
NotionTextAdapterFactoryExtension,
PlainTextAdapterFactoryExtension,
} from '@blocksuite/affine-shared/adapters';
import type { ExtensionType } from '@blocksuite/store';
import { defaultBlockHtmlAdapterMatchers } from './html/block-matcher';
import { defaultBlockMarkdownAdapterMatchers } from './markdown/block-matcher';
import { defaultMarkdownPreprocessors } from './markdown/preprocessor';
import { defaultBlockNotionHtmlAdapterMatchers } from './notion-html/block-matcher';
import { defaultBlockPlainTextAdapterMatchers } from './plain-text/block-matcher';
export function getAdapterFactoryExtensions(): ExtensionType[] {
return [
AttachmentAdapterFactoryExtension,
ImageAdapterFactoryExtension,
MarkdownAdapterFactoryExtension,
PlainTextAdapterFactoryExtension,
HtmlAdapterFactoryExtension,
NotionTextAdapterFactoryExtension,
NotionHtmlAdapterFactoryExtension,
MixTextAdapterFactoryExtension,
];
}
export function getHtmlAdapterExtensions(): ExtensionType[] {
return [
...HtmlInlineToDeltaAdapterExtensions,
...defaultBlockHtmlAdapterMatchers,
...InlineDeltaToHtmlAdapterExtensions,
];
}
export function getMarkdownAdapterExtensions(): ExtensionType[] {
return [
...MarkdownInlineToDeltaAdapterExtensions,
...defaultBlockMarkdownAdapterMatchers,
...InlineDeltaToMarkdownAdapterExtensions,
...defaultMarkdownPreprocessors,
];
}
export function getNotionHtmlAdapterExtensions(): ExtensionType[] {
return [
...NotionHtmlInlineToDeltaAdapterExtensions,
...defaultBlockNotionHtmlAdapterMatchers,
];
}
export function getPlainTextAdapterExtensions(): ExtensionType[] {
return [...defaultBlockPlainTextAdapterMatchers];
}
@@ -0,0 +1,37 @@
import { BookmarkBlockHtmlAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockHtmlAdapterExtension } from '@blocksuite/affine-block-code';
import { DatabaseBlockHtmlAdapterExtension } from '@blocksuite/affine-block-database';
import { DividerBlockHtmlAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockHtmlAdapterExtension,
EmbedGithubBlockHtmlAdapterExtension,
EmbedIframeBlockHtmlAdapterExtension,
EmbedLinkedDocHtmlAdapterExtension,
EmbedLoomBlockHtmlAdapterExtension,
EmbedSyncedDocBlockHtmlAdapterExtension,
EmbedYoutubeBlockHtmlAdapterExtension,
} from '@blocksuite/affine-block-embed';
import { ImageBlockHtmlAdapterExtension } from '@blocksuite/affine-block-image';
import { ListBlockHtmlAdapterExtension } from '@blocksuite/affine-block-list';
import { ParagraphBlockHtmlAdapterExtension } from '@blocksuite/affine-block-paragraph';
import { RootBlockHtmlAdapterExtension } from '@blocksuite/affine-block-root';
import { TableBlockHtmlAdapterExtension } from '@blocksuite/affine-block-table';
export const defaultBlockHtmlAdapterMatchers = [
ListBlockHtmlAdapterExtension,
ParagraphBlockHtmlAdapterExtension,
CodeBlockHtmlAdapterExtension,
DividerBlockHtmlAdapterExtension,
ImageBlockHtmlAdapterExtension,
RootBlockHtmlAdapterExtension,
EmbedYoutubeBlockHtmlAdapterExtension,
EmbedFigmaBlockHtmlAdapterExtension,
EmbedLoomBlockHtmlAdapterExtension,
EmbedGithubBlockHtmlAdapterExtension,
EmbedIframeBlockHtmlAdapterExtension,
BookmarkBlockHtmlAdapterExtension,
DatabaseBlockHtmlAdapterExtension,
TableBlockHtmlAdapterExtension,
EmbedLinkedDocHtmlAdapterExtension,
EmbedSyncedDocBlockHtmlAdapterExtension,
];
@@ -0,0 +1,6 @@
export * from './extension.js';
export * from './html/block-matcher.js';
export * from './markdown/block-matcher.js';
export * from './markdown/preprocessor.js';
export * from './notion-html/block-matcher.js';
export * from './plain-text/block-matcher.js';
@@ -0,0 +1,43 @@
import { AttachmentBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-code';
import { DatabaseBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-database';
import { DividerBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaMarkdownAdapterExtension,
EmbedGithubMarkdownAdapterExtension,
EmbedIframeBlockMarkdownAdapterExtension,
EmbedLinkedDocMarkdownAdapterExtension,
EmbedLoomMarkdownAdapterExtension,
EmbedSyncedDocMarkdownAdapterExtension,
EmbedYoutubeMarkdownAdapterExtension,
} from '@blocksuite/affine-block-embed';
import { ImageBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-image';
import { LatexBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-latex';
import { ListBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-list';
import { DocNoteBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-note';
import { ParagraphBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-paragraph';
import { RootBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-root';
import { TableBlockMarkdownAdapterExtension } from '@blocksuite/affine-block-table';
export const defaultBlockMarkdownAdapterMatchers = [
RootBlockMarkdownAdapterExtension,
DocNoteBlockMarkdownAdapterExtension,
EmbedFigmaMarkdownAdapterExtension,
EmbedGithubMarkdownAdapterExtension,
EmbedLinkedDocMarkdownAdapterExtension,
EmbedLoomMarkdownAdapterExtension,
EmbedSyncedDocMarkdownAdapterExtension,
EmbedYoutubeMarkdownAdapterExtension,
EmbedIframeBlockMarkdownAdapterExtension,
ListBlockMarkdownAdapterExtension,
ParagraphBlockMarkdownAdapterExtension,
BookmarkBlockMarkdownAdapterExtension,
CodeBlockMarkdownAdapterExtension,
DatabaseBlockMarkdownAdapterExtension,
TableBlockMarkdownAdapterExtension,
DividerBlockMarkdownAdapterExtension,
ImageBlockMarkdownAdapterExtension,
LatexBlockMarkdownAdapterExtension,
AttachmentBlockMarkdownAdapterExtension,
];
@@ -0,0 +1,9 @@
import { BookmarkBlockMarkdownPreprocessorExtension } from '@blocksuite/affine-block-bookmark';
import { CodeMarkdownPreprocessorExtension } from '@blocksuite/affine-block-code';
import { LatexMarkdownPreprocessorExtension } from '@blocksuite/affine-block-latex';
export const defaultMarkdownPreprocessors = [
LatexMarkdownPreprocessorExtension,
CodeMarkdownPreprocessorExtension,
BookmarkBlockMarkdownPreprocessorExtension,
];
@@ -0,0 +1,34 @@
import { AttachmentBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-attachment';
import { BookmarkBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-code';
import { DatabaseBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-database';
import { DividerBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockNotionHtmlAdapterExtension,
EmbedGithubBlockNotionHtmlAdapterExtension,
EmbedLoomBlockNotionHtmlAdapterExtension,
EmbedYoutubeBlockNotionHtmlAdapterExtension,
} from '@blocksuite/affine-block-embed';
import { ImageBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-image';
import { LatexBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-latex';
import { ListBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-list';
import { ParagraphBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-paragraph';
import { RootBlockNotionHtmlAdapterExtension } from '@blocksuite/affine-block-root';
import type { ExtensionType } from '@blocksuite/store';
export const defaultBlockNotionHtmlAdapterMatchers: ExtensionType[] = [
ListBlockNotionHtmlAdapterExtension,
ParagraphBlockNotionHtmlAdapterExtension,
CodeBlockNotionHtmlAdapterExtension,
DividerBlockNotionHtmlAdapterExtension,
ImageBlockNotionHtmlAdapterExtension,
RootBlockNotionHtmlAdapterExtension,
BookmarkBlockNotionHtmlAdapterExtension,
DatabaseBlockNotionHtmlAdapterExtension,
LatexBlockNotionHtmlAdapterExtension,
EmbedYoutubeBlockNotionHtmlAdapterExtension,
EmbedFigmaBlockNotionHtmlAdapterExtension,
EmbedGithubBlockNotionHtmlAdapterExtension,
EmbedLoomBlockNotionHtmlAdapterExtension,
AttachmentBlockNotionHtmlAdapterExtension,
];
@@ -0,0 +1,34 @@
import { BookmarkBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-bookmark';
import { CodeBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-code';
import { DatabaseBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-database';
import { DividerBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-divider';
import {
EmbedFigmaBlockPlainTextAdapterExtension,
EmbedGithubBlockPlainTextAdapterExtension,
EmbedIframeBlockPlainTextAdapterExtension,
EmbedLinkedDocBlockPlainTextAdapterExtension,
EmbedLoomBlockPlainTextAdapterExtension,
EmbedSyncedDocBlockPlainTextAdapterExtension,
EmbedYoutubeBlockPlainTextAdapterExtension,
} from '@blocksuite/affine-block-embed';
import { LatexBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-latex';
import { ListBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-list';
import { ParagraphBlockPlainTextAdapterExtension } from '@blocksuite/affine-block-paragraph';
import type { ExtensionType } from '@blocksuite/store';
export const defaultBlockPlainTextAdapterMatchers: ExtensionType[] = [
ParagraphBlockPlainTextAdapterExtension,
ListBlockPlainTextAdapterExtension,
DividerBlockPlainTextAdapterExtension,
CodeBlockPlainTextAdapterExtension,
BookmarkBlockPlainTextAdapterExtension,
EmbedFigmaBlockPlainTextAdapterExtension,
EmbedGithubBlockPlainTextAdapterExtension,
EmbedLoomBlockPlainTextAdapterExtension,
EmbedYoutubeBlockPlainTextAdapterExtension,
EmbedLinkedDocBlockPlainTextAdapterExtension,
EmbedSyncedDocBlockPlainTextAdapterExtension,
EmbedIframeBlockPlainTextAdapterExtension,
LatexBlockPlainTextAdapterExtension,
DatabaseBlockPlainTextAdapterExtension,
];
@@ -1 +0,0 @@
export * from '@blocksuite/affine-block-embed-doc';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-block-embed-doc/store';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-block-embed-doc/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-block-root/store';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-block-root/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-components/citation';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-components/resource';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-components/tooltip';
+170 -17
View File
@@ -1,24 +1,92 @@
import { type effects as blockRootEffects } from '@blocksuite/affine-block-root/effects'; import { effects as blockAttachmentEffects } from '@blocksuite/affine-block-attachment/effects';
import { type effects as componentCaptionEffects } from '@blocksuite/affine-components/caption'; import { effects as blockBookmarkEffects } from '@blocksuite/affine-block-bookmark/effects';
import { type effects as componentColorPickerEffects } from '@blocksuite/affine-components/color-picker'; import { effects as blockCalloutEffects } from '@blocksuite/affine-block-callout/effects';
import { type effects as componentContextMenuEffects } from '@blocksuite/affine-components/context-menu'; import { effects as blockCodeEffects } from '@blocksuite/affine-block-code/effects';
import { type effects as componentDatePickerEffects } from '@blocksuite/affine-components/date-picker'; import { effects as blockDataViewEffects } from '@blocksuite/affine-block-data-view/effects';
import { type effects as componentDropIndicatorEffects } from '@blocksuite/affine-components/drop-indicator'; import { effects as blockDatabaseEffects } from '@blocksuite/affine-block-database/effects';
import { type effects as componentEmbedCardModalEffects } from '@blocksuite/affine-components/embed-card-modal'; import { effects as blockDividerEffects } from '@blocksuite/affine-block-divider/effects';
import { type effects as componentHighlightDropdownMenuEffects } from '@blocksuite/affine-components/highlight-dropdown-menu'; import { effects as blockEdgelessTextEffects } from '@blocksuite/affine-block-edgeless-text/effects';
import { type effects as componentLinkPreviewEffects } from '@blocksuite/affine-components/link-preview'; import { effects as blockEmbedEffects } from '@blocksuite/affine-block-embed/effects';
import { type effects as componentLinkedDocTitleEffects } from '@blocksuite/affine-components/linked-doc-title'; import { effects as blockFrameEffects } from '@blocksuite/affine-block-frame/effects';
import { type effects as componentPortalEffects } from '@blocksuite/affine-components/portal'; import { effects as blockImageEffects } from '@blocksuite/affine-block-image/effects';
import { type effects as componentToggleButtonEffects } from '@blocksuite/affine-components/toggle-button'; import { effects as blockLatexEffects } from '@blocksuite/affine-block-latex/effects';
import { type effects as componentToolbarEffects } from '@blocksuite/affine-components/toolbar'; import { effects as blockListEffects } from '@blocksuite/affine-block-list/effects';
import { type effects as componentViewDropdownMenuEffects } from '@blocksuite/affine-components/view-dropdown-menu'; import { effects as blockNoteEffects } from '@blocksuite/affine-block-note/effects';
import { type effects as richTextEffects } from '@blocksuite/affine-rich-text/effects'; import { effects as blockParagraphEffects } from '@blocksuite/affine-block-paragraph/effects';
import { type effects as stdEffects } from '@blocksuite/std/effects'; import { effects as blockRootEffects } from '@blocksuite/affine-block-root/effects';
import { effects as blockSurfaceEffects } from '@blocksuite/affine-block-surface/effects';
import { effects as blockSurfaceRefEffects } from '@blocksuite/affine-block-surface-ref/effects';
import { effects as blockTableEffects } from '@blocksuite/affine-block-table/effects';
import { BlockSelection } from '@blocksuite/affine-components/block-selection';
import { BlockZeroWidth } from '@blocksuite/affine-components/block-zero-width';
import { effects as componentCaptionEffects } from '@blocksuite/affine-components/caption';
import { effects as componentCardStyleDropdownMenuEffects } from '@blocksuite/affine-components/card-style-dropdown-menu';
import { effects as componentCitationEffects } from '@blocksuite/affine-components/citation';
import { effects as componentColorPickerEffects } from '@blocksuite/affine-components/color-picker';
import { effects as componentContextMenuEffects } from '@blocksuite/affine-components/context-menu';
import { effects as componentDatePickerEffects } from '@blocksuite/affine-components/date-picker';
import { effects as componentDropIndicatorEffects } from '@blocksuite/affine-components/drop-indicator';
import { effects as componentEdgelessLineStylesEffects } from '@blocksuite/affine-components/edgeless-line-styles-panel';
import { effects as componentEdgelessLineWidthEffects } from '@blocksuite/affine-components/edgeless-line-width-panel';
import { effects as componentEdgelessShapeColorPickerEffects } from '@blocksuite/affine-components/edgeless-shape-color-picker';
import { effects as componentEmbedCardModalEffects } from '@blocksuite/affine-components/embed-card-modal';
import { FilterableListComponent } from '@blocksuite/affine-components/filterable-list';
import { effects as componentHighlightDropdownMenuEffects } from '@blocksuite/affine-components/highlight-dropdown-menu';
import { IconButton } from '@blocksuite/affine-components/icon-button';
import { effects as componentLinkPreviewEffects } from '@blocksuite/affine-components/link-preview';
import { effects as componentLinkedDocTitleEffects } from '@blocksuite/affine-components/linked-doc-title';
import { effects as componentOpenDocDropdownMenuEffects } from '@blocksuite/affine-components/open-doc-dropdown-menu';
import { effects as componentPortalEffects } from '@blocksuite/affine-components/portal';
import { effects as componentSizeDropdownMenuEffects } from '@blocksuite/affine-components/size-dropdown-menu';
import { SmoothCorner } from '@blocksuite/affine-components/smooth-corner';
import { effects as componentToggleButtonEffects } from '@blocksuite/affine-components/toggle-button';
import { ToggleSwitch } from '@blocksuite/affine-components/toggle-switch';
import { effects as componentToolbarEffects } from '@blocksuite/affine-components/toolbar';
import { effects as componentTooltipContentWithShortcutEffects } from '@blocksuite/affine-components/tooltip-content-with-shortcut';
import { effects as componentViewDropdownMenuEffects } from '@blocksuite/affine-components/view-dropdown-menu';
import { effects as fragmentDocTitleEffects } from '@blocksuite/affine-fragment-doc-title/effects';
import { effects as fragmentFramePanelEffects } from '@blocksuite/affine-fragment-frame-panel/effects';
import { effects as fragmentOutlineEffects } from '@blocksuite/affine-fragment-outline/effects';
import { effects as inlineFootnoteEffects } from '@blocksuite/affine-inline-footnote/effects';
import { effects as inlineLatexEffects } from '@blocksuite/affine-inline-latex/effects';
import { effects as inlineLinkEffects } from '@blocksuite/affine-inline-link/effects';
import { effects as inlineMentionEffects } from '@blocksuite/affine-inline-mention';
import { effects as inlinePresetEffects } from '@blocksuite/affine-inline-preset/effects';
import { effects as inlineReferenceEffects } from '@blocksuite/affine-inline-reference/effects';
import { effects as richTextEffects } from '@blocksuite/affine-rich-text/effects';
import { effects as widgetDragHandleEffects } from '@blocksuite/affine-widget-drag-handle/effects';
import { effects as widgetEdgelessAutoConnectEffects } from '@blocksuite/affine-widget-edgeless-auto-connect/effects';
import { effects as widgetFrameTitleEffects } from '@blocksuite/affine-widget-frame-title/effects';
import { effects as widgetRemoteSelectionEffects } from '@blocksuite/affine-widget-remote-selection/effects';
import { effects as widgetScrollAnchoringEffects } from '@blocksuite/affine-widget-scroll-anchoring/effects';
import { effects as widgetSlashMenuEffects } from '@blocksuite/affine-widget-slash-menu/effects';
import { effects as widgetToolbarEffects } from '@blocksuite/affine-widget-toolbar/effects';
import { effects as dataViewEffects } from '@blocksuite/data-view/effects';
import { effects as stdEffects } from '@blocksuite/std/effects';
export declare const _GLOBAL_: export declare const _GLOBAL_:
| typeof stdEffects | typeof stdEffects
| typeof dataViewEffects
| typeof richTextEffects | typeof richTextEffects
| typeof blockNoteEffects
| typeof blockAttachmentEffects
| typeof blockBookmarkEffects
| typeof blockFrameEffects
| typeof blockListEffects
| typeof blockParagraphEffects
| typeof blockEmbedEffects
| typeof blockSurfaceEffects
| typeof blockImageEffects
| typeof blockDatabaseEffects
| typeof blockSurfaceRefEffects
| typeof blockLatexEffects
| typeof blockEdgelessTextEffects
| typeof blockDividerEffects
| typeof blockDataViewEffects
| typeof blockCodeEffects
| typeof blockTableEffects
| typeof blockRootEffects | typeof blockRootEffects
| typeof blockCalloutEffects
| typeof componentCaptionEffects | typeof componentCaptionEffects
| typeof componentContextMenuEffects | typeof componentContextMenuEffects
| typeof componentDatePickerEffects | typeof componentDatePickerEffects
@@ -31,4 +99,89 @@ export declare const _GLOBAL_:
| typeof componentToolbarEffects | typeof componentToolbarEffects
| typeof componentToggleButtonEffects | typeof componentToggleButtonEffects
| typeof componentColorPickerEffects | typeof componentColorPickerEffects
| typeof componentViewDropdownMenuEffects; | typeof componentViewDropdownMenuEffects
| typeof widgetScrollAnchoringEffects
| typeof widgetFrameTitleEffects
| typeof widgetRemoteSelectionEffects
| typeof widgetDragHandleEffects
| typeof widgetEdgelessAutoConnectEffects
| typeof widgetToolbarEffects
| typeof widgetSlashMenuEffects
| typeof fragmentDocTitleEffects
| typeof fragmentFramePanelEffects
| typeof fragmentOutlineEffects;
export function effects() {
stdEffects();
dataViewEffects();
richTextEffects();
inlineReferenceEffects();
inlinePresetEffects();
inlineLinkEffects();
inlineFootnoteEffects();
inlineLatexEffects();
inlineMentionEffects();
blockNoteEffects();
blockAttachmentEffects();
blockBookmarkEffects();
blockFrameEffects();
blockListEffects();
blockParagraphEffects();
blockEmbedEffects();
blockSurfaceEffects();
blockImageEffects();
blockDatabaseEffects();
blockSurfaceRefEffects();
blockLatexEffects();
blockEdgelessTextEffects();
blockDividerEffects();
blockDataViewEffects();
blockCodeEffects();
blockTableEffects();
blockRootEffects();
blockCalloutEffects();
componentCaptionEffects();
componentContextMenuEffects();
componentDatePickerEffects();
componentPortalEffects();
componentToolbarEffects();
componentDropIndicatorEffects();
componentToggleButtonEffects();
componentColorPickerEffects();
componentEmbedCardModalEffects();
componentLinkPreviewEffects();
componentLinkedDocTitleEffects();
componentCitationEffects();
componentCardStyleDropdownMenuEffects();
componentHighlightDropdownMenuEffects();
componentViewDropdownMenuEffects();
componentTooltipContentWithShortcutEffects();
componentSizeDropdownMenuEffects();
componentEdgelessLineWidthEffects();
componentEdgelessLineStylesEffects();
componentEdgelessShapeColorPickerEffects();
componentOpenDocDropdownMenuEffects();
widgetScrollAnchoringEffects();
widgetFrameTitleEffects();
widgetRemoteSelectionEffects();
widgetDragHandleEffects();
widgetEdgelessAutoConnectEffects();
widgetSlashMenuEffects();
widgetToolbarEffects();
fragmentDocTitleEffects();
fragmentFramePanelEffects();
fragmentOutlineEffects();
customElements.define('icon-button', IconButton);
customElements.define('smooth-corner', SmoothCorner);
customElements.define('toggle-switch', ToggleSwitch);
customElements.define('affine-filterable-list', FilterableListComponent);
customElements.define('block-zero-width', BlockZeroWidth);
customElements.define('affine-block-selection', BlockSelection);
}
@@ -0,0 +1,12 @@
import { effects as blockRootEffects } from '@blocksuite/affine-block-root/effects';
import { effects as fragmentDocTitleEffects } from '@blocksuite/affine-fragment-doc-title/effects';
import { effects as fragmentFramePanelEffects } from '@blocksuite/affine-fragment-frame-panel/effects';
import { effects as fragmentOutlineEffects } from '@blocksuite/affine-fragment-outline/effects';
export function effects() {
blockRootEffects();
fragmentDocTitleEffects();
fragmentFramePanelEffects();
fragmentOutlineEffects();
}
@@ -0,0 +1,48 @@
import {
RootBlockHtmlAdapterExtension,
RootBlockMarkdownAdapterExtension,
RootBlockNotionHtmlAdapterExtension,
} from '@blocksuite/affine-block-root';
import {
type StoreExtensionContext,
StoreExtensionProvider,
} from '@blocksuite/affine-ext-loader';
import { RootBlockSchemaExtension } from '@blocksuite/affine-model';
import type { ExtensionType } from '@blocksuite/store';
const defaultBlockHtmlAdapterMatchers = [RootBlockHtmlAdapterExtension];
const defaultBlockMarkdownAdapterMatchers = [RootBlockMarkdownAdapterExtension];
const defaultBlockNotionHtmlAdapterMatchers: ExtensionType[] = [
RootBlockNotionHtmlAdapterExtension,
];
function getHtmlAdapterExtensions(): ExtensionType[] {
return [...defaultBlockHtmlAdapterMatchers];
}
function getMarkdownAdapterExtensions(): ExtensionType[] {
return [...defaultBlockMarkdownAdapterMatchers];
}
function getNotionHtmlAdapterExtensions(): ExtensionType[] {
return [...defaultBlockNotionHtmlAdapterMatchers];
}
const MigratingStoreExtensions: ExtensionType[] = [
RootBlockSchemaExtension,
getHtmlAdapterExtensions(),
getMarkdownAdapterExtensions(),
getNotionHtmlAdapterExtensions(),
].flat();
export class MigratingStoreExtension extends StoreExtensionProvider {
override name = 'migrating';
override setup(context: StoreExtensionContext) {
super.setup(context);
context.register(MigratingStoreExtensions);
}
}
@@ -0,0 +1,42 @@
import {
type ViewExtensionContext,
ViewExtensionProvider,
} from '@blocksuite/affine-ext-loader';
import { effects } from './effects';
import {
MigratingEdgelessEditorBlockSpecs,
MigratingPageEditorBlockSpecs,
MigratingPreviewEdgelessEditorBlockSpecs,
MigratingPreviewPageEditorBlockSpecs,
} from './migrating';
export class MigratingViewExtension extends ViewExtensionProvider {
override name = 'migrating';
override effect() {
super.effect();
effects();
}
override setup(context: ViewExtensionContext) {
super.setup(context);
const scope = context.scope;
if (scope === 'preview-page') {
context.register(MigratingPreviewPageEditorBlockSpecs);
return;
}
if (scope === 'preview-edgeless') {
context.register(MigratingPreviewEdgelessEditorBlockSpecs);
return;
}
if (scope === 'page' || scope === 'mobile-page') {
context.register(MigratingPageEditorBlockSpecs);
return;
}
if (scope === 'edgeless' || scope === 'mobile-edgeless') {
context.register(MigratingEdgelessEditorBlockSpecs);
return;
}
}
}
@@ -0,0 +1,26 @@
import {
EdgelessBuiltInSpecs,
PageRootBlockSpec,
PreviewEdgelessRootBlockSpec,
PreviewPageRootBlockSpec,
ReadOnlyClipboard,
} from '@blocksuite/affine-block-root';
import type { ExtensionType } from '@blocksuite/store';
export const MigratingEdgelessEditorBlockSpecs: ExtensionType[] = [
EdgelessBuiltInSpecs,
].flat();
export const MigratingPageEditorBlockSpecs: ExtensionType[] = [
PageRootBlockSpec,
].flat();
export const MigratingPreviewEdgelessEditorBlockSpecs: ExtensionType[] = [
PreviewEdgelessRootBlockSpec,
ReadOnlyClipboard,
].flat();
export const MigratingPreviewPageEditorBlockSpecs: ExtensionType[] = [
PreviewPageRootBlockSpec,
ReadOnlyClipboard,
].flat();
@@ -7,14 +7,12 @@ import { DatabaseStoreExtension } from '@blocksuite/affine-block-database/store'
import { DividerStoreExtension } from '@blocksuite/affine-block-divider/store'; import { DividerStoreExtension } from '@blocksuite/affine-block-divider/store';
import { EdgelessTextStoreExtension } from '@blocksuite/affine-block-edgeless-text/store'; import { EdgelessTextStoreExtension } from '@blocksuite/affine-block-edgeless-text/store';
import { EmbedStoreExtension } from '@blocksuite/affine-block-embed/store'; import { EmbedStoreExtension } from '@blocksuite/affine-block-embed/store';
import { EmbedDocStoreExtension } from '@blocksuite/affine-block-embed-doc/store';
import { FrameStoreExtension } from '@blocksuite/affine-block-frame/store'; import { FrameStoreExtension } from '@blocksuite/affine-block-frame/store';
import { ImageStoreExtension } from '@blocksuite/affine-block-image/store'; import { ImageStoreExtension } from '@blocksuite/affine-block-image/store';
import { LatexStoreExtension } from '@blocksuite/affine-block-latex/store'; import { LatexStoreExtension } from '@blocksuite/affine-block-latex/store';
import { ListStoreExtension } from '@blocksuite/affine-block-list/store'; import { ListStoreExtension } from '@blocksuite/affine-block-list/store';
import { NoteStoreExtension } from '@blocksuite/affine-block-note/store'; import { NoteStoreExtension } from '@blocksuite/affine-block-note/store';
import { ParagraphStoreExtension } from '@blocksuite/affine-block-paragraph/store'; import { ParagraphStoreExtension } from '@blocksuite/affine-block-paragraph/store';
import { RootStoreExtension } from '@blocksuite/affine-block-root/store';
import { SurfaceStoreExtension } from '@blocksuite/affine-block-surface/store'; import { SurfaceStoreExtension } from '@blocksuite/affine-block-surface/store';
import { SurfaceRefStoreExtension } from '@blocksuite/affine-block-surface-ref/store'; import { SurfaceRefStoreExtension } from '@blocksuite/affine-block-surface-ref/store';
import { TableStoreExtension } from '@blocksuite/affine-block-table/store'; import { TableStoreExtension } from '@blocksuite/affine-block-table/store';
@@ -31,6 +29,8 @@ import { LinkStoreExtension } from '@blocksuite/affine-inline-link/store';
import { InlinePresetStoreExtension } from '@blocksuite/affine-inline-preset/store'; import { InlinePresetStoreExtension } from '@blocksuite/affine-inline-preset/store';
import { ReferenceStoreExtension } from '@blocksuite/affine-inline-reference/store'; import { ReferenceStoreExtension } from '@blocksuite/affine-inline-reference/store';
import { MigratingStoreExtension } from './migrating-store';
export function getInternalStoreExtensions() { export function getInternalStoreExtensions() {
return [ return [
FoundationStoreExtension, FoundationStoreExtension,
@@ -44,7 +44,6 @@ export function getInternalStoreExtensions() {
DividerStoreExtension, DividerStoreExtension,
EdgelessTextStoreExtension, EdgelessTextStoreExtension,
EmbedStoreExtension, EmbedStoreExtension,
EmbedDocStoreExtension,
FrameStoreExtension, FrameStoreExtension,
ImageStoreExtension, ImageStoreExtension,
LatexStoreExtension, LatexStoreExtension,
@@ -54,7 +53,6 @@ export function getInternalStoreExtensions() {
SurfaceRefStoreExtension, SurfaceRefStoreExtension,
TableStoreExtension, TableStoreExtension,
SurfaceStoreExtension, SurfaceStoreExtension,
RootStoreExtension,
FootnoteStoreExtension, FootnoteStoreExtension,
LinkStoreExtension, LinkStoreExtension,
@@ -68,5 +66,7 @@ export function getInternalStoreExtensions() {
ConnectorStoreExtension, ConnectorStoreExtension,
GroupStoreExtension, GroupStoreExtension,
TextStoreExtension, TextStoreExtension,
MigratingStoreExtension,
]; ];
} }
+4 -24
View File
@@ -7,22 +7,16 @@ import { DatabaseViewExtension } from '@blocksuite/affine-block-database/view';
import { DividerViewExtension } from '@blocksuite/affine-block-divider/view'; import { DividerViewExtension } from '@blocksuite/affine-block-divider/view';
import { EdgelessTextViewExtension } from '@blocksuite/affine-block-edgeless-text/view'; import { EdgelessTextViewExtension } from '@blocksuite/affine-block-edgeless-text/view';
import { EmbedViewExtension } from '@blocksuite/affine-block-embed/view'; import { EmbedViewExtension } from '@blocksuite/affine-block-embed/view';
import { EmbedDocViewExtension } from '@blocksuite/affine-block-embed-doc/view';
import { FrameViewExtension } from '@blocksuite/affine-block-frame/view'; import { FrameViewExtension } from '@blocksuite/affine-block-frame/view';
import { ImageViewExtension } from '@blocksuite/affine-block-image/view'; import { ImageViewExtension } from '@blocksuite/affine-block-image/view';
import { LatexViewExtension } from '@blocksuite/affine-block-latex/view'; import { LatexViewExtension } from '@blocksuite/affine-block-latex/view';
import { ListViewExtension } from '@blocksuite/affine-block-list/view'; import { ListViewExtension } from '@blocksuite/affine-block-list/view';
import { NoteViewExtension } from '@blocksuite/affine-block-note/view'; import { NoteViewExtension } from '@blocksuite/affine-block-note/view';
import { ParagraphViewExtension } from '@blocksuite/affine-block-paragraph/view'; import { ParagraphViewExtension } from '@blocksuite/affine-block-paragraph/view';
import { RootViewExtension } from '@blocksuite/affine-block-root/view';
import { SurfaceViewExtension } from '@blocksuite/affine-block-surface/view'; import { SurfaceViewExtension } from '@blocksuite/affine-block-surface/view';
import { SurfaceRefViewExtension } from '@blocksuite/affine-block-surface-ref/view'; import { SurfaceRefViewExtension } from '@blocksuite/affine-block-surface-ref/view';
import { TableViewExtension } from '@blocksuite/affine-block-table/view'; import { TableViewExtension } from '@blocksuite/affine-block-table/view';
import { FoundationViewExtension } from '@blocksuite/affine-foundation/view'; import { FoundationViewExtension } from '@blocksuite/affine-foundation/view';
import { AdapterPanelViewExtension } from '@blocksuite/affine-fragment-adapter-panel/view';
import { DocTitleViewExtension } from '@blocksuite/affine-fragment-doc-title/view';
import { FramePanelViewExtension } from '@blocksuite/affine-fragment-frame-panel/view';
import { OutlineViewExtension } from '@blocksuite/affine-fragment-outline/view';
import { BrushViewExtension } from '@blocksuite/affine-gfx-brush/view'; import { BrushViewExtension } from '@blocksuite/affine-gfx-brush/view';
import { ConnectorViewExtension } from '@blocksuite/affine-gfx-connector/view'; import { ConnectorViewExtension } from '@blocksuite/affine-gfx-connector/view';
import { GroupViewExtension } from '@blocksuite/affine-gfx-group/view'; import { GroupViewExtension } from '@blocksuite/affine-gfx-group/view';
@@ -33,7 +27,6 @@ import { PointerViewExtension } from '@blocksuite/affine-gfx-pointer/view';
import { ShapeViewExtension } from '@blocksuite/affine-gfx-shape/view'; import { ShapeViewExtension } from '@blocksuite/affine-gfx-shape/view';
import { TemplateViewExtension } from '@blocksuite/affine-gfx-template/view'; import { TemplateViewExtension } from '@blocksuite/affine-gfx-template/view';
import { TextViewExtension } from '@blocksuite/affine-gfx-text/view'; import { TextViewExtension } from '@blocksuite/affine-gfx-text/view';
import { InlineCommentViewExtension } from '@blocksuite/affine-inline-comment/view';
import { FootnoteViewExtension } from '@blocksuite/affine-inline-footnote/view'; import { FootnoteViewExtension } from '@blocksuite/affine-inline-footnote/view';
import { LatexViewExtension as InlineLatexViewExtension } from '@blocksuite/affine-inline-latex/view'; import { LatexViewExtension as InlineLatexViewExtension } from '@blocksuite/affine-inline-latex/view';
import { LinkViewExtension } from '@blocksuite/affine-inline-link/view'; import { LinkViewExtension } from '@blocksuite/affine-inline-link/view';
@@ -42,14 +35,11 @@ import { InlinePresetViewExtension } from '@blocksuite/affine-inline-preset/view
import { ReferenceViewExtension } from '@blocksuite/affine-inline-reference/view'; import { ReferenceViewExtension } from '@blocksuite/affine-inline-reference/view';
import { DragHandleViewExtension } from '@blocksuite/affine-widget-drag-handle/view'; import { DragHandleViewExtension } from '@blocksuite/affine-widget-drag-handle/view';
import { EdgelessAutoConnectViewExtension } from '@blocksuite/affine-widget-edgeless-auto-connect/view'; import { EdgelessAutoConnectViewExtension } from '@blocksuite/affine-widget-edgeless-auto-connect/view';
import { EdgelessDraggingAreaViewExtension } from '@blocksuite/affine-widget-edgeless-dragging-area/view';
import { EdgelessSelectedRectViewExtension } from '@blocksuite/affine-widget-edgeless-selected-rect/view';
import { EdgelessToolbarViewExtension } from '@blocksuite/affine-widget-edgeless-toolbar/view'; import { EdgelessToolbarViewExtension } from '@blocksuite/affine-widget-edgeless-toolbar/view';
import { EdgelessZoomToolbarViewExtension } from '@blocksuite/affine-widget-edgeless-zoom-toolbar/view'; import { EdgelessZoomToolbarViewExtension } from '@blocksuite/affine-widget-edgeless-zoom-toolbar/view';
import { FrameTitleViewExtension } from '@blocksuite/affine-widget-frame-title/view'; import { FrameTitleViewExtension } from '@blocksuite/affine-widget-frame-title/view';
import { KeyboardToolbarViewExtension } from '@blocksuite/affine-widget-keyboard-toolbar/view'; import { KeyboardToolbarViewExtension } from '@blocksuite/affine-widget-keyboard-toolbar/view';
import { LinkedDocViewExtension } from '@blocksuite/affine-widget-linked-doc/view'; import { LinkedDocViewExtension } from '@blocksuite/affine-widget-linked-doc/view';
import { NoteSlicerViewExtension } from '@blocksuite/affine-widget-note-slicer/view';
import { PageDraggingAreaViewExtension } from '@blocksuite/affine-widget-page-dragging-area/view'; import { PageDraggingAreaViewExtension } from '@blocksuite/affine-widget-page-dragging-area/view';
import { RemoteSelectionViewExtension } from '@blocksuite/affine-widget-remote-selection/view'; import { RemoteSelectionViewExtension } from '@blocksuite/affine-widget-remote-selection/view';
import { ScrollAnchoringViewExtension } from '@blocksuite/affine-widget-scroll-anchoring/view'; import { ScrollAnchoringViewExtension } from '@blocksuite/affine-widget-scroll-anchoring/view';
@@ -57,6 +47,8 @@ import { SlashMenuViewExtension } from '@blocksuite/affine-widget-slash-menu/vie
import { ToolbarViewExtension } from '@blocksuite/affine-widget-toolbar/view'; import { ToolbarViewExtension } from '@blocksuite/affine-widget-toolbar/view';
import { ViewportOverlayViewExtension } from '@blocksuite/affine-widget-viewport-overlay/view'; import { ViewportOverlayViewExtension } from '@blocksuite/affine-widget-viewport-overlay/view';
import { MigratingViewExtension } from './migrating-view';
export function getInternalViewExtensions() { export function getInternalViewExtensions() {
return [ return [
FoundationViewExtension, FoundationViewExtension,
@@ -83,7 +75,6 @@ export function getInternalViewExtensions() {
DividerViewExtension, DividerViewExtension,
EdgelessTextViewExtension, EdgelessTextViewExtension,
EmbedViewExtension, EmbedViewExtension,
EmbedDocViewExtension,
FrameViewExtension, FrameViewExtension,
ImageViewExtension, ImageViewExtension,
LatexViewExtension, LatexViewExtension,
@@ -93,10 +84,8 @@ export function getInternalViewExtensions() {
SurfaceRefViewExtension, SurfaceRefViewExtension,
TableViewExtension, TableViewExtension,
SurfaceViewExtension, SurfaceViewExtension,
RootViewExtension,
// Inline // Inline
InlineCommentViewExtension,
FootnoteViewExtension, FootnoteViewExtension,
LinkViewExtension, LinkViewExtension,
ReferenceViewExtension, ReferenceViewExtension,
@@ -105,9 +94,10 @@ export function getInternalViewExtensions() {
InlinePresetViewExtension, InlinePresetViewExtension,
// Widget // Widget
// order will affect the z-index of the widget
DragHandleViewExtension, DragHandleViewExtension,
EdgelessAutoConnectViewExtension, EdgelessAutoConnectViewExtension,
EdgelessToolbarViewExtension,
MigratingViewExtension,
FrameTitleViewExtension, FrameTitleViewExtension,
KeyboardToolbarViewExtension, KeyboardToolbarViewExtension,
LinkedDocViewExtension, LinkedDocViewExtension,
@@ -118,15 +108,5 @@ export function getInternalViewExtensions() {
ViewportOverlayViewExtension, ViewportOverlayViewExtension,
EdgelessZoomToolbarViewExtension, EdgelessZoomToolbarViewExtension,
PageDraggingAreaViewExtension, PageDraggingAreaViewExtension,
EdgelessSelectedRectViewExtension,
EdgelessDraggingAreaViewExtension,
NoteSlicerViewExtension,
EdgelessToolbarViewExtension,
// Fragment
DocTitleViewExtension,
FramePanelViewExtension,
OutlineViewExtension,
AdapterPanelViewExtension,
]; ];
} }
@@ -1 +0,0 @@
export * from '@blocksuite/affine-foundation/clipboard';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-foundation/store';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-foundation/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-fragment-adapter-panel';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-fragment-adapter-panel/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-fragment-doc-title/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-fragment-frame-panel/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-fragment-outline/view';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-inline-comment';
@@ -1 +0,0 @@
export * from '@blocksuite/affine-widget-edgeless-dragging-area';

Some files were not shown because too many files have changed in this diff Show More