From 41a80b9da7faf924f00d52de84d0381832067bae Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:15:15 +0800 Subject: [PATCH 01/19] chore: add .gitattributes for consistent line endings and shell script support --- .gitattributes | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 000000000..bdc780ac2 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,18 @@ +# Git Attributes Configuration for Nomad Project + +# Ensure shell scripts use Unix line endings (LF) for Docker containers +# This is critical for DevContainer scripts which run in Linux containers +*.sh text eol=lf + +# Ensure consistent line endings for common text files +*.ts text +*.tsx text +*.js text +*.jsx text +*.json text +*.md text +*.yml text +*.yaml text + +# Ensure package manager lockfiles are not modified +pnpm-lock.yaml text eol=lf From 580e3353dccf08ee5c00fffc84b519c90c728ad5 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:15:26 +0800 Subject: [PATCH 02/19] chore(vscode): add extensions.json for recommended VSCode extensions --- .vscode/extensions.json | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 .vscode/extensions.json diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 000000000..851c3e4f7 --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,19 @@ +{ + "recommendations": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "biomejs.biome", + "editorconfig.editorconfig", + "dsznajder.es7-react-js-snippets", + "bradlc.vscode-tailwindcss", + "mtxr.sqltools", + "mtxr.sqltools-driver-pg", + "Playwright.playwright", + "ZixuanChen.vitest-explorer", + "eamodio.gitlens", + "usernamehw.errorlens", + "streetsidesoftware.code-spell-checker", + "DavidAnson.vscode-markdownlint", + "ms-azuretools.vscode-docker" + ] +} From 073d92adc0da90a93caab2e9d2fa3ba1dcf1b881 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:15:51 +0800 Subject: [PATCH 03/19] feat(devcontainer): add Dockerfile for development environment setup --- .devcontainer/Dockerfile | 61 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 .devcontainer/Dockerfile diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile new file mode 100644 index 000000000..778cf71a2 --- /dev/null +++ b/.devcontainer/Dockerfile @@ -0,0 +1,61 @@ +# syntax=docker/dockerfile:1.4 + +ARG NODE_VERSION=22.21.0 + +FROM node:${NODE_VERSION}-slim + +# Install necessary system dependencies +RUN apt-get update && apt-get install -y \ + git \ + ca-certificates \ + curl \ + gnupg \ + openssh-client \ + bash-completion \ + # Playwright browser dependencies + libnss3 \ + libnspr4 \ + libatk1.0-0 \ + libatk-bridge2.0-0 \ + libcups2 \ + libdrm2 \ + libxkbcommon0 \ + libxcomposite1 \ + libxdamage1 \ + libxfixes3 \ + libxrandr2 \ + libgbm1 \ + libasound2 \ + libpango-1.0-0 \ + libcairo2 \ + # PostgreSQL client for CLI debugging + postgresql-client \ + && rm -rf /var/lib/apt/lists/* + +# Install pnpm via corepack +ARG PNPM_VERSION=10.17.1 +RUN corepack enable && \ + corepack prepare pnpm@${PNPM_VERSION} --activate + +# Configure pnpm +ENV PNPM_HOME=/pnpm +ENV PATH=$PNPM_HOME:$PATH +RUN pnpm config set store-dir /pnpm/store + +# Set working directory +WORKDIR /workspace + +# Configure Git safe directory to avoid permission warnings +RUN git config --global --add safe.directory /workspace + +# Set up shell configuration for node user +USER node +RUN echo 'alias ll="ls -alh"' >> ~/.bashrc && \ + echo 'alias pn="pnpm"' >> ~/.bashrc && \ + echo 'export PS1="\[\e[32m\]\u@nomad-dev\[\e[m\]:\[\e[34m\]\w\[\e[m\]\$ "' >> ~/.bashrc + +# Health check +HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ + CMD node --version && pnpm --version || exit 1 + +CMD ["sleep", "infinity"] From 8c27071e617602dfd0abccd2dc9f65cae5b5310a Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:16:03 +0800 Subject: [PATCH 04/19] feat(devcontainer): add docker-compose.yml for development environment setup --- .devcontainer/docker-compose.yml | 82 ++++++++++++++++++++++++++++++++ 1 file changed, 82 insertions(+) create mode 100644 .devcontainer/docker-compose.yml diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml new file mode 100644 index 000000000..a86c5146e --- /dev/null +++ b/.devcontainer/docker-compose.yml @@ -0,0 +1,82 @@ +version: '3.8' + +services: + app: + build: + context: . + dockerfile: Dockerfile + args: + NODE_VERSION: 22.21.0 + PNPM_VERSION: 10.17.1 + + volumes: + - ..:/workspace:cached + - nomad-pnpm-store:/pnpm/store + - nomad-node-modules:/workspace/node_modules + - nomad-turbo-cache:/workspace/.turbo + + command: sleep infinity + + environment: + - NODE_ENV=development + - DATABASE_URL=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_dev + - DATABASE_URL_TEST=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_test + - BETTER_AUTH_URL=http://localhost:3000 + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev_secret_key_change_in_production_32_chars_min} + - LOG_LEVEL=${LOG_LEVEL:-debug} + - ENABLE_ALIYUN_SMS=${ENABLE_ALIYUN_SMS:-disabled} + - ENABLE_RESEND=${ENABLE_RESEND:-disabled} + - NEXT_PUBLIC_TURNSTILE_SITE_KEY=1x00000000000000000000AA + - TURNSTILE_SECRET_KEY=1x0000000000000000000000000000000AA + - RESEND_FROM_EMAIL=onboarding@resend.dev + - DATABASE_SSL=false + + depends_on: + postgres: + condition: service_healthy + + networks: + - nomad-network + + user: node + + postgres: + image: postgres:15-alpine + restart: unless-stopped + + volumes: + - nomad-postgres-data:/var/lib/postgresql/data + - ./init-scripts/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro + + environment: + POSTGRES_USER: nomad + POSTGRES_PASSWORD: nomad_dev_password + POSTGRES_DB: nomad_dev + POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" + + healthcheck: + test: ["CMD-SHELL", "pg_isready -U nomad -d nomad_dev"] + interval: 10s + timeout: 5s + retries: 5 + + networks: + - nomad-network + + ports: + - "5432:5432" + +volumes: + nomad-pnpm-store: + name: nomad-pnpm-store + nomad-node-modules: + name: nomad-node-modules + nomad-turbo-cache: + name: nomad-turbo-cache + nomad-postgres-data: + name: nomad-postgres-data + +networks: + nomad-network: + name: nomad-network + driver: bridge From 5226ad22e69684330260f37086fbccae8c4d1304 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:16:38 +0800 Subject: [PATCH 05/19] feat(devcontainer): add devcontainer.json for development environment setup --- .devcontainer/devcontainer.json | 131 ++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) create mode 100644 .devcontainer/devcontainer.json diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json new file mode 100644 index 000000000..ba912d394 --- /dev/null +++ b/.devcontainer/devcontainer.json @@ -0,0 +1,131 @@ +{ + "name": "Nomad OTA Platform", + "dockerComposeFile": "docker-compose.yml", + "service": "app", + "workspaceFolder": "/workspace", + + "features": { + "ghcr.io/devcontainers/features/git:1": {}, + "ghcr.io/devcontainers/features/github-cli:1": {} + }, + + "customizations": { + "vscode": { + "extensions": [ + "dbaeumer.vscode-eslint", + "esbenp.prettier-vscode", + "biomejs.biome", + "dsznajder.es7-react-js-snippets", + "styled-components.vscode-styled-components", + "mtxr.sqltools", + "mtxr.sqltools-driver-pg", + "Playwright.playwright", + "ZixuanChen.vitest-explorer", + "EditorConfig.EditorConfig", + "DavidAnson.vscode-markdownlint", + "usernamehw.errorlens", + "bradlc.vscode-tailwindcss", + "ms-azuretools.vscode-docker" + ], + + "settings": { + "editor.defaultFormatter": "biomejs.biome", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "quickfix.biome": "explicit", + "source.organizeImports.biome": "explicit" + }, + "[markdown]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + }, + "[json]": { + "editor.defaultFormatter": "biomejs.biome" + }, + "typescript.tsdk": "node_modules/typescript/lib", + "typescript.enablePromptUseWorkspaceTsdk": true, + "files.watcherExclude": { + "**/.git/objects/**": true, + "**/.git/subtree-cache/**": true, + "**/node_modules/**": true, + "**/.next/**": true, + "**/.turbo/**": true, + "**/dist/**": true + }, + "search.exclude": { + "**/node_modules": true, + "**/.next": true, + "**/.turbo": true, + "**/dist": true, + "pnpm-lock.yaml": true + }, + "sqltools.connections": [ + { + "name": "Nomad Development DB", + "driver": "PostgreSQL", + "previewLimit": 50, + "server": "postgres", + "port": 5432, + "database": "nomad_dev", + "username": "nomad", + "password": "nomad_dev_password" + }, + { + "name": "Nomad Test DB", + "driver": "PostgreSQL", + "previewLimit": 50, + "server": "postgres", + "port": 5432, + "database": "nomad_test", + "username": "nomad", + "password": "nomad_dev_password" + } + ] + } + } + }, + + "forwardPorts": [3000, 3001, 3002, 5432, 6006, 6007], + + "portsAttributes": { + "3000": { + "label": "Web App", + "onAutoForward": "notify" + }, + "3001": { + "label": "Documentation", + "onAutoForward": "silent" + }, + "3002": { + "label": "Demo (Remotion)", + "onAutoForward": "silent" + }, + "5432": { + "label": "PostgreSQL", + "onAutoForward": "silent" + }, + "6006": { + "label": "Storybook", + "onAutoForward": "silent" + }, + "6007": { + "label": "React Email", + "onAutoForward": "silent" + } + }, + + "postCreateCommand": "bash .devcontainer/init-scripts/postCreateCommand.sh", + "postStartCommand": "bash .devcontainer/init-scripts/postStartCommand.sh", + + "remoteUser": "node", + + "containerEnv": { + "NODE_ENV": "development", + "PNPM_HOME": "/pnpm", + "PATH": "/pnpm:${containerEnv:PATH}" + }, + + "mounts": [ + "source=nomad-pnpm-store,target=/pnpm/store,type=volume", + "source=nomad-node-modules,target=${containerWorkspaceFolder}/node_modules,type=volume" + ] +} From 0164479336e161e39e977eb02cd035e05f9f6711 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:16:48 +0800 Subject: [PATCH 06/19] feat(devcontainer): add initialization scripts for development environment setup --- .devcontainer/init-scripts/init-db.sh | 10 +++ .../init-scripts/postCreateCommand.sh | 75 +++++++++++++++++++ .../init-scripts/postStartCommand.sh | 21 ++++++ 3 files changed, 106 insertions(+) create mode 100644 .devcontainer/init-scripts/init-db.sh create mode 100644 .devcontainer/init-scripts/postCreateCommand.sh create mode 100644 .devcontainer/init-scripts/postStartCommand.sh diff --git a/.devcontainer/init-scripts/init-db.sh b/.devcontainer/init-scripts/init-db.sh new file mode 100644 index 000000000..73f66e469 --- /dev/null +++ b/.devcontainer/init-scripts/init-db.sh @@ -0,0 +1,10 @@ +#!/bin/bash +set -e + +# Create test database +psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL + CREATE DATABASE nomad_test; + GRANT ALL PRIVILEGES ON DATABASE nomad_test TO $POSTGRES_USER; +EOSQL + +echo "Test database 'nomad_test' created successfully" diff --git a/.devcontainer/init-scripts/postCreateCommand.sh b/.devcontainer/init-scripts/postCreateCommand.sh new file mode 100644 index 000000000..f87f2037d --- /dev/null +++ b/.devcontainer/init-scripts/postCreateCommand.sh @@ -0,0 +1,75 @@ +#!/bin/bash +set -e + +echo "Initializing Nomad development environment..." + +# Display environment information +echo "Node.js version: $(node --version)" +echo "pnpm version: $(pnpm --version)" + +# Install dependencies +echo "Installing dependencies..." +pnpm install --frozen-lockfile + +# Wait for database to be ready +echo "Waiting for PostgreSQL to be ready..." +until pg_isready -h postgres -U nomad -d nomad_dev > /dev/null 2>&1; do + echo "Waiting for database..." + sleep 2 +done +echo "Database is ready!" + +# Initialize development database +echo "Initializing development database..." +cd /workspace/apps/web +pnpm db:push + +# Seed development database (optional) +echo "Seeding development database..." +pnpm db:seed || echo "Warning: Seeding failed or skipped" + +# Initialize test database +echo "Initializing test database..." +export NODE_ENV=test +export DATABASE_URL=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_test +pnpm db:push || echo "Warning: Test DB initialization failed" + +# Install Playwright browsers +echo "Installing Playwright browsers..." +cd /workspace/apps/web +pnpm exec playwright install chromium --with-deps || echo "Warning: Playwright installation failed" + +# Create local environment variable file if it doesn't exist +cd /workspace/apps/web +if [ ! -f .env.local ]; then + echo "Creating .env.local for development..." + cat > .env.local << 'EOF' +# Local development overrides +# This file is automatically created by devcontainer + +# Database (managed by Docker Compose) +DATABASE_URL=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_dev + +# Auth (development defaults) +BETTER_AUTH_SECRET=dev_secret_key_change_in_production_32_chars_minimum +BETTER_AUTH_URL=http://localhost:3000 + +# Features (disabled by default in dev) +ENABLE_ALIYUN_SMS=disabled +ENABLE_RESEND=disabled + +# Logging +LOG_LEVEL=debug +EOF +fi + +# Return to workspace root +cd /workspace + +echo "" +echo "Setup complete! You can now:" +echo " - Run 'pnpm dev' to start all applications" +echo " - Run 'pnpm web:dev' to start only the web app" +echo " - Run 'pnpm web:test' to run tests" +echo " - Open http://localhost:3000 to view the app" +echo "" diff --git a/.devcontainer/init-scripts/postStartCommand.sh b/.devcontainer/init-scripts/postStartCommand.sh new file mode 100644 index 000000000..77fdd00bd --- /dev/null +++ b/.devcontainer/init-scripts/postStartCommand.sh @@ -0,0 +1,21 @@ +#!/bin/bash +set -e + +echo "Container started, running post-start checks..." + +# Check database connection +echo "Checking database connection..." +if pg_isready -h postgres -U nomad -d nomad_dev > /dev/null 2>&1; then + echo "Database connection OK" +else + echo "Warning: Database not ready, some features may not work" +fi + +# Display quick start guide +echo "" +echo "Quick Start Commands:" +echo " pnpm dev - Start all apps" +echo " pnpm web:dev - Start web app only" +echo " pnpm web:db:studio - Open Drizzle Studio" +echo " pnpm web:test - Run tests" +echo "" From fbca0a4efdc672ee3df58d146c5dd54d67e4fa2f Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:27:45 +0800 Subject: [PATCH 07/19] feat(devcontainer): add GitHub Actions workflow for DevContainer validation --- .github/workflows/devcontainer.yml | 63 ++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) create mode 100644 .github/workflows/devcontainer.yml diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml new file mode 100644 index 000000000..97f41d117 --- /dev/null +++ b/.github/workflows/devcontainer.yml @@ -0,0 +1,63 @@ +name: DevContainer Validation + +on: + pull_request: + paths: + - '.devcontainer/**' + - '.gitattributes' + push: + branches: + - main + - develop + paths: + - '.devcontainer/**' + - '.gitattributes' + workflow_dispatch: + +jobs: + validate-devcontainer: + name: Validate DevContainer Configuration + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Build and run DevContainer + uses: devcontainers/ci@v0.3 + with: + runCmd: | + echo "Validating DevContainer setup..." + + # Check Node.js and pnpm versions + echo "Node.js version: $(node --version)" + echo "pnpm version: $(pnpm --version)" + + # Verify database connection + echo "Checking PostgreSQL connection..." + pg_isready -h postgres -U nomad -d nomad_dev || exit 1 + + # Verify dependencies are installed + echo "Checking dependencies..." + test -d node_modules || exit 1 + + # Verify database schema is initialized + echo "Verifying database schema..." + cd /workspace/apps/web + pnpm drizzle-kit push --force || exit 1 + + # Run basic type checking + echo "Running TypeScript type check..." + cd /workspace + pnpm type-check || exit 1 + + # Run a smoke test + echo "Running smoke tests..." + cd /workspace/apps/web + pnpm test:unit --run || exit 1 + + echo "DevContainer validation successful!" + + - name: Summary + if: success() + run: echo "DevContainer configuration is valid and working correctly" From 8d422f342c128ccd1e9f9d89b9d088582b7759f9 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:27:51 +0800 Subject: [PATCH 08/19] feat(devcontainer): add DevContainer setup guide for development environment --- DEVCONTAINER.md | 485 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 485 insertions(+) create mode 100644 DEVCONTAINER.md diff --git a/DEVCONTAINER.md b/DEVCONTAINER.md new file mode 100644 index 000000000..7976a47fb --- /dev/null +++ b/DEVCONTAINER.md @@ -0,0 +1,485 @@ +# Nomad 项目 DevContainer 使用指南 + +本文档介绍如何使用 VSCode DevContainer 快速搭建 Nomad 项目的开发环境。 + +## 什么是 DevContainer? + +DevContainer(开发容器)是一种基于 Docker 的开发环境配置方案,它可以: + +- 统一团队的开发环境,避免"在我机器上可以运行"的问题 +- 自动安装所需的 Node.js、pnpm、PostgreSQL 等依赖 +- 隔离开发环境,不影响本地系统 +- 支持 Windows、macOS、Linux 跨平台使用 + +## 前置要求 + +### 必需软件 + +1. **Docker Desktop** 或 **Docker Engine** + - Windows/macOS: [Docker Desktop](https://www.docker.com/products/docker-desktop) + - Linux: Docker Engine + Docker Compose + +2. **Visual Studio Code** + - [下载 VSCode](https://code.visualstudio.com/) + +3. **Dev Containers 扩展** + - 在 VSCode 中搜索并安装 "Dev Containers" 扩展 + - 或运行命令: `code --install-extension ms-vscode-remote.remote-containers` + +### 系统要求 + +- **磁盘空间**: 至少 10GB 可用空间(用于 Docker 镜像和依赖) +- **内存**: 建议 8GB 及以上 +- **CPU**: 支持虚拟化(Windows 需启用 WSL2) + +## 快速开始 + +### 首次使用 + +1. **克隆仓库** + + ```bash + git clone https://github.com/ukeSJTU/nomad.git + cd nomad + ``` + +2. **(可选)配置环境变量** + + 如果需要测试外部服务(短信、邮件、OAuth 等),可以配置自定义环境变量: + + ```bash + cp .devcontainer/.env.devcontainer.example .devcontainer/.env.devcontainer + # 编辑 .env.devcontainer,添加你的 API 密钥 + ``` + +3. **在容器中打开项目** + + 在 VSCode 中打开项目文件夹,然后: + - 按 `F1` 或 `Cmd/Ctrl+Shift+P` 打开命令面板 + - 输入并选择: **Dev Containers: Reopen in Container** + - 或点击左下角的绿色图标,选择 "Reopen in Container" + +4. **等待初始化完成** + + 首次构建和初始化需要 10-15 分钟,过程包括: + - 构建 Docker 镜像(Node.js + 工具链) + - 启动 PostgreSQL 数据库 + - 安装项目依赖(pnpm install) + - 初始化数据库 schema + - 填充测试数据 + - 安装 Playwright 浏览器 + + 你可以在 VSCode 终端中查看进度。 + +5. **开始开发** + + 初始化完成后,运行: + + ```bash + pnpm dev + ``` + + 然后在浏览器中访问 [http://localhost:3000](http://localhost:3000) + +### 后续使用 + +容器配置完成后,每次使用只需: + +1. 打开 VSCode +2. 点击左下角绿色图标 → "Reopen in Container" +3. 等待约 30-60 秒容器启动 +4. 运行 `pnpm dev` 开始开发 + +## 常用命令 + +### 开发服务器 + +```bash +# 启动所有应用(web + docs + demo) +pnpm dev + +# 只启动 Web 应用(推荐) +pnpm web:dev + +# 启动文档站点 +pnpm docs:dev + +# 启动 Storybook(UI 组件库) +pnpm web:storybook +``` + +### 数据库管理 + +```bash +# 打开 Drizzle Studio(可视化数据库管理) +pnpm web:db:studio + +# 推送 schema 更改到数据库 +pnpm web:db:push + +# 重新填充测试数据 +pnpm web:db:seed + +# 使用 psql 连接数据库 +psql -h postgres -U nomad -d nomad_dev +``` + +### 测试 + +```bash +# 运行所有测试 +pnpm web:test + +# 运行单元测试 +pnpm web:test:unit + +# 运行集成测试 +pnpm web:test:integration + +# E2E 测试 +pnpm web:e2e + +# E2E 测试(带 UI) +pnpm web:e2e:ui +``` + +### 代码质量 + +```bash +# 代码检查 +pnpm lint + +# 自动修复代码问题 +pnpm lint:fix + +# 格式化代码 +pnpm format + +# TypeScript 类型检查 +pnpm type-check +``` + +## 容器配置说明 + +### 端口转发 + +以下端口会自动转发到本地: + +- **3000**: Web 应用(主应用) +- **3001**: 文档站点 +- **3002**: Demo 应用(Remotion) +- **5432**: PostgreSQL 数据库 +- **6006**: Storybook +- **6007**: React Email 预览 + +### 环境变量 + +环境变量的优先级(从高到低): + +1. `.devcontainer/.env.devcontainer`(你的自定义配置,不会提交到 Git) +2. `docker-compose.yml` 中的默认值 +3. `apps/web/.env.local`(容器自动创建) +4. `apps/web/.env`(项目默认配置) + +### 默认配置 + +开箱即用的默认配置: + +- **数据库**: PostgreSQL 15,用户名 `nomad`,密码 `nomad_dev_password` +- **外部服务**: 阿里云短信和 Resend 邮件服务默认**禁用** +- **日志级别**: `debug`(开发模式) +- **认证密钥**: 开发环境默认密钥(生产环境需更换) + +### 启用外部服务 + +如果需要测试短信或邮件功能: + +1. 创建 `.devcontainer/.env.devcontainer` 文件: + + ```bash + cp .devcontainer/.env.devcontainer.example .devcontainer/.env.devcontainer + ``` + +2. 编辑文件,添加你的 API 密钥: + + ```bash + # 启用阿里云短信 + ENABLE_ALIYUN_SMS=enabled + ALIBABA_CLOUD_ACCESS_KEY_ID=your_key_id + ALIBABA_CLOUD_ACCESS_KEY_SECRET=your_secret + ALIBABA_CLOUD_SMS_SIGN_NAME=YourAppName + ALIBABA_CLOUD_SMS_TEMPLATE_CODE=SMS_123456789 + + # 启用 Resend 邮件 + ENABLE_RESEND=enabled + RESEND_API_KEY=re_xxxxxxxxxxxxxxxxxxxx + RESEND_FROM_EMAIL=noreply@yourdomain.com + ``` + +3. 重建容器: + - 按 `F1` → **Dev Containers: Rebuild Container** + +## VSCode 扩展 + +容器会自动安装以下推荐扩展: + +- **Biome**: 代码格式化和检查(替代 ESLint + Prettier) +- **Playwright**: E2E 测试支持 +- **Vitest Explorer**: 单元测试运行器 +- **SQLTools**: 数据库管理工具 +- **Tailwind CSS IntelliSense**: Tailwind 自动补全 +- **GitLens**: Git 增强工具 +- **Error Lens**: 行内错误提示 + +### 使用 SQLTools 连接数据库 + +SQLTools 已预配置好数据库连接: + +1. 点击左侧活动栏的 SQLTools 图标 +2. 选择 "Nomad Development DB" 或 "Nomad Test DB" +3. 点击连接 +4. 即可查询和管理数据库 + +## 常见问题 + +### 容器构建失败 + +**症状**: Docker 构建时报错 + +**解决方案**: + +```bash +# 清理 Docker 缓存 +docker system prune -a + +# 重新构建容器 +# 在 VSCode 中: F1 → Dev Containers: Rebuild Container (Without Cache) +``` + +### 端口被占用 + +**症状**: "Port 3000 is already in use" + +**解决方案**: + +```bash +# macOS/Linux +lsof -ti:3000 | xargs kill + +# Windows +netstat -ano | findstr :3000 +taskkill /PID /F +``` + +### 数据库连接失败 + +**症状**: "ECONNREFUSED postgres:5432" + +**解决方案**: + +```bash +# 检查 PostgreSQL 容器状态 +docker ps + +# 查看数据库日志 +docker logs nomad-postgres + +# 重启数据库容器 +docker-compose -f .devcontainer/docker-compose.yml restart postgres +``` + +### pnpm install 失败 + +**症状**: 依赖安装失败或超时 + +**解决方案**: + +```bash +# 清理缓存并重新安装 +pnpm clean +pnpm install --frozen-lockfile + +# 如果仍然失败,尝试不使用 frozen-lockfile +pnpm install +``` + +### Playwright 浏览器缺失 + +**症状**: E2E 测试失败,提示浏览器未安装 + +**解决方案**: + +```bash +cd apps/web +pnpm exec playwright install chromium --with-deps +``` + +### Windows 行尾符问题 + +**症状**: 脚本执行失败,提示 `/bin/bash^M: bad interpreter` + +**解决方案**: + +项目已通过 `.gitattributes` 配置自动处理,但如果仍遇到问题: + +```bash +# 重新克隆仓库,确保 Git 自动转换行尾符 +git clone https://github.com/ukeSJTU/nomad.git +``` + +### 容器性能慢(Windows/macOS) + +**症状**: 文件读写和命令执行明显变慢 + +**优化方案**: + +1. 确保 Docker Desktop 分配了足够的资源(设置 → Resources) +2. 项目已使用命名卷缓存 `node_modules` 和 `pnpm store` +3. 避免在容器内编辑大文件(推荐在宿主机编辑,容器内执行) + +## 重建和清理 + +### 重建容器 + +如果遇到配置问题或需要更新容器: + +```bash +# 在 VSCode 中 +F1 → Dev Containers: Rebuild Container + +# 完全清理后重建(不保留缓存) +F1 → Dev Containers: Rebuild Container (Without Cache) +``` + +### 清理数据卷 + +如果需要完全重置环境(会删除所有数据): + +```bash +# 停止并删除容器 +docker-compose -f .devcontainer/docker-compose.yml down + +# 删除命名卷 +docker volume rm nomad-pnpm-store +docker volume rm nomad-node-modules +docker volume rm nomad-turbo-cache +docker volume rm nomad-postgres-data + +# 重新打开容器 +# VSCode: F1 → Dev Containers: Reopen in Container +``` + +## 性能优化建议 + +### 1. 限制文件监视范围 + +VSCode 设置已默认排除以下目录: + +- `node_modules` +- `.next` +- `.turbo` +- `dist` + +### 2. 使用 Turbo 缓存 + +项目已配置 Turbo 缓存卷,重复构建速度更快: + +```bash +# 查看缓存使用情况 +pnpm turbo:graph +``` + +### 3. 按需启动应用 + +不需要所有应用时,只启动 Web 应用: + +```bash +pnpm web:dev # 而不是 pnpm dev +``` + +### 4. 定期清理 Docker + +```bash +# 清理未使用的镜像和容器 +docker system prune + +# 查看磁盘占用 +docker system df +``` + +## 架构说明 + +### 为什么使用 Docker Compose? + +- **服务分离**: 应用容器和数据库容器独立管理 +- **健康检查**: 确保数据库就绪后才启动应用 +- **数据持久化**: PostgreSQL 数据不会随容器删除 +- **易于扩展**: 未来可添加 Redis、MinIO 等服务 + +### 为什么使用命名卷? + +- **pnpm-store**: 避免重复下载依赖包 +- **node_modules**: 跨容器重建保留已安装模块 +- **turbo-cache**: 持久化 Turborepo 构建缓存 +- **postgres-data**: 数据库数据持久化 + +**性能提升**: + +- 首次构建: 10-15 分钟 +- 重建容器: 1-2 分钟(依赖已缓存) + +### 环境变量分层设计 + +1. **开发默认值** (docker-compose.yml): 适合大多数开发场景,无需配置即可使用 +2. **个人覆盖** (.env.devcontainer): 开发者个人配置,不提交到 Git +3. **应用层配置** (apps/web/.env.local): 自动创建,支持 Next.js 约定 + +**好处**: 开箱即用 + 灵活定制 + 安全(敏感信息不提交) + +## 与现有工具集成 + +### Husky Git Hooks + +容器内 Git hooks 自动工作: + +- Pre-commit: Biome 检查和 lint-staged +- Commit-msg: Commitlint 验证提交信息 + +### Turborepo + +完全兼容: + +- 缓存卷 `nomad-turbo-cache` 持久化构建结果 +- 所有 workspace 可见 +- 守护进程正常运行 + +### Drizzle ORM + +自动配置: + +- `DATABASE_URL` 环境变量预设 +- 支持开发和测试数据库 +- `drizzle.config.ts` 无需修改 + +### Playwright + +浏览器预装: + +- Chromium 在初始化时自动安装 +- E2E 测试可立即运行 +- 支持 headed 和 UI 模式 + +## 技术支持 + +如果遇到问题: + +1. 查看本文档的"常见问题"部分 +2. 查看容器日志: VSCode 终端中的输出 +3. 在项目 GitHub 仓库提交 Issue +4. 联系项目维护者 + +## 参考资源 + +- [VSCode Dev Containers 官方文档](https://code.visualstudio.com/docs/devcontainers/containers) +- [Docker 官方文档](https://docs.docker.com/) +- [项目贡献指南](./CONTRIBUTING.md) From 81d1e921e0182953b87b7d648ea314cdd1f7ed28 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:36:14 +0800 Subject: [PATCH 09/19] feat(devcontainer): update VSCode extensions and database configuration for environment --- .devcontainer/devcontainer.json | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index ba912d394..c7771f916 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -15,16 +15,17 @@ "dbaeumer.vscode-eslint", "esbenp.prettier-vscode", "biomejs.biome", + "editorconfig.editorconfig", "dsznajder.es7-react-js-snippets", - "styled-components.vscode-styled-components", + "bradlc.vscode-tailwindcss", "mtxr.sqltools", "mtxr.sqltools-driver-pg", "Playwright.playwright", "ZixuanChen.vitest-explorer", - "EditorConfig.EditorConfig", - "DavidAnson.vscode-markdownlint", + "eamodio.gitlens", "usernamehw.errorlens", - "bradlc.vscode-tailwindcss", + "streetsidesoftware.code-spell-checker", + "DavidAnson.vscode-markdownlint", "ms-azuretools.vscode-docker" ], @@ -65,9 +66,9 @@ "previewLimit": 50, "server": "postgres", "port": 5432, - "database": "nomad_dev", - "username": "nomad", - "password": "nomad_dev_password" + "database": "${containerEnv:POSTGRES_DB:nomad_dev}", + "username": "${containerEnv:POSTGRES_USER:nomad}", + "password": "${containerEnv:POSTGRES_PASSWORD:nomad_dev_password}" }, { "name": "Nomad Test DB", @@ -76,8 +77,8 @@ "server": "postgres", "port": 5432, "database": "nomad_test", - "username": "nomad", - "password": "nomad_dev_password" + "username": "${containerEnv:POSTGRES_USER:nomad}", + "password": "${containerEnv:POSTGRES_PASSWORD:nomad_dev_password}" } ] } From d86cd30c5b676dc8020e041b327d72356eeb85f0 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Sun, 28 Dec 2025 14:36:25 +0800 Subject: [PATCH 10/19] feat(devcontainer): update Dockerfile and docker-compose for environment variable support --- .devcontainer/Dockerfile | 2 +- .devcontainer/docker-compose.yml | 14 +++++++------- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 778cf71a2..450787c5f 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -5,7 +5,7 @@ ARG NODE_VERSION=22.21.0 FROM node:${NODE_VERSION}-slim # Install necessary system dependencies -RUN apt-get update && apt-get install -y \ +RUN apt-get update && apt-get install -y --no-install-recommends \ git \ ca-certificates \ curl \ diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index a86c5146e..375f10129 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -19,10 +19,10 @@ services: environment: - NODE_ENV=development - - DATABASE_URL=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_dev - - DATABASE_URL_TEST=postgresql://nomad:nomad_dev_password@postgres:5432/nomad_test + - DATABASE_URL=postgresql://${POSTGRES_USER:-nomad}:${POSTGRES_PASSWORD:-nomad_dev_password}@postgres:5432/${POSTGRES_DB:-nomad_dev} + - DATABASE_URL_TEST=postgresql://${POSTGRES_USER:-nomad}:${POSTGRES_PASSWORD:-nomad_dev_password}@postgres:5432/nomad_test - BETTER_AUTH_URL=http://localhost:3000 - - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev_secret_key_change_in_production_32_chars_min} + - BETTER_AUTH_SECRET=${BETTER_AUTH_SECRET:-dev_secret_key_change_in_production_32_chars_minimum} - LOG_LEVEL=${LOG_LEVEL:-debug} - ENABLE_ALIYUN_SMS=${ENABLE_ALIYUN_SMS:-disabled} - ENABLE_RESEND=${ENABLE_RESEND:-disabled} @@ -49,13 +49,13 @@ services: - ./init-scripts/init-db.sh:/docker-entrypoint-initdb.d/init-db.sh:ro environment: - POSTGRES_USER: nomad - POSTGRES_PASSWORD: nomad_dev_password - POSTGRES_DB: nomad_dev + POSTGRES_USER: ${POSTGRES_USER:-nomad} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-nomad_dev_password} + POSTGRES_DB: ${POSTGRES_DB:-nomad_dev} POSTGRES_INITDB_ARGS: "--encoding=UTF8 --locale=C" healthcheck: - test: ["CMD-SHELL", "pg_isready -U nomad -d nomad_dev"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-nomad} -d ${POSTGRES_DB:-nomad_dev}"] interval: 10s timeout: 5s retries: 5 From 3fb0b73261d428b44a00a21bae4c48d379c05e89 Mon Sep 17 00:00:00 2001 From: Mingxi Lv Date: Sun, 28 Dec 2025 14:41:57 +0800 Subject: [PATCH 11/19] fix: add read permission for devcontainer verification workflow Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com> --- .github/workflows/devcontainer.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index 97f41d117..c4f470d07 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -1,5 +1,8 @@ name: DevContainer Validation +permissions: + contents: read + on: pull_request: paths: From b91fb175734c7a481ffca2e3fd72bee5bce561d8 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 00:28:32 +0800 Subject: [PATCH 12/19] feat(devcontainer): enhance CI environment setup for faster initialization --- .../init-scripts/postCreateCommand.sh | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/.devcontainer/init-scripts/postCreateCommand.sh b/.devcontainer/init-scripts/postCreateCommand.sh index f87f2037d..785664073 100644 --- a/.devcontainer/init-scripts/postCreateCommand.sh +++ b/.devcontainer/init-scripts/postCreateCommand.sh @@ -7,6 +7,37 @@ echo "Initializing Nomad development environment..." echo "Node.js version: $(node --version)" echo "pnpm version: $(pnpm --version)" +# ============================================================================ +# CI Environment Detection +# ============================================================================ +# In CI environments (like GitHub Actions), we skip time-consuming operations +# to speed up the container build process. All validation steps should be +# explicitly defined in the CI workflow's runCmd instead. +# +# This approach provides: +# - Faster container startup in CI +# - Better visibility of what's being tested (explicit in workflow YAML) +# - More reliable CI runs (avoiding timeouts during postCreateCommand) +# ============================================================================ +if [ "$CI" = "true" ]; then + echo "CI environment detected - Running lightweight setup..." + echo "Installing dependencies only..." + pnpm install --frozen-lockfile + + echo "" + echo "✓ CI setup complete!" + echo "Note: Database initialization, seeding, and Playwright installation" + echo " will be handled explicitly by the CI workflow's validation steps." + exit 0 +fi + +# ============================================================================ +# Full Development Environment Setup (Local Development Only) +# ============================================================================ +# The following steps are only executed in local development environments +# to provide a complete, ready-to-use setup. +# ============================================================================ + # Install dependencies echo "Installing dependencies..." pnpm install --frozen-lockfile From 2598c87c6522760b0d056054b0463a6014090ac0 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 00:29:43 +0800 Subject: [PATCH 13/19] feat(devcontainer): enhance validation steps for improved visibility and control --- .github/workflows/devcontainer.yml | 56 +++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index c4f470d07..d0257bc10 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -22,6 +22,10 @@ jobs: name: Validate DevContainer Configuration runs-on: ubuntu-latest + # GitHub Actions automatically sets CI=true, which triggers lightweight + # setup in postCreateCommand.sh. All heavy operations are explicitly + # defined in the runCmd below for better visibility and control. + steps: - name: Checkout repository uses: actions/checkout@v4 @@ -29,37 +33,65 @@ jobs: - name: Build and run DevContainer uses: devcontainers/ci@v0.3 with: + # ==================================================================== + # DevContainer Validation Steps + # ==================================================================== + # Since CI=true is set automatically by GitHub Actions, the + # postCreateCommand only installs dependencies. All other validation + # steps are explicitly defined here to: + # 1. Provide clear visibility of what's being tested + # 2. Get detailed logs for each validation step + # 3. Avoid timeout issues during container initialization + # 4. Allow fine-grained control over test execution order + # ==================================================================== runCmd: | - echo "Validating DevContainer setup..." + echo "===================================================================" + echo "Starting DevContainer Validation" + echo "===================================================================" - # Check Node.js and pnpm versions + # Verify environment + echo "" + echo "[1/6] Checking development environment..." echo "Node.js version: $(node --version)" echo "pnpm version: $(pnpm --version)" # Verify database connection - echo "Checking PostgreSQL connection..." + echo "" + echo "[2/6] Checking PostgreSQL connection..." pg_isready -h postgres -U nomad -d nomad_dev || exit 1 + echo "✓ Database connection successful" - # Verify dependencies are installed - echo "Checking dependencies..." + # Verify dependencies are installed (by postCreateCommand) + echo "" + echo "[3/6] Verifying dependencies installation..." test -d node_modules || exit 1 + echo "✓ Dependencies installed" - # Verify database schema is initialized - echo "Verifying database schema..." + # Initialize database schema + echo "" + echo "[4/6] Initializing database schema..." cd /workspace/apps/web pnpm drizzle-kit push --force || exit 1 + echo "✓ Database schema initialized" - # Run basic type checking - echo "Running TypeScript type check..." + # Run TypeScript type checking + echo "" + echo "[5/6] Running TypeScript type check..." cd /workspace pnpm type-check || exit 1 + echo "✓ Type checking passed" - # Run a smoke test - echo "Running smoke tests..." + # Run unit tests + echo "" + echo "[6/6] Running unit tests..." cd /workspace/apps/web pnpm test:unit --run || exit 1 + echo "✓ Unit tests passed" - echo "DevContainer validation successful!" + echo "" + echo "===================================================================" + echo "✓ DevContainer validation completed successfully!" + echo "===================================================================" - name: Summary if: success() From e556a55b0308b38ab47d7a9511a58ae574a2177d Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 00:35:31 +0800 Subject: [PATCH 14/19] feat(devcontainer): improve CI environment setup for better control and visibility --- .../init-scripts/postCreateCommand.sh | 30 +++++++++---------- .github/workflows/devcontainer.yml | 24 ++++++++++----- 2 files changed, 31 insertions(+), 23 deletions(-) diff --git a/.devcontainer/init-scripts/postCreateCommand.sh b/.devcontainer/init-scripts/postCreateCommand.sh index 785664073..1be9ceb9a 100644 --- a/.devcontainer/init-scripts/postCreateCommand.sh +++ b/.devcontainer/init-scripts/postCreateCommand.sh @@ -10,24 +10,24 @@ echo "pnpm version: $(pnpm --version)" # ============================================================================ # CI Environment Detection # ============================================================================ -# In CI environments (like GitHub Actions), we skip time-consuming operations -# to speed up the container build process. All validation steps should be -# explicitly defined in the CI workflow's runCmd instead. +# In CI environments (like GitHub Actions), we completely skip postCreateCommand +# to avoid timeout issues during container startup. The devcontainers/ci tool +# expects postCreateCommand to complete quickly, but even a basic "pnpm install" +# can take several minutes on first run. # -# This approach provides: -# - Faster container startup in CI -# - Better visibility of what's being tested (explicit in workflow YAML) -# - More reliable CI runs (avoiding timeouts during postCreateCommand) +# Solution: +# - In CI: postCreateCommand does nothing (instant return) +# - All setup steps (including dependency installation) are handled explicitly +# in the GitHub workflow's runCmd section for better control and visibility +# +# Benefits: +# - Reliable container startup in CI (no timeouts) +# - Complete visibility of all validation steps in workflow logs +# - Fine-grained control over each step's execution # ============================================================================ if [ "$CI" = "true" ]; then - echo "CI environment detected - Running lightweight setup..." - echo "Installing dependencies only..." - pnpm install --frozen-lockfile - - echo "" - echo "✓ CI setup complete!" - echo "Note: Database initialization, seeding, and Playwright installation" - echo " will be handled explicitly by the CI workflow's validation steps." + echo "CI environment detected - Skipping postCreateCommand" + echo "All setup steps will be handled by the CI workflow's runCmd" exit 0 fi diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml index d0257bc10..dd77a1a11 100644 --- a/.github/workflows/devcontainer.yml +++ b/.github/workflows/devcontainer.yml @@ -51,39 +51,47 @@ jobs: # Verify environment echo "" - echo "[1/6] Checking development environment..." + echo "[1/7] Checking development environment..." echo "Node.js version: $(node --version)" echo "pnpm version: $(pnpm --version)" # Verify database connection echo "" - echo "[2/6] Checking PostgreSQL connection..." + echo "[2/7] Checking PostgreSQL connection..." pg_isready -h postgres -U nomad -d nomad_dev || exit 1 echo "✓ Database connection successful" - # Verify dependencies are installed (by postCreateCommand) + # Install dependencies + # Note: In CI mode, postCreateCommand is skipped to avoid timeout issues. + # We install dependencies here for better control and visibility. echo "" - echo "[3/6] Verifying dependencies installation..." - test -d node_modules || exit 1 + echo "[3/7] Installing project dependencies..." + pnpm install --frozen-lockfile || exit 1 echo "✓ Dependencies installed" + # Verify installation + echo "" + echo "[4/7] Verifying dependencies installation..." + test -d node_modules || exit 1 + echo "✓ node_modules directory exists" + # Initialize database schema echo "" - echo "[4/6] Initializing database schema..." + echo "[5/7] Initializing database schema..." cd /workspace/apps/web pnpm drizzle-kit push --force || exit 1 echo "✓ Database schema initialized" # Run TypeScript type checking echo "" - echo "[5/6] Running TypeScript type check..." + echo "[6/7] Running TypeScript type check..." cd /workspace pnpm type-check || exit 1 echo "✓ Type checking passed" # Run unit tests echo "" - echo "[6/6] Running unit tests..." + echo "[7/7] Running unit tests..." cd /workspace/apps/web pnpm test:unit --run || exit 1 echo "✓ Unit tests passed" From e1c006003124a0756b391077fb75726ac8c2e9e6 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 00:45:16 +0800 Subject: [PATCH 15/19] refactor(ci): remove devcontainer verification workflow script --- .github/workflows/devcontainer.yml | 106 ----------------------------- 1 file changed, 106 deletions(-) delete mode 100644 .github/workflows/devcontainer.yml diff --git a/.github/workflows/devcontainer.yml b/.github/workflows/devcontainer.yml deleted file mode 100644 index dd77a1a11..000000000 --- a/.github/workflows/devcontainer.yml +++ /dev/null @@ -1,106 +0,0 @@ -name: DevContainer Validation - -permissions: - contents: read - -on: - pull_request: - paths: - - '.devcontainer/**' - - '.gitattributes' - push: - branches: - - main - - develop - paths: - - '.devcontainer/**' - - '.gitattributes' - workflow_dispatch: - -jobs: - validate-devcontainer: - name: Validate DevContainer Configuration - runs-on: ubuntu-latest - - # GitHub Actions automatically sets CI=true, which triggers lightweight - # setup in postCreateCommand.sh. All heavy operations are explicitly - # defined in the runCmd below for better visibility and control. - - steps: - - name: Checkout repository - uses: actions/checkout@v4 - - - name: Build and run DevContainer - uses: devcontainers/ci@v0.3 - with: - # ==================================================================== - # DevContainer Validation Steps - # ==================================================================== - # Since CI=true is set automatically by GitHub Actions, the - # postCreateCommand only installs dependencies. All other validation - # steps are explicitly defined here to: - # 1. Provide clear visibility of what's being tested - # 2. Get detailed logs for each validation step - # 3. Avoid timeout issues during container initialization - # 4. Allow fine-grained control over test execution order - # ==================================================================== - runCmd: | - echo "===================================================================" - echo "Starting DevContainer Validation" - echo "===================================================================" - - # Verify environment - echo "" - echo "[1/7] Checking development environment..." - echo "Node.js version: $(node --version)" - echo "pnpm version: $(pnpm --version)" - - # Verify database connection - echo "" - echo "[2/7] Checking PostgreSQL connection..." - pg_isready -h postgres -U nomad -d nomad_dev || exit 1 - echo "✓ Database connection successful" - - # Install dependencies - # Note: In CI mode, postCreateCommand is skipped to avoid timeout issues. - # We install dependencies here for better control and visibility. - echo "" - echo "[3/7] Installing project dependencies..." - pnpm install --frozen-lockfile || exit 1 - echo "✓ Dependencies installed" - - # Verify installation - echo "" - echo "[4/7] Verifying dependencies installation..." - test -d node_modules || exit 1 - echo "✓ node_modules directory exists" - - # Initialize database schema - echo "" - echo "[5/7] Initializing database schema..." - cd /workspace/apps/web - pnpm drizzle-kit push --force || exit 1 - echo "✓ Database schema initialized" - - # Run TypeScript type checking - echo "" - echo "[6/7] Running TypeScript type check..." - cd /workspace - pnpm type-check || exit 1 - echo "✓ Type checking passed" - - # Run unit tests - echo "" - echo "[7/7] Running unit tests..." - cd /workspace/apps/web - pnpm test:unit --run || exit 1 - echo "✓ Unit tests passed" - - echo "" - echo "===================================================================" - echo "✓ DevContainer validation completed successfully!" - echo "===================================================================" - - - name: Summary - if: success() - run: echo "DevContainer configuration is valid and working correctly" From a2a3fd37b081a14881c8d58e8893316d16691967 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 01:07:19 +0800 Subject: [PATCH 16/19] fix(devcontainer): update node version to 22 for consistency across configurations --- .devcontainer/Dockerfile | 4 +--- .devcontainer/docker-compose.yml | 4 +--- .nvmrc | 2 +- package.json | 2 +- 4 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 450787c5f..5a710b0cb 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1.4 -ARG NODE_VERSION=22.21.0 +ARG NODE_VERSION=22 FROM node:${NODE_VERSION}-slim @@ -57,5 +57,3 @@ RUN echo 'alias ll="ls -alh"' >> ~/.bashrc && \ # Health check HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ CMD node --version && pnpm --version || exit 1 - -CMD ["sleep", "infinity"] diff --git a/.devcontainer/docker-compose.yml b/.devcontainer/docker-compose.yml index 375f10129..7e48de04b 100644 --- a/.devcontainer/docker-compose.yml +++ b/.devcontainer/docker-compose.yml @@ -1,12 +1,10 @@ -version: '3.8' - services: app: build: context: . dockerfile: Dockerfile args: - NODE_VERSION: 22.21.0 + NODE_VERSION: 22 PNPM_VERSION: 10.17.1 volumes: diff --git a/.nvmrc b/.nvmrc index f5b3ef39f..8fdd954df 100644 --- a/.nvmrc +++ b/.nvmrc @@ -1 +1 @@ -22.21.0 \ No newline at end of file +22 \ No newline at end of file diff --git a/package.json b/package.json index 306d0e1d9..f6680207e 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "0.1.0", "private": true, "engines": { - "node": ">=22.21.0", + "node": ">=22.0.0", "pnpm": ">=10.0.0" }, "packageManager": "pnpm@10.17.1", From 9731079b760dd3e0eea7330a3f1050749d403dac Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 01:12:37 +0800 Subject: [PATCH 17/19] fix(devcontainer): switch pnpm installation method to npm for better reliability --- .devcontainer/Dockerfile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 5a710b0cb..4420d418e 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -32,10 +32,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ postgresql-client \ && rm -rf /var/lib/apt/lists/* -# Install pnpm via corepack +# Install pnpm via npm (with fallback to Taobao mirror for network issues) ARG PNPM_VERSION=10.17.1 -RUN corepack enable && \ - corepack prepare pnpm@${PNPM_VERSION} --activate +RUN npm install -g pnpm@${PNPM_VERSION} || \ + npm install -g pnpm@${PNPM_VERSION} --registry=https://registry.npmmirror.com # Configure pnpm ENV PNPM_HOME=/pnpm From 1800171e7b27b029c82877a44b6c26073139f793 Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 01:15:39 +0800 Subject: [PATCH 18/19] fix(devcontainer): remove unused environment variables for cleaner configuration --- .devcontainer/devcontainer.json | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index c7771f916..9a81754b5 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -120,9 +120,7 @@ "remoteUser": "node", "containerEnv": { - "NODE_ENV": "development", - "PNPM_HOME": "/pnpm", - "PATH": "/pnpm:${containerEnv:PATH}" + "NODE_ENV": "development" }, "mounts": [ From a3b161e14b5fc64e9a8ee465ed81b76d86f58c4c Mon Sep 17 00:00:00 2001 From: ukeSJTU Date: Mon, 29 Dec 2025 01:26:51 +0800 Subject: [PATCH 19/19] fix(devcontainer): ensure pnpm store directory is created before configuration --- .devcontainer/Dockerfile | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile index 4420d418e..f2ff35c77 100644 --- a/.devcontainer/Dockerfile +++ b/.devcontainer/Dockerfile @@ -40,7 +40,8 @@ RUN npm install -g pnpm@${PNPM_VERSION} || \ # Configure pnpm ENV PNPM_HOME=/pnpm ENV PATH=$PNPM_HOME:$PATH -RUN pnpm config set store-dir /pnpm/store +RUN mkdir -p /pnpm/store && \ + pnpm config set store-dir /pnpm/store # Set working directory WORKDIR /workspace @@ -48,6 +49,11 @@ WORKDIR /workspace # Configure Git safe directory to avoid permission warnings RUN git config --global --add safe.directory /workspace +# Pre-create directories for volumes and set correct permissions +# This ensures the node user can write to these directories +RUN mkdir -p /workspace/node_modules /workspace/.turbo && \ + chown -R node:node /workspace /pnpm + # Set up shell configuration for node user USER node RUN echo 'alias ll="ls -alh"' >> ~/.bashrc && \