chore: 统一本地服务器与远程仓库源码
- 合并 main 与 master 历史并以服务器结构为基线 - 保留迁移、数据保留、AWS 账单与部署安全能力 - 建立 SDD 规格和 CI 验证闭环
This commit is contained in:
commit
fd60361d93
460 files changed
+37492
-23871
No files matched your search
+152
-100
@@ -2,23 +2,23 @@ package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
)
|
||||
|
||||
// Pipeline CI/CD流水线模型
|
||||
type Pipeline struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Name string `gorm:"size:128;not null" json:"name"`
|
||||
Code string `gorm:"size:64;uniqueIndex;not null" json:"code"`
|
||||
JobName string `gorm:"size:128;uniqueIndex;comment:Job名称(webhook URL标识, 如 cex-admin-server)" json:"job_name,omitempty"`
|
||||
Description string `gorm:"size:500" json:"description"`
|
||||
Type string `gorm:"size:32;default:deploy" json:"type"` // build, deploy, test
|
||||
Source string `gorm:"size:255" json:"source"` // Git仓库地址
|
||||
Branch string `gorm:"size:64;default:main" json:"branch"`
|
||||
Dockerfile string `gorm:"size:255" json:"dockerfile"`
|
||||
Stages string `gorm:"type:text" json:"stages"` // JSON
|
||||
Variables string `gorm:"type:text" json:"variables"` // JSON
|
||||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Name string `gorm:"size:128;not null" json:"name"`
|
||||
Code string `gorm:"size:64;uniqueIndex;not null" json:"code"`
|
||||
JobName string `gorm:"size:128;uniqueIndex;comment:Job名称(webhook URL标识, 如 cex-admin-server)" json:"job_name,omitempty"`
|
||||
Description string `gorm:"size:500" json:"description"`
|
||||
Type string `gorm:"size:32;default:deploy" json:"type"` // build, deploy, test
|
||||
CIProvider string `gorm:"column:ci_provider;size:32;default:aiops;index;comment:流水线执行引擎 aiops/jenkins" json:"ci_provider"`
|
||||
Source string `gorm:"size:255" json:"source"` // Git仓库地址
|
||||
Branch string `gorm:"size:64;default:main" json:"branch"`
|
||||
Dockerfile string `gorm:"size:255" json:"dockerfile"`
|
||||
Stages string `gorm:"type:text" json:"stages"` // JSON
|
||||
Variables string `gorm:"type:text" json:"variables"` // JSON
|
||||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||||
|
||||
// 部署模式
|
||||
DeployMode string `gorm:"size:16;default:branch;comment:部署模式 branch/tag" json:"deploy_mode"`
|
||||
@@ -36,16 +36,12 @@ type Pipeline struct {
|
||||
DeployScript string `gorm:"type:text;comment:SSH部署后执行命令" json:"deploy_script,omitempty"`
|
||||
|
||||
// K8s 部署目标
|
||||
K8sClusterID *uint `json:"k8s_cluster_id,omitempty"` // FK → kubernetes_clusters
|
||||
K8sClusterID *uint `json:"k8s_cluster_id,omitempty"` // FK → k8s_clusters
|
||||
K8sNamespace string `gorm:"size:128;comment:K8s部署命名空间" json:"k8s_namespace,omitempty"`
|
||||
K8sDeployment string `gorm:"size:128;comment:K8s Deployment 名称" json:"k8s_deployment,omitempty"`
|
||||
K8sContainerName string `gorm:"size:128;comment:K8s更新镜像目标容器" json:"k8s_container_name,omitempty"`
|
||||
|
||||
// 仓库和镜像仓库关联(旧字段,待废弃)
|
||||
RepoID *uint `json:"repo_id"` // FK → deploy_pipeline_repos
|
||||
RegistryID *uint `json:"registry_id"` // FK → deploy_pipeline_registries
|
||||
|
||||
// 凭证关联(直接关联凭证 ID)
|
||||
// 凭证关联(直接关联统一凭证 ID)// Logan.Li
|
||||
GitCredentialID *uint `json:"git_credential_id"` // FK → iam_credentials (Git Token)
|
||||
RegistryCredentialID *uint `json:"registry_credential_id"` // FK → iam_credentials (Docker Password)
|
||||
|
||||
@@ -62,6 +58,15 @@ type Pipeline struct {
|
||||
// 缓存配置
|
||||
CachePaths string `gorm:"type:text;comment:缓存路径(逗号分隔)" json:"cache_paths,omitempty"`
|
||||
|
||||
// Jenkins 外部流水线映射,ci_provider=jenkins 时生效。 // Logan.Li
|
||||
JenkinsJobName string `gorm:"size:255;index;comment:Jenkins Job 名称或 folder/job 路径" json:"jenkins_job_name,omitempty"`
|
||||
JenkinsJobURL string `gorm:"size:500;comment:Jenkins Job URL" json:"jenkins_job_url,omitempty"`
|
||||
JenkinsView string `gorm:"size:128;index;comment:Jenkins 主视图名称" json:"jenkins_view,omitempty"`
|
||||
JenkinsViewURL string `gorm:"size:500;comment:Jenkins 主视图 URL" json:"jenkins_view_url,omitempty"`
|
||||
JenkinsViews string `gorm:"type:text;comment:Jenkins 视图列表 JSON" json:"jenkins_views,omitempty"`
|
||||
JenkinsParams string `gorm:"type:text;comment:Jenkins 参数定义 JSON" json:"jenkins_params,omitempty"`
|
||||
JenkinsSteps string `gorm:"type:text;comment:Jenkins 构建步骤只读摘要 JSON" json:"jenkins_steps,omitempty"`
|
||||
|
||||
LastRunAt *time.Time `json:"last_run_at"`
|
||||
LastStatus string `gorm:"size:32" json:"last_status"`
|
||||
RunCount int `gorm:"default:0" json:"run_count"`
|
||||
@@ -71,39 +76,39 @@ type Pipeline struct {
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// 关联
|
||||
Repo *PipelineRepo `json:"repo,omitempty" gorm:"foreignKey:RepoID"`
|
||||
Registry *PipelineRegistry `json:"registry,omitempty" gorm:"foreignKey:RegistryID"`
|
||||
Environment *DeployEnvironment `json:"environment,omitempty" gorm:"foreignKey:EnvironmentID"`
|
||||
Environment *DeployEnvironment `json:"environment,omitempty" gorm:"foreignKey:EnvironmentID"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
func (Pipeline) TableName() string {
|
||||
return "ops_pipelines"
|
||||
return "deploy_pipelines"
|
||||
}
|
||||
|
||||
// PipelineRun 流水线运行记录(CI 执行)
|
||||
type PipelineRun struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
PipelineID uint `gorm:"not null" json:"pipeline_id"`
|
||||
BuildNumber int `json:"build_number"`
|
||||
Status string `gorm:"size:32;default:pending" json:"status"` // pending, running, success, failed, cancelled
|
||||
Branch string `gorm:"size:64" json:"branch"`
|
||||
CommitID string `gorm:"size:64" json:"commit_id"`
|
||||
CommitMsg string `gorm:"size:500" json:"commit_msg"`
|
||||
Author string `gorm:"size:64" json:"author"`
|
||||
ImageTag string `gorm:"size:255" json:"image_tag"` // 构建产物镜像标签
|
||||
ArtifactURL string `gorm:"size:500" json:"artifact_url"` // 构建产物地址
|
||||
WorkspacePath string `gorm:"size:500" json:"workspace_path"` // 工作区路径
|
||||
BuildNodeID *uint `json:"build_node_id,omitempty"` // 实际执行节点(0/nil=Master)
|
||||
BuildNodeName string `gorm:"size:64" json:"build_node_name,omitempty"`
|
||||
Duration int `json:"duration"` // 秒
|
||||
Stages string `gorm:"type:text" json:"stages"` // JSON
|
||||
Logs string `gorm:"type:longtext" json:"logs"`
|
||||
TriggeredBy string `gorm:"size:64" json:"triggered_by"`
|
||||
StartedAt *time.Time `json:"started_at"`
|
||||
FinishedAt *time.Time `json:"finished_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
PipelineID uint `gorm:"not null" json:"pipeline_id"`
|
||||
BuildNumber int `json:"build_number"`
|
||||
Status string `gorm:"size:32;default:pending" json:"status"` // pending, running, success, failed, cancelled
|
||||
Branch string `gorm:"size:64" json:"branch"`
|
||||
CommitID string `gorm:"size:64" json:"commit_id"`
|
||||
CommitMsg string `gorm:"size:500" json:"commit_msg"`
|
||||
Author string `gorm:"size:64" json:"author"`
|
||||
ImageTag string `gorm:"size:255" json:"image_tag"` // 构建产物镜像标签
|
||||
ArtifactURL string `gorm:"size:500" json:"artifact_url"` // 构建产物地址
|
||||
WorkspacePath string `gorm:"size:500" json:"workspace_path"` // 工作区路径
|
||||
BuildNodeID *uint `json:"build_node_id,omitempty"` // 实际执行节点(0/nil=Master)
|
||||
BuildNodeName string `gorm:"size:64" json:"build_node_name,omitempty"`
|
||||
Duration int `json:"duration"` // 秒
|
||||
Stages string `gorm:"type:text" json:"stages"` // JSON
|
||||
Logs string `gorm:"type:longtext" json:"logs"`
|
||||
TriggeredBy string `gorm:"size:64" json:"triggered_by"`
|
||||
ExternalRunID string `gorm:"size:128;index;comment:外部 CI 构建号/队列号" json:"external_run_id,omitempty"`
|
||||
ExternalURL string `gorm:"size:500;comment:外部 CI 构建 URL" json:"external_url,omitempty"`
|
||||
StartedAt *time.Time `json:"started_at"`
|
||||
FinishedAt *time.Time `json:"finished_at"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
|
||||
// 关联
|
||||
Pipeline *Pipeline `json:"pipeline,omitempty"`
|
||||
@@ -111,34 +116,53 @@ type PipelineRun struct {
|
||||
|
||||
// TableName 表名
|
||||
func (PipelineRun) TableName() string {
|
||||
return "ops_pipeline_runs"
|
||||
return "deploy_pipeline_runs"
|
||||
}
|
||||
|
||||
// JenkinsConfig 保存 Jenkins 外部 CI 接入配置,密钥加密后落库。 // Logan.Li
|
||||
type JenkinsConfig struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
BaseURL string `gorm:"size:255;not null" json:"base_url"`
|
||||
Username string `gorm:"size:128" json:"username"`
|
||||
Token string `gorm:"type:text" json:"-"`
|
||||
AuthType string `gorm:"size:32;default:token" json:"auth_type"`
|
||||
Enabled bool `gorm:"default:true" json:"enabled"`
|
||||
RefMode string `gorm:"size:16;default:both;comment:Jenkins 分支/Tag 选择模式 branch/tag/both" json:"ref_mode"`
|
||||
RefParam string `gorm:"size:64;default:SELECT;comment:Jenkins 分支或 Tag 参数名" json:"ref_param"`
|
||||
LastSyncAt *time.Time `json:"last_sync_at,omitempty"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
func (JenkinsConfig) TableName() string {
|
||||
return "deploy_jenkins_configs"
|
||||
}
|
||||
|
||||
// AppRelease 应用发布模型(CD:从 CI 产物部署到目标环境)
|
||||
type AppRelease struct {
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
PipelineID *uint `json:"pipeline_id"` // 来源流水线
|
||||
PipelineRunID *uint `json:"pipeline_run_id"` // 来源 CI 执行记录
|
||||
AppName string `gorm:"size:128;not null" json:"app_name"`
|
||||
Version string `gorm:"size:64;not null" json:"version"`
|
||||
Environment string `gorm:"size:32;not null" json:"environment"` // dev, test, staging, prod
|
||||
DeployType string `gorm:"size:32;default:server" json:"deploy_type"` // server, kubernetes
|
||||
Status string `gorm:"size:32;default:pending" json:"status"` // pending, approved, rejected, deploying, success, failed, rolled_back
|
||||
CommitID string `gorm:"size:64" json:"commit_id"`
|
||||
CommitMsg string `gorm:"size:500" json:"commit_msg"`
|
||||
Author string `gorm:"size:64" json:"author"`
|
||||
Approver string `gorm:"size:64" json:"approver"`
|
||||
ApprovedAt *time.Time `json:"approved_at"`
|
||||
DeployedAt *time.Time `json:"deployed_at"`
|
||||
RollbackAt *time.Time `json:"rollback_at"`
|
||||
Duration int `json:"duration"`
|
||||
ImageTag string `gorm:"size:255" json:"image_tag"` // 构建产物镜像标签
|
||||
K8sClusterID *uint `json:"k8s_cluster_id"` // Kubernetes 部署目标集群
|
||||
K8sNamespace string `gorm:"size:128" json:"k8s_namespace"` // Kubernetes 部署目标命名空间
|
||||
Servers string `gorm:"type:text" json:"servers"` // JSON(传统服务器部署目标)
|
||||
Description string `gorm:"size:500" json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
PipelineID *uint `json:"pipeline_id"` // 来源流水线
|
||||
PipelineRunID *uint `json:"pipeline_run_id"` // 来源 CI 执行记录
|
||||
AppName string `gorm:"size:128;not null" json:"app_name"`
|
||||
Version string `gorm:"size:64;not null" json:"version"`
|
||||
Environment string `gorm:"size:32;not null" json:"environment"` // dev, test, staging, prod
|
||||
DeployType string `gorm:"size:32;default:server" json:"deploy_type"` // server, kubernetes
|
||||
Status string `gorm:"size:32;default:pending" json:"status"` // pending, approved, rejected, deploying, success, failed, rolled_back
|
||||
CommitID string `gorm:"size:64" json:"commit_id"`
|
||||
CommitMsg string `gorm:"size:500" json:"commit_msg"`
|
||||
Author string `gorm:"size:64" json:"author"`
|
||||
Approver string `gorm:"size:64" json:"approver"`
|
||||
ApprovedAt *time.Time `json:"approved_at"`
|
||||
DeployedAt *time.Time `json:"deployed_at"`
|
||||
RollbackAt *time.Time `json:"rollback_at"`
|
||||
Duration int `json:"duration"`
|
||||
ImageTag string `gorm:"size:255" json:"image_tag"` // 构建产物镜像标签
|
||||
K8sClusterID *uint `json:"k8s_cluster_id"` // Kubernetes 部署目标集群
|
||||
K8sNamespace string `gorm:"size:128" json:"k8s_namespace"` // Kubernetes 部署目标命名空间
|
||||
Servers string `gorm:"type:text" json:"servers"` // JSON(传统服务器部署目标)
|
||||
Description string `gorm:"size:500" json:"description"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
|
||||
// TableName 表名
|
||||
@@ -150,9 +174,10 @@ func (AppRelease) TableName() string {
|
||||
type CreatePipelineRequest struct {
|
||||
Name string `json:"name" binding:"required"`
|
||||
Code string `json:"code" binding:"required"`
|
||||
JobName string `json:"job_name"` // Webhook Job名称
|
||||
JobName string `json:"job_name"` // Webhook Job名称
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type" binding:"omitempty,oneof=build deploy test"`
|
||||
CIProvider string `json:"ci_provider"`
|
||||
Source string `json:"source"`
|
||||
Branch string `json:"branch"`
|
||||
Dockerfile string `json:"dockerfile"`
|
||||
@@ -160,9 +185,9 @@ type CreatePipelineRequest struct {
|
||||
Variables string `json:"variables"`
|
||||
|
||||
// 部署模式
|
||||
DeployMode string `json:"deploy_mode"` // branch / tag
|
||||
DeployTarget string `json:"deploy_target"` // ssh / k8s
|
||||
ServerIDs string `json:"server_ids"` // SSH 服务器ID JSON [1,2,3]
|
||||
DeployMode string `json:"deploy_mode"` // branch / tag
|
||||
DeployTarget string `json:"deploy_target"` // ssh / k8s
|
||||
ServerIDs string `json:"server_ids"` // SSH 服务器ID JSON [1,2,3]
|
||||
DeployRemotePath string `json:"deploy_remote_path"`
|
||||
DeployScript string `json:"deploy_script"`
|
||||
K8sClusterID *uint `json:"k8s_cluster_id"`
|
||||
@@ -170,12 +195,10 @@ type CreatePipelineRequest struct {
|
||||
K8sDeployment string `json:"k8s_deployment"`
|
||||
K8sContainerName string `json:"k8s_container_name"`
|
||||
|
||||
RepoID *uint `json:"repo_id"`
|
||||
RegistryID *uint `json:"registry_id"`
|
||||
// 凭证关联
|
||||
// 凭证关联 // Logan.Li
|
||||
GitCredentialID *uint `json:"git_credential_id"`
|
||||
RegistryCredentialID *uint `json:"registry_credential_id"`
|
||||
EnvironmentID *uint `json:"environment_id"`
|
||||
EnvironmentID *uint `json:"environment_id"`
|
||||
|
||||
// 触发配置
|
||||
TriggerMode string `json:"trigger_mode"`
|
||||
@@ -187,6 +210,13 @@ type CreatePipelineRequest struct {
|
||||
// 缓存路径
|
||||
CachePaths string `json:"cache_paths"`
|
||||
|
||||
JenkinsJobName string `json:"jenkins_job_name"`
|
||||
JenkinsJobURL string `json:"jenkins_job_url"`
|
||||
JenkinsView string `json:"jenkins_view"`
|
||||
JenkinsViewURL string `json:"jenkins_view_url"`
|
||||
JenkinsViews string `json:"jenkins_views"`
|
||||
JenkinsParams string `json:"jenkins_params"`
|
||||
|
||||
// 并发控制
|
||||
MaxExecutors int `json:"max_executors"`
|
||||
|
||||
@@ -196,17 +226,18 @@ type CreatePipelineRequest struct {
|
||||
|
||||
// UpdatePipelineRequest 更新流水线请求
|
||||
type UpdatePipelineRequest struct {
|
||||
Name string `json:"name"`
|
||||
JobName string `json:"job_name"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
Source string `json:"source"`
|
||||
Branch string `json:"branch"`
|
||||
Dockerfile string `json:"dockerfile"`
|
||||
Stages string `json:"stages"`
|
||||
Variables string `json:"variables"`
|
||||
DeployMode string `json:"deploy_mode"`
|
||||
DeployTarget string `json:"deploy_target"`
|
||||
Name string `json:"name"`
|
||||
JobName string `json:"job_name"`
|
||||
Description string `json:"description"`
|
||||
Type string `json:"type"`
|
||||
CIProvider string `json:"ci_provider"`
|
||||
Source string `json:"source"`
|
||||
Branch string `json:"branch"`
|
||||
Dockerfile string `json:"dockerfile"`
|
||||
Stages string `json:"stages"`
|
||||
Variables string `json:"variables"`
|
||||
DeployMode string `json:"deploy_mode"`
|
||||
DeployTarget string `json:"deploy_target"`
|
||||
ServerIDs string `json:"server_ids"`
|
||||
DeployRemotePath string `json:"deploy_remote_path"`
|
||||
DeployScript string `json:"deploy_script"`
|
||||
@@ -214,12 +245,10 @@ type UpdatePipelineRequest struct {
|
||||
K8sNamespace string `json:"k8s_namespace"`
|
||||
K8sDeployment string `json:"k8s_deployment"`
|
||||
K8sContainerName string `json:"k8s_container_name"`
|
||||
RepoID *uint `json:"repo_id"`
|
||||
RegistryID *uint `json:"registry_id"`
|
||||
// 凭证关联
|
||||
// 凭证关联 // Logan.Li
|
||||
GitCredentialID *uint `json:"git_credential_id"`
|
||||
RegistryCredentialID *uint `json:"registry_credential_id"`
|
||||
EnvironmentID *uint `json:"environment_id"`
|
||||
EnvironmentID *uint `json:"environment_id"`
|
||||
// 触发配置
|
||||
TriggerMode string `json:"trigger_mode"`
|
||||
WatchBranches string `json:"watch_branches"`
|
||||
@@ -227,8 +256,14 @@ type UpdatePipelineRequest struct {
|
||||
CronExpr string `json:"cron_expr"`
|
||||
WebhookToken string `json:"webhook_token"`
|
||||
// 缓存
|
||||
CachePaths string `json:"cache_paths"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
CachePaths string `json:"cache_paths"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
JenkinsJobName string `json:"jenkins_job_name"`
|
||||
JenkinsJobURL string `json:"jenkins_job_url"`
|
||||
JenkinsView string `json:"jenkins_view"`
|
||||
JenkinsViewURL string `json:"jenkins_view_url"`
|
||||
JenkinsViews string `json:"jenkins_views"`
|
||||
JenkinsParams string `json:"jenkins_params"`
|
||||
|
||||
// 并发控制
|
||||
MaxExecutors int `json:"max_executors"`
|
||||
@@ -240,10 +275,27 @@ type UpdatePipelineRequest struct {
|
||||
// TriggerPipelineRequest 触发流水线请求
|
||||
type TriggerPipelineRequest struct {
|
||||
Branch string `json:"branch"`
|
||||
Tag string `json:"tag"` // 发布 Tag
|
||||
Tag string `json:"tag"` // 发布 Tag
|
||||
Variables map[string]string `json:"variables"`
|
||||
}
|
||||
|
||||
// JenkinsConfigRequest 保存 Jenkins 接入配置。Token 为空时保留旧密钥。 // Logan.Li
|
||||
type JenkinsConfigRequest struct {
|
||||
BaseURL string `json:"base_url" binding:"required"`
|
||||
Username string `json:"username"`
|
||||
Token string `json:"token"`
|
||||
AuthType string `json:"auth_type"`
|
||||
Enabled *bool `json:"enabled"`
|
||||
RefMode string `json:"ref_mode"`
|
||||
RefParam string `json:"ref_param"`
|
||||
}
|
||||
|
||||
// JenkinsSyncRequest 同步 Jenkins Jobs 到 AIOps 流水线。 // Logan.Li
|
||||
type JenkinsSyncRequest struct {
|
||||
Prefix string `json:"prefix"`
|
||||
Overwrite bool `json:"overwrite"`
|
||||
}
|
||||
|
||||
// CreateAppReleaseRequest 创建应用发布请求
|
||||
type CreateAppReleaseRequest struct {
|
||||
PipelineID *uint `json:"pipeline_id"`
|
||||
@@ -263,10 +315,10 @@ type CreateAppReleaseRequest struct {
|
||||
|
||||
// PipelineStats 流水线统计
|
||||
type PipelineStats struct {
|
||||
Total int64 `json:"total"`
|
||||
Success int64 `json:"success"`
|
||||
Failed int64 `json:"failed"`
|
||||
Running int64 `json:"running"`
|
||||
TodayCount int64 `json:"today_count"`
|
||||
SuccessRate float64 `json:"success_rate"`
|
||||
Total int64 `json:"total"`
|
||||
Success int64 `json:"success"`
|
||||
Failed int64 `json:"failed"`
|
||||
Running int64 `json:"running"`
|
||||
TodayCount int64 `json:"today_count"`
|
||||
SuccessRate float64 `json:"success_rate"`
|
||||
}
|
||||
Reference in new issue
Block a user