v0.3.1: 版本号架构重构 — VERSION为唯一真相来源

- 新增 src/version.ts: 从文件读取版本(APP_VERSION_FILE → /app/VERSION)
- main.ts 改为 import { VERSION } from './version'(不再读 package.json)
- Dockerfile 构建时 COPY VERSION 到 /app/VERSION
- 新增 build.sh: 一键读取VERSION→构建→打标签
- docker-compose.yml: 清理重复/损坏内容, 添加 pansou network-alias
- package.json version 设为 0.0.0 (不再作为真相来源)
- 清理 .env 和 compose 注释中的过期版本号
This commit is contained in:
2026-05-17 03:26:00 +08:00
parent 476a7d458a
commit d5aa799acc
7 changed files with 74 additions and 72 deletions

11
build.sh Executable file
View File

@@ -0,0 +1,11 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/source_clean"
VERSION=$(cat ../VERSION)
echo "🔨 Building CloudSearch v${VERSION}..."
docker build -t cloudsearch-app:v${VERSION} -t cloudsearch-app:latest .
echo "✅ Built: cloudsearch-app:v${VERSION} + cloudsearch-app:latest"
echo " Run: docker-compose up -d app"

View File

@@ -1,13 +1,16 @@
# CloudSearch v2.3.0 — 单容器部署(全功能集成) # CloudSearch — single source of truth: ./VERSION
# 注意: 此 compose 用于参考/文档。实际部署使用 docker run 以兼容 1Panel Redis。
networks: networks:
cloudsearch-net: cloudsearch-network:
driver: bridge driver: bridge
volumes: volumes:
admin-data: admin-data:
app-data: app-data:
external: true
name: cloudsearch_app-data
pansou-data: pansou-data:
redis-data:
x-logging: &default-logging x-logging: &default-logging
driver: json-file driver: json-file
@@ -16,29 +19,31 @@ x-logging: &default-logging
max-file: "10" max-file: "10"
services: services:
# ============ Redis ============ pansou:
redis: container_name: CloudSearch_PanSou
container_name: CloudSearch_Redis image: ghcr.io/fish2018/pansou-web:latest
image: redis:7-alpine
command: redis-server --save 60 1 --appendonly yes
volumes:
- redis-data:/data
restart: always
networks: networks:
- cloudsearch-net cloudsearch-network:
aliases:
- pansou
environment:
- DOMAIN=${DOMAIN:-localhost}
- CACHE_TTL=60
volumes:
- pansou-data:/app/data
restart: always
logging: *default-logging logging: *default-logging
# ============ 全功能主应用 ============
app: app:
container_name: CloudSearch_App container_name: CloudSearch_App
image: cloudsearch-app:v0.3.0 image: cloudsearch-app:latest
ports: ports:
- "9527:9527" - "9527:9527"
environment: environment:
- NODE_ENV=production - NODE_ENV=production
- CORS_ORIGIN=http://jp-cs.timaa.cn - CORS_ORIGIN=http://jp-cs.timaa.cn
- JWT_SECRET=u-_1wBd1IlQNYwZ9l5P1838x2fdsp0DI-BUhMouJeIg - JWT_SECRET=u-_1wB...JeIg
- ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A - ADMIN_PASSWORD=0nL5kL...b25A
- PANSOU_URL=http://pansou:80 - PANSOU_URL=http://pansou:80
- DB_PATH=/data/database.sqlite - DB_PATH=/data/database.sqlite
- REDIS_URL=redis://:redis_GbR7XZ@1Panel-redis-aDp3:6379 - REDIS_URL=redis://:redis_GbR7XZ@1Panel-redis-aDp3:6379
@@ -46,19 +51,18 @@ services:
- TRANSFER_CONFIG_PATH=/data/transfer_config.json - TRANSFER_CONFIG_PATH=/data/transfer_config.json
- TZ=Asia/Shanghai - TZ=Asia/Shanghai
- APP_VERSION_FILE=/data/VERSION - APP_VERSION_FILE=/data/VERSION
- FEISHU_APP_ID=${FEISHU_APP_ID:-}
- FEISHU_APP_SECRET=${FEISHU_APP_SECRET:-}
- FEISHU_VERIFY_TOKEN=${FEISHU_VERIFY_TOKEN:-}
- FEISHU_WEBHOOK_URL=${FEISHU_WEBHOOK_URL:-}
- TMDB_API_KEY=${TMDB_API_KEY:-}
volumes: volumes:
- app-data:/data - cloudsearch_app-data:/data
- ./uploads:/app/uploads - ./uploads:/app/uploads
- ./VERSION:/app/VERSION
- ./icons:/app/dist/frontend/admin/icons - ./icons:/app/dist/frontend/admin/icons
- ./VERSION:/data/VERSION
depends_on: depends_on:
- pansou
# ============ 管理后台 (功能开关) ============ restart: always
networks:
- cloudsearch-network
logging: *default-logging
admin: admin:
container_name: CloudSearch_Admin container_name: CloudSearch_Admin
image: cloudsearch-admin:v0.1.0 image: cloudsearch-admin:v0.1.0
@@ -66,54 +70,11 @@ services:
- "127.0.0.1:9531:9531" - "127.0.0.1:9531:9531"
environment: environment:
- ADMIN_PORT=9531 - ADMIN_PORT=9531
- ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A - ADMIN_PASSWORD=0nL5kL...b25A
- ADMIN_DB_PATH=/data/admin_flags.sqlite - ADMIN_DB_PATH=/data/admin_flags.sqlite
volumes: volumes:
- admin-data:/data - admin-data:/data
restart: always restart: always
networks: networks:
- cloudsearch-net - cloudsearch-network
logging: *default-logging logging: *default-logging
pansou:
condition: service_started
redis:
condition: service_started
restart: always
networks:
- cloudsearch-net
logging: *default-logging
# ============ 管理后台 (功能开关) ============
admin:
container_name: CloudSearch_Admin
image: cloudsearch-admin:v0.1.0
ports:
- "127.0.0.1:9531:9531"
environment:
- ADMIN_PORT=9531
- ADMIN_PASSWORD=0nL5kLhMIJ1121PYmQb25A
- ADMIN_DB_PATH=/data/admin_flags.sqlite
volumes:
- admin-data:/data
restart: always
networks:
- cloudsearch-net
logging: *default-logging
pansou:
container_name: CloudSearch_PanSou
image: ghcr.io/fish2018/pansou-web:latest
expose:
- "80"
environment:
- DOMAIN=${DOMAIN:-localhost}
- CACHE_TTL=60
volumes:
- pansou-data:/app/data
restart: always
networks:
- cloudsearch-net
logging: *default-logging

View File

@@ -24,6 +24,8 @@ COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./ COPY --from=builder /app/package.json ./
COPY frontend/ ./dist/frontend/ COPY frontend/ ./dist/frontend/
# VERSION baked into image — single source of truth
COPY VERSION /app/VERSION
EXPOSE 9527 EXPOSE 9527
ENTRYPOINT ["dumb-init", "--"] ENTRYPOINT ["dumb-init", "--"]
CMD ["node", "dist/main.js"] CMD ["node", "dist/main.js"]

1
source_clean/VERSION Normal file
View File

@@ -0,0 +1 @@
0.3.0

View File

@@ -1,6 +1,6 @@
{ {
"name": "cloudsearch-backend", "name": "cloudsearch-backend",
"version": "2.0.26", "version": "0.0.0",
"private": true, "private": true,
"scripts": { "scripts": {
"dev": "tsx watch src/main.ts", "dev": "tsx watch src/main.ts",

View File

@@ -4,7 +4,7 @@ import cors from 'cors';
import helmet from 'helmet'; import helmet from 'helmet';
import morgan from 'morgan'; import morgan from 'morgan';
import config from './config'; import config from './config';
const { version } = require('../package.json'); import { VERSION as version } from "./version";
import { getDb } from './database/database'; import { getDb } from './database/database';
import { connectRedis, disconnectRedis, reconnectRedis, testRedisConnection } from './middleware/cache'; import { connectRedis, disconnectRedis, reconnectRedis, testRedisConnection } from './middleware/cache';
import rateLimiter from './middleware/rate-limit'; import rateLimiter from './middleware/rate-limit';

View File

@@ -0,0 +1,27 @@
import fs from 'fs';
/**
* Read version from file. Order:
* 1. APP_VERSION_FILE env var (e.g. /data/VERSION from mounted volume)
* 2. /app/VERSION (built into Docker image)
* 3. Fallback hardcoded default
*/
function readVersionFromFile(): string {
const paths = [
process.env.APP_VERSION_FILE, // from env
'/app/VERSION', // built-in fallback
].filter(Boolean) as string[];
for (const p of paths) {
try {
const content = fs.readFileSync(p, 'utf-8').trim();
if (content) return content;
} catch {
// file doesn't exist, try next
}
}
return '0.0.0'; // ultimate fallback — should never happen
}
export const VERSION = readVersionFromFile();