Compare commits

1 Commits
dev ... main

Author SHA1 Message Date
kim
e7eea8c6cc chore: add itom-platform auto build workflow 2026-01-19 05:12:39 +00:00
303 changed files with 133 additions and 82583 deletions

View File

@@ -1,28 +0,0 @@
# Ignore files and directories starting with a dot
# Ignore specific files
.dockerignore
# Ignore build artifacts
logs/
_output/
# Ignore non-essential documentation
README.md
README-zh_CN.md
CONTRIBUTING.md
CHANGELOG/
# LICENSE
# Ignore testing and linting configuration
.golangci.yml
# Ignore assets
assets/
# Ignore components
components/
# Ignore tools and scripts
.github/

1
.gitattributes vendored
View File

@@ -1 +0,0 @@
*.sh text eol=lf

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-api-server
spec:
replicas: 1
selector:
matchLabels:
app: admin-api-server
template:
metadata:
labels:
app: admin-api-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-admin-api-container
image: openim/openim-admin-api:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 10009
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: admin-api-service
spec:
selector:
app: admin-api-server
ports:
- name: http-10009
protocol: TCP
port: 10009
targetPort: 10009
type: NodePort

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-rpc-server
spec:
replicas: 1
selector:
matchLabels:
app: admin-rpc-server
template:
metadata:
labels:
app: admin-rpc-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-admin-rpc-container
image: openim/openim-admin-rpc:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 30200
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: admin-rpc-service
spec:
selector:
app: admin-rpc-server
ports:
- name: rpc-30200
protocol: TCP
port: 30200
targetPort: 30200
type: ClusterIP

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-api-server
spec:
replicas: 1
selector:
matchLabels:
app: chat-api-server
template:
metadata:
labels:
app: chat-api-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-chat-api-container
image: openim/openim-chat-api:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 10008
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: chat-api-service
spec:
selector:
app: chat-api-server
ports:
- name: http-10008
protocol: TCP
port: 10008
targetPort: 10008
type: NodePort

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-rpc-server
spec:
replicas: 1
selector:
matchLabels:
app: chat-rpc-server
template:
metadata:
labels:
app: chat-rpc-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-chat-rpc-container
image: openim/openim-chat-rpc:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 30300
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: chat-rpc-service
spec:
selector:
app: chat-rpc-server
ports:
- name: rpc-30300
protocol: TCP
port: 30300
targetPort: 30300
type: ClusterIP

View File

@@ -1,609 +0,0 @@
name: OpenIM Chat 构建和发布
on:
push:
branches: [ main,wallet, master, develop, release-* ]
paths:
- '**'
pull_request:
branches: [ main,wallet, master ]
paths:
- '**'
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Tag version to be used for Docker image"
required: true
default: "prod"
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env:
REGISTRY: docker.io
# Docker Hub 个人命名空间(需与 DOCKER_USERNAME 一致)
DOCKER_USER: kim6789
# Docker Hub 凭证来自仓库 Secrets
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
GO_VERSION: "1.24"
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: 检出代码
uses: actions/checkout@v4
with:
submodules: recursive
- name: 设置 SSH 密钥
run: |
echo "🔑 配置 SSH 密钥..."
# 创建 .ssh 目录
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# 解码 base64 编码的 SSH 私钥
echo "${{ secrets.SSH_PRIVATE_KEY }}" | base64 -d > ~/.ssh/id_rsa
# 验证解码是否成功
if [ ! -s ~/.ssh/id_rsa ]; then
echo "❌ SSH 私钥解码失败或为空"
exit 1
fi
# 设置权限
chmod 600 ~/.ssh/id_rsa
# 配置 SSH 主机密钥验证(可选,根据需要调整)
ssh-keyscan git.imall.cloud >> ~/.ssh/known_hosts 2>/dev/null || true
chmod 644 ~/.ssh/known_hosts
echo "✅ SSH 密钥配置完成"
- name: 检出 protocol 仓库
run: |
# 克隆 protocol 仓库到当前目录的 protocol 子目录(使用 SSH
git clone git@git.imall.cloud:openim/protocol.git ./protocol || true
cd ./protocol
git fetch --all
git checkout v1.0.4
- name: 设置 Go 缓存
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-
- name: 设置 Go 环境
uses: actions/setup-go@v5
with:
go-version: ${{ env.GO_VERSION }}
cache: true
- name: 设置 Docker Buildx
uses: docker/setup-buildx-action@v3.8.0
with:
platforms: linux/amd64
- name: 登录到 Docker Hub
uses: docker/login-action@v3.1.0
with:
# 使用账号登录,镜像仍推送到 DOCKER_USER 命名空间
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_PASSWORD }}
- name: 构建和推送 Docker 镜像
run: |
set -e
# 设置版本标签 - 默认使用 prod
if [ "${{ github.event_name }}" = "release" ]; then
VERSION_TAG="${{ github.event.release.tag_name }}"
elif [ -n "${{ github.event.inputs.tag }}" ]; then
VERSION_TAG="${{ github.event.inputs.tag }}"
elif [ "${{ github.ref }}" = "refs/heads/main" ] || [ "${{ github.ref }}" = "refs/heads/master" ]; then
VERSION_TAG="prod"
else
VERSION_TAG="prod" # 所有分支默认都使用 prod
fi
echo "版本标签: $VERSION_TAG"
echo "Docker用户: $DOCKER_USER"
# 获取CPU核心数
CPU_CORES=$(nproc)
echo "CPU核心数: $CPU_CORES"
# 定义服务列表
API_SERVICES=(
"openim-chat-api"
)
RPC_SERVICES=(
"openim-chat-rpc"
)
ADMIN_SERVICES=(
"openim-admin-api"
"openim-admin-rpc"
)
# 合并所有服务
ALL_SERVICES=("${API_SERVICES[@]}" "${RPC_SERVICES[@]}" "${ADMIN_SERVICES[@]}")
# 资源监控函数
monitor_resources() {
local cpu_usage=0
local mem_usage=0
local load_1min=0
# 获取CPU使用率
if command -v top >/dev/null 2>&1; then
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | sed 's/%us,//' | cut -d. -f1)
elif [ -f /proc/stat ]; then
local prev_idle=$(cat /tmp/cpu_idle 2>/dev/null || echo "0")
local prev_total=$(cat /tmp/cpu_total 2>/dev/null || echo "0")
local curr_cpu=($(cat /proc/stat | head -1))
local curr_idle=${curr_cpu[4]}
local curr_total=0
for val in "${curr_cpu[@]:1}"; do
curr_total=$((curr_total + val))
done
local diff_idle=$((curr_idle - prev_idle))
local diff_total=$((curr_total - prev_total))
local diff_usage=$((diff_total - diff_idle))
if [ $diff_total -gt 0 ]; then
cpu_usage=$((diff_usage * 100 / diff_total))
fi
echo "$curr_idle" > /tmp/cpu_idle
echo "$curr_total" > /tmp/cpu_total
fi
# 限制CPU使用率在0-100%之间
if [ "$cpu_usage" -gt 100 ]; then
cpu_usage=100
elif [ "$cpu_usage" -lt 0 ]; then
cpu_usage=0
fi
# 获取内存使用率
if command -v free >/dev/null 2>&1; then
mem_usage=$(free | awk 'NR==2{printf "%.0f", $3*100/$2}')
fi
# 获取1分钟负载
if [ -f /proc/loadavg ]; then
load_1min=$(cat /proc/loadavg | awk '{print $1}' | cut -d. -f1)
fi
echo "CPU: ${cpu_usage}%, 内存: ${mem_usage}%, 负载: ${load_1min}"
}
# 检查资源状态
check_resources() {
local cpu_usage=$(monitor_resources | awk '{print $1}' | sed 's/CPU://' | sed 's/%//')
local mem_usage=$(monitor_resources | awk '{print $2}' | sed 's/内存://' | sed 's/%//')
local load_1min=$(monitor_resources | awk '{print $3}' | sed 's/负载://')
# 如果CPU使用率超过90%或内存使用率超过85%,等待资源释放
if [ "$cpu_usage" -gt 90 ] || [ "$mem_usage" -gt 85 ]; then
echo "资源使用率过高,等待释放..."
local wait_count=0
local max_wait=20
while [ $wait_count -lt $max_wait ]; do
sleep 5
wait_count=$((wait_count + 1))
# 清理Docker缓存
if [ $((wait_count % 5)) -eq 0 ]; then
docker system prune -f >/dev/null 2>&1 || true
docker builder prune -f >/dev/null 2>&1 || true
fi
cpu_usage=$(monitor_resources | awk '{print $1}' | sed 's/CPU://' | sed 's/%//')
mem_usage=$(monitor_resources | awk '{print $2}' | sed 's/内存://' | sed 's/%//')
if [ "$cpu_usage" -le 90 ] && [ "$mem_usage" -le 85 ]; then
echo "资源已释放,继续构建"
break
fi
echo "等待资源释放... ($wait_count/$max_wait)"
done
if [ $wait_count -eq $max_wait ]; then
echo "警告:等待超时,继续执行构建"
fi
fi
}
# 构建服务函数
build_service() {
local service=$1
local dockerfile="build/images/$service/Dockerfile"
echo "检查服务: $service"
echo " Dockerfile 路径: $dockerfile"
echo " Dockerfile 是否存在: $([ -f "$dockerfile" ] && echo "是" || echo "否")"
# 检查资源状态
check_resources
if [ -f "$dockerfile" ]; then
echo "📦 开始构建 Docker 镜像: $service"
echo " 📁 Dockerfile: $dockerfile"
echo " 🏷️ 版本标签: $VERSION_TAG"
echo " 👤 Docker用户: $DOCKER_USER"
# 降低日志噪音:不打印 buildx 状态
# 构建和推送 Docker 镜像
echo " 尝试使用 buildx 构建..."
# 降低日志噪音:省略上下文验证输出
local start_time=$(date +%s)
# 尝试使用 buildx 构建
# 使用 git commit SHA 作为构建参数,确保代码变化时缓存失效
BUILD_SHA=$(git rev-parse --short HEAD)
BUILD_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
if docker buildx build \
--platform linux/amd64 \
--file "$dockerfile" \
--tag "$DOCKER_USER/$service:$VERSION_TAG" \
--push \
--cache-from type=gha,scope=openim-chat-build-${{ github.ref_name }}-$service \
--cache-to type=gha,mode=max,scope=openim-chat-build-${{ github.ref_name }}-$service \
--build-arg BUILDKIT_INLINE_CACHE=1 \
--build-arg GOCACHE=/go-cache \
--build-arg GOMAXPROCS=$CPU_CORES \
--build-arg BUILD_SHA=$BUILD_SHA \
--build-arg BUILD_TIME=$BUILD_TIME \
--provenance=false \
--sbom=false \
. > "/tmp/build_${service}.log" 2>&1; then
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo ""
echo "✅ 构建成功: $service"
echo " ⏱️ 耗时: ${duration}秒"
echo " 🏷️ 镜像: $DOCKER_USER/$service:$VERSION_TAG"
echo " 📤 推送状态: 已完成"
else
echo " buildx 构建失败,查看详细错误日志..."
echo " Buildx 构建日志:"
if [ -f "/tmp/build_${service}.log" ]; then
cat "/tmp/build_${service}.log"
fi
echo " 尝试使用传统 docker build..."
# 回退到传统 docker build
local build_cmd="docker build --file $dockerfile --tag $DOCKER_USER/$service:$VERSION_TAG --build-arg BUILDKIT_INLINE_CACHE=1 --build-arg GOCACHE=/go-cache --build-arg GOMAXPROCS=$CPU_CORES ."
echo " 传统构建命令: $build_cmd"
if eval "$build_cmd" > "/tmp/traditional_build_${service}.log" 2>&1; then
echo " 传统构建成功,推送镜像..."
docker push "$DOCKER_USER/$service:$VERSION_TAG" || echo "推送 $VERSION_TAG 失败"
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo ""
echo "✅ 构建成功: $service (传统构建)"
echo " ⏱️ 耗时: ${duration}秒"
echo " 🏷️ 镜像: $DOCKER_USER/$service:$VERSION_TAG"
echo " 📤 推送状态: 已完成"
else
local end_time=$(date +%s)
local duration=$((end_time - start_time))
echo ""
echo "❌ 构建失败: $service"
echo " ⏱️ 耗时: ${duration}秒"
echo " 🔍 查看详细错误日志:"
echo "=== 详细错误日志 ==="
echo "服务: $service"
echo "Dockerfile: $dockerfile"
echo "构建命令:"
echo "docker buildx build --platform linux/amd64 --file $dockerfile --tag $DOCKER_USER/$service:$VERSION_TAG --push --quiet --cache-from type=gha,scope=openim-chat-build-${{ github.ref_name }}-$service --cache-to type=gha,mode=max,scope=openim-chat-build-${{ github.ref_name }}-$service --build-arg BUILDKIT_INLINE_CACHE=1 --build-arg GOCACHE=/go-cache --build-arg GOMAXPROCS=$CPU_CORES --provenance=false --sbom=false ."
echo ""
echo "Buildx 构建日志:"
if [ -f "/tmp/build_${service}.log" ]; then
cat "/tmp/build_${service}.log"
fi
echo ""
echo "传统构建日志:"
if [ -f "/tmp/traditional_build_${service}.log" ]; then
cat "/tmp/traditional_build_${service}.log"
fi
echo "=== 错误日志结束 ==="
return 1
fi
fi
else
echo "❌ 错误: 找不到 Dockerfile: $dockerfile"
echo " 当前目录: $(pwd)"
echo " 目录内容: $(ls -la build/images/ 2>/dev/null || echo 'build/images 目录不存在')"
echo " 查找所有 Dockerfile: $(find . -name "Dockerfile" -type f 2>/dev/null | head -5)"
return 1
fi
}
# 初始化构建统计
failed_services=()
successful_services=()
# 计算总服务数
total_services=$((${#API_SERVICES[@]} + ${#RPC_SERVICES[@]} + ${#ADMIN_SERVICES[@]}))
echo ""
echo "🎯 开始构建 OpenIM Chat 镜像"
echo "📊 构建统计:"
echo " 📦 API服务: ${#API_SERVICES[@]} 个"
echo " 🔧 RPC服务: ${#RPC_SERVICES[@]} 个"
echo " 👑 管理服务: ${#ADMIN_SERVICES[@]} 个"
echo " 📈 总计: $total_services 个服务"
echo " 🏷️ 版本标签: $VERSION_TAG"
echo " 👤 Docker用户: $DOCKER_USER"
echo ""
# 先构建API服务
echo "API服务构建:"
echo "总服务数: ${#API_SERVICES[@]}"
echo "=========================================="
for i in "${!API_SERVICES[@]}"; do
service="${API_SERVICES[$i]}"
current=$((i + 1))
total=${#API_SERVICES[@]}
echo ""
echo "🚀 [${current}/${total}] 开始构建: $service"
echo "⏰ 开始时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
if build_service "$service"; then
successful_services+=("$service")
echo "✅ [${current}/${total}] 构建完成: $service"
else
failed_services+=("$service")
echo "❌ [${current}/${total}] 构建失败: $service"
fi
echo "⏰ 完成时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
done
# 构建RPC服务
echo "RPC服务构建:"
echo "总服务数: ${#RPC_SERVICES[@]}"
echo "=========================================="
for i in "${!RPC_SERVICES[@]}"; do
service="${RPC_SERVICES[$i]}"
current=$((i + 1))
total=${#RPC_SERVICES[@]}
echo ""
echo "🚀 [${current}/${total}] 开始构建: $service"
echo "⏰ 开始时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
if build_service "$service"; then
successful_services+=("$service")
echo "✅ [${current}/${total}] 构建完成: $service"
else
failed_services+=("$service")
echo "❌ [${current}/${total}] 构建失败: $service"
fi
echo "⏰ 完成时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
done
# 构建管理服务
echo "管理服务构建:"
echo "总服务数: ${#ADMIN_SERVICES[@]}"
echo "=========================================="
for i in "${!ADMIN_SERVICES[@]}"; do
service="${ADMIN_SERVICES[$i]}"
current=$((i + 1))
total=${#ADMIN_SERVICES[@]}
echo ""
echo "🚀 [${current}/${total}] 开始构建: $service"
echo "⏰ 开始时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
if build_service "$service"; then
successful_services+=("$service")
echo "✅ [${current}/${total}] 构建完成: $service"
else
failed_services+=("$service")
echo "❌ [${current}/${total}] 构建失败: $service"
fi
echo "⏰ 完成时间: $(date '+%H:%M:%S')"
echo "------------------------------------------"
done
# 输出构建结果统计
echo ""
echo "🎉 构建完成总结"
echo "=========================================="
echo "✅ 成功构建: ${#successful_services[@]} 个服务"
echo "❌ 构建失败: ${#failed_services[@]} 个服务"
echo "📊 成功率: $(( ${#successful_services[@]} * 100 / total_services ))%"
echo ""
if [ ${#successful_services[@]} -gt 0 ]; then
echo "✅ 成功构建的服务:"
for service in "${successful_services[@]}"; do
echo " - $service"
done
echo ""
fi
if [ ${#failed_services[@]} -gt 0 ]; then
echo "❌ 构建失败的服务:"
for service in "${failed_services[@]}"; do
echo " - $service"
done
echo ""
fi
if [ ${#failed_services[@]} -gt 0 ]; then
echo ""
echo "失败服务错误日志:"
for service in "${failed_services[@]}"; do
echo "=== $service 错误日志 ==="
if [ -f "/tmp/build_${service}.log" ]; then
echo "Buildx 构建日志:"
cat "/tmp/build_${service}.log"
fi
if [ -f "/tmp/traditional_build_${service}.log" ]; then
echo "传统构建日志:"
cat "/tmp/traditional_build_${service}.log"
fi
echo "=== $service 错误日志结束 ==="
echo ""
done
fi
# 如果有失败的服务退出码为1
if [ ${#failed_services[@]} -gt 0 ]; then
echo "❌ 构建失败,有 ${#failed_services[@]} 个服务构建失败"
exit 1
else
echo "🎉 所有服务构建成功!"
fi
- name: 配置 kubectl
if: success()
run: |
echo "🔧 配置 kubectl 连接到阿里云 ACK..."
# 创建 kubeconfig 目录
mkdir -p ~/.kube
# 直接解码 base64 内容
echo "解码 KUBECONFIG..."
echo "${{ secrets.KUBECONFIG }}" | base64 -d > ~/.kube/config
# 验证解码是否成功
if [ ! -s ~/.kube/config ]; then
echo "❌ KUBECONFIG 解码失败或为空"
exit 1
fi
# 设置权限
chmod 600 ~/.kube/config
echo "✅ kubeconfig 配置完成"
# 降低日志噪音:不输出 kubeconfig 内容
- name: 部署到阿里云 ACK
if: success()
run: |
echo "🚀 开始部署到阿里云 ACK..."
# 简单验证 kubectl
if ! kubectl version --client >/dev/null 2>&1; then
echo "❌ kubectl 不可用,跳过部署步骤"
exit 0
fi
echo "✅ kubectl 可用,尝试部署..."
# 获取版本标签
if [ "${{ github.event_name }}" = "release" ]; then
VERSION_TAG="${{ github.event.release.tag_name }}"
else
VERSION_TAG="${{ github.event.inputs.tag || github.ref_name || 'prod' }}"
fi
DOCKER_USER="${{ env.DOCKER_USER }}"
NS=${NS:-default}
echo "部署参数:"
echo "版本标签: $VERSION_TAG"
echo "Docker用户: $DOCKER_USER"
# 检查部署文件是否存在
DEPLOY_DIR=".gitea/deployments/deploy"
if [ ! -d "$DEPLOY_DIR" ]; then
echo "❌ 部署目录不存在: $DEPLOY_DIR"
echo "📁 当前目录内容:"
ls -la
exit 1
fi
echo "📁 部署目录: $DEPLOY_DIR"
echo "使用命名空间: $NS"
# 创建命名空间(如果不存在)
kubectl get ns "$NS" >/dev/null 2>&1 || kubectl create ns "$NS"
kubectl config set-context --current --namespace="$NS"
# 尝试部署,如果失败则继续
echo "🚀 开始部署 Chat 服务..."
# 定义所有部署文件
DEPLOY_FILES=(
"openim-chat-api-deployment.yml"
"openim-chat-api-service.yml"
"openim-chat-rpc-deployment.yml"
"openim-chat-rpc-service.yml"
"openim-admin-api-deployment.yml"
"openim-admin-api-service.yml"
"openim-admin-rpc-deployment.yml"
"openim-admin-rpc-service.yml"
)
# 部署所有文件
for file in "${DEPLOY_FILES[@]}"; do
if [ -f "$DEPLOY_DIR/$file" ]; then
echo "📄 部署文件: $file"
# 更新镜像标签
sed -i "s|image: .*/openim-|image: $DOCKER_USER/openim-|g" "$DEPLOY_DIR/$file"
sed -i "s|:latest|:$VERSION_TAG|g" "$DEPLOY_DIR/$file"
# 应用文件
kubectl apply -f "$DEPLOY_DIR/$file" || echo "⚠️ $file 部署失败,但继续"
else
echo "⚠️ $file 不存在,跳过"
fi
done
echo ""
echo "🔍 验证部署状态..."
# 简单检查,如果失败也不阻塞流程
kubectl get pods -l app=openim-chat-api || echo "⚠️ 无法获取 chat-api Pod 状态"
kubectl get pods -l app=openim-chat-rpc || echo "⚠️ 无法获取 chat-rpc Pod 状态"
echo "✅ 验证完成"
- name: 清理
if: always()
run: |
echo "🧹 清理临时文件..."
rm -f /tmp/build_*.log
echo "✅ 清理完成"

View File

@@ -1,9 +1,11 @@
name: itom-platform auto build image
# itom-platform:auto-ci-managed
# 自动生成:如需自定义并阻止覆盖,请删除上一行标记
on:
push:
branches:
- dev
- main
workflow_dispatch: {}
permissions:
@@ -20,23 +22,28 @@ jobs:
runs-on: ubuntu-latest
env:
# 使用 Docker Hub 作为镜像仓库
REGISTRY: docker.io
# Docker Hub 个人命名空间(需与 DOCKER_USERNAME 一致)
IMAGE: docker.io/kim6789/chat-deploy
# Docker Hub 凭证来自仓库 Secrets
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
steps:
- name: Check trigger mode
env:
# 兼容 Gitea/Forgejo优先仓库变量其次 Secrets
CI_TRIGGER_MODE_VAR: ${{ vars.CI_TRIGGER_MODE }}
CI_TRIGGER_MODE_SECRET: ${{ secrets.CI_TRIGGER_MODE }}
shell: sh
run: |
set -eu
MODE="${CI_TRIGGER_MODE_VAR:-${CI_TRIGGER_MODE_SECRET:-dispatch}}"
EVENT="${GITHUB_EVENT_NAME:-${GITEA_EVENT_NAME:-}}"
MODE="${CI_TRIGGER_MODE:-${CI_TRIGGER_MODE_VAR:-${CI_TRIGGER_MODE_SECRET:-dispatch}}}"
MODE="$(printf 'git.imall.cloud' "$MODE" | tr 'A-Z' 'a-z')"
EVENT="${GITHUB_EVENT_NAME:-${GITEA_EVENT_NAME:-${GITEA_EVENT:-}}}"
EVENT="$(printf '' "$EVENT" | tr 'A-Z' 'a-z')"
if [ -z "$EVENT" ]; then
# 兼容重跑场景:部分运行器不会传递事件名
EVENT="workflow_dispatch"
fi
ALLOW="false"
case "$EVENT" in
workflow_dispatch)
workflow_dispatch|manual|workflow_run)
if [ "$MODE" = "dispatch" ] || [ "$MODE" = "both" ]; then
ALLOW="true"
fi
@@ -46,6 +53,12 @@ jobs:
ALLOW="true"
fi
;;
*)
# 未知事件默认走 dispatch 逻辑,避免误跳过
if [ "$MODE" = "dispatch" ] || [ "$MODE" = "both" ]; then
ALLOW="true"
fi
;;
esac
echo "CI_TRIGGER_MODE=$MODE" >> "$GITHUB_ENV"
echo "CI_TRIGGER_ALLOWED=$ALLOW" >> "$GITHUB_ENV"
@@ -75,7 +88,7 @@ jobs:
WORKDIR="${GITHUB_WORKSPACE:-/workspace}"
mkdir -p "$WORKDIR"
REPO="${GITHUB_REPOSITORY:-${GITEA_REPOSITORY:-}}"
SERVER="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://git.imall.cloud}}"
SERVER="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://}}"
if [ -z "$REPO" ]; then
echo "ERROR: missing repository info."
exit 1
@@ -157,26 +170,99 @@ jobs:
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
shell: sh
env:
GIT_USER: ${{ secrets.GIT_USER }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
%!s(MISSING)
run: |
set -eu
# 使用 Docker Hub 凭证登录
if [ -z "${DOCKER_USERNAME:-}" ] || [ -z "${DOCKER_PASSWORD:-}" ]; then
echo "ERROR: 缺少 Docker Hub 凭证DOCKER_USERNAME/DOCKER_PASSWORD"
exit 1
# 带重试的登录函数(解决 Docker Hub 网络超时问题)
login_try() {
local user="$1"
local pass="$2"
local label="$3"
local max_retries=5
local retry_delay=10
if [ -z "$user" ] || [ -z "$pass" ]; then
return 1
fi
echo "$DOCKER_PASSWORD" | docker login "$REGISTRY" -u "$DOCKER_USERNAME" --password-stdin
for attempt in $(seq 1 $max_retries); do
echo "Registry login attempt $attempt/$max_retries ($label)..."
if echo "$pass" | docker login "$REGISTRY" -u "$user" --password-stdin 2>&1; then
echo "Registry login ok ($label)"
return 0
fi
if [ $attempt -lt $max_retries ]; then
echo "Login failed, waiting ${retry_delay}s before retry..."
sleep $retry_delay
retry_delay=$((retry_delay * 2))
fi
done
return 1
}
if login_try "$DOCKER_USERNAME" "$DOCKER_PASSWORD" "DOCKER"; then
exit 0
fi
if login_try "$REGISTRY_USER" "$REGISTRY_PASSWORD" "REGISTRY_USER"; then
exit 0
fi
if login_try "$GIT_USER" "$GIT_TOKEN" "GIT_USER"; then
exit 0
fi
if login_try "${AUTO_REGISTRY_USER:-}" "${AUTO_REGISTRY_PASS:-}" "AUTO_REGISTRY"; then
exit 0
fi
ACTOR="${GITEA_ACTOR:-${FORGEJO_ACTOR:-${GITHUB_ACTOR:-}}}"
JOB_TOKEN="${GITEA_TOKEN:-${FORGEJO_TOKEN:-${GITHUB_TOKEN:-}}}"
if login_try "$ACTOR" "$JOB_TOKEN" "JOB_TOKEN"; then
exit 0
fi
echo "ERROR: registry login failed after retries. Provide REGISTRY_USER/REGISTRY_PASSWORD or GIT_USER/GIT_TOKEN with packages write permission."
exit 1
- name: Build and push images
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
shell: sh
env:
GIT_USER: ${{ secrets.GIT_USER }}
GIT_TOKEN: ${{ secrets.GIT_TOKEN }}
REGISTRY_USER: ${{ secrets.REGISTRY_USER }}
REGISTRY_PASSWORD: ${{ secrets.REGISTRY_PASSWORD }}
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
%!s(MISSING)
run: |
set -eu
cd "${GITHUB_WORKSPACE:-/workspace}"
IMAGE_BRANCH_TAG="$IMAGE:${BRANCH}"
IMAGE_SHA_TAG="$IMAGE:sha-${SHA_SHORT}"
docker build -t "$IMAGE_BRANCH_TAG" -t "$IMAGE_SHA_TAG" -f "$DOCKERFILE_PATH" "$BUILD_CONTEXT"
git_user="${GIT_USER:-}"
git_token="${GIT_TOKEN:-}"
registry_user="${REGISTRY_USER:-}"
registry_pass="${REGISTRY_PASSWORD:-}"
if [ -z "$registry_user" ] && [ -n "${DOCKER_USERNAME:-}" ]; then
registry_user="$DOCKER_USERNAME"
registry_pass="${DOCKER_PASSWORD:-}"
fi
if [ -z "$registry_user" ] && [ -n "${AUTO_REGISTRY_USER:-}" ]; then
registry_user="$AUTO_REGISTRY_USER"
registry_pass="${AUTO_REGISTRY_PASS:-}"
fi
set -- docker build
if [ -n "$git_user" ] && [ -n "$git_token" ]; then
set -- "$@" --build-arg "GIT_USER=$git_user" --build-arg "GIT_TOKEN=$git_token"
fi
if [ -n "$registry_user" ] && [ -n "$registry_pass" ]; then
set -- "$@" --build-arg "REGISTRY_USER=$registry_user" --build-arg "REGISTRY_PASSWORD=$registry_pass"
fi
set -- "$@" -t "$IMAGE_BRANCH_TAG" -t "$IMAGE_SHA_TAG" -f "$DOCKERFILE_PATH" "$BUILD_CONTEXT"
"$@"
log_image() {
local tag="$1"
@@ -201,16 +287,30 @@ jobs:
log_layers "$IMAGE_BRANCH_TAG"
log_history "$IMAGE_BRANCH_TAG"
# 带重试的 push 函数(解决 Docker Hub 网络超时问题)
push_with_diag() {
local tag="$1"
local safe_tag
safe_tag=$(echo "$tag" | tr '/:' '__')
local log_file="/tmp/docker-push-${safe_tag}.log"
echo "== docker push $tag =="
local max_retries=3
local retry_delay=15
for attempt in $(seq 1 $max_retries); do
echo "== docker push $tag (attempt $attempt/$max_retries) =="
if docker push "$tag" >"$log_file" 2>&1; then
tail -n 5 "$log_file" || true
return 0
fi
echo "Push attempt $attempt failed."
if [ $attempt -lt $max_retries ]; then
echo "Waiting ${retry_delay}s before retry..."
sleep $retry_delay
retry_delay=$((retry_delay * 2))
fi
done
# 所有重试失败后,输出诊断信息
log_image "$tag"
log_layers "$tag"
log_history "$tag"

22
.github/.codecov.yml vendored
View File

@@ -1,22 +0,0 @@
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
coverage:
status:
project:
default: false # disable the default status that measures entire project
pkg: # declare a new status context "pkg"
paths:
- pkg/* # only include coverage in "pkg/" folder
informational: true # Always pass check
patch: off # disable the commit only checks

View File

@@ -1,10 +0,0 @@
openim-sigs/openim-docker:
- source: ./config
dest: ./openim-chat/release/config
replace: true
- source: ./docs
dest: ./openim-chat/release/docs
replace: true
- source: ./scripts
dest: ./openim-chat/release/scripts
replace: true

26
.github/sync.yml vendored
View File

@@ -1,26 +0,0 @@
# Copyright © 2023 OpenIM. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# https://github.com/BetaHuhn/repo-file-sync-action
# Synchronization for the.github repository
openim-sigs/openim-docker:
- source: ./config
dest: ./openim-chat/main/config
replace: true
- source: ./docs
dest: ./openim-chat/main/docs
replace: true
- source: ./scripts
dest: ./openim-chat/main/scripts
replace: true

View File

@@ -1,29 +0,0 @@
name: Assign issue to comment author
on:
issue_comment:
types: [created]
jobs:
assign-issue:
if: |
contains(github.event.comment.body, '/assign') || contains(github.event.comment.body, '/accept') &&
!contains(github.event.comment.user.login, 'openim-robot')
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Assign the issue
run: |
export LETASE_MILESTONES=$(curl 'https://api.github.com/repos/$OWNER/$PEPO/milestones' | jq -r 'last(.[]).title')
gh issue edit ${{ github.event.issue.number }} --add-assignee "${{ github.event.comment.user.login }}"
gh issue edit ${{ github.event.issue.number }} --add-label "accepted"
gh issue comment $ISSUE --body "@${{ github.event.comment.user.login }} Glad to see you accepted this issue🤲, this issue has been assigned to you. I set the milestones for this issue to [$LETASE_MILESTONES](https://github.com/$OWNER/$PEPO/milestones), We are looking forward to your PR!"
# gh issue edit ${{ github.event.issue.number }} --milestone "$LETASE_MILESTONES"
env:
GH_TOKEN: ${{ secrets.BOT_TOKEN }}
ISSUE: ${{ github.event.issue.html_url }}
OWNER: ${{ github.repository_owner }}
REPO: ${{ github.event.repository.name }}

View File

@@ -1,38 +0,0 @@
name: Invite users to join OpenIM Community.
on:
issue_comment:
types:
- created
jobs:
issue_comment:
name: Invite users to join OpenIM Community
if: ${{ github.event.comment.body == '/invite' || github.event.comment.body == '/close' || github.event.comment.body == '/comment' }}
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Invite user to join OpenIM Community
uses: peter-evans/create-or-update-comment@v4
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
We value close connections with our users, developers, and contributors here at Open-IM-Server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of Open-IM-Server. You can ask technical questions, seek help, or share your experiences with other users of Open-IM-Server.
In addition to Slack, we also offer the following ways to get in touch:
+ <a href="https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A" target="_blank"><img src="https://img.shields.io/badge/Slack-OpenIM%2B-blueviolet?logo=slack&amp;logoColor=white"></a> We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) team channel.
+ <a href="https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=info@openim.io" target="_blank"><img src="https://img.shields.io/badge/gmail-%40OOpenIMSDKCore?style=social&logo=gmail"></a> Get in touch with us on [Gmail](https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email.
+ <a href="https://doc.rentsoft.cn/" target="_blank"><img src="https://img.shields.io/badge/%E5%8D%9A%E5%AE%A2-%40OpenIMSDKCore-blue?style=social&logo=Octopus%20Deploy"></a> Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
+ <a href="https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg" target="_blank"><img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-OpenIMSDKCore-brightgreen?logo=wechat&style=flat-square"></a> Add [Wechat](https://github.com/OpenIMSDK/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible.
# - name: Close Issue
# uses: peter-evans/close-issue@v3
# with:
# token: ${{ secrets.BOT_GITHUB_TOKEN }}
# issue-number: ${{ github.event.issue.number }}
# comment: 🤖 Auto-closing issue, if you still need help please reopen the issue or ask for help in the community above
# labels: |
# accepted

View File

@@ -1,52 +0,0 @@
# Copyright © 2023 OpenIM open source community. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Invite users to join our group
on:
issue_comment:
types:
- created
jobs:
issue_comment:
name: Invite users to join our group
if: ${{ github.event.comment.body == '/invite' || github.event.comment.body == '/close' || github.event.comment.body == '/comment' }}
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Invite user to join our group
uses: peter-evans/create-or-update-comment@v3
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
body: |
We value close connections with our users, developers, and contributors here at Open-IM-Server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of Open-IM-Server. You can ask technical questions, seek help, or share your experiences with other users of Open-IM-Server.
In addition to Slack, we also offer the following ways to get in touch:
+ <a href="https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A" target="_blank"><img src="https://img.shields.io/badge/Slack-OpenIM%2B-blueviolet?logo=slack&amp;logoColor=white"></a> We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) team channel.
+ <a href="https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com" target="_blank"><img src="https://img.shields.io/badge/gmail-%40OOpenIMSDKCore?style=social&logo=gmail"></a> Get in touch with us on [Gmail](https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email.
+ <a href="https://doc.rentsoft.cn/" target="_blank"><img src="https://img.shields.io/badge/%E5%8D%9A%E5%AE%A2-%40OpenIMSDKCore-blue?style=social&logo=Octopus%20Deploy"></a> Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
+ <a href="https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg" target="_blank"><img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-OpenIMSDKCore-brightgreen?logo=wechat&style=flat-square"></a> Add [Wechat](https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible.
- name: Close Issue
uses: peter-evans/close-issue@v3
with:
token: ${{ secrets.BOT_GITHUB_TOKEN }}
issue-number: ${{ github.event.issue.number }}
comment: 🤖 Auto-closing issue, if you still need help please reopen the issue or ask for help in the community above
labels: |
triage/accepted

View File

@@ -1,105 +0,0 @@
name: Publish Docker image
on:
push:
branches:
# - main
- release-*
# tags:
# - v*
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Tag version to be used for Docker image"
required: true
default: "v3.8.0"
env:
GO_VERSION: "1.22"
# Docker Hub 凭证来自仓库 Secrets
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
jobs:
build-image:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.8.0
- name: Log in to Docker Hub
uses: docker/login-action@v3.3.0
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_PASSWORD }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Aliyun Container Registry
uses: docker/login-action@v3.3.0
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5.6.0
with:
images: |
openim/openim-chat
ghcr.io/openimsdk/openim-chat
registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat
tags: |
type=ref,event=tag
type=schedule
type=ref,event=branch
# type=ref,event=pr
# type=semver,pattern={{version}}
type=semver,pattern=v{{version}}
type=semver,pattern=release-{{raw}}
type=sha
type=raw,value=${{ github.event.inputs.tag }}
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: .
platforms: linux/amd64,linux/arm64
push: ${{ github.event_name != 'pull_request' }}
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
- name: Verify multi-platform support
run: |
images=("openim/openim-chat" "ghcr.io/openimsdk/openim-chat" "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat")
for image in "${images[@]}"; do
for tag in $(echo "${{ steps.meta.outputs.tags }}" | tr ',' '\n'); do
manifest=$(docker manifest inspect "$image:$tag" || echo "error")
if [[ "$manifest" == "error" ]]; then
echo "Manifest not found for $image:$tag"
exit 1
fi
amd64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "amd64")')
arm64_found=$(echo "$manifest" | jq '.manifests[] | select(.platform.architecture == "arm64")')
if [[ -z "$amd64_found" ]]; then
echo "Multi-platform support check failed for $image:$tag - missing amd64"
exit 1
fi
if [[ -z "$arm64_found" ]]; then
echo "Multi-platform support check failed for $image:$tag - missing arm64"
exit 1
fi
done
done

View File

@@ -1,78 +0,0 @@
name: Release Changelog
on:
release:
types: [released]
permissions:
contents: write
pull-requests: write
jobs:
update-changelog:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Run Go Changelog Generator
run: |
# Run the Go changelog generator, passing the release tag if available
if [ "${{ github.event.release.tag_name }}" = "latest" ]; then
go run tools/changelog/changelog.go > "${{ github.event.release.tag_name }}-changelog.md"
else
go run tools/changelog/changelog.go "${{ github.event.release.tag_name }}" > "${{ github.event.release.tag_name }}-changelog.md"
fi
- name: Handle changelog files
run: |
# Ensure that the CHANGELOG directory exists
mkdir -p CHANGELOG
# Extract Major.Minor version by removing the 'v' prefix from the tag name
TAG_NAME=${{ github.event.release.tag_name }}
CHANGELOG_VERSION_NUMBER=$(echo "$TAG_NAME" | sed 's/^v//' | grep -oP '^\d+\.\d+')
# Define the new changelog file path
CHANGELOG_FILENAME="CHANGELOG-$CHANGELOG_VERSION_NUMBER.md"
CHANGELOG_PATH="CHANGELOG/$CHANGELOG_FILENAME"
# Check if the changelog file for the current release already exists
if [ -f "$CHANGELOG_PATH" ]; then
# If the file exists, append the new changelog to the existing one
cat "$CHANGELOG_PATH" >> "${TAG_NAME}-changelog.md"
# Overwrite the existing changelog with the updated content
mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH"
else
# If the changelog file doesn't exist, rename the temp changelog file to the new changelog file
mv "${TAG_NAME}-changelog.md" "$CHANGELOG_PATH"
# Ensure that README.md exists
if [ ! -f "CHANGELOG/README.md" ]; then
echo -e "# CHANGELOGs\n\n" > CHANGELOG/README.md
fi
# Add the new changelog entry at the top of the README.md
if ! grep -q "\[$CHANGELOG_FILENAME\]" CHANGELOG/README.md; then
sed -i "3i- [$CHANGELOG_FILENAME](./$CHANGELOG_FILENAME)" CHANGELOG/README.md
# Remove the extra newline character added by sed
# sed -i '4d' CHANGELOG/README.md
fi
fi
- name: Clean up
run: |
# Remove any temporary files that were created during the process
rm -f "${{ github.event.release.tag_name }}-changelog.md"
- name: Create Pull Request
uses: peter-evans/create-pull-request@v7.0.5
with:
token: ${{ secrets.GITHUB_TOKEN }}
commit-message: "Update CHANGELOG for release ${{ github.event.release.tag_name }}"
title: "Update CHANGELOG for release ${{ github.event.release.tag_name }}"
body: "This PR updates the CHANGELOG files for release ${{ github.event.release.tag_name }}"
branch: changelog-${{ github.event.release.tag_name }}
base: main
delete-branch: true
labels: changelog

View File

@@ -1,165 +0,0 @@
name: OpenIM Chat Build Test
on:
push:
branches:
- main
- release-*
paths-ignore:
- "docs/**"
- "README.md"
- "README_zh-CN.md"
- "**.md"
- "docs/**"
- "CONTRIBUTING.md"
pull_request:
branches:
- main
- release-*
paths-ignore:
- "README.md"
- "README_zh-CN.md"
- "CONTRIBUTING/**"
- "**.md"
- "docs/**"
workflow_dispatch:
jobs:
build-linux:
name: Execute OpenIM Script On Linux
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
# environment:
# name: openim
strategy:
matrix:
arch: [amd64]
steps:
- uses: actions/checkout@v4
- name: Set up Go
uses: actions/setup-go@v4
with:
go-version: "1.22"
- name: init
run: sudo bash bootstrap.sh
timeout-minutes: 20
- name: Checkout chat repository
uses: actions/checkout@v4
with:
repository: "openimsdk/chat-deploy"
path: "server-repo"
- name: Set up Docker for Linux
run: |
cd ${{ github.workspace }}/server-repo
sudo docker compose up -d
sudo sleep 30 # Increased sleep time for better stability
timeout-minutes: 30 # Increased timeout for Docker setup
- name: Modify Server Configuration
run: |
yq e '.secret = 123456' -i ${{ github.workspace }}/server-repo/config/share.yml
- name: Build and Start IM Serevr Services
run: |
cd ${{ github.workspace }}/server-repo
sudo mage
sudo mage start
sudo mage check
- name: Modify Chat Configuration
run: |
yq e '.openIM.secret = 123456' -i config/share.yml
- name: Build, Start, Check Services and Print Logs for Linux
run: |
sudo mage
sudo mage start
sudo mage check
- name: Restart Services and Print Logs
run: |
sudo mage stop
sudo mage start
sudo mage check
- name: Test Chat
run: |
check_error() {
echo "Response: $1"
errCode=$(echo $1 | jq -r '.errCode')
if [ "$errCode" != "0" ]; then
errMsg=$(echo $1 | jq -r '.errMsg')
echo "Error: $errMsg"
exit 1
fi
}
# Test register
response1=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
"verifyCode": "666666",
"platform": 3,
"autoLogin": true,
"user":{
"nickname": "test12312",
"areaCode":"+86",
"phoneNumber": "12345678190",
"password":"test123456"
}
}' http://127.0.0.1:10008/account/register)
check_error "$response1"
userID1=$(echo $response1 | jq -r '.data.userID')
echo "userID1: $userID1"
response2=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
"verifyCode": "666666",
"platform": 3,
"autoLogin": true,
"user":{
"nickname": "test22312",
"areaCode":"+86",
"phoneNumber": "12345678290",
"password":"test123456"
}
}' http://127.0.0.1:10008/account/register)
check_error "$response2"
userID2=$(echo $response2 | jq -r '.data.userID')
echo "userID2: $userID2"
# Test login
login_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
"platform": 3,
"areaCode":"+86",
"phoneNumber": "12345678190",
"password":"test123456"
}' http://localhost:10008/account/login)
check_error "$login_response"
# Test get admin token
get_admin_token_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -d '{
"secret": "123456",
"platformID": 2,
"userID": "imAdmin"
}' http://127.0.0.1:10002/auth/get_admin_token)
check_error "$get_admin_token_response"
adminToken=$(echo $get_admin_token_response | jq -r '.data.token')
echo "adminToken: $adminToken"
# Test send message
send_msg_response=$(curl -X POST -H "Content-Type: application/json" -H "operationID: imAdmin" -H "token: $adminToken" -d '{
"sendID": "'$userID1'",
"recvID": "'$userID2'",
"senderPlatformID": 3,
"content": {
"content": "hello!!"
},
"contentType": 101,
"sessionType": 1
}' http://127.0.0.1:10002/msg/send_msg)
check_error "$send_msg_response"

View File

@@ -1,45 +0,0 @@
name: Check-Coverage
on:
workflow_dispatch:
push:
branches: [ "main" ]
paths-ignore:
- "docs/**"
- "**/*.md"
- "**/*.yaml"
- "CONTRIBUTORS"
- "CHANGELOG/**"
pull_request:
branches: [ "*" ]
paths-ignore:
- "docs/**"
- "**/*.md"
- "**/*.yaml"
- "CONTRIBUTORS"
- "CHANGELOG/**"
env:
# Common versions
GO_VERSION: "1.20"
jobs:
coverage:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup Golang with cache
uses: magnetikonline/action-golang-cache@v4
with:
go-version: ${{ env.GO_VERSION }}
- name: Install Dependencies
run: sudo apt update && sudo apt install -y libgpgme-dev libbtrfs-dev libdevmapper-dev
- name: Run Cover
run: make cover
continue-on-error: true
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@v3

View File

@@ -1,40 +0,0 @@
name: CLA Assistant
on:
issue_comment:
types: [created]
pull_request_target:
types: [opened,closed,synchronize]
# explicitly configure permissions, in case your GITHUB_TOKEN workflow permissions are set to read-only in repository settings
permissions:
actions: write
contents: write # this can be 'read' if the signatures are in remote repository
pull-requests: write
statuses: write
jobs:
CLA-Assistant:
runs-on: ubuntu-latest
steps:
- name: "CLA Assistant"
if: (github.event.comment.body == 'recheck' || github.event.comment.body == 'I have read the CLA Document and I hereby sign the CLA') || github.event_name == 'pull_request_target'
uses: contributor-assistant/github-action@v2.4.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.BOT_TOKEN }}
with:
path-to-signatures: 'signatures/cla.json'
path-to-document: 'https://github.com/OpenIM-Robot/cla/blob/main/README.md' # e.g. a CLA or a DCO document
branch: 'main'
allowlist: 'bot*,*bot,OpenIM-Robot'
# the followings are the optional inputs - If the optional inputs are not given, then default values will be taken
remote-organization-name: OpenIM-Robot
remote-repository-name: cla
create-file-commit-message: 'Creating file for storing CLA Signatures'
# signed-commit-message: '$contributorName has signed the CLA in $owner/$repo#$pullRequestNo'
custom-notsigned-prcomment: '💕 Thank you for your contribution and please kindly read and sign our CLA. [CLA Docs](https://github.com/OpenIM-Robot/cla/blob/main/README.md)'
custom-pr-sign-comment: 'I have read the CLA Document and I hereby sign the CLA'
custom-allsigned-prcomment: '🤖 All Contributors have signed the [CLA](https://github.com/OpenIM-Robot/cla/blob/main/README.md).<br> The signed information is recorded [**here**](https://github.com/OpenIM-Robot/cla/blob/main/signatures/cla.json)'
#lock-pullrequest-aftermerge: false - if you don't want this bot to automatically lock the pull request after merging (default - true)
#use-dco-flag: true - If you are using DCO instead of CLA

View File

@@ -1,65 +0,0 @@
name: Cleanup After Milestone PRs Merged
on:
pull_request:
types:
- closed
jobs:
handle_pr:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4.2.0
- name: Get the PR title and extract PR numbers
id: extract_pr_numbers
run: |
# Get the PR title
PR_TITLE="${{ github.event.pull_request.title }}"
echo "PR Title: $PR_TITLE"
# Extract PR numbers from the title
PR_NUMBERS=$(echo "$PR_TITLE" | grep -oE "#[0-9]+" | tr -d '#' | tr '\n' ' ')
echo "Extracted PR Numbers: $PR_NUMBERS"
# Save PR numbers to a file
echo "$PR_NUMBERS" > pr_numbers.txt
echo "Saved PR Numbers to pr_numbers.txt"
# Check if the title matches a specific pattern
if echo "$PR_TITLE" | grep -qE "^deps: Merge( #[0-9]+)+ PRs into .+"; then
echo "proceed=true" >> $GITHUB_OUTPUT
else
echo "proceed=false" >> $GITHUB_OUTPUT
fi
- name: Use extracted PR numbers and label PRs
if: (steps.extract_pr_numbers.outputs.proceed == 'true' || contains(github.event.pull_request.labels.*.name, 'milestone-merge')) && github.event.pull_request.merged == true
run: |
# Read the previously saved PR numbers
PR_NUMBERS=$(cat pr_numbers.txt)
echo "Using extracted PR Numbers: $PR_NUMBERS"
# Loop through each PR number and add label
for PR_NUMBER in $PR_NUMBERS; do
echo "Adding 'cherry-picked' label to PR #$PR_NUMBER"
curl -X POST \
-H "Authorization: token ${{ secrets.GITHUB_TOKEN }}" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/${{ github.repository }}/issues/$PR_NUMBER/labels \
-d '{"labels":["cherry-picked"]}'
done
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Delete branch after PR close
if: steps.extract_pr_numbers.outputs.proceed == 'true' || contains(github.event.pull_request.labels.*.name, 'milestone-merge')
run: |
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
echo "Branch to delete: $BRANCH_NAME"
git push origin --delete "$BRANCH_NAME"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,67 +0,0 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '18 19 * * 6'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
language: [ 'go' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ]
# Learn more:
# https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed
steps:
- name: Checkout repository
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell.
# 📚 https://git.io/JvXDl
# ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
# and modify them (or add more) to build your code if your project
# uses a compiled language
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3

View File

@@ -1,51 +0,0 @@
name: Non-English Comments Check
on:
pull_request:
branches:
- main
workflow_dispatch:
jobs:
non-english-comments-check:
runs-on: ubuntu-latest
env:
# need ignore Dirs
EXCLUDE_DIRS: ".git docs tests scripts assets node_modules build"
# need ignore Files
EXCLUDE_FILES: "*.md *.txt *.html *.css *.min.js *.mdx"
steps:
- uses: actions/checkout@v4
- name: Search for Non-English comments
run: |
set -e
# Define the regex pattern to match Chinese characters
pattern='[\p{Han}]'
# Process the directories to be excluded
exclude_dirs=""
for dir in $EXCLUDE_DIRS; do
exclude_dirs="$exclude_dirs --exclude-dir=$dir"
done
# Process the file types to be excluded
exclude_files=""
for file in $EXCLUDE_FILES; do
exclude_files="$exclude_files --exclude=$file"
done
# Use grep to find all comments containing Non-English characters and save to file
grep -Pnr "$pattern" . $exclude_dirs $exclude_files > non_english_comments.txt || true
- name: Output non-English comments are found
run: |
if [ -s non_english_comments.txt ]; then
echo "Non-English comments found in the following locations:"
cat non_english_comments.txt
exit 1 # terminate the workflow
else
echo "No Non_English comments found."
fi

View File

@@ -1,95 +0,0 @@
name: Build and release services Docker Images
on:
push:
branches:
- release-*
release:
types: [published]
workflow_dispatch:
inputs:
tag:
description: "Tag version to be used for Docker image"
required: true
default: "v3.8.3"
env:
# Docker Hub 凭证来自仓库 Secrets
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3.8.0
- name: Log in to Docker Hub
uses: docker/login-action@v3.3.0
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_PASSWORD }}
- name: Log in to GitHub Container Registry
uses: docker/login-action@v3.3.0
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Aliyun Container Registry
uses: docker/login-action@v3.3.0
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: Extract metadata for Docker (tags, labels)
id: meta
uses: docker/metadata-action@v5
with:
tags: |
type=ref,event=tag
type=schedule
type=ref,event=branch
type=semver,pattern=v{{version}}
type=semver,pattern=release-{{raw}}
type=sha
type=raw,value=${{ github.event.inputs.tag }}
- name: Build and push Docker images
run: |
IMG_DIR="build/images"
for dir in "$IMG_DIR"/*/; do
# Find Dockerfile or *.dockerfile in a case-insensitive manner
dockerfile=$(find "$dir" -maxdepth 1 -type f \( -iname 'dockerfile' -o -iname '*.dockerfile' \) | head -n 1)
if [ -n "$dockerfile" ] && [ -f "$dockerfile" ]; then
IMAGE_NAME=$(basename "$dir")
echo "Building Docker image for $IMAGE_NAME with tags:"
# Initialize tag arguments
tag_args=()
# Read each tag and append --tag arguments
while IFS= read -r tag; do
tag_args+=(--tag "${{ env.DOCKER_USERNAME }}/$IMAGE_NAME:$tag")
tag_args+=(--tag "ghcr.io/${{ github.repository_owner }}/$IMAGE_NAME:$tag")
tag_args+=(--tag "registry.cn-hangzhou.aliyuncs.com/openimsdk/$IMAGE_NAME:$tag")
done <<< "${{ steps.meta.outputs.tags }}"
# Build and push the Docker image with all tags
docker buildx build --platform linux/amd64,linux/arm64 \
--file "$dockerfile" \
"${tag_args[@]}" \
--push \
"."
else
echo "No valid Dockerfile found in $dir"
fi
done

View File

@@ -1,31 +0,0 @@
name: OpenIM Run Gosec
# gosec is a source code security audit tool for the Go language. It performs a static
# analysis of the Go code, looking for potential security problems. The main functions of gosec are:
# 1. Find common security vulnerabilities, such as SQL injection, command injection, and cross-site scripting (XSS).
# 2. Audit codes according to common security standards and find non-standard codes.
# 3. Assist the Go language engineer to write safe and reliable code.
# https://github.com/securego/gosec/
on:
push:
branches: "*"
pull_request:
branches: "*"
paths-ignore:
- '*.md'
- '*.yml'
- '.github'
jobs:
golang-security-action:
runs-on: ubuntu-latest
env:
GO111MODULE: on
steps:
- name: Check out code
uses: actions/checkout@v3
- name: Run Gosec Security Scanner
uses: securego/gosec@master
with:
args: ./...
continue-on-error: true

View File

@@ -1,22 +0,0 @@
name: Good frist issue add comment
on:
issues:
types:
- labeled
jobs:
add-comment:
if: github.event.label.name == 'help wanted' || github.event.label.name == 'good first issue'
runs-on: ubuntu-latest
permissions:
issues: write
steps:
- name: Add comment
uses: peter-evans/create-or-update-comment@v4
with:
issue-number: ${{ github.event.issue.number }}
token: ${{ secrets.BOT_TOKEN }}
body: |
This issue is available for anyone to work on. **Make sure to reference this issue in your pull request.** :sparkles: Thank you for your contribution! :sparkles:
[Join slack 🤖](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) to connect and communicate with our developers.
If you wish to accept this assignment, please leave a comment in the comments section: `/accept`.🎯

View File

@@ -1,19 +0,0 @@
name: 'issue-translator'
on:
issue_comment:
types: [created]
issues:
types: [opened]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: usthe/issues-translate-action@v2.7
with:
BOT_GITHUB_TOKEN: ${{ secrets.BOT_TOKEN }}
IS_MODIFY_TITLE: true
# not require, default false, . Decide whether to modify the issue title
# if true, the robot account @Issues-translate-bot must have modification permissions, invite @Issues-translate-bot to your project or use your custom bot.
CUSTOM_BOT_NOTE: Bot detected the issue body's language is not English, translate it automatically. 👯👭🏻🧑‍🤝‍🧑👫🧑🏿‍🤝‍🧑🏻👩🏾‍🤝‍👨🏿👬🏿
# not require. Customize the translation robot prefix message.

View File

@@ -1,181 +0,0 @@
name: Create Individual PRs from Milestone
permissions:
contents: write
pull-requests: write
issues: write
on:
workflow_dispatch:
inputs:
milestone_name:
description: "Milestone name to collect closed PRs from"
required: true
default: "v1.8.5"
target_branch:
description: "Target branch to merge the consolidated PR"
required: true
default: "pre-release-v1.8.5"
env:
MILESTONE_NAME: ${{ github.event.inputs.milestone_name || 'v1.8.5' }}
TARGET_BRANCH: ${{ github.event.inputs.target_branch || 'pre-release-v1.8.5' }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
BOT_TOKEN: ${{ secrets.BOT_TOKEN }}
LABEL_NAME: cherry-picked
TEMP_DIR: /tmp
jobs:
merge_milestone_prs:
runs-on: ubuntu-latest
steps:
- name: Setup temp directory
run: |
# Create the temporary directory and initialize necessary files
mkdir -p ${{ env.TEMP_DIR }}
touch ${{ env.TEMP_DIR }}/pr_numbers.txt
touch ${{ env.TEMP_DIR }}/commit_hashes.txt
touch ${{ env.TEMP_DIR }}/pr_title.txt
touch ${{ env.TEMP_DIR }}/pr_body.txt
touch ${{ env.TEMP_DIR }}/created_pr_number.txt
- name: Checkout repository
uses: actions/checkout@v4
with:
fetch-depth: 0
token: ${{ secrets.BOT_TOKEN }}
- name: Setup Git User for OpenIM-Robot
run: |
git config --global user.email "OpenIM-Robot@users.noreply.github.com"
git config --global user.name "OpenIM-Robot"
- name: Fetch Milestone ID and Filter PR Numbers
env:
MILESTONE_NAME: ${{ env.MILESTONE_NAME }}
run: |
# Fetch milestone details and extract milestone ID
milestones=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/milestones")
milestone_id=$(echo "$milestones" | grep -B3 "\"title\": \"$MILESTONE_NAME\"" | grep '"number":' | head -n1 | grep -o '[0-9]\+')
if [ -z "$milestone_id" ]; then
echo "Milestone '$MILESTONE_NAME' not found. Exiting."
exit 1
fi
echo "Milestone ID: $milestone_id"
echo "MILESTONE_ID=$milestone_id" >> $GITHUB_ENV
# Fetch issues for the milestone
issues=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues?milestone=$milestone_id&state=closed&per_page=100")
> ${{ env.TEMP_DIR }}/pr_numbers.txt
# Filter PRs that do not have the 'cherry-picked' label
for pr_number in $(echo "$issues" | jq -r '.[] | select(.pull_request != null) | .number'); do
labels=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/issues/$pr_number/labels" | jq -r '.[].name')
if ! echo "$labels" | grep -q "${LABEL_NAME}"; then
echo "PR #$pr_number does not have the 'cherry-picked' label. Adding to the list."
echo "$pr_number" >> ${{ env.TEMP_DIR }}/pr_numbers.txt
fi
done
sort -n ${{ env.TEMP_DIR }}/pr_numbers.txt -o ${{ env.TEMP_DIR }}/pr_numbers.txt
- name: Create Individual PRs
run: |
for pr_number in $(cat ${{ env.TEMP_DIR }}/pr_numbers.txt); do
pr_details=$(curl -s -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
"https://api.github.com/repos/${{ github.repository }}/pulls/$pr_number")
pr_title=$(echo "$pr_details" | jq -r '.title')
pr_body=$(echo "$pr_details" | jq -r '.body')
pr_creator=$(echo "$pr_details" | jq -r '.user.login')
merge_commit=$(echo "$pr_details" | jq -r '.merge_commit_sha')
short_commit_hash=$(echo "$merge_commit" | cut -c 1-7)
if [ "$merge_commit" != "null" ]; then
git fetch origin
echo "Checking out target branch: $TARGET_BRANCH"
git checkout $TARGET_BRANCH
echo "Pulling latest changes from target branch: $TARGET_BRANCH"
git pull origin $TARGET_BRANCH
cherry_pick_branch="cherry-pick-${short_commit_hash}"
git checkout -b $cherry_pick_branch
echo "Cherry-picking commit: $merge_commit"
if ! git cherry-pick "$merge_commit" --strategy=recursive -X theirs; then
echo "Conflict detected for $merge_commit. Resolving with incoming changes."
conflict_files=$(git diff --name-only --diff-filter=U)
echo "Conflicting files:"
echo "$conflict_files"
for file in $conflict_files; do
if [ -f "$file" ]; then
echo "Resolving conflict for $file"
git add "$file"
else
echo "File $file has been deleted. Skipping."
git rm "$file"
fi
done
echo "Conflicts resolved. Continuing cherry-pick."
git cherry-pick --continue || { echo "Cherry-pick failed, but continuing to create PR."; }
else
echo "Cherry-pick successful for commit $merge_commit."
fi
git remote set-url origin "https://${BOT_TOKEN}@github.com/${{ github.repository }}.git"
echo "Pushing branch: $cherry_pick_branch"
if ! git push origin $cherry_pick_branch --force; then
echo "Push failed, but continuing to create PR..."
fi
new_pr_title="$pr_title [Created by @$pr_creator from #$pr_number]"
new_pr_body="$pr_body
> This PR is created from original PR #$pr_number."
response=$(curl -s -X POST -H "Authorization: token $BOT_TOKEN" \
-H "Accept: application/vnd.github+json" \
https://api.github.com/repos/${{ github.repository }}/pulls \
-d "$(jq -n --arg title "$new_pr_title" \
--arg head "$cherry_pick_branch" \
--arg base "$TARGET_BRANCH" \
--arg body "$new_pr_body" \
'{title: $title, head: $head, base: $base, body: $body}')")
new_pr_number=$(echo "$response" | jq -r '.number')
if [[ "$new_pr_number" == "null" || -z "$new_pr_number" ]]; then
echo "Failed to create PR. Response: $response"
git checkout $TARGET_BRANCH
git branch -D $cherry_pick_branch
echo "Deleted branch: $cherry_pick_branch"
git push origin --delete $cherry_pick_branch
else
echo "Created PR #$new_pr_number"
curl -s -X POST -H "Authorization: token $GITHUB_TOKEN" \
-H "Accept: application/vnd.github+json" \
-d '{"labels": ["milestone-merge"]}' \
"https://api.github.com/repos/${{ github.repository }}/issues/$new_pr_number/labels"
fi
echo ""
echo "----------------------------------------"
echo ""
fi
done

View File

@@ -1,102 +0,0 @@
name: OpenIM chat release
on:
push:
# run only against tags
tags:
- '*'
permissions:
contents: write
packages: write
issues: write
jobs:
goreleaser:
runs-on: ubuntu-latest
env:
DOCKER_CLI_EXPERIMENTAL: "enabled"
# Docker Hub 凭证来自仓库 Secrets
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: setup-snapcraft
# FIXME: the mkdirs are a hack for https://github.com/goreleaser/goreleaser/issues/1715
run: |
sudo apt-get update
sudo apt-get -yq --no-install-suggests --no-install-recommends install snapcraft
mkdir -p $HOME/.cache/snapcraft/download
mkdir -p $HOME/.cache/snapcraft/stage-packages
- uses: actions/setup-go@v4
with:
go-version: stable
- name: Set up QEMU
uses: docker/setup-qemu-action@v2
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ env.DOCKER_USERNAME }}
password: ${{ env.DOCKER_PASSWORD }}
- name: Login to GitHub Container Registry
uses: docker/login-action@v2
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to AliYun Docker Hub
uses: docker/login-action@v2
with:
registry: registry.cn-hangzhou.aliyuncs.com
username: ${{ secrets.ALIREGISTRY_USERNAME }}
password: ${{ secrets.ALIREGISTRY_TOKEN }}
- name: set action env cache
uses: actions/cache@v3
with:
path: |
./_output/dist/*.deb
./_output/dist/*.rpm
./_output/dist/*.apk
key: ${{ github.ref }}
- uses: sigstore/cosign-installer@v3.1.1
- uses: anchore/sbom-action/download-syft@v0.14.3
- uses: crazy-max/ghaction-upx@v2
with:
install-only: true
- uses: cachix/install-nix-action@v22
with:
github_access_token: ${{ secrets.GITHUB_TOKEN }}
# - name: snapcraft-login
# if: startsWith(github.ref, 'refs/tags/v')
# run: snapcraft login --with <(echo "${{ secrets.SNAPCRAFT_TOKEN }}")
# More assembly might be required: Docker logins, GPG, etc. It all depends
# on your needs.
- uses: goreleaser/goreleaser-action@v4
with:
# either 'goreleaser' (default) or 'goreleaser-pro':
distribution: goreleaser
version: latest
args: release --clean
env:
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN }}
USERNAME: ${{ github.repository_owner }}
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro'
# distribution:
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
FURY_TOKEN: ${{ secrets.FURY_TOKEN }}

View File

@@ -1,75 +0,0 @@
name: Remove Unused Labels
on:
workflow_dispatch:
jobs:
cleanup:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Fetch All Issues and PRs
id: fetch_issues_prs
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
state: 'all',
per_page: 100
});
const labelsInUse = new Set();
issues.forEach(issue => {
issue.labels.forEach(label => {
labelsInUse.add(label.name);
});
});
return JSON.stringify(Array.from(labelsInUse));
result-encoding: string
- name: Fetch All Labels
id: fetch_labels
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const labels = await github.paginate(github.rest.issues.listLabelsForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100
});
return JSON.stringify(labels.map(label => label.name));
result-encoding: string
- name: Remove Unused Labels
uses: actions/github-script@v7.0.1
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const labelsInUse = new Set(JSON.parse(process.env.LABELS_IN_USE));
const allLabels = JSON.parse(process.env.ALL_LABELS);
const unusedLabels = allLabels.filter(label => !labelsInUse.has(label));
for (const label of unusedLabels) {
await github.rest.issues.deleteLabel({
owner: context.repo.owner,
repo: context.repo.repo,
name: label
});
console.log(`Deleted label: ${label}`);
}
env:
LABELS_IN_USE: ${{ steps.fetch_issues_prs.outputs.result }}
ALL_LABELS: ${{ steps.fetch_labels.outputs.result }}

View File

@@ -1,78 +0,0 @@
name: Reopen and Update Stale Issues
on:
workflow_dispatch:
jobs:
reopen_stale_issues:
runs-on: ubuntu-latest
permissions:
issues: write
contents: read
steps:
- name: Checkout Repository
uses: actions/checkout@v4
- name: Fetch Closed Issues with lifecycle/stale Label
id: fetch_issues
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issues = await github.paginate(github.rest.issues.listForRepo, {
owner: context.repo.owner,
repo: context.repo.repo,
state: 'closed',
labels: 'lifecycle/stale',
per_page: 100
});
const issueNumbers = issues
.filter(issue => !issue.pull_request)
.map(issue => issue.number);
console.log(`Fetched issues: ${issueNumbers}`);
return issueNumbers;
- name: Set issue numbers
id: set_issue_numbers
run: |
echo "ISSUE_NUMBERS=${{ steps.fetch_issues.outputs.result }}" >> $GITHUB_ENV
echo "Issue numbers: ${{ steps.fetch_issues.outputs.result }}"
- name: Reopen Issues
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumbers = JSON.parse(process.env.ISSUE_NUMBERS);
console.log(`Reopening issues: ${issueNumbers}`);
for (const issue_number of issueNumbers) {
// Reopen the issue
await github.rest.issues.update({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
state: 'open'
});
console.log(`Reopened issue #${issue_number}`);
}
- name: Remove lifecycle/stale Label
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const issueNumbers = JSON.parse(process.env.ISSUE_NUMBERS);
console.log(`Removing 'lifecycle/stale' label from issues: ${issueNumbers}`);
for (const issue_number of issueNumbers) {
// Remove the lifecycle/stale label
await github.rest.issues.removeLabel({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: issue_number,
name: 'lifecycle/stale'
});
console.log(`Removed label 'lifecycle/stale' from issue #${issue_number}`);
}

View File

@@ -1,119 +0,0 @@
name: Update Version File on Release
on:
release:
types: [created]
jobs:
update-version:
runs-on: ubuntu-latest
env:
TAG_VERSION: ${{ github.event.release.tag_name }}
steps:
# Step 1: Checkout the original repository's code
- name: Checkout code
uses: actions/checkout@v4
with:
fetch-depth: 0
# submodules: "recursive"
- name: Safe submodule initialization
run: |
echo "Checking for submodules..."
if [ -f .gitmodules ]; then
if [ -s .gitmodules ]; then
echo "Initializing submodules..."
if git submodule sync --recursive 2>/dev/null; then
git submodule update --init --force --recursive || {
echo "Warning: Some submodules failed to initialize, continuing anyway..."
}
else
echo "Warning: Submodule sync failed, continuing without submodules..."
fi
else
echo ".gitmodules exists but is empty, skipping submodule initialization"
fi
else
echo "No .gitmodules file found, no submodules to initialize"
fi
# Step 2: Set up Git with official account
- name: Set up Git
run: |
git config --global user.name "github-actions[bot]"
git config --global user.email "github-actions[bot]@users.noreply.github.com"
# Step 3: Check and delete existing tag
- name: Check and delete existing tag
run: |
if git rev-parse ${{ env.TAG_VERSION }} >/dev/null 2>&1; then
git tag -d ${{ env.TAG_VERSION }}
git push --delete origin ${{ env.TAG_VERSION }}
fi
# Step 4: Update version file
- name: Update version file
run: |
mkdir -p version
echo -n "${{ env.TAG_VERSION }}" > version/version
# Step 5: Commit and push changes
- name: Commit and push changes
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git add version/version
git commit -m "Update version to ${{ env.TAG_VERSION }}"
# Step 6: Update tag
- name: Update tag
run: |
git tag -fa ${{ env.TAG_VERSION }} -m "Update version to ${{ env.TAG_VERSION }}"
git push origin ${{ env.TAG_VERSION }} --force
# Step 7: Find and Publish Draft Release
- name: Find and Publish Draft Release
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const { owner, repo } = context.repo;
const tagName = process.env.TAG_VERSION;
try {
let release;
try {
const response = await github.rest.repos.getReleaseByTag({
owner,
repo,
tag: tagName
});
release = response.data;
} catch (tagError) {
core.info(`Release not found by tag, searching all releases...`);
const releases = await github.rest.repos.listReleases({
owner,
repo,
per_page: 100
});
release = releases.data.find(r => r.draft && r.tag_name === tagName);
if (!release) {
throw new Error(`No release found with tag ${tagName}`);
}
}
await github.rest.repos.updateRelease({
owner,
repo,
release_id: release.id,
draft: false,
prerelease: release.prerelease
});
const status = release.draft ? "was draft" : "was already published";
core.info(`Release ${tagName} ensured to be published (${status}).`);
} catch (error) {
core.warning(`Could not find or update release for tag ${tagName}: ${error.message}`);
}

376
.gitignore vendored
View File

@@ -1,376 +0,0 @@
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
.idea/
bin/
components/
logs
# Created by https://www.toptal.com/developers/gitignore/api/vim,jetbrains,vscode,git,go,tags,backup,test,emacs
# Edit at https://www.toptal.com/developers/gitignore?templates=vim,jetbrains,vscode,git,go,tags,backup,test,emacs
### Backup ###
*.bak
*.gho
*.ori
*.orig
*.tmp
### Git ###
# Created by git for backups. To disable backups in Git:
# $ git config --global mergetool.keepBackup false
# Created by git when using merge tools for conflicts
*.BACKUP.*
*.BASE.*
*.LOCAL.*
*.REMOTE.*
*_BACKUP_*.txt
*_BASE_*.txt
*_LOCAL_*.txt
*_REMOTE_*.txt
### Go ###
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
_output/
bin/
# Dependency directories (remove the comment below to include it)
# vendor/
### Go Patch ###
/vendor/
/Godeps/
### JetBrains ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
.idea
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/artifacts
# .idea/compiler.xml
# .idea/jarRepositories.xml
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### JetBrains Patch ###
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
# *.iml
# modules.xml
# .idea/misc.xml
# *.ipr
# Sonarlint plugin
# https://plugins.jetbrains.com/plugin/7973-sonarlint
.idea/**/sonarlint/
# SonarQube Plugin
# https://plugins.jetbrains.com/plugin/7238-sonarqube-community-plugin
.idea/**/sonarIssues.xml
# Markdown Navigator plugin
# https://plugins.jetbrains.com/plugin/7896-markdown-navigator-enhanced
.idea/**/markdown-navigator.xml
.idea/**/markdown-navigator-enh.xml
.idea/**/markdown-navigator/
# Cache file creation bug
# See https://youtrack.jetbrains.com/issue/JBR-2257
.idea/$CACHE_FILE$
# CodeStream plugin
# https://plugins.jetbrains.com/plugin/12206-codestream
.idea/codestream.xml
### Tags ###
# Ignore tags created by etags, ctags, gtags (GNU global) and cscope
TAGS
.TAGS
!TAGS/
tags
.tags
!tags/
gtags.files
GTAGS
GRTAGS
GPATH
GSYMS
cscope.files
cscope.out
cscope.in.out
cscope.po.out
### Test ###
### Ignore all files that could be used to test your code and
### you wouldn't want to push
# Reference https://en.wikipedia.org/wiki/Metasyntactic_variable
# Most common
*foo
*bar
*fubar
*foobar
*baz
# Less common
*qux
*quux
*bongo
*bazola
*ztesch
# UK, Australia
*wibble
*wobble
*wubble
*flob
*blep
*blah
*boop
*beep
# Japanese
*hoge
*piyo
*fuga
*hogera
*hogehoge
# Portugal, Spain
*fulano
*sicrano
*beltrano
*mengano
*perengano
*zutano
# France, Italy, the Netherlands
*toto
*titi
*tata
*tutu
*pipppo
*pluto
*paperino
*aap
*noot
*mies
# Other names that would make sense
*tests
*testsdir
*testsfile
*testsfiles
*testdir
*testfile
*testfiles
*testing
*testingdir
*testingfile
*testingfiles
*temp
*tempdir
*tempfile
*tempfiles
*tmp
*tmpdir
*tmpfile
*tmpfiles
*lol
### Vim ###
# Swap
[._]*.s[a-v][a-z]
!*.svg # comment out if you don't need vector files
[._]*.sw[a-p]
[._]s[a-rt-v][a-z]
[._]ss[a-gi-z]
[._]sw[a-p]
# Session
Session.vim
Sessionx.vim
# Temporary
.netrwhist
*~
# Auto-generated tag files
# Persistent undo
[._]*.un~
### Emacs ###
# -*- mode: gitignore; -*-
*~
\#*\#
/.emacs.desktop
/.emacs.desktop.lock
*.elc
auto-save-list
tramp
.\#*
# Org-mode
.org-id-locations
*_archive
ltximg/**
# flymake-mode
*_flymake.*
# eshell files
/eshell/history
/eshell/lastdir
# elpa packages
/elpa/
# reftex files
*.rel
# AUCTeX auto folder
/auto/
# cask packages
.cask/
dist/
# Flycheck
flycheck_*.el
# server auth directory
/server/
# projectiles files
.projectile
# directory configuration
.dir-locals.el
# network security
/network-security.data
### vscode ###
.vscode
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
*.code-workspace
# End of https://www.toptal.com/developers/gitignore/api/vim,jetbrains,vscode,git,go,tags,backup,test
# Start by kubecub
# log
*.log
# Output of backend and frontend
/_output
/_debug
# Misc
.DS_Store
# *.env
# .env
dist
# files used by the developer
.idea.md
.todo.md
.note.md
# config files, may contain sensitive informatio
config/config.yaml

View File

@@ -1,934 +0,0 @@
# Copyright © 2023 OpenIMSDK open source community. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This file contains all available configuration options
# with their default values.
# options for analysis running
run:
# default concurrency is a available CPU number
concurrency: 4
# timeout for analysis, e.g. 30s, 5m, default is 1m
timeout: 5m
# exit code when at least one issue was found, default is 1
issues-exit-code: 1
# include test files or not, default is true
tests: true
# list of build tags, all linters use it. Default is empty list.
build-tags:
- mytag
# which dirs to skip: issues from them won't be reported;
# can use regexp here: generated.*, regexp is applied on full path;
# default value is empty list, but default dirs are skipped independently
# from this option's value (see skip-dirs-use-default).
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-dirs:
- util
- .*~
- api/swagger/docs
- server/docs
# default is true. Enables skipping of directories:
# vendor$, third_party$, testdata$, examples$, Godeps$, builtin$
skip-dirs-use-default: true
# which files to skip: they will be analyzed, but issues from them
# won't be reported. Default value is empty list, but there is
# no need to include all autogenerated files, we confidently recognize
# autogenerated files. If it's not please let us know.
# "/" will be replaced by current OS file path separator to properly work
# on Windows.
skip-files:
- ".*\\.my\\.go$"
- _test.go
# by default isn't set. If set we pass it to "go list -mod={option}". From "go help modules":
# If invoked with -mod=readonly, the go command is disallowed from the implicit
# automatic updating of go.mod described above. Instead, it fails when any changes
# to go.mod are needed. This setting is most useful to check that go.mod does
# not need updates, such as in a continuous integration and testing system.
# If invoked with -mod=vendor, the go command assumes that the vendor
# directory holds the correct copies of dependencies and ignores
# the dependency descriptions in go.mod.
#modules-download-mode: release|readonly|vendor
# Allow multiple parallel golangci-lint instances running.
# If false (default) - golangci-lint acquires file lock on start.
allow-parallel-runners: true
# output configuration options
output:
# colored-line-number|line-number|json|tab|checkstyle|code-climate, default is "colored-line-number"
format: colored-line-number
# print lines of code with issue, default is true
print-issued-lines: true
# print linter name in the end of issue text, default is true
print-linter-name: true
# make issues output unique by line, default is true
uniq-by-line: true
# add a prefix to the output file references; default is no prefix
path-prefix: ""
# sorts results by: filepath, line and column
sort-results: true
# all available settings of specific linters
linters-settings:
bidichk:
# The following configurations check for all mentioned invisible unicode
# runes. It can be omitted because all runes are enabled by default.
left-to-right-embedding: true
right-to-left-embedding: true
pop-directional-formatting: true
left-to-right-override: true
right-to-left-override: true
left-to-right-isolate: true
right-to-left-isolate: true
first-strong-isolate: true
pop-directional-isolate: true
dogsled:
# checks assignments with too many blank identifiers; default is 2
max-blank-identifiers: 2
dupl:
# tokens count to trigger issue, 150 by default
threshold: 200
errcheck:
# report about not checking of errors in type assertions: `a := b.(MyStruct)`;
# default is false: such cases aren't reported by default.
check-type-assertions: false
# report about assignment of errors to blank identifier: `num, _ := strconv.Atoi(numStr)`;
# default is false: such cases aren't reported by default.
check-blank: false
# [deprecated] comma-separated list of pairs of the form pkg:regex
# the regex is used to ignore names within pkg. (default "fmt:.*").
# see https://github.com/kisielk/errcheck#the-deprecated-method for details
#ignore: GenMarkdownTree,os:.*,BindPFlags,WriteTo,Help
#ignore: (os\.)?std(out|err)\..*|.*Close|.*Flush|os\.Remove(All)?|.*print(f|ln)?|os\.(Un)?Setenv
# path to a file containing a list of functions to exclude from checking
# see https://github.com/kisielk/errcheck#excluding-functions for details
#exclude: errcheck.txt
errorlint:
# Check whether fmt.Errorf uses the %w verb for formatting errors. See the readme for caveats
errorf: true
# Check for plain type assertions and type switches
asserts: true
# Check for plain error comparisons
comparison: true
exhaustive:
# check switch statements in generated files also
check-generated: false
# indicates that switch statements are to be considered exhaustive if a
# 'default' case is present, even if all enum members aren't listed in the
# switch
default-signifies-exhaustive: false
# enum members matching the supplied regex do not have to be listed in
# switch statements to satisfy exhaustiveness
ignore-enum-members: ""
# consider enums only in package scopes, not in inner scopes
package-scope-only: false
exhaustivestruct:
struct-patterns:
- '*.Test'
- '*.Test2'
- '*.Embedded'
- '*.External'
# forbidigo:
# # Forbid the following identifiers (identifiers are written using regexp):
# forbid:
# - ^print.*$
# - 'fmt\.Print.*'
# - fmt.Println.* # too much log noise
# - ginkgo\\.F.* # these are used just for local development
# # Exclude godoc examples from forbidigo checks. Default is true.
# exclude_godoc_examples: false
funlen:
lines: 150
statements: 50
gci:
# put imports beginning with prefix after 3rd-party packages;
# only support one prefix
# if not set, use goimports.local-prefixes
prefix: github.com/openimsdk/OpenKF
gocognit:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 30
goconst:
# minimal length of string constant, 3 by default
min-len: 3
# minimal occurrences count to trigger, 3 by default
min-occurrences: 3
# ignore test files, false by default
ignore-tests: false
# look for existing constants matching the values, true by default
match-constant: true
# search also for duplicated numbers, false by default
numbers: false
# minimum value, only works with goconst.numbers, 3 by default
min: 3
# maximum value, only works with goconst.numbers, 3 by default
max: 3
# ignore when constant is not used as function argument, true by default
ignore-calls: true
gocritic:
# Which checks should be enabled; can't be combined with 'disabled-checks';
# See https://go-critic.github.io/overview#checks-overview
# To check which checks are enabled run `GL_DEBUG=gocritic golangci-lint run`
# By default list of stable checks is used.
enabled-checks:
#- rangeValCopy
- nestingreduce
- truncatecmp
- unnamedresult
- ruleguard
# Which checks should be disabled; can't be combined with 'enabled-checks'; default is empty
disabled-checks:
- regexpMust
- ifElseChain
#- exitAfterDefer
# Enable multiple checks by tags, run `GL_DEBUG=gocritic golangci-lint run` to see all tags and checks.
# Empty list by default. See https://github.com/go-critic/go-critic#usage -> section "Tags".
enabled-tags:
- performance
disabled-tags:
- experimental
# Settings passed to gocritic.
# The settings key is the name of a supported gocritic checker.
# The list of supported checkers can be find in https://go-critic.github.io/overview.
settings:
captLocal: # must be valid enabled check name
# whether to restrict checker to params only (default true)
paramsOnly: true
elseif:
# whether to skip balanced if-else pairs (default true)
skipBalanced: true
hugeParam:
# size in bytes that makes the warning trigger (default 80)
sizeThreshold: 80
nestingReduce:
# min number of statements inside a branch to trigger a warning (default 5)
bodyWidth: 5
rangeExprCopy:
# size in bytes that makes the warning trigger (default 512)
sizeThreshold: 512
# whether to check test functions (default true)
skipTestFuncs: true
rangeValCopy:
# size in bytes that makes the warning trigger (default 128)
sizeThreshold: 32
# whether to check test functions (default true)
skipTestFuncs: true
ruleguard:
# path to a gorules file for the ruleguard checker
rules: ''
truncateCmp:
# whether to skip int/uint/uintptr types (default true)
skipArchDependent: true
underef:
# whether to skip (*x).method() calls where x is a pointer receiver (default true)
skipRecvDeref: true
unnamedResult:
# whether to check exported functions
checkExported: true
gocyclo:
# minimal code complexity to report, 30 by default (but we recommend 10-20)
min-complexity: 30
cyclop:
# the maximal code complexity to report
max-complexity: 50
# the maximal average package complexity. If it's higher than 0.0 (float) the check is enabled (default 0.0)
package-average: 0.0
# should ignore tests (default false)
skip-tests: false
godot:
# comments to be checked: `declarations`, `toplevel`, or `all`
scope: declarations
# list of regexps for excluding particular comment lines from check
exclude:
# example: exclude comments which contain numbers
# - '[0-9]+'
# check that each sentence starts with a capital letter
capital: false
godox:
# report any comments starting with keywords, this is useful for TODO or FIXME comments that
# might be left in the code accidentally and should be resolved before merging
keywords: # default keywords are TODO, BUG, and FIXME, these can be overwritten by this setting
#- TODO
- BUG
- FIXME
#- NOTE
- OPTIMIZE # marks code that should be optimized before merging
- HACK # marks hack-arounds that should be removed before merging
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
gofumpt:
# Select the Go version to target. The default is `1.18`.
lang-version: "1.20"
# Choose whether or not to use the extra rules that are disabled
# by default
extra-rules: false
goheader:
values:
const:
# define here const type values in format k:v, for example:
# COMPANY: MY COMPANY
regexp:
# define here regexp type values, for example
# AUTHOR: .*@mycompany\.com
template: # |-
# put here copyright header template for source code files, for example:
# Note: {{ YEAR }} is a builtin value that returns the year relative to the current machine time.
#
# {{ AUTHOR }} {{ COMPANY }} {{ YEAR }}
# SPDX-License-Identifier: Apache-2.0
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at:
# http://www.apache.org/licenses/LICENSE-2.0
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
template-path:
# also as alternative of directive 'template' you may put the path to file with the template source
goimports:
# put imports beginning with prefix after 3rd-party packages;
# it's a comma-separated list of prefixes
local-prefixes: github.com/openimsdk/OpenKF
golint:
# minimal confidence for issues, default is 0.8
min-confidence: 0.9
gomnd:
settings:
mnd:
# the list of enabled checks, see https://github.com/tommy-muehle/go-mnd/#checks for description.
checks: argument,case,condition,operation,return,assign
# ignored-numbers: 1000
# ignored-files: magic_.*.go
# ignored-functions: math.*
gomoddirectives:
# Allow local `replace` directives. Default is false.
replace-local: true
# List of allowed `replace` directives. Default is empty.
replace-allow-list:
- google.golang.org/grpc
# Allow to not explain why the version has been retracted in the `retract` directives. Default is false.
retract-allow-no-explanation: false
# Forbid the use of the `exclude` directives. Default is false.
exclude-forbidden: false
gomodguard:
allowed:
modules:
- gorm.io/gen # List of allowed modules
- gorm.io/gorm
- gorm.io/driver/mysql
- k8s.io/klog
# - gopkg.in/yaml.v2
domains: # List of allowed module domains
- google.golang.org
- gopkg.in
- golang.org
- github.com
- go.uber.org
- go.etcd.io
blocked:
versions:
- github.com/MakeNowJust/heredoc:
version: "> 2.0.9"
reason: "use the latest version"
local_replace_directives: false # Set to true to raise lint issues for packages that are loaded from a local path via replace directive
gosec:
# To select a subset of rules to run.
# Available rules: https://github.com/securego/gosec#available-rules
includes:
- G401
- G306
- G101
# To specify a set of rules to explicitly exclude.
# Available rules: https://github.com/securego/gosec#available-rules
excludes:
- G204
# Exclude generated files
exclude-generated: true
# Filter out the issues with a lower severity than the given value. Valid options are: low, medium, high.
severity: "low"
# Filter out the issues with a lower confidence than the given value. Valid options are: low, medium, high.
confidence: "low"
# To specify the configuration of rules.
# The configuration of rules is not fully documented by gosec:
# https://github.com/securego/gosec#configuration
# https://github.com/securego/gosec/blob/569328eade2ccbad4ce2d0f21ee158ab5356a5cf/rules/rulelist.go#L60-L102
config:
G306: "0600"
G101:
pattern: "(?i)example"
ignore_entropy: false
entropy_threshold: "80.0"
per_char_threshold: "3.0"
truncate: "32"
gosimple:
# Select the Go version to target. The default is '1.13'.
go: "1.20"
# https://staticcheck.io/docs/options#checks
checks: [ "all" ]
govet:
# report about shadowed variables
check-shadowing: true
# settings per analyzer
settings:
printf: # analyzer name, run `go tool vet help` to see all analyzers
funcs: # run `go tool vet help printf` to see available settings for `printf` analyzer
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Infof
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Warnf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Errorf
- (github.com/golangci/golangci-lint/pkg/logutils.Log).Fatalf
# enable or disable analyzers by name
enable:
- atomicalign
enable-all: false
disable:
- shadow
disable-all: false
# depguard:
# list-type: blacklist
# include-go-root: false
# packages:
# - github.com/Sirupsen/logrus
# packages-with-error-message:
# # specify an error message to output when a blacklisted package is used
# - github.com/Sirupsen/logrus: "logging is allowed only by logutils.Log"
ifshort:
# Maximum length of variable declaration measured in number of lines, after which linter won't suggest using short syntax.
# Has higher priority than max-decl-chars.
max-decl-lines: 1
# Maximum length of variable declaration measured in number of characters, after which linter won't suggest using short syntax.
max-decl-chars: 30
importas:
# if set to `true`, force to use alias.
no-unaliased: true
# List of aliases
alias:
# using `servingv1` alias for `knative.dev/serving/pkg/apis/serving/v1` package
- pkg: knative.dev/serving/pkg/apis/serving/v1
alias: servingv1
# using `autoscalingv1alpha1` alias for `knative.dev/serving/pkg/apis/autoscaling/v1alpha1` package
- pkg: knative.dev/serving/pkg/apis/autoscaling/v1alpha1
alias: autoscalingv1alpha1
# You can specify the package path by regular expression,
# and alias by regular expression expansion syntax like below.
# see https://github.com/julz/importas#use-regular-expression for details
- pkg: knative.dev/serving/pkg/apis/(\w+)/(v[\w\d]+)
alias: $1$2
# using `jwt` alias for `github.com/appleboy/gin-jwt/v2` package
jwt: github.com/appleboy/gin-jwt/v2
ireturn:
# ireturn allows using `allow` and `reject` settings at the same time.
# Both settings are lists of the keywords and regular expressions matched to interface or package names.
# keywords:
# - `empty` for `interface{}`
# - `error` for errors
# - `stdlib` for standard library
# - `anon` for anonymous interfaces
# By default, it allows using errors, empty interfaces, anonymous interfaces,
# and interfaces provided by the standard library.
allow:
- anon
- error
- empty
- stdlib
# You can specify idiomatic endings for interface
- (or|er)$
# Reject patterns
reject:
- github.com\/user\/package\/v4\.Type
lll:
# max line length, lines longer will be reported. Default is 120.
# '\t' is counted as 1 character by default, and can be changed with the tab-width option
line-length: 240
# tab width in spaces. Default to 1.
tab-width: 4
maligned:
# print struct with more effective memory layout or not, false by default
suggest-new: true
misspell:
# Correct spellings using locale preferences for US or UK.
# Default is to use a neutral variety of English.
# Setting locale to US will correct the British spelling of 'colour' to 'color'.
locale: US
ignore-words:
- someword
nakedret:
# make an issue if func has more lines of code than this setting and it has naked returns; default is 30
max-func-lines: 30
nestif:
# minimal complexity of if statements to report, 5 by default
min-complexity: 4
nilnil:
# By default, nilnil checks all returned types below.
checked-types:
- ptr
- func
- iface
- map
- chan
nlreturn:
# size of the block (including return statement that is still "OK")
# so no return split required.
block-size: 1
nolintlint:
# Disable to ensure that all nolint directives actually have an effect. Default is true.
allow-unused: false
# Disable to ensure that nolint directives don't have a leading space. Default is true.
allow-leading-space: true
# Exclude following linters from requiring an explanation. Default is [].
allow-no-explanation: [ ]
# Enable to require an explanation of nonzero length after each nolint directive. Default is false.
require-explanation: false
# Enable to require nolint directives to mention the specific linter being suppressed. Default is false.
require-specific: true
prealloc:
# XXX: we don't recommend using this linter before doing performance profiling.
# For most programs usage of prealloc will be a premature optimization.
# Report preallocation suggestions only on simple loops that have no returns/breaks/continues/gotos in them.
# True by default.
simple: true
range-loops: true # Report preallocation suggestions on range loops, true by default
for-loops: false # Report preallocation suggestions on for loops, false by default
promlinter:
# Promlinter cannot infer all metrics name in static analysis.
# Enable strict mode will also include the errors caused by failing to parse the args.
strict: false
# Please refer to https://github.com/yeya24/promlinter#usage for detailed usage.
disabled-linters:
# - "Help"
# - "MetricUnits"
# - "Counter"
# - "HistogramSummaryReserved"
# - "MetricTypeInName"
# - "ReservedChars"
# - "CamelCase"
# - "lintUnitAbbreviations"
predeclared:
# comma-separated list of predeclared identifiers to not report on
ignore: ""
# include method names and field names (i.e., qualified names) in checks
q: false
rowserrcheck:
packages:
- github.com/jmoiron/sqlx
revive:
# see https://github.com/mgechev/revive#available-rules for details.
ignore-generated-header: true
severity: warning
rules:
- name: indent-error-flow
severity: warning
staticcheck:
# Select the Go version to target. The default is '1.13'.
go: "1.16"
# https://staticcheck.io/docs/options#checks
checks: [ "all" ]
stylecheck:
# Select the Go version to target. The default is '1.13'.
go: "1.16"
# https://staticcheck.io/docs/options#checks
checks: [ "all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022" ]
# https://staticcheck.io/docs/options#dot_import_whitelist
dot-import-whitelist:
- fmt
# https://staticcheck.io/docs/options#initialisms
initialisms: [ "ACL", "API", "ASCII", "CPU", "CSS", "DNS", "EOF", "GUID", "HTML", "HTTP", "HTTPS", "ID", "IP", "JSON", "QPS", "RAM", "RPC", "SLA", "SMTP", "SQL", "SSH", "TCP", "TLS", "TTL", "UDP", "UI", "GID", "UID", "UUID", "URI", "URL", "UTF8", "VM", "XML", "XMPP", "XSRF", "XSS" ]
# https://staticcheck.io/docs/options#http_status_code_whitelist
http-status-code-whitelist: [ "200", "400", "404", "500" ]
tagliatelle:
# check the struck tag name case
case:
# use the struct field name to check the name of the struct tag
use-field-name: true
rules:
# any struct tag type can be used.
# support string case: `camel`, `pascal`, `kebab`, `snake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`
json: camel
yaml: camel
xml: camel
bson: camel
avro: snake
mapstructure: kebab
testpackage:
# regexp pattern to skip files
skip-regexp: (id|export|internal)_test\.go
thelper:
# The following configurations enable all checks. It can be omitted because all checks are enabled by default.
# You can enable only required checks deleting unnecessary checks.
test:
first: true
name: true
begin: true
benchmark:
first: true
name: true
begin: true
tb:
first: true
name: true
begin: true
tenv:
# The option `all` will run against whole test files (`_test.go`) regardless of method/function signatures.
# By default, only methods that take `*testing.T`, `*testing.B`, and `testing.TB` as arguments are checked.
all: false
unparam:
# Inspect exported functions, default is false. Set to true if no external program/library imports your code.
# XXX: if you enable this setting, unparam will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find external interfaces. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
unused:
# treat code as a program (not a library) and report unused exported identifiers; default is false.
# XXX: if you enable this setting, unused will report a lot of false-positives in text editors:
# if it's called for subdir of a project it can't find funcs usages. All text editor integrations
# with golangci-lint call it on a directory with the changed file.
check-exported: false
whitespace:
multi-if: false # Enforces newlines (or comments) after every multi-line if statement
multi-func: false # Enforces newlines (or comments) after every multi-line function signature
wrapcheck:
# An array of strings that specify substrings of signatures to ignore.
# If this set, it will override the default set of ignored signatures.
# See https://github.com/tomarrell/wrapcheck#configuration for more information.
ignoreSigs:
- .Errorf(
- errors.New(
- errors.Unwrap(
- .Wrap(
- .Wrapf(
- .WithMessage(
- .WithMessagef(
- .WithStack(
ignorePackageGlobs:
- encoding/*
- github.com/pkg/*
wsl:
# If true append is only allowed to be cuddled if appending value is
# matching variables, fields or types on line above. Default is true.
strict-append: true
# Allow calls and assignments to be cuddled as long as the lines have any
# matching variables, fields or types. Default is true.
allow-assign-and-call: true
# Allow assignments to be cuddled with anything. Default is false.
allow-assign-and-anything: false
# Allow multiline assignments to be cuddled. Default is true.
allow-multiline-assign: true
# Allow declarations (var) to be cuddled.
allow-cuddle-declarations: false
# Allow trailing comments in ending of blocks
allow-trailing-comment: false
# Force newlines in end of case at this limit (0 = never).
force-case-trailing-whitespace: 0
# Force cuddling of err checks with err var assignment
force-err-cuddling: false
# Allow leading comments to be separated with empty liens
allow-separated-leading-comment: false
makezero:
# Allow only slices initialized with a length of zero. Default is false.
always: false
# The custom section can be used to define linter plugins to be loaded at runtime. See README doc
# for more info.
#custom:
# Each custom linter should have a unique name.
#example:
# The path to the plugin *.so. Can be absolute or local. Required for each custom linter
#path: /path/to/example.so
# The description of the linter. Optional, just for documentation purposes.
#description: This is an example usage of a plugin linter.
# Intended to point to the repo location of the linter. Optional, just for documentation purposes.
#original-url: github.com/golangci/example-linter
linters:
# please, do not use `enable-all`: it's deprecated and will be removed soon.
# inverted configuration with `enable-all` and `disable` is not scalable during updates of golangci-lint
# enable-all: true
disable-all: true
enable:
- typecheck
- asciicheck
- bodyclose
- cyclop
- deadcode
# - depguard
- dogsled
- dupl
- durationcheck
- errcheck
- errorlint
- exhaustive
- exportloopref
# - forbidigo
- funlen
# - gci
# - gochecknoinits
- gocognit
- goconst
- gocyclo
- godot
- godox
- gofmt
- gofumpt
- goheader
- goimports
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- gosimple
- govet
- ifshort
- importas
- ineffassign
- lll
- makezero
- misspell
- nakedret
- nestif
- nilerr
- nlreturn
- noctx
- nolintlint
- paralleltest
- prealloc
- predeclared
- promlinter
- revive
- rowserrcheck
- sqlclosecheck
- staticcheck
- structcheck
- stylecheck
- thelper
- tparallel
- unconvert
- unparam
- unused
- varcheck
- wastedassign
- whitespace
- bidichk
- wastedassign
- golint
- execinquery
- nosprintfhostport
- grouper
- decorder
- errchkjson
- maintidx
#- containedctx
#- tagliatelle
#- nonamedreturns
#- nilnil
#- tenv
#- varnamelen
#- contextcheck
#- errname
#- ForceTypeAssert
#- nilassign
fast: false
issues:
# List of regexps of issue texts to exclude, empty list by default.
# But independently from this option we use default exclude patterns,
# it can be disabled by `exclude-use-default: false`. To list all
# excluded by default patterns execute `golangci-lint run --help`
exclude:
- tools/.*
- test/.*
- third_party/.*
# Excluding configuration per-path, per-linter, per-text and per-source
exclude-rules:
- linters:
- golint
path: (internal/api/.*)\.go # exclude golint for internal/api/... files
- linters:
- revive
path: (log/.*)\.go
- linters:
- wrapcheck
path: (cmd/.*|pkg/.*)\.go
- linters:
- typecheck
#path: (pkg/storage/.*)\.go
path: (internal/.*|pkg/.*)\.go
- path: (cmd/.*|test/.*|tools/.*|internal/pump/pumps/.*)\.go
linters:
- forbidigo
- path: (cmd/[a-z]*/.*|store/.*)\.go
linters:
- dupl
- linters:
- gocritic
text: (hugeParam:|rangeValCopy:)
- path: (cmd/[a-z]*/.*)\.go
linters:
- lll
- path: (validator/.*|code/.*|validator/.*|watcher/watcher/.*)
linters:
- gochecknoinits
- path: (internal/.*/options|internal/pump|pkg/log/options.go|internal/authzserver|tools/)
linters:
- tagliatelle
- path: (pkg/app/.*)\.go
linters:
- deadcode
- unused
- varcheck
- forbidigo
# Exclude some staticcheck messages
- linters:
- staticcheck
text: "SA9003:"
# Exclude lll issues for long lines with go:generate
- linters:
- lll
source: "^//go:generate "
# Independently from option `exclude` we use default exclude patterns,
# it can be disabled by this option. To list all
# excluded by default patterns execute `golangci-lint run --help`.
# Default value for this option is true.
exclude-use-default: true
# The default value is false. If set to true exclude and exclude-rules
# regular expressions become case sensitive.
exclude-case-sensitive: false
# The list of ids of default excludes to include or disable. By default it's empty.
include:
- EXC0002 # disable excluding of issues about comments from golint
# Maximum issues count per one linter. Set to 0 to disable. Default is 50.
max-issues-per-linter: 0
# Maximum count of issues with the same text. Set to 0 to disable. Default is 3.
max-same-issues: 0
# Show only new issues: if there are unstaged changes or untracked files,
# only those changes are analyzed, else only changes in HEAD~ are analyzed.
# It's a super-useful option for integration of golangci-lint into existing
# large codebase. It's not practical to fix all existing issues at the moment
# of integration: much better don't allow issues in new code.
# Default is false.
new: false
# Show only new issues created after git revision `REV`
# new-from-rev: REV
# Show only new issues created in git patch with set file path.
#new-from-patch: path/to/patch/file
# Fix found issues (if it's supported by the linter)
fix: true
severity:
# Default value is empty string.
# Set the default severity for issues. If severity rules are defined and the issues
# do not match or no severity is provided to the rule this will be the default
# severity applied. Severities should match the supported severity names of the
# selected out format.
# - Code climate: https://docs.codeclimate.com/docs/issues#issue-severity
# - Checkstyle: https://checkstyle.sourceforge.io/property_types.html#severity
# - Github: https://help.github.com/en/actions/reference/workflow-commands-for-github-actions#setting-an-error-message
default-severity: error
# The default value is false.
# If set to true severity-rules regular expressions become case sensitive.
case-sensitive: false
# Default value is empty list.
# When a list of severity rules are provided, severity information will be added to lint
# issues. Severity rules have the same filtering capability as exclude rules except you
# are allowed to specify one matcher per severity rule.
# Only affects out formats that support setting severity information.
rules:
- linters:
- dupl
severity: info

View File

@@ -1,493 +0,0 @@
# Copyright © 2023 OpenIM open source community. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
# This is an example .goreleaser.yml file with some sensible defaults.
# Make sure to check the documentation at https://goreleaser.com
before:
hooks:
- make clean
# You may remove this if you don't use go modules.
- go mod tidy
# you may remove this if you don't need go generate
- go generate ./...
git:
# What should be used to sort tags when gathering the current and previous
# tags if there are more than one tag in the same commit.
#
# Default: '-version:refname'
tag_sort: -version:creatordate
# What should be used to specify prerelease suffix while sorting tags when gathering
# the current and previous tags if there are more than one tag in the same commit.
#
# Since: v1.17
prerelease_suffix: "-"
# Tags to be ignored by GoReleaser.
# This means that GoReleaser will not pick up tags that match any of the
# provided values as either previous or current tags.
#
# Templates: allowed.
# Since: v1.21.
ignore_tags:
- nightly
# - "{{.Env.IGNORE_TAG}}"
report_sizes: true
builds:
- binary: chat-api
id: chat-api
main: ./cmd/api/chat-api/main.go
goos:
- darwin
- linux
- windows
goarch:
- amd64
- s390x
- arm64
- ppc64le
goarm:
- "6"
- "7"
ignore:
- goos: darwin
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: arm64
- goos: windows
goarch: ppc64le
- binary: admin-api
id: admin-api
main: ./cmd/api/admin-api/main.go
goos:
- darwin
- linux
- windows
goarch:
- amd64
- s390x
- arm64
- ppc64le
goarm:
- "6"
- "7"
ignore:
- goos: darwin
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: arm64
- goos: windows
goarch: ppc64le
- binary: chat-rpc
id: chat-rpc
main: ./cmd/rpc/chat-rpc/main.go
goos:
- darwin
- linux
- windows
goarch:
- amd64
- s390x
- arm64
- ppc64le
goarm:
- "6"
- "7"
ignore:
- goos: darwin
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: arm64
- goos: windows
goarch: ppc64le
- binary: admin-rpc
id: admin-rpc
main: ./cmd/rpc/admin-rpc/main.go
goos:
- darwin
- linux
- windows
goarch:
- amd64
- s390x
- arm64
- ppc64le
goarm:
- "6"
- "7"
ignore:
- goos: darwin
goarch: s390x
- goos: darwin
goarch: ppc64le
- goos: windows
goarch: s390x
- goos: windows
goarch: arm64
- goos: windows
goarch: ppc64le
archives:
- format: tar.gz
# this name template makes the OS and Arch compatible with the results of uname.
name_template: >-
{{ .ProjectName }}_
{{- title .Os }}_
{{- if eq .Arch "amd64" }}x86_64
{{- else if eq .Arch "386" }}i386
{{- else }}{{ .Arch }}{{ end }}
{{- if .Arm }}v{{ .Arm }}{{ end }}
# use zip for windows archives
files:
- LICENSE
- README.md
- docs/*
# a more complete example, check the globbing deep dive below
- src: "*.md"
dst: docs
# Strip parent folders when adding files to the archive.
strip_parent: true
# File info.
# Not all fields are supported by all formats available formats.
#
# Default: copied from the source file
info:
# Templates: allowed (since v1.14)
owner: root
# Templates: allowed (since v1.14)
group: root
# Must be in time.RFC3339Nano format.
#
# Templates: allowed (since v1.14)
mtime: "{{ .CommitDate }}"
# File mode.
mode: 0644
format_overrides:
- goos: windows
format: zip
changelog:
sort: asc
use: github
filters:
exclude:
- "^test:"
- "^chore"
- "merge conflict"
- Merge pull request
- Merge remote-tracking branch
- Merge branch
- go mod tidy
groups:
- title: Dependency updates
regexp: '^.*?(feat|fix)\(deps\)!?:.+$'
order: 300
- title: "New Features"
regexp: '^.*?feat(\([[:word:]]+\))??!?:.+$'
order: 100
- title: "Security updates"
regexp: '^.*?sec(\([[:word:]]+\))??!?:.+$'
order: 150
- title: "Bug fixes"
regexp: '^.*?fix(\([[:word:]]+\))??!?:.+$'
order: 200
- title: "Documentation updates"
regexp: ^.*?doc(\([[:word:]]+\))??!?:.+$
order: 400
- title: "Build process updates"
regexp: ^.*?build(\([[:word:]]+\))??!?:.+$
order: 400
- title: Other work
order: 9999
# dockers:
# - image_templates:
# - "openim/openim-chat-api-chat:{{ .Tag }}-amd64"
# - "ghcr.io/openimsdk/openim-chat-api-chat:{{ .Tag }}-amd64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-chat:{{ .Tag }}-amd64"
# build_flag_templates:
# - "--pull"
# - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/OpenIMSDK/chat/main/README.md"
# - "--label=io.artifacthub.package.logo-url=hhttps://git.imall.cloud/openim/chat/blob/main/assets/logo/openim-logo-green.png"
# - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
# - "--label=io.artifacthub.package.license=Apace-2.0"
# - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
# - "--label=org.opencontainers.image.created={{.Date}}"
# - "--label=org.opencontainers.image.name={{.ProjectName}}"
# - "--label=org.opencontainers.image.revision={{.FullCommit}}"
# - "--label=org.opencontainers.image.version={{.Version}}"
# - "--label=org.opencontainers.image.source={{.GitURL}}"
# - "--platform=linux/amd64"
# goos: linux
# goarch: amd64
# dockerfile: ./build/images/api-chat/Dockerfile
# use: buildx
# - image_templates:
# - "openim/openim-chat-api-chat:{{ .Tag }}-arm64"
# - "ghcr.io/openimsdk/openim-chat-api-chat:{{ .Tag }}-arm64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-chat:{{ .Tag }}-arm64"
# build_flag_templates:
# - "--pull"
# - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/OpenIMSDK/chat/main/README.md"
# - "--label=io.artifacthub.package.logo-url=hhttps://git.imall.cloud/openim/chat/blob/main/assets/logo/openim-logo-green.png"
# - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
# - "--label=io.artifacthub.package.license=Apace-2.0"
# - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
# - "--label=org.opencontainers.image.created={{.Date}}"
# - "--label=org.opencontainers.image.name={{.ProjectName}}"
# - "--label=org.opencontainers.image.revision={{.FullCommit}}"
# - "--label=org.opencontainers.image.version={{.Version}}"
# - "--label=org.opencontainers.image.source={{.GitURL}}"
# - "--platform=linux/arm64"
# goos: linux
# goarch: arm64
# dockerfile: ./build/images/api-chat/Dockerfile
# use: buildx
# - image_templates:
# - "openim/openim-chat-api-admin:{{ .Tag }}-amd64"
# - "ghcr.io/openimsdk/openim-chat-api-admin:{{ .Tag }}-amd64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-admin:{{ .Tag }}-amd64"
# build_flag_templates:
# - "--pull"
# - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/OpenIMSDK/chat/main/README.md"
# - "--label=io.artifacthub.package.logo-url=hhttps://git.imall.cloud/openim/chat/blob/main/assets/logo/openim-logo-green.png"
# - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
# - "--label=io.artifacthub.package.license=Apace-2.0"
# - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
# - "--label=org.opencontainers.image.created={{.Date}}"
# - "--label=org.opencontainers.image.name={{.ProjectName}}"
# - "--label=org.opencontainers.image.revision={{.FullCommit}}"
# - "--label=org.opencontainers.image.version={{.Version}}"
# - "--label=org.opencontainers.image.source={{.GitURL}}"
# - "--platform=linux/amd64"
# goos: linux
# goarch: amd64
# dockerfile: ./build/images/api-admin/Dockerfile
# use: buildx
# - image_templates:
# - "openim/openim-chat-api-admin:{{ .Tag }}-arm64"
# - "ghcr.io/openimsdk/openim-chat-api-admin:{{ .Tag }}-arm64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-admin:{{ .Tag }}-arm64"
# build_flag_templates:
# - "--pull"
# - "--label=io.artifacthub.package.readme-url=https://raw.githubusercontent.com/OpenIMSDK/chat/main/README.md"
# - "--label=io.artifacthub.package.logo-url=hhttps://git.imall.cloud/openim/chat/blob/main/assets/logo/openim-logo-green.png"
# - '--label=io.artifacthub.package.maintainers=[{"name":"Xinwei Xiong","email":"3293172751nss@gmail.com"}]'
# - "--label=io.artifacthub.package.license=Apace-2.0"
# - "--label=org.opencontainers.image.description=OpenIM Open source top instant messaging system"
# - "--label=org.opencontainers.image.created={{.Date}}"
# - "--label=org.opencontainers.image.name={{.ProjectName}}"
# - "--label=org.opencontainers.image.revision={{.FullCommit}}"
# - "--label=org.opencontainers.image.version={{.Version}}"
# - "--label=org.opencontainers.image.source={{.GitURL}}"
# - "--platform=linux/arm64"
# goos: linux
# goarch: arm64
# dockerfile: ./build/images/api-admin/Dockerfile
# use: buildx
# docker_manifests:
# - name_template: "openim/openim-chat-api-admin:{{ .Tag }}"
# image_templates:
# - "openim/openim-chat-api-admin:{{ .Tag }}-amd64"
# - "openim/openim-chat-api-admin:{{ .Tag }}-arm64"
# - name_template: "ghcr.io/openimsdk/openim-chat:{{ .Tag }}"
# image_templates:
# - "ghcr.io/openimsdk/openim-chat:{{ .Tag }}-amd64"
# - "ghcr.io/openimsdk/openim-chat:{{ .Tag }}-arm64"
# - name_template: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-admin:{{ .Tag }}"
# image_templates:
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-admin:{{ .Tag }}-amd64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-admin:{{ .Tag }}-arm64"
# - name_template: "openim/openim-chat-api-admin:latest"
# image_templates:
# - "openim/openim-chat-api-chat:{{ .Tag }}-amd64"
# - "openim/openim-chat-api-chat:{{ .Tag }}-arm64"
# - name_template: "ghcr.io/openimsdk/openim-chat-api-chat:latest"
# image_templates:
# - "ghcr.io/openimsdk/openim-chat-api-chat:{{ .Tag }}-amd64"
# - "ghcr.io/openimsdk/openim-chat-api-chat:{{ .Tag }}-arm64"
# - name_template: "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-chat:latest"
# image_templates:
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-chat:{{ .Tag }}-amd64"
# - "registry.cn-hangzhou.aliyuncs.com/openimsdk/openim-chat-api-chat:{{ .Tag }}-arm64"
nfpms:
- id: packages
builds:
- admin-api
- chat-api
- chat-rpc
- admin-rpc
# Your app's vendor.
vendor: OpenIMSDK
homepage: https://git.imall.cloud/openim/chat
maintainer: kubbot <https://github.com/kubbot>
description: |-
Auto sync github labels
kubbot && openimbot
license: MIT
formats:
- apk
- deb
- rpm
- termux.deb # Since: v1.11
- archlinux # Since: v1.13
dependencies:
- git
recommends:
- golang
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj
# Default: './dist'
dist: ./_output/dist
# # .goreleaser.yaml
# milestones:
# # You can have multiple milestone configs
# -
# # Repository for the milestone
# # Default is extracted from the origin remote URL
# repo:
# owner: OpenIMSDK
# name: chat
# # Whether to close the milestone
# close: true
# # Fail release on errors, such as missing milestone.
# fail_on_error: false
# # Name of the milestone
# #
# Default: '{{ .Tag }}'
# name_template: "Current Release"
publishers:
- name: "fury.io"
ids:
- packages
dir: "{{ dir .ArtifactPath }}"
cmd: |
bash -c '
if [[ "{{ .Tag }}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
curl -F package=@{{ .ArtifactName }} https://{{ .Env.FURY_TOKEN }}@push.fury.io/openim/
else
echo "Skipping deployment: Non-production release detected"
fi'
# snapcrafts:
# - name_template: "{{ .ProjectName }}_{{ .Arch }}{{ if .Arm }}v{{ .Arm }}{{ end }}"
# summary: openim is open source instant messaging
# description: |
# OpenIM yyds
# grade: stable
# confinement: classic
# publish: true
checksum:
name_template: "{{ .ProjectName }}_checksums.txt"
algorithm: sha256
snapshot:
name_template: "{{ .Tag }}-next"
release:
prerelease: auto
footer: |
## Welcome to the {{ .Tag }} release of [chat](https://git.imall.cloud/openim/chat)!🎉🎉!
**Full Changelog**: https://git.imall.cloud/openim/chat/compare/{{ .PreviousTag }}...{{ .Tag }}
## Helping out
+ We release logs are recorded on [✨ CHANGELOG](https://github.com/openimsdk/Open-IM-Server/blob/main/CHANGELOG/CHANGELOG.md)
+ For information on versions of OpenIM and how to maintain branches, read [📚this article](https://github.com/openimsdk/Open-IM-Server/blob/main/docs/conversions/version.md)
+ If you wish to use mirroring, read OpenIM's [image management policy](https://github.com/openimsdk/Open-IM-Server/blob/main/docs/conversions/images.md)
**Want to be one of them 😘?**
<p align="center">
<a href="https://github.com/kubbot" style="float: left; margin-right: 10px;">
<img src="https://github.com/openimbot/openimbot/blob/main/assets/icon/blue%E9%80%8F%E6%98%8E.png" width="50" height="50" />
</a>
<a href="https://www.openim.online">
<img src="https://github.com/openimsdk/Open-IM-Server/blob/main/assets/logo/openim-logo.png" />
</a>
<a href="https://github.com/openimbot" style="float: right; margin-left: 10px;">
<img src="https://github.com/openimbot/openimbot/blob/main/assets/icon/red%E9%80%8F%E6%98%8E.png" width="50" height="50" />
</a>
</p>
> **Note**
> @openimbot and @kubbot have made great contributions to the community as community 🤖robots(@openimsdk/bot), respectively.
> Thanks to the @openimsdk/openim team for all their hard work on this release.
> Thank you to all the [💕developers and contributors](https://git.imall.cloud/openim/chat/graphs/contributors), people from all over the world, OpenIM brings us together
> Contributions to this project are welcome! Please see [CONTRIBUTING.md](https://github.com/openimsdk/Open-IM-Server/blob/main/CONTRIBUTING.md) for details.
## Get Involved with OpenIM!
**Here are some ways to get involved with the OpenIM community:**
📢 **Slack Channel**: Join our Slack channels for discussions, communication, and support. Click [here](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) to join the chat Slack team channel.
📧 **Gmail Contact**: If you have any questions, suggestions, or feedback for our open-source projects, please feel free to [contact us via email](https://mail.google.com/mail/?view=cm&fs=1&tf=1&to=winxu81@gmail.com).
📖 **Blog**: Stay up-to-date with OpenIM-Server projects and trends by reading our [blog](https://doc.rentsoft.cn/). We share the latest developments, tech trends, and other interesting information related to OpenIM.
📱 **WeChat**: Add us on WeChat (QR Code) and indicate that you are a user or developer of chat. We'll process your request as soon as possible.
Remember, your contributions play a vital role in making OpenIM successful, and we look forward to your active participation in our community! 🙌
# webhook
# announce:
# slack:
# enabled: false
# message_template: "slack {{ .Tag }} is out! Check it out: https://github.com/openimsdk/Open-IM-Server/releases/tag/{{ .Tag }}"

View File

@@ -1,128 +0,0 @@
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders have the right and responsibility to remove, edit, or reject
comments, commits, code, wiki edits, issues, and other contributions that are
not aligned to this Code of Conduct, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
3293172751nss@gmail.com.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.

View File

@@ -1,371 +0,0 @@
# Contributing to Open-IM-Server
So, you want to hack on Open-IM-Server? Yay!
First of all, thank you for considering contributing to our project! We appreciate your time and effort, and we value any contribution, whether it's reporting a bug, suggesting a new feature, or submitting a pull request.
This document provides guidelines and best practices to help you contribute effectively.
## 📇Topics
- [Contributing to Open-IM-Server](#contributing-to-chat-deploy)
- [📇Topics](#topics)
- [What we expect of you](#what-we-expect-of-you)
- [Code of ConductCode of Conduct](#code-of-conductcode-of-conduct)
- [Code and doc contribution](#code-and-doc-contribution)
- [Where should I start?](#where-should-i-start)
- [Design documents](#design-documents)
- [Getting Started](#getting-started)
- [Style and Specification](#style-and-specification)
- [Reporting security issues](#reporting-security-issues)
- [Reporting general issues](#reporting-general-issues)
- [Commit Rules](#commit-rules)
- [PR Description](#pr-description)
- [Docs Contribution](#docs-contribution)
- [Engage to help anything](#engage-to-help-anything)
- [Release version](#release-version)
- [Contact Us](#contact-us)
## What we expect of you
We hope that anyone can join Open-IM-Server , even if you are a student, writer, translator
Please meet the minimum version of the Go language published in [go.mod](./go.mod). If you want to manage the Go language version, we provide tools to install [gvm](https://github.com/moovweb/gvm) in our [Makefile](./Makefile)
You'd better use Linux OR WSL as the development environment, Linux with [Makefile](./Makefile) can help you quickly build and test Open-IM-Server project.
If you are familiar with [Makefile](./Makefile) , you can easily see the clever design of the Open-IM-Server Makefile. Storing the necessary tools such as golangci in the `/tools` directory can avoid some tool version issues.
The [Makefile](./Makefile) is for every developer, even if you don't know how to use the Makefile tool, don't worry, we provide two great commands to get you up to speed with the Makefile architecture, `make help` and `make help-all`, it can reduce problems of the developing environment.
## Code of ConductCode of Conduct
#### Code and doc contribution
Every action to make project Open-IM-Server better is encouraged. On GitHub, every improvement for Open-IM-Server could be via a [PR](https://github.com/openimsdk/Open-IM-Server/pulls) (short for pull request).
- If you find a typo, try to fix it!
- If you find a bug, try to fix it!
- If you find some redundant codes, try to remove them!
- If you find some test cases missing, try to add them!
- If you could enhance a feature, please **DO NOT** hesitate!
- If you find code implicit, try to add comments to make it clear!
- If you find code ugly, try to refactor that!
- If you can help to improve documents, it could not be better!
- If you find document incorrect, just do it and fix that!
- ...
#### Where should I start?
- If you are new to the project, don't know how to contribute Open-IM-Server, please check out the [good first issue](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aopen+label%3A"good+first+issue"+sort%3Aupdated-desc) label.
- You should be good at filtering the Open-IM-Server issue tags and finding the ones you like, such as [RFC](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) for big initiatives, features for [feature](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+label%3Afeature) proposals, and [bug](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+label%3Abug+) fixes.
- If you are looking for something to work on, check out our [open issues](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc).
- If you have an idea for a new feature, please [open an issue](https://github.com/openimsdk/Open-IM-Server/issues/new/choose), and we can discuss it.
#### Design documents
For any substantial design, there should be a well-crafted design document. This document is not just a simple record, but also a detailed description and manifestation, which can help team members better understand the design thinking and grasp the design direction. In the process of writing the design document, we can choose to use tools such as `Google Docs` or `Notion`, and even mark RFC in [issues](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) or [discussions](https://github.com/openimsdk/Open-IM-Server/discussions) for better collaboration. Of course, after completing the design document, we should also add it to our [Shared Drive](https://drive.google.com/drive/) and notify the appropriate working group to let everyone know of its existence. Only by doing so can we maximize the effectiveness of the design document and provide strong support for the smooth progress of the project.
Anybody can access the shared Drive for reading. To get access to comment. Once you've done that, head to the [shared Drive](https://drive.google.com/) and behold all the docs.
In addition to that, we'd love to invite you to [join our Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) where you can play with your imagination, tell us what you're working on, and get a quick response.
When documenting a new design, we recommend a 2-step approach:
1. Use the short-form RFC template to outline your ideas and get early feedback.
2. Once you have received sufficient feedback and consensus, you may use the longer-form design doc template to specify and discuss your design in more details.
In order to contribute a feature to Open-IM-Server you'll need to go through the following steps:
- Discuss your idea with the appropriate [working groups](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) on the working group's Slack channel.
- Once there is general agreement that the feature is useful, create a GitHub issue to track the discussion. The issue should include information about the requirements and use cases that it is trying to address.
- Include a discussion of the proposed design and technical details of the implementation in the issue.
But keep in mind that there is no guarantee of it being accepted and so it is usually best to get agreement on the idea/design before time is spent coding it. However, sometimes seeing the exact code change can help focus discussions, so the choice is up to you.
## Getting Started
To propose PR for the Open-IM-Server item, we assume you have registered a GitHub ID. Then you could finish the preparation in the following steps:
1. Fork the repository(Open-IM-Server)
2. **CLONE** your own repository to main locally. Use `git clone https://github.com/<your-username>/Open-IM-Server.git` to clone repository to your local machine. Then you can create new branches to finish the change you wish to make.
3. **Set Remote** upstream to be `https://github.com/openimsdk/Open-IM-Server.git` using the following two commands:
```bash
git remote add upstream https://github.com/openimsdk/Open-IM-Server.git
git remote set-url --push upstream no-pushing
```
With this remote setting, you can check your git remote configuration like this:
```bash
git remote -v
origin https://github.com/<your-username>/Open-IM-Server.git (fetch)
origin https://github.com/<your-username>/Open-IM-Server.git (push)
upstream https://github.com/openimsdk/Open-IM-Server.git (fetch)
upstream no-pushing (push)
```
Adding this, we can easily synchronize local branches with upstream branches.
4. Create a new branch for your changes (use a descriptive name, such as `fix-bug-123` or `add-new-feature`).
```bash
cd Open-IM-Server
git fetch upstream
git checkout upstream/main
```
Create a new branch:
```bash
git checkout -b <new-branch>
```
Make any change on the `new-branch` then use [Makefile](./Makefile) build and test your codes.
5. **Commit your changes** to your local branch, lint before committing and commit with sign-off
```bash
git rebase upstream/main
make lint # golangci-lint run -c .golangci.yml
git add -A # add changes to staging
git commit -a -s -m "message for your changes" # -s adds a Signed-off-by trailer
```
6. **Push your branch** to your forked repository, it is recommended to have only one commit for a PR.
```bash
# sync up with upstream
git fetch upstream main
git rebase upstream/main
git rebase -i <commit-id> # rebase with interactive mode to squash your commits into a single one
git push # push to the remote repository, if it's a first time push, run git push --set-upstream origin <new-branch># sync up with upstream
git fetch upstream main
git rebase upstream/main
git rebase -i <commit-id> # rebase with interactive mode to squash your commits into a single one
git push # push to the remote repository, if it's a first time push, run git push --set-upstream origin <new-branch>
```
You can also use `git commit -s --amend && git push -f` to update modifications on the previous commit.
If you have developed multiple features in the same branch, you should create PR separately by rebasing to the main branch between each push:
```bash
# create new branch, for example git checkout -b feature/infra
git checkout -b <new branch>
# update some code, feature1
git add -A
git commit -m -s "feat: feature one"
git push # if it's first time push, run git push --set-upstream origin <new-branch>
# then create pull request, and merge
# update some new feature, feature2, rebase main branch first.
git rebase upstream/main # rebase the current branch to upstream/main branch
git add -A
git commit -m -s "feat: feature two"
# then create pull request, and merge
```
7. **Open a pull request** to `OpenIMSDK/Open-IM-Server:main`
It is recommended to review your changes before filing a pull request. Check if your code doesn't conflict with the main branch and no redundant code is included.
## Style and Specification
We divide the problem into security and general problems:
#### Reporting security issues
Security issues are always treated seriously. As our usual principle, we discourage anyone to spread security issues. If you find a security issue of Open-IM-Server, please do not discuss it in public and even do not open a public issue.
Instead we encourage you to send us a private email to winxu81@gmail.com to report this.
#### Reporting general issues
To be honest, we regard every user of Open-IM-Serveras a very kind contributor. After experiencing Open-IM-Server, you may have some feedback for the project. Then feel free to open an issue via [NEW ISSUE](https://github.com/openimsdk/Open-IM-Server/issues/new/choose).
Since we collaborate project Open-IM-Server in a distributed way, we appreciate **WELL-WRITTEN**, **DETAILED**, **EXPLICIT** issue reports. To make the communication more efficient, we wish everyone could search if your issue is an existing one in the searching list. If you find it existing, please add your details in comments under the existing issue instead of opening a brand new one.
To make the issue details as standard as possible, we setup an [ISSUE TEMPLATE](https://github.com/openimsdk/.github/tree/main/.github/ISSUE_TEMPLATE) for issue reporters. You can find three kinds of issue templates there: question, bug report and feature request. Please **BE SURE** to follow the instructions to fill fields in template.
**There are a lot of cases when you could open an issue:**
- bug report
- feature request
- Open-IM-Server performance issues
- feature proposal
- feature design
- help wanted
- doc incomplete
- test improvement
- any questions on Open-IM-Server project
- and so on
Also, we must be reminded when submitting a new question about Open-IM-Server, please remember to remove the sensitive data from your post. Sensitive data could be password, secret key, network locations, private business data and so on.
#### Commit Rules
Actually in Open-IM-Server, we take two rules serious when committing:
**🥇 Commit Message:**
Commit message could help reviewers better understand what the purpose of submitted PR is. It could help accelerate the code review procedure as well. We encourage contributors to use **EXPLICIT** commit message rather than ambiguous message. In general, we advocate the following commit message type:
We use [Semantic Commits](https://www.conventionalcommits.org/en/v1.0.0/) to make it easier to understand what a commit does and to build pretty changelogs. Please use the following prefixes for your commits:
- `docs: xxxx`. For example, "docs: add docs about storage installation".
- `feature: xxxx`.For example, "feature: make result show in sorted order".
- `bugfix: xxxx`. For example, "bugfix: fix panic when input nil parameter".
- `style: xxxx`. For example, "style: format the code style of Constants.java".
- `refactor: xxxx.` For example, "refactor: simplify to make codes more readable".
- `test: xxx`. For example, "test: add unit test case for func InsertIntoArray".
- `chore: xxx.` For example, "chore: integrate travis-ci". It's the type of mantainance change.
- other readable and explicit expression ways.
On the other side, we discourage contributors from committing message like the following ways:
- ~~fix bug~~
- ~~update~~
- ~~add doc~~
**🥈 Commit Content:**
Commit content represents all content changes included in one commit. We had better include things in one single commit which could support reviewer's complete review without any other commits' help.
In another word, contents in one single commit can pass the CI to avoid code mess. In brief, there are two minor rules for us to keep in mind:
1. avoid very large change in a commit.
2. complete and reviewable for each commit.
3. words are written in lowercase English, not uppercase English or other languages such as Chinese.
No matter what the commit message, or commit content is, we do take more emphasis on code review.
An example for this could be:
```bash
git commit -a -s -m "docs: add a new section to the README"
```
#### PR Description
PR is the only way to make change to Open-IM-Server project files. To help reviewers better get your purpose, PR description could not be too detailed. We encourage contributors to follow the [PR template](https://github.com/openimsdk/.github/tree/main/.github/PULL_REQUEST_TEMPLATE.md) to finish the pull request.
You can find some very formal PR in [RFC](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+RFC+label%3ARFC) issues and learn about them.
**📖 Opening PRs:**
- As long as you are working on your PR, please mark it as a draft
- Please make sure that your PR is up-to-date with the latest changes in `main`
- Mention the issue that your PR is addressing (Fix: #{ID_1}, #{ID_2})
- Make sure that your PR passes all checks
**🈴 Reviewing PRs:**
- Be respectful and constructive
- Assign yourself to the PR
- Check if all checks are passing
- Suggest changes instead of simply commenting on found issues
- If you are unsure about something, ask the author
- If you are not sure if the changes work, try them out
- Reach out to other reviewers if you are unsure about something
- If you are happy with the changes, approve the PR
- Merge the PR once it has all approvals and the checks are passing
**⚠️ DCO check:**
We have a DCO check that runs on every pull request to ensure code quality and maintainability. This check verifies that the commit has been signed off, indicating that you have read and agreed to the provisions of the Developer Certificate of Origin. If you have not yet signed off on the commit, you can use the following command to sign off on the last commit you made:
```bash
git commit --amend --signoff
```
Please note that signing off on a commit is a commitment that you have read and agreed to the provisions of the Developer Certificate of Origin. If you have not yet read this document, we strongly recommend that you take some time to read it carefully. If you have any questions about the content of this document, or if you need further assistance, please contact an administrator or relevant personnel.
You can also automate signing off your commits by adding the following to your `.zshrc` or `.bashrc`:
```go
git() {
if [ $# -gt 0 ] && [[ "$1" == "commit" ]] ; then
shift
command git commit --signoff "$@"
else
command git "$@"
fi
}
```
#### Docs Contribution
The documentation for Open-IM-Server includes:
- [README.md](https://github.com/openimsdk/Open-IM-Server/blob/main/README.md): This file includes the basic information and instructions for getting started with Open-IM-Server.
- [CONTRIBUTING.md](https://github.com/openimsdk/Open-IM-Server/blob/main/CONTRIBUTING.md): This file contains guidelines for contributing to Open-IM-Server's codebase, such as how to submit issues, pull requests, and code reviews.
- [Official Documentation](https://doc.rentsoft.cn/): This is the official documentation for Open-IM-Server, which includes comprehensive information on all of its features, configuration options, and troubleshooting tips.
Please obey the following rules to better format the docs, which would greatly improve the reading experience.
1. Please do not use Chinese punctuations in English docs, and vice versa.
2. Please use upper case letters where applicable, like the first letter of sentences / headings, etc.
3. Please specify a language for each Markdown code blocks, unless there's no associated languages.
4. Please insert a whitespace between Chinese and English words.
5. Please use the correct case for technical terms, such as using `HTTP` instead of http, `MySQL` rather than mysql, `Kubernetes` instead of kubernetes, etc.
6. Please check if there's any typos in the docs before submitting PRs.
## Engage to help anything
We choose GitHub as the primary place for Open-IM-Server to collaborate. So the latest updates of Open-IM-Server are always here. Although contributions via PR is an explicit way to help, we still call for any other ways.
- reply to other's [issues](https://github.com/openimsdk/Open-IM-Server/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc) if you could;
- help solve other user's problems;
- help review other's [PR](https://github.com/openimsdk/Open-IM-Server/pulls?q=is%3Apr+is%3Aopen+sort%3Aupdated-desc) design;
- discuss about Open-IM-Server to make things clearer;
- advocate [Open-IM-Server](https://google.com/search?q=Open-IM-Server) technology beyond GitHub;
- write blogs on Open-IM-Server and so on.
In a word, **ANY HELP IS CONTRIBUTION.**
## Release version
Releases of Open-IM-Server are done using [Release Please](https://github.com/googleapis/release-please) and [GoReleaser](https://goreleaser.com/). The workflow looks like this:
🎯 A PR is merged to the `main` branch:
- Release please is triggered, creates or updates a new release PR
- This is done with every merge to main, the current release PR is updated every time
🎯 Merging the 'release please' PR to `main`:
- Release please is triggered, creates a new release and updates the changelog based on the commit messages
- GoReleaser is triggered, builds the binaries and attaches them to the release
- Containers are created and pushed to the container registry
With the next relevant merge, a new release PR will be created and the process starts again
**👀 Manually setting the version:**
If you want to manually set the version, you can create a PR with an empty commit message that contains the version number in the commit message. For example:
Such a commit can get produced as follows:
```bash
git commit --allow-empty -m "chore: release 0.0.3" -m "Release-As: 0.0.3
```
## Contact Us
We value close connections with our users, developers, and contributors here at Open-IM-Server. With a large community and maintainer team, we're always here to help and support you. Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.
Our most recommended way to get in touch is through [Slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A). Even if you're in China, Slack is usually not blocked by firewalls, making it an easy way to connect with us. Our Slack community is the ideal place to discuss and share ideas and suggestions with other users and developers of Open-IM-Server. You can ask technical questions, seek help, or share your experiences with other users of Open-IM-Server.
In addition to Slack, we also offer the following ways to get in touch:
- <a href="https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A" target="_blank"><img src="https://img.shields.io/badge/slack-%40OpenIMSDKCore-informational?logo=slack&style=flat-square"></a>: We also have Slack channels for you to communicate and discuss. To join, visit https://slack.com/ and join our [👀 Open-IM-Server slack](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A) team channel.
- <a href="https://mail.google.com/mail/u/0/?fs=1&tf=cm&to=4closetool3@gmail.com" target="_blank"><img src="https://img.shields.io/badge/gmail-%40OOpenIMSDKCore?style=social&logo=gmail"></a>: Get in touch with us on [Gmail](winxu81@gmail.com). If you have any questions or issues that need resolving, or any suggestions and feedback for our open source projects, please feel free to contact us via email.
- <a href="https://doc.rentsoft.cn/" target="_blank"><img src="https://img.shields.io/badge/%E5%8D%9A%E5%AE%A2-%40OpenIMSDKCore-blue?style=social&logo=Octopus%20Deploy"></a>: Read our [blog](https://doc.rentsoft.cn/). Our blog is a great place to stay up-to-date with Open-IM-Server projects and trends. On the blog, we share our latest developments, tech trends, and other interesting information.
- <a href="https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg" target="_blank"><img src="https://img.shields.io/badge/%E5%BE%AE%E4%BF%A1-OpenIMSDKCore-brightgreen?logo=wechat&style=flat-square"></a>: Add [Wechat](https://github.com/openimsdk/OpenIM-Docs/blob/main/docs/images/WechatIMG20.jpeg) and indicate that you are a user or developer of Open-IM-Server. We will process your request as soon as possible.
Whether you're looking to join our community or have any questions or suggestions, we welcome you to get in touch with us.

View File

@@ -1,52 +0,0 @@
# Use Go 1.21 Alpine as the base image for building the application
FROM golang:1.22-alpine AS builder
# Define the base directory for the application as an environment variable
ENV SERVER_DIR=/openim-chat
# Set the working directory inside the container based on the environment variable
WORKDIR $SERVER_DIR
# Set the Go proxy to improve dependency resolution speed
# ENV GOPROXY=https://goproxy.io,direct
COPY go.mod go.sum ./
RUN go mod download
# Copy all files from the current directory into the container
COPY . .
# Install Mage to use for building the application
RUN go install github.com/magefile/mage@v1.15.0
# Optionally build your application if needed
RUN mage build
# Using Alpine Linux with Go environment for the final image
FROM golang:1.22-alpine
# Install necessary packages, such as bash
RUN apk add --no-cache bash
# Set the environment and work directory
ENV SERVER_DIR=/openim-chat
WORKDIR $SERVER_DIR
# Copy the compiled binaries and mage from the builder image to the final image
COPY --from=builder $SERVER_DIR/_output $SERVER_DIR/_output
COPY --from=builder $SERVER_DIR/config $SERVER_DIR/config
COPY --from=builder /go/bin/mage /usr/local/bin/mage
COPY --from=builder $SERVER_DIR/magefile_windows.go $SERVER_DIR/
COPY --from=builder $SERVER_DIR/magefile_unix.go $SERVER_DIR/
COPY --from=builder $SERVER_DIR/magefile.go $SERVER_DIR/
COPY --from=builder $SERVER_DIR/start-config.yml $SERVER_DIR/
COPY --from=builder $SERVER_DIR/go.mod $SERVER_DIR/
COPY --from=builder $SERVER_DIR/go.sum $SERVER_DIR/
RUN go get github.com/openimsdk/gomake@v0.0.14-alpha.5
# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "mage start && tail -f /dev/null"]

View File

@@ -1,157 +0,0 @@
# How to add REST RPC API for OpenIM Chat
</br>
OpenIM Chat server works with the OpenIM Server to offer the powerfull IM service. It has many REST APIs which are called by the OpenIM Server, works as an Application Server to fullfill your system demands.
You can add your business extensions to the OpenIM Chat server by adding REST APIs and let the OpenIM Server call these extend APIs to fulfill your system demands. The following will show you how to add a REST API for it.
## Protobuf source file modifications
First, your should add the REST API request and response message declarations, and RPC method declarations to the '.proto' protobuf source code, then call 'protoc' command to generate '.pb.go' go protobuf implementation codes.
For example, to add a REST API to generate login token for video meeting, you may want to add a request message named <font color="#FF8000">GetTokenForVideoMeetingReq</font> and a response message named <font color="#FF8000">GetTokenForVideoMeetingResp</font>. This can be done by adding this two messages to '/pkg/proto/chat/chat.proto'. You also should add a RPC method named <font color="#FF8000">GetTokenForVideoMeeting()</font> fors the <font color="#FF8000">chat</font> service.
### chat.proto:
```proto
syntax = "proto3";
package OpenIMChat.chat;
import "pub/wrapperspb.proto";
import "pub/sdkws.proto";
import "common/common.proto";
option go_package = "git.imall.cloud/openim/chat/pkg/protocol/chat";
...
message GetTokenForVideoMeetingReq {
string room = 1;
string identity = 2;
}
message GetTokenForVideoMeetingResp {
string serverUrl = 1;
string token = 2;
}
service chat {
...
// Audio/video call and video meeting
rpc GetTokenForVideoMeeting(GetTokenForVideoMeetingReq) returns (GetTokenForVideoMeetingResp);
}
```
## Generate protobuf implementations
</br>
Then, we start a terminal to run 'pkg/proto/gen.sh' shell script, which will call protoc command to regenerate chat.pb.go with protobuf implementation codes for your add messages.
## Add Check() method for the request message
</br>
To check the parameters in the request message, we should add a Check() method for newly added Request message. Take chat.proto as an example, we add the a Check() member method for GetTokenForVideoMeetingReq class in 'pkg/proto/chat/chat.go'.
```go
func (x *GetTokenForVideoMeetingReq) Check() error {
if x.Room == "" {
errs.ErrArgs.WrapMsg("Room is empty")
}
if x.Identity == "" {
errs.ErrArgs.WrapMsg("User Identity is empty")
}
return nil
}
```
## Add the URL for REST RPC API
</br>
Now, we should add a URL for REST RPC API.
For example, to add a REST API to generate login token for video meeting, you may want to add a RPC API named 'get_token', which is a member of the 'user' group, the REST URL can be '/user/rtc/get_token'.
This URL should be add to NewChatRoute() method in 'internal/api/router.go'.
```go
func NewChatRoute(router gin.IRouter, discov discoveryregistry.SvcDiscoveryRegistry) {
...
user := router.Group("/user", mw.CheckToken)
user.POST("/update", chat.UpdateUserInfo) // Edit personal information
user.POST("/find/public", chat.FindUserPublicInfo) // Get user's public information
user.POST("/find/full", chat.FindUserFullInfo) // Get all information of the user
user.POST("/search/full", chat.SearchUserFullInfo) // Search user's public information
user.POST("/search/public", chat.SearchUserPublicInfo) // Search all information of the user
// your added code begins here
user.POST("/rtc/get_token", chat.GetTokenForVideoMeeting) // Get token for video meeting
...
}
```
## Implement the REST service
### Implement the REST Service Api
We add REST RPC API implementation to the corresponding service implementation go file located in '/internal/api/'. For the chat service, we add codes to '/internal/api/chat.go'.
```go
...
func (o *ChatApi) GetTokenForVideoMeeting(c *gin.Context)
{
a2r.Call(chat.ChatClient.GetTokenForVideoMeeting, o.chatClient, c)
}
...
```
### Implement the REST Service logic
We implement the REST Service logic in go files of the path '/internal/rpc/service_name/group_name.go'. For the user group of <font color="#FF8000">chat</font> service, the implementation logic should be added to '/internal/rpc/chat/user.go'.
Here we call the GetLiveKitServerUrl() and GetLiveKitToken() func in the rtc package to allocate a new GetTokenForVideoMeetingResp message and return it to the RPC caller.
```go
package chat
import (
...
"git.imall.cloud/openim/chat/pkg/common/rtc"
...
)
...
func (o *chatSvr) GetTokenForVideoMeeting(ctx context.Context, req *chat.GetTokenForVideoMeetingReq) (*chat.GetTokenForVideoMeetingResp, error)
{
if _, _, err := mctx.Check(ctx); err != nil {
return nil, err
}
serverUrl := rtc.GetLiveKitServerUrl()
token, err := rtc.GetLiveKitToken(req.Room, req.Identity)
if err != nil {
return nil, err
}
return &chat.GetTokenForVideoMeetingResp{
ServerUrl: serverUrl,
Token: token,
}, err
}
```
## Done
Now we have finished all the works to add an REST RPC API for OpenIM Chat. We may call
```shell
make build
```
to re-compile the chat project and call
```shell
make start
```
to start the OpenIM Chat server and test the <font color="#FF8000">chat</font> service's new REST RPC API.
###

View File

@@ -1,57 +0,0 @@
# Setting Up LiveKit Server for OpenIM Chat
OpenIM Chat uses the LiveKit server as the media server to support video calls and video meeting services.
## About LiveKit
[LiveKit](https://github.com/livekit/livekit-server) is an open-source WebRTC SFU written in Go, built on top of the excellent [Pion](https://github.com/pion) project. For more information, visit the [LiveKit website](https://livekit.io/).
## Quick Start
To self-host LiveKit, start the server with the following Docker command:
> replace `your-server-ip` with your server IP address
```bash
docker run -d \
-p 7880:7880 \
-p 7881:7881 \
-p 7882:7882/udp \
-v $PWD/livekit/livekit.yaml:/livekit.yaml \
livekit/livekit-server \
--config /livekit.yaml \
--bind 0.0.0.0 \
--node-ip=your-server-ip
```
## Viewing Logs
To check the server logs and ensure everything is running correctly, use the following command:
```bash
docker logs livekit/livekit-server
```
## Configuring the LiveKit Address in OpenIM Chat
- **If Chat is deployed from source code**, update the `config/chat-rpc-chat.yml` file to configure the LiveKit server address:
```yaml
liveKit:
url: "ws://127.0.0.1:7880" # ws://your-server-ip:7880 or wss://your-domain/path
```
- **If Chat is deployed via Docker**, add the following environment variable to the `docker-compose.yaml` file:
```yaml
CHATENV_CHAT_RPC_CHAT_LIVEKIT_URL="ws://your-server-ip:7880" # or wss://your-domain/path
```
Open the following ports: TCP: 7880-7881, UDP: 7882, and UDP: 50000-60000.
By following these steps, you can set up and configure the LiveKit server for use with OpenIM Chat.
## More about Deploying LiveKi
For detailed instructions on deploying LiveKit, refer to the self-hosting [deployment documentation](https://docs.livekit.io/realtime/self-hosting/deployment/).

201
LICENSE
View File

@@ -1,201 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@@ -1,89 +0,0 @@
# openim-chat
## 🧩 Feature Overview
1. This repository implements a business system, which consists of two parts: User System and Backend Management System.
2. The system relies on the [chat-deploy repository](https://github.com/openimsdk/chat-deploy) and implements various business functions by calling the APIs of the instant messaging system.
3. The User System includes regular functions such as user login, user registration, user information update, etc.
4. The Backend Management System includes APIs for managing users, groups, and messages.
## :busts_in_silhouette: Community
- 💬 [Follow our Twitter account](https://twitter.com/founder_im63606)
- 🚀 [Join our Slack community](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
- :eyes: [Join our WeChat group](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
## 🛫 Quick Start
> :warning: **Note**: This project works on Linux/Windows/Mac platforms and both ARM and AMD architectures.
### 📦 Clone
```bash
git clone https://git.imall.cloud/openim/chat openim-chat
cd openim-chat
```
### 🛠 Initialization
:computer: Before the first compilation, execute on Linux/Mac platforms:
```
sh bootstrap.sh
```
:computer: On Windows execute:
```
bootstrap.bat
```
### 🏗 Build
```bash
mage
```
### 🚀 Start
```bash
mage start
```
### :floppy_disk: Or start in the background and collect logs
```
nohup mage start >> _output/logs/chat.log 2>&1 &
```
### :mag_right: Check
```bash
mage check
```
### 🛑 Stop
```bash
mage stop
```
### 🚀 Start Sequence
1. Successfully start [chat-deploy](https://github.com/openimsdk/chat-deploy).
2. Compile chat `mage`.
3. Start chat `mage start`.
## 📞 If you want to enable audio and video calls, please configure LiveKit
:link: Please refer to "[How to set up LiveKit server](./HOW_TO_SETUP_LIVEKIT_SERVER.md)".
## :handshake: Contributing
:heart: Contributions to this project are welcome! Please see [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
## 🚨 License
This software is licensed under the Apache License 2.0

View File

@@ -1,89 +0,0 @@
# openim-chat
## 🧩 功能简介
1. 该仓库实现了业务系统,包括两部分:用户系统和后台管理系统。
2. 该系统依赖于 [chat-deploy 仓库](https://github.com/openimsdk/chat-deploy),通过调用即时消息系统的 API 实现丰富的业务功能。
3. 用户系统包括一些常规功能,如用户登录、用户注册、用户信息更新等。
4. 后台管理系统包括提供了 API 管理用户、群组和消息等。
## :busts_in_silhouette: 社区
- 💬 [关注我们的 Twitter 账户](https://twitter.com/founder_im63606)
- 🚀 [加入我们的 Slack 社区](https://join.slack.com/t/openimsdk/shared_invite/zt-2ijy1ys1f-O0aEDCr7ExRZ7mwsHAVg9A)
- :eyes: [加入我们的微信群](https://openim-1253691595.cos.ap-nanjing.myqcloud.com/WechatIMG20.jpeg)
## 🛫 快速开始
> :warning: **注意**:本项目在 Linux/Windows/Mac 平台以及 ARM 和 AMD 架构下均可正常使用
### 📦 克隆
```bash
git clone https://git.imall.cloud/openim/chat openim-chat
cd openim-chat
```
### 🛠 初始化
:computer: 第一次编译前Linux/Mac 平台下执行:
```
sh bootstrap.sh
```
:computer: Windows 执行:
```
bootstrap.bat
```
### 🏗 编译
```bash
mage
```
### 🚀 启动
```bash
mage start
```
### :floppy_disk: 或后台启动 收集日志
```
nohup mage start >> _output/logs/chat.log 2>&1 &
```
### :mag_right: 检测
```bash
mage check
```
### 🛑 停止
```bash
mage stop
```
### 🚀 启动顺序
1. 成功启动 [chat-deploy](https://github.com/openimsdk/chat-deploy)。
2. 编译 chat `mage`
3. 启动 chat `mage start`
## 📞 如果您想启用音视频通话,请配置 LiveKit
:link: 请参考 "[如何设置 LiveKit 服务器](./HOW_TO_SETUP_LIVEKIT_SERVER.md)"。
## :handshake: 贡献
:heart: 欢迎对该项目做出贡献!请查看 [CONTRIBUTING.md](./CONTRIBUTING.md) 了解详情。
## 🚨 许可
This software is licensed under the Apache License 2.0

View File

@@ -1,31 +0,0 @@
@echo off
SETLOCAL
mage -version >nul 2>&1
IF %ERRORLEVEL% EQU 0 (
echo Mage is already installed.
GOTO DOWNLOAD
)
go version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
echo Go is not installed. Please install Go and try again.
exit /b 1
)
echo Installing Mage...
go install github.com/magefile/mage@latest
mage -version >nul 2>&1
IF NOT %ERRORLEVEL% EQU 0 (
echo Mage installation failed.
echo Please ensure that %GOPATH%/bin is in your PATH.
exit /b 1
)
echo Mage installed successfully.
:DOWNLOAD
go mod download
ENDLOCAL

View File

@@ -1,23 +0,0 @@
#!/bin/bash
if [[ ":$PATH:" == *":$HOME/.local/bin:"* ]]; then
TARGET_DIR="$HOME/.local/bin"
else
TARGET_DIR="/usr/local/bin"
echo "Using /usr/local/bin as the installation directory. Might require sudo permissions."
fi
if ! command -v mage &> /dev/null; then
echo "Installing Mage to $TARGET_DIR ..."
GOBIN=$TARGET_DIR go install github.com/magefile/mage@latest
fi
if ! command -v mage &> /dev/null; then
echo "Mage installation failed."
echo "Please ensure that $TARGET_DIR is in your \$PATH."
exit 1
fi
echo "Mage installed successfully."
go mod download

View File

@@ -1,65 +0,0 @@
# Building OpenIM
Building OpenIM is easy if you take advantage of the containerized build environment. This document will help guide you through understanding this build process.
## Requirements
1. Docker, using one of the following configurations:
* **macOS** Install Docker for Mac. See installation instructions [here](https://docs.docker.com/docker-for-mac/).
**Note**: You will want to set the Docker VM to have at least 4GB of initial memory or building will likely fail.
* **Linux with local Docker** Install Docker according to the [instructions](https://docs.docker.com/installation/#installation) for your OS.
* **Windows with Docker Desktop WSL2 backend** Install Docker according to the [instructions](https://docs.docker.com/docker-for-windows/wsl-tech-preview/). Be sure to store your sources in the local Linux file system, not the Windows remote mount at `/mnt/c`.
**Note**: You will need to check if Docker CLI plugin buildx is properly installed (`docker-buildx` file should be present in `~/.docker/cli-plugins`). You can install buildx according to the [instructions](https://github.com/docker/buildx/blob/master/README.md#installing).
2. **Optional** [Google Cloud SDK](https://developers.google.com/cloud/sdk/)
You must install and configure Google Cloud SDK if you want to upload your release to Google Cloud Storage and may safely omit this otherwise.
## Actions
About [Images packages](https://github.com/orgs/OpenIMSDK/packages?repo_name=Open-IM-Server)
All files in the `build/images` directory are not templated and are instead rendered by Github Actions, which is an automated process.
Trigger condition:
1. create a new tag with the format `vX.Y.Z` (e.g. `v1.0.0`)
2. push the tag to the remote repository
3. wait for the build to finish
4. download the artifacts from the release page
## Make images
**help info:**
```bash
$ make image.help
```
**build images:**
```bash
$ make image
```
## Overview
While it is possible to build OpenIM using a local golang installation, we have a build process that runs in a Docker container. This simplifies initial set up and provides for a very consistent build and test environment.
## Basic Flow
The scripts directly under [`build/`](.) are used to build and test. They will ensure that the `openim-build` Docker image is built (based on [`build/build-image/Dockerfile`](../Dockerfile) and after base image's `OPENIM_BUILD_IMAGE_CROSS_TAG` from Dockerfile is replaced with one of those actual tags of the base image, like `v1.13.9-2`) and then execute the appropriate command in that container. These scripts will both ensure that the right data is cached from run to run for incremental builds and will copy the results back out of the container. You can specify a different registry/name and version for `openim-cross` by setting `OPENIM_CROSS_IMAGE` and `OPENIM_CROSS_VERSION`, see [`common.sh`](common.sh) for more details.
The `openim-build` container image is built by first creating a "context" directory in `_output/images/build-image`. It is done there instead of at the root of the OpenIM repo to minimize the amount of data we need to package up when building the image.
There are 3 different containers instances that are run from this image. The first is a "data" container to store all data that needs to persist across to support incremental builds. Next there is an "rsync" container that is used to transfer data in and out to the data container. Lastly there is a "build" container that is used for actually doing build actions. The data container persists across runs while the rsync and build containers are deleted after each use.
`rsync` is used transparently behind the scenes to efficiently move data in and out of the container. This will use an ephemeral port picked by Docker. You can modify this by setting the `OPENIM_RSYNC_PORT` env variable.
All Docker names are suffixed with a hash derived from the file path (to allow concurrent usage on things like CI machines) and a version number. When the version number changes all state is cleared and clean build is started. This allows the build infrastructure to be changed and signal to CI systems that old artifacts need to be deleted.
## Build artifacts
The build system output all its products to a top level directory in the source repository named `_output`.
These include the binary compiled packages (e.g. imctl, openim-api etc.) and archived Docker images.
If you intend to run a component with a docker image you will need to import it from this directory with

View File

@@ -1,24 +0,0 @@
# Copyright © 2023 OpenIM open source community. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM BASE_IMAGE
WORKDIR ${SERVER_WORKDIR}
# Set HTTP proxy
ARG BINARY_NAME
COPY BINARY_NAME ./bin/BINARY_NAME
ENTRYPOINT ["./bin/BINARY_NAME"]

View File

@@ -1,39 +0,0 @@
# Use Go 1.22 Alpine as the base image for building the application
FROM golang:1.22-alpine AS builder
# Install git for repository access
RUN apk add --no-cache git ca-certificates
# Define the base directory for the application as an environment variable
ENV CHAT_DIR=/openim-chat
# Set the working directory inside the container based on the environment variable
WORKDIR $CHAT_DIR
# Copy protocol directory
COPY protocol /protocol
# Copy current directory
COPY . .
# Use container's existing SSH configuration for private repositories
RUN go mod tidy
RUN go build -o _output/admin-api ./cmd/api/admin-api
# Using Alpine Linux for the final image
FROM alpine:latest
# Install necessary packages, such as bash
RUN apk add --no-cache bash
# Set the environment and work directory
ENV CHAT_DIR=/openim-chat
WORKDIR $CHAT_DIR
# Copy the compiled binaries and mage from the builder image to the final image
COPY --from=builder $CHAT_DIR/_output $CHAT_DIR/_output
COPY --from=builder $CHAT_DIR/config $CHAT_DIR/config
# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/admin-api"]

View File

@@ -1,39 +0,0 @@
# Use Go 1.22 Alpine as the base image for building the application
FROM golang:1.22-alpine AS builder
# Install git for repository access
RUN apk add --no-cache git ca-certificates
# Define the base directory for the application as an environment variable
ENV CHAT_DIR=/openim-chat
# Set the working directory inside the container based on the environment variable
WORKDIR $CHAT_DIR
# Copy protocol directory
COPY protocol /protocol
# Copy current directory
COPY . .
# Use container's existing SSH configuration for private repositories
RUN go mod tidy
RUN go build -o _output/admin-rpc ./cmd/rpc/admin-rpc
# Using Alpine Linux for the final image
FROM alpine:latest
# Install necessary packages, such as bash
RUN apk add --no-cache bash
# Set the environment and work directory
ENV CHAT_DIR=/openim-chat
WORKDIR $CHAT_DIR
# Copy the compiled binaries and mage from the builder image to the final image
COPY --from=builder $CHAT_DIR/_output $CHAT_DIR/_output
COPY --from=builder $CHAT_DIR/config $CHAT_DIR/config
# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/admin-rpc"]

View File

@@ -1,51 +0,0 @@
# Use Go 1.22 Alpine as the base image for building the application
FROM golang:1.22-alpine AS builder
# Install git for repository access
RUN apk add --no-cache git ca-certificates
# Define the base directory for the application as an environment variable
ENV CHAT_DIR=/openim-chat
# Set the working directory inside the container based on the environment variable
WORKDIR $CHAT_DIR
# Build arguments to invalidate cache when code changes
ARG BUILD_SHA
ARG BUILD_TIME
ENV BUILD_SHA=$BUILD_SHA
ENV BUILD_TIME=$BUILD_TIME
# Copy protocol directory
COPY protocol /protocol
# Copy go mod files first for better caching
COPY go.mod go.sum ./
# Download dependencies (this layer will be cached if go.mod/go.sum don't change)
RUN go mod download
# Copy current directory (this will invalidate cache when code changes)
COPY . .
# Use container's existing SSH configuration for private repositories
RUN go mod tidy
RUN go build -o _output/chat-api ./cmd/api/chat-api
# Using Alpine Linux for the final image
FROM alpine:latest
# Install necessary packages, such as bash
RUN apk add --no-cache bash
# Set the environment and work directory
ENV CHAT_DIR=/openim-chat
WORKDIR $CHAT_DIR
# Copy the compiled binaries and mage from the builder image to the final image
COPY --from=builder $CHAT_DIR/_output $CHAT_DIR/_output
COPY --from=builder $CHAT_DIR/config $CHAT_DIR/config
# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/chat-api"]

View File

@@ -1,39 +0,0 @@
# Use Go 1.22 Alpine as the base image for building the application
FROM golang:1.22-alpine AS builder
# Install git for repository access
RUN apk add --no-cache git ca-certificates
# Define the base directory for the application as an environment variable
ENV CHAT_DIR=/openim-chat
# Set the working directory inside the container based on the environment variable
WORKDIR $CHAT_DIR
# Copy protocol directory
COPY protocol /protocol
# Copy current directory
COPY . .
# Use container's existing SSH configuration for private repositories
RUN go mod tidy
RUN go build -o _output/chat-rpc ./cmd/rpc/chat-rpc
# Using Alpine Linux for the final image
FROM alpine:latest
# Install necessary packages, such as bash
RUN apk add --no-cache bash
# Set the environment and work directory
ENV CHAT_DIR=/openim-chat
WORKDIR $CHAT_DIR
# Copy the compiled binaries and mage from the builder image to the final image
COPY --from=builder $CHAT_DIR/_output $CHAT_DIR/_output
COPY --from=builder $CHAT_DIR/config $CHAT_DIR/config
# Set the command to run when the container starts
ENTRYPOINT ["sh", "-c", "_output/chat-rpc"]

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewAdminApiCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewBotApiCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewChatApiCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewAdminRpcCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewBotRpcCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,26 +0,0 @@
// Copyright © 2023 OpenIM open source community. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"git.imall.cloud/openim/chat/pkg/common/cmd"
"github.com/openimsdk/tools/system/program"
)
func main() {
if err := cmd.NewChatRpcCmd().Exec(); err != nil {
program.ExitWithError(err)
}
}

View File

@@ -1,44 +0,0 @@
# OpenIM Chat Configuration Files and Common Configuration Item Modifications Guide
## Configuration Files Explanation
| Configuration File | Description |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
| **redis.yml** | Configurations for Redis password, address, etc. |
| **mongodb.yml** | Configurations for MongoDB username, password, address, etc. |
| **share.yml** | Common configurations needed by various OpenIM services, such as secret. |
| **discovery.yml** | Service discovery account, password, service name and other configurations. |
| **chat-api-chat.yml** | Configurations for listening IP, port, etc., in chat-api-chat service. |
| **chat-api-admin.yml** | Configurations for listening IP, port, etc., in chat-api-admin service. |
| **chat-rpc-chat.yml** | Configurations for listening IP, port, login registration verification code, registration allowance, and livekit in chat-rpc-chat service. |
| **chat-rpc-admin.yml** | Configurations for listening IP, port, chat backend token expiration policy, and chat backend Secret in chat-rpc-admin service. |
## Common Configuration Item Modifications
| Configuration Item to Modify | Configuration File |
| ----------------------------------------- | -------------------- |
| Modify OpenIM secret | `share.yml` |
| Production environment logs | `log.yml` |
| Modify chat Admin username and password | `share.yml` |
| Modify verification code | `chat-rpc-chat.yml` |
| Allow user registration | `chat-rpc-chat.yml` |
| Modify chat Admin token expiration policy | `chat-rpc-admin.yml` |
| Modify chat Admin Secret | `chat-rpc-admin.yml` |
## Starting Multiple Instances of an OpenIM Service
To launch multiple instances of an OpenIM service, you just need to increase the corresponding number of ports and modify the `start-config.yml` file in the project's root directory, then restart the service for the changes to take effect. For example, the configuration for launching 2 instances of `chat-rpc` is as follows:
```yaml
rpc:
registerIP: ""
listenIP: 0.0.0.0
ports: [30300, 30301]
```
Modify `start-config.yml`:
```yaml
serviceBinaries:
chat-rpc: 2
```

View File

@@ -1,45 +0,0 @@
# OpenIM Chat 配置文件说明以及常用配置修改说明
## 配置文件说明
| Configuration File | Description |
| ---------------------- | ----------------------------------------------------------------------------------------- |
| **redis.yml** | Redis 密码、地址等配置 |
| **mongodb.yml** | MongoDB 用户名、密码、地址等配置 |
| **log.yml** | 日志级别及存储目录等配置 |
| **share.yml** | OpenIM 各服务所需的公共配置,如 secret、Admin 后台密码等 |
| **discovery.yml** | 服务发现对应的账号密码和服务名等配置 |
| **chat-api-chat.yml** | chat-api-chat 服务的监听 IP、端口等配置 |
| **chat-api-admin.yml** | chat-api-admin 服务的监听 IP、端口等配置 |
| **chat-rpc-chat.yml** | chat-rpc-chat.yml 服务的监听 IP、端口以及登录注册验证码、是否允许注册和 livekit 等配置 |
| **chat-rpc-admin.yml** | chat-rpc-admin 服务的监听 IP、端口以及 chat 后台 token 过期策略和 chat 后台 Secret 等配置 |
## 常用配置修改
| 修改配置项 | 配置文件 |
| ----------------------------- | -------------------- |
| 修改 OpenIM secret | `share.yml` |
| 生产环境日志调整 | `log.yml` |
| 修改 chat Admin | `share.yml` |
| 修改验证码相关配置 | `chat-rpc-chat.yml` |
| 允许用户注册 | `chat-rpc-chat.yml` |
| 修改 chat 后台 token 过期策略 | `chat-rpc-admin.yml` |
| 修改 chat 后台 Secret | `chat-rpc-admin.yml` |
## 启动某个 OpenIM 服务的多个实例
若要启动某个 OpenIM 的多个实例,只需增加对应的端口数,并修改项目根目录下的`start-config.yml`文件,重启服务即可生效。例如,启动 2 个`chat-rpc`实例的配置如下:
```yaml
rpc:
registerIP: ""
listenIP: 0.0.0.0
ports: [30300, 30301]
```
Modify start-config.yml:
```yaml
serviceBinaries:
chat-rpc: 2
```

View File

@@ -1,6 +0,0 @@
api:
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended
listenIP: 0.0.0.0
# Listening ports; if multiple are configured, multiple instances will be launched
ports: [ 10009 ]

View File

@@ -1,6 +0,0 @@
api:
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended
listenIP: 0.0.0.0
# Listening ports; if multiple are configured, multiple instances will be launched
ports: [ 10010 ]

View File

@@ -1,6 +0,0 @@
api:
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended
listenIP: 0.0.0.0
# Listening ports; if multiple are configured, multiple instances will be launched
ports: [ 10008 ]

View File

@@ -1,12 +0,0 @@
rpc:
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
registerIP: ''
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
listenIP: 0.0.0.0
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances.
ports: [ 30200 ]
tokenPolicy:
expire: 90
secret: chat123

View File

@@ -1,10 +0,0 @@
rpc:
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
registerIP: ''
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
listenIP: 0.0.0.0
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances.
ports: [ 30400 ]
# Model request timeout. Unit: s
timeout: 20

View File

@@ -1,44 +0,0 @@
rpc:
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
registerIP: ''
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
listenIP: 0.0.0.0
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances.
ports: [ 30300 ]
verifyCode:
validTime: 300
validCount: 5
uintTime: 86400
maxCount: 10
superCode: "666666"
len: 6
phone:
use: "superCode" # superCode: user superCode; ali: use ali verify code; bao: use bao verify code;
ali:
endpoint: ""
accessKeyId: ""
accessKeySecret: ""
signName: ""
verificationCodeTemplateCode: ""
bao:
endpoint: "http://127.0.0.1:18080"
accessKeyId: "local"
accessKeySecret: "local"
signName: "local"
verificationCodeTemplateCode: ""
mail:
use: "superCode" # superCode: user superCode; mail: use mail verify code;
title: ""
senderMail: ""
senderAuthorizationCode: ""
smtpAddr: ""
smtpPort:
liveKit:
url: "ws://127.0.0.1:7880" # LIVEKIT_URL, LiveKit server address and port
key: "devkey"
secret: "devsecret"
allowRegister: true
allowVerifyCodeLogin: false # 是否允许验证码登录设置为false则隐藏验证码登录功能

View File

@@ -1,14 +0,0 @@
enable: "etcd"
etcd:
rootDirectory: openim
address: [ localhost:12379 ]
username: ''
password: ''
kubernetes:
namespace: default
rpcService:
chat: chat-rpc-service
admin: admin-rpc-service
bot: bot-rpc-service

View File

@@ -1,14 +0,0 @@
# Log storage path, default is acceptable, change to a full path if modification is needed
storageLocation: ../../../../logs/
# Log rotation period (in hours), default is acceptable
rotationTime: 24
# Number of log files to retain, default is acceptable
remainRotationCount: 2
# Log level settings: 3 for production environment; 6 for more verbose logging in debugging environments
remainLogLevel: 6
# Whether to output to standard output, default is acceptable
isStdout: true
# Whether to log in JSON format, default is acceptable
isJson: false
# output simplify log when KeyAndValues's value len is bigger than 50 in rpc method log
isSimplify: true

View File

@@ -1,16 +0,0 @@
# URI for database connection, leave empty if using address and credential settings directly
uri: ""
# List of MongoDB server addresses
address: [localhost:37017]
# Name of the database
database: openim_v3
# Username for database authentication
username: openIM
# Password for database authentication
password: openIM123
# Authentication source for database authentication, if use root user, set it to admin
authSource: openim_v3
# Maximum number of connections in the connection pool
maxPoolSize: 100
# Maximum number of retry attempts for a failed database connection
maxRetry: 10

View File

@@ -1,14 +0,0 @@
# List of Redis server addresses
address: [ localhost:16379 ]
# Username for Redis authentication (leave blank if not used)
username: ''
# Password for Redis authentication
password: openIM123
# Enable or disable pipeline processing
enablePipeline: false
# Enable or disable cluster mode
clusterMode: false
# Database index to be used
db: 0
# Maximum number of retry attempts for a failed connection
maxRetry: 10

View File

@@ -1,13 +0,0 @@
openIM:
# OpenIM API address
apiURL: http://127.0.0.1:10002
# OpenIM secret key, must be consistent with OpenIM
secret: openIM123
# OpenIM administrator userID, must be consistent with OpenIM
adminUserID: imAdmin
# Refresh OpenIM token interval
tokenRefreshInterval: 120 # unit: minute
chatAdmin:
# Default username and password for the admin
- "chatAdmin"

View File

@@ -1,122 +0,0 @@
# OpenIM Chat Deployment
## Preconditions
- Ensure deployed OpenIM Server and its dependencies.
- Redis
- MongoDB
- Kafka
- MinIO
- Expose the corresponding Services and ports of OpenIM Server.
## Deploy OpenIM Chat
**Chat depends on OpenIM Server, so you need to deploy OpenIM Server first.**
enter the target directory
```shell
cd deployments/deploy
```
### Modify ConfigMap
You need to modify the `chat-config.yml` file to match your environment. Focus on the following fields:
**discovery.yml**
- `kubernetes.namespace`: default is `default`, you can change it to your namespace.
**mongodb.yml**
- `address`: set to your already mongodb address or mongo Service name and port in your deployed.
- `database`: set to your mongodb database name.(Need have a created database.)
- `authSource`: et to your mongodb authSource. (authSource is specify the database name associated with the user's credentials, user need create in this database.)
**redis.yml**
- `address`: set to your already redis address or redis Service name and port in your deployed.
**share.yml**
- `openIM.apiURL`: modify to your already API address or use your `openim-api` service name and port
- `openIM.secret`: same to IM Server `share.secret` value.
### Set the secret
A Secret is an object that contains a small amount of sensitive data. Such as password and secret. Secret is similar to ConfigMaps.
#### Redis:
Update the `redis-password` value in `redis-secret.yml` to your Redis password encoded in base64.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: openim-redis-secret
type: Opaque
data:
redis-password: b3BlbklNMTIz # update to your redis password encoded in base64, if need empty, you can set to ""
```
#### Mongo:
Update the `mongo_openim_username`, `mongo_openim_password` value in `mongo-secret.yml` to your Mongo username and password encoded in base64.
```yaml
apiVersion: v1
kind: Secret
metadata:
name: openim-mongo-secret
type: Opaque
data:
mongo_openim_username: b3BlbklN # update to your mongo username encoded in base64, if need empty, you can set to "" (this user credentials need in authSource database)
mongo_openim_password: b3BlbklNMTIz # update to your mongo password encoded in base64, if need empty, you can set to ""
```
### Apply the secret.
```shell
kubectl apply -f redis-secret.yml -f mongo-secret.yml
```
### Apply Config and Services
deploy the config and services
```shell
kubectl apply -f chat-config.yml -f openim-admin-api-service.yml -f openim-chat-api-service.yml -f openim-admin-rpc-service.yml -f openim-chat-rpc-service.yml
```
### Start Chat Deployments
```shell
kubectl apply -f openim-chat-api-deployment.yml -f openim-admin-api-deployment.yml -f openim-chat-rpc-deployment.yml -f openim-admin-rpc-deployment.yml
```
## Verify
After the deployment is complete, you can verify the deployment status.
```shell
# Check the status of all pods
kubectl get pods
# Check the status of services
kubectl get svc
# Check the status of deployments
kubectl get deployments
# View all resources
kubectl get all
```
## clean all
`kubectl delete -f ./`
## Notes:
- If you use a specific namespace for your deployment, be sure to append the -n <namespace> flag to your kubectl commands.

View File

@@ -1,148 +0,0 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: openim-chat-config
data:
discovery.yml: |
enable: kubernetes
kubernetes:
namespace: default
etcd:
rootDirectory: openim
address: [ localhost:12379 ]
username: ''
password: ''
rpcService:
chat: chat-rpc-service
admin: admin-rpc-service
log.yml: |
# Log storage path, default is acceptable, change to a full path if modification is needed
# storageLocation: ../../../../logs/
storageLocation: ./logs/
# Log rotation period (in hours), default is acceptable
rotationTime: 24
# Number of log files to retain, default is acceptable
remainRotationCount: 2
# Log level settings: 3 for production environment; 6 for more verbose logging in debugging environments
remainLogLevel: 6
# Whether to output to standard output, default is acceptable
isStdout: true
# Whether to log in JSON format, default is acceptable
isJson: false
# output simplify log when KeyAndValues's value len is bigger than 50 in rpc method log
isSimplify: true
mongodb.yml: |
# URI for database connection, leave empty if using address and credential settings directly
uri: ''
# List of MongoDB server addresses
address: [ mongo-service:37017 ]
# Name of the database
database: openim_v3
# Username for database authentication
username: openIM
# Password for database authentication
password: # openIM123
# Authentication source for database authentication, if use root user, set it to admin
authSource: openim_v3
# Maximum number of connections in the connection pool
maxPoolSize: 100
# Maximum number of retry attempts for a failed database connection
maxRetry: 10
redis.yml: |
# List of Redis server addresses
address: [ redis-service:16379 ]
# Username for Redis authentication (leave blank if not used)
username: ''
# Password for Redis authentication
password: # openIM123
# Enable or disable pipeline processing
enablePipeline: false
# Enable or disable cluster mode
clusterMode: false
# Database index to be used
db: 0
# Maximum number of retry attempts for a failed connection
maxRetry: 10
share.yml: |
openIM:
# OpenIM API address
apiURL: http://openim-api-service:10002
# OpenIM secret key, must be consistent with OpenIM
secret: openIM123
# OpenIM administrator userID, must be consistent with OpenIM
adminUserID: imAdmin
chatAdmin:
# Default username and password for the admin
- "chatAdmin"
chat-api-admin.yml: |
api:
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended
listenIP: 0.0.0.0
# Listening ports; if multiple are configured, multiple instances will be launched
ports: [ 10009 ]
chat-rpc-admin.yml: |
rpc:
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
registerIP: ''
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
listenIP: 0.0.0.0
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances.
ports: [ 30200 ]
tokenPolicy:
expire: 90
secret: chat123
chat-api-chat.yml: |
api:
# Listening IP; 0.0.0.0 means both internal and external IPs are listened to, default is recommended
listenIP: 0.0.0.0
# Listening ports; if multiple are configured, multiple instances will be launched
ports: [ 10008 ]
chat-rpc-chat.yml: |
rpc:
# The IP address where this RPC service registers itself; if left blank, it defaults to the internal network IP
registerIP: ''
# IP address that the RPC service listens on; setting to 0.0.0.0 listens on both internal and external IPs. If left blank, it automatically uses the internal network IP
listenIP: 0.0.0.0
# List of ports that the RPC service listens on; configuring multiple ports will launch multiple instances.
ports: [ 30300 ]
verifyCode:
validTime: 300
validCount: 5
uintTime: 86400
maxCount: 10
superCode: "666666"
len: 6
phone:
use: ""
ali:
endpoint: ""
accessKeyId: ""
accessKeySecret: ""
signName: ""
verificationCodeTemplateCode: ""
mail:
enable: false
title: ""
senderMail: ""
senderAuthorizationCode: ""
smtpAddr: ""
smtpPort:
liveKit:
url: "ws://127.0.0.1:7880" # LIVEKIT_URL, LiveKit server address and port
key: "APIGPW3gnFTzqHH"
secret: "23ztfSqsfQ8hKkHzHTl3Z4bvaxro0snjk5jwbp5p6Q3"
allowRegister: true

View File

@@ -1,8 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: openim-mongo-secret
type: Opaque
data:
mongo_openim_username: b3BlbklN # base64 for "openIM", this user credentials need in authSource database.
mongo_openim_password: b3BlbklNMTIz # base64 for "openIM123"

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-api-server
spec:
replicas: 1
selector:
matchLabels:
app: admin-api-server
template:
metadata:
labels:
app: admin-api-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-admin-api-container
image: mag1666888/openim-admin-api:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 10009
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: admin-api-service
spec:
selector:
app: admin-api-server
ports:
- name: http-10009
protocol: TCP
port: 10009
targetPort: 10009
type: NodePort

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: admin-rpc-server
spec:
replicas: 1
selector:
matchLabels:
app: admin-rpc-server
template:
metadata:
labels:
app: admin-rpc-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-admin-rpc-container
image: mag1666888/openim-admin-rpc:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 30200
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: admin-rpc-service
spec:
selector:
app: admin-rpc-server
ports:
- name: rpc-30200
protocol: TCP
port: 30200
targetPort: 30200
type: ClusterIP

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-api-server
spec:
replicas: 1
selector:
matchLabels:
app: chat-api-server
template:
metadata:
labels:
app: chat-api-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-chat-api-container
image: mag1666888/openim-chat-api:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 10008
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: chat-api-service
spec:
selector:
app: chat-api-server
ports:
- name: http-10008
protocol: TCP
port: 10008
targetPort: 10008
type: NodePort

View File

@@ -1,49 +0,0 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: chat-rpc-server
spec:
replicas: 1
selector:
matchLabels:
app: chat-rpc-server
template:
metadata:
labels:
app: chat-rpc-server
spec:
imagePullSecrets:
- name: dockerhub-secret
containers:
- name: openim-chat-rpc-container
image: mag1666888/openim-chat-rpc:prod
imagePullPolicy: Always
env:
- name: CONFIG_PATH
value: "/config"
- name: CHATENV_REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: openim-redis-secret
key: redis-password
- name: IMENV_MONGODB_USERNAME
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_username
- name: CHATENV_MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: openim-mongo-secret
key: mongo_openim_password
volumeMounts:
- name: openim-chat-config
mountPath: "/config"
readOnly: true
ports:
- containerPort: 30300
volumes:
- name: openim-chat-config
configMap:
name: openim-chat-config

View File

@@ -1,13 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: chat-rpc-service
spec:
selector:
app: chat-rpc-server
ports:
- name: rpc-30300
protocol: TCP
port: 30300
targetPort: 30300
type: ClusterIP

View File

@@ -1,7 +0,0 @@
apiVersion: v1
kind: Secret
metadata:
name: openim-redis-secret
type: Opaque
data:
redis-password: b3BlbklNMTIz # "openIM123" in base64

View File

@@ -1,174 +0,0 @@
# chat-deploy 可观测性部署指南
本目录包含将 chat-deploy 接入 itom-platform 可观测中心所需的配置文件。
## 功能说明
- **日志采集**:通过 Promtail 采集 Docker 容器日志,推送到 itom-platform 的 Loki
- **MongoDB 监控**:通过 MongoDB Exporter 采集 MongoDB 指标
- **Redis 监控**(可选):通过 Redis Exporter 采集 Redis 指标
- **系统监控**(可选):通过 Node Exporter 采集系统级指标CPU/Memory/Disk/Network
## 快速开始
### 1. 配置环境变量
复制示例配置文件并修改:
```bash
cp config.env.example config.env
```
**必须修改的配置项**
| 配置项 | 说明 | 示例 |
|--------|------|------|
| `OBS_HOST` | itom-platform 可观测中心地址 | `192.168.1.100``obs.example.com` |
| `OBS_AUTH_TOKEN` | 鉴权 token与中心侧一致 | `your-secret-token` |
| `MONGODB_URI` | MongoDB 连接 URI | `mongodb://user:pass@host:27017/db` |
### 2. 启动日志采集
仅启用日志采集:
```bash
docker compose --env-file config.env -f docker-compose-observability.yaml up -d
```
### 3. 启动完整可观测性(日志 + 指标)
同时启用日志和指标采集:
```bash
docker compose --env-file config.env -f docker-compose-observability.yaml --profile metrics up -d
```
### 4. 验证服务状态
```bash
# 查看服务状态
docker compose --env-file config.env -f docker-compose-observability.yaml ps
# 查看 Promtail 日志
docker logs chat-deploy-promtail
# 查看 MongoDB Exporter 指标
curl http://localhost:9216/metrics | head -50
```
## 配置说明
### MongoDB 配置
MongoDB Exporter 需要正确的连接 URI。根据 `config/mongodb.yml` 中的配置:
```env
# 默认配置
MONGODB_URI=mongodb://openIM:openIM123@localhost:37017/openim_v3?authSource=openim_v3
```
如果 MongoDB 运行在 Docker 容器中,请使用容器名或宿主机 IP
```env
# 使用容器名(需要在同一网络)
MONGODB_URI=mongodb://openIM:openIM123@mongo:27017/openim_v3?authSource=openim_v3
# 使用宿主机 IP
MONGODB_URI=mongodb://openIM:openIM123@host.docker.internal:37017/openim_v3?authSource=openim_v3
```
### Redis 配置(可选)
如果需要监控 Redis
```env
REDIS_ADDR=localhost:6379
REDIS_PASSWORD=your_redis_password
```
### 网络配置
如果 chat-deploy 的服务运行在其他 Docker 网络中,需要将可观测性组件加入该网络。
编辑 `docker-compose-observability.yaml`,添加外部网络:
```yaml
networks:
chat-deploy-obs:
driver: bridge
# 添加外部网络
chat-deploy-network:
external: true
services:
mongodb-exporter:
networks:
- chat-deploy-obs
- chat-deploy-network # 加入 chat-deploy 网络
```
## 监控面板
在 itom-platform 的 Grafana 中,使用 `chat-deploy-dashboard` 查看:
- 服务健康状态
- Go 运行时指标CPU、内存、GC
- MongoDB 操作统计query/insert/update/delete
- MongoDB 连接数
- Redis 指标(如已配置)
- 应用日志
## 故障排查
### 日志未采集
1. 检查 Promtail 是否正常运行:
```bash
docker logs chat-deploy-promtail
```
2. 确认 LOKI_URL 配置正确:
```bash
echo $LOKI_URL
# 应输出类似http://192.168.1.100/loki/api/v1/push
```
3. 测试网络连通性:
```bash
curl -v http://<OBS_HOST>/loki/api/v1/push
```
### MongoDB 指标缺失
1. 检查 MongoDB Exporter 是否正常运行:
```bash
docker logs chat-deploy-mongodb-exporter
```
2. 验证 MongoDB 连接:
```bash
curl http://localhost:9216/metrics | grep mongodb_up
# 应输出mongodb_up 1
```
3. 确认 MongoDB URI 格式正确且网络可达
### 指标未推送到中心
1. 检查 Prometheus Agent 日志:
```bash
docker logs chat-deploy-prometheus-agent
```
2. 确认 remote_write URL 配置正确
3. 检查网络防火墙是否允许访问中心端口
## 更新配置
修改 `config.env` 后,重启服务:
```bash
docker compose --env-file config.env -f docker-compose-observability.yaml down
docker compose --env-file config.env -f docker-compose-observability.yaml --profile metrics up -d
```

View File

@@ -1,71 +0,0 @@
# ==============================
# chat-deploy 可观测性配置
# ==============================
# 项目标识(必须与 itom-platform 中配置一致)
OBS_PROJECT=chat-deploy
OBS_SERVICE=chat-deploy
OBS_SERVICE_NAME=chat-deploy
OBS_ENV=prod
# ==============================
# 中心侧连接配置(必须修改)
# ==============================
# itom-platform 可观测中心的地址
OBS_HOST=CHANGE_ME
OBS_SCHEME=http
# 鉴权 token必须与 itom-platform 中心侧一致)
OBS_AUTH_TOKEN=CHANGE_ME
# ==============================
# 日志采集配置Promtail
# ==============================
# Loki 写入 URL走网关
LOKI_URL=${OBS_SCHEME}://${OBS_HOST}/loki/api/v1/push
# Promtail 镜像版本
PROMTAIL_IMAGE=grafana/promtail:3.0.0
# Docker API 版本(避免与旧 Docker daemon 协议不兼容)
DOCKER_API_VERSION=1.44
# ==============================
# 指标采集配置Prometheus Agent
# ==============================
# 中心侧 remote_write receiver 地址
METRICS_REMOTE_WRITE_URL=${OBS_SCHEME}://${OBS_HOST}/api/v1/write
# 中心侧是否开启 remote_write 鉴权
OBS_AUTH_ENABLE=false
# 业务服务指标采集目标可选格式name=host:port,name2=host:port
METRICS_TARGETS=
# ==============================
# MongoDB 配置(必须修改)
# ==============================
# MongoDB 连接 URI用于 mongodb-exporter
# 格式mongodb://username:password@host:port/database?authSource=admin
MONGODB_URI=mongodb://openIM:openIM123@localhost:37017/openim_v3?authSource=openim_v3
# MongoDB Exporter 采集目标(自动配置,通常无需修改)
MONGODB_EXPORTER_TARGETS=mongodb-exporter:9216
MONGODB_EXPORTER_SERVICE=chat-deploy
# ==============================
# Redis 配置(可选)
# ==============================
# Redis 地址(用于 redis-exporter
REDIS_ADDR=localhost:6379
REDIS_PASSWORD=
# Redis Exporter 采集目标
REDIS_EXPORTER_TARGETS=redis-exporter:9121
REDIS_EXPORTER_SERVICE=chat-deploy
# ==============================
# Node Exporter 配置(可选)
# ==============================
NODE_EXPORTER_TARGETS=node-exporter:9100
NODE_EXPORTER_SERVICE=chat-deploy

View File

@@ -1,236 +0,0 @@
#!/usr/bin/env sh
set -eu
# ------------------------------
# chat-deploy 指标采集Prometheus Agent Entrypoint
# - 根据环境变量生成 /prometheus/prometheus.yml 与 /prometheus/targets.json
# - 然后以 agent 模式启动 Prometheusremote_write 推送到 itom-platform 中心)
#
# 关键环境变量(来自 config.env
# - METRICS_REMOTE_WRITE_URL=http(s)://<OBS_HOST>/api/v1/write
# - METRICS_TARGETS=name=host:port,name2=host:port
# - OBS_AUTH_ENABLE=false/true中心侧是否要求鉴权
# - OBS_AUTH_TOKEN=xxxxx当 OBS_AUTH_ENABLE=true 时必填)
# - OBS_PROJECT/OBS_ENV写入 labels便于中心侧筛选
# ------------------------------
METRICS_REMOTE_WRITE_URL="${METRICS_REMOTE_WRITE_URL:-}"
OBS_AUTH_ENABLE="${OBS_AUTH_ENABLE:-false}"
OBS_AUTH_TOKEN="${OBS_AUTH_TOKEN:-}"
METRICS_TARGETS="${METRICS_TARGETS:-}"
OBS_PROJECT="${OBS_PROJECT:-chat-deploy}"
OBS_ENV="${OBS_ENV:-prod}"
OBS_SERVICE="${OBS_SERVICE:-chat-deploy}"
OBS_SERVICE_NAME="${OBS_SERVICE_NAME:-$OBS_SERVICE}"
if [ -z "$OBS_SERVICE_NAME" ]; then
OBS_SERVICE_NAME="chat-deploy"
fi
is_truthy() { case "$1" in 1|true|TRUE|yes|YES|on|ON) return 0 ;; esac; return 1; }
if [ -z "$METRICS_REMOTE_WRITE_URL" ]; then
echo "[prometheus-agent] FAIL: METRICS_REMOTE_WRITE_URL 为空" >&2
exit 2
fi
if is_truthy "$OBS_AUTH_ENABLE" && [ -z "$OBS_AUTH_TOKEN" ]; then
echo "[prometheus-agent] FAIL: OBS_AUTH_ENABLE=true 但 OBS_AUTH_TOKEN 为空" >&2
exit 2
fi
# 确保数据目录存在且有写权限
mkdir -p /prometheus/data
chmod -R 777 /prometheus 2>/dev/null || true
TARGETS_JSON="/prometheus/targets.json"
echo "[" > "$TARGETS_JSON"
first=1
IFS=','
for item in $METRICS_TARGETS; do
item="$(printf "%s" "$item" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')"
[ -z "$item" ] && continue
name="$(printf "%s" "$item" | cut -d= -f1 | tr -d '[:space:]')"
target="$(printf "%s" "$item" | cut -d= -f2- | tr -d '[:space:]')"
[ -z "$name" ] && continue
[ -z "$target" ] && continue
target="$(printf "%s" "$target" | sed -E 's#^https?://##; s#/.*$##')"
if [ $first -eq 1 ]; then first=0; else echo "," >> "$TARGETS_JSON"; fi
cat >> "$TARGETS_JSON" <<EOF
{"targets":["$target"],"labels":{"service":"$name","project":"$OBS_PROJECT","env":"$OBS_ENV"}}
EOF
done
unset IFS
echo "]" >> "$TARGETS_JSON"
if [ "$first" -eq 1 ]; then
echo "[prometheus-agent] WARN: METRICS_TARGETS 为空或格式无效,仅采集 prometheus-agent 自身指标和 Exporter 指标" >&2
fi
CONFIG="/prometheus/prometheus.yml"
cat > "$CONFIG" <<EOF
global:
scrape_interval: 15s
external_labels:
project: $OBS_PROJECT
env: $OBS_ENV
service: $OBS_SERVICE_NAME
scrape_configs:
# Prometheus Agent 自身指标(用于验证采集链路是否正常)
- job_name: "prometheus-agent"
static_configs:
- targets: ["localhost:9090"]
# 业务服务指标(通过 METRICS_TARGETS 或 file_sd_configs 配置)
- job_name: "services"
metrics_path: /metrics
file_sd_configs:
- files: ["$TARGETS_JSON"]
refresh_interval: 10s
EOF
# 自动发现并采集 Exporter 指标Redis、MongoDB
echo "" >> "$CONFIG"
echo " # 自动发现/手动指定的 Exporter 指标" >> "$CONFIG"
trim() {
printf "%s" "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'
}
normalize_target() {
raw="$1"
default_port="$2"
raw="$(printf "%s" "$raw" | sed -E 's#^https?://##; s#/.*$##')"
raw="$(trim "$raw")"
[ -z "$raw" ] && return 1
case "$raw" in
*:*) printf "%s" "$raw" ;;
*) printf "%s:%s" "$raw" "$default_port" ;;
esac
}
append_exporter_job() {
job="$1"
targets="$2"
default_port="$3"
service_label="$4"
targets_list=""
IFS=','
for item in $targets; do
item="$(normalize_target "$item" "$default_port" || true)"
[ -z "$item" ] && continue
if [ -z "$targets_list" ]; then
targets_list="$item"
else
targets_list="${targets_list},$item"
fi
done
unset IFS
if [ -z "$targets_list" ]; then
return 0
fi
echo " - job_name: '$job'" >> "$CONFIG"
echo " static_configs:" >> "$CONFIG"
echo " - targets:" >> "$CONFIG"
IFS=','
for item in $targets_list; do
echo " - '$item'" >> "$CONFIG"
done
unset IFS
cat >> "$CONFIG" <<EOF
labels:
project: '${OBS_PROJECT}'
service: '${service_label}'
EOF
}
# Redis Exporter端口 9121
REDIS_EXPORTER_HOST=""
REDIS_EXPORTER_TARGETS="${REDIS_EXPORTER_TARGETS:-}"
REDIS_EXPORTER_SERVICE="${REDIS_EXPORTER_SERVICE:-$OBS_SERVICE_NAME}"
if getent hosts redis-exporter >/dev/null 2>&1; then
REDIS_EXPORTER_HOST="redis-exporter"
elif getent hosts chat-deploy-redis-exporter >/dev/null 2>&1; then
REDIS_EXPORTER_HOST="chat-deploy-redis-exporter"
fi
if [ -n "$REDIS_EXPORTER_HOST" ]; then
if [ -n "$REDIS_EXPORTER_TARGETS" ]; then
REDIS_EXPORTER_TARGETS="${REDIS_EXPORTER_TARGETS},${REDIS_EXPORTER_HOST}:9121"
else
REDIS_EXPORTER_TARGETS="${REDIS_EXPORTER_HOST}:9121"
fi
fi
append_exporter_job "redis" "$REDIS_EXPORTER_TARGETS" "9121" "$REDIS_EXPORTER_SERVICE"
if [ -n "$REDIS_EXPORTER_TARGETS" ]; then
echo "[prometheus-agent] Redis Exporter 采集目标已配置project=${OBS_PROJECT} service=${REDIS_EXPORTER_SERVICE}"
fi
# MongoDB Exporter端口 9216- chat-deploy 使用 MongoDB
MONGODB_EXPORTER_HOST=""
MONGODB_EXPORTER_TARGETS="${MONGODB_EXPORTER_TARGETS:-}"
MONGODB_EXPORTER_SERVICE="${MONGODB_EXPORTER_SERVICE:-$OBS_SERVICE_NAME}"
if getent hosts mongodb-exporter >/dev/null 2>&1; then
MONGODB_EXPORTER_HOST="mongodb-exporter"
elif getent hosts chat-deploy-mongodb-exporter >/dev/null 2>&1; then
MONGODB_EXPORTER_HOST="chat-deploy-mongodb-exporter"
fi
if [ -n "$MONGODB_EXPORTER_HOST" ]; then
if [ -n "$MONGODB_EXPORTER_TARGETS" ]; then
MONGODB_EXPORTER_TARGETS="${MONGODB_EXPORTER_TARGETS},${MONGODB_EXPORTER_HOST}:9216"
else
MONGODB_EXPORTER_TARGETS="${MONGODB_EXPORTER_HOST}:9216"
fi
fi
append_exporter_job "mongodb" "$MONGODB_EXPORTER_TARGETS" "9216" "$MONGODB_EXPORTER_SERVICE"
if [ -n "$MONGODB_EXPORTER_TARGETS" ]; then
echo "[prometheus-agent] MongoDB Exporter 采集目标已配置project=${OBS_PROJECT} service=${MONGODB_EXPORTER_SERVICE}"
fi
# Node Exporter端口 9100- 用于系统级指标CPU/Memory/Disk/Network/IO
NODE_EXPORTER_HOST=""
NODE_EXPORTER_TARGETS="${NODE_EXPORTER_TARGETS:-}"
NODE_EXPORTER_SERVICE="${NODE_EXPORTER_SERVICE:-$OBS_SERVICE_NAME}"
if getent hosts node-exporter >/dev/null 2>&1; then
NODE_EXPORTER_HOST="node-exporter"
elif getent hosts chat-deploy-node-exporter >/dev/null 2>&1; then
NODE_EXPORTER_HOST="chat-deploy-node-exporter"
fi
if [ -n "$NODE_EXPORTER_HOST" ]; then
if [ -n "$NODE_EXPORTER_TARGETS" ]; then
NODE_EXPORTER_TARGETS="${NODE_EXPORTER_TARGETS},${NODE_EXPORTER_HOST}:9100"
else
NODE_EXPORTER_TARGETS="${NODE_EXPORTER_HOST}:9100"
fi
fi
append_exporter_job "node" "$NODE_EXPORTER_TARGETS" "9100" "$NODE_EXPORTER_SERVICE"
if [ -n "$NODE_EXPORTER_TARGETS" ]; then
echo "[prometheus-agent] Node Exporter 采集目标已配置project=${OBS_PROJECT} service=${NODE_EXPORTER_SERVICE}"
fi
cat >> "$CONFIG" <<EOF
remote_write:
- url: "$METRICS_REMOTE_WRITE_URL"
EOF
if is_truthy "$OBS_AUTH_ENABLE"; then
echo " bearer_token: \"$OBS_AUTH_TOKEN\"" >> "$CONFIG"
echo "[prometheus-agent] remote_write 鉴权已启用" >&2
else
echo "[prometheus-agent] remote_write 鉴权未启用" >&2
fi
echo "[prometheus-agent] 配置文件已生成:"
cat "$CONFIG"
echo ""
# Prometheus 3.x 不再需要 --enable-feature=agent
exec /bin/prometheus --config.file=/prometheus/prometheus.yml --storage.tsdb.path=/prometheus/data --web.enable-lifecycle

View File

@@ -1,61 +0,0 @@
server:
http_listen_port: 9080
grpc_listen_port: 0
positions:
filename: /tmp/positions.yaml
clients:
- url: ${LOKI_URL}
bearer_token: ${OBS_AUTH_TOKEN}
scrape_configs:
# ============================================
# chat-deploy 业务层日志采集
# ============================================
- job_name: chat-deploy-logs
static_configs:
- targets:
- localhost
labels:
job: chat-deploy-logs
project: ${OBS_PROJECT}
service: ${OBS_SERVICE}
log_layer: business
__path__: /var/lib/docker/containers/*/*-json.log
pipeline_stages:
# 解析 Docker JSON 日志格式
- docker: {}
# 从文件路径提取容器 ID
- regex:
source: filename
expression: '/var/lib/docker/containers/(?P<container_id>[0-9a-f]{12})[0-9a-f]*/'
- labels:
container_id:
# ============================================
# 过滤规则:只丢弃基础设施层日志
# 保留 chat-deploy 业务层日志包括Go服务的caller日志
# ============================================
# 1. 丢弃 promtail/prometheus/grafana 等基础设施组件的内部日志
- drop:
expression: 'caller=.*(promtail|prometheus|grafana|loki|exporter).*\.go:[0-9]+'
drop_counter_reason: infra_go_internal_log
# 2. 丢弃基础设施组件日志prometheus/grafana/exporter等
- drop:
expression: '(component=|target=|scrape_pool=|instance=.*exporter)'
drop_counter_reason: infrastructure_component
# 3. 丢弃 Docker 服务发现和 API 错误日志
- drop:
expression: '(docker_discovery|Unable to refresh target groups|client version.*is too old|Minimum supported API version)'
drop_counter_reason: docker_api_error
# 4. 丢弃文件监控事件日志promtail 内部)
- drop:
expression: '(file watcher event|filetargetmanager|fsnotify)'
drop_counter_reason: file_watcher

View File

@@ -1,135 +0,0 @@
# chat-deploy 可观测性组件部署配置
# 用于向 itom-platform 可观测中心推送日志和指标
#
# 使用方法:
# 1. 复制 config.env.example 为 config.env 并修改配置
# 2. 启动服务docker compose --env-file config.env -f docker-compose-observability.yaml up -d
# 3. 如需启用指标采集docker compose --env-file config.env -f docker-compose-observability.yaml --profile metrics up -d
services:
# ==============================
# 日志采集Promtail
# 采集 Docker 容器日志并推送到 itom-platform 的 Loki
# ==============================
promtail:
image: "${PROMTAIL_IMAGE:-grafana/promtail:3.0.0}"
container_name: chat-deploy-promtail
restart: always
user: "0"
command: ["-config.file=/etc/promtail/config.yml", "-config.expand-env=true"]
# 禁用 promtail 自身的日志输出到 Docker避免日志循环
logging:
driver: "none"
environment:
- LOKI_URL=${LOKI_URL}
- OBS_AUTH_TOKEN=${OBS_AUTH_TOKEN}
- OBS_PROJECT=${OBS_PROJECT}
- OBS_SERVICE=${OBS_SERVICE}
- DOCKER_API_VERSION=${DOCKER_API_VERSION:-1.44}
volumes:
- /var/lib/docker/containers:/var/lib/docker/containers:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./config/promtail.yaml:/etc/promtail/config.yml:ro
networks:
- chat-deploy-obs
# ==============================
# 指标采集Prometheus Agent Remote Write
# 可选,需要 --profile metrics 启用
# ==============================
prometheus-agent:
profiles: ["metrics"]
image: prom/prometheus:latest
container_name: chat-deploy-prometheus-agent
restart: always
user: "0"
command:
- "--config.file=/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus"
environment:
- METRICS_REMOTE_WRITE_URL=${METRICS_REMOTE_WRITE_URL}
- METRICS_TARGETS=${METRICS_TARGETS}
- OBS_AUTH_ENABLE=${OBS_AUTH_ENABLE:-false}
- OBS_AUTH_TOKEN=${OBS_AUTH_TOKEN}
- OBS_PROJECT=${OBS_PROJECT}
- OBS_SERVICE=${OBS_SERVICE}
- OBS_SERVICE_NAME=${OBS_SERVICE_NAME}
- OBS_ENV=${OBS_ENV:-prod}
- REDIS_EXPORTER_TARGETS=${REDIS_EXPORTER_TARGETS}
- MONGODB_EXPORTER_TARGETS=${MONGODB_EXPORTER_TARGETS}
- NODE_EXPORTER_TARGETS=${NODE_EXPORTER_TARGETS}
- REDIS_EXPORTER_SERVICE=${REDIS_EXPORTER_SERVICE}
- MONGODB_EXPORTER_SERVICE=${MONGODB_EXPORTER_SERVICE}
- NODE_EXPORTER_SERVICE=${NODE_EXPORTER_SERVICE}
volumes:
- prometheus_agent_data:/prometheus
- ./config/prometheus-agent-entrypoint.sh:/etc/prometheus/entrypoint.sh:ro
entrypoint: ["/bin/sh", "/etc/prometheus/entrypoint.sh"]
networks:
- chat-deploy-obs
depends_on:
- mongodb-exporter
# ==============================
# MongoDB Exporter
# 采集 MongoDB 指标,需要 --profile metrics 启用
# ==============================
mongodb-exporter:
profiles: ["metrics"]
image: percona/mongodb_exporter:0.40.0
container_name: chat-deploy-mongodb-exporter
restart: always
command:
- "--mongodb.uri=${MONGODB_URI}"
- "--compatible-mode"
- "--collect-all"
environment:
- MONGODB_URI=${MONGODB_URI}
ports:
- "9216:9216"
networks:
- chat-deploy-obs
# ==============================
# Redis Exporter可选
# 采集 Redis 指标,需要 --profile metrics 启用
# ==============================
redis-exporter:
profiles: ["metrics"]
image: oliver006/redis_exporter:latest
container_name: chat-deploy-redis-exporter
restart: always
environment:
- REDIS_ADDR=${REDIS_ADDR}
- REDIS_PASSWORD=${REDIS_PASSWORD}
ports:
- "9121:9121"
networks:
- chat-deploy-obs
# ==============================
# Node Exporter可选
# 采集系统级指标CPU/Memory/Disk/Network
# 需要 --profile metrics 启用
# ==============================
node-exporter:
profiles: ["metrics"]
image: prom/node-exporter:latest
container_name: chat-deploy-node-exporter
restart: always
command:
- "--path.rootfs=/host"
- "--collector.filesystem.mount-points-exclude=^/(sys|proc|dev|host|etc)($$|/)"
volumes:
- /:/host:ro,rslave
ports:
- "9100:9100"
networks:
- chat-deploy-obs
networks:
chat-deploy-obs:
driver: bridge
volumes:
prometheus_agent_data: {}

View File

@@ -1,84 +0,0 @@
docs/.generated_docs
docs/guide/en-US/cmd/iam-apiserver.md
docs/guide/en-US/cmd/iam-authz-server.md
docs/guide/en-US/cmd/iam-pump.md
docs/guide/en-US/cmd/iam-watcher.md
docs/guide/en-US/cmd/openim/openim.md
docs/guide/en-US/cmd/openim/openim_color.md
docs/guide/en-US/cmd/openim/openim_completion.md
docs/guide/en-US/cmd/openim/openim_info.md
docs/guide/en-US/cmd/openim/openim_jwt.md
docs/guide/en-US/cmd/openim/openim_jwt_show.md
docs/guide/en-US/cmd/openim/openim_jwt_sign.md
docs/guide/en-US/cmd/openim/openim_jwt_verify.md
docs/guide/en-US/cmd/openim/openim_new.md
docs/guide/en-US/cmd/openim/openim_options.md
docs/guide/en-US/cmd/openim/openim_policy.md
docs/guide/en-US/cmd/openim/openim_policy_create.md
docs/guide/en-US/cmd/openim/openim_policy_delete.md
docs/guide/en-US/cmd/openim/openim_policy_get.md
docs/guide/en-US/cmd/openim/openim_policy_list.md
docs/guide/en-US/cmd/openim/openim_policy_update.md
docs/guide/en-US/cmd/openim/openim_secret.md
docs/guide/en-US/cmd/openim/openim_secret_create.md
docs/guide/en-US/cmd/openim/openim_secret_delete.md
docs/guide/en-US/cmd/openim/openim_secret_get.md
docs/guide/en-US/cmd/openim/openim_secret_list.md
docs/guide/en-US/cmd/openim/openim_secret_update.md
docs/guide/en-US/cmd/openim/openim_set.md
docs/guide/en-US/cmd/openim/openim-rpc-user.md
docs/guide/en-US/cmd/openim/openim-rpc-user_create.md
docs/guide/en-US/cmd/openim/openim-rpc-user_delete.md
docs/guide/en-US/cmd/openim/openim-rpc-user_get.md
docs/guide/en-US/cmd/openim/openim-rpc-user_list.md
docs/guide/en-US/cmd/openim/openim-rpc-user_update.md
docs/guide/en-US/cmd/openim/openim_validate.md
docs/guide/en-US/cmd/openim/openim_version.md
docs/guide/en-US/yaml/openim/openim.yaml
docs/guide/en-US/yaml/openim/openim_color.yaml
docs/guide/en-US/yaml/openim/openim_completion.yaml
docs/guide/en-US/yaml/openim/openim_info.yaml
docs/guide/en-US/yaml/openim/openim_jwt.yaml
docs/guide/en-US/yaml/openim/openim_new.yaml
docs/guide/en-US/yaml/openim/openim_options.yaml
docs/guide/en-US/yaml/openim/openim_policy.yaml
docs/guide/en-US/yaml/openim/openim_secret.yaml
docs/guide/en-US/yaml/openim/openim_set.yaml
docs/guide/en-US/yaml/openim/openim-rpc-user.yaml
docs/guide/en-US/yaml/openim/openim_validate.yaml
docs/guide/en-US/yaml/openim/openim_version.yaml
docs/man/man1/iam-apiserver.1
docs/man/man1/iam-authz-server.1
docs/man/man1/iam-pump.1
docs/man/man1/iam-watcher.1
docs/man/man1/openim-color.1
docs/man/man1/openim-completion.1
docs/man/man1/openim-info.1
docs/man/man1/openim-jwt-show.1
docs/man/man1/openim-jwt-sign.1
docs/man/man1/openim-jwt-verify.1
docs/man/man1/openim-jwt.1
docs/man/man1/openim-new.1
docs/man/man1/openim-options.1
docs/man/man1/openim-policy-create.1
docs/man/man1/openim-policy-delete.1
docs/man/man1/openim-policy-get.1
docs/man/man1/openim-policy-list.1
docs/man/man1/openim-policy-update.1
docs/man/man1/openim-policy.1
docs/man/man1/openim-secret-create.1
docs/man/man1/openim-secret-delete.1
docs/man/man1/openim-secret-get.1
docs/man/man1/openim-secret-list.1
docs/man/man1/openim-secret-update.1
docs/man/man1/openim-secret.1
docs/man/man1/openim-set.1
docs/man/man1/openim-user-create.1
docs/man/man1/openim-user-delete.1
docs/man/man1/openim-user-get.1
docs/man/man1/openim-user-list.1
docs/man/man1/openim-user-update.1
docs/man/man1/openim-user.1
docs/man/man1/openim-validate.1
docs/man/man1/openim-version.1
docs/man/man1/openim.1

View File

@@ -1,340 +0,0 @@
# 定时任务 API 接口文档
## 基础信息
- **基础路径**: `/scheduled_task`
- **认证方式**: 所有接口都需要在请求头中携带 `token`(通过 `mw.CheckToken` 中间件验证)
- **请求方法**: 所有接口均为 `POST`
## 公共数据结构
### ScheduledTaskMessage消息内容
```json
{
"type": 1, // 消息类型1-文本2-图片3-视频
"content": "string", // 消息内容文本内容、图片URL、视频URL等
"thumbnail": "string", // 缩略图URL用于图片和视频可选
"duration": 0, // 时长(秒,用于视频,可选)
"fileSize": 0 // 文件大小(字节,用于图片和视频,可选)
}
```
### ScheduledTaskInfo定时任务信息
```json
{
"id": "string", // 任务ID
"userID": "string", // 用户ID
"name": "string", // 任务名称
"cronExpression": "string", // Crontab表达式分 时 日 月 周(例如:"0 9 * * *"
"messages": [ // 消息列表(支持多条消息一起发送)
{
"type": 1,
"content": "string",
"thumbnail": "string",
"duration": 0,
"fileSize": 0
}
],
"recvIDs": ["string"], // 接收者ID列表单聊可以多个
"groupIDs": ["string"], // 群组ID列表群聊可以多个
"status": 1, // 状态0-已禁用1-已启用
"createTime": 1234567890123, // 创建时间(毫秒时间戳)
"updateTime": 1234567890123 // 更新时间(毫秒时间戳)
}
```
### RequestPagination分页信息
```json
{
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
```
## Crontab 表达式说明
格式:`分 时 日 月 周`
- **分**: 0-59
- **时**: 0-23
- **日**: 1-31
- **月**: 1-12
- **周**: 0-70和7都表示周日
### 示例
- `"0 9 * * *"` - 每天9点执行
- `"*/5 * * * *"` - 每5分钟执行
- `"0 0 * * 1"` - 每周一0点执行
- `"0 12 * * 1-5"` - 周一到周五每天12点执行
- `"0 0 1 * *"` - 每月1号0点执行
---
## 1. 创建定时任务
**接口地址**: `POST /scheduled_task/create`
**请求参数**:
```json
{
"name": "string", // 必填:任务名称
"cronExpression": "string", // 必填Crontab表达式
"messages": [ // 必填:消息列表(至少一条)
{
"type": 1, // 必填消息类型1-文本2-图片3-视频
"content": "string", // 必填:消息内容
"thumbnail": "string", // 可选缩略图URL
"duration": 0, // 可选:时长(秒)
"fileSize": 0 // 可选:文件大小(字节)
}
],
"recvIDs": ["string"], // 可选接收者ID列表单聊可以多个
"groupIDs": ["string"], // 可选群组ID列表群聊可以多个
"status": 1 // 可选状态0-已禁用1-已启用默认为1
}
```
**注意**: `recvIDs``groupIDs` 至少需要提供一个,不能同时为空。
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"taskID": "string" // 创建的任务ID
}
}
```
**请求示例**:
```json
{
"name": "每日问候",
"cronExpression": "0 9 * * *",
"messages": [
{
"type": 1,
"content": "早上好!"
},
{
"type": 2,
"content": "https://example.com/image.jpg",
"thumbnail": "https://example.com/thumb.jpg",
"fileSize": 102400
}
],
"recvIDs": ["user1", "user2"],
"groupIDs": ["group1"],
"status": 1
}
```
---
## 2. 获取定时任务详情
**接口地址**: `POST /scheduled_task/get`
**请求参数**:
```json
{
"taskID": "string" // 必填任务ID
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"task": { // 定时任务信息
"id": "string",
"userID": "string",
"name": "string",
"cronExpression": "string",
"messages": [
{
"type": 1,
"content": "string",
"thumbnail": "string",
"duration": 0,
"fileSize": 0
}
],
"recvIDs": ["string"],
"groupIDs": ["string"],
"status": 1,
"createTime": 1234567890123,
"updateTime": 1234567890123
}
}
}
```
---
## 3. 获取定时任务列表
**接口地址**: `POST /scheduled_task/list`
**请求参数**:
```json
{
"pagination": { // 必填:分页信息
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 100, // 总数
"tasks": [ // 任务列表
{
"id": "string",
"userID": "string",
"name": "string",
"cronExpression": "string",
"messages": [
{
"type": 1,
"content": "string",
"thumbnail": "string",
"duration": 0,
"fileSize": 0
}
],
"recvIDs": ["string"],
"groupIDs": ["string"],
"status": 1,
"createTime": 1234567890123,
"updateTime": 1234567890123
}
]
}
}
```
---
## 4. 更新定时任务
**接口地址**: `POST /scheduled_task/update`
**请求参数**:
```json
{
"taskID": "string", // 必填任务ID
"name": "string", // 可选:任务名称
"cronExpression": "string", // 可选Crontab表达式
"messages": [ // 可选:消息列表
{
"type": 1,
"content": "string",
"thumbnail": "string",
"duration": 0,
"fileSize": 0
}
],
"recvIDs": ["string"], // 可选接收者ID列表
"groupIDs": ["string"], // 可选群组ID列表
"status": 1 // 可选状态0-已禁用1-已启用
}
```
**注意**:
- 所有字段都是可选的,只更新提供的字段
- 如果更新 `recvIDs``groupIDs`,确保至少有一个不为空
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
```json
{
"taskID": "task123",
"name": "更新后的任务名称",
"status": 0
}
```
---
## 5. 删除定时任务
**接口地址**: `POST /scheduled_task/delete`
**请求参数**:
```json
{
"taskIDs": ["string"] // 必填任务ID列表支持批量删除
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
```json
{
"taskIDs": ["task1", "task2", "task3"]
}
```
---
## 错误码说明
- `0`: 成功
- 其他错误码请参考系统错误码定义
## 注意事项
1. 所有接口都需要在请求头中携带有效的 `token`
2. 用户只能操作自己创建的定时任务
3. `recvIDs``groupIDs` 可以同时提供,表示同时发送到多个单聊和群聊
4. `messages` 数组支持多条消息,会按顺序发送
5. Crontab 表达式需要符合标准格式,客户端负责解析和执行
6. 服务端只负责存储配置,不执行定时任务

View File

@@ -1,739 +0,0 @@
# 系统配置管理 API 接口文档
## 基础信息
- **基础路径**: `/system_config`
- **认证方式**: 所有接口都需要在请求头中携带 `token`(通过 `mw.CheckAdmin` 中间件验证,需要管理员权限)
- **请求方法**: 所有接口均为 `POST`
## 响应格式说明
所有接口的响应格式统一为:
```json
{
"errCode": 0, // 错误码0 表示成功
"errMsg": "", // 错误消息
"errDlt": "", // 错误详情
"data": {} // 响应数据
}
```
**注意**: 为了兼容 Ant Design Pro Table前端在 `request` 函数中需要将响应格式转换为 ProTable 期望的格式:
```typescript
const request = async (params) => {
const response = await request('/system_config/list', {
method: 'POST',
data: params,
});
// 将 errCode 格式转换为 ProTable 期望的格式
return {
success: response.errCode === 0,
data: response.data?.list || [],
total: response.data?.total || 0,
};
};
```
## 公共数据结构
### SystemConfigInfo系统配置信息
```json
{
"key": "string", // 配置键(唯一标识)
"title": "string", // 配置标题
"value": "string", // 配置值字符串形式存储根据ValueType解析
"valueType": 1, // 配置值类型1-字符串2-数字3-布尔4-JSON
"description": "string", // 配置描述
"enabled": true, // 是否启用(用于开关类配置)
"showInApp": false, // 是否在APP端展示默认为false
"createTime": 1234567890123, // 创建时间(毫秒时间戳)
"updateTime": 1234567890123 // 更新时间(毫秒时间戳)
}
```
### RequestPagination分页信息
```json
{
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
```
### StringValue可选字符串值
```json
{
"value": "string" // 字符串值,如果为 null 或未设置则表示不更新该字段
}
```
### Int32Value可选整数值
```json
{
"value": 1 // 整数值,如果为 null 或未设置则表示不更新该字段
}
```
### BoolValue可选布尔值
```json
{
"value": true // 布尔值,如果为 null 或未设置则表示不更新该字段
}
```
## 配置值类型说明
- **1 - 字符串类型 (ConfigValueTypeString)**: 普通文本字符串
- **2 - 数字类型 (ConfigValueTypeNumber)**: 数值字符串,需要转换为数字使用
- **3 - 布尔类型 (ConfigValueTypeBool)**: 布尔值字符串("true"/"false"),需要转换为布尔值使用
- **4 - JSON类型 (ConfigValueTypeJSON)**: JSON 格式字符串,需要解析为 JSON 对象使用
## 常用配置键
- `wallet.enabled`: 是否开启钱包功能(布尔类型)
- `register.phone.verify_code.enabled`: 手机号注册验证码功能是否开启(布尔类型)
---
## 1. 创建系统配置
**接口地址**: `POST /system_config/create`
**请求参数**:
```json
{
"key": "string", // 必填:配置键(唯一标识)
"title": "string", // 可选:配置标题
"value": "string|number|boolean|object", // 可选:配置值(支持多种类型,会根据 valueType 自动转换为字符串存储)
"valueType": 1, // 可选配置值类型1-字符串2-数字3-布尔4-JSON默认为1
"description": "string", // 可选:配置描述
"enabled": true, // 可选是否启用默认为true
"showInApp": false // 可选是否在APP端展示默认为false
}
```
**注意**: `value` 字段支持多种类型传参,系统会根据 `valueType` 自动转换并验证:
- **字符串类型 (valueType=1)**: 可以传字符串,如 `"value": "hello"`
- **数字类型 (valueType=2)**: 可以传数字,如 `"value": 100``"value": 3.14`,会自动转换为字符串存储
- **布尔类型 (valueType=3)**: 可以传布尔值,如 `"value": true``"value": false`,会自动转换为 `"true"``"false"` 字符串存储
- **JSON类型 (valueType=4)**: 可以传 JSON 对象,如 `"value": {"key": "value"}`,会自动序列化为 JSON 字符串存储
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
**示例1: 布尔类型配置(推荐直接传布尔值)**
```json
{
"key": "wallet.enabled",
"title": "钱包功能开关",
"value": true, // ✅ 直接传布尔值,不需要传字符串 "true"
"valueType": 3,
"description": "控制是否开启钱包功能",
"enabled": true,
"showInApp": true // 在APP端展示此配置
}
```
**示例2: 数字类型配置(推荐直接传数字)**
```json
{
"key": "wallet.min_withdraw_amount",
"title": "最小提现金额",
"value": 100, // ✅ 直接传数字,会自动转换为字符串 "100" 存储
"valueType": 2,
"description": "用户提现的最小金额(单位:分)",
"enabled": true
}
```
**示例3: JSON类型配置推荐直接传对象**
```json
{
"key": "wallet.withdraw_config",
"title": "提现配置",
"value": { // ✅ 直接传 JSON 对象,会自动序列化为字符串存储
"dailyLimit": 10000,
"monthlyLimit": 100000,
"feeRate": 0.01
},
"valueType": 4,
"description": "提现相关配置JSON格式",
"enabled": true
}
```
**示例4: 字符串类型配置**
```json
{
"key": "wallet.welcome_message",
"title": "欢迎消息",
"value": "欢迎使用钱包功能", // ✅ 字符串类型直接传字符串
"valueType": 1,
"description": "钱包功能欢迎消息",
"enabled": true
}
```
**错误码**:
- `ErrArgs`: 配置键为空
- `ErrDuplicateKey`: 配置键已存在
---
## 2. 获取系统配置详情
**接口地址**: `POST /system_config/get`
**请求参数**:
```json
{
"key": "string" // 必填:配置键
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"config": { // 系统配置信息
"key": "string",
"title": "string",
"value": "string",
"valueType": 1,
"description": "string",
"enabled": true,
"createTime": 1234567890123,
"updateTime": 1234567890123
}
}
}
```
**请求示例**:
```json
{
"key": "wallet.enabled"
}
```
**错误码**:
- `ErrNotFound`: 配置不存在
---
## 3. 获取所有系统配置(分页)
**接口地址**: `POST /system_config/list`
**请求参数**:
```json
{
"pagination": { // 必填:分页信息
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 100, // 总数
"list": [ // 配置列表Ant Design Pro 标准格式)
{
"key": "string",
"title": "string",
"value": "string|number|boolean|object", // 根据 valueType 自动转换为对应类型
"valueType": 1,
"description": "string",
"enabled": true,
"createTime": 1234567890123,
"updateTime": 1234567890123
}
]
}
}
```
**注意**: 返回的 `value` 字段会根据 `valueType` 自动转换为对应类型(详见"2. 获取系统配置详情"的说明)。
**请求示例**:
```json
{
"pagination": {
"pageNumber": 1,
"showNumber": 20
}
}
```
---
## 4. 更新系统配置
**接口地址**: `POST /system_config/update`
**请求参数**:
```json
{
"key": "string", // 必填:配置键
"title": "string", // 可选:配置标题(如果为 null 则不更新)
"value": "string|number|boolean|object", // 可选:配置值(支持多种类型,会根据 valueType 自动转换)
"valueType": 1, // 可选:配置值类型(如果为 null 则不更新)
"description": "string", // 可选:配置描述(如果为 null 则不更新)
"enabled": true, // 可选:是否启用(如果为 null 则不更新)
"showInApp": false // 可选是否在APP端展示如果为 null 则不更新)
}
```
**注意**:
- `value` 字段支持多种类型传参,系统会根据当前的 `valueType`(或新设置的 `valueType`)自动转换并验证
- 如果同时更新 `value``valueType`,系统会验证新值是否符合新的类型要求
- 如果只更新 `valueType`,系统会验证当前值是否符合新的类型要求
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
**示例1: 更新布尔类型配置的值**
```json
{
"key": "wallet.enabled",
"value": false, // ✅ 直接传布尔值
"description": "已关闭钱包功能"
}
```
**示例2: 更新数字类型配置的值**
```json
{
"key": "wallet.min_withdraw_amount",
"value": 200 // ✅ 直接传数字
}
```
**示例3: 同时更新值和类型**
```json
{
"key": "wallet.min_amount",
"value": 150, // ✅ 新值
"valueType": 2 // 更新为数字类型
}
```
**注意**: 只有提供的字段才会被更新,未提供的字段保持不变。
**错误码**:
- `ErrNotFound`: 配置不存在
---
## 5. 更新系统配置值
**接口地址**: `POST /system_config/update_value`
**请求参数**:
```json
{
"key": "string", // 必填:配置键
"value": "string" // 必填:新的配置值
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
**示例1: 更新布尔类型配置**
```json
{
"key": "wallet.enabled",
"value": false // ✅ 直接传布尔值,不需要传字符串 "false"
}
```
**示例2: 更新数字类型配置**
```json
{
"key": "wallet.min_withdraw_amount",
"value": 200 // ✅ 直接传数字
}
```
**示例3: 更新 JSON 类型配置**
```json
{
"key": "wallet.withdraw_config",
"value": { // ✅ 直接传 JSON 对象
"dailyLimit": 20000,
"monthlyLimit": 200000
}
}
```
**错误码**:
- `ErrNotFound`: 配置不存在
---
## 6. 更新系统配置启用状态
**接口地址**: `POST /system_config/update_enabled`
**请求参数**:
```json
{
"key": "string", // 必填:配置键
"enabled": true // 必填:是否启用
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
```json
{
"key": "wallet.enabled",
"enabled": false
}
```
**错误码**:
- `ErrNotFound`: 配置不存在
---
## 7. 删除系统配置
**接口地址**: `POST /system_config/delete`
**请求参数**:
```json
{
"keys": ["string"] // 必填:配置键列表(支持批量删除)
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**请求示例**:
```json
{
"keys": ["wallet.enabled", "register.phone.verify_code.enabled"]
}
```
---
## 8. 获取所有已启用的配置
**接口地址**: `POST /system_config/get_enabled`
**请求参数**:
```json
{}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"list": [ // 已启用的配置列表Ant Design Pro 标准格式)
{
"key": "string",
"title": "string",
"value": "string|number|boolean|object", // 根据 valueType 自动转换为对应类型
"valueType": 1,
"description": "string",
"enabled": true,
"createTime": 1234567890123,
"updateTime": 1234567890123
}
]
}
}
```
**注意**: 返回的 `value` 字段会根据 `valueType` 自动转换为对应类型(详见"2. 获取系统配置详情"的说明)。
**请求示例**:
```json
{}
```
**说明**: 此接口用于获取所有已启用enabled=true的配置通常用于前端展示或业务逻辑判断。
---
## 使用场景示例
### 场景1: 开启/关闭钱包功能
1. **创建钱包功能配置**(推荐直接传布尔值):
```json
POST /system_config/create
{
"key": "wallet.enabled",
"title": "钱包功能开关",
"value": true, // ✅ 直接传布尔值,更直观
"valueType": 3,
"description": "控制是否开启钱包功能",
"enabled": true
}
```
2. **关闭钱包功能**(两种方式):
方式1: 更新 enabled 字段
```json
POST /system_config/update_enabled
{
"key": "wallet.enabled",
"enabled": false
}
```
方式2: 更新 value 字段
```json
POST /system_config/update_value
{
"key": "wallet.enabled",
"value": false // ✅ 直接传布尔值
}
```
3. **业务代码中检查钱包功能是否开启**:
```go
config, err := db.GetSystemConfig(ctx, "wallet.enabled")
if err != nil || !config.Enabled {
return errors.New("钱包功能未开启")
}
```
### 场景2: 配置手机号注册验证码功能
1. **创建验证码功能配置**(推荐直接传布尔值):
```json
POST /system_config/create
{
"key": "register.phone.verify_code.enabled",
"title": "手机号注册验证码功能",
"value": true, // ✅ 直接传布尔值
"valueType": 3,
"description": "控制手机号注册时是否需要验证码",
"enabled": true
}
```
### 场景3: 配置数字类型的参数(推荐直接传数字)
**创建配置**:
```json
POST /system_config/create
{
"key": "wallet.min_withdraw_amount",
"title": "最小提现金额",
"value": 100, // ✅ 直接传数字,会自动转换为字符串存储
"valueType": 2,
"description": "用户提现的最小金额(单位:分)",
"enabled": true
}
```
**获取配置**(返回时会自动转换为数字):
```json
GET /system_config/get
{
"key": "wallet.min_withdraw_amount"
}
// 响应
{
"data": {
"config": {
"key": "wallet.min_withdraw_amount",
"value": 100, // ✅ 返回数字类型,不是字符串 "100"
"valueType": 2
}
}
}
```
**后端使用**(如果直接使用数据库模型,需要手动转换):
```go
config, _ := db.GetSystemConfig(ctx, "wallet.min_withdraw_amount")
minAmount, _ := strconv.ParseInt(config.Value, 10, 64)
```
### 场景4: 配置 JSON 类型的复杂参数(推荐直接传对象)
**创建配置**:
```json
POST /system_config/create
{
"key": "wallet.withdraw_config",
"title": "提现配置",
"value": { // ✅ 直接传 JSON 对象,会自动序列化为字符串存储
"dailyLimit": 10000,
"monthlyLimit": 100000,
"feeRate": 0.01
},
"valueType": 4,
"description": "提现相关配置JSON格式",
"enabled": true
}
```
**获取配置**(返回时会自动解析为对象):
```json
GET /system_config/get
{
"key": "wallet.withdraw_config"
}
// 响应
{
"data": {
"config": {
"key": "wallet.withdraw_config",
"value": { // ✅ 返回 JSON 对象,不是字符串
"dailyLimit": 10000,
"monthlyLimit": 100000,
"feeRate": 0.01
},
"valueType": 4
}
}
}
```
**后端使用**(如果直接使用数据库模型,需要手动解析):
```go
config, _ := db.GetSystemConfig(ctx, "wallet.withdraw_config")
var withdrawConfig map[string]interface{}
json.Unmarshal([]byte(config.Value), &withdrawConfig)
```
---
## 错误码说明
- `ErrArgs`: 参数错误(如必填字段为空)
- `ErrNotFound`: 资源不存在(如配置键不存在)
- `ErrDuplicateKey`: 重复键(如创建配置时键已存在)
- `ErrNoPermission`: 无权限(非管理员用户)
---
## 注意事项
1. **配置键唯一性**: 配置键key在整个系统中必须唯一不能重复。
2. **配置值类型转换**:
- **传参时**: `value` 字段支持多种类型字符串、数字、布尔、JSON对象系统会根据 `valueType` 自动转换为字符串存储
- **返回时**: `value` 字段会根据 `valueType` 自动转换为对应类型返回数字返回数字布尔返回布尔JSON返回对象
- **数据库存储**: 所有值都以字符串形式存储在数据库中
- **后端使用**: 如果直接使用数据库模型,需要根据 `valueType` 手动转换:
- 字符串类型:直接使用
- 数字类型:使用 `strconv.ParseInt``strconv.ParseFloat` 转换
- 布尔类型:使用 `strconv.ParseBool` 转换
- JSON类型使用 `json.Unmarshal` 解析
3. **类型验证**: 系统会在创建和更新时自动验证 `value` 是否符合 `valueType` 的要求:
- 数字类型:必须是有效的数字
- 布尔类型:必须是 `true``false`
- JSON类型必须是有效的 JSON
4. **可选字段更新**: 在 `UpdateSystemConfig` 接口中,如果字段为 `null` 或未设置,则不会更新该字段。
5. **启用状态**: `enabled` 字段用于控制配置是否生效。即使配置存在,如果 `enabled``false`,业务代码也应该认为该功能未开启。
6. **APP端展示**: `showInApp` 字段用于控制配置是否在APP端展示。只有 `showInApp``true` 的配置才会在APP端显示给用户。此字段默认为 `false`
7. **推荐用法**:
- 创建/更新布尔类型配置时,推荐直接传布尔值:`"value": true` 而不是 `"value": "true"`
- 创建/更新数字类型配置时,推荐直接传数字:`"value": 100` 而不是 `"value": "100"`
- 创建/更新 JSON 类型配置时,推荐直接传对象:`"value": {"key": "value"}` 而不是 `"value": "{\"key\":\"value\"}"`
5. **管理员权限**: 所有接口都需要管理员权限,普通用户无法访问。
6. **请求头**: 所有请求都需要在请求头中携带 `token``operationid`

View File

@@ -1,453 +0,0 @@
# 钱包相关接口汇总
## 基础信息
- **基础路径**: `/wallet`
- **认证方式**: 所有接口都需要在请求头中携带 `token`(通过 `mw.CheckToken` 中间件验证)
- **请求方法**: 所有接口均为 `POST`
- **Content-Type**: `application/json`
---
## 接口列表
### 1. 获取钱包余额
**接口地址**: `POST /wallet/balance`
**请求参数**: 无
**响应参数**:
```json
{
"errCode": 0,
"data": {
"balance": 10000 // 余额(单位:分)
}
}
```
---
### 2. 获取钱包详细信息
**接口地址**: `POST /wallet/info`
**请求参数**: 无
**响应参数**:
```json
{
"errCode": 0,
"data": {
"balance": 10000, // 余额(单位:分)
"withdrawAccount": "string", // 提现账号
"withdrawAccountType": 1, // 提现账号类型1-支付宝2-微信3-银行卡
"withdrawReceiveAccount": "string", // 提现收款账号
"hasPaymentPassword": true, // 是否已设置支付密码
"realNameAuth": { // 实名认证信息(可选)
"idCard": "string",
"idCardPhotoFront": "string",
"idCardPhotoBack": "string",
"name": "string"
}
}
}
```
---
### 3. 获取余额明细
**接口地址**: `POST /wallet/balance_records`
**请求参数**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| pagination | object | 是 | 分页参数 |
| pagination.pageNumber | int32 | 是 | 页码从1开始 |
| pagination.showNumber | int32 | 是 | 每页显示数量 |
| type | int32 | 否 | 变动类型可选0表示查询所有类型1-充值2-提现/提款3-消费4-退款5-奖励6-后台充值7-发红包8-抢红包99-其他 |
**响应参数**:
```json
{
"errCode": 0,
"data": {
"total": 100,
"records": [
{
"id": "string",
"userID": "string",
"amount": 10000,
"type": 1,
"beforeBalance": 0,
"afterBalance": 10000,
"orderID": "string",
"transactionID": "string",
"redPacketID": "string",
"remark": "string",
"createTime": 1234567890123
}
]
}
}
```
**变动类型说明**:
| 类型值 | 类型名称 | 说明 |
|--------|---------|------|
| 1 | 充值 | 用户充值 |
| 2 | 提现/提款 | 提现申请 |
| 3 | 消费 | 消费支出 |
| 4 | 退款 | 退款收入 |
| 5 | 奖励 | 奖励收入 |
| 6 | 后台充值 | 管理员后台充值 |
| 7 | 发红包 | 发红包(减少余额) |
| 8 | 抢红包 | 抢红包(增加余额) |
| 99 | 其他 | 其他类型 |
**业务逻辑**:
1. 从 token 中获取当前用户ID
2. 如果指定了 type按类型查询否则查询所有类型
3. 按创建时间倒序排列
4. 支持分页查询
**请求示例**:
查询所有记录:
```json
{
"pagination": {
"pageNumber": 1,
"showNumber": 10
}
}
```
按类型查询(只查询充值记录):
```json
{
"pagination": {
"pageNumber": 1,
"showNumber": 10
},
"type": 1
}
```
---
### 4. 设置支付密码
**接口地址**: `POST /wallet/payment_password/set`
**请求参数**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| newPassword | string | 是 | 新支付密码 |
| oldPassword | string | 条件必填 | 旧支付密码(修改时必填,首次设置时不需要) |
**响应参数**:
```json
{
"errCode": 0,
"data": {}
}
```
**业务逻辑**:
1. **首次设置支付密码**:
- 钱包不存在或未设置支付密码
- 不需要提供 `oldPassword`
- 如果提供了 `oldPassword`,会返回错误
- 如果钱包不存在,会自动创建钱包并设置支付密码
2. **修改支付密码**:
- 已设置支付密码
- 必须提供 `oldPassword`
- 验证旧密码是否正确
- 验证新密码不能与旧密码相同
**错误码说明**:
| 错误信息 | 说明 |
|---------|------|
| 新支付密码不能为空 | newPassword 为空 |
| 修改支付密码需要提供旧密码 | 已设置密码但未提供 oldPassword |
| 首次设置支付密码不需要提供旧密码 | 未设置密码但提供了 oldPassword |
| 旧支付密码错误 | oldPassword 验证失败 |
| 新密码不能与旧密码相同 | newPassword == oldPassword |
**请求示例**:
首次设置:
```json
{
"newPassword": "123456"
}
```
修改密码:
```json
{
"newPassword": "654321",
"oldPassword": "123456"
}
```
---
### 4. 设置提现账号
**接口地址**: `POST /wallet/withdraw_account/set`
**请求参数**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| account | string | 是 | 提现账号 |
| accountType | int32 | 是 | 账号类型1-支付宝2-微信3-银行卡 |
**响应参数**:
```json
{
"errCode": 0,
"data": {}
}
```
**账号类型说明**:
| 类型值 | 类型名称 | 说明 |
|--------|---------|------|
| 1 | 支付宝 | 支付宝账号 |
| 2 | 微信 | 微信账号 |
| 3 | 银行卡 | 银行卡号 |
**错误码说明**:
| 错误信息 | 说明 |
|---------|------|
| 提现账号不能为空 | account 为空 |
| 账号类型无效必须是1-支付宝2-微信3-银行卡 | accountType 不在有效范围内 |
**请求示例**:
设置支付宝账号:
```json
{
"account": "13800138000",
"accountType": 1
}
```
设置银行卡:
```json
{
"account": "6222021234567890123",
"accountType": 3
}
```
---
### 5. 申请提现
**接口地址**: `POST /wallet/withdraw/apply`
**请求参数**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| amount | int64 | 是 | 提现金额(单位:分,必须 > 0 |
| paymentPassword | string | 是 | 支付密码 |
| ip | string | 否 | 申请IP |
| deviceID | string | 否 | 设备ID |
| platform | string | 否 | 平台iOS、Android、Web等 |
| deviceModel | string | 否 | 设备型号 |
| deviceBrand | string | 否 | 设备品牌 |
| osVersion | string | 否 | 操作系统版本 |
| appVersion | string | 否 | 应用版本 |
**注意**:
- 提现账号从用户钱包中自动获取,不需要在请求中提供
- 如果钱包中未设置提现账号,会返回错误提示"请先在钱包中设置提现账号"
- 备注remark由后台管理员在审核时填写用户申请时不需要提供
**响应参数**:
```json
{
"errCode": 0,
"data": {
"applicationID": "uuid-string" // 申请ID
}
}
```
**错误码说明**:
| 错误信息 | 说明 |
|---------|------|
| 提现金额必须大于0 | amount <= 0 |
| 支付密码不能为空 | paymentPassword 为空 |
| 钱包不存在,无法申请提现 | 用户钱包不存在 |
| 请先设置支付密码 | 用户未设置支付密码 |
| 支付密码错误 | 支付密码验证失败 |
| 余额不足,无法申请提现 | 钱包余额 < 提现金额 |
| 请先在钱包中设置提现账号 | 钱包中未设置提现账号 |
---
### 6. 获取提现申请列表
**接口地址**: `POST /wallet/withdraw/list`
**请求参数**:
| 字段名 | 类型 | 必填 | 说明 |
|--------|------|------|------|
| pagination | object | | 分页参数 |
| pagination.pageNumber | int32 | | 页码从1开始 |
| pagination.showNumber | int32 | | 每页显示数量 |
**响应参数**:
```json
{
"errCode": 0,
"data": {
"total": 100,
"applications": [
{
"id": "string",
"userID": "string",
"amount": 10000,
"withdrawAccount": "string",
"withdrawAccountType": 1,
"status": 1,
"auditorID": "string",
"auditTime": 1234567890123,
"auditRemark": "string",
"ip": "string",
"deviceID": "string",
"platform": "string",
"deviceModel": "string",
"deviceBrand": "string",
"osVersion": "string",
"appVersion": "string",
"remark": "string",
"createTime": 1234567890123,
"updateTime": 1234567890123
}
]
}
}
```
**状态值说明**:
| 状态值 | 状态名称 | 说明 |
|--------|---------|------|
| 1 | 待审核 | 用户已提交等待管理员审核 |
| 2 | 已通过 | 管理员审核通过 |
| 3 | 已拒绝 | 管理员审核拒绝 |
| 4 | 处理中 | 审核通过后正在处理提现 |
| 5 | 已完成 | 提现已完成 |
---
## RPC 接口对应关系
| HTTP 接口 | RPC 方法 | 请求消息 | 响应消息 |
|----------|---------|---------|---------|
| `/wallet/balance` | `GetWalletBalance` | `GetWalletBalanceReq` | `GetWalletBalanceResp` |
| `/wallet/info` | `GetWalletInfo` | `GetWalletInfoReq` | `GetWalletInfoResp` |
| `/wallet/balance_records` | `GetWalletBalanceRecords` | `GetWalletBalanceRecordsReq` | `GetWalletBalanceRecordsResp` |
| `/wallet/payment_password/set` | `SetPaymentPassword` | `SetPaymentPasswordReq` | `SetPaymentPasswordResp` |
| `/wallet/withdraw_account/set` | `SetWithdrawAccount` | `SetWithdrawAccountReq` | `SetWithdrawAccountResp` |
| `/wallet/withdraw/apply` | `CreateWithdrawApplication` | `CreateWithdrawApplicationReq` | `CreateWithdrawApplicationResp` |
| `/wallet/withdraw/list` | `GetWithdrawApplications` | `GetWithdrawApplicationsReq` | `GetWithdrawApplicationsResp` |
---
## 使用流程示例
### 1. 首次使用钱包
```bash
# 1. 获取钱包信息(检查是否已设置支付密码)
POST /wallet/info
# 2. 如果 hasPaymentPassword 为 false设置支付密码
POST /wallet/payment_password/set
{
"newPassword": "123456"
}
# 3. 设置提现账号
POST /wallet/withdraw_account/set
{
"account": "13800138000",
"accountType": 1 // 1-支付宝2-微信3-银行卡
}
# 4. 申请提现(提现账号从钱包中自动获取)
POST /wallet/withdraw/apply
{
"amount": 10000,
"paymentPassword": "123456"
}
```
### 2. 修改支付密码
```bash
# 修改支付密码
POST /wallet/payment_password/set
{
"newPassword": "654321",
"oldPassword": "123456"
}
```
### 3. 查看提现记录
```bash
# 获取提现申请列表
POST /wallet/withdraw/list
{
"pagination": {
"pageNumber": 1,
"showNumber": 10
}
}
```
---
## 注意事项
1. **支付密码设置**:
- 首次设置不需要旧密码
- 修改时必须提供正确的旧密码
- 新密码不能与旧密码相同
2. **提现申请**:
- 必须已设置支付密码
- 必须验证支付密码
- 余额必须足够
- 需要设置提现账号
3. **权限控制**:
- 所有接口都需要 token 认证
- 用户只能操作自己的钱包
- 用户只能查看自己的提现申请列表
4. **数据单位**:
- 所有金额单位均为""1元 = 100分
- 时间戳单位为毫秒

View File

@@ -1,486 +0,0 @@
# 提现管理后台接口文档
## 接口列表
| 接口地址 | 请求方法 | 说明 |
|---------|---------|------|
| `/withdraw/get` | POST | 获取提现申请详情 |
| `/withdraw/list` | POST | 获取提现申请列表(支持按状态筛选) |
| `/withdraw/user_list` | POST | 获取用户的提现申请列表 |
| `/withdraw/audit` | POST | 审核提现申请 |
**注意:**
- 所有接口都需要管理员权限(需要 `mw.CheckAdmin` 中间件验证)
- 这些接口操作的是 `withdraw_applications` 集合(用户申请的提现)
- 用户在前端申请提现后,后台管理员通过这些接口进行审核
---
## 1. 获取提现申请详情
**接口地址**: `/withdraw/get`
**请求方法**: `POST`
**请求参数**:
```json
{
"withdrawID": "string" // 提现申请ID必填
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"withdraw": {
"id": "string", // 提现申请ID
"userID": "string", // 用户ID
"amount": 10000, // 提现金额(单位:分)
"withdrawAccount": "string", // 提现账号
"status": 1, // 申请状态1-待审核2-已通过3-已拒绝4-处理中5-已完成
"auditorID": "string", // 审核人ID管理员ID
"auditTime": 1699000000000, // 审核时间(毫秒时间戳)
"auditRemark": "string", // 审核备注
"ip": "string", // 申请IP
"deviceID": "string", // 设备ID
"platform": "string", // 平台iOS、Android、Web等
"deviceModel": "string", // 设备型号
"deviceBrand": "string", // 设备品牌
"osVersion": "string", // 操作系统版本
"appVersion": "string", // 应用版本
"createTime": 1699000000000, // 创建时间(毫秒时间戳)
"updateTime": 1699000000000 // 更新时间(毫秒时间戳)
}
}
}
```
**状态说明**:
| 状态值 | 状态名称 | 说明 |
|--------|---------|------|
| 1 | 待审核 | 用户已提交申请,等待审核 |
| 2 | 已通过 | 审核通过,提现成功(余额已在申请时扣除) |
| 3 | 已拒绝 | 审核拒绝,余额已退回 |
| 4 | 处理中 | 审核通过后,正在处理中 |
| 5 | 已完成 | 提现已完成 |
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | applicationID is required | 提现申请ID不能为空 |
| 404 | 记录不存在 | 提现申请不存在 |
| 401 | 无权限 | 需要管理员权限 |
---
## 2. 获取提现申请列表(支持按状态筛选)
**接口地址**: `/withdraw/list`
**请求方法**: `POST`
**请求参数**:
```json
{
"status": 1, // 状态筛选可选0-全部1-待审核2-已通过3-已拒绝4-处理中5-已完成。默认为0全部
"pagination": {
"pageNumber": 1, // 页码必填从1开始
"showNumber": 10 // 每页数量(必填)
}
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 100, // 总数
"list": [
{
"id": "string", // 提现申请ID
"userID": "string", // 用户ID
"amount": 10000, // 提现金额(单位:分)
"withdrawAccount": "string", // 提现账号
"status": 1, // 申请状态1-待审核2-已通过3-已拒绝4-处理中5-已完成
"auditorID": "string", // 审核人ID管理员ID
"auditTime": 1699000000000, // 审核时间(毫秒时间戳)
"auditRemark": "string", // 审核备注
"ip": "string", // 申请IP
"deviceID": "string", // 设备ID
"platform": "string", // 平台iOS、Android、Web等
"deviceModel": "string", // 设备型号
"deviceBrand": "string", // 设备品牌
"osVersion": "string", // 操作系统版本
"appVersion": "string", // 应用版本
"createTime": 1699000000000, // 创建时间(毫秒时间戳)
"updateTime": 1699000000000 // 更新时间(毫秒时间戳)
}
]
}
}
```
**请求示例**:
```json
// 获取所有提现申请
{
"status": 0,
"pagination": {
"pageNumber": 1,
"showNumber": 20
}
}
// 获取待审核的提现申请
{
"status": 1,
"pagination": {
"pageNumber": 1,
"showNumber": 20
}
}
// 获取已通过的提现申请
{
"status": 2,
"pagination": {
"pageNumber": 1,
"showNumber": 20
}
}
```
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | invalid request | 请求参数格式错误 |
| 401 | 无权限 | 需要管理员权限 |
---
## 3. 获取用户的提现申请列表
**接口地址**: `/withdraw/user_list`
**请求方法**: `POST`
**请求参数**:
```json
{
"userID": "string", // 用户ID必填
"pagination": {
"pageNumber": 1, // 页码必填从1开始
"showNumber": 10 // 每页数量(必填)
}
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 10, // 总数
"list": [
{
"id": "string", // 提现申请ID
"userID": "string", // 用户ID
"amount": 10000, // 提现金额(单位:分)
"withdrawAccount": "string", // 提现账号
"status": 1, // 申请状态1-待审核2-已通过3-已拒绝4-处理中5-已完成
"auditorID": "string", // 审核人ID管理员ID
"auditTime": 1699000000000, // 审核时间(毫秒时间戳)
"auditRemark": "string", // 审核备注
"ip": "string", // 申请IP
"deviceID": "string", // 设备ID
"platform": "string", // 平台iOS、Android、Web等
"deviceModel": "string", // 设备型号
"deviceBrand": "string", // 设备品牌
"osVersion": "string", // 操作系统版本
"appVersion": "string", // 应用版本
"createTime": 1699000000000, // 创建时间(毫秒时间戳)
"updateTime": 1699000000000 // 更新时间(毫秒时间戳)
}
]
}
}
```
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | userID is required | 用户ID不能为空 |
| 400 | invalid request | 请求参数格式错误 |
| 401 | 无权限 | 需要管理员权限 |
---
## 4. 批量审核提现申请
**接口地址**: `/withdraw/audit`
**请求方法**: `POST`
**请求参数**:
```json
{
"withdrawIDs": ["string", "string"], // 提现申请ID列表必填支持批量审核
"status": 2, // 审核状态必填2-已通过3-已拒绝
"auditRemark": "string" // 审核备注(可选)
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"successCount": 5, // 成功审核的数量
"failCount": 2, // 失败审核的数量
"failedIDs": ["id1", "id2"] // 失败的提现申请ID列表
}
}
```
**状态说明**:
| 状态值 | 状态名称 | 说明 |
|--------|---------|------|
| 2 | 已通过 | 审核通过,提现成功(余额已在用户申请时扣除,无需额外操作) |
| 3 | 已拒绝 | 审核拒绝,系统会自动将余额退回用户钱包,并创建退款记录 |
**业务逻辑**:
1. 验证必填字段提现申请ID列表、审核状态
2. 验证审核状态必须是2通过或3拒绝
3. **批量处理每个提现申请**
- 检查提现申请是否存在
- 检查提现申请状态,允许"待审核"和"已通过"状态的提现申请被审核(已通过的提现申请可以重新审核为拒绝)
- 更新提现申请状态和审核信息
- **如果审核拒绝**
- 自动将提现金额退回用户钱包(包括从"待审核"改为"已拒绝",或从"已通过"改为"已拒绝"
- 创建一条类型为"退款"的余额变动记录
- 备注为"提现审核拒绝,退回余额"
4. 返回成功和失败的数量以及失败的ID列表
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | withdrawIDs is required and cannot be empty | 提现申请ID列表不能为空 |
| 400 | status must be 2 (approved) or 3 (rejected) | 审核状态必须是2或3 |
| 401 | 无权限 | 需要管理员权限 |
**注意**
- 批量审核时,部分成功部分失败是正常的
- 失败的提现申请会在 `failedIDs` 中返回
- 失败的常见原因:
- 提现申请不存在
- 提现申请状态不是"待审核"或"已通过"
- 更新状态时出错
**请求示例**:
```json
// 批量审核通过
{
"withdrawIDs": ["xxx-xxx-xxx-1", "xxx-xxx-xxx-2", "xxx-xxx-xxx-3"],
"status": 2,
"auditRemark": "批量审核通过,已打款"
}
// 批量审核拒绝
{
"withdrawIDs": ["xxx-xxx-xxx-1", "xxx-xxx-xxx-2"],
"status": 3,
"auditRemark": "提现账号信息有误,已拒绝"
}
// 单个审核(也支持)
{
"withdrawIDs": ["xxx-xxx-xxx"],
"status": 2,
"auditRemark": "审核通过,已打款"
}
```
**响应示例**:
```json
// 全部成功
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"successCount": 3,
"failCount": 0,
"failedIDs": []
}
}
// 部分成功
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"successCount": 2,
"failCount": 1,
"failedIDs": ["xxx-xxx-xxx-3"] // 这个ID可能不存在或状态不对
}
}
```
---
## 通用说明
### 分页参数说明
所有列表接口都使用统一的分页参数格式:
```json
{
"pagination": {
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
}
```
### 时间戳说明
所有时间字段都是毫秒时间戳Unix timestamp in milliseconds例如
- `1699000000000` 表示 `2023-11-03 12:00:00`UTC时间
### 金额单位说明
所有金额字段的单位都是**分**cent例如
- `10000` 表示 `100.00`
- `100` 表示 `1.00`
### 权限说明
所有接口都需要管理员权限,需要在请求头中携带有效的管理员 token。
### 响应格式说明
所有接口都遵循统一的响应格式:
```json
{
"errCode": 0, // 错误码0表示成功
"errMsg": "", // 错误信息
"errDlt": "", // 错误详情
"data": {} // 响应数据
}
```
---
## 接口调用示例
### 示例1获取待审核的提现申请列表
```bash
curl -X POST http://your-domain/withdraw/list \
-H "Content-Type: application/json" \
-H "token: your-admin-token" \
-d '{
"status": 1,
"pagination": {
"pageNumber": 1,
"showNumber": 20
}
}'
```
### 示例2批量审核提现申请通过
```bash
curl -X POST http://your-domain/withdraw/audit \
-H "Content-Type: application/json" \
-H "token: your-admin-token" \
-d '{
"withdrawIDs": ["withdraw-123", "withdraw-124", "withdraw-125"],
"status": 2,
"auditRemark": "批量审核通过,已打款"
}'
```
### 示例3批量审核提现申请拒绝
```bash
curl -X POST http://your-domain/withdraw/audit \
-H "Content-Type: application/json" \
-H "token: your-admin-token" \
-d '{
"withdrawIDs": ["withdraw-123", "withdraw-124"],
"status": 3,
"auditRemark": "提现账号信息有误,已拒绝"
}'
```
### 示例4单个审核也支持
```bash
curl -X POST http://your-domain/withdraw/audit \
-H "Content-Type: application/json" \
-H "token: your-admin-token" \
-d '{
"withdrawIDs": ["withdraw-123"],
"status": 2,
"auditRemark": "审核通过,已打款"
}'
```
---
## 状态流转图
```
待审核 (1)
├─ 审核通过 (2) → 已通过(余额已在用户申请时扣除,无需额外操作)
│ ├─ 重新审核拒绝 (3) → 已拒绝(余额自动退回用户钱包)
│ └─ 处理中 (4) → 已完成 (5)
└─ 审核拒绝 (3) → 已拒绝(余额自动退回用户钱包)
```
---
## 注意事项
1. **用户申请提现**:用户在前端申请提现时,余额会立即扣除,创建提现申请记录
2. **后台审核**:管理员通过后台接口审核用户的提现申请,支持批量审核
3. **批量审核**:可以一次审核多个提现申请,返回成功和失败的数量
4. **审核通过**:余额已在用户申请时扣除,审核通过时无需额外操作
5. **审核拒绝**:审核拒绝时会自动退回余额到用户钱包,并创建退款记录(包括从"已通过"改为"已拒绝"的情况)
6. **状态检查**:允许"待审核"和"已通过"状态的提现申请被审核,已通过的提现申请可以重新审核为拒绝
7. **部分失败处理**批量审核时部分成功部分失败是正常的失败的ID会在响应中返回
8. **金额单位**:所有金额都以"分"为单位前端显示时需要除以100
9. **数据来源**:所有接口操作的都是 `withdraw_applications` 集合(用户申请的提现),不是 `withdraws` 集合

View File

@@ -1,439 +0,0 @@
# 提现申请接口文档
## 基础信息
- **基础路径**: `/wallet`
- **认证方式**: 所有接口都需要在请求头中携带 `token`(通过 `mw.CheckToken` 中间件验证)
- **请求方法**: 所有接口均为 `POST`
- **Content-Type**: `application/json`
## 响应格式说明
所有接口的响应格式统一为:
```json
{
"errCode": 0, // 错误码0 表示成功
"errMsg": "", // 错误消息
"errDlt": "", // 错误详情
"data": {} // 响应数据
}
```
## 公共数据结构
### RequestPagination分页信息
```json
{
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
```
### WithdrawApplicationInfo提现申请信息
```json
{
"id": "string", // 申请ID
"userID": "string", // 用户ID
"amount": 10000, // 提现金额(单位:分)
"withdrawAccount": "string", // 提现账号
"withdrawAccountType": 1, // 提现账号类型1-支付宝2-微信3-银行卡
"status": 1, // 申请状态1-待审核2-已通过3-已拒绝4-处理中5-已完成
"auditorID": "string", // 审核人ID管理员ID
"auditTime": 1234567890123, // 审核时间毫秒时间戳未审核时为0
"auditRemark": "string", // 审核备注
"ip": "string", // 申请IP
"deviceID": "string", // 设备ID
"platform": "string", // 平台iOS、Android、Web等
"deviceModel": "string", // 设备型号
"deviceBrand": "string", // 设备品牌
"osVersion": "string", // 操作系统版本
"appVersion": "string", // 应用版本
"remark": "string", // 申请备注
"createTime": 1234567890123, // 创建时间(毫秒时间戳)
"updateTime": 1234567890123 // 更新时间(毫秒时间戳)
}
```
### 提现申请状态说明
| 状态值 | 状态名称 | 说明 |
|--------|---------|------|
| 1 | 待审核 | 用户已提交申请,等待管理员审核 |
| 2 | 已通过 | 管理员审核通过 |
| 3 | 已拒绝 | 管理员审核拒绝 |
| 4 | 处理中 | 审核通过后,正在处理提现 |
| 5 | 已完成 | 提现已完成 |
---
## 接口列表
### 1. 设置支付密码
**接口地址**: `/wallet/payment_password/set`
**请求参数**:
```json
{
"newPassword": "string", // 新支付密码(必填)
"oldPassword": "string" // 旧支付密码(修改时必填,首次设置时不需要)
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**业务逻辑**:
1. **首次设置支付密码**(钱包不存在或未设置支付密码):
- 不需要提供 `oldPassword`
- 如果提供了 `oldPassword`,会返回错误
- 如果钱包不存在,会自动创建钱包并设置支付密码
2. **修改支付密码**(已设置支付密码):
- 必须提供 `oldPassword`
- 验证旧密码是否正确
- 验证新密码不能与旧密码相同
- 更新支付密码
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | 新支付密码不能为空 | newPassword 为空 |
| 400 | 修改支付密码需要提供旧密码 | 已设置密码但未提供 oldPassword |
| 400 | 首次设置支付密码不需要提供旧密码 | 未设置密码但提供了 oldPassword |
| 400 | 旧支付密码错误 | oldPassword 验证失败 |
| 400 | 新密码不能与旧密码相同 | newPassword == oldPassword |
**请求示例**:
首次设置:
```json
{
"newPassword": "123456"
}
```
修改密码:
```json
{
"newPassword": "654321",
"oldPassword": "123456"
}
```
---
### 2. 设置提现账号
**接口地址**: `/wallet/withdraw_account/set`
**请求参数**:
```json
{
"account": "string", // 提现账号(必填)
"accountType": 1 // 账号类型必填1-支付宝2-微信3-银行卡
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {}
}
```
**账号类型说明**:
| 类型值 | 类型名称 | 说明 |
|--------|---------|------|
| 1 | 支付宝 | 支付宝账号 |
| 2 | 微信 | 微信账号 |
| 3 | 银行卡 | 银行卡号 |
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | 提现账号不能为空 | account 为空 |
| 400 | 账号类型无效必须是1-支付宝2-微信3-银行卡 | accountType 不在有效范围内 |
**业务逻辑**:
1. 验证必填字段(账号、账号类型)
2. 验证账号类型是否有效1-3
3. 更新钱包中的提现账号和账号类型
---
### 3. 申请提现
**接口地址**: `/wallet/withdraw/apply`
**请求参数**:
```json
{
"amount": 10000, // 提现金额单位必填必须大于0
"paymentPassword": "string", // 支付密码(必填)
"ip": "string", // 申请IP可选
"deviceID": "string", // 设备ID可选
"platform": "string", // 平台可选iOS、Android、Web
"deviceModel": "string", // 设备型号可选iPhone 14 Pro
"deviceBrand": "string", // 设备品牌可选Apple
"osVersion": "string", // 操作系统版本可选iOS 17.0
"appVersion": "string" // 应用版本(可选)
}
```
**注意**:
- 提现账号从用户钱包中自动获取,不需要在请求中提供
- 如果钱包中未设置提现账号,会返回错误提示
- 备注remark由后台管理员在审核时填写用户申请时不需要提供
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"applicationID": "uuid-string" // 申请ID
}
}
```
**错误码说明**:
| 错误码 | 错误信息 | 说明 |
|--------|---------|------|
| 400 | 提现金额必须大于0 | amount <= 0 |
| 400 | 支付密码不能为空 | paymentPassword 为空 |
| 400 | 钱包不存在,无法申请提现 | 用户钱包不存在 |
| 400 | 请先设置支付密码 | 用户未设置支付密码 |
| 400 | 支付密码错误 | 支付密码验证失败 |
| 400 | 余额不足,无法申请提现 | 钱包余额 < 提现金额 |
| 400 | 请先在钱包中设置提现账号 | 钱包中未设置提现账号 |
**业务逻辑**:
1. 验证必填字段金额支付密码
2. 获取用户钱包信息
3. 验证支付密码
4. 检查余额是否足够
5. 检查钱包中是否设置了提现账号从钱包中获取
6. 创建提现申请记录状态待审核提现账号从钱包中获取
---
### 4. 获取提现申请列表
**接口地址**: `/wallet/withdraw/list`
**请求参数**:
```json
{
"pagination": {
"pageNumber": 1, // 页码从1开始
"showNumber": 10 // 每页显示数量
}
}
```
**响应参数**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 100, // 总数
"applications": [ // 申请列表
{
"id": "string",
"userID": "string",
"amount": 10000,
"withdrawAccount": "string",
"status": 1,
"auditorID": "string",
"auditTime": 1234567890123,
"auditRemark": "string",
"ip": "string",
"deviceID": "string",
"platform": "string",
"deviceModel": "string",
"deviceBrand": "string",
"osVersion": "string",
"appVersion": "string",
"remark": "string",
"createTime": 1234567890123,
"updateTime": 1234567890123
}
]
}
}
```
**业务逻辑**:
1. token 中获取当前用户ID
2. 根据用户ID查询提现申请列表
3. 按创建时间倒序排列
4. 支持分页查询
---
## 请求示例
### 申请提现
```bash
curl -X POST http://your-domain/wallet/withdraw/apply \
-H "Content-Type: application/json" \
-H "token: your-token" \
-d '{
"amount": 10000,
"paymentPassword": "123456",
"ip": "192.168.1.1",
"deviceID": "device-uuid",
"platform": "iOS",
"deviceModel": "iPhone 14 Pro",
"deviceBrand": "Apple",
"osVersion": "iOS 17.0",
"appVersion": "1.0.0"
}'
```
**响应示例**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"applicationID": "550e8400-e29b-41d4-a716-446655440000"
}
}
```
### 获取提现申请列表
```bash
curl -X POST http://your-domain/wallet/withdraw/list \
-H "Content-Type: application/json" \
-H "token: your-token" \
-d '{
"pagination": {
"pageNumber": 1,
"showNumber": 10
}
}'
```
**响应示例**:
```json
{
"errCode": 0,
"errMsg": "",
"errDlt": "",
"data": {
"total": 5,
"applications": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"userID": "user123",
"amount": 10000,
"withdrawAccount": "6222021234567890123",
"status": 1,
"auditorID": "",
"auditTime": 0,
"auditRemark": "",
"ip": "192.168.1.1",
"deviceID": "device-uuid",
"platform": "iOS",
"deviceModel": "iPhone 14 Pro",
"deviceBrand": "Apple",
"osVersion": "iOS 17.0",
"appVersion": "1.0.0",
"remark": "提现备注",
"createTime": 1704067200000,
"updateTime": 1704067200000
}
]
}
}
```
---
## RPC 接口说明
### gRPC 服务
**服务名**: `openim.chat.Chat`
### 1. CreateWithdrawApplication
**RPC 方法**: `CreateWithdrawApplication`
**请求消息**: `CreateWithdrawApplicationReq`
**响应消息**: `CreateWithdrawApplicationResp`
### 2. SetPaymentPassword
**RPC 方法**: `SetPaymentPassword`
**请求消息**: `SetPaymentPasswordReq`
**响应消息**: `SetPaymentPasswordResp`
### 3. GetWithdrawApplications
**RPC 方法**: `GetWithdrawApplications`
**请求消息**: `GetWithdrawApplicationsReq`
**响应消息**: `GetWithdrawApplicationsResp`
---
## 注意事项
1. **支付密码验证**: 申请提现时必须提供正确的支付密码
2. **余额检查**: 系统会检查钱包余额是否足够余额不足时无法申请
3. **提现账号**: 如果钱包中已设置提现账号可以不传 `withdrawAccount`系统会使用钱包中的账号
4. **申请状态**: 新创建的申请状态为"待审核"status=1需要管理员审核
5. **分页查询**: 列表接口支持分页默认按创建时间倒序排列
6. **权限控制**: 用户只能查看自己的提现申请列表
---
## 相关接口
- [钱包余额查询](./API_WALLET.md#获取钱包余额)
- [钱包信息查询](./API_WALLET.md#获取钱包详细信息)
- [设置支付密码](#设置支付密码)

View File

@@ -1 +0,0 @@
* @Bloomingg @FGadvancer @skiffer-git @withchao

View File

@@ -1,129 +0,0 @@
# Continuous Integration and Automation
Every change on the OpenIM repository, either made through a pull request or direct push, triggers the continuous integration pipelines defined within the same repository. Needless to say, all the OpenIM contributions can be merged until all the checks pass (AKA having green builds).
- [Continuous Integration and Automation](#continuous-integration-and-automation)
- [CI Platforms](#ci-platforms)
- [GitHub Actions](#github-actions)
- [Running locally](#running-locally)
## CI Platforms
Currently, there are two different platforms involved in running the CI processes:
- GitHub actions
- Drone pipelines on CNCF infrastructure
### GitHub Actions
All the existing GitHub Actions are defined as YAML files under the `.github/workflows` directory. These can be grouped into:
- **PR Checks**. These actions run all the required validations upon PR creation and update. Covering the DCO compliance check, `x86_64` test batteries (unit, integration, smoke), and code coverage.
- **Repository automation**. Currently, it only covers issues and epic grooming.
Everything runs on GitHub's provided runners; thus, the tests are limited to run in `x86_64` architectures.
## Running locally
A contributor should verify their changes locally to speed up the pull request process. Fortunately, all the CI steps can be on local environments, except for the publishing ones, through either of the following methods:
**User Makefile:**
```bash
root@PS2023EVRHNCXG:~/workspaces/openim/Open-IM-Server# make help 😊
Usage: make <TARGETS> <OPTIONS> ...
Targets:
all Run tidy, gen, add-copyright, format, lint, cover, build 🚀
build Build binaries by default 🛠️
multiarch Build binaries for multiple platforms. See option PLATFORMS. 🌍
tidy tidy go.mod ✨
vendor vendor go.mod 📦
style code style -> fmt,vet,lint 💅
fmt Run go fmt against code. ✨
vet Run go vet against code. ✅
lint Check syntax and styling of go sources. ✔️
format Gofmt (reformat) package sources (exclude vendor dir if existed). 🔄
test Run unit test. 🧪
cover Run unit test and get test coverage. 📊
updates Check for updates to go.mod dependencies 🆕
imports task to automatically handle import packages in Go files using goimports tool 📥
clean Remove all files that are created by building. 🗑️
image Build docker images for host arch. 🐳
image.multiarch Build docker images for multiple platforms. See option PLATFORMS. 🌍🐳
push Build docker images for host arch and push images to registry. 📤🐳
push.multiarch Build docker images for multiple platforms and push images to registry. 🌍📤🐳
tools Install dependent tools. 🧰
gen Generate all necessary files. 🧩
swagger Generate swagger document. 📖
serve-swagger Serve swagger spec and docs. 🚀📚
verify-copyright Verify the license headers for all files. ✅
add-copyright Add copyright ensure source code files have license headers. 📄
release release the project 🎉
help Show this help info.
help-all Show all help details info. ℹ️📚
Options:
DEBUG Whether or not to generate debug symbols. Default is 0. ❓
BINS Binaries to build. Default is all binaries under cmd. 🛠️
This option is available when using: make {build}(.multiarch) 🧰
Example: make build BINS="openim-api openim_cms_api".
PLATFORMS Platform to build for. Default is linux_arm64 and linux_amd64. 🌍
This option is available when using: make {build}.multiarch 🌍
Example: make multiarch PLATFORMS="linux_s390x linux_mips64
linux_mips64le darwin_amd64 windows_amd64 linux_amd64 linux_arm64".
V Set to 1 enable verbose build. Default is 0. 📝
```
How to Use Makefile to Help Contributors Build Projects Quickly 😊
The `make help` command is a handy tool that provides useful information on how to utilize the Makefile effectively. By running this command, contributors will gain insights into various targets and options available for building projects swiftly.
Here's a breakdown of the targets and options provided by the Makefile:
**Targets 😃**
1. `all`: This target runs multiple tasks like `tidy`, `gen`, `add-copyright`, `format`, `lint`, `cover`, and `build`. It ensures comprehensive project building.
2. `build`: The primary target that compiles binaries by default. It is particularly useful for creating the necessary executable files.
3. `multiarch`: A target that builds binaries for multiple platforms. Contributors can specify the desired platforms using the `PLATFORMS` option.
4. `tidy`: This target cleans up the `go.mod` file, ensuring its consistency.
5. `vendor`: A target that updates the project dependencies based on the `go.mod` file.
6. `style`: Checks the code style using tools like `fmt`, `vet`, and `lint`. It ensures a consistent coding style throughout the project.
7. `fmt`: Formats the code using the `go fmt` command, ensuring proper indentation and formatting.
8. `vet`: Runs the `go vet` command to identify common errors in the code.
9. `lint`: Validates the syntax and styling of Go source files using a linter.
10. `format`: Reformats the package sources using `gofmt`. It excludes the vendor directory if it exists.
11. `test`: Executes unit tests to ensure the functionality and stability of the code.
12. `cover`: Performs unit tests and calculates the test coverage of the code.
13. `updates`: Checks for updates to the project's dependencies specified in the `go.mod` file.
14. `imports`: Automatically handles import packages in Go files using the `goimports` tool.
15. `clean`: Removes all files generated during the build process, effectively cleaning up the project directory.
16. `image`: Builds Docker images for the host architecture.
17. `image.multiarch`: Similar to the `image` target, but it builds Docker images for multiple platforms. Contributors can specify the desired platforms using the `PLATFORMS` option.
18. `push`: Builds Docker images for the host architecture and pushes them to a registry.
19. `push.multiarch`: Builds Docker images for multiple platforms and pushes them to a registry. Contributors can specify the desired platforms using the `PLATFORMS` option.
20. `tools`: Installs the necessary tools or dependencies required by the project.
21. `gen`: Generates all the required files automatically.
22. `swagger`: Generates the swagger document for the project.
23. `serve-swagger`: Serves the swagger specification and documentation.
24. `verify-copyright`: Verifies the license headers for all project files.
25. `add-copyright`: Adds copyright headers to the source code files.
26. `release`: Releases the project, presumably for distribution.
27. `help`: Displays information about available targets and options.
28. `help-all`: Shows detailed information about all available targets and options.
**Options 😄**
1. `DEBUG`: A boolean option that determines whether or not to generate debug symbols. The default value is 0 (false).
2. `BINS`: Specifies the binaries to build. By default, it builds all binaries under the `cmd` directory. Contributors can provide a list of specific binaries using this option.
3. `PLATFORMS`: Specifies the platforms to build for. The default platforms are `linux_arm64` and `linux_amd64`. Contributors can specify multiple platforms by providing a space-separated list of platform names.
4. `V`: A boolean option that enables verbose build output when set to 1 (true). The default value is 0 (false).
With these targets and options in place, contributors can efficiently build projects using the Makefile. Happy coding! 🚀😊

View File

@@ -1,38 +0,0 @@
# Code conventions
- [Code conventions](#code-conventions)
- [POSIX shell](#posix-shell)
- [Go](#go)
- [Directory and file conventions](#directory-and-file-conventions)
- [Testing conventions](#testing-conventions)
## POSIX shell
- [Style guide](https://google.github.io/styleguide/shell.xml)
## Go
- [Go Code Review Comments](https://github.com/golang/go/wiki/CodeReviewComments)
- [Effective Go](https://golang.org/doc/effective_go.html)
- Know and avoid [Go landmines](https://gist.github.com/lavalamp/4bd23295a9f32706a48f)
- Comment your code.
- [Go's commenting conventions](http://blog.golang.org/godoc-documenting-go-code)
- If reviewers ask questions about why the code is the way it is, that's a sign that comments might be helpful.
- Command-line flags should use dashes, not underscores
- Naming
- Please consider package name when selecting an interface name, and avoid redundancy. For example, `storage.Interface` is better than `storage.StorageInterface`.
- Do not use uppercase characters, underscores, or dashes in package names.
- Please consider parent directory name when choosing a package name. For example, `pkg/controllers/autoscaler/foo.go` should say `package autoscaler` not `package autoscalercontroller`.
- Unless there's a good reason, the `package foo` line should match the name of the directory in which the `.go` file exists.
- Importers can use a different name if they need to disambiguate.
## Directory and file conventions
- Avoid general utility packages. Packages called "util" are suspect. Instead, derive a name that describes your desired function. For example, the utility functions dealing with waiting for operations are in the `wait` package and include functionality like `Poll`. The full name is `wait.Poll`.
- All filenames should be lowercase.
- All source files and directories should use underscores, not dashes.
- Package directories should generally avoid using separators as much as possible. When package names are multiple words, they usually should be in nested subdirectories.
## Testing conventions
Please refer to [TESTING.md](../../tests/TESTING.md) document.

View File

@@ -1,80 +0,0 @@
# Development Guide
Since OpenIM is written in Go, it is fair to assume that the Go tools are all one needs to contribute to this project. Unfortunately, there is a point where this no longer holds true when required to test or build local changes. This document elaborates on the required tooling for OpenIM development.
- [Development Guide](#development-guide)
- [Non-Linux environment prerequisites](#non-linux-environment-prerequisites)
- [Windows Setup](#windows-setup)
- [macOS Setup](#macos-setup)
- [Installing Required Software](#installing-required-software)
- [Go](#go)
- [Docker](#docker)
- [Vagrant](#vagrant)
- [Cloning, Building and Testing OpenIM](#cloning-building-and-testing-openim)
- [Dependency management](#dependency-management)
## Non-Linux environment prerequisites
All the test and build scripts within this repository were created to be run on GNU Linux development environments. Due to this, it is suggested to use the virtual machine defined on this repository's [Vagrantfile](../../Vagrantfile) to use them.
Either way, if one still wants to build and test OpenIM on non-Linux environments, specific setups are to be followed.
### Windows Setup
To build OpenIM on Windows is only possible for versions that support Windows Subsystem for Linux (WSL). If the development environment in question has Windows 10, Version 2004, Build 19041 or higher, [follow these instructions to install WSL2](https://docs.microsoft.com/en-us/windows/wsl/install-win10); otherwise, use a Linux Virtual machine instead.
### macOS Setup
The shell scripts in charge of the build and test processes rely on GNU utils (i.e. `sed`), [which slightly differ on macOS](https://unix.stackexchange.com/a/79357), meaning that one must make some adjustments before using them.
First, install the GNU utils:
```sh
brew install coreutils findutils gawk gnu-sed gnu-tar grep make
```
Then update the shell init script (i.e. `.bashrc`) to prepend the GNU Utils to the `$PATH` variable
```sh
GNUBINS="$(find /usr/local/opt -type d -follow -name gnubin -print)"
for bindir in ${GNUBINS[@]}; do
PATH=$bindir:$PATH
done
export PATH
```
## Installing Required Software
### Go
It is well known that OpenIM is written in [Go](http://golang.org). Please follow the [Go Getting Started guide](https://golang.org/doc/install) to install and set up the Go tools used to compile and run the test batteries.
| OpenIM | requires Go |
|----------------|-------------|
| 2.24 - 3.00 | 1.15 + |
| 3.30 + | 1.18 + |
### Docker
OpenIM build and test processes development require Docker to run certain steps. [Follow the Docker website instructions to install Docker](https://docs.docker.com/get-docker/) in the development environment.
### Vagrant
As described in the [Testing documentation](../../tests/TESTING.md), all the smoke tests are run in virtual machines managed by Vagrant. To install Vagrant in the development environment, [follow the instructions from the Hashicorp website](https://www.vagrantup.com/downloads), alongside any of the following hypervisors:
- [VirtualBox](https://www.virtualbox.org/)
- [libvirt](https://libvirt.org/) and the [vagrant-libvirt plugin](https://github.com/vagrant-libvirt/vagrant-libvirt#installation)
## Cloning, Building and Testing OpenIM
These topics already have been addressed on their respective documents:
- [Git Workflow](./git-workflow.md)
- [Building](../../BUILDING.md)
- [Testing](../../tests/TESTING.md)
## Dependency management
OpenIM uses [go modules](https://github.com/golang/go/wiki/Modules) to manage dependencies.

Some files were not shown because too many files have changed in this diff Show More