mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-11 03:48:39 +00:00
Compare commits
1 Commits
v2026.2.6-
...
eyhn/init-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b2678b8448 |
@@ -1,21 +1,2 @@
|
|||||||
[target.x86_64-pc-windows-msvc]
|
[target.x86_64-pc-windows-msvc]
|
||||||
rustflags = ["-C", "target-feature=+crt-static"]
|
rustflags = ["-C", "target-feature=+crt-static"]
|
||||||
[target.aarch64-pc-windows-msvc]
|
|
||||||
rustflags = ["-C", "target-feature=+crt-static"]
|
|
||||||
[target.'cfg(target_os = "linux")']
|
|
||||||
rustflags = ["-C", "link-args=-Wl,--warn-unresolved-symbols"]
|
|
||||||
[target.'cfg(target_os = "macos")']
|
|
||||||
rustflags = [
|
|
||||||
"-C",
|
|
||||||
"link-args=-Wl,-undefined,dynamic_lookup,-no_fixup_chains",
|
|
||||||
"-C",
|
|
||||||
"link-args=-all_load",
|
|
||||||
"-C",
|
|
||||||
"link-args=-weak_framework ScreenCaptureKit",
|
|
||||||
]
|
|
||||||
# https://sourceware.org/bugzilla/show_bug.cgi?id=21032
|
|
||||||
# https://sourceware.org/bugzilla/show_bug.cgi?id=21031
|
|
||||||
# https://github.com/rust-lang/rust/issues/134820
|
|
||||||
# pthread_key_create() destructors and segfault after a DSO unloading
|
|
||||||
[target.'cfg(all(target_env = "gnu", not(target_os = "windows")))']
|
|
||||||
rustflags = ["-C", "link-args=-Wl,-z,nodelete"]
|
|
||||||
|
|||||||
9
.devcontainer/Dockerfile
Normal file
9
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
FROM mcr.microsoft.com/devcontainers/base:bookworm
|
||||||
|
|
||||||
|
# Install Homebrew For Linux
|
||||||
|
RUN /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)" && \
|
||||||
|
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)" && \
|
||||||
|
echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> /home/vscode/.zshrc && \
|
||||||
|
echo "eval \"\$($(brew --prefix)/bin/brew shellenv)\"" >> /home/vscode/.bashrc && \
|
||||||
|
# Install Graphite
|
||||||
|
brew install withgraphite/tap/graphite && gt --version
|
||||||
@@ -1,11 +1,18 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# This is a script used by the devcontainer to build the project
|
# This is a script used by the devcontainer to build the project
|
||||||
|
|
||||||
|
#Enable yarn
|
||||||
|
corepack enable
|
||||||
|
corepack prepare yarn@stable --activate
|
||||||
|
|
||||||
# install dependencies
|
# install dependencies
|
||||||
yarn install
|
yarn install
|
||||||
|
|
||||||
# Build Server Dependencies
|
# Build Server Dependencies
|
||||||
yarn affine @affine/server-native build
|
yarn workspace @affine/server-native build
|
||||||
|
|
||||||
# Create database
|
# Create database
|
||||||
yarn affine @affine/server prisma migrate reset -f
|
yarn workspace @affine/server prisma db push
|
||||||
|
|
||||||
|
# Create user username: affine, password: affine
|
||||||
|
echo "INSERT INTO \"users\"(\"id\",\"name\",\"email\",\"email_verified\",\"created_at\",\"password\") VALUES('99f3ad04-7c9b-441e-a6db-79f73aa64db9','affine','affine@affine.pro','2024-02-26 15:54:16.974','2024-02-26 15:54:16.974+00','\$argon2id\$v=19\$m=19456,t=2,p=1\$esDS3QCHRH0Kmeh87YPm5Q\$9S+jf+xzw2Hicj6nkWltvaaaXX3dQIxAFwCfFa9o38A');" | yarn workspace @affine/server prisma db execute --stdin
|
||||||
|
|||||||
@@ -1,16 +1,12 @@
|
|||||||
// For format details, see https://aka.ms/devcontainer.json.
|
// For format details, see https://aka.ms/devcontainer.json.
|
||||||
{
|
{
|
||||||
"name": "AFFiNE Dev Container",
|
"name": "Debian",
|
||||||
"dockerComposeFile": "docker-compose.yml",
|
"dockerComposeFile": "docker-compose.yml",
|
||||||
"service": "app",
|
"service": "app",
|
||||||
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
"workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}",
|
||||||
"containerEnv": {
|
|
||||||
"COREPACK_ENABLE_DOWNLOAD_PROMPT": "0"
|
|
||||||
},
|
|
||||||
"features": {
|
"features": {
|
||||||
"ghcr.io/devcontainers/features/node:1": {
|
"ghcr.io/devcontainers/features/node:1": {
|
||||||
"version": "lts",
|
"version": "18"
|
||||||
"installYarnUsingApt": false
|
|
||||||
},
|
},
|
||||||
"ghcr.io/devcontainers/features/rust:1": {}
|
"ghcr.io/devcontainers/features/rust:1": {}
|
||||||
},
|
},
|
||||||
@@ -20,10 +16,11 @@
|
|||||||
"extensions": [
|
"extensions": [
|
||||||
"ms-playwright.playwright",
|
"ms-playwright.playwright",
|
||||||
"esbenp.prettier-vscode",
|
"esbenp.prettier-vscode",
|
||||||
"dbaeumer.vscode-eslint"
|
"streetsidesoftware.code-spell-checker"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"updateContentCommand": "bash ./.devcontainer/build.sh",
|
"updateContentCommand": "bash ./.devcontainer/build.sh",
|
||||||
"postCreateCommand": "bash ./.devcontainer/setup-user.sh"
|
"postCreateCommand": "bash ./.devcontainer/setup-user.sh",
|
||||||
|
"postStartCommand": ["yarn dev", "yarn workspace @affine/server dev"]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,20 +2,18 @@ version: '3.8'
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
app:
|
app:
|
||||||
security_opt:
|
build:
|
||||||
- no-new-privileges:true
|
context: .
|
||||||
image: mcr.microsoft.com/devcontainers/base:bookworm
|
dockerfile: Dockerfile
|
||||||
volumes:
|
volumes:
|
||||||
- ../..:/workspaces:cached
|
- ../..:/workspaces:cached
|
||||||
command: sleep infinity
|
command: sleep infinity
|
||||||
network_mode: service:db
|
network_mode: service:db
|
||||||
environment:
|
environment:
|
||||||
DATABASE_URL: postgresql://affine:affine@db:5432/affine
|
DATABASE_URL: postgresql://affine:affine@db:5432/affine
|
||||||
REDIS_SERVER_HOST: redis
|
|
||||||
AFFINE_INDEXER_SEARCH_ENDPOINT: http://indexer:9308
|
|
||||||
|
|
||||||
db:
|
db:
|
||||||
image: pgvector/pgvector:pg16
|
image: postgres:latest
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
volumes:
|
volumes:
|
||||||
- postgres-data:/var/lib/postgresql/data
|
- postgres-data:/var/lib/postgresql/data
|
||||||
@@ -23,22 +21,6 @@ services:
|
|||||||
POSTGRES_PASSWORD: affine
|
POSTGRES_PASSWORD: affine
|
||||||
POSTGRES_USER: affine
|
POSTGRES_USER: affine
|
||||||
POSTGRES_DB: affine
|
POSTGRES_DB: affine
|
||||||
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,9 +1,9 @@
|
|||||||
set -e
|
set -e
|
||||||
|
|
||||||
npm install -g @withgraphite/graphite-cli@stable
|
|
||||||
|
|
||||||
if [ -v GRAPHITE_TOKEN ];then
|
if [ -v GRAPHITE_TOKEN ];then
|
||||||
gt auth --token $GRAPHITE_TOKEN
|
gt auth --token $GRAPHITE_TOKEN
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
git fetch origin canary:canary --depth=1
|
||||||
|
git branch canary -t origin/canary
|
||||||
gt init --trunk canary
|
gt init --trunk canary
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
# postgres major version
|
|
||||||
DB_VERSION=16
|
|
||||||
# database credentials
|
|
||||||
DB_PASSWORD=affine
|
|
||||||
DB_USERNAME=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
|
|
||||||
6
.docker/dev/.gitignore
vendored
6
.docker/dev/.gitignore
vendored
@@ -1,6 +0,0 @@
|
|||||||
postgres
|
|
||||||
.env
|
|
||||||
compose.yml
|
|
||||||
certs/*
|
|
||||||
!certs/.gitkeep
|
|
||||||
nginx/conf.d/*
|
|
||||||
@@ -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
|
|
||||||
@@ -1,99 +0,0 @@
|
|||||||
name: affine_dev_services
|
|
||||||
services:
|
|
||||||
postgres:
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
image: pgvector/pgvector:pg${DB_VERSION:-16}
|
|
||||||
ports:
|
|
||||||
- 5432:5432
|
|
||||||
environment:
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
||||||
POSTGRES_USER: ${DB_USERNAME}
|
|
||||||
POSTGRES_DB: ${DB_DATABASE_NAME}
|
|
||||||
volumes:
|
|
||||||
- postgres_data:/var/lib/postgresql/data
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis:latest
|
|
||||||
ports:
|
|
||||||
- 6379:6379
|
|
||||||
|
|
||||||
# https://mailpit.axllent.org/docs/install/docker/
|
|
||||||
mailpit:
|
|
||||||
image: axllent/mailpit:latest
|
|
||||||
ports:
|
|
||||||
- 1025:1025
|
|
||||||
- 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:
|
|
||||||
dev:
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
postgres_data:
|
|
||||||
manticoresearch_data:
|
|
||||||
mailpit_data:
|
|
||||||
elasticsearch_data:
|
|
||||||
@@ -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/*";
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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,23 +0,0 @@
|
|||||||
# select a revision to deploy, available values: stable, beta, canary
|
|
||||||
AFFINE_REVISION=stable
|
|
||||||
|
|
||||||
# set the port for the server container it will expose the server on
|
|
||||||
PORT=3010
|
|
||||||
|
|
||||||
# set the host for the server for outgoing links
|
|
||||||
# AFFINE_SERVER_HTTPS=true
|
|
||||||
# AFFINE_SERVER_HOST=affine.yourdomain.com
|
|
||||||
# or
|
|
||||||
# AFFINE_SERVER_EXTERNAL_URL=https://affine.yourdomain.com
|
|
||||||
|
|
||||||
# position of the database data to persist
|
|
||||||
DB_DATA_LOCATION=~/.affine/self-host/postgres/pgdata
|
|
||||||
# position of the upload data(images, files, etc.) to persist
|
|
||||||
UPLOAD_LOCATION=~/.affine/self-host/storage
|
|
||||||
# position of the configuration files to persist
|
|
||||||
CONFIG_LOCATION=~/.affine/self-host/config
|
|
||||||
|
|
||||||
# database credentials
|
|
||||||
DB_USERNAME=affine
|
|
||||||
DB_PASSWORD=
|
|
||||||
DB_DATABASE=affine
|
|
||||||
1
.docker/selfhost/.gitignore
vendored
1
.docker/selfhost/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
.env
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
name: affine
|
|
||||||
services:
|
|
||||||
affine:
|
|
||||||
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
|
|
||||||
container_name: affine_server
|
|
||||||
ports:
|
|
||||||
- '${PORT:-3010}:3010'
|
|
||||||
depends_on:
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
affine_migration:
|
|
||||||
condition: service_completed_successfully
|
|
||||||
volumes:
|
|
||||||
# custom configurations
|
|
||||||
- ${UPLOAD_LOCATION}:/root/.affine/storage
|
|
||||||
- ${CONFIG_LOCATION}:/root/.affine/config
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
- REDIS_SERVER_HOST=redis
|
|
||||||
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
|
|
||||||
- AFFINE_INDEXER_ENABLED=false
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
affine_migration:
|
|
||||||
image: ghcr.io/toeverything/affine:${AFFINE_REVISION:-stable}
|
|
||||||
container_name: affine_migration_job
|
|
||||||
volumes:
|
|
||||||
# custom configurations
|
|
||||||
- ${UPLOAD_LOCATION}:/root/.affine/storage
|
|
||||||
- ${CONFIG_LOCATION}:/root/.affine/config
|
|
||||||
command: ['sh', '-c', 'node ./scripts/self-host-predeploy.js']
|
|
||||||
env_file:
|
|
||||||
- .env
|
|
||||||
environment:
|
|
||||||
- REDIS_SERVER_HOST=redis
|
|
||||||
- DATABASE_URL=postgresql://${DB_USERNAME}:${DB_PASSWORD}@postgres:5432/${DB_DATABASE:-affine}
|
|
||||||
- AFFINE_INDEXER_ENABLED=false
|
|
||||||
depends_on:
|
|
||||||
postgres:
|
|
||||||
condition: service_healthy
|
|
||||||
redis:
|
|
||||||
condition: service_healthy
|
|
||||||
|
|
||||||
redis:
|
|
||||||
image: redis
|
|
||||||
container_name: affine_redis
|
|
||||||
healthcheck:
|
|
||||||
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
postgres:
|
|
||||||
image: pgvector/pgvector:pg16
|
|
||||||
container_name: affine_postgres
|
|
||||||
volumes:
|
|
||||||
- ${DB_DATA_LOCATION}:/var/lib/postgresql/data
|
|
||||||
environment:
|
|
||||||
POSTGRES_USER: ${DB_USERNAME}
|
|
||||||
POSTGRES_PASSWORD: ${DB_PASSWORD}
|
|
||||||
POSTGRES_DB: ${DB_DATABASE:-affine}
|
|
||||||
POSTGRES_INITDB_ARGS: '--data-checksums'
|
|
||||||
# you better set a password for you database
|
|
||||||
# or you may add 'POSTGRES_HOST_AUTH_METHOD=trust' to ignore postgres security policy
|
|
||||||
POSTGRES_HOST_AUTH_METHOD: trust
|
|
||||||
healthcheck:
|
|
||||||
test:
|
|
||||||
['CMD', 'pg_isready', '-U', "${DB_USERNAME}", '-d', "${DB_DATABASE:-affine}"]
|
|
||||||
interval: 10s
|
|
||||||
timeout: 5s
|
|
||||||
retries: 5
|
|
||||||
restart: unless-stopped
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
{
|
|
||||||
"$schema": "https://github.com/toeverything/affine/releases/latest/download/config.schema.json",
|
|
||||||
"server": {
|
|
||||||
"name": "AFFiNE Self Hosted Server"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,6 @@
|
|||||||
# Editor configuration, see http://editorconfig.org
|
# Editor configuration, see http://editorconfig.org
|
||||||
root = true
|
root = true
|
||||||
|
|
||||||
[*.rs]
|
|
||||||
max_line_length = 120
|
|
||||||
[*]
|
[*]
|
||||||
charset = utf-8
|
charset = utf-8
|
||||||
indent_style = space
|
indent_style = space
|
||||||
|
|||||||
8
.env.template
Normal file
8
.env.template
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
CHANGELOG_URL=
|
||||||
|
ENABLE_PRELOADING=
|
||||||
|
ENABLE_NEW_SETTING_UNSTABLE_API=
|
||||||
|
ENABLE_CAPTCHA=
|
||||||
|
CAPTCHA_SITE_KEY=
|
||||||
|
ENABLE_ENHANCE_SHARE_MODE=
|
||||||
|
ALLOW_LOCAL_WORKSPACE=
|
||||||
|
DEBUG_JOTAI=
|
||||||
15
.eslintignore
Normal file
15
.eslintignore
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
node_modules
|
||||||
|
dist
|
||||||
|
.next
|
||||||
|
out
|
||||||
|
storybook-static
|
||||||
|
affine-out
|
||||||
|
_next
|
||||||
|
lib
|
||||||
|
.eslintrc.js
|
||||||
|
e2e-dist-*
|
||||||
|
static
|
||||||
|
web-static
|
||||||
|
public
|
||||||
|
packages/frontend/i18n/src/i18n-generated.ts
|
||||||
|
packages/frontend/templates/*.gen.ts
|
||||||
285
.eslintrc.js
Normal file
285
.eslintrc.js
Normal file
@@ -0,0 +1,285 @@
|
|||||||
|
const { join } = require('node:path');
|
||||||
|
|
||||||
|
const createPattern = packageName => [
|
||||||
|
{
|
||||||
|
group: ['**/dist', '**/dist/**'],
|
||||||
|
message: 'Do not import from dist',
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['**/src', '**/src/**'],
|
||||||
|
message: 'Do not import from src',
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: [`@affine/${packageName}`],
|
||||||
|
message: 'Do not import package itself',
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: [`@toeverything/${packageName}`],
|
||||||
|
message: 'Do not import package itself',
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['@blocksuite/store'],
|
||||||
|
message: "Import from '@blocksuite/global/utils'",
|
||||||
|
importNames: ['assertExists', 'assertEquals'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['react-router-dom'],
|
||||||
|
message: 'Use `useNavigateHelper` instead',
|
||||||
|
importNames: ['useNavigate'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['@affine/env/constant'],
|
||||||
|
message:
|
||||||
|
'Do not import from @affine/env/constant. Use `environment.isDesktop` instead',
|
||||||
|
importNames: ['isDesktop'],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const allPackages = [
|
||||||
|
'packages/backend/server',
|
||||||
|
'packages/frontend/component',
|
||||||
|
'packages/frontend/core',
|
||||||
|
'packages/frontend/electron',
|
||||||
|
'packages/frontend/graphql',
|
||||||
|
'packages/frontend/i18n',
|
||||||
|
'packages/frontend/native',
|
||||||
|
'packages/frontend/templates',
|
||||||
|
'packages/common/debug',
|
||||||
|
'packages/common/env',
|
||||||
|
'packages/common/infra',
|
||||||
|
'packages/common/theme',
|
||||||
|
'tools/cli',
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @type {import('eslint').Linter.Config}
|
||||||
|
*/
|
||||||
|
const config = {
|
||||||
|
root: true,
|
||||||
|
settings: {
|
||||||
|
react: {
|
||||||
|
version: 'detect',
|
||||||
|
},
|
||||||
|
next: {
|
||||||
|
rootDir: 'packages/frontend/core',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
|
'plugin:react/recommended',
|
||||||
|
'plugin:react/jsx-runtime',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'prettier',
|
||||||
|
],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
globalReturn: false,
|
||||||
|
impliedStrict: true,
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
ecmaVersion: 'latest',
|
||||||
|
sourceType: 'module',
|
||||||
|
project: join(__dirname, 'tsconfig.eslint.json'),
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
'react',
|
||||||
|
'@typescript-eslint',
|
||||||
|
'simple-import-sort',
|
||||||
|
'sonarjs',
|
||||||
|
'import-x',
|
||||||
|
'unused-imports',
|
||||||
|
'unicorn',
|
||||||
|
'rxjs',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'array-callback-return': 'error',
|
||||||
|
'no-undef': 'off',
|
||||||
|
'no-empty': 'off',
|
||||||
|
'no-func-assign': 'off',
|
||||||
|
'no-cond-assign': 'off',
|
||||||
|
'no-constant-binary-expression': 'error',
|
||||||
|
'no-constructor-return': 'error',
|
||||||
|
'no-self-compare': 'error',
|
||||||
|
eqeqeq: ['error', 'always', { null: 'ignore' }],
|
||||||
|
'react/prop-types': 'off',
|
||||||
|
'react/jsx-no-useless-fragment': 'error',
|
||||||
|
'@typescript-eslint/consistent-type-imports': 'error',
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 'error',
|
||||||
|
'@typescript-eslint/no-explicit-any': 'off',
|
||||||
|
'@typescript-eslint/no-empty-function': 'off',
|
||||||
|
'@typescript-eslint/await-thenable': 'error',
|
||||||
|
'@typescript-eslint/require-array-sort-compare': 'error',
|
||||||
|
'@typescript-eslint/unified-signatures': 'error',
|
||||||
|
'@typescript-eslint/prefer-for-of': 'error',
|
||||||
|
'@typescript-eslint/no-unused-vars': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
varsIgnorePattern: '^_',
|
||||||
|
argsIgnorePattern: '^_',
|
||||||
|
caughtErrorsIgnorePattern: '^_',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unused-imports/no-unused-imports': 'error',
|
||||||
|
'simple-import-sort/imports': 'error',
|
||||||
|
'simple-import-sort/exports': 'error',
|
||||||
|
'import-x/no-duplicates': 'error',
|
||||||
|
'@typescript-eslint/ban-ts-comment': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'ts-expect-error': 'allow-with-description',
|
||||||
|
'ts-ignore': true,
|
||||||
|
'ts-nocheck': true,
|
||||||
|
'ts-check': false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
patterns: [
|
||||||
|
{
|
||||||
|
group: ['**/dist'],
|
||||||
|
message: "Don't import from dist",
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['**/src'],
|
||||||
|
message: "Don't import from src",
|
||||||
|
allowTypeImports: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
group: ['@blocksuite/store'],
|
||||||
|
message: "Import from '@blocksuite/global/utils'",
|
||||||
|
importNames: ['assertExists', 'assertEquals'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unicorn/filename-case': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
case: 'kebabCase',
|
||||||
|
ignore: ['^\\[[a-zA-Z0-9-_]+\\]\\.tsx$'],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'unicorn/no-unnecessary-await': 'error',
|
||||||
|
'unicorn/no-useless-fallback-in-spread': 'error',
|
||||||
|
'unicorn/prefer-dom-node-dataset': 'error',
|
||||||
|
'unicorn/prefer-dom-node-append': 'error',
|
||||||
|
'unicorn/prefer-dom-node-remove': 'error',
|
||||||
|
'unicorn/prefer-array-some': 'error',
|
||||||
|
'unicorn/prefer-date-now': 'error',
|
||||||
|
'unicorn/prefer-blob-reading-methods': 'error',
|
||||||
|
'unicorn/no-typeof-undefined': 'error',
|
||||||
|
'unicorn/no-useless-promise-resolve-reject': 'error',
|
||||||
|
'unicorn/no-new-array': 'error',
|
||||||
|
'unicorn/new-for-builtins': 'error',
|
||||||
|
'unicorn/prefer-node-protocol': 'error',
|
||||||
|
'sonarjs/no-all-duplicated-branches': 'error',
|
||||||
|
'sonarjs/no-element-overwrite': 'error',
|
||||||
|
'sonarjs/no-empty-collection': 'error',
|
||||||
|
'sonarjs/no-extra-arguments': 'error',
|
||||||
|
'sonarjs/no-identical-conditions': 'error',
|
||||||
|
'sonarjs/no-identical-expressions': 'error',
|
||||||
|
'sonarjs/no-ignored-return': 'error',
|
||||||
|
'sonarjs/no-one-iteration-loop': 'error',
|
||||||
|
'sonarjs/no-use-of-empty-return-value': 'error',
|
||||||
|
'sonarjs/non-existent-operator': 'error',
|
||||||
|
'sonarjs/no-collapsible-if': 'error',
|
||||||
|
'sonarjs/no-same-line-conditional': 'error',
|
||||||
|
'sonarjs/no-duplicated-branches': 'error',
|
||||||
|
'sonarjs/no-collection-size-mischeck': 'error',
|
||||||
|
'sonarjs/no-useless-catch': 'error',
|
||||||
|
'sonarjs/no-identical-functions': 'error',
|
||||||
|
'rxjs/finnish': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
functions: false,
|
||||||
|
methods: false,
|
||||||
|
strict: true,
|
||||||
|
types: {
|
||||||
|
'^LiveData$': true,
|
||||||
|
// some yjs classes are Observables, but they don't need to be in Finnish notation
|
||||||
|
'^Doc$': false, // yjs Doc
|
||||||
|
'^Awareness$': false, // yjs Awareness
|
||||||
|
'^UndoManager$': false, // yjs UndoManager
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: 'packages/backend/server/**/*.ts',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/consistent-type-imports': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: '*.cjs',
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-var-requires': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
...allPackages.map(pkg => ({
|
||||||
|
files: [`${pkg}/src/**/*.ts`, `${pkg}/src/**/*.tsx`, `${pkg}/**/*.mjs`],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-restricted-imports': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
patterns: createPattern(pkg),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-floating-promises': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
ignoreVoid: false,
|
||||||
|
ignoreIIFE: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-misused-promises': ['error'],
|
||||||
|
'@typescript-eslint/prefer-readonly': 'error',
|
||||||
|
'import-x/no-extraneous-dependencies': ['error'],
|
||||||
|
'react-hooks/exhaustive-deps': [
|
||||||
|
'warn',
|
||||||
|
{
|
||||||
|
additionalHooks: '(useAsyncCallback|useDraggable|useDropTarget)',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
{
|
||||||
|
files: [
|
||||||
|
'**/__tests__/**/*',
|
||||||
|
'**/*.stories.tsx',
|
||||||
|
'**/*.spec.ts',
|
||||||
|
'**/tests/**/*',
|
||||||
|
'scripts/**/*',
|
||||||
|
'**/benchmark/**/*',
|
||||||
|
'**/__debug__/**/*',
|
||||||
|
'**/e2e/**/*',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
'@typescript-eslint/no-non-null-assertion': 0,
|
||||||
|
'@typescript-eslint/ban-ts-comment': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'ts-expect-error': false,
|
||||||
|
'ts-ignore': true,
|
||||||
|
'ts-nocheck': true,
|
||||||
|
'ts-check': false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'@typescript-eslint/no-floating-promises': 0,
|
||||||
|
'@typescript-eslint/no-misused-promises': 0,
|
||||||
|
'@typescript-eslint/no-restricted-imports': 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = config;
|
||||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1,2 +0,0 @@
|
|||||||
/blocksuite/ @toeverything/blocksuite-core
|
|
||||||
/packages/frontend/core/src/blocksuite @toeverything/blocksuite-core
|
|
||||||
|
|||||||
31
.github/ISSUE_TEMPLATE/BUG-REPORT.yml
vendored
31
.github/ISSUE_TEMPLATE/BUG-REPORT.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: Bug Report
|
name: Bug Report
|
||||||
description: File a bug report
|
description: File a bug report
|
||||||
title: '[Bug]: '
|
title: "\u200b"
|
||||||
labels: ['bug']
|
labels: ['bug']
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
@@ -18,26 +18,20 @@ body:
|
|||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: distribution
|
id: version
|
||||||
attributes:
|
attributes:
|
||||||
label: Distribution version
|
label: Distribution version
|
||||||
description: What distribution of AFFiNE are you using?
|
description: What version of AFFiNE are you using?
|
||||||
options:
|
options:
|
||||||
- macOS x64 (Intel)
|
- macOS x64 (Intel)
|
||||||
- macOS ARM 64 (Apple Silicon)
|
- macOS ARM 64 (Apple Silicon)
|
||||||
- Windows x64
|
- Windows x64
|
||||||
- Linux
|
- Linux
|
||||||
- Web (https://app.affine.pro)
|
- Web (app.affine.pro)
|
||||||
- Beta Web (https://insider.affine.pro)
|
- Web (affine.fail)
|
||||||
- Canary Web (https://affine.fail)
|
- Web (insider.affine.pro)
|
||||||
validations:
|
validations:
|
||||||
required: true
|
required: true
|
||||||
- type: input
|
|
||||||
id: version
|
|
||||||
attributes:
|
|
||||||
label: App Version
|
|
||||||
description: What version of AFFiNE are you using?
|
|
||||||
placeholder: (You can find AFFiNE version in [About AFFiNE] setting panel)
|
|
||||||
- type: dropdown
|
- type: dropdown
|
||||||
id: browsers
|
id: browsers
|
||||||
attributes:
|
attributes:
|
||||||
@@ -57,11 +51,6 @@ body:
|
|||||||
If you are self-hosting, please check the box and provide information about your setup.
|
If you are self-hosting, please check the box and provide information about your setup.
|
||||||
options:
|
options:
|
||||||
- label: 'Yes'
|
- label: 'Yes'
|
||||||
- type: input
|
|
||||||
id: selfhost-version
|
|
||||||
attributes:
|
|
||||||
label: Self-hosting Version
|
|
||||||
description: What version of AFFiNE are you selfhosting?
|
|
||||||
- type: textarea
|
- type: textarea
|
||||||
id: logs
|
id: logs
|
||||||
attributes:
|
attributes:
|
||||||
@@ -74,11 +63,3 @@ body:
|
|||||||
description: |
|
description: |
|
||||||
Links? References? Anything that will give us more context about the issue you are encountering!
|
Links? References? Anything that will give us more context about the issue you are encountering!
|
||||||
Tip: You can attach images here
|
Tip: You can attach images here
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is your content generated by AI?
|
|
||||||
description: >
|
|
||||||
(Required) Please confirm that the content you submit was not generated by AI or only minimally edited by AI.
|
|
||||||
If an administrator believes the post contains a large amount of AI-generated content, they may directly close the question.
|
|
||||||
options:
|
|
||||||
- label: I confirm that the content I submitted was **not** generated by AI / **merely contained minimal** AI edits.
|
|
||||||
|
|||||||
10
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
10
.github/ISSUE_TEMPLATE/FEATURE-REQUEST.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
name: Feature Request
|
name: Feature Request
|
||||||
description: Suggest a feature or improvement
|
description: Suggest a feature or improvement
|
||||||
title: '[Feature Request]: '
|
title: "\u200b"
|
||||||
labels: ['feat', 'story']
|
labels: ['feat', 'story']
|
||||||
body:
|
body:
|
||||||
- type: markdown
|
- type: markdown
|
||||||
@@ -34,11 +34,3 @@ body:
|
|||||||
See the AFFiNE [Contributing Guide](https://github.com/toeverything/affine/blob/canary/CONTRIBUTING.md) to get started.
|
See the AFFiNE [Contributing Guide](https://github.com/toeverything/affine/blob/canary/CONTRIBUTING.md) to get started.
|
||||||
options:
|
options:
|
||||||
- label: Yes I'd like to help by submitting a PR!
|
- label: Yes I'd like to help by submitting a PR!
|
||||||
- type: checkboxes
|
|
||||||
attributes:
|
|
||||||
label: Is your content generated by AI?
|
|
||||||
description: >
|
|
||||||
(Required) Please confirm that the content you submit was not generated by AI or only minimally edited by AI.
|
|
||||||
If an administrator believes the post contains a large amount of AI-generated content, they may directly close the question.
|
|
||||||
options:
|
|
||||||
- label: I confirm that the content I submitted was **not** generated by AI / **merely contained minimal** AI edits.
|
|
||||||
|
|||||||
70
.github/actions/build-rust/action.yml
vendored
70
.github/actions/build-rust/action.yml
vendored
@@ -7,10 +7,9 @@ inputs:
|
|||||||
package:
|
package:
|
||||||
description: 'Package to build'
|
description: 'Package to build'
|
||||||
required: true
|
required: true
|
||||||
no-build:
|
nx_token:
|
||||||
description: 'Whether to skip building'
|
description: 'Nx Cloud access token'
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
@@ -18,78 +17,39 @@ runs:
|
|||||||
- name: Print rustup toolchain version
|
- name: Print rustup toolchain version
|
||||||
shell: bash
|
shell: bash
|
||||||
id: rustup-version
|
id: rustup-version
|
||||||
working-directory: ${{ env.DEV_DRIVE_WORKSPACE || github.workspace }}
|
|
||||||
run: |
|
run: |
|
||||||
export RUST_TOOLCHAIN_VERSION="$(grep 'channel' rust-toolchain.toml | head -1 | awk -F '"' '{print $2}')"
|
export RUST_TOOLCHAIN_VERSION="$(grep 'channel' rust-toolchain.toml | head -1 | awk -F '"' '{print $2}')"
|
||||||
echo "Rust toolchain version: $RUST_TOOLCHAIN_VERSION"
|
echo "Rust toolchain version: $RUST_TOOLCHAIN_VERSION"
|
||||||
echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> "$GITHUB_OUTPUT"
|
echo "RUST_TOOLCHAIN_VERSION=$RUST_TOOLCHAIN_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
- name: Setup Rust
|
- name: Setup Rust
|
||||||
uses: dtolnay/rust-toolchain@stable
|
uses: dtolnay/rust-toolchain@stable
|
||||||
if: ${{ runner.os != 'Windows' }}
|
|
||||||
with:
|
with:
|
||||||
toolchain: '${{ steps.rustup-version.outputs.RUST_TOOLCHAIN_VERSION }}'
|
toolchain: '${{ steps.rustup-version.outputs.RUST_TOOLCHAIN_VERSION }}'
|
||||||
targets: ${{ inputs.target }}
|
targets: ${{ inputs.target }}
|
||||||
env:
|
env:
|
||||||
CARGO_INCREMENTAL: '1'
|
CARGO_INCREMENTAL: '1'
|
||||||
|
|
||||||
- name: Setup Rust
|
|
||||||
uses: dtolnay/rust-toolchain@stable
|
|
||||||
if: ${{ runner.os == 'Windows' }}
|
|
||||||
with:
|
|
||||||
toolchain: '${{ steps.rustup-version.outputs.RUST_TOOLCHAIN_VERSION }}'
|
|
||||||
targets: ${{ inputs.target }}
|
|
||||||
env:
|
|
||||||
CARGO_INCREMENTAL: '1'
|
|
||||||
CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo
|
|
||||||
RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup
|
|
||||||
|
|
||||||
- name: Set CC
|
- name: Set CC
|
||||||
if: ${{ contains(inputs.target, 'linux') && inputs.no-build != 'true' }}
|
if: ${{ contains(inputs.target, 'linux') && inputs.package != '@affine/native' }}
|
||||||
working-directory: ${{ env.DEV_DRIVE_WORKSPACE || github.workspace }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
# https://github.com/tree-sitter/tree-sitter/issues/4186
|
|
||||||
# pass -D_BSD_SOURCE to clang to fix the tree-sitter build issue
|
|
||||||
run: |
|
run: |
|
||||||
echo "CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
echo "CC=clang" >> "$GITHUB_ENV"
|
||||||
echo "TARGET_CC=clang -D_BSD_SOURCE" >> "$GITHUB_ENV"
|
echo "TARGET_CC=clang" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
- name: Cache cargo
|
- name: Cache cargo
|
||||||
uses: Swatinem/rust-cache@v2
|
uses: actions/cache@v4
|
||||||
if: ${{ runner.os == 'Windows' }}
|
|
||||||
with:
|
with:
|
||||||
workspaces: ${{ env.DEV_DRIVE_WORKSPACE }}
|
path: |
|
||||||
save-if: ${{ github.ref_name == 'canary' }}
|
~/.cargo/registry/index/
|
||||||
shared-key: ${{ inputs.target }}-${{ inputs.package }}
|
~/.cargo/registry/cache/
|
||||||
env:
|
~/.cargo/git/db/
|
||||||
CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo
|
~/.napi-rs
|
||||||
RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup
|
target/${{ inputs.target }}
|
||||||
|
key: stable-${{ inputs.target }}-cargo-cache
|
||||||
- name: Cache cargo
|
|
||||||
uses: Swatinem/rust-cache@v2
|
|
||||||
if: ${{ runner.os != 'Windows' }}
|
|
||||||
with:
|
|
||||||
save-if: ${{ github.ref_name == 'canary' }}
|
|
||||||
shared-key: ${{ inputs.target }}-${{ inputs.package }}
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
if: ${{ runner.os != 'Windows' && inputs.no-build != 'true' }}
|
|
||||||
run: |
|
run: |
|
||||||
if [[ "${{ inputs.target }}" == "x86_64-unknown-linux-gnu" ]]; then
|
yarn workspace ${{ inputs.package }} nx build ${{ inputs.package }} -- --target ${{ inputs.target }} --use-napi-cross
|
||||||
yarn workspace ${{ inputs.package }} build --target ${{ inputs.target }}
|
|
||||||
else
|
|
||||||
yarn workspace ${{ inputs.package }} build --target ${{ inputs.target }} --use-napi-cross
|
|
||||||
fi
|
|
||||||
env:
|
env:
|
||||||
|
NX_CLOUD_ACCESS_TOKEN: ${{ inputs.nx_token }}
|
||||||
DEBUG: 'napi:*'
|
DEBUG: 'napi:*'
|
||||||
|
|
||||||
- name: Build
|
|
||||||
working-directory: ${{ env.DEV_DRIVE_WORKSPACE || github.workspace }}
|
|
||||||
shell: bash
|
|
||||||
if: ${{ runner.os == 'Windows' && inputs.no-build != 'true' }}
|
|
||||||
run: |
|
|
||||||
yarn workspace ${{ inputs.package }} build --target ${{ inputs.target }}
|
|
||||||
env:
|
|
||||||
DEBUG: 'napi:*'
|
|
||||||
CARGO_HOME: ${{ env.DEV_DRIVE }}/.cargo
|
|
||||||
RUSTUP_HOME: ${{ env.DEV_DRIVE }}/.rustup
|
|
||||||
|
|||||||
36
.github/actions/cluster-auth/action.yml
vendored
36
.github/actions/cluster-auth/action.yml
vendored
@@ -1,36 +0,0 @@
|
|||||||
name: 'Auth to Cluster'
|
|
||||||
description: 'Auth to the GCP Cluster'
|
|
||||||
inputs:
|
|
||||||
gcp-project-number:
|
|
||||||
description: 'GCP project number'
|
|
||||||
required: true
|
|
||||||
gcp-project-id:
|
|
||||||
description: 'GCP project id'
|
|
||||||
required: true
|
|
||||||
service-account:
|
|
||||||
description: 'Service account'
|
|
||||||
cluster-name:
|
|
||||||
description: 'Cluster name'
|
|
||||||
cluster-location:
|
|
||||||
description: 'Cluster location'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- id: auth
|
|
||||||
uses: google-github-actions/auth@v2
|
|
||||||
with:
|
|
||||||
workload_identity_provider: 'projects/${{ inputs.gcp-project-number }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy'
|
|
||||||
service_account: '${{ inputs.service-account }}'
|
|
||||||
token_format: 'access_token'
|
|
||||||
project_id: '${{ inputs.gcp-project-id }}'
|
|
||||||
|
|
||||||
- name: 'Setup gcloud cli'
|
|
||||||
uses: 'google-github-actions/setup-gcloud@v2'
|
|
||||||
with:
|
|
||||||
install_components: 'gke-gcloud-auth-plugin'
|
|
||||||
|
|
||||||
- id: get-gke-credentials
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
gcloud container clusters get-credentials ${{ inputs.cluster-name }} --region ${{ inputs.cluster-location }} --project ${{ inputs.gcp-project-id }}
|
|
||||||
25
.github/actions/copilot-test/action.yml
vendored
25
.github/actions/copilot-test/action.yml
vendored
@@ -1,25 +0,0 @@
|
|||||||
name: 'Run Copilot E2E Test'
|
|
||||||
description: 'Run Copilot E2E Test'
|
|
||||||
inputs:
|
|
||||||
script:
|
|
||||||
description: 'Script to run'
|
|
||||||
default: 'yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only'
|
|
||||||
required: false
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Server Copilot E2E Test
|
|
||||||
shell: bash
|
|
||||||
run: ${{ inputs.script }}
|
|
||||||
env:
|
|
||||||
COPILOT: true
|
|
||||||
DEV_SERVER_URL: http://localhost:8080
|
|
||||||
|
|
||||||
- name: Upload test results
|
|
||||||
if: ${{ failure() }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: test-results-e2e-server-copilot
|
|
||||||
path: ./test-results
|
|
||||||
if-no-files-found: ignore
|
|
||||||
29
.github/actions/deploy/action.yml
vendored
29
.github/actions/deploy/action.yml
vendored
@@ -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
|
||||||
@@ -21,15 +24,27 @@ runs:
|
|||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
|
echo "GIT_SHORT_HASH=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV"
|
||||||
- name: 'Auth to cluster'
|
- uses: azure/setup-helm@v4
|
||||||
uses: './.github/actions/cluster-auth'
|
- id: auth
|
||||||
|
uses: google-github-actions/auth@v2
|
||||||
with:
|
with:
|
||||||
gcp-project-number: '${{ inputs.gcp-project-number }}'
|
workload_identity_provider: 'projects/${{ inputs.gcp-project-number }}/locations/global/workloadIdentityPools/github-actions/providers/github-actions-helm-deploy'
|
||||||
gcp-project-id: '${{ inputs.gcp-project-id }}'
|
service_account: '${{ inputs.service-account }}'
|
||||||
service-account: '${{ inputs.service-account }}'
|
token_format: 'access_token'
|
||||||
cluster-name: '${{ inputs.cluster-name }}'
|
project_id: '${{ inputs.gcp-project-id }}'
|
||||||
cluster-location: '${{ inputs.cluster-location }}'
|
|
||||||
|
- name: 'Setup gcloud cli'
|
||||||
|
uses: 'google-github-actions/setup-gcloud@v2'
|
||||||
|
with:
|
||||||
|
install_components: 'gke-gcloud-auth-plugin'
|
||||||
|
|
||||||
|
- id: get-gke-credentials
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
gcloud container clusters get-credentials ${{ inputs.cluster-name }} --region ${{ inputs.cluster-location }} --project ${{ inputs.gcp-project-id }}
|
||||||
|
|
||||||
- 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 }}'
|
||||||
|
|||||||
181
.github/actions/deploy/deploy.mjs
vendored
181
.github/actions/deploy/deploy.mjs
vendored
@@ -10,114 +10,74 @@ const {
|
|||||||
DATABASE_USERNAME,
|
DATABASE_USERNAME,
|
||||||
DATABASE_PASSWORD,
|
DATABASE_PASSWORD,
|
||||||
DATABASE_NAME,
|
DATABASE_NAME,
|
||||||
GCLOUD_CONNECTION_NAME,
|
R2_ACCOUNT_ID,
|
||||||
|
R2_ACCESS_KEY_ID,
|
||||||
|
R2_SECRET_ACCESS_KEY,
|
||||||
|
CAPTCHA_TURNSTILE_SECRET,
|
||||||
|
METRICS_CUSTOMER_IO_TOKEN,
|
||||||
|
COPILOT_OPENAI_API_KEY,
|
||||||
|
COPILOT_FAL_API_KEY,
|
||||||
|
COPILOT_UNSPLASH_API_KEY,
|
||||||
|
MAILER_SENDER,
|
||||||
|
MAILER_USER,
|
||||||
|
MAILER_PASSWORD,
|
||||||
|
AFFINE_GOOGLE_CLIENT_ID,
|
||||||
|
AFFINE_GOOGLE_CLIENT_SECRET,
|
||||||
CLOUD_SQL_IAM_ACCOUNT,
|
CLOUD_SQL_IAM_ACCOUNT,
|
||||||
APP_IAM_ACCOUNT,
|
GCLOUD_CONNECTION_NAME,
|
||||||
REDIS_SERVER_HOST,
|
GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT,
|
||||||
REDIS_SERVER_PASSWORD,
|
REDIS_HOST,
|
||||||
|
REDIS_PASSWORD,
|
||||||
|
STRIPE_API_KEY,
|
||||||
|
STRIPE_WEBHOOK_KEY,
|
||||||
STATIC_IP_NAME,
|
STATIC_IP_NAME,
|
||||||
AFFINE_INDEXER_SEARCH_PROVIDER,
|
|
||||||
AFFINE_INDEXER_SEARCH_ENDPOINT,
|
|
||||||
AFFINE_INDEXER_SEARCH_API_KEY,
|
|
||||||
} = process.env;
|
} = process.env;
|
||||||
|
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
const buildType = BUILD_TYPE || 'canary';
|
const buildType = BUILD_TYPE || 'canary';
|
||||||
|
|
||||||
const isProduction = buildType === 'stable';
|
const isProduction = buildType === 'stable';
|
||||||
const isBeta = buildType === 'beta';
|
const isBeta = buildType === 'beta';
|
||||||
const isInternal = buildType === 'internal';
|
const isInternal = buildType === 'internal';
|
||||||
|
|
||||||
const replicaConfig = {
|
|
||||||
stable: {
|
|
||||||
web: 2,
|
|
||||||
graphql: Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 2,
|
|
||||||
sync: Number(process.env.PRODUCTION_SYNC_REPLICA) || 2,
|
|
||||||
renderer: Number(process.env.PRODUCTION_RENDERER_REPLICA) || 2,
|
|
||||||
doc: Number(process.env.PRODUCTION_DOC_REPLICA) || 2,
|
|
||||||
},
|
|
||||||
beta: {
|
|
||||||
web: 1,
|
|
||||||
graphql: Number(process.env.BETA_GRAPHQL_REPLICA) || 1,
|
|
||||||
sync: Number(process.env.BETA_SYNC_REPLICA) || 1,
|
|
||||||
renderer: Number(process.env.BETA_RENDERER_REPLICA) || 1,
|
|
||||||
doc: Number(process.env.BETA_DOC_REPLICA) || 1,
|
|
||||||
},
|
|
||||||
canary: {
|
|
||||||
web: 1,
|
|
||||||
graphql: 1,
|
|
||||||
sync: 1,
|
|
||||||
renderer: 1,
|
|
||||||
doc: 1,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const cpuConfig = {
|
|
||||||
beta: {
|
|
||||||
web: '300m',
|
|
||||||
graphql: '1',
|
|
||||||
sync: '1',
|
|
||||||
doc: '1',
|
|
||||||
renderer: '300m',
|
|
||||||
},
|
|
||||||
canary: {
|
|
||||||
web: '300m',
|
|
||||||
graphql: '1',
|
|
||||||
sync: '1',
|
|
||||||
doc: '1',
|
|
||||||
renderer: '300m',
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const createHelmCommand = ({ isDryRun }) => {
|
const createHelmCommand = ({ isDryRun }) => {
|
||||||
const flag = isDryRun ? '--dry-run' : '--atomic';
|
const flag = isDryRun ? '--dry-run' : '--atomic';
|
||||||
const imageTag = `${buildType}-${GIT_SHORT_HASH}`;
|
const imageTag = `${buildType}-${GIT_SHORT_HASH}`;
|
||||||
const redisAndPostgres =
|
const redisAndPostgres =
|
||||||
isProduction || isBeta || isInternal
|
isProduction || isBeta || isInternal
|
||||||
? [
|
? [
|
||||||
`--set cloud-sql-proxy.enabled=true`,
|
`--set-string global.database.url=${DATABASE_URL}`,
|
||||||
`--set-string cloud-sql-proxy.database.connectionName="${GCLOUD_CONNECTION_NAME}"`,
|
|
||||||
`--set-string global.database.host=${DATABASE_URL}`,
|
|
||||||
`--set-string global.database.user=${DATABASE_USERNAME}`,
|
`--set-string global.database.user=${DATABASE_USERNAME}`,
|
||||||
`--set-string global.database.password=${DATABASE_PASSWORD}`,
|
`--set-string global.database.password=${DATABASE_PASSWORD}`,
|
||||||
`--set-string global.database.name=${DATABASE_NAME}`,
|
`--set-string global.database.name=${DATABASE_NAME}`,
|
||||||
`--set-string global.redis.host="${REDIS_SERVER_HOST}"`,
|
`--set global.database.gcloud.enabled=true`,
|
||||||
`--set-string global.redis.password="${REDIS_SERVER_PASSWORD}"`,
|
`--set-string global.database.gcloud.connectionName="${GCLOUD_CONNECTION_NAME}"`,
|
||||||
|
`--set-string global.database.gcloud.cloudSqlInternal="${GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT}"`,
|
||||||
|
`--set-string global.redis.host="${REDIS_HOST}"`,
|
||||||
|
`--set-string global.redis.password="${REDIS_PASSWORD}"`,
|
||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
const indexerOptions = [
|
const serviceAnnotations =
|
||||||
`--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 = [
|
|
||||||
`--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 sync.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
|
||||||
`--set-json doc.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${APP_IAM_ACCOUNT}\\" }"`,
|
|
||||||
].concat(
|
|
||||||
isProduction || isBeta || isInternal
|
isProduction || isBeta || isInternal
|
||||||
? [
|
? [
|
||||||
`--set-json web.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
`--set-json web.service.annotations=\"{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }\"`,
|
||||||
`--set-json graphql.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
`--set-json graphql.service.annotations=\"{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }\"`,
|
||||||
`--set-json sync.service.annotations="{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }"`,
|
`--set-json sync.service.annotations=\"{ \\"cloud.google.com/neg\\": \\"{\\\\\\"ingress\\\\\\": true}\\" }\"`,
|
||||||
`--set-json cloud-sql-proxy.serviceAccount.annotations="{ \\"iam.gke.io/gcp-service-account\\": \\"${CLOUD_SQL_IAM_ACCOUNT}\\" }"`,
|
`--set-json cloud-sql-proxy.serviceAccount.annotations=\"{ \\"iam.gke.io/gcp-service-account\\": \\"${CLOUD_SQL_IAM_ACCOUNT}\\" }\"`,
|
||||||
`--set-json cloud-sql-proxy.nodeSelector="{ \\"iam.gke.io/gke-metadata-server-enabled\\": \\"true\\" }"`,
|
`--set-json cloud-sql-proxy.nodeSelector=\"{ \\"iam.gke.io/gke-metadata-server-enabled\\": \\"true\\" }\"`,
|
||||||
]
|
|
||||||
: []
|
|
||||||
);
|
|
||||||
|
|
||||||
const cpu = cpuConfig[buildType];
|
|
||||||
const resources = cpu
|
|
||||||
? [
|
|
||||||
`--set web.resources.requests.cpu="${cpu.web}"`,
|
|
||||||
`--set graphql.resources.requests.cpu="${cpu.graphql}"`,
|
|
||||||
`--set sync.resources.requests.cpu="${cpu.sync}"`,
|
|
||||||
`--set doc.resources.requests.cpu="${cpu.doc}"`,
|
|
||||||
]
|
]
|
||||||
: [];
|
: [];
|
||||||
|
const webReplicaCount = isProduction ? 3 : isBeta ? 2 : 2;
|
||||||
const replica = replicaConfig[buildType] || replicaConfig.canary;
|
const graphqlReplicaCount = isProduction
|
||||||
|
? Number(process.env.PRODUCTION_GRAPHQL_REPLICA) || 3
|
||||||
|
: isBeta
|
||||||
|
? Number(process.env.isBeta_GRAPHQL_REPLICA) || 2
|
||||||
|
: 2;
|
||||||
|
const syncReplicaCount = isProduction
|
||||||
|
? Number(process.env.PRODUCTION_SYNC_REPLICA) || 3
|
||||||
|
: isBeta
|
||||||
|
? Number(process.env.BETA_SYNC_REPLICA) || 2
|
||||||
|
: 2;
|
||||||
const namespace = isProduction
|
const namespace = isProduction
|
||||||
? 'production'
|
? 'production'
|
||||||
: isBeta
|
: isBeta
|
||||||
@@ -125,40 +85,47 @@ const createHelmCommand = ({ isDryRun }) => {
|
|||||||
: isInternal
|
: isInternal
|
||||||
? 'internal'
|
? 'internal'
|
||||||
: 'dev';
|
: 'dev';
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||||
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}`,
|
||||||
`--set-string global.deployment.type="affine"`,
|
|
||||||
`--set-string global.deployment.platform="gcp"`,
|
|
||||||
`--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=${webReplicaCount}`,
|
||||||
`--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=${graphqlReplicaCount}`,
|
||||||
`--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 graphql.app.captcha.enabled=true`,
|
||||||
|
`--set-string graphql.app.captcha.turnstile.secret="${CAPTCHA_TURNSTILE_SECRET}"`,
|
||||||
|
`--set graphql.app.copilot.enabled=true`,
|
||||||
|
`--set-string graphql.app.copilot.openai.key="${COPILOT_OPENAI_API_KEY}"`,
|
||||||
|
`--set-string graphql.app.copilot.fal.key="${COPILOT_FAL_API_KEY}"`,
|
||||||
|
`--set-string graphql.app.copilot.unsplash.key="${COPILOT_UNSPLASH_API_KEY}"`,
|
||||||
|
`--set graphql.app.objectStorage.r2.enabled=true`,
|
||||||
|
`--set-string graphql.app.objectStorage.r2.accountId="${R2_ACCOUNT_ID}"`,
|
||||||
|
`--set-string graphql.app.objectStorage.r2.accessKeyId="${R2_ACCESS_KEY_ID}"`,
|
||||||
|
`--set-string graphql.app.objectStorage.r2.secretAccessKey="${R2_SECRET_ACCESS_KEY}"`,
|
||||||
|
`--set-string graphql.app.mailer.sender="${MAILER_SENDER}"`,
|
||||||
|
`--set-string graphql.app.mailer.user="${MAILER_USER}"`,
|
||||||
|
`--set-string graphql.app.mailer.password="${MAILER_PASSWORD}"`,
|
||||||
|
`--set-string graphql.app.oauth.google.enabled=true`,
|
||||||
|
`--set-string graphql.app.oauth.google.clientId="${AFFINE_GOOGLE_CLIENT_ID}"`,
|
||||||
|
`--set-string graphql.app.oauth.google.clientSecret="${AFFINE_GOOGLE_CLIENT_SECRET}"`,
|
||||||
|
`--set-string graphql.app.payment.stripe.apiKey="${STRIPE_API_KEY}"`,
|
||||||
|
`--set-string graphql.app.payment.stripe.webhookKey="${STRIPE_WEBHOOK_KEY}"`,
|
||||||
|
`--set graphql.app.metrics.enabled=true`,
|
||||||
|
`--set-string graphql.app.metrics.customerIo.token="${METRICS_CUSTOMER_IO_TOKEN}"`,
|
||||||
|
`--set graphql.app.experimental.enableJwstCodec=${namespace === 'dev'}`,
|
||||||
|
`--set graphql.app.features.earlyAccessPreview=false`,
|
||||||
|
`--set graphql.app.features.syncClientVersionCheck=true`,
|
||||||
|
`--set sync.replicaCount=${syncReplicaCount}`,
|
||||||
`--set-string sync.image.tag="${imageTag}"`,
|
`--set-string sync.image.tag="${imageTag}"`,
|
||||||
`--set-string renderer.image.tag="${imageTag}"`,
|
|
||||||
`--set renderer.app.host=${hosts[0]}`,
|
|
||||||
`--set renderer.replicaCount=${replica.renderer}`,
|
|
||||||
`--set-string doc.image.tag="${imageTag}"`,
|
|
||||||
`--set doc.app.host=${hosts[0]}`,
|
|
||||||
`--set doc.replicaCount=${replica.doc}`,
|
|
||||||
...serviceAnnotations,
|
...serviceAnnotations,
|
||||||
...resources,
|
|
||||||
`--timeout 10m`,
|
`--timeout 10m`,
|
||||||
flag,
|
flag,
|
||||||
].join(' ');
|
].join(' ');
|
||||||
|
|||||||
41
.github/actions/prepare-release/action.yml
vendored
41
.github/actions/prepare-release/action.yml
vendored
@@ -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"
|
|
||||||
30
.github/actions/server-test-env/action.yml
vendored
30
.github/actions/server-test-env/action.yml
vendored
@@ -1,30 +0,0 @@
|
|||||||
name: 'Prepare Server Test Environment'
|
|
||||||
description: 'Prepare Server Test Environment'
|
|
||||||
|
|
||||||
runs:
|
|
||||||
using: 'composite'
|
|
||||||
steps:
|
|
||||||
- name: Initialize database
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
psql -h localhost -U postgres -c "CREATE DATABASE affine;"
|
|
||||||
psql -h localhost -U postgres -c "CREATE USER affine WITH PASSWORD 'affine';"
|
|
||||||
psql -h localhost -U postgres -c "ALTER USER affine WITH SUPERUSER;"
|
|
||||||
env:
|
|
||||||
PGPASSWORD: affine
|
|
||||||
|
|
||||||
- name: Run init-db script
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
NODE_ENV: test
|
|
||||||
run: |
|
|
||||||
yarn affine @affine/server prisma generate
|
|
||||||
yarn affine @affine/server prisma migrate deploy
|
|
||||||
yarn affine @affine/server data-migration run
|
|
||||||
|
|
||||||
- name: Import config
|
|
||||||
shell: bash
|
|
||||||
env:
|
|
||||||
DEFAULT_CONFIG: '{}'
|
|
||||||
run: |
|
|
||||||
printf '%s\n' "${SERVER_CONFIG:-$DEFAULT_CONFIG}" > ./packages/backend/server/config.json
|
|
||||||
82
.github/actions/setup-node/action.yml
vendored
82
.github/actions/setup-node/action.yml
vendored
@@ -13,18 +13,10 @@ inputs:
|
|||||||
description: 'Run the install step for Playwright.'
|
description: 'Run the install step for Playwright.'
|
||||||
required: false
|
required: false
|
||||||
default: 'false'
|
default: 'false'
|
||||||
playwright-platform:
|
|
||||||
description: 'The platform to install Playwright for.'
|
|
||||||
required: false
|
|
||||||
default: 'chromium,webkit'
|
|
||||||
electron-install:
|
electron-install:
|
||||||
description: 'Download the Electron binary'
|
description: 'Download the Electron binary'
|
||||||
required: false
|
required: false
|
||||||
default: 'true'
|
default: 'true'
|
||||||
corepack-install:
|
|
||||||
description: 'Install CorePack'
|
|
||||||
required: false
|
|
||||||
default: 'false'
|
|
||||||
hard-link-nm:
|
hard-link-nm:
|
||||||
description: 'set nmMode to hardlinks-local in .yarnrc.yml'
|
description: 'set nmMode to hardlinks-local in .yarnrc.yml'
|
||||||
required: false
|
required: false
|
||||||
@@ -39,19 +31,10 @@ inputs:
|
|||||||
full-cache:
|
full-cache:
|
||||||
description: 'Full installation cache'
|
description: 'Full installation cache'
|
||||||
required: false
|
required: false
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: 'composite'
|
using: 'composite'
|
||||||
steps:
|
steps:
|
||||||
- name: Output workspace path
|
|
||||||
id: workspace-path
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
if [ -n "${{ env.DEV_DRIVE_WORKSPACE }}" ]; then
|
|
||||||
echo "workspace_path=${{ env.DEV_DRIVE_WORKSPACE }}" >> $GITHUB_OUTPUT
|
|
||||||
else
|
|
||||||
echo "workspace_path=${{ github.workspace }}" >> $GITHUB_OUTPUT
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
@@ -59,37 +42,24 @@ runs:
|
|||||||
registry-url: https://npm.pkg.github.com
|
registry-url: https://npm.pkg.github.com
|
||||||
scope: '@toeverything'
|
scope: '@toeverything'
|
||||||
|
|
||||||
- uses: kenchan0130/actions-system-info@master
|
|
||||||
id: system-info
|
|
||||||
|
|
||||||
- name: Init CorePack
|
|
||||||
if: ${{ inputs.corepack-install == 'true' }}
|
|
||||||
shell: bash
|
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: corepack enable
|
|
||||||
|
|
||||||
- name: Set nmMode
|
- name: Set nmMode
|
||||||
if: ${{ inputs.hard-link-nm == 'false' }}
|
if: ${{ inputs.hard-link-nm == 'false' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: yarn config set nmMode classic
|
run: yarn config set nmMode classic
|
||||||
|
|
||||||
- name: Set nmHoistingLimits
|
- name: Set nmHoistingLimits
|
||||||
if: ${{ inputs.nmHoistingLimits }}
|
if: ${{ inputs.nmHoistingLimits }}
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: yarn config set nmHoistingLimits ${{ inputs.nmHoistingLimits }}
|
run: yarn config set nmHoistingLimits ${{ inputs.nmHoistingLimits }}
|
||||||
|
|
||||||
- name: Set enableScripts
|
- name: Set enableScripts
|
||||||
if: ${{ inputs.enableScripts == 'false' }}
|
if: ${{ inputs.enableScripts == 'false' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: yarn config set enableScripts false
|
run: yarn config set enableScripts false
|
||||||
|
|
||||||
- name: Set yarn global cache path
|
- name: Set yarn global cache path
|
||||||
shell: bash
|
shell: bash
|
||||||
id: yarn-cache
|
id: yarn-cache
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: node -e "const p = $(yarn config cacheFolder --json).effective; console.log('yarn_global_cache=' + p)" >> $GITHUB_OUTPUT
|
run: node -e "const p = $(yarn config cacheFolder --json).effective; console.log('yarn_global_cache=' + p)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Cache non-full yarn cache on Linux
|
- name: Cache non-full yarn cache on Linux
|
||||||
@@ -97,9 +67,9 @@ runs:
|
|||||||
if: ${{ inputs.full-cache != 'true' && runner.os == 'Linux' }}
|
if: ${{ inputs.full-cache != 'true' && runner.os == 'Linux' }}
|
||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
${{ steps.workspace-path.outputs.workspace_path }}/node_modules
|
node_modules
|
||||||
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
||||||
key: node_modules-cache-${{ github.job }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-${{ github.job }}-${{ runner.os }}
|
||||||
|
|
||||||
# The network performance on macOS is very poor
|
# The network performance on macOS is very poor
|
||||||
# and the decompression performance on Windows is very terrible
|
# and the decompression performance on Windows is very terrible
|
||||||
@@ -110,7 +80,7 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
||||||
key: node_modules-cache-${{ github.job }}-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-${{ github.job }}-${{ runner.os }}
|
||||||
|
|
||||||
- name: Cache full yarn cache on Linux
|
- name: Cache full yarn cache on Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -119,7 +89,7 @@ runs:
|
|||||||
path: |
|
path: |
|
||||||
node_modules
|
node_modules
|
||||||
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
||||||
key: node_modules-cache-full-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-full-${{ runner.os }}
|
||||||
|
|
||||||
- name: Cache full yarn cache on non-Linux
|
- name: Cache full yarn cache on non-Linux
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -127,12 +97,23 @@ runs:
|
|||||||
with:
|
with:
|
||||||
path: |
|
path: |
|
||||||
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
${{ steps.yarn-cache.outputs.yarn_global_cache }}
|
||||||
key: node_modules-cache-full-${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}
|
key: node_modules-cache-full-${{ runner.os }}
|
||||||
|
|
||||||
- name: yarn install
|
- name: yarn install
|
||||||
if: ${{ inputs.package-install == 'true' }}
|
if: ${{ inputs.package-install == 'true' }}
|
||||||
|
continue-on-error: true
|
||||||
|
shell: bash
|
||||||
|
run: yarn ${{ inputs.extra-flags }}
|
||||||
|
env:
|
||||||
|
HUSKY: '0'
|
||||||
|
PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: '1'
|
||||||
|
ELECTRON_SKIP_BINARY_DOWNLOAD: '1'
|
||||||
|
SENTRYCLI_SKIP_DOWNLOAD: '1'
|
||||||
|
DEBUG: '*'
|
||||||
|
|
||||||
|
- name: yarn install (try again)
|
||||||
|
if: ${{ steps.install.outcome == 'failure' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: yarn ${{ inputs.extra-flags }}
|
run: yarn ${{ inputs.extra-flags }}
|
||||||
env:
|
env:
|
||||||
HUSKY: '0'
|
HUSKY: '0'
|
||||||
@@ -145,7 +126,6 @@ runs:
|
|||||||
id: playwright-version
|
id: playwright-version
|
||||||
if: ${{ inputs.playwright-install == 'true' }}
|
if: ${{ inputs.playwright-install == 'true' }}
|
||||||
shell: bash
|
shell: bash
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
run: echo "version=$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
run: echo "version=$(yarn why --json @playwright/test | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Attempt to restore the correct Playwright browser binaries based on the
|
# Attempt to restore the correct Playwright browser binaries based on the
|
||||||
@@ -158,8 +138,8 @@ runs:
|
|||||||
id: playwright-cache
|
id: playwright-cache
|
||||||
if: ${{ inputs.playwright-install == 'true' }}
|
if: ${{ inputs.playwright-install == 'true' }}
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.workspace-path.outputs.workspace_path }}/node_modules/.cache/ms-playwright
|
path: ${{ github.workspace }}/node_modules/.cache/ms-playwright
|
||||||
key: '${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}-playwright-${{ steps.playwright-version.outputs.version }}'
|
key: '${{ runner.os }}-playwright-${{ steps.playwright-version.outputs.version }}'
|
||||||
# As a fallback, if the Playwright version has changed, try use the
|
# As a fallback, if the Playwright version has changed, try use the
|
||||||
# most recently cached version. There's a good chance that at least one
|
# most recently cached version. There's a good chance that at least one
|
||||||
# of the browser binary versions haven't been updated, so Playwright can
|
# of the browser binary versions haven't been updated, so Playwright can
|
||||||
@@ -169,22 +149,20 @@ runs:
|
|||||||
# date cache, but still let Playwright decide if it needs to download
|
# date cache, but still let Playwright decide if it needs to download
|
||||||
# new binaries or not.
|
# new binaries or not.
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}-playwright-
|
${{ runner.os }}-playwright-
|
||||||
|
|
||||||
# If the Playwright browser binaries weren't able to be restored, we tell
|
# If the Playwright browser binaries weren't able to be restored, we tell
|
||||||
# playwright to install everything for us.
|
# playwright to install everything for us.
|
||||||
- name: Install Playwright's dependencies
|
- name: Install Playwright's dependencies
|
||||||
shell: bash
|
shell: bash
|
||||||
if: inputs.playwright-install == 'true'
|
if: inputs.playwright-install == 'true'
|
||||||
run: yarn playwright install --with-deps $(echo "${{ inputs.playwright-platform }}" | tr ',' ' ')
|
run: yarn playwright install --with-deps chromium
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
env:
|
env:
|
||||||
PLAYWRIGHT_BROWSERS_PATH: ${{ steps.workspace-path.outputs.workspace_path }}/node_modules/.cache/ms-playwright
|
PLAYWRIGHT_BROWSERS_PATH: ${{ github.workspace }}/node_modules/.cache/ms-playwright
|
||||||
|
|
||||||
- name: Get installed Electron version
|
- name: Get installed Electron version
|
||||||
id: electron-version
|
id: electron-version
|
||||||
if: ${{ inputs.electron-install == 'true' }}
|
if: ${{ inputs.electron-install == 'true' }}
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
echo "version=$(yarn why --json electron | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
echo "version=$(yarn why --json electron | grep -h 'workspace:.' | jq --raw-output '.children[].locator' | sed -e 's/@playwright\/test@.*://' | head -n 1)" >> $GITHUB_OUTPUT
|
||||||
@@ -193,20 +171,14 @@ runs:
|
|||||||
id: electron-cache
|
id: electron-cache
|
||||||
if: ${{ inputs.electron-install == 'true' }}
|
if: ${{ inputs.electron-install == 'true' }}
|
||||||
with:
|
with:
|
||||||
path: ${{ steps.workspace-path.outputs.workspace_path }}/node_modules/.cache/electron
|
path: 'node_modules/.cache/electron'
|
||||||
key: '${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}-electron-${{ steps.electron-version.outputs.version }}'
|
key: '${{ runner.os }}-electron-${{ steps.electron-version.outputs.version }}'
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
${{ runner.os }}-${{ runner.arch }}-${{ steps.system-info.outputs.name }}-${{ steps.system-info.outputs.release }}-${{ steps.system-info.outputs.version }}-electron-
|
${{ runner.os }}-electron-
|
||||||
|
|
||||||
- name: Install Electron binary
|
- name: Install Electron binary
|
||||||
shell: bash
|
shell: bash
|
||||||
if: inputs.electron-install == 'true'
|
if: inputs.electron-install == 'true'
|
||||||
run: node ./node_modules/electron/install.js
|
run: node ./node_modules/electron/install.js
|
||||||
working-directory: ${{ steps.workspace-path.outputs.workspace_path }}
|
|
||||||
env:
|
env:
|
||||||
electron_config_cache: ${{ steps.workspace-path.outputs.workspace_path }}/node_modules/.cache/electron
|
electron_config_cache: ./node_modules/.cache/electron
|
||||||
|
|
||||||
- name: Write PLAYWRIGHT_BROWSERS_PATH env
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
echo "PLAYWRIGHT_BROWSERS_PATH=${{ steps.workspace-path.outputs.workspace_path }}/node_modules/.cache/ms-playwright" >> $GITHUB_ENV
|
|
||||||
|
|||||||
26
.github/actions/setup-version/action.yml
vendored
26
.github/actions/setup-version/action.yml
vendored
@@ -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-$GIT_SHORT_HASH
|
||||||
|
fi
|
||||||
|
echo $APP_VERSION
|
||||||
|
echo "APP_VERSION=$APP_VERSION" >> "$GITHUB_OUTPUT"
|
||||||
|
./scripts/set-version.sh $APP_VERSION
|
||||||
|
|||||||
5
.github/deployment/front/Dockerfile
vendored
5
.github/deployment/front/Dockerfile
vendored
@@ -1,8 +1,7 @@
|
|||||||
FROM openresty/openresty:1.27.1.1-0-buster
|
FROM openresty/openresty:1.25.3.1-0-buster
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY ./packages/frontend/apps/web/dist ./dist
|
COPY ./packages/frontend/web/dist ./dist
|
||||||
COPY ./packages/frontend/admin/dist ./admin
|
COPY ./packages/frontend/admin/dist ./admin
|
||||||
COPY ./packages/frontend/apps/mobile/dist ./mobile
|
|
||||||
COPY ./.github/deployment/front/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
|
COPY ./.github/deployment/front/nginx.conf /usr/local/openresty/nginx/conf/nginx.conf
|
||||||
COPY ./.github/deployment/front/affine.nginx.conf /etc/nginx/conf.d/affine.nginx.conf
|
COPY ./.github/deployment/front/affine.nginx.conf /etc/nginx/conf.d/affine.nginx.conf
|
||||||
|
|
||||||
|
|||||||
22
.github/deployment/front/affine.nginx.conf
vendored
22
.github/deployment/front/affine.nginx.conf
vendored
@@ -6,33 +6,15 @@ server {
|
|||||||
try_files $uri/index.html $uri/ $uri /admin/index.html;
|
try_files $uri/index.html $uri/ $uri /admin/index.html;
|
||||||
}
|
}
|
||||||
|
|
||||||
set $app_root_path /app/dist/;
|
|
||||||
set $mobile_root /app/dist/;
|
|
||||||
set_by_lua $affine_env 'return os.getenv("AFFINE_ENV")';
|
|
||||||
|
|
||||||
if ($affine_env = "dev") {
|
|
||||||
set $mobile_root /app/mobile/;
|
|
||||||
}
|
|
||||||
|
|
||||||
# https://gist.github.com/mariusom/6683dc52b1cad1a1f372e908bdb209d0
|
|
||||||
if ($http_user_agent ~* "(android|bb\d+|meego).+mobile|avantgo|bada\/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|iris|kindle|lge |maemo|midp|mmp|mobile.+firefox|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)\/|plucker|pocket|psp|series(4|6)0|symbian|treo|up\.(browser|link)|vodafone|wap|windows ce|xda|xiino") {
|
|
||||||
set $app_root_path $mobile_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($http_user_agent ~* "^(1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s\-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|\-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw\-(n|u)|c55\/|capi|ccwa|cdm\-|cell|chtm|cldc|cmd\-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc\-s|devi|dica|dmob|do(c|p)o|ds(12|\-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(\-|_)|g1 u|g560|gene|gf\-5|g\-mo|go(\.w|od)|gr(ad|un)|haie|hcit|hd\-(m|p|t)|hei\-|hi(pt|ta)|hp( i|ip)|hs\-c|ht(c(\-| |_|a|g|p|s|t)|tp)|hu(aw|tc)|i\-(20|go|ma)|i230|iac( |\-|\/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |\/)|klon|kpt |kwc\-|kyo(c|k)|le(no|xi)|lg( g|\/(k|l|u)|50|54|\-[a-w])|libw|lynx|m1\-w|m3ga|m50\/|ma(te|ui|xo)|mc(01|21|ca)|m\-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(\-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)\-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|\-([1-8]|c))|phil|pire|pl(ay|uc)|pn\-2|po(ck|rt|se)|prox|psio|pt\-g|qa\-a|qc(07|12|21|32|60|\-[2-7]|i\-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55\/|sa(ge|ma|mm|ms|ny|va)|sc(01|h\-|oo|p\-)|sdk\/|se(c(\-|0|1)|47|mc|nd|ri)|sgh\-|shar|sie(\-|m)|sk\-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h\-|v\-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl\-|tdg\-|tel(i|m)|tim\-|t\-mo|to(pl|sh)|ts(70|m\-|m3|m5)|tx\-9|up(\.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|\-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(\-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas\-|your|zeto|zte\-)") {
|
|
||||||
set $app_root_path $mobile_root;
|
|
||||||
}
|
|
||||||
|
|
||||||
location ~ ^/(_plugin|assets|imgs|js|plugins|static)/ {
|
location ~ ^/(_plugin|assets|imgs|js|plugins|static)/ {
|
||||||
root $app_root_path;
|
root /app/dist/;
|
||||||
try_files $uri $uri/ =404;
|
try_files $uri $uri/ =404;
|
||||||
}
|
}
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
root $app_root_path;
|
root /app/dist/;
|
||||||
index index.html;
|
index index.html;
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
add_header Cache-Control "private, no-cache, no-store, max-age=0, must-revalidate";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
error_page 404 /404.html;
|
error_page 404 /404.html;
|
||||||
|
|||||||
1
.github/deployment/front/nginx.conf
vendored
1
.github/deployment/front/nginx.conf
vendored
@@ -1,7 +1,6 @@
|
|||||||
worker_processes 4;
|
worker_processes 4;
|
||||||
error_log /var/log/nginx/error.log warn;
|
error_log /var/log/nginx/error.log warn;
|
||||||
pcre_jit on;
|
pcre_jit on;
|
||||||
env AFFINE_ENV;
|
|
||||||
events {
|
events {
|
||||||
worker_connections 1024;
|
worker_connections 1024;
|
||||||
}
|
}
|
||||||
|
|||||||
14
.github/deployment/node/Dockerfile
vendored
14
.github/deployment/node/Dockerfile
vendored
@@ -1,18 +1,12 @@
|
|||||||
FROM node:22-bookworm-slim
|
FROM node:20-bookworm-slim
|
||||||
|
|
||||||
COPY ./packages/backend/server /app
|
COPY ./packages/backend/server /app
|
||||||
COPY ./packages/frontend/apps/web/dist /app/static
|
COPY ./packages/frontend/web/dist /app/static
|
||||||
COPY ./packages/frontend/admin/dist /app/static/admin
|
COPY ./packages/frontend/admin/dist /app/static/admin
|
||||||
COPY ./packages/frontend/apps/mobile/dist /app/static/mobile
|
|
||||||
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
|
CMD ["node", "--import", "./scripts/register.js", "./dist/index.js"]
|
||||||
ENV LD_PRELOAD=libjemalloc.so.2
|
|
||||||
|
|
||||||
EXPOSE 3010
|
|
||||||
|
|
||||||
CMD ["node", "./dist/main.js"]
|
|
||||||
|
|||||||
62
.github/deployment/self-host/compose.yaml
vendored
Normal file
62
.github/deployment/self-host/compose.yaml
vendored
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
services:
|
||||||
|
affine:
|
||||||
|
image: ghcr.io/toeverything/affine-graphql:stable
|
||||||
|
container_name: affine_selfhosted
|
||||||
|
command:
|
||||||
|
['sh', '-c', 'node ./scripts/self-host-predeploy && node ./dist/index.js']
|
||||||
|
ports:
|
||||||
|
- '3010:3010'
|
||||||
|
- '5555:5555'
|
||||||
|
depends_on:
|
||||||
|
redis:
|
||||||
|
condition: service_healthy
|
||||||
|
postgres:
|
||||||
|
condition: service_healthy
|
||||||
|
volumes:
|
||||||
|
# custom configurations
|
||||||
|
- ~/.affine/self-host/config:/root/.affine/config
|
||||||
|
# blob storage
|
||||||
|
- ~/.affine/self-host/storage:/root/.affine/storage
|
||||||
|
logging:
|
||||||
|
driver: 'json-file'
|
||||||
|
options:
|
||||||
|
max-size: '1000m'
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- NODE_OPTIONS="--import=./scripts/register.js"
|
||||||
|
- AFFINE_CONFIG_PATH=/root/.affine/config
|
||||||
|
- REDIS_SERVER_HOST=redis
|
||||||
|
- DATABASE_URL=postgres://affine:affine@postgres:5432/affine
|
||||||
|
- NODE_ENV=production
|
||||||
|
- AFFINE_ADMIN_EMAIL=${AFFINE_ADMIN_EMAIL}
|
||||||
|
- AFFINE_ADMIN_PASSWORD=${AFFINE_ADMIN_PASSWORD}
|
||||||
|
# Telemetry allows us to collect data on how you use the affine. This data will helps us improve the app and provide better features.
|
||||||
|
# Uncomment next line if you wish to quit telemetry.
|
||||||
|
# - TELEMETRY_ENABLE=false
|
||||||
|
redis:
|
||||||
|
image: redis
|
||||||
|
container_name: affine_redis
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ~/.affine/self-host/redis:/data
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'redis-cli', '--raw', 'incr', 'ping']
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
postgres:
|
||||||
|
image: postgres
|
||||||
|
container_name: affine_postgres
|
||||||
|
restart: unless-stopped
|
||||||
|
volumes:
|
||||||
|
- ~/.affine/self-host/postgres:/var/lib/postgresql/data
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD-SHELL', 'pg_isready -U affine']
|
||||||
|
interval: 10s
|
||||||
|
timeout: 5s
|
||||||
|
retries: 5
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: affine
|
||||||
|
POSTGRES_PASSWORD: affine
|
||||||
|
POSTGRES_DB: affine
|
||||||
|
PGDATA: /var/lib/postgresql/data/pgdata
|
||||||
2
.github/helm/affine/Chart.yaml
vendored
2
.github/helm/affine/Chart.yaml
vendored
@@ -3,4 +3,4 @@ name: affine
|
|||||||
description: AFFiNE cloud chart
|
description: AFFiNE cloud chart
|
||||||
type: application
|
type: application
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
appVersion: "0.26.0"
|
appVersion: "0.15.0"
|
||||||
|
|||||||
11
.github/helm/affine/charts/doc/Chart.yaml
vendored
11
.github/helm/affine/charts/doc/Chart.yaml
vendored
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: doc
|
|
||||||
description: AFFiNE doc server
|
|
||||||
type: application
|
|
||||||
version: 0.0.0
|
|
||||||
appVersion: "0.26.0"
|
|
||||||
dependencies:
|
|
||||||
- name: gcloud-sql-proxy
|
|
||||||
version: 0.0.0
|
|
||||||
repository: "file://../gcloud-sql-proxy"
|
|
||||||
condition: .global.database.gcloud.enabled
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "doc.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "doc.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "doc.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "doc.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "doc.chart" . }}
|
|
||||||
{{ include "doc.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
monitoring: enabled
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "doc.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "doc.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "doc.fullname" .) .Values.global.docService.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.global.docService.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "doc.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "doc.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "doc.serviceAccountName" . }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_PRIVATE_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.global.secret.secretName }}"
|
|
||||||
key: key
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: "{{ .Values.env }}"
|
|
||||||
- name: NODE_OPTIONS
|
|
||||||
value: "--max-old-space-size=4096"
|
|
||||||
- name: NO_COLOR
|
|
||||||
value: "1"
|
|
||||||
- name: DEPLOYMENT_TYPE
|
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
|
||||||
value: "doc"
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pg-postgresql
|
|
||||||
key: postgres-password
|
|
||||||
- name: DATABASE_URL
|
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
|
||||||
- name: REDIS_SERVER_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: REDIS_SERVER_HOST
|
|
||||||
value: "{{ .Values.global.redis.host }}"
|
|
||||||
- name: REDIS_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.redis.port }}"
|
|
||||||
- name: REDIS_SERVER_USER
|
|
||||||
value: "{{ .Values.global.redis.username }}"
|
|
||||||
- name: REDIS_SERVER_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis
|
|
||||||
key: redis-password
|
|
||||||
- name: REDIS_SERVER_DATABASE
|
|
||||||
value: "{{ .Values.global.redis.database }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: indexer
|
|
||||||
key: indexer-apiKey
|
|
||||||
- name: AFFINE_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.docService.port }}"
|
|
||||||
- name: AFFINE_SERVER_SUB_PATH
|
|
||||||
value: "{{ .Values.app.path }}"
|
|
||||||
- name: AFFINE_SERVER_HOST
|
|
||||||
value: "{{ .Values.app.host }}"
|
|
||||||
- name: AFFINE_SERVER_HTTPS
|
|
||||||
value: "{{ .Values.app.https }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.global.docService.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
timeoutSeconds: {{ .Values.probe.timeoutSeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "doc.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.global.docService.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "doc.selectorLabels" . | nindent 4 }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "doc.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "doc.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "doc.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "doc.fullname" . }}:{{ .Values.global.docService.port }}']
|
|
||||||
restartPolicy: Never
|
|
||||||
43
.github/helm/affine/charts/doc/values.yaml
vendored
43
.github/helm/affine/charts/doc/values.yaml
vendored
@@ -1,43 +0,0 @@
|
|||||||
replicaCount: 1
|
|
||||||
image:
|
|
||||||
repository: ghcr.io/toeverything/affine
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
tag: ''
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ''
|
|
||||||
fullnameOverride: ''
|
|
||||||
# map to NODE_ENV environment variable
|
|
||||||
env: 'production'
|
|
||||||
app:
|
|
||||||
# AFFINE_SERVER_SUB_PATH
|
|
||||||
path: ''
|
|
||||||
# AFFINE_SERVER_HOST
|
|
||||||
host: '0.0.0.0'
|
|
||||||
https: true
|
|
||||||
copilot:
|
|
||||||
enabled: false
|
|
||||||
secretName: copilot
|
|
||||||
openai:
|
|
||||||
key: ''
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
annotations: {}
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext:
|
|
||||||
fsGroup: 2000
|
|
||||||
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: '1'
|
|
||||||
memory: 4Gi
|
|
||||||
|
|
||||||
probe:
|
|
||||||
initialDelaySeconds: 20
|
|
||||||
timeoutSeconds: 5
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
tolerations: []
|
|
||||||
affinity: {}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.enabled -}}
|
{{- if .Values.global.database.gcloud.enabled -}}
|
||||||
1. Get the application URL by running these commands:
|
1. Get the application URL by running these commands:
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
{{- if contains "NodePort" .Values.service.type }}
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gcloud-sql-proxy.fullname" . }})
|
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "gcloud-sql-proxy.fullname" . }})
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.enabled -}}
|
{{- if .Values.global.database.gcloud.enabled -}}
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
@@ -42,7 +42,7 @@ spec:
|
|||||||
- "0.0.0.0"
|
- "0.0.0.0"
|
||||||
- "--structured-logs"
|
- "--structured-logs"
|
||||||
- "--auto-iam-authn"
|
- "--auto-iam-authn"
|
||||||
- "{{ .Values.database.connectionName }}"
|
- "{{ .Values.global.database.gcloud.connectionName }}"
|
||||||
env:
|
env:
|
||||||
# Enable HTTP healthchecks on port 9801. This enables /liveness,
|
# Enable HTTP healthchecks on port 9801. This enables /liveness,
|
||||||
# /readiness and /startup health check endpoints. Allow connections
|
# /readiness and /startup health check endpoints. Allow connections
|
||||||
@@ -56,7 +56,7 @@ spec:
|
|||||||
value: 0.0.0.0
|
value: 0.0.0.0
|
||||||
ports:
|
ports:
|
||||||
- name: cloud-sql-proxy
|
- name: cloud-sql-proxy
|
||||||
containerPort: {{ .Values.service.port }}
|
containerPort: {{ .Values.global.database.gcloud.proxyPort }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
- containerPort: 9801
|
- containerPort: 9801
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.enabled -}}
|
{{- if .Values.global.database.gcloud.enabled -}}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.enabled -}}
|
{{- if .Values.global.database.gcloud.enabled -}}
|
||||||
{{- if .Values.serviceAccount.create -}}
|
{{- if .Values.serviceAccount.create -}}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ServiceAccount
|
kind: ServiceAccount
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
{{- if .Values.enabled -}}
|
{{- if .Values.global.database.gcloud.enabled -}}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Pod
|
kind: Pod
|
||||||
metadata:
|
metadata:
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
replicaCount: 2
|
replicaCount: 3
|
||||||
enabled: false
|
|
||||||
database:
|
|
||||||
connectionName: ""
|
|
||||||
|
|
||||||
image:
|
image:
|
||||||
# the tag is defined as chart appVersion.
|
# the tag is defined as chart appVersion.
|
||||||
@@ -33,11 +30,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.26.0"
|
appVersion: "0.15.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: gcloud-sql-proxy
|
- name: gcloud-sql-proxy
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
|||||||
9
.github/helm/affine/charts/graphql/templates/captcha-secret.yaml
vendored
Normal file
9
.github/helm/affine/charts/graphql/templates/captcha-secret.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{{- if .Values.app.captcha.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.captcha.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
turnstileSecret: {{ .Values.app.captcha.turnstile.secret | b64enc }}
|
||||||
|
{{- end }}
|
||||||
11
.github/helm/affine/charts/graphql/templates/copilot-secret.yaml
vendored
Normal file
11
.github/helm/affine/charts/graphql/templates/copilot-secret.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{{- if .Values.app.copilot.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.copilot.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
openaiSecret: {{ .Values.app.copilot.openai.key | b64enc }}
|
||||||
|
falSecret: {{ .Values.app.copilot.fal.key | b64enc }}
|
||||||
|
unsplashSecret: {{ .Values.app.copilot.unsplash.key | b64enc }}
|
||||||
|
{{- end }}
|
||||||
@@ -36,13 +36,11 @@ spec:
|
|||||||
- name: NODE_ENV
|
- name: NODE_ENV
|
||||||
value: "{{ .Values.env }}"
|
value: "{{ .Values.env }}"
|
||||||
- name: NODE_OPTIONS
|
- name: NODE_OPTIONS
|
||||||
value: "--max-old-space-size=2048"
|
value: "--max-old-space-size=4096"
|
||||||
- name: NO_COLOR
|
- name: NO_COLOR
|
||||||
value: "1"
|
value: "1"
|
||||||
- name: DEPLOYMENT_TYPE
|
- name: DEPLOYMENT_TYPE
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
value: "affine"
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
- name: SERVER_FLAVOR
|
||||||
value: "graphql"
|
value: "graphql"
|
||||||
- name: AFFINE_ENV
|
- name: AFFINE_ENV
|
||||||
@@ -53,7 +51,9 @@ spec:
|
|||||||
name: pg-postgresql
|
name: pg-postgresql
|
||||||
key: postgres-password
|
key: postgres-password
|
||||||
- name: DATABASE_URL
|
- name: DATABASE_URL
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.url }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
||||||
|
- name: REDIS_SERVER_ENABLED
|
||||||
|
value: "true"
|
||||||
- name: REDIS_SERVER_HOST
|
- name: REDIS_SERVER_HOST
|
||||||
value: "{{ .Values.global.redis.host }}"
|
value: "{{ .Values.global.redis.host }}"
|
||||||
- name: REDIS_SERVER_PORT
|
- name: REDIS_SERVER_PORT
|
||||||
@@ -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
|
||||||
@@ -84,20 +75,141 @@ spec:
|
|||||||
value: "{{ .Values.app.host }}"
|
value: "{{ .Values.app.host }}"
|
||||||
- name: AFFINE_SERVER_HTTPS
|
- name: AFFINE_SERVER_HTTPS
|
||||||
value: "{{ .Values.app.https }}"
|
value: "{{ .Values.app.https }}"
|
||||||
- name: DOC_SERVICE_ENDPOINT
|
- name: ENABLE_R2_OBJECT_STORAGE
|
||||||
value: "http://{{ .Values.global.docService.name }}:{{ .Values.global.docService.port }}"
|
value: "{{ .Values.app.objectStorage.r2.enabled }}"
|
||||||
|
- name: ENABLE_CAPTCHA
|
||||||
|
value: "{{ .Values.app.captcha.enabled }}"
|
||||||
|
- name: FEATURES_EARLY_ACCESS_PREVIEW
|
||||||
|
value: "{{ .Values.app.features.earlyAccessPreview }}"
|
||||||
|
- name: FEATURES_SYNC_CLIENT_VERSION_CHECK
|
||||||
|
value: "{{ .Values.app.features.syncClientVersionCheck }}"
|
||||||
|
- name: MAILER_HOST
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: host
|
||||||
|
- name: MAILER_PORT
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: port
|
||||||
|
- name: MAILER_USER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: user
|
||||||
|
- name: MAILER_PASSWORD
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: password
|
||||||
|
- name: MAILER_SENDER
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
key: sender
|
||||||
|
- name: STRIPE_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.payment.stripe.secretName }}"
|
||||||
|
key: stripeAPIKey
|
||||||
|
- name: STRIPE_WEBHOOK_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.payment.stripe.secretName }}"
|
||||||
|
key: stripeWebhookKey
|
||||||
|
- name: DOC_MERGE_INTERVAL
|
||||||
|
value: "{{ .Values.app.doc.mergeInterval }}"
|
||||||
|
{{ if .Values.app.experimental.enableJwstCodec }}
|
||||||
|
- name: DOC_MERGE_USE_JWST_CODEC
|
||||||
|
value: "true"
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.objectStorage.r2.enabled }}
|
||||||
|
- name: R2_OBJECT_STORAGE_ACCOUNT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
|
key: accountId
|
||||||
|
- name: R2_OBJECT_STORAGE_ACCESS_KEY_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
|
key: accessKeyId
|
||||||
|
- name: R2_OBJECT_STORAGE_SECRET_ACCESS_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
|
key: secretAccessKey
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.captcha.enabled }}
|
||||||
|
- name: CAPTCHA_TURNSTILE_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.captcha.secretName }}"
|
||||||
|
key: turnstileSecret
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.copilot.enabled }}
|
||||||
|
- name: COPILOT_OPENAI_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.copilot.secretName }}"
|
||||||
|
key: openaiSecret
|
||||||
|
- name: COPILOT_FAL_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.copilot.secretName }}"
|
||||||
|
key: falSecret
|
||||||
|
- name: COPILOT_UNSPLASH_API_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.copilot.secretName }}"
|
||||||
|
key: unsplashSecret
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.oauth.google.enabled }}
|
||||||
|
- name: OAUTH_GOOGLE_ENABLED
|
||||||
|
value: "true"
|
||||||
|
- name: OAUTH_GOOGLE_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.oauth.google.secretName }}"
|
||||||
|
key: clientId
|
||||||
|
- name: OAUTH_GOOGLE_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.oauth.google.secretName }}"
|
||||||
|
key: clientSecret
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.oauth.github.enabled }}
|
||||||
|
- name: OAUTH_GITHUB_CLIENT_ID
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.oauth.github.secretName }}"
|
||||||
|
key: clientId
|
||||||
|
- name: OAUTH_GITHUB_CLIENT_SECRET
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.oauth.github.secretName }}"
|
||||||
|
key: clientSecret
|
||||||
|
{{ end }}
|
||||||
|
{{ if .Values.app.metrics.enabled }}
|
||||||
|
- name: METRICS_CUSTOMER_IO_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.metrics.secretName }}"
|
||||||
|
key: customerIoSecret
|
||||||
|
{{ end }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: {{ .Values.service.port }}
|
containerPort: {{ .Values.service.port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
livenessProbe:
|
livenessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /info
|
path: /
|
||||||
port: http
|
port: http
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
path: /info
|
path: /
|
||||||
port: http
|
port: http
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
13
.github/helm/affine/charts/graphql/templates/mailer.yaml
vendored
Normal file
13
.github/helm/affine/charts/graphql/templates/mailer.yaml
vendored
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{{- if .Values.app.mailer.secretName -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.mailer.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
host: "{{ .Values.app.mailer.host | b64enc }}"
|
||||||
|
port: "{{ .Values.app.mailer.port | b64enc }}"
|
||||||
|
user: "{{ .Values.app.mailer.user | b64enc }}"
|
||||||
|
password: "{{ .Values.app.mailer.password | b64enc }}"
|
||||||
|
sender: "{{ .Values.app.mailer.sender | b64enc }}"
|
||||||
|
{{- end }}
|
||||||
9
.github/helm/affine/charts/graphql/templates/metrics-secret.yaml
vendored
Normal file
9
.github/helm/affine/charts/graphql/templates/metrics-secret.yaml
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{{- if .Values.app.metrics.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.metrics.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
customerIoSecret: {{ .Values.app.metrics.customerIo.token | b64enc }}
|
||||||
|
{{- end }}
|
||||||
@@ -23,36 +23,37 @@ spec:
|
|||||||
- name: AFFINE_ENV
|
- name: AFFINE_ENV
|
||||||
value: "{{ .Release.Namespace }}"
|
value: "{{ .Release.Namespace }}"
|
||||||
- name: DEPLOYMENT_TYPE
|
- name: DEPLOYMENT_TYPE
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
value: "affine"
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
- name: DATABASE_PASSWORD
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: pg-postgresql
|
name: pg-postgresql
|
||||||
key: postgres-password
|
key: postgres-password
|
||||||
|
{{ if not .Values.global.database.gcloud.enabled }}
|
||||||
- name: DATABASE_URL
|
- name: DATABASE_URL
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.url }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
||||||
- name: REDIS_SERVER_HOST
|
{{ end }}
|
||||||
value: "{{ .Values.global.redis.host }}"
|
{{ if .Values.global.database.gcloud.enabled }}
|
||||||
- name: REDIS_SERVER_PORT
|
- name: DATABASE_URL
|
||||||
value: "{{ .Values.global.redis.port }}"
|
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.gcloud.cloudSqlInternal }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
||||||
- name: REDIS_SERVER_USER
|
{{ end }}
|
||||||
value: "{{ .Values.global.redis.username }}"
|
{{ if .Values.app.objectStorage.r2.enabled }}
|
||||||
- name: REDIS_SERVER_PASSWORD
|
- name: R2_OBJECT_STORAGE_ACCOUNT_ID
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: redis
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
key: redis-password
|
key: accountId
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
- name: R2_OBJECT_STORAGE_ACCESS_KEY_ID
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: indexer
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
key: indexer-apiKey
|
key: accessKeyId
|
||||||
|
- name: R2_OBJECT_STORAGE_SECRET_ACCESS_KEY
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
|
key: secretAccessKey
|
||||||
|
{{ end }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: '100m'
|
cpu: '100m'
|
||||||
|
|||||||
21
.github/helm/affine/charts/graphql/templates/oauth.yaml
vendored
Normal file
21
.github/helm/affine/charts/graphql/templates/oauth.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{{- if .Values.app.oauth.google.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.oauth.google.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
clientId: "{{ .Values.app.oauth.google.clientId | b64enc }}"
|
||||||
|
clientSecret: "{{ .Values.app.oauth.google.clientSecret | b64enc }}"
|
||||||
|
{{- end }}
|
||||||
|
---
|
||||||
|
{{- if .Values.app.oauth.github.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.oauth.github.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
clientId: "{{ .Values.app.oauth.github.clientId | b64enc }}"
|
||||||
|
clientSecret: "{{ .Values.app.oauth.github.clientSecret | b64enc }}"
|
||||||
|
{{- end }}
|
||||||
8
.github/helm/affine/charts/graphql/templates/payment.yml
vendored
Normal file
8
.github/helm/affine/charts/graphql/templates/payment.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.payment.stripe.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
stripeAPIKey: "{{ .Values.app.payment.stripe.apiKey | b64enc }}"
|
||||||
|
stripeWebhookKey: "{{ .Values.app.payment.stripe.webhookKey | b64enc }}"
|
||||||
11
.github/helm/affine/charts/graphql/templates/r2-secret.yaml
vendored
Normal file
11
.github/helm/affine/charts/graphql/templates/r2-secret.yaml
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{{- if .Values.app.objectStorage.r2.enabled -}}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: "{{ .Values.app.objectStorage.r2.secretName }}"
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
accountId: {{ .Values.app.objectStorage.r2.accountId | b64enc }}
|
||||||
|
accessKeyId: {{ .Values.app.objectStorage.r2.accessKeyId | b64enc }}
|
||||||
|
secretAccessKey: {{ .Values.app.objectStorage.r2.secretAccessKey | b64enc }}
|
||||||
|
{{- end }}
|
||||||
@@ -4,10 +4,6 @@ metadata:
|
|||||||
name: {{ include "graphql.fullname" . }}
|
name: {{ include "graphql.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "graphql.labels" . | nindent 4 }}
|
{{- include "graphql.labels" . | nindent 4 }}
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
spec:
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.service.type }}
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
58
.github/helm/affine/charts/graphql/values.yaml
vendored
58
.github/helm/affine/charts/graphql/values.yaml
vendored
@@ -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: ''
|
||||||
|
|
||||||
@@ -10,11 +10,63 @@ fullnameOverride: ''
|
|||||||
# map to NODE_ENV environment variable
|
# map to NODE_ENV environment variable
|
||||||
env: 'production'
|
env: 'production'
|
||||||
app:
|
app:
|
||||||
|
experimental:
|
||||||
|
enableJwstCodec: true
|
||||||
# AFFINE_SERVER_SUB_PATH
|
# AFFINE_SERVER_SUB_PATH
|
||||||
path: ''
|
path: ''
|
||||||
# AFFINE_SERVER_HOST
|
# AFFINE_SERVER_HOST
|
||||||
host: '0.0.0.0'
|
host: '0.0.0.0'
|
||||||
https: true
|
https: true
|
||||||
|
doc:
|
||||||
|
mergeInterval: "3000"
|
||||||
|
captcha:
|
||||||
|
enabled: false
|
||||||
|
secretName: captcha
|
||||||
|
turnstile:
|
||||||
|
secret: ''
|
||||||
|
copilot:
|
||||||
|
enabled: false
|
||||||
|
secretName: copilot
|
||||||
|
openai:
|
||||||
|
key: ''
|
||||||
|
objectStorage:
|
||||||
|
r2:
|
||||||
|
enabled: false
|
||||||
|
secretName: r2
|
||||||
|
accountId: ''
|
||||||
|
accessKeyId: ''
|
||||||
|
secretAccessKey: ''
|
||||||
|
oauth:
|
||||||
|
google:
|
||||||
|
enabled: false
|
||||||
|
secretName: oauth-google
|
||||||
|
clientId: ''
|
||||||
|
clientSecret: ''
|
||||||
|
github:
|
||||||
|
enabled: false
|
||||||
|
secretName: oauth-github
|
||||||
|
clientId: ''
|
||||||
|
clientSecret: ''
|
||||||
|
mailer:
|
||||||
|
secretName: 'mailer'
|
||||||
|
host: 'smtp.gmail.com'
|
||||||
|
port: '465'
|
||||||
|
user: ''
|
||||||
|
password: ''
|
||||||
|
sender: 'noreply@toeverything.info'
|
||||||
|
metrics:
|
||||||
|
enabled: false
|
||||||
|
secretName: 'metrics'
|
||||||
|
customerIo:
|
||||||
|
token: ''
|
||||||
|
payment:
|
||||||
|
stripe:
|
||||||
|
secretName: 'stripe'
|
||||||
|
apiKey: ''
|
||||||
|
webhookKey: ''
|
||||||
|
features:
|
||||||
|
earlyAccessPreview: false
|
||||||
|
syncClientVersionCheck: false
|
||||||
|
|
||||||
serviceAccount:
|
serviceAccount:
|
||||||
create: true
|
create: true
|
||||||
@@ -28,8 +80,8 @@ podSecurityContext:
|
|||||||
|
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
cpu: '2'
|
cpu: '4'
|
||||||
memory: 2Gi
|
memory: 4Gi
|
||||||
|
|
||||||
probe:
|
probe:
|
||||||
initialDelaySeconds: 20
|
initialDelaySeconds: 20
|
||||||
|
|||||||
11
.github/helm/affine/charts/renderer/Chart.yaml
vendored
11
.github/helm/affine/charts/renderer/Chart.yaml
vendored
@@ -1,11 +0,0 @@
|
|||||||
apiVersion: v2
|
|
||||||
name: renderer
|
|
||||||
description: AFFiNE renderer server
|
|
||||||
type: application
|
|
||||||
version: 0.0.0
|
|
||||||
appVersion: "0.26.0"
|
|
||||||
dependencies:
|
|
||||||
- name: gcloud-sql-proxy
|
|
||||||
version: 0.0.0
|
|
||||||
repository: "file://../gcloud-sql-proxy"
|
|
||||||
condition: .global.database.gcloud.enabled
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
1. Get the application URL by running these commands:
|
|
||||||
{{- if contains "NodePort" .Values.service.type }}
|
|
||||||
export NODE_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "renderer.fullname" . }})
|
|
||||||
export NODE_IP=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
|
||||||
echo http://$NODE_IP:$NODE_PORT
|
|
||||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
|
||||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
|
||||||
You can watch the status of by running 'kubectl get --namespace {{ .Release.Namespace }} svc -w {{ include "renderer.fullname" . }}'
|
|
||||||
export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ include "renderer.fullname" . }} --template "{{"{{ range (index .status.loadBalancer.ingress 0) }}{{.}}{{ end }}"}}")
|
|
||||||
echo http://$SERVICE_IP:{{ .Values.service.port }}
|
|
||||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
|
||||||
export POD_NAME=$(kubectl get pods --namespace {{ .Release.Namespace }} -l "app.kubernetes.io/name={{ include "renderer.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
|
||||||
export CONTAINER_PORT=$(kubectl get pod --namespace {{ .Release.Namespace }} $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
|
|
||||||
echo "Visit http://127.0.0.1:8080 to use your application"
|
|
||||||
kubectl --namespace {{ .Release.Namespace }} port-forward $POD_NAME 8080:$CONTAINER_PORT
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{{/*
|
|
||||||
Expand the name of the chart.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.name" -}}
|
|
||||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create a default fully qualified app name.
|
|
||||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
|
||||||
If release name contains chart name it will be used as a full name.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.fullname" -}}
|
|
||||||
{{- if .Values.fullnameOverride }}
|
|
||||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
|
||||||
{{- if contains $name .Release.Name }}
|
|
||||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- else }}
|
|
||||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create chart name and version as used by the chart label.
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.chart" -}}
|
|
||||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Common labels
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.labels" -}}
|
|
||||||
helm.sh/chart: {{ include "renderer.chart" . }}
|
|
||||||
{{ include "renderer.selectorLabels" . }}
|
|
||||||
{{- if .Chart.AppVersion }}
|
|
||||||
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
|
||||||
{{- end }}
|
|
||||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
|
||||||
monitoring: enabled
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Selector labels
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.selectorLabels" -}}
|
|
||||||
app.kubernetes.io/name: {{ include "renderer.name" . }}
|
|
||||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
|
||||||
{{- end }}
|
|
||||||
|
|
||||||
{{/*
|
|
||||||
Create the name of the service account to use
|
|
||||||
*/}}
|
|
||||||
{{- define "renderer.serviceAccountName" -}}
|
|
||||||
{{- if .Values.serviceAccount.create }}
|
|
||||||
{{- default (include "renderer.fullname" .) .Values.serviceAccount.name }}
|
|
||||||
{{- else }}
|
|
||||||
{{- default "default" .Values.serviceAccount.name }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
apiVersion: apps/v1
|
|
||||||
kind: Deployment
|
|
||||||
metadata:
|
|
||||||
name: {{ include "renderer.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.labels" . | nindent 4 }}
|
|
||||||
spec:
|
|
||||||
replicas: {{ .Values.replicaCount }}
|
|
||||||
selector:
|
|
||||||
matchLabels:
|
|
||||||
{{- include "renderer.selectorLabels" . | nindent 6 }}
|
|
||||||
template:
|
|
||||||
metadata:
|
|
||||||
{{- with .Values.podAnnotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.selectorLabels" . | nindent 8 }}
|
|
||||||
spec:
|
|
||||||
{{- with .Values.imagePullSecrets }}
|
|
||||||
imagePullSecrets:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
serviceAccountName: {{ include "renderer.serviceAccountName" . }}
|
|
||||||
containers:
|
|
||||||
- name: {{ .Chart.Name }}
|
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
|
||||||
env:
|
|
||||||
- name: AFFINE_PRIVATE_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: "{{ .Values.global.secret.secretName }}"
|
|
||||||
key: key
|
|
||||||
- name: NODE_ENV
|
|
||||||
value: "{{ .Values.env }}"
|
|
||||||
- name: NODE_OPTIONS
|
|
||||||
value: "--max-old-space-size=2048"
|
|
||||||
- name: NO_COLOR
|
|
||||||
value: "1"
|
|
||||||
- name: DEPLOYMENT_TYPE
|
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
|
||||||
value: "renderer"
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
- name: DATABASE_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: pg-postgresql
|
|
||||||
key: postgres-password
|
|
||||||
- name: DATABASE_URL
|
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
|
||||||
- name: REDIS_SERVER_ENABLED
|
|
||||||
value: "true"
|
|
||||||
- name: REDIS_SERVER_HOST
|
|
||||||
value: "{{ .Values.global.redis.host }}"
|
|
||||||
- name: REDIS_SERVER_PORT
|
|
||||||
value: "{{ .Values.global.redis.port }}"
|
|
||||||
- name: REDIS_SERVER_USER
|
|
||||||
value: "{{ .Values.global.redis.username }}"
|
|
||||||
- name: REDIS_SERVER_PASSWORD
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: redis
|
|
||||||
key: redis-password
|
|
||||||
- name: REDIS_SERVER_DATABASE
|
|
||||||
value: "{{ .Values.global.redis.database }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_PROVIDER
|
|
||||||
value: "{{ .Values.global.indexer.provider }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_ENDPOINT
|
|
||||||
value: "{{ .Values.global.indexer.endpoint }}"
|
|
||||||
- name: AFFINE_INDEXER_SEARCH_API_KEY
|
|
||||||
valueFrom:
|
|
||||||
secretKeyRef:
|
|
||||||
name: indexer
|
|
||||||
key: indexer-apiKey
|
|
||||||
- name: AFFINE_SERVER_PORT
|
|
||||||
value: "{{ .Values.service.port }}"
|
|
||||||
- name: AFFINE_SERVER_SUB_PATH
|
|
||||||
value: "{{ .Values.app.path }}"
|
|
||||||
- name: AFFINE_SERVER_HOST
|
|
||||||
value: "{{ .Values.app.host }}"
|
|
||||||
- name: AFFINE_SERVER_HTTPS
|
|
||||||
value: "{{ .Values.app.https }}"
|
|
||||||
- name: DOC_SERVICE_ENDPOINT
|
|
||||||
value: "http://{{ .Values.global.docService.name }}:{{ .Values.global.docService.port }}"
|
|
||||||
ports:
|
|
||||||
- name: http
|
|
||||||
containerPort: {{ .Values.service.port }}
|
|
||||||
protocol: TCP
|
|
||||||
livenessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
readinessProbe:
|
|
||||||
httpGet:
|
|
||||||
path: /info
|
|
||||||
port: http
|
|
||||||
initialDelaySeconds: {{ .Values.probe.initialDelaySeconds }}
|
|
||||||
resources:
|
|
||||||
{{- toYaml .Values.resources | nindent 12 }}
|
|
||||||
{{- with .Values.nodeSelector }}
|
|
||||||
nodeSelector:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.affinity }}
|
|
||||||
affinity:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- with .Values.tolerations }}
|
|
||||||
tolerations:
|
|
||||||
{{- toYaml . | nindent 8 }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Service
|
|
||||||
metadata:
|
|
||||||
name: {{ include "graphql.fullname" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "graphql.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.service.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
spec:
|
|
||||||
type: {{ .Values.service.type }}
|
|
||||||
ports:
|
|
||||||
- port: {{ .Values.service.port }}
|
|
||||||
targetPort: http
|
|
||||||
protocol: TCP
|
|
||||||
name: http
|
|
||||||
selector:
|
|
||||||
{{- include "graphql.selectorLabels" . | nindent 4 }}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{{- if .Values.serviceAccount.create -}}
|
|
||||||
apiVersion: v1
|
|
||||||
kind: ServiceAccount
|
|
||||||
metadata:
|
|
||||||
name: {{ include "graphql.serviceAccountName" . }}
|
|
||||||
labels:
|
|
||||||
{{- include "graphql.labels" . | nindent 4 }}
|
|
||||||
{{- with .Values.serviceAccount.annotations }}
|
|
||||||
annotations:
|
|
||||||
{{- toYaml . | nindent 4 }}
|
|
||||||
{{- end }}
|
|
||||||
{{- end }}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: Pod
|
|
||||||
metadata:
|
|
||||||
name: "{{ include "renderer.fullname" . }}-test-connection"
|
|
||||||
labels:
|
|
||||||
{{- include "renderer.labels" . | nindent 4 }}
|
|
||||||
annotations:
|
|
||||||
"helm.sh/hook": test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: wget
|
|
||||||
image: busybox
|
|
||||||
command: ['wget']
|
|
||||||
args: ['{{ include "renderer.fullname" . }}:{{ .Values.service.port }}']
|
|
||||||
restartPolicy: Never
|
|
||||||
38
.github/helm/affine/charts/renderer/values.yaml
vendored
38
.github/helm/affine/charts/renderer/values.yaml
vendored
@@ -1,38 +0,0 @@
|
|||||||
replicaCount: 1
|
|
||||||
image:
|
|
||||||
repository: ghcr.io/toeverything/affine
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
tag: ''
|
|
||||||
|
|
||||||
imagePullSecrets: []
|
|
||||||
nameOverride: ''
|
|
||||||
fullnameOverride: ''
|
|
||||||
# map to NODE_ENV environment variable
|
|
||||||
env: 'production'
|
|
||||||
app:
|
|
||||||
# AFFINE_SERVER_SUB_PATH
|
|
||||||
path: ''
|
|
||||||
# AFFINE_SERVER_HOST
|
|
||||||
host: '0.0.0.0'
|
|
||||||
https: true
|
|
||||||
serviceAccount:
|
|
||||||
create: true
|
|
||||||
annotations: {}
|
|
||||||
name: 'affine-renderer'
|
|
||||||
|
|
||||||
podAnnotations: {}
|
|
||||||
|
|
||||||
podSecurityContext:
|
|
||||||
fsGroup: 2000
|
|
||||||
|
|
||||||
resources:
|
|
||||||
requests:
|
|
||||||
cpu: '1'
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
probe:
|
|
||||||
initialDelaySeconds: 20
|
|
||||||
|
|
||||||
nodeSelector: {}
|
|
||||||
tolerations: []
|
|
||||||
affinity: {}
|
|
||||||
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
2
.github/helm/affine/charts/sync/Chart.yaml
vendored
@@ -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.26.0"
|
appVersion: "0.15.0"
|
||||||
dependencies:
|
dependencies:
|
||||||
- name: gcloud-sql-proxy
|
- name: gcloud-sql-proxy
|
||||||
version: 0.0.0
|
version: 0.0.0
|
||||||
|
|||||||
@@ -42,9 +42,7 @@ spec:
|
|||||||
- name: NO_COLOR
|
- name: NO_COLOR
|
||||||
value: "1"
|
value: "1"
|
||||||
- name: DEPLOYMENT_TYPE
|
- name: DEPLOYMENT_TYPE
|
||||||
value: "{{ .Values.global.deployment.type }}"
|
value: "affine"
|
||||||
- name: DEPLOYMENT_PLATFORM
|
|
||||||
value: "{{ .Values.global.deployment.platform }}"
|
|
||||||
- name: SERVER_FLAVOR
|
- name: SERVER_FLAVOR
|
||||||
value: "sync"
|
value: "sync"
|
||||||
- name: AFFINE_ENV
|
- name: AFFINE_ENV
|
||||||
@@ -55,7 +53,9 @@ spec:
|
|||||||
name: pg-postgresql
|
name: pg-postgresql
|
||||||
key: postgres-password
|
key: postgres-password
|
||||||
- name: DATABASE_URL
|
- name: DATABASE_URL
|
||||||
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.host }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
value: postgres://{{ .Values.global.database.user }}:$(DATABASE_PASSWORD)@{{ .Values.global.database.url }}:{{ .Values.global.database.port }}/{{ .Values.global.database.name }}
|
||||||
|
- name: REDIS_SERVER_ENABLED
|
||||||
|
value: "true"
|
||||||
- name: REDIS_SERVER_HOST
|
- name: REDIS_SERVER_HOST
|
||||||
value: "{{ .Values.global.redis.host }}"
|
value: "{{ .Values.global.redis.host }}"
|
||||||
- name: REDIS_SERVER_PORT
|
- name: REDIS_SERVER_PORT
|
||||||
@@ -69,21 +69,10 @@ 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
|
||||||
value: "{{ .Values.app.host }}"
|
value: "{{ .Values.app.host }}"
|
||||||
- name: DOC_SERVICE_ENDPOINT
|
|
||||||
value: "http://{{ .Values.global.docService.name }}:{{ .Values.global.docService.port }}"
|
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: {{ .Values.service.port }}
|
containerPort: {{ .Values.service.port }}
|
||||||
|
|||||||
8
.github/helm/affine/charts/sync/values.yaml
vendored
8
.github/helm/affine/charts/sync/values.yaml
vendored
@@ -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: ''
|
||||||
|
|
||||||
@@ -24,11 +24,11 @@ podSecurityContext:
|
|||||||
|
|
||||||
resources:
|
resources:
|
||||||
limits:
|
limits:
|
||||||
|
cpu: '4'
|
||||||
|
memory: 8Gi
|
||||||
|
requests:
|
||||||
cpu: '2'
|
cpu: '2'
|
||||||
memory: 4Gi
|
memory: 4Gi
|
||||||
requests:
|
|
||||||
cpu: '1'
|
|
||||||
memory: 2Gi
|
|
||||||
|
|
||||||
probe:
|
probe:
|
||||||
initialDelaySeconds: 20
|
initialDelaySeconds: 20
|
||||||
|
|||||||
@@ -27,9 +27,6 @@ spec:
|
|||||||
- name: {{ .Chart.Name }}
|
- name: {{ .Chart.Name }}
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
env:
|
|
||||||
- name: AFFINE_ENV
|
|
||||||
value: "{{ .Release.Namespace }}"
|
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: {{ .Values.service.port }}
|
containerPort: {{ .Values.service.port }}
|
||||||
|
|||||||
9
.github/helm/affine/templates/configmap.yaml
vendored
9
.github/helm/affine/templates/configmap.yaml
vendored
@@ -1,9 +0,0 @@
|
|||||||
apiVersion: v1
|
|
||||||
kind: ConfigMap
|
|
||||||
metadata:
|
|
||||||
name: {{ .Release.Name }}-runtime-config
|
|
||||||
data:
|
|
||||||
web-assets-manifest: |-
|
|
||||||
{{ .Files.Get "web-assets-manifest.json" | nindent 4 }}
|
|
||||||
mobile-assets-manifest: |-
|
|
||||||
{{ .Files.Get "mobile-assets-manifest.json" | nindent 4 }}
|
|
||||||
@@ -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 }}
|
|
||||||
25
.github/helm/affine/templates/ingress.yaml
vendored
25
.github/helm/affine/templates/ingress.yaml
vendored
@@ -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,40 @@ 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: /oauth
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: affine-renderer
|
name: affine-graphql
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.renderer.service.port }}
|
number: {{ .Values.graphql.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 }}
|
- path: /js/worker.(.+).js
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: affine-web
|
||||||
|
port:
|
||||||
|
number: {{ .Values.web.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|||||||
13
.github/helm/affine/templates/monitoring.yaml
vendored
13
.github/helm/affine/templates/monitoring.yaml
vendored
@@ -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 }}
|
|
||||||
52
.github/helm/affine/values.yaml
vendored
52
.github/helm/affine/values.yaml
vendored
@@ -1,71 +1,49 @@
|
|||||||
global:
|
global:
|
||||||
app:
|
|
||||||
buildType: 'stable'
|
|
||||||
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'
|
||||||
privateKey: ''
|
privateKey: ''
|
||||||
database:
|
database:
|
||||||
user: 'postgres'
|
user: 'postgres'
|
||||||
host: 'pg-postgresql'
|
url: 'pg-postgresql'
|
||||||
port: '5432'
|
port: '5432'
|
||||||
name: 'affine'
|
name: 'affine'
|
||||||
password: ''
|
password: ''
|
||||||
|
gcloud:
|
||||||
|
enabled: false
|
||||||
|
# use for migration
|
||||||
|
cloudSqlInternal: ''
|
||||||
|
connectionName: ''
|
||||||
|
serviceAccount: ''
|
||||||
|
cloudProxyReplicas: 3
|
||||||
|
proxyPort: '5432'
|
||||||
redis:
|
redis:
|
||||||
|
enabled: true
|
||||||
host: 'redis-master'
|
host: 'redis-master'
|
||||||
port: '6379'
|
port: '6379'
|
||||||
username: ''
|
username: ''
|
||||||
password: ''
|
password: ''
|
||||||
database: 0
|
database: 0
|
||||||
indexer:
|
gke:
|
||||||
provider: ''
|
enabled: true
|
||||||
endpoint: ''
|
|
||||||
username: ''
|
|
||||||
password: ''
|
|
||||||
docService:
|
|
||||||
name: 'affine-doc'
|
|
||||||
port: 3020
|
|
||||||
deployment:
|
|
||||||
# change to 'selfhosted' and 'unknown' if this chart is ready to be used for selfhosted deployment
|
|
||||||
type: 'affine'
|
|
||||||
platform: 'gcp'
|
|
||||||
|
|
||||||
graphql:
|
graphql:
|
||||||
service:
|
service:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
port: 3000
|
port: 3000
|
||||||
annotations:
|
annotations:
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
cloud.google.com/backend-config: '{"default": "affine-backendconfig"}'
|
||||||
|
|
||||||
sync:
|
sync:
|
||||||
service:
|
service:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
port: 3010
|
port: 3010
|
||||||
annotations:
|
annotations:
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
cloud.google.com/backend-config: '{"default": "affine-backendconfig"}'
|
||||||
|
|
||||||
renderer:
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
port: 3000
|
|
||||||
annotations:
|
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
|
||||||
|
|
||||||
doc:
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
annotations:
|
|
||||||
cloud.google.com/backend-config: '{"default": "affine-api-backendconfig"}'
|
|
||||||
|
|
||||||
web:
|
web:
|
||||||
service:
|
service:
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
FROM pgvector/pgvector:pg15 AS builder
|
|
||||||
|
|
||||||
FROM bitnami/postgresql:15
|
|
||||||
|
|
||||||
COPY --from=builder /usr/lib/postgresql/15/lib/vector.so /opt/bitnami/postgresql/lib/
|
|
||||||
COPY --from=builder /usr/share/postgresql/15/extension/vector* /opt/bitnami/postgresql/share/extension/
|
|
||||||
10
.github/helm/separate-config/backend-config.yaml
vendored
10
.github/helm/separate-config/backend-config.yaml
vendored
@@ -1,10 +0,0 @@
|
|||||||
apiVersion: cloud.google.com/v1
|
|
||||||
kind: BackendConfig
|
|
||||||
metadata:
|
|
||||||
name: "affine-api-backendconfig"
|
|
||||||
spec:
|
|
||||||
healthCheck:
|
|
||||||
timeoutSec: 1
|
|
||||||
type: HTTP
|
|
||||||
requestPath: /info
|
|
||||||
|
|
||||||
2
.github/labeler.yml
vendored
2
.github/labeler.yml
vendored
@@ -77,7 +77,7 @@ app:core:
|
|||||||
app:electron:
|
app:electron:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-any-file:
|
- any-glob-to-any-file:
|
||||||
- 'packages/frontend/apps/electron/**/*'
|
- 'packages/frontend/electron/**/*'
|
||||||
|
|
||||||
app:server:
|
app:server:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
52
.github/renovate.json
vendored
52
.github/renovate.json
vendored
@@ -7,13 +7,15 @@
|
|||||||
"**/bower_components/**",
|
"**/bower_components/**",
|
||||||
"**/vendor/**",
|
"**/vendor/**",
|
||||||
"**/examples/**",
|
"**/examples/**",
|
||||||
"**/__tests__/**"
|
"**/__tests__/**",
|
||||||
|
"**/test/**",
|
||||||
|
"**/__fixtures__/**"
|
||||||
],
|
],
|
||||||
"packageRules": [
|
"packageRules": [
|
||||||
{
|
{
|
||||||
|
"matchPackagePatterns": ["^eslint", "^@typescript-eslint"],
|
||||||
"rangeStrategy": "replace",
|
"rangeStrategy": "replace",
|
||||||
"groupName": "linter",
|
"groupName": "linter"
|
||||||
"matchPackageNames": ["/^eslint/", "/^@typescript-eslint/"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"matchDepNames": ["oxlint"],
|
"matchDepNames": ["oxlint"],
|
||||||
@@ -21,50 +23,24 @@
|
|||||||
"groupName": "oxlint"
|
"groupName": "oxlint"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"groupName": "all non-major rust dependencies",
|
"groupName": "blocksuite-canary",
|
||||||
"groupSlug": "all-minor-patch",
|
"matchPackagePatterns": ["^@blocksuite"],
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
"excludePackageNames": ["@blocksuite/icons"],
|
||||||
"matchManagers": ["cargo"]
|
"rangeStrategy": "replace",
|
||||||
},
|
"followTag": "canary",
|
||||||
{
|
"enabled": false
|
||||||
"groupName": "all non-major npm dependencies",
|
|
||||||
"groupSlug": "all-minor-patch",
|
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
|
||||||
"matchManagers": ["npm"],
|
|
||||||
"matchPackageNames": ["*", "!/^@blocksuite//", "!/oxlint/"]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"groupName": "all non-major dependencies",
|
"groupName": "all non-major dependencies",
|
||||||
"groupSlug": "all-minor-patch",
|
"groupSlug": "all-minor-patch",
|
||||||
"matchUpdateTypes": ["minor", "patch"],
|
"matchPackagePatterns": ["*"],
|
||||||
"matchManagers": [
|
"excludePackagePatterns": ["^@blocksuite/", "oxlint"],
|
||||||
"dockerfile",
|
"matchUpdateTypes": ["minor", "patch"]
|
||||||
"github-actions",
|
|
||||||
"helmv3",
|
|
||||||
"helm-values",
|
|
||||||
"gradle-wrapper",
|
|
||||||
"gradle",
|
|
||||||
"docker-compose",
|
|
||||||
"devcontainer",
|
|
||||||
"cocoapods",
|
|
||||||
"bundler"
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"groupName": "rust toolchain",
|
"groupName": "rust toolchain",
|
||||||
"matchManagers": ["custom.regex"],
|
"matchManagers": ["custom.regex"],
|
||||||
"matchDepNames": ["rustc"]
|
"matchDepNames": ["rustc"]
|
||||||
},
|
|
||||||
{
|
|
||||||
"groupName": "nestjs",
|
|
||||||
"matchPackageNames": ["/^@nestjs/"]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"groupName": "opentelemetry",
|
|
||||||
"matchPackageNames": [
|
|
||||||
"/^@opentelemetry/",
|
|
||||||
"/^@google-cloud\/opentelemetry-/"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"commitMessagePrefix": "chore: ",
|
"commitMessagePrefix": "chore: ",
|
||||||
|
|||||||
286
.github/workflows/build-images.yml
vendored
286
.github/workflows/build-images.yml
vendored
@@ -1,286 +0,0 @@
|
|||||||
name: Build Images
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
build-type:
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
app-version:
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
git-short-hash:
|
|
||||||
type: string
|
|
||||||
required: true
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
contents: 'write'
|
|
||||||
id-token: 'write'
|
|
||||||
packages: 'write'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-web:
|
|
||||||
name: Build @affine/web
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: ${{ inputs.build-type }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
- name: Build Core
|
|
||||||
run: yarn affine @affine/web build
|
|
||||||
env:
|
|
||||||
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
|
||||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
||||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
||||||
BUILD_TYPE: ${{ inputs.build-type }}
|
|
||||||
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
||||||
SENTRY_PROJECT: 'affine-web'
|
|
||||||
SENTRY_RELEASE: ${{ inputs.app-version }}
|
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
|
||||||
- name: Upload web artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: web
|
|
||||||
path: ./packages/frontend/apps/web/dist
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-admin:
|
|
||||||
name: Build @affine/admin
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: ${{ inputs.build-type }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
- name: Build Admin
|
|
||||||
run: yarn affine @affine/admin build
|
|
||||||
env:
|
|
||||||
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
|
||||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
||||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
||||||
BUILD_TYPE: ${{ inputs.build-type }}
|
|
||||||
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
||||||
SENTRY_PROJECT: 'affine-admin'
|
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
|
||||||
- name: Upload admin artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: admin
|
|
||||||
path: ./packages/frontend/admin/dist
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-mobile:
|
|
||||||
name: Build @affine/mobile
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: ${{ inputs.build-type }}
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
- name: Build Mobile
|
|
||||||
run: yarn affine @affine/mobile build
|
|
||||||
env:
|
|
||||||
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
|
||||||
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
|
||||||
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
|
||||||
BUILD_TYPE: ${{ inputs.build-type }}
|
|
||||||
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
|
|
||||||
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
|
||||||
SENTRY_PROJECT: 'affine-mobile'
|
|
||||||
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
|
||||||
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
|
||||||
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
|
||||||
- name: Upload mobile artifact
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mobile
|
|
||||||
path: ./packages/frontend/apps/mobile/dist
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-server-native:
|
|
||||||
name: Build Server native - ${{ matrix.targets.name }}
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
environment: ${{ inputs.build-type }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
targets:
|
|
||||||
- name: x86_64-unknown-linux-gnu
|
|
||||||
file: server-native.x64.node
|
|
||||||
- name: aarch64-unknown-linux-gnu
|
|
||||||
file: server-native.arm64.node
|
|
||||||
- name: armv7-unknown-linux-gnueabihf
|
|
||||||
file: server-native.armv7.node
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
electron-install: false
|
|
||||||
extra-flags: workspaces focus @affine/server-native
|
|
||||||
- name: 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:
|
|
||||||
target: ${{ matrix.targets.name }}
|
|
||||||
package: '@affine/server-native'
|
|
||||||
- name: Rename ${{ matrix.targets.file }}
|
|
||||||
run: |
|
|
||||||
mv ./packages/backend/native/server-native.node ./packages/backend/native/${{ matrix.targets.file }}
|
|
||||||
- name: Upload ${{ matrix.targets.file }}
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: server-native-${{ matrix.targets.file }}
|
|
||||||
path: ./packages/backend/native/${{ matrix.targets.file }}
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-server:
|
|
||||||
name: Build Server
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- build-server-native
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
electron-install: false
|
|
||||||
extra-flags: workspaces focus @affine/server @types/affine__env
|
|
||||||
- name: Download server-native
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
pattern: server-native-*
|
|
||||||
merge-multiple: true
|
|
||||||
path: ./packages/backend/native
|
|
||||||
- name: List server-native files
|
|
||||||
run: ls -alh ./packages/backend/native
|
|
||||||
- name: Build Server
|
|
||||||
run: yarn workspace @affine/server build
|
|
||||||
- name: Upload server dist
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: server-dist
|
|
||||||
path: ./packages/backend/server/dist
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
build-images:
|
|
||||||
name: Build Images
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- build-server
|
|
||||||
- build-web
|
|
||||||
- build-mobile
|
|
||||||
- build-admin
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Download server dist
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: server-dist
|
|
||||||
path: ./packages/backend/server/dist
|
|
||||||
- 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 QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
# setup node without cache configuration
|
|
||||||
# Prisma cache is not compatible with docker build cache
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: actions/setup-node@v4
|
|
||||||
with:
|
|
||||||
node-version-file: '.nvmrc'
|
|
||||||
registry-url: https://npm.pkg.github.com
|
|
||||||
scope: '@toeverything'
|
|
||||||
|
|
||||||
- name: Download web artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: web
|
|
||||||
path: ./packages/frontend/apps/web/dist
|
|
||||||
|
|
||||||
- name: Download mobile artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: mobile
|
|
||||||
path: ./packages/frontend/apps/mobile/dist
|
|
||||||
|
|
||||||
- name: Download admin artifact
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: admin
|
|
||||||
path: ./packages/frontend/admin/dist
|
|
||||||
|
|
||||||
- name: Install Node.js dependencies
|
|
||||||
run: |
|
|
||||||
yarn config set --json supportedArchitectures.cpu '["x64", "arm64", "arm"]'
|
|
||||||
yarn config set --json supportedArchitectures.libc '["glibc"]'
|
|
||||||
yarn workspaces focus @affine/server --production
|
|
||||||
|
|
||||||
- name: Generate Prisma client
|
|
||||||
run: yarn workspace @affine/server prisma generate
|
|
||||||
|
|
||||||
- name: Mv node_modules
|
|
||||||
run: mv ./node_modules ./packages/backend/server
|
|
||||||
|
|
||||||
- name: Setup Version
|
|
||||||
uses: ./.github/actions/setup-version
|
|
||||||
with:
|
|
||||||
app-version: ${{ inputs.app-version }}
|
|
||||||
|
|
||||||
- name: Build front Dockerfile
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
pull: true
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
provenance: true
|
|
||||||
file: .github/deployment/front/Dockerfile
|
|
||||||
tags: ghcr.io/toeverything/affine-front:${{inputs.build-type}}-${{ inputs.git-short-hash }}
|
|
||||||
|
|
||||||
- name: Build graphql Dockerfile
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: .
|
|
||||||
push: true
|
|
||||||
pull: true
|
|
||||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
|
||||||
provenance: true
|
|
||||||
file: .github/deployment/node/Dockerfile
|
|
||||||
tags: ghcr.io/toeverything/affine:${{inputs.build-type}}-${{ inputs.git-short-hash }}
|
|
||||||
25
.github/workflows/build-selfhost-image.yml
vendored
Normal file
25
.github/workflows/build-selfhost-image.yml
vendored
Normal file
@@ -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-server-image.yml
|
||||||
|
with:
|
||||||
|
flavor: ${{ github.event.inputs.flavor }}
|
||||||
232
.github/workflows/build-server-image.yml
vendored
Normal file
232
.github/workflows/build-server-image.yml
vendored
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
name: Build Images
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
flavor:
|
||||||
|
type: string
|
||||||
|
required: true
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
flavor:
|
||||||
|
type: string
|
||||||
|
required: false
|
||||||
|
|
||||||
|
env:
|
||||||
|
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: 'write'
|
||||||
|
id-token: 'write'
|
||||||
|
packages: 'write'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-server:
|
||||||
|
name: Build Server
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
with:
|
||||||
|
electron-install: false
|
||||||
|
extra-flags: workspaces focus @affine/server
|
||||||
|
- name: Build Server
|
||||||
|
run: yarn workspace @affine/server build
|
||||||
|
- name: Upload server dist
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: server-dist
|
||||||
|
path: ./packages/backend/server/dist
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-web-selfhost:
|
||||||
|
name: Build @affine/web selfhost
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: ${{ github.event.inputs.flavor }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
- name: Build Core
|
||||||
|
run: yarn nx build @affine/web --skip-nx-cache
|
||||||
|
env:
|
||||||
|
BUILD_TYPE: ${{ github.event.inputs.flavor }}
|
||||||
|
PUBLIC_PATH: '/'
|
||||||
|
SELF_HOSTED: true
|
||||||
|
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
||||||
|
- name: Download selfhost fonts
|
||||||
|
run: node ./scripts/download-blocksuite-fonts.mjs
|
||||||
|
- name: Upload web artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: selfhost-web
|
||||||
|
path: ./packages/frontend/web/dist
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-admin-selfhost:
|
||||||
|
name: Build @affine/admin selfhost
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: ${{ github.event.inputs.flavor }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
- name: Build Core
|
||||||
|
run: yarn nx build @affine/admin --skip-nx-cache
|
||||||
|
env:
|
||||||
|
BUILD_TYPE: ${{ github.event.inputs.flavor }}
|
||||||
|
PUBLIC_PATH: '/admin/'
|
||||||
|
SELF_HOSTED: true
|
||||||
|
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
||||||
|
- name: Upload admin artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: selfhost-admin
|
||||||
|
path: ./packages/frontend/admin/dist
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-server-native:
|
||||||
|
name: Build Server native - ${{ matrix.targets.name }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
targets:
|
||||||
|
- name: x86_64-unknown-linux-gnu
|
||||||
|
file: server-native.node
|
||||||
|
- name: aarch64-unknown-linux-gnu
|
||||||
|
file: server-native.arm64.node
|
||||||
|
- name: armv7-unknown-linux-gnueabihf
|
||||||
|
file: server-native.armv7.node
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
with:
|
||||||
|
electron-install: false
|
||||||
|
extra-flags: workspaces focus @affine/server-native
|
||||||
|
- name: Build Rust
|
||||||
|
uses: ./.github/actions/build-rust
|
||||||
|
with:
|
||||||
|
target: ${{ matrix.targets.name }}
|
||||||
|
package: '@affine/server-native'
|
||||||
|
nx_token: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
|
||||||
|
- name: Upload ${{ matrix.targets.file }}
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: ${{ matrix.targets.file }}
|
||||||
|
path: ./packages/backend/native/server-native.node
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-docker:
|
||||||
|
name: Build Docker
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build-server
|
||||||
|
- build-web-selfhost
|
||||||
|
- build-admin-selfhost
|
||||||
|
- build-server-native
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Download server dist
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: server-dist
|
||||||
|
path: ./packages/backend/server/dist
|
||||||
|
- name: Download server-native.node
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: server-native.node
|
||||||
|
path: ./packages/backend/server
|
||||||
|
- name: Download server-native.node arm64
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: server-native.arm64.node
|
||||||
|
path: ./packages/backend/native
|
||||||
|
- name: Download server-native.node arm64
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: server-native.armv7.node
|
||||||
|
path: .
|
||||||
|
- name: move server-native files
|
||||||
|
run: |
|
||||||
|
mv ./packages/backend/native/server-native.node ./packages/backend/server/server-native.arm64.node
|
||||||
|
mv server-native.node ./packages/backend/server/server-native.armv7.node
|
||||||
|
- 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
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
logout: false
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
# setup node without cache configuration
|
||||||
|
# Prisma cache is not compatible with docker build cache
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version-file: '.nvmrc'
|
||||||
|
registry-url: https://npm.pkg.github.com
|
||||||
|
scope: '@toeverything'
|
||||||
|
|
||||||
|
- name: Download selfhost web artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: selfhost-web
|
||||||
|
path: ./packages/frontend/web/dist
|
||||||
|
|
||||||
|
- name: Download selfhost admin artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: selfhost-admin
|
||||||
|
path: ./packages/frontend/admin/dist
|
||||||
|
|
||||||
|
- name: Install Node.js dependencies
|
||||||
|
run: |
|
||||||
|
yarn config set --json supportedArchitectures.cpu '["x64", "arm64", "arm"]'
|
||||||
|
yarn config set --json supportedArchitectures.libc '["glibc"]'
|
||||||
|
yarn workspaces focus @affine/server --production
|
||||||
|
|
||||||
|
- name: Generate Prisma client
|
||||||
|
run: yarn workspace @affine/server prisma generate
|
||||||
|
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
|
||||||
|
- name: Build graphql Dockerfile
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
pull: true
|
||||||
|
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||||
|
provenance: true
|
||||||
|
file: .github/deployment/node/Dockerfile
|
||||||
|
tags: ghcr.io/toeverything/affine-graphql:${{env.RELEASE_FLAVOR}}-${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-graphql:${{env.RELEASE_FLAVOR}}
|
||||||
1016
.github/workflows/build-test.yml
vendored
1016
.github/workflows/build-test.yml
vendored
File diff suppressed because it is too large
Load Diff
29
.github/workflows/copilot-test-automatically.yml
vendored
29
.github/workflows/copilot-test-automatically.yml
vendored
@@ -1,29 +0,0 @@
|
|||||||
name: Copilot Test Automatically
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- 'v[0-9]+.[0-9]+.[0-9]+-canary.[0-9]+'
|
|
||||||
schedule:
|
|
||||||
- cron: '0 8 * * *'
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
permissions:
|
|
||||||
actions: write
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
dispatch-test:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Setup Test
|
|
||||||
steps:
|
|
||||||
- name: dispatch test by tag
|
|
||||||
if: ${{ github.event_name == 'push' || github.event_name == 'workflow_dispatch' }}
|
|
||||||
uses: benc-uk/workflow-dispatch@v1
|
|
||||||
with:
|
|
||||||
workflow: copilot-test.yml
|
|
||||||
- name: dispatch test by schedule
|
|
||||||
if: ${{ github.event_name == 'schedule' }}
|
|
||||||
uses: benc-uk/workflow-dispatch@v1
|
|
||||||
with:
|
|
||||||
workflow: copilot-test.yml
|
|
||||||
ref: canary
|
|
||||||
206
.github/workflows/copilot-test.yml
vendored
206
.github/workflows/copilot-test.yml
vendored
@@ -1,206 +0,0 @@
|
|||||||
name: Copilot Cron Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-server-native:
|
|
||||||
name: Build Server native
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
CARGO_PROFILE_RELEASE_DEBUG: '1'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
extra-flags: workspaces focus @affine/server-native
|
|
||||||
electron-install: false
|
|
||||||
- name: Build Rust
|
|
||||||
uses: ./.github/actions/build-rust
|
|
||||||
with:
|
|
||||||
target: 'x86_64-unknown-linux-gnu'
|
|
||||||
package: '@affine/server-native'
|
|
||||||
- name: Upload server-native.node
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: server-native.node
|
|
||||||
path: ./packages/backend/native/server-native.node
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
copilot-api-test:
|
|
||||||
name: Server Copilot Api Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs:
|
|
||||||
- build-server-native
|
|
||||||
env:
|
|
||||||
NODE_ENV: test
|
|
||||||
DISTRIBUTION: web
|
|
||||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
|
||||||
REDIS_SERVER_HOST: localhost
|
|
||||||
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
|
|
||||||
indexer:
|
|
||||||
image: manticoresearch/manticore:10.1.0
|
|
||||||
ports:
|
|
||||||
- 9308:9308
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
playwright-install: true
|
|
||||||
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
|
|
||||||
env:
|
|
||||||
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
|
||||||
uses: ./.github/actions/server-test-env
|
|
||||||
|
|
||||||
- name: Run server tests
|
|
||||||
run: yarn affine @affine/server test:copilot:coverage --forbid-only
|
|
||||||
env:
|
|
||||||
CARGO_TARGET_DIR: '${{ github.workspace }}/target'
|
|
||||||
|
|
||||||
- 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
|
|
||||||
|
|
||||||
copilot-e2e-test:
|
|
||||||
name: Frontend Copilot E2E Test
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
DISTRIBUTION: web
|
|
||||||
DATABASE_URL: postgresql://affine:affine@localhost:5432/affine
|
|
||||||
REDIS_SERVER_HOST: localhost
|
|
||||||
IN_CI_TEST: true
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
shardIndex: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
|
|
||||||
shardTotal: [10]
|
|
||||||
needs:
|
|
||||||
- build-server-native
|
|
||||||
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
|
|
||||||
indexer:
|
|
||||||
image: manticoresearch/manticore:10.1.0
|
|
||||||
ports:
|
|
||||||
- 9308:9308
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
playwright-install: true
|
|
||||||
electron-install: false
|
|
||||||
hard-link-nm: false
|
|
||||||
|
|
||||||
- name: Download server-native.node
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: server-native.node
|
|
||||||
path: ./packages/backend/native
|
|
||||||
|
|
||||||
- name: Prepare Server Test Environment
|
|
||||||
env:
|
|
||||||
SERVER_CONFIG: ${{ secrets.TEST_SERVER_CONFIG }}
|
|
||||||
uses: ./.github/actions/server-test-env
|
|
||||||
|
|
||||||
- name: Run Copilot E2E Test ${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
|
||||||
uses: ./.github/actions/copilot-test
|
|
||||||
with:
|
|
||||||
script: yarn affine @affine-test/affine-cloud-copilot e2e --forbid-only --shard=${{ matrix.shardIndex }}/${{ matrix.shardTotal }}
|
|
||||||
|
|
||||||
test-done:
|
|
||||||
needs:
|
|
||||||
- copilot-api-test
|
|
||||||
- copilot-e2e-test
|
|
||||||
if: always()
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: Post test result message
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
fetch-depth: 0
|
|
||||||
- name: Setup Node.js
|
|
||||||
uses: ./.github/actions/setup-node
|
|
||||||
with:
|
|
||||||
extra-flags: 'workspaces focus @affine/copilot-result'
|
|
||||||
electron-install: false
|
|
||||||
- name: Post Success event to a Slack channel
|
|
||||||
if: ${{ always() && !contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled') }}
|
|
||||||
run: node ./tools/copilot-result/index.js
|
|
||||||
env:
|
|
||||||
CHANNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
|
|
||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
||||||
BRANCH_SHA: ${{ github.sha }}
|
|
||||||
BRANCH_NAME: ${{ github.ref }}
|
|
||||||
COPILOT_RESULT: success
|
|
||||||
- name: Post Failed event to a Slack channel
|
|
||||||
id: failed-slack
|
|
||||||
if: ${{ always() && contains(needs.*.result, 'failure') }}
|
|
||||||
run: node ./tools/copilot-result/index.js
|
|
||||||
env:
|
|
||||||
CHANNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
|
|
||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
||||||
BRANCH_SHA: ${{ github.sha }}
|
|
||||||
BRANCH_NAME: ${{ github.ref }}
|
|
||||||
COPILOT_RESULT: failed
|
|
||||||
- name: Post Cancel event to a Slack channel
|
|
||||||
id: cancel-slack
|
|
||||||
if: ${{ always() && contains(needs.*.result, 'cancelled') && !contains(needs.*.result, 'failure') }}
|
|
||||||
run: node ./tools/copilot-result/index.js
|
|
||||||
env:
|
|
||||||
CHANNEL_ID: ${{ secrets.RELEASE_SLACK_CHNNEL_ID }}
|
|
||||||
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
|
|
||||||
BRANCH_SHA: ${{ github.sha }}
|
|
||||||
BRANCH_NAME: ${{ github.ref }}
|
|
||||||
COPILOT_RESULT: canceled
|
|
||||||
32
.github/workflows/deploy-automatically.yml
vendored
Normal file
32
.github/workflows/deploy-automatically.yml
vendored
Normal file
@@ -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
|
||||||
195
.github/workflows/deploy.yml
vendored
Normal file
195
.github/workflows/deploy.yml
vendored
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
name: Deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
flavor:
|
||||||
|
description: 'Select what enverionment to deploy to'
|
||||||
|
type: choice
|
||||||
|
default: canary
|
||||||
|
options:
|
||||||
|
- canary
|
||||||
|
- beta
|
||||||
|
- stable
|
||||||
|
- internal
|
||||||
|
env:
|
||||||
|
NX_CLOUD_ACCESS_TOKEN: ${{ secrets.NX_CLOUD_ACCESS_TOKEN }}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: 'write'
|
||||||
|
id-token: 'write'
|
||||||
|
packages: 'write'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-server-image:
|
||||||
|
name: Build Server Image
|
||||||
|
uses: ./.github/workflows/build-server-image.yml
|
||||||
|
with:
|
||||||
|
flavor: ${{ github.event.inputs.flavor }}
|
||||||
|
|
||||||
|
build-web:
|
||||||
|
name: Build @affine/web
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: ${{ github.event.inputs.flavor }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
- name: Build Core
|
||||||
|
run: yarn nx build @affine/web --skip-nx-cache
|
||||||
|
env:
|
||||||
|
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
||||||
|
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
BUILD_TYPE: ${{ github.event.inputs.flavor }}
|
||||||
|
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: 'affine-web'
|
||||||
|
SENTRY_RELEASE: ${{ steps.version.outputs.APP_VERSION }}
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
|
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
||||||
|
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
||||||
|
- name: Upload web artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: web
|
||||||
|
path: ./packages/frontend/web/dist
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-admin:
|
||||||
|
name: Build @affine/admin
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: ${{ github.event.inputs.flavor }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Version
|
||||||
|
id: version
|
||||||
|
uses: ./.github/actions/setup-version
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: ./.github/actions/setup-node
|
||||||
|
- name: Build Core
|
||||||
|
run: yarn nx build @affine/admin --skip-nx-cache
|
||||||
|
env:
|
||||||
|
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
||||||
|
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
BUILD_TYPE: ${{ github.event.inputs.flavor }}
|
||||||
|
CAPTCHA_SITE_KEY: ${{ secrets.CAPTCHA_SITE_KEY }}
|
||||||
|
SENTRY_ORG: ${{ secrets.SENTRY_ORG }}
|
||||||
|
SENTRY_PROJECT: 'affine-admin'
|
||||||
|
SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }}
|
||||||
|
SENTRY_DSN: ${{ secrets.SENTRY_DSN }}
|
||||||
|
PERFSEE_TOKEN: ${{ secrets.PERFSEE_TOKEN }}
|
||||||
|
MIXPANEL_TOKEN: ${{ secrets.MIXPANEL_TOKEN }}
|
||||||
|
- name: Upload admin artifact
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: admin
|
||||||
|
path: ./packages/frontend/admin/dist
|
||||||
|
if-no-files-found: error
|
||||||
|
|
||||||
|
build-frontend-image:
|
||||||
|
name: Build Frontend Image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs:
|
||||||
|
- build-web
|
||||||
|
- build-admin
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Download web artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: web
|
||||||
|
path: ./packages/frontend/web/dist
|
||||||
|
- name: Download admin artifact
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: admin
|
||||||
|
path: ./packages/frontend/admin/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
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
logout: false
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Build front Dockerfile
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
push: true
|
||||||
|
pull: true
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
provenance: true
|
||||||
|
file: .github/deployment/front/Dockerfile
|
||||||
|
tags: ghcr.io/toeverything/affine-front:${{env.RELEASE_FLAVOR}}-${{ env.GIT_SHORT_HASH }},ghcr.io/toeverything/affine-front:${{env.RELEASE_FLAVOR}}
|
||||||
|
|
||||||
|
deploy:
|
||||||
|
name: Deploy to cluster
|
||||||
|
if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||||
|
environment: ${{ github.event.inputs.flavor }}
|
||||||
|
needs:
|
||||||
|
- build-frontend-image
|
||||||
|
- build-server-image
|
||||||
|
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 }}
|
||||||
|
R2_ACCOUNT_ID: ${{ secrets.R2_ACCOUNT_ID }}
|
||||||
|
R2_ACCESS_KEY_ID: ${{ secrets.R2_ACCESS_KEY_ID }}
|
||||||
|
R2_SECRET_ACCESS_KEY: ${{ secrets.R2_SECRET_ACCESS_KEY }}
|
||||||
|
CAPTCHA_TURNSTILE_SECRET: ${{ secrets.CAPTCHA_TURNSTILE_SECRET }}
|
||||||
|
COPILOT_OPENAI_API_KEY: ${{ secrets.COPILOT_OPENAI_API_KEY }}
|
||||||
|
COPILOT_FAL_API_KEY: ${{ secrets.COPILOT_FAL_API_KEY }}
|
||||||
|
COPILOT_UNSPLASH_API_KEY: ${{ secrets.COPILOT_UNSPLASH_API_KEY }}
|
||||||
|
METRICS_CUSTOMER_IO_TOKEN: ${{ secrets.METRICS_CUSTOMER_IO_TOKEN }}
|
||||||
|
MAILER_SENDER: ${{ secrets.OAUTH_EMAIL_SENDER }}
|
||||||
|
MAILER_USER: ${{ secrets.OAUTH_EMAIL_LOGIN }}
|
||||||
|
MAILER_PASSWORD: ${{ secrets.OAUTH_EMAIL_PASSWORD }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
AFFINE_GOOGLE_CLIENT_ID: ${{ secrets.AFFINE_GOOGLE_CLIENT_ID }}
|
||||||
|
AFFINE_GOOGLE_CLIENT_SECRET: ${{ secrets.AFFINE_GOOGLE_CLIENT_SECRET }}
|
||||||
|
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 }}
|
||||||
|
GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT: ${{ secrets.GCLOUD_CLOUD_SQL_INTERNAL_ENDPOINT }}
|
||||||
|
REDIS_HOST: ${{ secrets.REDIS_HOST }}
|
||||||
|
REDIS_PASSWORD: ${{ secrets.REDIS_PASSWORD }}
|
||||||
|
CLOUD_SQL_IAM_ACCOUNT: ${{ secrets.CLOUD_SQL_IAM_ACCOUNT }}
|
||||||
|
STRIPE_API_KEY: ${{ secrets.STRIPE_API_KEY }}
|
||||||
|
STRIPE_WEBHOOK_KEY: ${{ secrets.STRIPE_WEBHOOK_KEY }}
|
||||||
|
STATIC_IP_NAME: ${{ secrets.STATIC_IP_NAME }}
|
||||||
66
.github/workflows/helm-releaser.yml
vendored
Normal file
66
.github/workflows/helm-releaser.yml
vendored
Normal 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
.github/workflows/label-checker.yml
vendored
Normal file
19
.github/workflows/label-checker.yml
vendored
Normal 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 }}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user