add
This commit is contained in:
304
init_monorepo.py
Normal file
304
init_monorepo.py
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
# ===================== 可自定义配置(按需修改) =====================
|
||||||
|
PROJECT_ROOT = "go-monorepo" # 项目根目录名
|
||||||
|
GO_VERSION = "1.21" # 团队统一Go版本
|
||||||
|
# ====================================================================
|
||||||
|
|
||||||
|
def create_dirs(base_path: Path):
|
||||||
|
"""创建所有核心目录结构"""
|
||||||
|
dirs = [
|
||||||
|
# 公共模块目录
|
||||||
|
"common/db",
|
||||||
|
"common/redis",
|
||||||
|
"common/logger",
|
||||||
|
"common/utils",
|
||||||
|
"common/middleware",
|
||||||
|
# 业务服务根目录(无具体业务)
|
||||||
|
"services",
|
||||||
|
# 部署资源目录
|
||||||
|
"deploy/postgres",
|
||||||
|
"deploy/redis",
|
||||||
|
# 日志目录
|
||||||
|
"logs"
|
||||||
|
]
|
||||||
|
for dir_path in dirs:
|
||||||
|
full_path = base_path / dir_path
|
||||||
|
full_path.mkdir(parents=True, exist_ok=True)
|
||||||
|
print(f"✅ 创建目录: {full_path}")
|
||||||
|
|
||||||
|
def write_file(file_path: Path, content: str, overwrite: bool = False):
|
||||||
|
"""写入文件(避免覆盖已有文件)"""
|
||||||
|
if file_path.exists() and not overwrite:
|
||||||
|
print(f"⚠️ 文件已存在,跳过: {file_path}")
|
||||||
|
return
|
||||||
|
with open(file_path, "w", encoding="utf-8") as f:
|
||||||
|
f.write(content)
|
||||||
|
print(f"✅ 生成文件: {file_path}")
|
||||||
|
|
||||||
|
def generate_go_work(base_path: Path):
|
||||||
|
"""生成Go工作区核心文件 go.work + go.work.sum"""
|
||||||
|
# go.work
|
||||||
|
content = f"""go {GO_VERSION}
|
||||||
|
|
||||||
|
# 公共模块
|
||||||
|
use ./common
|
||||||
|
|
||||||
|
# 业务服务根目录(新增业务时手动追加 use ./services/xxx)
|
||||||
|
use ./services
|
||||||
|
"""
|
||||||
|
write_file(base_path / "go.work", content)
|
||||||
|
# 空的go.work.sum
|
||||||
|
write_file(base_path / "go.work.sum", "")
|
||||||
|
|
||||||
|
def generate_common_module(base_path: Path):
|
||||||
|
"""生成公共模块common的基础文件"""
|
||||||
|
common_path = base_path / "common"
|
||||||
|
# common/go.mod
|
||||||
|
mod_content = f"""module {PROJECT_ROOT}/common
|
||||||
|
|
||||||
|
go {GO_VERSION}
|
||||||
|
|
||||||
|
require (
|
||||||
|
github.com/gin-gonic/gin v1.9.1
|
||||||
|
github.com/jmoiron/sqlx v1.3.5
|
||||||
|
github.com/redis/go-redis/v9 v9.3.0
|
||||||
|
go.uber.org/zap v1.26.0
|
||||||
|
github.com/lib/pq v1.10.9
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
write_file(common_path / "go.mod", mod_content)
|
||||||
|
# 空的go.sum
|
||||||
|
write_file(common_path / "go.sum", "")
|
||||||
|
# 公共模块基础空文件(占位)
|
||||||
|
empty_files = [
|
||||||
|
"db/postgres.go",
|
||||||
|
"db/options.go",
|
||||||
|
"redis/redis.go",
|
||||||
|
"logger/logger.go",
|
||||||
|
"utils/common.go",
|
||||||
|
"middleware/cors.go"
|
||||||
|
]
|
||||||
|
for file in empty_files:
|
||||||
|
write_file(common_path / file, "")
|
||||||
|
|
||||||
|
def generate_deploy_files(base_path: Path):
|
||||||
|
"""生成部署资源deploy的基础文件"""
|
||||||
|
deploy_path = base_path / "deploy"
|
||||||
|
# postgres/init.sql
|
||||||
|
pg_sql = """-- PostgresSQL全局初始化脚本
|
||||||
|
-- 所有业务公共建库/建表语句写在这里,单独业务表建议在各自业务中处理
|
||||||
|
CREATE DATABASE IF NOT EXISTS monorepo;
|
||||||
|
\\c monorepo;
|
||||||
|
"""
|
||||||
|
write_file(deploy_path / "postgres/init.sql", pg_sql)
|
||||||
|
# redis/redis.conf
|
||||||
|
redis_conf = """# Redis基础配置
|
||||||
|
bind 0.0.0.0
|
||||||
|
protected-mode no
|
||||||
|
port 6379
|
||||||
|
daemonize no
|
||||||
|
requirepass 123456
|
||||||
|
appendonly yes
|
||||||
|
appendfsync everysec
|
||||||
|
"""
|
||||||
|
write_file(deploy_path / "redis/redis.conf", redis_conf)
|
||||||
|
|
||||||
|
def generate_docker_compose(base_path: Path):
|
||||||
|
"""生成根目录docker-compose.yml(聚合中间件+业务模板)"""
|
||||||
|
compose_content = f"""version: '3.8'
|
||||||
|
services:
|
||||||
|
# 公共PostgresSQL
|
||||||
|
postgres:
|
||||||
|
image: postgres:16-alpine
|
||||||
|
container_name: {PROJECT_ROOT}-postgres
|
||||||
|
environment:
|
||||||
|
POSTGRES_USER: ${{PG_USER:-root}}
|
||||||
|
POSTGRES_PASSWORD: ${{PG_PWD:-123456}}
|
||||||
|
POSTGRES_DB: ${{PG_DB:-monorepo}}
|
||||||
|
ports:
|
||||||
|
- "${{PG_PORT:-5432}}:5432"
|
||||||
|
volumes:
|
||||||
|
- ./deploy/postgres/init.sql:/docker-entrypoint-initdb.d/init.sql
|
||||||
|
- pg_data:/var/lib/postgresql/data
|
||||||
|
networks:
|
||||||
|
- monorepo-net
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
# 公共Redis
|
||||||
|
redis:
|
||||||
|
image: redis:7-alpine
|
||||||
|
container_name: {PROJECT_ROOT}-redis
|
||||||
|
ports:
|
||||||
|
- "${{REDIS_PORT:-6379}}:6379"
|
||||||
|
volumes:
|
||||||
|
- ./deploy/redis/redis.conf:/etc/redis/redis.conf
|
||||||
|
- redis_data:/data
|
||||||
|
command: redis-server /etc/redis/redis.conf
|
||||||
|
networks:
|
||||||
|
- monorepo-net
|
||||||
|
restart: always
|
||||||
|
|
||||||
|
# 【业务服务模板】新增业务时复制以下块修改
|
||||||
|
# user:
|
||||||
|
# build:
|
||||||
|
# context: ./services/user
|
||||||
|
# dockerfile: Dockerfile
|
||||||
|
# container_name: {PROJECT_ROOT}-user
|
||||||
|
# environment:
|
||||||
|
# - GIN_MODE=release
|
||||||
|
# - PG_ADDR=postgres:5432
|
||||||
|
# - REDIS_ADDR=redis:6379
|
||||||
|
# ports:
|
||||||
|
# - "8080:8080"
|
||||||
|
# volumes:
|
||||||
|
# - ./logs/user:/app/logs
|
||||||
|
# networks:
|
||||||
|
# - monorepo-net
|
||||||
|
# restart: always
|
||||||
|
# depends_on:
|
||||||
|
# - postgres
|
||||||
|
# - redis
|
||||||
|
# deploy:
|
||||||
|
# resources:
|
||||||
|
# limits:
|
||||||
|
# cpus: "0.5"
|
||||||
|
# memory: "512M"
|
||||||
|
|
||||||
|
# 全局网络
|
||||||
|
networks:
|
||||||
|
monorepo-net:
|
||||||
|
driver: bridge
|
||||||
|
|
||||||
|
# 全局数据卷
|
||||||
|
volumes:
|
||||||
|
pg_data:
|
||||||
|
redis_data:
|
||||||
|
"""
|
||||||
|
write_file(base_path / "docker-compose.yml", compose_content)
|
||||||
|
# 日志目录占位文件
|
||||||
|
write_file(base_path / "logs/.gitkeep", "")
|
||||||
|
|
||||||
|
def generate_global_config(base_path: Path):
|
||||||
|
"""生成全局配置文件 .env + Makefile"""
|
||||||
|
# .env 全局环境变量
|
||||||
|
env_content = """# 全局环境变量 - 所有服务共享
|
||||||
|
# PostgresSQL
|
||||||
|
PG_USER=root
|
||||||
|
PG_PWD=123456
|
||||||
|
PG_DB=monorepo
|
||||||
|
PG_PORT=5432
|
||||||
|
# Redis
|
||||||
|
REDIS_PORT=6379
|
||||||
|
REDIS_PWD=123456
|
||||||
|
# Go服务通用
|
||||||
|
GIN_MODE=release
|
||||||
|
"""
|
||||||
|
write_file(base_path / ".env", env_content)
|
||||||
|
|
||||||
|
# Makefile 全局快捷命令
|
||||||
|
makefile_content = f"""# Go Monorepo 全局快捷命令(3人团队统一使用)
|
||||||
|
PROJECT_NAME={PROJECT_ROOT}
|
||||||
|
|
||||||
|
# 全局启动所有服务(中间件+已配置业务)
|
||||||
|
up:
|
||||||
|
\tdocker compose up -d
|
||||||
|
|
||||||
|
# 单独启动某一个服务(如:make up-svc svc=user)
|
||||||
|
up-svc:
|
||||||
|
\tdocker compose up -d $(svc)
|
||||||
|
|
||||||
|
# 全局停止所有服务
|
||||||
|
down:
|
||||||
|
\tdocker compose down
|
||||||
|
|
||||||
|
# 单独停止某一个服务
|
||||||
|
down-svc:
|
||||||
|
\tdocker compose stop $(svc)
|
||||||
|
|
||||||
|
# 构建所有业务镜像
|
||||||
|
build:
|
||||||
|
\tdocker compose build
|
||||||
|
|
||||||
|
# 单独构建某一个业务镜像(发布核心命令)
|
||||||
|
build-svc:
|
||||||
|
\tdocker compose build $(svc)
|
||||||
|
|
||||||
|
# 查看所有服务日志
|
||||||
|
logs:
|
||||||
|
\tdocker compose logs -f
|
||||||
|
|
||||||
|
# 查看某一个服务日志
|
||||||
|
logs-svc:
|
||||||
|
\tdocker compose logs -f $(svc)
|
||||||
|
|
||||||
|
# 重新启动某一个服务(代码修改后快速重启)
|
||||||
|
restart-svc:
|
||||||
|
\tdocker compose restart $(svc)
|
||||||
|
|
||||||
|
# 清理Docker无用镜像/容器
|
||||||
|
clean:
|
||||||
|
\tdocker system prune -f
|
||||||
|
|
||||||
|
# 初始化Go工作区(新成员拉取代码后执行)
|
||||||
|
go-init:
|
||||||
|
\tgo work init
|
||||||
|
\tgo work use ./common
|
||||||
|
\tgo work use ./services
|
||||||
|
\tgo mod tidy -C ./common
|
||||||
|
|
||||||
|
# 进入某一个服务容器(如:make exec svc=user)
|
||||||
|
exec:
|
||||||
|
\tdocker exec -it ${PROJECT_NAME}-$(svc) /bin/sh
|
||||||
|
|
||||||
|
# 查看所有服务状态
|
||||||
|
ps:
|
||||||
|
\tdocker compose ps
|
||||||
|
"""
|
||||||
|
write_file(base_path / "Makefile", makefile_content)
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""主执行函数"""
|
||||||
|
print(f"===== 开始生成Go Monorepo基础结构,根目录:{PROJECT_ROOT} =====")
|
||||||
|
try:
|
||||||
|
# 项目根路径
|
||||||
|
base_path = Path(os.getcwd()) / PROJECT_ROOT
|
||||||
|
# 1. 创建核心目录
|
||||||
|
create_dirs(base_path)
|
||||||
|
# 2. 生成Go工作区文件
|
||||||
|
generate_go_work(base_path)
|
||||||
|
# 3. 生成公共模块common
|
||||||
|
generate_common_module(base_path)
|
||||||
|
# 4. 生成部署资源文件
|
||||||
|
generate_deploy_files(base_path)
|
||||||
|
# 5. 生成Docker Compose
|
||||||
|
generate_docker_compose(base_path)
|
||||||
|
# 6. 生成全局配置(.env/Makefile)
|
||||||
|
generate_global_config(base_path)
|
||||||
|
|
||||||
|
# 日志目录权限处理(Ubuntu/Docker)
|
||||||
|
if sys.platform != "win32":
|
||||||
|
logs_path = base_path / "logs"
|
||||||
|
os.chmod(logs_path, 0o777)
|
||||||
|
print(f"✅ 配置日志目录权限: {logs_path}")
|
||||||
|
|
||||||
|
print("="*50)
|
||||||
|
print("🎉 Go Monorepo基础结构生成完成!")
|
||||||
|
print("="*50)
|
||||||
|
print("核心操作步骤:")
|
||||||
|
print(f"1. 进入项目根目录:cd {PROJECT_ROOT}")
|
||||||
|
print("2. 新成员初始化工作区:make go-init")
|
||||||
|
print("3. 启动公共中间件:make up-svc svc=postgres && make up-svc svc=redis")
|
||||||
|
print("4. 新增业务:在services/下创建业务目录,复制模板配置即可独立部署")
|
||||||
|
print("5. 常用命令:make ps(查看状态)、make logs-svc svc=postgres(查看日志)")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 生成失败,错误信息:{str(e)}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
118
init_monorepo.sh
Normal file
118
init_monorepo.sh
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
# 脚本编码设置,避免中文乱码
|
||||||
|
export LANG=C.UTF-8
|
||||||
|
|
||||||
|
# 配置项(可按需修改)
|
||||||
|
PROJECT_NAME="go-monorepo"
|
||||||
|
PYTHON_IMAGE="python:3.11-alpine" # 轻量Python3镜像,仅80+MB
|
||||||
|
PYTHON_SCRIPT="init-monorepo.py"
|
||||||
|
|
||||||
|
# 颜色输出函数(增强可读性)
|
||||||
|
red() { echo -e "\033[31m$1\033[0m"; }
|
||||||
|
green() { echo -e "\033[32m$1\033[0m"; }
|
||||||
|
yellow() { echo -e "\033[33m$1\033[0m"; }
|
||||||
|
blue() { echo -e "\033[34m$1\033[0m"; }
|
||||||
|
|
||||||
|
# 第一步:检查Docker环境是否安装
|
||||||
|
check_docker() {
|
||||||
|
blue "===== 1. 检测Docker环境 ====="
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
red "❌ 错误:本地未安装Docker,请先安装Docker后再执行!"
|
||||||
|
red "Docker官方安装地址:https://docs.docker.com/get-docker/"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 检查Docker守护进程是否运行
|
||||||
|
if ! docker info &> /dev/null; then
|
||||||
|
red "❌ 错误:Docker守护进程未启动,请先启动Docker服务!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
green "✅ Docker环境检测通过(版本:$(docker --version | awk '{print $3}' | sed 's/,//g'))"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 第二步:检查Python脚本是否存在
|
||||||
|
check_script() {
|
||||||
|
blue -e "\n===== 2. 检测${PYTHON_SCRIPT}脚本 ====="
|
||||||
|
if [ ! -f "${PYTHON_SCRIPT}" ]; then
|
||||||
|
red "❌ 错误:当前目录未找到${PYTHON_SCRIPT}文件!"
|
||||||
|
red "请确保${PYTHON_SCRIPT}与本sh脚本在同一目录下!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
green "✅ ${PYTHON_SCRIPT}脚本检测通过"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 第三步:拉取Python镜像(若本地无)
|
||||||
|
pull_python_image() {
|
||||||
|
blue -e "\n===== 3. 检查Python3镜像 ====="
|
||||||
|
if docker images --format "{{.Repository}}:{{.Tag}}" | grep -q "^${PYTHON_IMAGE}$"; then
|
||||||
|
green "✅ 本地已存在${PYTHON_IMAGE}镜像,无需拉取"
|
||||||
|
else
|
||||||
|
yellow "⚠️ 本地无${PYTHON_IMAGE}镜像,开始拉取(轻量镜像,仅80+MB,耗时约10s)"
|
||||||
|
docker pull "${PYTHON_IMAGE}"
|
||||||
|
green "✅ ${PYTHON_IMAGE}镜像拉取完成"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 第四步:创建临时Python容器执行初始化脚本
|
||||||
|
run_python_container() {
|
||||||
|
blue -e "\n===== 4. 启动临时Python容器,执行初始化 ====="
|
||||||
|
yellow "⚠️ 正在生成${PROJECT_NAME}基础结构,文件将保存在当前目录..."
|
||||||
|
# 核心docker run命令:
|
||||||
|
# --rm:执行完成后自动销毁容器
|
||||||
|
# -v $(pwd):/app:将本地当前目录挂载到容器内/app目录
|
||||||
|
# -w /app:设置容器工作目录为/app(与本地挂载目录一致)
|
||||||
|
# ${PYTHON_IMAGE}:使用的Python镜像
|
||||||
|
# python3 ${PYTHON_SCRIPT}:在容器内执行Python脚本
|
||||||
|
docker run --rm \
|
||||||
|
-v "$(pwd)":/app \
|
||||||
|
-w /app \
|
||||||
|
--name "tmp-go-monorepo-init" \
|
||||||
|
"${PYTHON_IMAGE}" \
|
||||||
|
python3 "${PYTHON_SCRIPT}"
|
||||||
|
|
||||||
|
# 检查脚本执行结果
|
||||||
|
if [ -d "${PROJECT_NAME}" ]; then
|
||||||
|
green -e "\n✅ 容器执行完成!${PROJECT_NAME}基础结构已生成在当前目录"
|
||||||
|
else
|
||||||
|
red "❌ 容器执行失败,未生成${PROJECT_NAME}目录,请检查日志!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 第五步:权限修复(解决容器生成文件的权限问题)
|
||||||
|
fix_permission() {
|
||||||
|
blue -e "\n===== 5. 修复文件目录权限 ====="
|
||||||
|
# 容器内生成的文件可能属于root用户,修复为当前用户权限
|
||||||
|
if [ -d "${PROJECT_NAME}" ] && [ "$(id -u)" -ne 0 ]; then
|
||||||
|
sudo chown -R "$(id -u)":"$(id -g)" "${PROJECT_NAME}" 2>/dev/null || true
|
||||||
|
chmod +x "${PROJECT_NAME}/Makefile" 2>/dev/null || true
|
||||||
|
green "✅ 目录权限修复完成,当前用户可正常操作${PROJECT_NAME}内文件"
|
||||||
|
else
|
||||||
|
yellow "⚠️ 无需修复权限(当前为root用户或目录不存在)"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主执行流程
|
||||||
|
main() {
|
||||||
|
clear
|
||||||
|
blue "====================================================="
|
||||||
|
blue " Go Monorepo 容器化初始化脚本"
|
||||||
|
blue " 无本地Python环境依赖 · 仅需Docker"
|
||||||
|
blue "====================================================="
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
check_docker
|
||||||
|
check_script
|
||||||
|
pull_python_image
|
||||||
|
run_python_container
|
||||||
|
fix_permission
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
green "🎉 所有操作完成!"
|
||||||
|
green "👉 下一步操作:cd ${PROJECT_NAME} && make go-init"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main
|
||||||
Reference in New Issue
Block a user