Compare commits
29 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ab6ca82c14 | ||
|
|
85b455ed31 | ||
|
|
9584baa208 | ||
|
|
ea386977ba | ||
|
|
e018f742ad | ||
|
|
59aa8c4fce | ||
|
|
8ffaccab05 | ||
|
|
44923fa5b7 | ||
|
|
c3f70a6008 | ||
|
|
45a33927ac | ||
|
|
032dfd7d80 | ||
|
|
1ec903b15f | ||
|
|
26ee115d8c | ||
|
|
162a35dc72 | ||
|
|
da7c729b72 | ||
|
|
ea5b06752a | ||
|
|
ba53ee745f | ||
|
|
6731516e06 | ||
|
|
7b2b3996be | ||
|
|
35f2f7ff81 | ||
|
|
4eb593782c | ||
|
|
82b7953639 | ||
|
|
c88903c534 | ||
|
|
2bdfafb4cf | ||
|
|
3fb403dce8 | ||
|
|
b4623b8a6f | ||
|
|
3a787cfd22 | ||
|
|
26f7102989 | ||
|
|
b7f8db7d08 |
28
.dockerignore
Normal file
28
.dockerignore
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# 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
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.sh text eol=lf
|
||||||
49
.gitea/deployments/deploy/openim-admin-api-deployment.yml
Normal file
49
.gitea/deployments/deploy/openim-admin-api-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
.gitea/deployments/deploy/openim-admin-api-service.yml
Normal file
13
.gitea/deployments/deploy/openim-admin-api-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
.gitea/deployments/deploy/openim-admin-rpc-deployment.yml
Normal file
49
.gitea/deployments/deploy/openim-admin-rpc-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
.gitea/deployments/deploy/openim-admin-rpc-service.yml
Normal file
13
.gitea/deployments/deploy/openim-admin-rpc-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
.gitea/deployments/deploy/openim-chat-api-deployment.yml
Normal file
49
.gitea/deployments/deploy/openim-chat-api-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
.gitea/deployments/deploy/openim-chat-api-service.yml
Normal file
13
.gitea/deployments/deploy/openim-chat-api-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
.gitea/deployments/deploy/openim-chat-rpc-deployment.yml
Normal file
49
.gitea/deployments/deploy/openim-chat-rpc-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
.gitea/deployments/deploy/openim-chat-rpc-service.yml
Normal file
13
.gitea/deployments/deploy/openim-chat-rpc-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
609
.gitea/workflows/build.yml
Normal file
609
.gitea/workflows/build.yml
Normal file
@@ -0,0 +1,609 @@
|
|||||||
|
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 "✅ 清理完成"
|
||||||
229
.gitea/workflows/itom-platform-auto-build.yml
Normal file
229
.gitea/workflows/itom-platform-auto-build.yml
Normal file
@@ -0,0 +1,229 @@
|
|||||||
|
name: itom-platform auto build image
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
workflow_dispatch: {}
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
|
||||||
|
env:
|
||||||
|
# CI 触发模式:优先仓库变量,其次 Secrets(默认 dispatch)
|
||||||
|
CI_TRIGGER_MODE_VAR: ${{ vars.CI_TRIGGER_MODE }}
|
||||||
|
CI_TRIGGER_MODE_SECRET: ${{ secrets.CI_TRIGGER_MODE }}
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
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
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
MODE="${CI_TRIGGER_MODE_VAR:-${CI_TRIGGER_MODE_SECRET:-dispatch}}"
|
||||||
|
EVENT="${GITHUB_EVENT_NAME:-${GITEA_EVENT_NAME:-}}"
|
||||||
|
ALLOW="false"
|
||||||
|
case "$EVENT" in
|
||||||
|
workflow_dispatch)
|
||||||
|
if [ "$MODE" = "dispatch" ] || [ "$MODE" = "both" ]; then
|
||||||
|
ALLOW="true"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
push)
|
||||||
|
if [ "$MODE" = "push" ] || [ "$MODE" = "both" ]; then
|
||||||
|
ALLOW="true"
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
echo "CI_TRIGGER_MODE=$MODE" >> "$GITHUB_ENV"
|
||||||
|
echo "CI_TRIGGER_ALLOWED=$ALLOW" >> "$GITHUB_ENV"
|
||||||
|
if [ "$ALLOW" != "true" ]; then
|
||||||
|
echo "Skip build: event=$EVENT mode=$MODE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Install git
|
||||||
|
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
if ! command -v git >/dev/null 2>&1; then
|
||||||
|
apk add --no-cache git openssh-client ca-certificates
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Checkout
|
||||||
|
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 }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
WORKDIR="${GITHUB_WORKSPACE:-/workspace}"
|
||||||
|
mkdir -p "$WORKDIR"
|
||||||
|
REPO="${GITHUB_REPOSITORY:-${GITEA_REPOSITORY:-}}"
|
||||||
|
SERVER="${GITHUB_SERVER_URL:-${GITEA_SERVER_URL:-https://git.imall.cloud}}"
|
||||||
|
if [ -z "$REPO" ]; then
|
||||||
|
echo "ERROR: missing repository info."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
USER=""
|
||||||
|
TOKEN=""
|
||||||
|
if [ -n "${GIT_USER:-}" ] && [ -n "${GIT_TOKEN:-}" ]; then
|
||||||
|
USER="$GIT_USER"
|
||||||
|
TOKEN="$GIT_TOKEN"
|
||||||
|
elif [ -n "${GITEA_TOKEN:-}" ]; then
|
||||||
|
USER="${GITEA_ACTOR:-${FORGEJO_ACTOR:-${GITHUB_ACTOR:-}}}"
|
||||||
|
TOKEN="$GITEA_TOKEN"
|
||||||
|
elif [ -n "${FORGEJO_TOKEN:-}" ]; then
|
||||||
|
USER="${FORGEJO_ACTOR:-${GITHUB_ACTOR:-}}"
|
||||||
|
TOKEN="$FORGEJO_TOKEN"
|
||||||
|
elif [ -n "${GITHUB_TOKEN:-}" ]; then
|
||||||
|
USER="${GITHUB_ACTOR:-}"
|
||||||
|
TOKEN="$GITHUB_TOKEN"
|
||||||
|
elif [ -n "${REGISTRY_USER:-}" ] && [ -n "${REGISTRY_PASSWORD:-}" ]; then
|
||||||
|
USER="$REGISTRY_USER"
|
||||||
|
TOKEN="$REGISTRY_PASSWORD"
|
||||||
|
fi
|
||||||
|
if [ -n "$TOKEN" ]; then
|
||||||
|
if [ -z "$USER" ]; then
|
||||||
|
echo "ERROR: missing git username for token auth."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
AUTH_HOST="${SERVER#https://}"
|
||||||
|
AUTH_HOST="${AUTH_HOST#http://}"
|
||||||
|
git clone "https://${USER}:${TOKEN}@${AUTH_HOST}/${REPO}.git" "$WORKDIR"
|
||||||
|
else
|
||||||
|
git clone "${SERVER}/${REPO}.git" "$WORKDIR"
|
||||||
|
fi
|
||||||
|
cd "$WORKDIR"
|
||||||
|
SHA="${GITHUB_SHA:-${GITEA_SHA:-}}"
|
||||||
|
if [ -n "$SHA" ]; then
|
||||||
|
git checkout "$SHA"
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Prepare tags
|
||||||
|
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
BRANCH="${GITHUB_REF_NAME:-${GITEA_REF_NAME:-}}"
|
||||||
|
if [ -z "$BRANCH" ]; then
|
||||||
|
BRANCH="$(echo "${GITHUB_REF:-${GITEA_REF:-}}" | sed 's#.*/##')"
|
||||||
|
fi
|
||||||
|
BRANCH="$(echo "$BRANCH" | tr '/' '-')"
|
||||||
|
SHA="${GITHUB_SHA:-${GITEA_SHA:-}}"
|
||||||
|
SHA_SHORT="$(printf '%s' "$SHA" | cut -c1-7)"
|
||||||
|
echo "BRANCH=$BRANCH" >> "$GITHUB_ENV"
|
||||||
|
echo "SHA_SHORT=$SHA_SHORT" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
- name: Resolve Dockerfile
|
||||||
|
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
|
||||||
|
shell: sh
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
DOCKERFILE_PATH="${DOCKERFILE_PATH:-}"
|
||||||
|
BUILD_CONTEXT="${BUILD_CONTEXT:-.}"
|
||||||
|
if [ -z "$DOCKERFILE_PATH" ]; then
|
||||||
|
for candidate in Dockerfile docker/Dockerfile .docker/Dockerfile build/Dockerfile api/Dockerfile api/docker/Dockerfile; do
|
||||||
|
if [ -f "$candidate" ]; then
|
||||||
|
DOCKERFILE_PATH="$candidate"
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
if [ -z "$DOCKERFILE_PATH" ]; then
|
||||||
|
echo "ERROR: Dockerfile not found. Set DOCKERFILE_PATH or add Dockerfile."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "DOCKERFILE_PATH=$DOCKERFILE_PATH" >> "$GITHUB_ENV"
|
||||||
|
echo "BUILD_CONTEXT=$BUILD_CONTEXT" >> "$GITHUB_ENV"
|
||||||
|
|
||||||
|
|
||||||
|
- name: Login registry
|
||||||
|
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
|
||||||
|
shell: sh
|
||||||
|
env:
|
||||||
|
DOCKER_USERNAME: ${{ secrets.DOCKER_USERNAME }}
|
||||||
|
DOCKER_PASSWORD: ${{ secrets.DOCKER_PASSWORD }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
# 使用 Docker Hub 凭证登录
|
||||||
|
if [ -z "${DOCKER_USERNAME:-}" ] || [ -z "${DOCKER_PASSWORD:-}" ]; then
|
||||||
|
echo "ERROR: 缺少 Docker Hub 凭证(DOCKER_USERNAME/DOCKER_PASSWORD)。"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "$DOCKER_PASSWORD" | docker login "$REGISTRY" -u "$DOCKER_USERNAME" --password-stdin
|
||||||
|
|
||||||
|
- name: Build and push images
|
||||||
|
if: ${{ env.CI_TRIGGER_ALLOWED == 'true' }}
|
||||||
|
shell: sh
|
||||||
|
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"
|
||||||
|
|
||||||
|
log_image() {
|
||||||
|
local tag="$1"
|
||||||
|
echo "== Image info: $tag =="
|
||||||
|
docker image inspect --format 'Image ID: {{.Id}} Size: {{.Size}}' "$tag" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
log_layers() {
|
||||||
|
local tag="$1"
|
||||||
|
echo "== RootFS layers (base -> top): $tag =="
|
||||||
|
docker image inspect --format '{{range $i, $layer := .RootFS.Layers}}{{println $i $layer}}{{end}}' "$tag" || true
|
||||||
|
}
|
||||||
|
|
||||||
|
log_history() {
|
||||||
|
local tag="$1"
|
||||||
|
echo "== Image history (top -> base): $tag =="
|
||||||
|
docker history --no-trunc "$tag" | head -n 80 || true
|
||||||
|
echo "== (history truncated to 80 lines) =="
|
||||||
|
}
|
||||||
|
|
||||||
|
log_image "$IMAGE_BRANCH_TAG"
|
||||||
|
log_layers "$IMAGE_BRANCH_TAG"
|
||||||
|
log_history "$IMAGE_BRANCH_TAG"
|
||||||
|
|
||||||
|
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 =="
|
||||||
|
if docker push "$tag" >"$log_file" 2>&1; then
|
||||||
|
tail -n 5 "$log_file" || true
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
log_image "$tag"
|
||||||
|
log_layers "$tag"
|
||||||
|
log_history "$tag"
|
||||||
|
echo "== Docker system info =="
|
||||||
|
docker info || true
|
||||||
|
echo "== Disk usage (df -h) =="
|
||||||
|
df -h || true
|
||||||
|
echo "== Docker disk usage =="
|
||||||
|
docker system df -v | head -n 200 || true
|
||||||
|
echo "== Push failed (tail) for $tag =="
|
||||||
|
tail -n 200 "$log_file" || true
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
push_with_diag "$IMAGE_BRANCH_TAG"
|
||||||
|
push_with_diag "$IMAGE_SHA_TAG"
|
||||||
22
.github/.codecov.yml
vendored
Normal file
22
.github/.codecov.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# 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
|
||||||
10
.github/sync-release.yml
vendored
Normal file
10
.github/sync-release.yml
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
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
Normal file
26
.github/sync.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
# 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
|
||||||
29
.github/workflows/auto-assign-issue.yml
vendored
Normal file
29
.github/workflows/auto-assign-issue.yml
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
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 }}
|
||||||
38
.github/workflows/auto-invite-comment.yml
vendored
Normal file
38
.github/workflows/auto-invite-comment.yml
vendored
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
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&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
|
||||||
52
.github/workflows/auto-invite.yml
vendored
Normal file
52
.github/workflows/auto-invite.yml
vendored
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 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&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
|
||||||
105
.github/workflows/build-docker-image.yml
vendored
Normal file
105
.github/workflows/build-docker-image.yml
vendored
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
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
|
||||||
78
.github/workflows/changelog.yml
vendored
Normal file
78
.github/workflows/changelog.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
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
|
||||||
165
.github/workflows/chat-build-test.yml
vendored
Normal file
165
.github/workflows/chat-build-test.yml
vendored
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
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"
|
||||||
45
.github/workflows/check-coverage.yml
vendored
Normal file
45
.github/workflows/check-coverage.yml
vendored
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
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
|
||||||
40
.github/workflows/cla-assistant.yml
vendored
Normal file
40
.github/workflows/cla-assistant.yml
vendored
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
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
|
||||||
65
.github/workflows/cleanup-after-milestone-prs-merged.yml
vendored
Normal file
65
.github/workflows/cleanup-after-milestone-prs-merged.yml
vendored
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
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 }}
|
||||||
67
.github/workflows/codeql-analysis.yml
vendored
Normal file
67
.github/workflows/codeql-analysis.yml
vendored
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
# 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
|
||||||
51
.github/workflows/comment-check.yml
vendored
Normal file
51
.github/workflows/comment-check.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
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
|
||||||
95
.github/workflows/docker-build-and-release-services-images.yml
vendored
Normal file
95
.github/workflows/docker-build-and-release-services-images.yml
vendored
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
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
|
||||||
31
.github/workflows/gosec.yml
vendored
Normal file
31
.github/workflows/gosec.yml
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
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
|
||||||
22
.github/workflows/help-comment-issue.yml
vendored
Normal file
22
.github/workflows/help-comment-issue.yml
vendored
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
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`.🎯
|
||||||
19
.github/workflows/issue-translator.yml
vendored
Normal file
19
.github/workflows/issue-translator.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
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.
|
||||||
181
.github/workflows/merge-from-milestone.yml
vendored
Normal file
181
.github/workflows/merge-from-milestone.yml
vendored
Normal file
@@ -0,0 +1,181 @@
|
|||||||
|
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
|
||||||
102
.github/workflows/release.yml
vendored
Normal file
102
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
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 }}
|
||||||
|
|
||||||
75
.github/workflows/remove-unused-labels.yml
vendored
Normal file
75
.github/workflows/remove-unused-labels.yml
vendored
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
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 }}
|
||||||
78
.github/workflows/reopen-issue.yml
vendored
Normal file
78
.github/workflows/reopen-issue.yml
vendored
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
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}`);
|
||||||
|
}
|
||||||
119
.github/workflows/update-version-file-on-release.yml
vendored
Normal file
119
.github/workflows/update-version-file-on-release.yml
vendored
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
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
Normal file
376
.gitignore
vendored
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
934
.golangci.yml
Normal file
934
.golangci.yml
Normal file
@@ -0,0 +1,934 @@
|
|||||||
|
# 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
|
||||||
493
.goreleaser.yaml
Normal file
493
.goreleaser.yaml
Normal file
@@ -0,0 +1,493 @@
|
|||||||
|
# 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 }}"
|
||||||
128
CODE_OF_CONDUCT.md
Normal file
128
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
# 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.
|
||||||
371
CONTRIBUTING.md
Normal file
371
CONTRIBUTING.md
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
# 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.
|
||||||
52
Dockerfile
Normal file
52
Dockerfile
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# 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"]
|
||||||
157
HOW_TO_ADD_REST_RPC_API.md
Normal file
157
HOW_TO_ADD_REST_RPC_API.md
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
# 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.
|
||||||
|
|
||||||
|
###
|
||||||
57
HOW_TO_SETUP_LIVEKIT_SERVER.md
Normal file
57
HOW_TO_SETUP_LIVEKIT_SERVER.md
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# 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
Normal file
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
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.
|
||||||
89
README.md
89
README.md
@@ -0,0 +1,89 @@
|
|||||||
|
# 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
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
89
README_zh_CN.md
Normal file
89
README_zh_CN.md
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
# 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
|
||||||
31
bootstrap.bat
Normal file
31
bootstrap.bat
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
@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
|
||||||
23
bootstrap.sh
Executable file
23
bootstrap.sh
Executable file
@@ -0,0 +1,23 @@
|
|||||||
|
#!/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
|
||||||
65
build/README.md
Normal file
65
build/README.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# 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
|
||||||
24
build/images/Dockerfile
Normal file
24
build/images/Dockerfile
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
# 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"]
|
||||||
39
build/images/openim-admin-api/Dockerfile
Normal file
39
build/images/openim-admin-api/Dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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"]
|
||||||
39
build/images/openim-admin-rpc/Dockerfile
Normal file
39
build/images/openim-admin-rpc/Dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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"]
|
||||||
51
build/images/openim-chat-api/Dockerfile
Normal file
51
build/images/openim-chat-api/Dockerfile
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# 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"]
|
||||||
39
build/images/openim-chat-rpc/Dockerfile
Normal file
39
build/images/openim-chat-rpc/Dockerfile
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
# 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"]
|
||||||
26
cmd/api/admin-api/main.go
Normal file
26
cmd/api/admin-api/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cmd/api/bot-api/main.go
Normal file
26
cmd/api/bot-api/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cmd/api/chat-api/main.go
Normal file
26
cmd/api/chat-api/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cmd/rpc/admin-rpc/main.go
Normal file
26
cmd/rpc/admin-rpc/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cmd/rpc/bot-rpc/main.go
Normal file
26
cmd/rpc/bot-rpc/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
26
cmd/rpc/chat-rpc/main.go
Normal file
26
cmd/rpc/chat-rpc/main.go
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
44
config/README.md
Normal file
44
config/README.md
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
45
config/README_zh_CN.md
Normal file
45
config/README_zh_CN.md
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
6
config/chat-api-admin.yml
Normal file
6
config/chat-api-admin.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
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 ]
|
||||||
|
|
||||||
6
config/chat-api-bot.yml
Normal file
6
config/chat-api-bot.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
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 ]
|
||||||
|
|
||||||
6
config/chat-api-chat.yml
Normal file
6
config/chat-api-chat.yml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
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 ]
|
||||||
|
|
||||||
12
config/chat-rpc-admin.yml
Normal file
12
config/chat-rpc-admin.yml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
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
|
||||||
10
config/chat-rpc-bot.yml
Normal file
10
config/chat-rpc-bot.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
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
|
||||||
44
config/chat-rpc-chat.yml
Normal file
44
config/chat-rpc-chat.yml
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
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则隐藏验证码登录功能
|
||||||
14
config/discovery.yml
Normal file
14
config/discovery.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
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
|
||||||
14
config/log.yml
Normal file
14
config/log.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 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
|
||||||
16
config/mongodb.yml
Normal file
16
config/mongodb.yml
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
# 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
|
||||||
14
config/redis.yml
Normal file
14
config/redis.yml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
# 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
|
||||||
13
config/share.yml
Normal file
13
config/share.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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"
|
||||||
122
deployments/README.md
Normal file
122
deployments/README.md
Normal file
@@ -0,0 +1,122 @@
|
|||||||
|
# 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.
|
||||||
148
deployments/deploy/chat-config.yml
Normal file
148
deployments/deploy/chat-config.yml
Normal file
@@ -0,0 +1,148 @@
|
|||||||
|
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
|
||||||
8
deployments/deploy/mongo-secret.yml
Normal file
8
deployments/deploy/mongo-secret.yml
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
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"
|
||||||
49
deployments/deploy/openim-admin-api-deployment.yml
Normal file
49
deployments/deploy/openim-admin-api-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
deployments/deploy/openim-admin-api-service.yml
Normal file
13
deployments/deploy/openim-admin-api-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
deployments/deploy/openim-admin-rpc-deployment.yml
Normal file
49
deployments/deploy/openim-admin-rpc-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
deployments/deploy/openim-admin-rpc-service.yml
Normal file
13
deployments/deploy/openim-admin-rpc-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
deployments/deploy/openim-chat-api-deployment.yml
Normal file
49
deployments/deploy/openim-chat-api-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
deployments/deploy/openim-chat-api-service.yml
Normal file
13
deployments/deploy/openim-chat-api-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
49
deployments/deploy/openim-chat-rpc-deployment.yml
Normal file
49
deployments/deploy/openim-chat-rpc-deployment.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
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
|
||||||
13
deployments/deploy/openim-chat-rpc-service.yml
Normal file
13
deployments/deploy/openim-chat-rpc-service.yml
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
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
|
||||||
7
deployments/deploy/redis-secret.yml
Normal file
7
deployments/deploy/redis-secret.yml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: openim-redis-secret
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
redis-password: b3BlbklNMTIz # "openIM123" in base64
|
||||||
174
deployments/observability/README.md
Normal file
174
deployments/observability/README.md
Normal file
@@ -0,0 +1,174 @@
|
|||||||
|
# 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
|
||||||
|
```
|
||||||
71
deployments/observability/config.env.example
Normal file
71
deployments/observability/config.env.example
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
# ==============================
|
||||||
|
# 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
|
||||||
236
deployments/observability/config/prometheus-agent-entrypoint.sh
Normal file
236
deployments/observability/config/prometheus-agent-entrypoint.sh
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
set -eu
|
||||||
|
|
||||||
|
# ------------------------------
|
||||||
|
# chat-deploy 指标采集:Prometheus Agent Entrypoint
|
||||||
|
# - 根据环境变量生成 /prometheus/prometheus.yml 与 /prometheus/targets.json
|
||||||
|
# - 然后以 agent 模式启动 Prometheus(remote_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
|
||||||
61
deployments/observability/config/promtail.yaml
Normal file
61
deployments/observability/config/promtail.yaml
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
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
|
||||||
135
deployments/observability/docker-compose-observability.yaml
Normal file
135
deployments/observability/docker-compose-observability.yaml
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
# 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: {}
|
||||||
84
docs/.generated_docs
Normal file
84
docs/.generated_docs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
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
|
||||||
340
docs/API_SCHEDULED_TASK.md
Normal file
340
docs/API_SCHEDULED_TASK.md
Normal file
@@ -0,0 +1,340 @@
|
|||||||
|
# 定时任务 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-7(0和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. 服务端只负责存储配置,不执行定时任务
|
||||||
|
|
||||||
739
docs/API_SYSTEM_CONFIG.md
Normal file
739
docs/API_SYSTEM_CONFIG.md
Normal file
@@ -0,0 +1,739 @@
|
|||||||
|
# 系统配置管理 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`。
|
||||||
453
docs/API_WALLET_SUMMARY.md
Normal file
453
docs/API_WALLET_SUMMARY.md
Normal file
@@ -0,0 +1,453 @@
|
|||||||
|
# 钱包相关接口汇总
|
||||||
|
|
||||||
|
## 基础信息
|
||||||
|
|
||||||
|
- **基础路径**: `/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分)
|
||||||
|
- 时间戳单位为毫秒
|
||||||
486
docs/API_WITHDRAW_ADMIN.md
Normal file
486
docs/API_WITHDRAW_ADMIN.md
Normal file
@@ -0,0 +1,486 @@
|
|||||||
|
# 提现管理后台接口文档
|
||||||
|
|
||||||
|
## 接口列表
|
||||||
|
|
||||||
|
| 接口地址 | 请求方法 | 说明 |
|
||||||
|
|---------|---------|------|
|
||||||
|
| `/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` 集合
|
||||||
439
docs/API_WITHDRAW_APPLICATION.md
Normal file
439
docs/API_WITHDRAW_APPLICATION.md
Normal file
@@ -0,0 +1,439 @@
|
|||||||
|
# 提现申请接口文档
|
||||||
|
|
||||||
|
## 基础信息
|
||||||
|
|
||||||
|
- **基础路径**: `/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#获取钱包详细信息)
|
||||||
|
- [设置支付密码](#设置支付密码)
|
||||||
1
docs/CODEOWNERS
Normal file
1
docs/CODEOWNERS
Normal file
@@ -0,0 +1 @@
|
|||||||
|
* @Bloomingg @FGadvancer @skiffer-git @withchao
|
||||||
129
docs/contrib/cicd-actions.md
Normal file
129
docs/contrib/cicd-actions.md
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
# 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! 🚀😊
|
||||||
38
docs/contrib/code_conventions.md
Normal file
38
docs/contrib/code_conventions.md
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
# 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.
|
||||||
80
docs/contrib/development.md
Normal file
80
docs/contrib/development.md
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
# 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
Reference in New Issue
Block a user