From 41eefcdcfa6b2dc0e1378398b173073b7d5c0c67 Mon Sep 17 00:00:00 2001 From: uonr Date: Tue, 26 Dec 2023 08:35:36 +0900 Subject: [PATCH] feat: add devcontainer support (#234) * style: format * feat: devcontainer * feat: minio * fix: pgadmin password * fix: remove `just env` * feat: adjust configurations * feat: custom docker image * fix: direnv * fix: initialize minio --- .devcontainer/.env | 7 +++ .devcontainer/Dockerfile | 19 ++++++ .devcontainer/devcontainer.json | 36 +++++++++++ .devcontainer/docker-compose.yml | 93 +++++++++++++++++++++++++++++ .devcontainer/servers.json | 21 +++++++ .env.local.example | 12 ++++ .env.local.template | 11 ---- .envrc | 1 + .gitignore | 3 +- .vscode/settings.json | 10 ++-- apps/server/bindings/ClientEvent.ts | 4 +- apps/server/bindings/EventBody.ts | 24 ++++---- apps/server/src/context.rs | 4 +- apps/server/src/server.rs | 9 +++ docker-compose.yaml | 15 ----- justfile | 2 + migrations.json | 27 --------- 17 files changed, 222 insertions(+), 76 deletions(-) create mode 100644 .devcontainer/.env create mode 100644 .devcontainer/Dockerfile create mode 100644 .devcontainer/devcontainer.json create mode 100644 .devcontainer/docker-compose.yml create mode 100644 .devcontainer/servers.json create mode 100644 .env.local.example delete mode 100644 .env.local.template create mode 100644 .envrc delete mode 100644 docker-compose.yaml delete mode 100644 migrations.json diff --git a/.devcontainer/.env b/.devcontainer/.env new file mode 100644 index 00000000..0c4d7847 --- /dev/null +++ b/.devcontainer/.env @@ -0,0 +1,7 @@ +POSTGRES_USER=boluo +POSTGRES_PASSWORD=boluo +PGADMIN_DEFAULT_EMAIL=dev@boluo.chat +PGADMIN_DEFAULT_PASSWORD=boluo +PGADMIN_LISTEN_PORT=4841 +MINIO_ROOT_USER=boluo +MINIO_ROOT_PASSWORD=boluo-development diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 00000000..4eb55954 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,19 @@ +FROM ubuntu:latest +RUN apt update -y +RUN apt install -y curl xz-utils git && mkdir /nix +RUN \ + useradd -m -s /bin/bash -u 1000 dev;\ + chown dev /nix;\ + mkdir -p /etc/nix;\ + echo "experimental-features = nix-command flakes" >> /etc/nix/nix.conf +ENV USER=dev +USER dev +WORKDIR /home/dev +RUN curl -L https://nixos.org/nix/install | sh -s -- --no-daemon; +ENV PATH="/home/dev/.nix-profile/bin:${PATH}" + +ARG PNPM_STORE_DIR=/home/dev/.local/share/pnpm +ENV PNPM_STORE_DIR=${PNPM_STORE_DIR} +RUN mkdir -p "${PNPM_STORE_DIR}" +COPY --chown=dev:dev flake.lock flake.nix rust-toolchain.toml ./ +RUN nix develop --command bash -c "pnpm config set store-dir ${PNPM_STORE_DIR}" && rm flake.lock flake.nix rust-toolchain.toml diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 00000000..793444fe --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,36 @@ +// For format details, see https://aka.ms/devcontainer.json. For config options, see the +// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node-postgres +{ + "name": "Boluo", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspaces/${localWorkspaceFolderBasename}", + // Features to add to the dev container. More info: https://containers.dev/features. + "features": { + "ghcr.io/christophermacgown/devcontainer-features/direnv:1": {} + }, + + // Configure tool-specific properties. + "customizations": { + "vscode": { + "extensions": [ + "EditorConfig.EditorConfig", + "bradlc.vscode-tailwindcss", + "dprint.dprint", + "rust-lang.rust-analyzer", + "mkhl.direnv", + "dbaeumer.vscode-eslint" + ] + } + }, + + // Use 'forwardPorts' to make a list of ports inside the container available locally. + // This can be used to network with other containers or with the host. + "forwardPorts": [3000, 4841, 9000, 9090, 8080], + // Use 'postCreateCommand' to run commands after the container is created. + "postCreateCommand": "cp .env.local.example .env.local && direnv allow", + + // More info: https://aka.ms/dev-containers-non-root. + "remoteUser": "dev", + "containerUser": "dev" +} diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 00000000..0a46a5d3 --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,93 @@ +version: '3.8' + +services: + app: + build: + context: .. + dockerfile: .devcontainer/Dockerfile + + volumes: + - ../..:/workspaces:cached + + # Overrides default command so things don't shut down after the process ends. + command: sleep infinity + + # Runs app on the same network as the database container, allows "forwardPorts" in devcontainer.json function. + network_mode: service:db + + # Use "forwardPorts" in **devcontainer.json** to forward an app port locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + + redis: + image: redis + restart: unless-stopped + + db: + image: postgres:latest + restart: unless-stopped + volumes: + - postgres-data:/var/lib/postgresql/data + - ../apps/server/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + + db-test: + image: postgres:latest + restart: unless-stopped + volumes: + - ../apps/server/schema.sql:/docker-entrypoint-initdb.d/schema.sql:ro + environment: + - POSTGRES_USER=${POSTGRES_USER} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + + pgadmin: + image: dpage/pgadmin4 + restart: unless-stopped + volumes: + - ./servers.json:/pgadmin4/servers.json:ro + depends_on: + - db + - db-test + environment: + - PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL} + - PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD} + - PGADMIN_LISTEN_PORT=${PGADMIN_LISTEN_PORT} + - PGADMIN_CONFIG_SERVER_MODE=FALSE + - PGADMIN_CONFIG_MASTER_PASSWORD_REQUIRED=False + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + network_mode: service:db + + store: + image: quay.io/minio/minio + restart: unless-stopped + network_mode: service:db + volumes: + - minio-data:/data + environment: + - MINIO_ROOT_USER=${MINIO_ROOT_USER} + - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD} + command: server /data --console-address ":9090" + + + store-init: + image: quay.io/minio/mc + network_mode: service:db + depends_on: + - store + entrypoint: > + /bin/sh -c " + sleep 10; + /usr/bin/mc config host add devminio http://127.0.0.1:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD}; + /usr/bin/mc rm -r --force devminio/boluo; + /usr/bin/mc mb devminio/boluo; + /usr/bin/mc anonymous set public devminio/boluo; + exit 0; + " + # Add "forwardPorts": ["5432"] to **devcontainer.json** to forward PostgreSQL locally. + # (Adding the "ports" property to this file will not forward from a Codespace.) + +volumes: + nix-store: + postgres-data: + minio-data: diff --git a/.devcontainer/servers.json b/.devcontainer/servers.json new file mode 100644 index 00000000..b3461ae4 --- /dev/null +++ b/.devcontainer/servers.json @@ -0,0 +1,21 @@ +{ + "Servers": { + "1": { + "Name": "boluo", + "Group": "Servers", + "Host": "db", + "Port": 5432, + "MaintenanceDB": "postgres", + "Username": "boluo", + "UseSSHTunnel": 0, + "TunnelPort": "22", + "TunnelAuthentication": 0, + "KerberosAuthentication": false, + "ConnectionParameters": { + "sslmode": "prefer", + "connect_timeout": 10 + }, + "PasswordExecCommand": "echo $POSTGRES_PASSWORD" + } + } +} diff --git a/.env.local.example b/.env.local.example new file mode 100644 index 00000000..c6a9c48e --- /dev/null +++ b/.env.local.example @@ -0,0 +1,12 @@ +DATABASE_URL=postgresql://boluo:boluo@db/boluo?sslmode=disable +TEST_DATABASE_URL=postgresql://boluo:boluo@db-test/boluo?sslmode=disable +REDIS_URL=redis://redis:6379 +BACKEND_URL=http://127.0.0.1:3000 + +SECRET=SOME_SECRET +S3_ACCESS_KEY_ID=boluo +S3_SECRET_ACCESS_KEY=boluo-development +S3_ENDPOINT_URL=http://127.0.0.1:9000 +S3_BUCKET_NAME=boluo + +PUBLIC_MEDIA_URL=http://127.0.0.1:9000/boluo diff --git a/.env.local.template b/.env.local.template deleted file mode 100644 index 3691501e..00000000 --- a/.env.local.template +++ /dev/null @@ -1,11 +0,0 @@ -DATABASE_URL=postgresql://username:password@host/boluo -TEST_DATABASE_URL=postgresql://username:password@host/boluo_test -BACKEND_URL=https://example.com - -SECRET=SOME_SECRET -S3_ACCESS_KEY_ID=00000000000000000000000000000000 -S3_SECRET_ACCESS_KEY=0000000000000000000000000000000000000000000000000000000000000000 -S3_ENDPOINT_URL=https://00000000000000000000000000000000.r2.cloudflarestorage.com -S3_BUCKET_NAME=boluo-0000 - -PUBLIC_MEDIA_URL=https://media.example.com diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..3550a30f --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +use flake diff --git a/.gitignore b/.gitignore index 38add786..b1dd69b3 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,6 @@ .bin/ /media -.envrc .env.local .env*.local **/*.tsbuildinfo @@ -49,4 +48,4 @@ testem.log .DS_Store Thumbs.db -.nx/cache \ No newline at end of file +.nx/cache diff --git a/.vscode/settings.json b/.vscode/settings.json index 6968ce93..3a879092 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,9 @@ { + "files.associations": { + "tailwind.css": "tailwindcss", + "*.tailwind.css": "tailwindcss", + ".env.local.example": "properties" + }, // ESLint "eslint.workingDirectories": [ { @@ -37,8 +42,5 @@ "editor.quickSuggestions": { "strings": true }, - "tailwindCSS.experimental.configFile": "packages/ui/tailwind.config.mjs", - "files.associations": { - "tailwind.css": "tailwindcss" - } + "tailwindCSS.experimental.configFile": "packages/ui/tailwind.config.mjs" } diff --git a/apps/server/bindings/ClientEvent.ts b/apps/server/bindings/ClientEvent.ts index 8c4fe9a2..4a70da2e 100644 --- a/apps/server/bindings/ClientEvent.ts +++ b/apps/server/bindings/ClientEvent.ts @@ -2,8 +2,8 @@ import type { PreviewPost } from './PreviewPost'; import type { StatusKind } from './StatusKind'; -export type ClientEvent = { type: 'PREVIEW'; preview: PreviewPost } | { - type: 'STATUS'; +export type ClientEvent = { 'type': 'PREVIEW'; preview: PreviewPost } | { + 'type': 'STATUS'; kind: StatusKind; focus: Array; }; diff --git a/apps/server/bindings/EventBody.ts b/apps/server/bindings/EventBody.ts index 17a15d7e..7836675c 100644 --- a/apps/server/bindings/EventBody.ts +++ b/apps/server/bindings/EventBody.ts @@ -7,15 +7,15 @@ import type { SpaceWithRelated } from './SpaceWithRelated'; import type { UserStatus } from './UserStatus'; export type EventBody = - | { type: 'NEW_MESSAGE'; channelId: string; message: Message; previewId: string | null } - | { type: 'MESSAGE_DELETED'; messageId: string; channelId: string } - | { type: 'MESSAGE_EDITED'; channelId: string; message: Message } - | { type: 'MESSAGE_PREVIEW'; channelId: string; preview: Preview } - | { type: 'CHANNEL_DELETED'; channelId: string } - | { type: 'CHANNEL_EDITED'; channelId: string; channel: Channel } - | { type: 'MEMBERS'; channelId: string; members: Array } - | { type: 'BATCH'; encodedEvents: Array } - | { type: 'INITIALIZED' } - | { type: 'STATUS_MAP'; statusMap: Record; spaceId: string } - | { type: 'SPACE_UPDATED'; spaceWithRelated: SpaceWithRelated } - | { type: 'APP_UPDATED'; version: string }; + | { 'type': 'NEW_MESSAGE'; channelId: string; message: Message; previewId: string | null } + | { 'type': 'MESSAGE_DELETED'; messageId: string; channelId: string } + | { 'type': 'MESSAGE_EDITED'; channelId: string; message: Message } + | { 'type': 'MESSAGE_PREVIEW'; channelId: string; preview: Preview } + | { 'type': 'CHANNEL_DELETED'; channelId: string } + | { 'type': 'CHANNEL_EDITED'; channelId: string; channel: Channel } + | { 'type': 'MEMBERS'; channelId: string; members: Array } + | { 'type': 'BATCH'; encodedEvents: Array } + | { 'type': 'INITIALIZED' } + | { 'type': 'STATUS_MAP'; statusMap: Record; spaceId: string } + | { 'type': 'SPACE_UPDATED'; spaceWithRelated: SpaceWithRelated } + | { 'type': 'APP_UPDATED'; version: string }; diff --git a/apps/server/src/context.rs b/apps/server/src/context.rs index 9254e6d9..6453b690 100644 --- a/apps/server/src/context.rs +++ b/apps/server/src/context.rs @@ -27,9 +27,7 @@ pub fn media_public_url() -> &'static str { static MEDIA_PUBLIC_URL: OnceCell = OnceCell::new(); MEDIA_PUBLIC_URL.get_or_init(|| { let url = env::var("PUBLIC_MEDIA_URL").unwrap_or_default(); - let url = url.trim_end_matches('/'); - let url = url.trim_start_matches("https://"); - format!("https://{}", url) + url.trim_end_matches('/').to_owned() }) } diff --git a/apps/server/src/server.rs b/apps/server/src/server.rs index c1653599..f7b428bd 100644 --- a/apps/server/src/server.rs +++ b/apps/server/src/server.rs @@ -122,6 +122,15 @@ async fn main() { // https://tokio.rs/tokio/topics/shutdown let mut stream = signal(SignalKind::terminate()).unwrap(); + // check + let s3_client = s3::get_client(); + s3_client + .head_bucket() + .bucket(s3::get_bucket_name()) + .send() + .await + .expect("s3 bucket not found"); + #[allow(clippy::never_loop)] loop { tokio::select! { diff --git a/docker-compose.yaml b/docker-compose.yaml deleted file mode 100644 index 568a65bf..00000000 --- a/docker-compose.yaml +++ /dev/null @@ -1,15 +0,0 @@ -services: - site: # site - image: ghcr.io/mythal/boluo/site:master - build: - dockerfile: ./apps/site/Dockerfile - - legacy: - image: ghcr.io/mythal/boluo/legacy:master - build: - dockerfile: ./apps/legacy/Dockerfile - - server: - image: ghcr.io/mythal/boluo/server:master - build: - dockerfile: ./apps/server/Dockerfile diff --git a/justfile b/justfile index c3e1b376..f945328e 100644 --- a/justfile +++ b/justfile @@ -10,6 +10,7 @@ check: lint: pnpm exec nx run-many --target=lint pnpm exec dprint check + cargo fmt --check dev projects="*": pnpm exec nx run-many --target=dev --projects={{projects}} --parallel=16 @@ -28,6 +29,7 @@ install: format: pnpm exec dprint fmt + cargo fmt generate: pnpm exec nx run-many --target=generate diff --git a/migrations.json b/migrations.json deleted file mode 100644 index d9038173..00000000 --- a/migrations.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "migrations": [ - { - "cli": "nx", - "version": "17.0.0-beta.1", - "description": "Updates the default cache directory to .nx/cache", - "implementation": "./src/migrations/update-17-0-0/move-cache-directory", - "package": "nx", - "name": "17.0.0-move-cache-directory" - }, - { - "cli": "nx", - "version": "17.0.0-beta.3", - "description": "Use minimal config for tasksRunnerOptions", - "implementation": "./src/migrations/update-17-0-0/use-minimal-config-for-tasks-runner-options", - "package": "nx", - "name": "17.0.0-use-minimal-config-for-tasks-runner-options" - }, - { - "version": "17.0.0-rc.1", - "description": "Migration for v17.0.0-rc.1", - "implementation": "./src/migrations/update-17-0-0/rm-default-collection-npm-scope", - "package": "nx", - "name": "rm-default-collection-npm-scope" - } - ] -}