Create & Init Project...
This commit is contained in:
22
app/admin/ep/marthe/BUILD
Normal file
22
app/admin/ep/marthe/BUILD
Normal file
@ -0,0 +1,22 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//app/admin/ep/marthe/cmd:all-srcs",
|
||||
"//app/admin/ep/marthe/conf:all-srcs",
|
||||
"//app/admin/ep/marthe/dao:all-srcs",
|
||||
"//app/admin/ep/marthe/model:all-srcs",
|
||||
"//app/admin/ep/marthe/server/http:all-srcs",
|
||||
"//app/admin/ep/marthe/service:all-srcs",
|
||||
],
|
||||
tags = ["automanaged"],
|
||||
)
|
4
app/admin/ep/marthe/CHANGELOG.md
Normal file
4
app/admin/ep/marthe/CHANGELOG.md
Normal file
@ -0,0 +1,4 @@
|
||||
##### marthe
|
||||
|
||||
##### Version 1. 0. 1
|
||||
1. 拉取bugly原始数据以自定义的格式落库
|
14
app/admin/ep/marthe/CONTRIBUTORS.md
Normal file
14
app/admin/ep/marthe/CONTRIBUTORS.md
Normal file
@ -0,0 +1,14 @@
|
||||
# Owner
|
||||
maojian
|
||||
yuanmin
|
||||
fengyifeng
|
||||
xuneng
|
||||
|
||||
# Author
|
||||
yuanmin
|
||||
fengyifeng
|
||||
xuneng
|
||||
|
||||
# Reviewer
|
||||
zhapuyu
|
||||
wangxu01
|
19
app/admin/ep/marthe/OWNERS
Normal file
19
app/admin/ep/marthe/OWNERS
Normal file
@ -0,0 +1,19 @@
|
||||
# See the OWNERS docs at https://go.k8s.io/owners
|
||||
|
||||
approvers:
|
||||
- fengyifeng
|
||||
- maojian
|
||||
- xuneng
|
||||
- yuanmin
|
||||
labels:
|
||||
- admin
|
||||
- admin/ep/marthe
|
||||
- ep
|
||||
options:
|
||||
no_parent_owners: true
|
||||
reviewers:
|
||||
- fengyifeng
|
||||
- wangxu01
|
||||
- xuneng
|
||||
- yuanmin
|
||||
- zhapuyu
|
19
app/admin/ep/marthe/README.md
Normal file
19
app/admin/ep/marthe/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Marthe-service
|
||||
|
||||
# 项目简介
|
||||
### 背景/Background
|
||||
* 目前移动端crash信息会上报到bugly,bugly系统查询数据比较慢且没有足够的数据分析功能,影响开发查询分析crash的效率
|
||||
* 目前项目需求bug等信息记录在tapd, 同样tapd系统现有的报表功能并不满足我们PMO的需求,使PMO拿不到充足的数据做分析
|
||||
* 于是Marthe项目为了解决这些问题孕育而生
|
||||
|
||||
### 概览/Overview
|
||||
* Marthe会根据开发和测试的需求,从bugly拉取原始数据并进行二次处理
|
||||
|
||||
|
||||
# 编译环境
|
||||
|
||||
|
||||
# 依赖包
|
||||
|
||||
|
||||
# 编译执行
|
44
app/admin/ep/marthe/cmd/BUILD
Normal file
44
app/admin/ep/marthe/cmd/BUILD
Normal file
@ -0,0 +1,44 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_binary",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "cmd",
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
data = ["admin.toml"],
|
||||
importpath = "go-common/app/admin/ep/marthe/cmd",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/marthe/conf:go_default_library",
|
||||
"//app/admin/ep/marthe/server/http:go_default_library",
|
||||
"//app/admin/ep/marthe/service:go_default_library",
|
||||
"//library/ecode/tip:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/trace:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
130
app/admin/ep/marthe/cmd/admin.toml
Normal file
130
app/admin/ep/marthe/cmd/admin.toml
Normal file
@ -0,0 +1,130 @@
|
||||
|
||||
[bm]
|
||||
addr = "0.0.0.0:9001"
|
||||
timeout = "10s"
|
||||
|
||||
[httpClient]
|
||||
key = "c05dd4e1638a8af0"
|
||||
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
|
||||
dial = "2s"
|
||||
timeout = "100s"
|
||||
keepAlive = "60s"
|
||||
timer = 1000
|
||||
[httpClient.breaker]
|
||||
window = "10s"
|
||||
sleep = "2000ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
|
||||
[mail]
|
||||
host = "smtp.exmail.qq.com"
|
||||
port = 465
|
||||
username = "merlin@bilibili.com"
|
||||
password = ""
|
||||
noticeOwner = ["fengyifeng@bilibili.com"]
|
||||
|
||||
[memcache]
|
||||
name = "merlin"
|
||||
proto = "tcp"
|
||||
addr = "172.18.33.61:11232"
|
||||
idle = 5
|
||||
active = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "10s"
|
||||
expire = "12h"
|
||||
|
||||
[bugly]
|
||||
#bugly URL
|
||||
host = "https://bugly.qq.com"
|
||||
|
||||
#bugly请求尝试次数
|
||||
urlRetryCount = 3
|
||||
|
||||
#cookie 使用上限次数
|
||||
cookieUsageUpper = 300
|
||||
|
||||
#bugly 每页获取issue个数
|
||||
issuePageSize = 50
|
||||
|
||||
#bugly 抓取issue上限个数
|
||||
issueCountUpper = 100
|
||||
|
||||
#bugly 超级管理员
|
||||
superOwner = ["fengyifeng","yuanmin"]
|
||||
|
||||
[tapd]
|
||||
#tapd bug相关操作 是否认证tapd权限
|
||||
bugOperateAuth = false
|
||||
|
||||
|
||||
[Scheduler]
|
||||
#每过30分钟 跑enable version 抓bugly数据
|
||||
batchRunEnableVersion = "0 */30 * * * ?"
|
||||
|
||||
#每天晚上23点 定时更新tapd bug
|
||||
batchRunUpdateTapdBug = "0 0 23 * * ?"
|
||||
|
||||
#每10分钟,定时删除超过三小时为执行完毕的任务
|
||||
disableBatchRunOverTime = "0 */10 * * * ?"
|
||||
#过期时限
|
||||
batchRunOverHourTime = 3
|
||||
|
||||
#每天晚上22点,更新同步wechat contact
|
||||
syncWechatContact = "0 0 22 * * ?"
|
||||
|
||||
#是否开启定时任务
|
||||
active = false
|
||||
|
||||
|
||||
[orm]
|
||||
dsn = "root:123456@tcp(172.18.33.130:3306)/Marthe2?timeout=200ms&readTimeout=2000ms&writeTimeout=2000ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 5
|
||||
idleTimeout = "4h"
|
||||
|
||||
[auth]
|
||||
managerHost = "http://uat-manager.bilibili.co"
|
||||
dashboardHost = "http://dashboard-mng.bilibili.co"
|
||||
dashboardCaller = "marthe"
|
||||
[auth.DsHTTPClient]
|
||||
key = "marthe"
|
||||
secret = "4344bea3587b383bc0b9de5de0efcc3f"
|
||||
dial = "1s"
|
||||
timeout = "1s"
|
||||
keepAlive = "60s"
|
||||
[auth.DsHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.MaHTTPClient]
|
||||
key = "f6433799dbd88751"
|
||||
secret = "36f8ddb1806207fe07013ab6a77a3935"
|
||||
dial = "1ms"
|
||||
timeout = "1ms"
|
||||
keepAlive = "60s"
|
||||
[auth.MaHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.session]
|
||||
sessionIDLength = 32
|
||||
cookieLifeTime = 1
|
||||
cookieName = "mng-go"
|
||||
domain = ".bilibili.co"
|
||||
[auth.session.Memcache]
|
||||
name = "go-business/auth"
|
||||
proto = "tcp"
|
||||
addr = "172.18.33.61:11232"
|
||||
active = 10
|
||||
idle = 10
|
||||
dialTimeout = "1ms"
|
||||
readTimeout = "1ms"
|
||||
writeTimeout = "1ms"
|
||||
idleTimeout = "80s"
|
106
app/admin/ep/marthe/cmd/convey-test.toml
Normal file
106
app/admin/ep/marthe/cmd/convey-test.toml
Normal file
@ -0,0 +1,106 @@
|
||||
|
||||
[bm]
|
||||
addr = "0.0.0.0:9001"
|
||||
timeout = "10s"
|
||||
|
||||
[httpClient]
|
||||
key = "c05dd4e1638a8af0"
|
||||
secret = "7daa7f8c06cd33c5c3067063c746fdcb"
|
||||
dial = "2s"
|
||||
timeout = "100s"
|
||||
keepAlive = "60s"
|
||||
timer = 1000
|
||||
[httpClient.breaker]
|
||||
window = "10s"
|
||||
sleep = "2000ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
|
||||
[mail]
|
||||
host = "smtp.exmail.qq.com"
|
||||
port = 465
|
||||
username = "merlin@bilibili.com"
|
||||
password = ""
|
||||
noticeOwner = ["fengyifeng@bilibili.com"]
|
||||
|
||||
[memcache]
|
||||
name = "merlin"
|
||||
proto = "tcp"
|
||||
addr = "172.18.33.61:11232"
|
||||
idle = 5
|
||||
active = 10
|
||||
dialTimeout = "1s"
|
||||
readTimeout = "1s"
|
||||
writeTimeout = "1s"
|
||||
idleTimeout = "10s"
|
||||
expire = "12h"
|
||||
|
||||
[bugly]
|
||||
host = "https://bugly.qq.com"
|
||||
urlRetryCount = 3
|
||||
cookieUsageUpper = 300
|
||||
issuePageSize = 50
|
||||
issueCountUpper = 100
|
||||
|
||||
[Scheduler]
|
||||
#每过10分钟 更新表
|
||||
batchRunEnableVersion = "0 */10 * * * ?"
|
||||
|
||||
batchRunUpdateTapdBug = "0 */10 * * * ?"
|
||||
|
||||
disableBatchRunOverTime = "0 */10 * * * ?"
|
||||
batchRunOverHourTime = 3
|
||||
|
||||
active = false
|
||||
|
||||
|
||||
[orm]
|
||||
dsn = "root:123456@tcp(172.18.33.130:3306)/Marthe2?timeout=200ms&readTimeout=2000ms&writeTimeout=2000ms&parseTime=true&loc=Local&charset=utf8,utf8mb4"
|
||||
active = 5
|
||||
idle = 5
|
||||
idleTimeout = "4h"
|
||||
|
||||
[auth]
|
||||
managerHost = "http://uat-manager.bilibili.co"
|
||||
dashboardHost = "http://dashboard-mng.bilibili.co"
|
||||
dashboardCaller = "merlin"
|
||||
[auth.DsHTTPClient]
|
||||
key = "merlin"
|
||||
secret = "4fb521f66dfd5efcf6e77d078ed2eb0a"
|
||||
dial = "1s"
|
||||
timeout = "1s"
|
||||
keepAlive = "60s"
|
||||
[auth.DsHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.MaHTTPClient]
|
||||
key = "f6433799dbd88751"
|
||||
secret = "36f8ddb1806207fe07013ab6a77a3935"
|
||||
dial = "1ms"
|
||||
timeout = "1ms"
|
||||
keepAlive = "60s"
|
||||
[auth.MaHTTPClient.breaker]
|
||||
window = "3s"
|
||||
sleep = "100ms"
|
||||
bucket = 10
|
||||
ratio = 0.5
|
||||
request = 100
|
||||
[auth.session]
|
||||
sessionIDLength = 32
|
||||
cookieLifeTime = 1
|
||||
cookieName = "mng-go"
|
||||
domain = ".bilibili.co"
|
||||
[auth.session.Memcache]
|
||||
name = "go-business/auth"
|
||||
proto = "tcp"
|
||||
addr = "172.18.33.61:11232"
|
||||
active = 10
|
||||
idle = 10
|
||||
dialTimeout = "1ms"
|
||||
readTimeout = "1ms"
|
||||
writeTimeout = "1ms"
|
||||
idleTimeout = "80s"
|
46
app/admin/ep/marthe/cmd/main.go
Normal file
46
app/admin/ep/marthe/cmd/main.go
Normal file
@ -0,0 +1,46 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"go-common/app/admin/ep/marthe/conf"
|
||||
"go-common/app/admin/ep/marthe/server/http"
|
||||
"go-common/app/admin/ep/marthe/service"
|
||||
ecode "go-common/library/ecode/tip"
|
||||
"go-common/library/log"
|
||||
"go-common/library/net/trace"
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if err := conf.Init(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
log.Init(conf.Conf.Log)
|
||||
defer log.Close()
|
||||
log.Info("start")
|
||||
defer trace.Close()
|
||||
ecode.Init(conf.Conf.Ecode)
|
||||
|
||||
s := service.New(conf.Conf)
|
||||
|
||||
http.Init(conf.Conf, s)
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
|
||||
for {
|
||||
si := <-c
|
||||
log.Info("get a signal %s", si.String())
|
||||
switch si {
|
||||
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
|
||||
log.Info("exit")
|
||||
s.Close()
|
||||
return
|
||||
case syscall.SIGHUP:
|
||||
default:
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
39
app/admin/ep/marthe/conf/BUILD
Normal file
39
app/admin/ep/marthe/conf/BUILD
Normal file
@ -0,0 +1,39 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["conf.go"],
|
||||
importpath = "go-common/app/admin/ep/marthe/conf",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/conf:go_default_library",
|
||||
"//library/database/orm:go_default_library",
|
||||
"//library/ecode/tip:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/permit:go_default_library",
|
||||
"//library/time:go_default_library",
|
||||
"//vendor/github.com/BurntSushi/toml:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
162
app/admin/ep/marthe/conf/conf.go
Normal file
162
app/admin/ep/marthe/conf/conf.go
Normal file
@ -0,0 +1,162 @@
|
||||
package conf
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"flag"
|
||||
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/conf"
|
||||
"go-common/library/database/orm"
|
||||
ecode "go-common/library/ecode/tip"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/permit"
|
||||
xtime "go-common/library/time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
confPath string
|
||||
client *conf.Client
|
||||
// Conf Config
|
||||
Conf = &Config{}
|
||||
)
|
||||
|
||||
// Config .
|
||||
type Config struct {
|
||||
Log *log.Config
|
||||
|
||||
Bugly *BuglyConf
|
||||
|
||||
BM *bm.ServerConfig
|
||||
|
||||
Ecode *ecode.Config
|
||||
|
||||
ORM *orm.Config
|
||||
|
||||
HTTPClient *bm.ClientConfig
|
||||
|
||||
Mail *Mail
|
||||
|
||||
Auth *permit.Config
|
||||
|
||||
Memcache *Memcache
|
||||
|
||||
Scheduler *Scheduler
|
||||
|
||||
Tapd *TapdConf
|
||||
}
|
||||
|
||||
func init() {
|
||||
flag.StringVar(&confPath, "conf", "", "default config path")
|
||||
}
|
||||
|
||||
// Scheduler scheduler
|
||||
type Scheduler struct {
|
||||
BatchRunEnableVersion string
|
||||
|
||||
BatchRunUpdateTapdBug string
|
||||
|
||||
DisableBatchRunOverTime string
|
||||
BatchRunOverHourTime int
|
||||
|
||||
SyncWechatContact string
|
||||
|
||||
Active bool
|
||||
}
|
||||
|
||||
// Memcache memcache
|
||||
type Memcache struct {
|
||||
*memcache.Config
|
||||
Expire xtime.Duration
|
||||
}
|
||||
|
||||
// Mail mail
|
||||
type Mail struct {
|
||||
Host string
|
||||
Port int
|
||||
Username string
|
||||
Password string
|
||||
NoticeOwner []string
|
||||
}
|
||||
|
||||
// BuglyConf Bugly Conf.
|
||||
type BuglyConf struct {
|
||||
Host string
|
||||
UrlRetryCount int
|
||||
CookieUsageUpper int
|
||||
IssuePageSize int
|
||||
IssueCountUpper int
|
||||
|
||||
SuperOwner []string
|
||||
}
|
||||
|
||||
// TapdConf Tapd Conf.
|
||||
type TapdConf struct {
|
||||
BugOperateAuth bool
|
||||
}
|
||||
|
||||
// Tapd Tapd info
|
||||
type Tapd struct {
|
||||
IterationWorkspaceIDs []string
|
||||
StoryWorkspaceIDs []string
|
||||
BugWorkspaceIDs []string
|
||||
IPS int
|
||||
SPS int
|
||||
SCPS int
|
||||
CPS int
|
||||
StoryFilePath string
|
||||
ChangeFilePath string
|
||||
IterationFilePath string
|
||||
BugFilePath string
|
||||
RetryTime int
|
||||
WaitTime xtime.Duration
|
||||
}
|
||||
|
||||
// Init init conf
|
||||
func Init() error {
|
||||
if confPath != "" {
|
||||
return local()
|
||||
}
|
||||
return remote()
|
||||
}
|
||||
|
||||
func local() (err error) {
|
||||
_, err = toml.DecodeFile(confPath, &Conf)
|
||||
return
|
||||
}
|
||||
|
||||
func remote() (err error) {
|
||||
if client, err = conf.New(); err != nil {
|
||||
return
|
||||
}
|
||||
if err = load(); err != nil {
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
for range client.Event() {
|
||||
log.Info("config reload")
|
||||
if load() != nil {
|
||||
log.Error("config reload error (%v)", err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
return
|
||||
}
|
||||
|
||||
func load() (err error) {
|
||||
var (
|
||||
s string
|
||||
ok bool
|
||||
tmpConf *Config
|
||||
)
|
||||
if s, ok = client.Toml2(); !ok {
|
||||
return errors.New("load config center error")
|
||||
}
|
||||
if _, err = toml.Decode(s, &tmpConf); err != nil {
|
||||
return errors.New("could not decode config")
|
||||
}
|
||||
*Conf = *tmpConf
|
||||
return
|
||||
}
|
87
app/admin/ep/marthe/dao/BUILD
Normal file
87
app/admin/ep/marthe/dao/BUILD
Normal file
@ -0,0 +1,87 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bugly.go",
|
||||
"dao.go",
|
||||
"mail.go",
|
||||
"mysql_bugly_batch_run.go",
|
||||
"mysql_bugly_cookie.go",
|
||||
"mysql_bugly_issue.go",
|
||||
"mysql_bugly_project.go",
|
||||
"mysql_bugly_version.go",
|
||||
"mysql_contact_info.go",
|
||||
"mysql_schedule_task.go",
|
||||
"mysql_tapd_bug_priority_conf.go",
|
||||
"mysql_tapd_bug_record.go",
|
||||
"mysql_tapd_bug_template.go",
|
||||
"mysql_tapd_bug_version_template.go",
|
||||
"mysql_user.go",
|
||||
"tapd.go",
|
||||
"wechat.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/marthe/dao",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/marthe/conf:go_default_library",
|
||||
"//app/admin/ep/marthe/model:go_default_library",
|
||||
"//library/cache/memcache:go_default_library",
|
||||
"//library/database/orm:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/sync/pipeline/fanout:go_default_library",
|
||||
"//vendor/github.com/jinzhu/gorm:go_default_library",
|
||||
"//vendor/github.com/pkg/errors:go_default_library",
|
||||
"//vendor/gopkg.in/gomail.v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"dao_test.go",
|
||||
"mysql_bugly_batch_run_test.go",
|
||||
"mysql_bugly_cookie_test.go",
|
||||
"mysql_bugly_issue_test.go",
|
||||
"mysql_bugly_version_test.go",
|
||||
"mysql_schedule_task_test.go",
|
||||
"mysql_tapd_bug_priority_confg_test.go",
|
||||
"mysql_tapd_bug_record_test.go",
|
||||
"mysql_tapd_bug_template_test.go",
|
||||
"mysql_tapd_bug_version_template_test.go",
|
||||
"mysql_user_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
tags = ["automanaged"],
|
||||
deps = [
|
||||
"//app/admin/ep/marthe/conf:go_default_library",
|
||||
"//app/admin/ep/marthe/model:go_default_library",
|
||||
"//vendor/github.com/go-sql-driver/mysql:go_default_library",
|
||||
"//vendor/github.com/satori/go.uuid:go_default_library",
|
||||
"//vendor/github.com/smartystreets/goconvey/convey:go_default_library",
|
||||
"//vendor/gopkg.in/h2non/gock.v1:go_default_library",
|
||||
],
|
||||
)
|
192
app/admin/ep/marthe/dao/bugly.go
Normal file
192
app/admin/ep/marthe/dao/bugly.go
Normal file
@ -0,0 +1,192 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_buglyOkCode = 200
|
||||
_buglyCookieExpiredCode = 100006
|
||||
_issueDetailCode = 100000
|
||||
|
||||
_issueDetailList = "/v2/lastCrashInfo/appId/%s/platformId/%s/issues/%s/crashDataType/null?offsetTop=56&fsn=6d0260aa-331f-48b9-8557-c2aaf6e0be90"
|
||||
_issueList = "/v2/issueList?sortOrder=desc&sortField=uploadTime&rows=50&fsn=45cdb5aa-eb6f-4bda-9bba-ba0b264bfc93&appId=%s&platformId=%s&version=%s&start=%s&rows=%s&exceptionTypeList=%s"
|
||||
_issueVersionList = "/v2/getSelector/appId/%s/platformId/%s?types=version&fsn=8b8782b5-053d-4f58-bc17-d5c43d7f5ece"
|
||||
_issueExceptionList = "/v2/issueInfo/appId/%s/platformId/%s/issueId/%s/exceptionTypeList/Crash,Native,ExtensionCrash?fsn=114a8d02-586d-4fe4-8c23-79003fbe6882"
|
||||
)
|
||||
|
||||
// BuglyVersion Bugly Version .
|
||||
func (d *Dao) BuglyVersion(c context.Context, buglyCookie *model.BuglyCookie, projectID, platformID string) (ret []*model.BugVersion, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.BugVersionResponse
|
||||
hostStr string
|
||||
)
|
||||
|
||||
hostStr = d.c.Bugly.Host + fmt.Sprintf(_issueVersionList, projectID, platformID)
|
||||
|
||||
if req, err = d.newRequest("GET", hostStr, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("Cookie", buglyCookie.Cookie)
|
||||
req.Header.Set("x-token", buglyCookie.Token)
|
||||
req.Header.Set("content-type", "application/json;charset=utf-8")
|
||||
req.Header.Set("x-csrf-token", "undefined")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.BugVersion url(%s) err(%v)", "BugVersion", err)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _buglyOkCode {
|
||||
if res.Code == _buglyCookieExpiredCode {
|
||||
err = ecode.MartheCookieExpired
|
||||
log.Error("maybe need to update cookie and token")
|
||||
} else {
|
||||
err = ecode.MartheBuglyErr
|
||||
}
|
||||
log.Error("Status url(%s) res(%v) err(%v)", "BugVersion", res, err)
|
||||
return
|
||||
}
|
||||
|
||||
ret = res.Ret.BugVersionList
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyIssueAndRetry Bugly Issue And Retry.
|
||||
func (d *Dao) BuglyIssueAndRetry(c context.Context, buglyCookie *model.BuglyCookie, bugIssueRequest *model.BugIssueRequest) (ret *model.BugRet, err error) {
|
||||
for i := 0; i < d.c.Bugly.UrlRetryCount; i++ {
|
||||
if ret, err = d.BuglyIssue(c, buglyCookie, bugIssueRequest); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyIssue Get Issue.
|
||||
func (d *Dao) BuglyIssue(c context.Context, buglyCookie *model.BuglyCookie, bugIssueRequest *model.BugIssueRequest) (ret *model.BugRet, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.BugIssueResponse
|
||||
hostStr string
|
||||
)
|
||||
|
||||
hostStr = d.c.Bugly.Host + fmt.Sprintf(_issueList, bugIssueRequest.ProjectID, bugIssueRequest.PlatformID, bugIssueRequest.Version, strconv.Itoa(bugIssueRequest.StartNum), strconv.Itoa(bugIssueRequest.Rows), bugIssueRequest.ExceptionType)
|
||||
|
||||
if req, err = d.newRequest("GET", hostStr, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("Cookie", buglyCookie.Cookie)
|
||||
req.Header.Set("x-token", buglyCookie.Token)
|
||||
req.Header.Set("content-type", "application/json;charset=utf-8")
|
||||
req.Header.Set("x-csrf-token", "undefined")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.BuglyIssue url(%s) err(%v)", "BuglyIssue", err)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _buglyOkCode {
|
||||
if res.Code == _buglyCookieExpiredCode {
|
||||
err = ecode.MartheCookieExpired
|
||||
log.Error("maybe need to update cookie and token")
|
||||
} else {
|
||||
err = ecode.MartheBuglyErr
|
||||
}
|
||||
log.Error("Status url(%s) res(%v) err(%v)", "BuglyIssue", res, err)
|
||||
return
|
||||
}
|
||||
|
||||
ret = res.Ret
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyIssueDetailAndRetry Bugly Issue Detail And Retry.
|
||||
func (d *Dao) BuglyIssueDetailAndRetry(c context.Context, buglyCookie *model.BuglyCookie, projectID, platformID, issueNo string) (bugIssueDetail *model.BugIssueDetail, err error) {
|
||||
for i := 0; i < d.c.Bugly.UrlRetryCount; i++ {
|
||||
if bugIssueDetail, err = d.BuglyIssueDetail(c, buglyCookie, projectID, platformID, issueNo); err == nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyIssueDetail Get Issue Detail.
|
||||
func (d *Dao) BuglyIssueDetail(c context.Context, buglyCookie *model.BuglyCookie, projectID, platformID, issueNo string) (bugIssueDetail *model.BugIssueDetail, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.BugIssueDetailResponse
|
||||
hostStr string
|
||||
)
|
||||
|
||||
hostStr = d.c.Bugly.Host + fmt.Sprintf(_issueDetailList, projectID, platformID, issueNo)
|
||||
|
||||
if req, err = d.newRequest("GET", hostStr, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("Cookie", buglyCookie.Cookie)
|
||||
req.Header.Set("x-token", buglyCookie.Token)
|
||||
req.Header.Set("content-type", "application/json;charset=utf-8")
|
||||
req.Header.Set("x-csrf-token", "undefined")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.BuglyIssue url(%s) err(%v)", "BuglyIssue", err)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Code != _issueDetailCode {
|
||||
err = ecode.MartheBuglyErr
|
||||
log.Error("Status url(%s) res(%v) err(%v)", "BuglyIssue", res, err)
|
||||
return
|
||||
}
|
||||
|
||||
bugIssueDetail = res.Data
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyIssueExceptionList Bugly Issue Exception List.
|
||||
func (d *Dao) BuglyIssueExceptionList(c context.Context, buglyCookie *model.BuglyCookie, projectID, platformID, issueNo string) (bugIssueException *model.IssueException, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res *model.BugIssueExceptionListResponse
|
||||
hostStr string
|
||||
)
|
||||
|
||||
hostStr = d.c.Bugly.Host + fmt.Sprintf(_issueExceptionList, projectID, platformID, issueNo)
|
||||
|
||||
if req, err = d.newRequest("GET", hostStr, nil); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
req.Header.Set("Cookie", buglyCookie.Cookie)
|
||||
req.Header.Set("x-token", buglyCookie.Token)
|
||||
req.Header.Set("content-type", "application/json;charset=utf-8")
|
||||
req.Header.Set("x-csrf-token", "undefined")
|
||||
|
||||
if err = d.httpClient.Do(c, req, &res); err != nil {
|
||||
log.Error("d.BuglyIssueExceptionList url(%s) err(%v)", "BuglyIssueExceptionList", err)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _buglyOkCode {
|
||||
err = ecode.MartheBuglyErr
|
||||
log.Error("Status url(%s) res(%v) err(%v)", "BuglyIssueExceptionList", res, err)
|
||||
return
|
||||
}
|
||||
|
||||
if res.Ret != nil && len(res.Ret.IssueException) != 0 && res.Ret.IssueException[0].IssueID == issueNo {
|
||||
bugIssueException = res.Ret.IssueException[0]
|
||||
}
|
||||
|
||||
return
|
||||
}
|
100
app/admin/ep/marthe/dao/dao.go
Normal file
100
app/admin/ep/marthe/dao/dao.go
Normal file
@ -0,0 +1,100 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/conf"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/database/orm"
|
||||
"go-common/library/log"
|
||||
xhttp "go-common/library/net/http/blademaster"
|
||||
"go-common/library/sync/pipeline/fanout"
|
||||
|
||||
"github.com/jinzhu/gorm"
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
const _wildcards = "%"
|
||||
|
||||
// Dao dao
|
||||
type Dao struct {
|
||||
c *conf.Config
|
||||
httpClient *xhttp.Client
|
||||
email *gomail.Dialer
|
||||
db *gorm.DB
|
||||
cache *fanout.Fanout
|
||||
mc *memcache.Pool
|
||||
expire int32
|
||||
}
|
||||
|
||||
// New init mysql db
|
||||
func New(c *conf.Config) (dao *Dao) {
|
||||
dao = &Dao{
|
||||
c: c,
|
||||
email: gomail.NewDialer(c.Mail.Host, c.Mail.Port, c.Mail.Username, c.Mail.Password),
|
||||
httpClient: xhttp.NewClient(c.HTTPClient),
|
||||
cache: fanout.New("mcCache", fanout.Worker(1), fanout.Buffer(1024)),
|
||||
mc: memcache.NewPool(c.Memcache.Config),
|
||||
expire: int32(time.Duration(c.Memcache.Expire) / time.Second),
|
||||
}
|
||||
if c.ORM != nil {
|
||||
dao.db = orm.NewMySQL(c.ORM)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Close close the resource.
|
||||
func (d *Dao) Close() {
|
||||
if d.db != nil {
|
||||
d.db.Close()
|
||||
}
|
||||
|
||||
if d.mc != nil {
|
||||
d.mc.Close()
|
||||
}
|
||||
}
|
||||
|
||||
// Ping verify server is ok.
|
||||
func (d *Dao) Ping(c context.Context) (err error) {
|
||||
if d.db != nil {
|
||||
if err = d.db.DB().Ping(); err != nil {
|
||||
log.Info("dao.cloudDB.Ping() error(%v)", err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (d *Dao) newRequest(method, url string, v interface{}) (req *http.Request, err error) {
|
||||
body := &bytes.Buffer{}
|
||||
if method != http.MethodGet {
|
||||
if err = json.NewEncoder(body).Encode(v); err != nil {
|
||||
log.Error("json encode value(%s) err(%v) ", v, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if req, err = http.NewRequest(method, url, body); err != nil {
|
||||
log.Error("http new request url(%s) err(%v)", url, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// cacheSave cache Save.
|
||||
func (d *Dao) cacheSave(c context.Context, cacheItem *memcache.Item) {
|
||||
var f = func(ctx context.Context) {
|
||||
var (
|
||||
conn = d.mc.Get(c)
|
||||
err error
|
||||
)
|
||||
defer conn.Close()
|
||||
if err = conn.Set(cacheItem); err != nil {
|
||||
log.Error("Add Cache conn.Set(%s) error(%v)", cacheItem.Key, err)
|
||||
}
|
||||
}
|
||||
if err := d.cache.Do(c, f); err != nil {
|
||||
log.Error("ReleaseName cache save err(%v)", err)
|
||||
}
|
||||
}
|
30
app/admin/ep/marthe/dao/dao_test.go
Normal file
30
app/admin/ep/marthe/dao/dao_test.go
Normal file
@ -0,0 +1,30 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"path/filepath"
|
||||
|
||||
"go-common/app/admin/ep/marthe/conf"
|
||||
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"gopkg.in/h2non/gock.v1"
|
||||
)
|
||||
|
||||
var (
|
||||
d *Dao
|
||||
c context.Context
|
||||
)
|
||||
|
||||
func init() {
|
||||
dir, _ := filepath.Abs("../cmd/convey-test.toml")
|
||||
flag.Set("conf", dir)
|
||||
conf.Init()
|
||||
d = New(conf.Conf)
|
||||
d.httpClient.SetTransport(gock.DefaultTransport)
|
||||
c = ctx()
|
||||
}
|
||||
|
||||
func ctx() context.Context {
|
||||
return context.Background()
|
||||
}
|
35
app/admin/ep/marthe/dao/mail.go
Normal file
35
app/admin/ep/marthe/dao/mail.go
Normal file
@ -0,0 +1,35 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"gopkg.in/gomail.v2"
|
||||
)
|
||||
|
||||
const (
|
||||
_MailBoxNotFound = "Mailbox not found"
|
||||
)
|
||||
|
||||
// SendMail asynchronous send mail.
|
||||
func (d *Dao) SendMail(message *gomail.Message) {
|
||||
message.SetAddressHeader("From", d.email.Username, "merlin")
|
||||
d.cache.Do(context.TODO(), func(ctx context.Context) {
|
||||
d.SendMailIfFailed(message)
|
||||
})
|
||||
}
|
||||
|
||||
// SendMailIfFailed Send Mail If Failed
|
||||
func (d *Dao) SendMailIfFailed(message *gomail.Message) {
|
||||
if err := d.email.DialAndSend(message); err != nil {
|
||||
if strings.Contains(err.Error(), _MailBoxNotFound) {
|
||||
headerMsg := message.GetHeader("Subject")
|
||||
headerMsg = append(headerMsg, "Mail Send Error:"+err.Error()+",Receiver:")
|
||||
headerMsg = append(headerMsg, message.GetHeader("To")...)
|
||||
|
||||
message.SetHeader("To", d.c.Mail.NoticeOwner...)
|
||||
message.SetHeader("Subject", headerMsg...)
|
||||
d.email.DialAndSend(message)
|
||||
}
|
||||
}
|
||||
}
|
92
app/admin/ep/marthe/dao/mysql_bugly_batch_run.go
Normal file
92
app/admin/ep/marthe/dao/mysql_bugly_batch_run.go
Normal file
@ -0,0 +1,92 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertBuglyBatchRuns Insert Bugly Batch Runs.
|
||||
func (d *Dao) InsertBuglyBatchRuns(buglyBatchRuns []*model.BuglyBatchRun) (err error) {
|
||||
tx := d.db.Begin()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if err = tx.Error; err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyBatchRun := range buglyBatchRuns {
|
||||
if err = d.db.Create(buglyBatchRun).Error; err != nil {
|
||||
tx.Rollback()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = tx.Commit().Error; err != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// InsertBuglyBatchRun Insert Bugly Batch Run.
|
||||
func (d *Dao) InsertBuglyBatchRun(buglyBatchRun *model.BuglyBatchRun) error {
|
||||
return pkgerr.WithStack(d.db.Create(buglyBatchRun).Error)
|
||||
}
|
||||
|
||||
// UpdateBuglyBatchRun Update Bugly Batch Run.
|
||||
func (d *Dao) UpdateBuglyBatchRun(buglyBatchRun *model.BuglyBatchRun) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyBatchRun{}).Where("id=?", buglyBatchRun.ID).Updates(buglyBatchRun).Error)
|
||||
}
|
||||
|
||||
// FindBuglyBatchRuns Find Bugly Batch Runs.
|
||||
func (d *Dao) FindBuglyBatchRuns(req *model.QueryBuglyBatchRunsRequest) (total int64, buglyBatchRuns []*model.BuglyBatchRun, err error) {
|
||||
gDB := d.db.Model(&model.BuglyBatchRun{})
|
||||
|
||||
if req.Version != "" {
|
||||
gDB = gDB.Where("version=?", req.Version)
|
||||
}
|
||||
|
||||
if req.Status != 0 {
|
||||
gDB = gDB.Where("status=?", req.Status)
|
||||
}
|
||||
|
||||
if req.BatchID != "" {
|
||||
gDB = gDB.Where("batch_id=?", req.BatchID)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&buglyBatchRuns).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyBatchRunsByStatus Find Bugly Batch Runs By Status.
|
||||
func (d *Dao) QueryBuglyBatchRunsByStatus(status int) (buglyBatchRuns []*model.BuglyBatchRun, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status = ?", status).Find(&buglyBatchRuns).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryLastSuccessBatchRunByVersion Find Last Success Batch Run By Version.
|
||||
func (d *Dao) QueryLastSuccessBatchRunByVersion(version string) (buglyBatchRun *model.BuglyBatchRun, err error) {
|
||||
buglyBatchRun = &model.BuglyBatchRun{}
|
||||
if err = d.db.Where("version = ? and status = ?", version, model.BuglyBatchRunStatusDone).Order("id desc").First(&buglyBatchRun).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
58
app/admin/ep/marthe/dao/mysql_bugly_batch_run_test.go
Normal file
58
app/admin/ep/marthe/dao/mysql_bugly_batch_run_test.go
Normal file
@ -0,0 +1,58 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpVersion = time.Now().Format("2006_01_02_15_04_05")
|
||||
buglyBatchRun = &model.BuglyBatchRun{
|
||||
BuglyVersionID: 1,
|
||||
Version: tmpVersion,
|
||||
BatchID: uuid.NewV4().String(),
|
||||
RetryCount: 0,
|
||||
Status: model.BuglyBatchRunStatusRunning,
|
||||
ErrorMsg: "no",
|
||||
}
|
||||
|
||||
queryBuglyBatchRunsRequest = &model.QueryBuglyBatchRunsRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
Version: tmpVersion,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Bugly_batch_run(t *testing.T) {
|
||||
Convey("test insert bugly batch run", t, func() {
|
||||
err := d.InsertBuglyBatchRun(buglyBatchRun)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test update bugly batch run", t, func() {
|
||||
buglyBatchRun.Status = model.BuglyBatchRunStatusDone
|
||||
err := d.UpdateBuglyBatchRun(buglyBatchRun)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Find Bugly Batch Runs", t, func() {
|
||||
buglyBatchRun.Status = model.BuglyBatchRunStatusDone
|
||||
total, buglyBatchRuns, err := d.FindBuglyBatchRuns(queryBuglyBatchRunsRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldEqual, 1)
|
||||
So(buglyBatchRun.BatchID, ShouldEqual, buglyBatchRuns[0].BatchID)
|
||||
})
|
||||
|
||||
Convey("test Find Last Success Batch Run By Version", t, func() {
|
||||
tmpBuglyBatchRun, err := d.QueryLastSuccessBatchRunByVersion(tmpVersion)
|
||||
So(err, ShouldBeNil)
|
||||
So(buglyBatchRun.BatchID, ShouldEqual, tmpBuglyBatchRun.BatchID)
|
||||
})
|
||||
}
|
67
app/admin/ep/marthe/dao/mysql_bugly_cookie.go
Normal file
67
app/admin/ep/marthe/dao/mysql_bugly_cookie.go
Normal file
@ -0,0 +1,67 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertCookie Insert Cookie.
|
||||
func (d *Dao) InsertCookie(buglyCookie *model.BuglyCookie) error {
|
||||
return pkgerr.WithStack(d.db.Create(buglyCookie).Error)
|
||||
}
|
||||
|
||||
// UpdateCookie Update cookie.
|
||||
func (d *Dao) UpdateCookie(buglyCookie *model.BuglyCookie) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyCookie{}).Updates(buglyCookie).Error)
|
||||
}
|
||||
|
||||
// UpdateCookieStatus Update Cookie Status.
|
||||
func (d *Dao) UpdateCookieStatus(id int64, status int) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyCookie{}).Where("id = ?", id).Update("status", status).Error)
|
||||
}
|
||||
|
||||
// UpdateCookieUsageCount Update Cookie Usage Count.
|
||||
func (d *Dao) UpdateCookieUsageCount(id int64, usageCount int) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyCookie{}).Where("id = ?", id).Update("usage_count", usageCount).Error)
|
||||
}
|
||||
|
||||
// QueryCookieByStatus Query Cookie By Status.
|
||||
func (d *Dao) QueryCookieByStatus(status int) (buglyCookies []*model.BuglyCookie, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status=?", status).Order("ctime desc").Find(&buglyCookies).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryCookieByQQAccount Query Cookie By QQ Account.
|
||||
func (d *Dao) QueryCookieByQQAccount(qqAccount int) (buglyCookie *model.BuglyCookie, err error) {
|
||||
buglyCookie = &model.BuglyCookie{}
|
||||
if err = d.db.Where("qq_account=?", qqAccount).First(buglyCookie).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindCookies Find Cookies.
|
||||
func (d *Dao) FindCookies(req *model.QueryBuglyCookiesRequest) (total int64, buglyCookies []*model.BuglyCookie, err error) {
|
||||
gDB := d.db.Model(&model.BuglyCookie{})
|
||||
|
||||
if req.QQAccount != 0 {
|
||||
gDB = gDB.Where("qq_account=?", req.QQAccount)
|
||||
}
|
||||
|
||||
if req.Status != 0 {
|
||||
gDB = gDB.Where("status=?", req.Status)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&buglyCookies).Error)
|
||||
return
|
||||
}
|
51
app/admin/ep/marthe/dao/mysql_bugly_cookie_test.go
Normal file
51
app/admin/ep/marthe/dao/mysql_bugly_cookie_test.go
Normal file
@ -0,0 +1,51 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
buglyCookie = &model.BuglyCookie{
|
||||
QQAccount: 246802468,
|
||||
Cookie: "eas_sid=6105G3k2D0Q428f5u0c6B527B0; pgv_pvi=95820800; RK=kfyEYkBgS6; btcu_id=c64abeb0e4f6485712c0bb79bf16c19d5b6aa5326be74; vc=vc-01c6b914-d8f9-4449-adcb-abba3ebe137c; vc.sig=b8t0PNSdSX1m4wOr-B12whzwaf75BlJjOjz5Jy7YTkE; _ga=GA1.2.1955813367.1533715741; pgv_si=s229603328; _qpsvr_localtk=0.0198901072762101; o_cookie=972360526; pac_uid=1_972360526; csrfToken=gekJ-F5QdGgVTZqLC0NiBEOA; ptui_loginuin=1211712225; ptisp=ctc; ptcz=f45f877d04ce6b659e432a158d35cbc9dea2c565d17eb6ee23640a0c7f82aaf9; uin=o1211712225; skey=@FGItvXrQ6; pt2gguin=o1211712225; IED_LOG_INFO2=userUin%3D1211712225%26nickName%3D%2525E5%2525B0%25258F%2525E7%2525BE%25258E+%26userLoginTime%3D1545802497; midas_openid=1211712225; midas_openkey=@FGItvXrQ6; pgv_info=ssid=s2529006206&pgvReferrer=; pgv_pvid=7939868100; NODINX_SESS=7XIt-RXcFpUaAwKwVFHFbIsssGiryDAw_dF_oP1uVFP2V5vV95jh92eADSSJIq0v; token-skey=771060e7-cd54-f0b3-960c-c8fe485fde10; token-lifeTime=1545828885; bugly_session=eyJpdiI6IldLOHM2V2lhNXFyemdMV1d6YXQ0SHc9PSIsInZhbHVlIjoiekt5UllBZWU4OEltSDVzTzJOeHRESjdQMWY5Y1wveEpYbUlDNmxrV25XTHR3ME5RMkRUdk9VaGlKbGFrQ0cxc2xoUzBOVXdCM0hzVWZIemlFR1BLZXJnPT0iLCJtYWMiOiJhZTI5ZmVjNmVjNzZjMWI2MTMyM2U4NWE5MGZiNWMxMjQzZmEzMWEyMGZhMTcxZjg1N2FiOTY4OTgxNWZjMDExIn0%3D; referrer=eyJpdiI6Im9FZ00yMHdsS2hIeHp3UERSaFVhWlE9PSIsInZhbHVlIjoiZXN6dmZFWmJ4V3R6UmordnowVXZkMXdhbm8zN3QrNzVcL2NSc1I0eWw1ZUVYbVFvTnlwdDB2QWVoaXp4VmZxY2tFV2VSdDIrWG40bEpqb3hvWTZmaVAwXC9vR1JqNEE5NG1MQnlkR1dvV1dkWitSakV6RjV1dWF4dEtzbGpXRFhsNW10SEhrSDVrZk1tRE9EXC9zUEVBRGxwSzhoTHRzSHhuTktFV1g1ckpOTEo0PSIsIm1hYyI6IjAzZWJiMjQ0YjkyNmUyYTk2MDRmNTdjYjY2OWYwNzIzZjZjMmNiMzU0NWRhZmExZWFhYWUzMGFiMTI2MDI4NzIifQ%3D%3F",
|
||||
Token: "1768129694",
|
||||
UsageCount: 0,
|
||||
Status: model.BuglyCookieStatusEnable,
|
||||
}
|
||||
|
||||
queryBuglyCookiesRequest = &model.QueryBuglyCookiesRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
QQAccount: buglyCookie.QQAccount,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Bugly_cookie(t *testing.T) {
|
||||
Convey("test insert bugly cookie", t, func() {
|
||||
err := d.InsertCookie(buglyCookie)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Cookie Status", t, func() {
|
||||
err := d.UpdateCookieStatus(buglyCookie.ID, model.BuglyCookieStatusDisable)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Cookie Usage Count", t, func() {
|
||||
err := d.UpdateCookieUsageCount(buglyCookie.ID, 5)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Find Cookies", t, func() {
|
||||
total, buglyCookies, err := d.FindCookies(queryBuglyCookiesRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldBeGreaterThan, 0)
|
||||
So(len(buglyCookies), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
}
|
104
app/admin/ep/marthe/dao/mysql_bugly_issue.go
Normal file
104
app/admin/ep/marthe/dao/mysql_bugly_issue.go
Normal file
@ -0,0 +1,104 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// GetBuglyIssue Get Issue Record.
|
||||
func (d *Dao) GetBuglyIssue(issueNo, version string) (buglyIssue *model.BuglyIssue, err error) {
|
||||
buglyIssue = &model.BuglyIssue{}
|
||||
if err = d.db.Where("issue_no = ? and version = ?", issueNo, version).First(buglyIssue).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateBuglyIssue Update Issue Record.
|
||||
func (d *Dao) UpdateBuglyIssue(buglyIssue *model.BuglyIssue) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyIssue{}).Where("issue_no = ? and version = ?", buglyIssue.IssueNo, buglyIssue.Version).UpdateColumn(map[string]interface{}{
|
||||
"last_time": buglyIssue.LastTime,
|
||||
"happen_times": buglyIssue.HappenTimes,
|
||||
"user_times": buglyIssue.UserTimes,
|
||||
}).Error)
|
||||
}
|
||||
|
||||
// InsertBuglyIssue Insert Issue Record.
|
||||
func (d *Dao) InsertBuglyIssue(buglyIssue *model.BuglyIssue) (err error) {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyIssue{}).Create(buglyIssue).Error)
|
||||
}
|
||||
|
||||
// GetBuglyIssuesByFilterSQL Get Bugly Issues By Filter SQL.
|
||||
func (d *Dao) GetBuglyIssuesByFilterSQL(issueFilterSQL string) (buglyIssues []*model.BuglyIssue, err error) {
|
||||
if err = d.db.Raw(issueFilterSQL).Order("id asc").Find(&buglyIssues).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateBuglyIssueTapdBugID Update Issue Record Tapd Bug ID.
|
||||
func (d *Dao) UpdateBuglyIssueTapdBugID(id int64, tapdBugID string) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyIssue{}).Where("id=?", id).Update("tapd_bug_id", tapdBugID).Error)
|
||||
}
|
||||
|
||||
// FindBuglyIssues Find Bugly Issues.
|
||||
func (d *Dao) FindBuglyIssues(req *model.QueryBuglyIssueRequest) (total int64, buglyIssues []*model.BuglyIssue, err error) {
|
||||
gDB := d.db.Model(&model.BuglyIssue{})
|
||||
|
||||
if req.IssueNo != "" {
|
||||
gDB = gDB.Where("issue_no = ?", req.IssueNo)
|
||||
}
|
||||
if req.Title != "" {
|
||||
gDB = gDB.Where("title like ?", _wildcards+req.Title+_wildcards)
|
||||
}
|
||||
if req.ExceptionMsg != "" {
|
||||
gDB = gDB.Where("exception_msg like ?", _wildcards+req.ExceptionMsg+_wildcards)
|
||||
}
|
||||
if req.KeyStack != "" {
|
||||
gDB = gDB.Where("key_stack like ?", _wildcards+req.KeyStack+_wildcards)
|
||||
}
|
||||
if req.Detail != "" {
|
||||
gDB = gDB.Where("detail like ?", _wildcards+req.Detail+_wildcards)
|
||||
}
|
||||
if req.Tags != "" {
|
||||
gDB = gDB.Where("tags like ?", _wildcards+req.Tags+_wildcards)
|
||||
}
|
||||
if req.Version != "" {
|
||||
gDB = gDB.Where("version like ?", _wildcards+req.Version+_wildcards)
|
||||
}
|
||||
if req.ProjectID != "" {
|
||||
gDB = gDB.Where("project_id like ?", _wildcards+req.ProjectID+_wildcards)
|
||||
}
|
||||
if req.TapdBugID != "" {
|
||||
gDB = gDB.Where("tapd_bug_id = ?", req.TapdBugID)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("mtime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&buglyIssues).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// GetBuglyIssuesHasInTapd Get Bugly Issues Has In Tapd.
|
||||
func (d *Dao) GetBuglyIssuesHasInTapd() (buglyIssues []*model.BuglyIssue, err error) {
|
||||
if err = d.db.Where("tapd_bug_id<>''").Find(&buglyIssues).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
78
app/admin/ep/marthe/dao/mysql_bugly_issue_test.go
Normal file
78
app/admin/ep/marthe/dao/mysql_bugly_issue_test.go
Normal file
@ -0,0 +1,78 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpIssueNoStr = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
tmpTapdBugID = "bug" + tmpIssueNoStr
|
||||
|
||||
buglyIssue = &model.BuglyIssue{
|
||||
IssueNo: tmpIssueNoStr,
|
||||
Title: "Title" + tmpIssueNoStr,
|
||||
ExceptionMsg: "ExceptionMsg" + tmpIssueNoStr,
|
||||
KeyStack: "KeyStack" + tmpIssueNoStr,
|
||||
Detail: "Detail" + tmpIssueNoStr,
|
||||
Tags: "Tags" + tmpIssueNoStr,
|
||||
LastTime: time.Now(),
|
||||
HappenTimes: 10,
|
||||
UserTimes: 20,
|
||||
Version: "Version" + tmpIssueNoStr,
|
||||
ProjectID: "ProjectID" + tmpIssueNoStr,
|
||||
IssueLink: "IssueLink" + tmpIssueNoStr,
|
||||
}
|
||||
|
||||
queryBuglyIssueRequest = &model.QueryBuglyIssueRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
IssueNo: buglyIssue.IssueNo,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Bugly_Issue(t *testing.T) {
|
||||
Convey("test insert bugly issue", t, func() {
|
||||
err := d.InsertBuglyIssue(buglyIssue)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test update Bugly Issue", t, func() {
|
||||
buglyIssue.ExceptionMsg = "update exception message"
|
||||
err := d.UpdateBuglyIssue(buglyIssue)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test update Bugly Issue tapd bug id", t, func() {
|
||||
err := d.UpdateBuglyIssueTapdBugID(buglyIssue.ID, tmpTapdBugID)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Get Bugly Issue", t, func() {
|
||||
tmpBuglyIssue, err := d.GetBuglyIssue(buglyIssue.IssueNo, buglyIssue.Version)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpBuglyIssue.ID, ShouldEqual, buglyIssue.ID)
|
||||
})
|
||||
|
||||
Convey("test Get Bugly Issues By Filter SQL", t, func() {
|
||||
sql := "select * from bugly_issues where issue_no = '" + buglyIssue.IssueNo + "'"
|
||||
tmpBuglyIssues, err := d.GetBuglyIssuesByFilterSQL(sql)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpBuglyIssues[0].IssueNo, ShouldEqual, buglyIssue.IssueNo)
|
||||
})
|
||||
|
||||
Convey("test Find Bugly Issues", t, func() {
|
||||
total, tmpBuglyIssues, err := d.FindBuglyIssues(queryBuglyIssueRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldBeGreaterThan, 0)
|
||||
So(len(tmpBuglyIssues), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
}
|
89
app/admin/ep/marthe/dao/mysql_bugly_project.go
Normal file
89
app/admin/ep/marthe/dao/mysql_bugly_project.go
Normal file
@ -0,0 +1,89 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertBuglyProject Insert Bugly Project.
|
||||
func (d *Dao) InsertBuglyProject(buglyProject *model.BuglyProject) error {
|
||||
return pkgerr.WithStack(d.db.Create(buglyProject).Error)
|
||||
}
|
||||
|
||||
// UpdateBuglyProject Update Bugly Project.
|
||||
func (d *Dao) UpdateBuglyProject(buglyProject *model.BuglyProject) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyProject{}).Updates(buglyProject).Error)
|
||||
}
|
||||
|
||||
// QueryBuglyProject Query Bugly Project.
|
||||
func (d *Dao) QueryBuglyProject(id int64) (buglyProject *model.BuglyProject, err error) {
|
||||
buglyProject = &model.BuglyProject{}
|
||||
err = pkgerr.WithStack(d.db.Where("id = ?", id).First(buglyProject).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyProjectByName Query Bugly Project.
|
||||
func (d *Dao) QueryBuglyProjectByName(projectName string) (buglyProject *model.BuglyProject, err error) {
|
||||
buglyProject = &model.BuglyProject{}
|
||||
if err = d.db.Where("project_name = ?", projectName).First(buglyProject).Error; err == ecode.NothingFound {
|
||||
err = nil
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryAllBuglyProjects Query All Bugly Project.
|
||||
func (d *Dao) QueryAllBuglyProjects() (buglyProjects []*model.BuglyProject, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.BuglyProject{}).Find(&buglyProjects).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindBuglyProjects Find Bugly Project.
|
||||
func (d *Dao) FindBuglyProjects(req *model.QueryBuglyProjectRequest) (total int64, buglyProject []*model.BuglyProject, err error) {
|
||||
gDB := d.db.Model(&model.BuglyProject{})
|
||||
|
||||
if req.ProjectID != "" {
|
||||
gDB = gDB.Where("project_id=?", req.ProjectID)
|
||||
}
|
||||
if req.ProjectName != "" {
|
||||
gDB = gDB.Where("project_name like ?", _wildcards+req.ProjectName+_wildcards)
|
||||
}
|
||||
if req.PlatformID != "" {
|
||||
gDB = gDB.Where("platform_id=?", req.PlatformID)
|
||||
}
|
||||
|
||||
if req.UpdateBy != "" {
|
||||
gDB = gDB.Where("update_by=?", req.UpdateBy)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&buglyProject).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyProjectList Query Bugly Project List.
|
||||
func (d *Dao) QueryBuglyProjectList() (projectList []string, err error) {
|
||||
var (
|
||||
rows *sql.Rows
|
||||
)
|
||||
sql := "select DISTINCT project_name from bugly_projects"
|
||||
if rows, err = d.db.Raw(sql).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ver string
|
||||
if err = rows.Scan(&ver); err != nil {
|
||||
return
|
||||
}
|
||||
projectList = append(projectList, ver)
|
||||
}
|
||||
return
|
||||
}
|
139
app/admin/ep/marthe/dao/mysql_bugly_version.go
Normal file
139
app/admin/ep/marthe/dao/mysql_bugly_version.go
Normal file
@ -0,0 +1,139 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const (
|
||||
_versionInnerJoinProjectSql = "select a.id,a.version,a.bugly_project_id,a.action,a.task_status,a.update_by,a.ctime,a.mtime,b.project_name,b.exception_type from bugly_versions as a inner join bugly_projects as b on a.bugly_project_id = b.id"
|
||||
_versionInnerJoinProjectSqlCount = "select count(-1) as totalCount from bugly_versions as a inner join bugly_projects as b on a.bugly_project_id = b.id"
|
||||
_where = "WHERE"
|
||||
_and = "AND"
|
||||
)
|
||||
|
||||
// InsertBuglyVersion Insert Bugly Version.
|
||||
func (d *Dao) InsertBuglyVersion(buglyVersion *model.BuglyVersion) error {
|
||||
return pkgerr.WithStack(d.db.Create(buglyVersion).Error)
|
||||
}
|
||||
|
||||
// UpdateBuglyVersion Update Bugly Version.
|
||||
func (d *Dao) UpdateBuglyVersion(buglyVersion *model.BuglyVersion) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.BuglyVersion{}).Updates(buglyVersion).Error)
|
||||
}
|
||||
|
||||
// QueryBuglyVersionByVersion Query Bugly Version By Version.
|
||||
func (d *Dao) QueryBuglyVersionByVersion(version string) (buglyVersion *model.BuglyVersion, err error) {
|
||||
buglyVersion = &model.BuglyVersion{}
|
||||
if err = d.db.Where("version = ?", version).First(buglyVersion).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyVersion Query Bugly Version .
|
||||
func (d *Dao) QueryBuglyVersion(id int64) (buglyVersion *model.BuglyVersion, err error) {
|
||||
buglyVersion = &model.BuglyVersion{}
|
||||
if err = d.db.Where("id = ?", id).First(buglyVersion).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyVersionList Query Bugly Version List.
|
||||
func (d *Dao) QueryBuglyVersionList() (versionList []string, err error) {
|
||||
var (
|
||||
rows *sql.Rows
|
||||
)
|
||||
sql := "select DISTINCT version from bugly_versions"
|
||||
if rows, err = d.db.Raw(sql).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
var ver string
|
||||
if err = rows.Scan(&ver); err != nil {
|
||||
return
|
||||
}
|
||||
versionList = append(versionList, ver)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindBuglyProjectVersions Find Bugly Project Versions.
|
||||
func (d *Dao) FindBuglyProjectVersions(req *model.QueryBuglyVersionRequest) (total int64, buglyProjectVersions []*model.BuglyProjectVersion, err error) {
|
||||
var (
|
||||
qSQL = _versionInnerJoinProjectSql
|
||||
cSQL = _versionInnerJoinProjectSqlCount
|
||||
rows *sql.Rows
|
||||
)
|
||||
|
||||
if req.UpdateBy != "" || req.ProjectName != "" || req.Action > 0 || req.Version != "" {
|
||||
var (
|
||||
partSql string
|
||||
logicalWord = _where
|
||||
)
|
||||
|
||||
if req.UpdateBy != "" {
|
||||
partSql = fmt.Sprintf("%s %s a.update_by = '%s'", partSql, logicalWord, req.UpdateBy)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if req.ProjectName != "" {
|
||||
partSql = fmt.Sprintf("%s %s b.project_name like '%s'", partSql, logicalWord, _wildcards+req.ProjectName+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if req.Action > 0 {
|
||||
partSql = fmt.Sprintf("%s %s a.action = %d", partSql, logicalWord, req.Action)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
if req.Version != "" {
|
||||
partSql = fmt.Sprintf("%s %s a.version like '%s'", partSql, logicalWord, _wildcards+req.Version+_wildcards)
|
||||
logicalWord = _and
|
||||
}
|
||||
|
||||
qSQL = qSQL + partSql
|
||||
cSQL = cSQL + partSql
|
||||
}
|
||||
|
||||
cDB := d.db.Raw(cSQL)
|
||||
if err = pkgerr.WithStack(cDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
gDB := d.db.Raw(qSQL)
|
||||
if rows, err = gDB.Order("a.ctime DESC").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Rows(); err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
for rows.Next() {
|
||||
pv := &model.BuglyProjectVersion{}
|
||||
if err = rows.Scan(&pv.ID, &pv.Version, &pv.BuglyProjectID, &pv.Action, &pv.TaskStatus, &pv.UpdateBy, &pv.CTime, &pv.MTime, &pv.ProjectName, &pv.ExceptionType); err != nil {
|
||||
return
|
||||
}
|
||||
buglyProjectVersions = append(buglyProjectVersions, pv)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// FindEnableAndReadyVersions Find Enable And Ready Versions.
|
||||
func (d *Dao) FindEnableAndReadyVersions() (buglyVersions []*model.BuglyVersion, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("action = ? and task_status = ?", model.BuglyVersionActionEnable, model.BuglyVersionTaskStatusReady).Find(&buglyVersions).Error)
|
||||
return
|
||||
}
|
49
app/admin/ep/marthe/dao/mysql_bugly_version_test.go
Normal file
49
app/admin/ep/marthe/dao/mysql_bugly_version_test.go
Normal file
@ -0,0 +1,49 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpIssueNoStr2 = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
buglyVersion = &model.BuglyVersion{
|
||||
Version: "Version" + tmpIssueNoStr2,
|
||||
BuglyProjectID: 1,
|
||||
Action: model.BuglyVersionActionDisable,
|
||||
TaskStatus: 1,
|
||||
UpdateBy: "fengyifeng",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Bugly_Version(t *testing.T) {
|
||||
Convey("test insert bugly Version", t, func() {
|
||||
err := d.InsertBuglyVersion(buglyVersion)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test update bugly Version", t, func() {
|
||||
buglyVersion.Version = "update" + tmpIssueNoStr2
|
||||
err := d.UpdateBuglyVersion(buglyVersion)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Query Bugly Version By Version", t, func() {
|
||||
tmpBuglyVersion, err := d.QueryBuglyVersionByVersion(buglyVersion.Version)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpBuglyVersion.Version, ShouldEqual, buglyVersion.Version)
|
||||
})
|
||||
|
||||
Convey("test Query Bugly Version By Id", t, func() {
|
||||
tmpBuglyVersion, err := d.QueryBuglyVersion(buglyVersion.ID)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpBuglyVersion.Version, ShouldEqual, buglyVersion.Version)
|
||||
})
|
||||
|
||||
}
|
50
app/admin/ep/marthe/dao/mysql_contact_info.go
Normal file
50
app/admin/ep/marthe/dao/mysql_contact_info.go
Normal file
@ -0,0 +1,50 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertContactInfo Insert Contact Info.
|
||||
func (d *Dao) InsertContactInfo(contactInfo *model.ContactInfo) error {
|
||||
return pkgerr.WithStack(d.db.Create(contactInfo).Error)
|
||||
}
|
||||
|
||||
// UpdateContactInfo Update Contact Info.
|
||||
func (d *Dao) UpdateContactInfo(contactInfo *model.ContactInfo) error {
|
||||
return pkgerr.WithStack(d.db.Save(&contactInfo).Error)
|
||||
}
|
||||
|
||||
// QueryContactInfoByUserID Query Contact Info By User ID
|
||||
func (d *Dao) QueryContactInfoByUserID(userID string) (contactInfo *model.ContactInfo, err error) {
|
||||
contactInfo = &model.ContactInfo{}
|
||||
if err = d.db.Where("user_id = ?", userID).First(contactInfo).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryContactInfoByUsername Query Contact Info By Username
|
||||
func (d *Dao) QueryContactInfoByUsername(username string) (contactInfo *model.ContactInfo, err error) {
|
||||
contactInfo = &model.ContactInfo{}
|
||||
if err = d.db.Where("username = ?", username).First(contactInfo).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryAllContactInfos Query All Contact Infos
|
||||
func (d *Dao) QueryAllContactInfos() (contactInfos []*model.ContactInfo, err error) {
|
||||
err = pkgerr.WithStack(d.db.Find(&contactInfos).Error)
|
||||
return
|
||||
}
|
17
app/admin/ep/marthe/dao/mysql_schedule_task.go
Normal file
17
app/admin/ep/marthe/dao/mysql_schedule_task.go
Normal file
@ -0,0 +1,17 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertScheduleTask Insert Schedule Task.
|
||||
func (d *Dao) InsertScheduleTask(scheduleTask *model.ScheduleTask) error {
|
||||
return pkgerr.WithStack(d.db.Create(scheduleTask).Error)
|
||||
}
|
||||
|
||||
// UpdateScheduleTask Update Schedule Task.
|
||||
func (d *Dao) UpdateScheduleTask(scheduleTask *model.ScheduleTask) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.ScheduleTask{}).Updates(scheduleTask).Error)
|
||||
}
|
33
app/admin/ep/marthe/dao/mysql_schedule_task_test.go
Normal file
33
app/admin/ep/marthe/dao/mysql_schedule_task_test.go
Normal file
@ -0,0 +1,33 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpIssueNoStr3 = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
scheduleTask = &model.ScheduleTask{
|
||||
Name: tmpIssueNoStr3,
|
||||
Status: model.TaskStatusRunning,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Schedule_task(t *testing.T) {
|
||||
Convey("test insert schedule task", t, func() {
|
||||
err := d.InsertScheduleTask(scheduleTask)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test update schedule task", t, func() {
|
||||
scheduleTask.Status = model.TaskStatusDone
|
||||
err := d.UpdateScheduleTask(scheduleTask)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
}
|
47
app/admin/ep/marthe/dao/mysql_tapd_bug_priority_conf.go
Normal file
47
app/admin/ep/marthe/dao/mysql_tapd_bug_priority_conf.go
Normal file
@ -0,0 +1,47 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertTapdBugPriorityConf Insert Tapd Bug Priority Conf.
|
||||
func (d *Dao) InsertTapdBugPriorityConf(tapdBugPriorityConf *model.TapdBugPriorityConf) error {
|
||||
return pkgerr.WithStack(d.db.Create(tapdBugPriorityConf).Error)
|
||||
}
|
||||
|
||||
// UpdateTapdBugPriorityConf Update Tapd Bug Priority Conf.
|
||||
func (d *Dao) UpdateTapdBugPriorityConf(tapdBugPriorityConf *model.TapdBugPriorityConf) error {
|
||||
return pkgerr.WithStack(d.db.Save(&tapdBugPriorityConf).Error)
|
||||
}
|
||||
|
||||
// QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus Query Tapd Bug Priority Confs By Project TemplateId And tatus.
|
||||
func (d *Dao) QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus(projectTemplateID int64, status int) (tapdBugPriorityConfs []*model.TapdBugPriorityConf, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("project_template_id = ? and status = ?", projectTemplateID, status).Find(&tapdBugPriorityConfs).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindTapdBugPriorityConfs Find Tapd Bug Priority Confs.
|
||||
func (d *Dao) FindTapdBugPriorityConfs(req *model.QueryTapdBugPriorityConfsRequest) (total int64, tapdBugPriorityConfs []*model.TapdBugPriorityConf, err error) {
|
||||
gDB := d.db.Model(&model.TapdBugPriorityConf{})
|
||||
|
||||
if req.ProjectTemplateID > 0 {
|
||||
gDB = gDB.Where("project_template_id=?", req.ProjectTemplateID)
|
||||
}
|
||||
|
||||
if req.UpdateBy != "" {
|
||||
gDB = gDB.Where("update_by=?", req.UpdateBy)
|
||||
}
|
||||
|
||||
if req.Status > 0 {
|
||||
gDB = gDB.Where("status=?", req.Status)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&tapdBugPriorityConfs).Error)
|
||||
return
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"time"
|
||||
)
|
||||
|
||||
var (
|
||||
tapdBugPriorityConf = &model.TapdBugPriorityConf{
|
||||
ProjectTemplateID: 1000,
|
||||
Urgent: 123,
|
||||
High: 321,
|
||||
Medium: 111,
|
||||
UpdateBy: "fengyifeng",
|
||||
StartTime: time.Now(),
|
||||
EndTime: time.Now().AddDate(0, 1, 0),
|
||||
Status: model.TapdBugPriorityConfDisable,
|
||||
}
|
||||
|
||||
queryTapdBugPriorityConfsRequest = &model.QueryTapdBugPriorityConfsRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
ProjectTemplateID: 1000,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Tapd_Bug_Priority_Conf(t *testing.T) {
|
||||
Convey("test Insert Tapd Bug Priority Conf", t, func() {
|
||||
err := d.InsertTapdBugPriorityConf(tapdBugPriorityConf)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Tapd Bug Priority Conf", t, func() {
|
||||
tapdBugPriorityConf.Urgent = 10010
|
||||
err := d.UpdateTapdBugPriorityConf(tapdBugPriorityConf)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Find Tapd Bug Priority Confs", t, func() {
|
||||
total, tapdBugPriorityConfs, err := d.FindTapdBugPriorityConfs(queryTapdBugPriorityConfsRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldBeGreaterThan, 0)
|
||||
So(len(tapdBugPriorityConfs), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
}
|
57
app/admin/ep/marthe/dao/mysql_tapd_bug_record.go
Normal file
57
app/admin/ep/marthe/dao/mysql_tapd_bug_record.go
Normal file
@ -0,0 +1,57 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertTapdBugRecord Insert Tapd Bug Insert Log.
|
||||
func (d *Dao) InsertTapdBugRecord(tapdBugRecord *model.TapdBugRecord) error {
|
||||
return pkgerr.WithStack(d.db.Create(tapdBugRecord).Error)
|
||||
}
|
||||
|
||||
// UpdateTapdBugRecord Update Tapd Bug Insert Log.
|
||||
func (d *Dao) UpdateTapdBugRecord(tapdBugRecord *model.TapdBugRecord) error {
|
||||
return pkgerr.WithStack(d.db.Save(&tapdBugRecord).Error)
|
||||
}
|
||||
|
||||
// QueryTapdBugRecordByProjectIDAndStatus Query Tapd Bug Record By Project ID and status
|
||||
func (d *Dao) QueryTapdBugRecordByProjectIDAndStatus(projectID int64, status int) (tapdBugRecords []*model.TapdBugRecord, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("project_template_id = ? and status = ?", projectID, status).Find(&tapdBugRecords).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTapdBugRecordByStatus Query Tapd Bug Record By and status
|
||||
func (d *Dao) QueryTapdBugRecordByStatus(status int) (tapdBugRecords []*model.TapdBugRecord, err error) {
|
||||
err = pkgerr.WithStack(d.db.Where("status = ?", status).Find(&tapdBugRecords).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindBugRecords Find Bug Records.
|
||||
func (d *Dao) FindBugRecords(req *model.QueryBugRecordsRequest) (total int64, tapdBugRecords []*model.TapdBugRecord, err error) {
|
||||
gDB := d.db.Model(&model.TapdBugRecord{})
|
||||
|
||||
if req.ProjectTemplateID > 0 {
|
||||
gDB = gDB.Where("project_template_id=?", req.ProjectTemplateID)
|
||||
}
|
||||
|
||||
if req.VersionTemplateID > 0 {
|
||||
gDB = gDB.Where("version_template_id=?", req.VersionTemplateID)
|
||||
}
|
||||
|
||||
if req.Operator != "" {
|
||||
gDB = gDB.Where("operator=?", req.Operator)
|
||||
}
|
||||
|
||||
if req.Status > 0 {
|
||||
gDB = gDB.Where("status=?", req.Status)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&tapdBugRecords).Error)
|
||||
return
|
||||
}
|
42
app/admin/ep/marthe/dao/mysql_tapd_bug_record_test.go
Normal file
42
app/admin/ep/marthe/dao/mysql_tapd_bug_record_test.go
Normal file
@ -0,0 +1,42 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmpID = time.Now().Unix()
|
||||
|
||||
tapdBugRecord = &model.TapdBugRecord{
|
||||
ProjectTemplateID: tmpID,
|
||||
VersionTemplateID: tmpID + 1,
|
||||
Operator: "fengyifeng",
|
||||
Count: 10,
|
||||
Status: model.InsertBugStatusRunning,
|
||||
IssueFilterSQL: "SELECT * FROM bugly_issues WHERE issue_no = '265'",
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Tapd_bug_record(t *testing.T) {
|
||||
Convey("test Insert Tapd Bug Record", t, func() {
|
||||
err := d.InsertTapdBugRecord(tapdBugRecord)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Tapd Bug Record", t, func() {
|
||||
tapdBugRecord.Status = model.InsertBugStatusDone
|
||||
err := d.UpdateTapdBugRecord(tapdBugRecord)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Query Tapd Bug Record By Project ID And Status", t, func() {
|
||||
tapdBugRecords, err := d.QueryTapdBugRecordByProjectIDAndStatus(tapdBugRecord.ProjectTemplateID, model.InsertBugStatusDone)
|
||||
So(err, ShouldBeNil)
|
||||
So(len(tapdBugRecords), ShouldEqual, 1)
|
||||
})
|
||||
}
|
66
app/admin/ep/marthe/dao/mysql_tapd_bug_template.go
Normal file
66
app/admin/ep/marthe/dao/mysql_tapd_bug_template.go
Normal file
@ -0,0 +1,66 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertTapdBugTemplate Insert Tapd Bug Template.
|
||||
func (d *Dao) InsertTapdBugTemplate(tapdBugTemplate *model.TapdBugTemplate) error {
|
||||
return pkgerr.WithStack(d.db.Create(tapdBugTemplate).Error)
|
||||
}
|
||||
|
||||
// UpdateTapdBugTemplate Update Tapd Bug Template.
|
||||
func (d *Dao) UpdateTapdBugTemplate(tapdBugTemplate *model.TapdBugTemplate) error {
|
||||
return pkgerr.WithStack(d.db.Save(&tapdBugTemplate).Error)
|
||||
}
|
||||
|
||||
// QueryTapdBugTemplate Query Tapd Bug Template.
|
||||
func (d *Dao) QueryTapdBugTemplate(id int64) (tapdBugTemplate *model.TapdBugTemplate, err error) {
|
||||
tapdBugTemplate = &model.TapdBugTemplate{}
|
||||
if err = d.db.Where("id=?", id).First(&tapdBugTemplate).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTapdBugTemplateByProjectID Query Tapd Bug Template by project id.
|
||||
func (d *Dao) QueryTapdBugTemplateByProjectID(projectID string) (tapdBugTemplate *model.TapdBugTemplate, err error) {
|
||||
tapdBugTemplate = &model.TapdBugTemplate{}
|
||||
if err = d.db.Where("project_id=?", projectID).First(&tapdBugTemplate).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryAllTapdBugTemplates Query All Tapd Bug Templates.
|
||||
func (d *Dao) QueryAllTapdBugTemplates() (tapdBugTemplates []*model.TapdBugTemplate, err error) {
|
||||
err = pkgerr.WithStack(d.db.Model(&model.TapdBugTemplate{}).Find(&tapdBugTemplates).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// FindTapdBugTemplates Find tapd Bug Templates.
|
||||
func (d *Dao) FindTapdBugTemplates(req *model.QueryTapdBugTemplateRequest) (total int64, tapdBugTemplates []*model.TapdBugTemplate, err error) {
|
||||
gDB := d.db.Model(&model.TapdBugTemplate{})
|
||||
|
||||
if req.UpdateBy != "" {
|
||||
gDB = gDB.Where("update_by=?", req.UpdateBy)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&tapdBugTemplates).Error)
|
||||
return
|
||||
}
|
75
app/admin/ep/marthe/dao/mysql_tapd_bug_template_test.go
Normal file
75
app/admin/ep/marthe/dao/mysql_tapd_bug_template_test.go
Normal file
@ -0,0 +1,75 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmp5 = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
tapdBugTemplate = &model.TapdBugTemplate{
|
||||
WorkspaceID: tmp5,
|
||||
IssueFilterSQL: "SELECT * FROM bugly_issues WHERE issue_no = '265'",
|
||||
SeverityKey: "SeverityKey" + tmp5,
|
||||
UpdateBy: "fengyifeng",
|
||||
|
||||
TapdProperty: model.TapdProperty{
|
||||
Title: "Title" + tmp5,
|
||||
Description: "Description" + tmp5,
|
||||
CurrentOwner: "CurrentOwner" + tmp5,
|
||||
Platform: "Platform" + tmp5,
|
||||
Module: "Module" + tmp5,
|
||||
IterationID: "IterationID" + tmp5,
|
||||
ReleaseID: "ReleaseID" + tmp5,
|
||||
Priority: "Priority" + tmp5,
|
||||
Severity: "Severity" + tmp5,
|
||||
Source: "Source" + tmp5,
|
||||
CustomFieldFour: "CustomFieldFour" + tmp5,
|
||||
BugType: "BugType" + tmp5,
|
||||
OriginPhase: "OriginPhase" + tmp5,
|
||||
CustomFieldThree: "CustomFieldThree" + tmp5,
|
||||
Reporter: "Reporter" + tmp5,
|
||||
Status: "Status" + tmp5,
|
||||
},
|
||||
}
|
||||
|
||||
queryTapdBugTemplateRequest = &model.QueryTapdBugTemplateRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Tapd_bug_template(t *testing.T) {
|
||||
Convey("test Insert Tapd Bug Template", t, func() {
|
||||
err := d.InsertTapdBugTemplate(tapdBugTemplate)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Tapd Bug Template", t, func() {
|
||||
tapdBugTemplate.UpdateBy = "xuneng"
|
||||
err := d.UpdateTapdBugTemplate(tapdBugTemplate)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Query Tapd Bug Template", t, func() {
|
||||
tmpTapdBugTemplate, err := d.QueryTapdBugTemplate(tapdBugTemplate.ID)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpTapdBugTemplate.ID, ShouldEqual, tapdBugTemplate.ID)
|
||||
})
|
||||
|
||||
Convey("test Find Tapd Bug Templates", t, func() {
|
||||
total, tapdBugTemplates, err := d.FindTapdBugTemplates(queryTapdBugTemplateRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldBeGreaterThan, 0)
|
||||
So(len(tapdBugTemplates), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
|
||||
}
|
68
app/admin/ep/marthe/dao/mysql_tapd_bug_version_template.go
Normal file
68
app/admin/ep/marthe/dao/mysql_tapd_bug_version_template.go
Normal file
@ -0,0 +1,68 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// InsertTapdBugVersionTemplate Insert TapdBug Version Template.
|
||||
func (d *Dao) InsertTapdBugVersionTemplate(tapdBugVersionTemplate *model.TapdBugVersionTemplate) error {
|
||||
return pkgerr.WithStack(d.db.Create(tapdBugVersionTemplate).Error)
|
||||
}
|
||||
|
||||
// UpdateTapdBugVersionTemplate Update Tapd Bug Version Template.
|
||||
func (d *Dao) UpdateTapdBugVersionTemplate(tapdBugVersionTemplate *model.TapdBugVersionTemplate) error {
|
||||
return pkgerr.WithStack(d.db.Save(&tapdBugVersionTemplate).Error)
|
||||
}
|
||||
|
||||
// QueryTapdBugVersionTemplate Query Tapd Bug Version Template.
|
||||
func (d *Dao) QueryTapdBugVersionTemplate(id int64) (tapdBugVersionTemplate *model.TapdBugVersionTemplate, err error) {
|
||||
tapdBugVersionTemplate = &model.TapdBugVersionTemplate{}
|
||||
if err = d.db.Where("id=?", id).First(&tapdBugVersionTemplate).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTapdBugVersionTemplateByVersion Query Tapd Bug Version Template.
|
||||
func (d *Dao) QueryTapdBugVersionTemplateByVersion(version string) (tapdBugVersionTemplate *model.TapdBugVersionTemplate, err error) {
|
||||
tapdBugVersionTemplate = &model.TapdBugVersionTemplate{}
|
||||
if err = d.db.Where("version=?", version).First(&tapdBugVersionTemplate).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindTapdBugVersionTemplates Find Tapd Bug Version Templates.
|
||||
func (d *Dao) FindTapdBugVersionTemplates(req *model.QueryTapdBugVersionTemplateRequest) (total int64, tapdBugVersionTemplate []*model.TapdBugVersionTemplate, err error) {
|
||||
gDB := d.db.Model(&model.TapdBugVersionTemplate{})
|
||||
|
||||
if req.ProjectID > 0 {
|
||||
gDB = gDB.Where("project_template_id = ?", req.ProjectID)
|
||||
}
|
||||
|
||||
if req.Version != "" {
|
||||
gDB = gDB.Where("version like ?", req.Version+_wildcards)
|
||||
}
|
||||
|
||||
if req.UpdateBy != "" {
|
||||
gDB = gDB.Where("update_by = ?", req.UpdateBy)
|
||||
}
|
||||
|
||||
if err = pkgerr.WithStack(gDB.Count(&total).Error); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = pkgerr.WithStack(gDB.Order("ctime desc").Offset((req.PageNum - 1) * req.PageSize).Limit(req.PageSize).Find(&tapdBugVersionTemplate).Error)
|
||||
return
|
||||
}
|
@ -0,0 +1,82 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
var (
|
||||
tmp6 = strconv.FormatInt(time.Now().Unix(), 10)
|
||||
|
||||
tapdBugVersionTemplate = &model.TapdBugVersionTemplate{
|
||||
Version: "version" + tmp6,
|
||||
ProjectTemplateID: 10,
|
||||
IssueFilterSQL: "SELECT * FROM bugly_issues WHERE issue_no = '265'",
|
||||
SeverityKey: "SeverityKey" + tmp6,
|
||||
UpdateBy: "fengyifeng",
|
||||
|
||||
TapdProperty: model.TapdProperty{
|
||||
Title: "Title" + tmp6,
|
||||
Description: "Description" + tmp6,
|
||||
CurrentOwner: "CurrentOwner" + tmp6,
|
||||
Platform: "Platform" + tmp6,
|
||||
Module: "Module" + tmp6,
|
||||
IterationID: "IterationID" + tmp6,
|
||||
ReleaseID: "ReleaseID" + tmp6,
|
||||
Priority: "Priority" + tmp6,
|
||||
Severity: "Severity" + tmp6,
|
||||
Source: "Source" + tmp6,
|
||||
CustomFieldFour: "CustomFieldFour" + tmp6,
|
||||
BugType: "BugType" + tmp6,
|
||||
OriginPhase: "OriginPhase" + tmp6,
|
||||
CustomFieldThree: "CustomFieldThree" + tmp6,
|
||||
Reporter: "Reporter" + tmp6,
|
||||
Status: "Status" + tmp6,
|
||||
},
|
||||
}
|
||||
|
||||
queryTapdBugVersionTemplateRequest = &model.QueryTapdBugVersionTemplateRequest{
|
||||
Pagination: model.Pagination{
|
||||
PageSize: 10,
|
||||
PageNum: 1,
|
||||
},
|
||||
Version: tapdBugVersionTemplate.Version,
|
||||
}
|
||||
)
|
||||
|
||||
func Test_Tapd_bug_version_template(t *testing.T) {
|
||||
Convey("test Insert Tapd Bug version Template", t, func() {
|
||||
err := d.InsertTapdBugVersionTemplate(tapdBugVersionTemplate)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Update Tapd Bug version Template", t, func() {
|
||||
tapdBugTemplate.UpdateBy = "xuneng"
|
||||
err := d.UpdateTapdBugVersionTemplate(tapdBugVersionTemplate)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("test Query Tapd Bug version Template", t, func() {
|
||||
tmpTapdBugVersionTemplate, err := d.QueryTapdBugVersionTemplate(tapdBugVersionTemplate.ID)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpTapdBugVersionTemplate.ID, ShouldEqual, tapdBugVersionTemplate.ID)
|
||||
})
|
||||
|
||||
Convey("test Query Tapd Bug Version Template By version", t, func() {
|
||||
tmpTapdBugVersionTemplate, err := d.QueryTapdBugVersionTemplateByVersion(tapdBugVersionTemplate.Version)
|
||||
So(err, ShouldBeNil)
|
||||
So(tmpTapdBugVersionTemplate.ID, ShouldEqual, tapdBugVersionTemplate.ID)
|
||||
})
|
||||
|
||||
Convey("test Find Tapd Bug version Templates", t, func() {
|
||||
total, tapdBugVersionTemplate, err := d.FindTapdBugVersionTemplates(queryTapdBugVersionTemplateRequest)
|
||||
So(err, ShouldBeNil)
|
||||
So(total, ShouldBeGreaterThan, 0)
|
||||
So(len(tapdBugVersionTemplate), ShouldBeGreaterThan, 0)
|
||||
})
|
||||
}
|
43
app/admin/ep/marthe/dao/mysql_user.go
Normal file
43
app/admin/ep/marthe/dao/mysql_user.go
Normal file
@ -0,0 +1,43 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
|
||||
pkgerr "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// FindUserByUserName find user by username.
|
||||
func (d *Dao) FindUserByUserName(name string) (user *model.User, err error) {
|
||||
user = &model.User{}
|
||||
if err = d.db.Where("name = ?", name).First(user).Error; err != nil {
|
||||
if err == ecode.NothingFound {
|
||||
err = nil
|
||||
} else {
|
||||
err = pkgerr.WithStack(err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// FindUserByID find user by id.
|
||||
func (d *Dao) FindUserByID(ID int64) (user *model.User, err error) {
|
||||
user = &model.User{}
|
||||
err = pkgerr.WithStack(d.db.Where("id = ?", ID).First(user).Error)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateUser create user.
|
||||
func (d *Dao) CreateUser(user *model.User) error {
|
||||
return pkgerr.WithStack(d.db.Create(user).Error)
|
||||
}
|
||||
|
||||
// DelUser delete user.
|
||||
func (d *Dao) DelUser(user *model.User) error {
|
||||
return pkgerr.WithStack(d.db.Delete(user).Error)
|
||||
}
|
||||
|
||||
// UpdateUserVisibleBugly Update User Visible Bugly.
|
||||
func (d *Dao) UpdateUserVisibleBugly(ID int64, visibleBugly bool) error {
|
||||
return pkgerr.WithStack(d.db.Model(&model.User{}).Where("id = ?", ID).Update("visible_bugly", visibleBugly).Error)
|
||||
}
|
42
app/admin/ep/marthe/dao/mysql_user_test.go
Normal file
42
app/admin/ep/marthe/dao/mysql_user_test.go
Normal file
@ -0,0 +1,42 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
)
|
||||
|
||||
var (
|
||||
testTime = time.Now().Format("2006_01_02_15_04_05")
|
||||
testUser = model.User{
|
||||
Name: testTime,
|
||||
EMail: testTime + "@bilibili.com"}
|
||||
)
|
||||
|
||||
func Test_User(t *testing.T) {
|
||||
Convey("test CreateUser", t, func() {
|
||||
err := d.CreateUser(&testUser)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("find user by user name", t, func() {
|
||||
userInDb, err := d.FindUserByUserName(testUser.Name)
|
||||
So(userInDb.EMail, ShouldEqual, testUser.EMail)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("find user by id", t, func() {
|
||||
userID := testUser.ID
|
||||
userInDb, err := d.FindUserByID(userID)
|
||||
So(userInDb.EMail, ShouldEqual, testUser.EMail)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
Convey("delete user", t, func() {
|
||||
err := d.DelUser(&testUser)
|
||||
So(err, ShouldBeNil)
|
||||
})
|
||||
|
||||
}
|
221
app/admin/ep/marthe/dao/tapd.go
Normal file
221
app/admin/ep/marthe/dao/tapd.go
Normal file
@ -0,0 +1,221 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/cache/memcache"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
const (
|
||||
_userName = "bilibilinik"
|
||||
_password = "0989D4F0-AF9D-949F-C950-E22A3F891NIK"
|
||||
_successCode = 1
|
||||
|
||||
_releaseURL = "https://api.tapd.cn/releases?workspace_id=%s&id=%s"
|
||||
_bugPreURL = "https://api.tapd.cn/bugs?workspace_id=%s&id=%s"
|
||||
_createBugURL = "https://api.tapd.cn/bugs"
|
||||
_workspaceUserURL = "https://api.tapd.cn/workspaces/users?workspace_id=%s&fields=user"
|
||||
)
|
||||
|
||||
//Bug Bug
|
||||
func (d *Dao) Bug(bugURL string) (res *model.BugResponse, err error) {
|
||||
var req *http.Request
|
||||
res = &model.BugResponse{}
|
||||
if req, err = d.newTapdRequest(http.MethodGet, bugURL, nil); err != nil {
|
||||
log.Error("Bug url(%s) res(%v) err(%v)", bugURL, res, err)
|
||||
return nil, ecode.MartheTapdErr
|
||||
}
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil {
|
||||
log.Error("WorkspaceUser url(%s) res(%v) err(%v)", bugURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode {
|
||||
log.Error("WorkspaceUser url(%s) res(%v) err(%v)", bugURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//BugPre Bug Pre
|
||||
func (d *Dao) BugPre(workSpaceID, bugID string) (bug *model.Bug, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.BugSingleResponse{}
|
||||
)
|
||||
|
||||
url := fmt.Sprintf(_bugPreURL, workSpaceID, bugID)
|
||||
if req, err = d.newTapdRequest(http.MethodGet, url, nil); err != nil {
|
||||
log.Error("BugPre url(%s) res(%v) err(%v)", url, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil || res.Data == nil {
|
||||
log.Error("BugPre url(%s) res(%v) err(%v)", url, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode || res.Data == nil {
|
||||
log.Error("BugPre url(%s) res(%v) err(%v)", url, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
return
|
||||
}
|
||||
|
||||
bug = res.Data.Bug
|
||||
return
|
||||
}
|
||||
|
||||
//Release Release
|
||||
func (d *Dao) Release(workSpaceID, releaseID string) (release *model.Release, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.ReleaseResponse{}
|
||||
)
|
||||
|
||||
releaseURL := fmt.Sprintf(_releaseURL, workSpaceID, releaseID)
|
||||
if req, err = d.newTapdRequest(http.MethodGet, releaseURL, nil); err != nil {
|
||||
log.Error("Release url(%s) res(%v) err(%v)", _releaseURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil || res.Data == nil {
|
||||
log.Error("Release url(%s) res(%v) err(%v)", _releaseURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode || res.Data == nil {
|
||||
log.Error("Release url(%s) res(%v) err(%v)", _releaseURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
return
|
||||
}
|
||||
|
||||
release = res.Data.Release
|
||||
return
|
||||
}
|
||||
|
||||
// ReleaseName ReleaseName
|
||||
func (d *Dao) ReleaseName(workspaceID, releaseID string) (releaseName string, err error) {
|
||||
var (
|
||||
item *memcache.Item
|
||||
conn = d.mc.Get(context.Background())
|
||||
release *model.Release
|
||||
)
|
||||
defer conn.Close()
|
||||
|
||||
if item, err = conn.Get(workspaceID + releaseID); err == nil {
|
||||
if err = json.Unmarshal(item.Value, &releaseName); err != nil {
|
||||
log.Error("Json unmarshal err(%v)", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if release, err = d.Release(workspaceID, releaseID); err != nil {
|
||||
return
|
||||
}
|
||||
releaseName = release.Name
|
||||
item = &memcache.Item{Key: workspaceID + releaseID, Object: release.Name, Flags: memcache.FlagJSON, Expiration: d.expire}
|
||||
d.cacheSave(context.Background(), item)
|
||||
return
|
||||
}
|
||||
|
||||
//newTapdRequest new tapd request
|
||||
func (d *Dao) newTapdRequest(method, url string, v interface{}) (req *http.Request, err error) {
|
||||
req, err = d.newRequest(method, url, v)
|
||||
req.SetBasicAuth(_userName, _password)
|
||||
return
|
||||
}
|
||||
|
||||
// CreateBug Create Bug.
|
||||
func (d *Dao) CreateBug(bug *model.Bug) (bugID string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.BugSingleResponse{}
|
||||
)
|
||||
|
||||
if req, err = d.newTapdRequest(http.MethodPost, _createBugURL, bug); err != nil {
|
||||
log.Error("CreateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil {
|
||||
log.Error("CreateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode {
|
||||
log.Error("CreateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
}
|
||||
|
||||
bugID = res.Data.Bug.ID
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateBug Update Bug.
|
||||
func (d *Dao) UpdateBug(bug *model.UpdateBug) (err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.BugSingleResponse{}
|
||||
)
|
||||
|
||||
if req, err = d.newTapdRequest(http.MethodPost, _createBugURL, bug); err != nil {
|
||||
log.Error("UpdateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil {
|
||||
log.Error("UpdateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode {
|
||||
log.Error("UpdateBug url(%s) res(%v) err(%v)", _createBugURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// WorkspaceUser Workspace User
|
||||
func (d *Dao) WorkspaceUser(workspaceID string) (usernames []string, err error) {
|
||||
var (
|
||||
req *http.Request
|
||||
res = &model.WorkspaceUserResponse{}
|
||||
)
|
||||
|
||||
workspaceUserURL := fmt.Sprintf(_workspaceUserURL, workspaceID)
|
||||
if req, err = d.newTapdRequest(http.MethodGet, workspaceUserURL, nil); err != nil {
|
||||
log.Error("WorkspaceUser url(%s) res(%v) err(%v)", workspaceUserURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
if err = d.httpClient.Do(context.TODO(), req, res); err != nil {
|
||||
log.Error("WorkspaceUser url(%s) res(%v) err(%v)", workspaceUserURL, res, err)
|
||||
err = ecode.MartheTapdErr
|
||||
return
|
||||
}
|
||||
|
||||
if res.Status != _successCode || res.Data == nil {
|
||||
log.Error("WorkspaceUser url(%s) res(%v) err(%v)", workspaceUserURL, res, err)
|
||||
err = ecode.MartheTapdResDataErr
|
||||
return
|
||||
}
|
||||
|
||||
for _, workspaceUser := range res.Data {
|
||||
usernames = append(usernames, workspaceUser.UserWrapper.User)
|
||||
}
|
||||
return
|
||||
}
|
80
app/admin/ep/marthe/dao/wechat.go
Normal file
80
app/admin/ep/marthe/dao/wechat.go
Normal file
@ -0,0 +1,80 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
)
|
||||
|
||||
const (
|
||||
_qyWechatURL = "https://qyapi.weixin.qq.com"
|
||||
_corpID = "wx0833ac9926284fa5" // 企业微信:Bilibili的企业ID
|
||||
_departmentID = "12" // 公司统一用部门ID
|
||||
_corpsecret = "WveODxk3xpT9box48wcxkmArx3mu6d4vJHdJkNy_iTk"
|
||||
|
||||
_getToken = "/cgi-bin/gettoken"
|
||||
_userList = "/cgi-bin/user/list"
|
||||
)
|
||||
|
||||
// WechatAccessToken query access token with the specified secret 企业微信api获取公司token
|
||||
func (d *Dao) WechatAccessToken(c context.Context) (token string, err error) {
|
||||
var (
|
||||
u string
|
||||
params = url.Values{}
|
||||
res struct {
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
AccessToken string `json:"access_token"`
|
||||
ExpiresIn int32 `json:"expires_in"`
|
||||
}
|
||||
)
|
||||
u = _qyWechatURL + _getToken
|
||||
params.Set("corpid", _corpID)
|
||||
params.Set("corpsecret", _corpsecret)
|
||||
|
||||
if err = d.httpClient.Get(c, u, "", params, &res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if res.ErrCode != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
token = res.AccessToken
|
||||
return
|
||||
}
|
||||
|
||||
// WechatContacts Wechat Contacts 获取用户信息列表
|
||||
func (d *Dao) WechatContacts(c context.Context) (contacts []*model.WechatContact, err error) {
|
||||
var (
|
||||
token string
|
||||
u string
|
||||
params = url.Values{}
|
||||
res struct {
|
||||
ErrCode int `json:"errcode"`
|
||||
ErrMsg string `json:"errmsg"`
|
||||
UserList []*model.WechatContact `json:"userlist"`
|
||||
}
|
||||
)
|
||||
//get token
|
||||
if token, err = d.WechatAccessToken(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
u = _qyWechatURL + _userList
|
||||
params.Set("access_token", token)
|
||||
params.Set("department_id", _departmentID)
|
||||
params.Set("fetch_child", "1")
|
||||
|
||||
if err = d.httpClient.Get(c, u, "", params, &res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if res.ErrCode != 0 {
|
||||
return
|
||||
}
|
||||
|
||||
contacts = res.UserList
|
||||
return
|
||||
}
|
36
app/admin/ep/marthe/model/BUILD
Normal file
36
app/admin/ep/marthe/model/BUILD
Normal file
@ -0,0 +1,36 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bugly.go",
|
||||
"constants.go",
|
||||
"marthe.go",
|
||||
"model.go",
|
||||
"tapd.go",
|
||||
"wechat.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/marthe/model",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//library/ecode:go_default_library"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
89
app/admin/ep/marthe/model/bugly.go
Normal file
89
app/admin/ep/marthe/model/bugly.go
Normal file
@ -0,0 +1,89 @@
|
||||
package model
|
||||
|
||||
// BugIssueRequest Bug Issue Request.
|
||||
type BugIssueRequest struct {
|
||||
StartNum int
|
||||
Version string
|
||||
Rows int
|
||||
PlatformID string
|
||||
ProjectID string
|
||||
ExceptionType string
|
||||
}
|
||||
|
||||
// BugIssueResponse Bug Issue Response.
|
||||
type BugIssueResponse struct {
|
||||
Status int `json:"status"`
|
||||
Code int `json:"code"`
|
||||
Ret *BugRet `json:"ret"`
|
||||
}
|
||||
|
||||
// BugRet Bug Ret.
|
||||
type BugRet struct {
|
||||
NumFound int `json:"numFound"`
|
||||
BugIssues []*BugIssues `json:"issueList"`
|
||||
}
|
||||
|
||||
// BugIssues Bug Issues.
|
||||
type BugIssues struct {
|
||||
IssueID string `json:"issueId"`
|
||||
Title string `json:"exceptionName"`
|
||||
ExceptionMsg string `json:"exceptionMessage"`
|
||||
KeyStack string `json:"keyStack"`
|
||||
LastTime string `json:"lastestUploadTime"`
|
||||
Count int `json:"count"`
|
||||
Tags []*BugTag `json:"tagInfoList"`
|
||||
UserCount int `json:"imeiCount"`
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// BugTag Bug Tag.
|
||||
type BugTag struct {
|
||||
TagName string `json:"tagName"`
|
||||
}
|
||||
|
||||
// BugIssueDetailResponse Bug Issue Detail Response.
|
||||
type BugIssueDetailResponse struct {
|
||||
Code int `json:"code"`
|
||||
Data *BugIssueDetail `json:"data"`
|
||||
}
|
||||
|
||||
// BugIssueDetail Bug Issue Detail.
|
||||
type BugIssueDetail struct {
|
||||
CallStack string `json:"callStack"`
|
||||
}
|
||||
|
||||
// BugVersionResponse Bug Version Response.
|
||||
type BugVersionResponse struct {
|
||||
Status int `json:"status"`
|
||||
Code int `json:"code"`
|
||||
Ret *SelectorPropertyList `json:"ret"`
|
||||
}
|
||||
|
||||
// SelectorPropertyList SelectorPropertyList.
|
||||
type SelectorPropertyList struct {
|
||||
BugVersionList []*BugVersion `json:"versionList"`
|
||||
}
|
||||
|
||||
// BugVersion BugVersion.
|
||||
type BugVersion struct {
|
||||
Name string `json:"name"`
|
||||
Enable int `json:"enable"`
|
||||
SDKVersion string `json:"sdkVersion"`
|
||||
}
|
||||
|
||||
// BugIssueExceptionListResponse Bug Issue Exception List Response.
|
||||
type BugIssueExceptionListResponse struct {
|
||||
Status int `json:"status"`
|
||||
Ret *IssueExceptionList `json:"ret"`
|
||||
}
|
||||
|
||||
// IssueExceptionList IssueExceptionList.
|
||||
type IssueExceptionList struct {
|
||||
IssueException []*IssueException `json:"issueList"`
|
||||
}
|
||||
|
||||
// IssueException IssueException.
|
||||
type IssueException struct {
|
||||
IssueID string `json:"issueId"`
|
||||
Status int `json:"status"`
|
||||
}
|
65
app/admin/ep/marthe/model/constants.go
Normal file
65
app/admin/ep/marthe/model/constants.go
Normal file
@ -0,0 +1,65 @@
|
||||
package model
|
||||
|
||||
// TimeLayout
|
||||
const (
|
||||
TimeLayout = "2006-01-02 15:04:05"
|
||||
)
|
||||
|
||||
// page
|
||||
const (
|
||||
DefaultPageSize = 5
|
||||
DefaultPageNum = 1
|
||||
)
|
||||
|
||||
// BuglyVersion task status
|
||||
const (
|
||||
BuglyVersionTaskStatusReady = 1
|
||||
BuglyVersionTaskStatusRunning = 2
|
||||
)
|
||||
|
||||
// BuglyVersion action
|
||||
const (
|
||||
BuglyVersionActionEnable = 1
|
||||
BuglyVersionActionDisable = 2
|
||||
)
|
||||
|
||||
// BuglyCookie status
|
||||
const (
|
||||
BuglyCookieStatusEnable = 1
|
||||
BuglyCookieStatusDisable = 2
|
||||
)
|
||||
|
||||
// BuglyBatchRun status
|
||||
const (
|
||||
BuglyBatchRunStatusRunning = 1
|
||||
BuglyBatchRunStatusDone = 2
|
||||
BuglyBatchRunStatusFailed = 3
|
||||
)
|
||||
|
||||
// Insert bug status
|
||||
const (
|
||||
InsertBugStatusRunning = 1
|
||||
InsertBugStatusDone = 2
|
||||
InsertBugStatusFailed = 3
|
||||
)
|
||||
|
||||
// Tapd Bug Priority Conf Enable
|
||||
const (
|
||||
TapdBugPriorityConfEnable = 1
|
||||
TapdBugPriorityConfDisable = 2
|
||||
)
|
||||
|
||||
// Task Status
|
||||
const (
|
||||
TaskStatusRunning = 1
|
||||
TaskStatusDone = 2
|
||||
TaskStatusFailed = 3
|
||||
)
|
||||
|
||||
// Task Type
|
||||
const (
|
||||
TaskBatchRunVersions = "BatchRunVersions"
|
||||
TaskDisableBatchRunOverTime = "DisableBatchRunOverTime"
|
||||
TaskBatchRunUpdateBugInTapd = "BatchRunUpdateBugInTapd"
|
||||
TaskSyncWechatContact = "SyncWechatContact"
|
||||
)
|
260
app/admin/ep/marthe/model/marthe.go
Normal file
260
app/admin/ep/marthe/model/marthe.go
Normal file
@ -0,0 +1,260 @@
|
||||
package model
|
||||
|
||||
import "go-common/library/ecode"
|
||||
|
||||
// AddVersionRequest Add Version Request.
|
||||
type AddVersionRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
BuglyProjectID int64 `json:"bugly_project_id"`
|
||||
Version string `json:"version"`
|
||||
Action int `json:"action"`
|
||||
}
|
||||
|
||||
// AddProjectRequest Add Project Request.
|
||||
type AddProjectRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
ProjectName string `json:"project_name"`
|
||||
ProjectID string `json:"project_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
ExceptionType string `json:"exception_type"`
|
||||
}
|
||||
|
||||
// AddCookieRequest Add Cookie Request.
|
||||
type AddCookieRequest struct {
|
||||
ID int64 `json:"id"`
|
||||
Cookie string `json:"cookie"`
|
||||
Token string `json:"token"`
|
||||
Status int `json:"status"`
|
||||
QQAccount int `json:"qq_account"`
|
||||
}
|
||||
|
||||
// BuglyIssueImportRequest Bugly Issue Import Request.
|
||||
type BuglyIssueImportRequest struct {
|
||||
IssueImportInfo []*IssueImportInfo `json:"import_info"`
|
||||
}
|
||||
|
||||
// IssueImportInfo Issue Import Info.
|
||||
type IssueImportInfo struct {
|
||||
ProjectID string `json:"project_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
Version []string `json:"version"`
|
||||
}
|
||||
|
||||
// Pagination Pagination.
|
||||
type Pagination struct {
|
||||
PageSize int `form:"page_size" json:"page_size"`
|
||||
PageNum int `form:"page_num" json:"page_num"`
|
||||
}
|
||||
|
||||
// PaginationRep Pagination Response.
|
||||
type PaginationRep struct {
|
||||
PageSize int `json:"page_size"`
|
||||
PageNum int `json:"page_num"`
|
||||
Total int64 `json:"total"`
|
||||
}
|
||||
|
||||
// Verify verify the value of pageNum and pageSize.
|
||||
func (p *Pagination) Verify() error {
|
||||
if p.PageNum < 0 {
|
||||
return ecode.MerlinIllegalPageNumErr
|
||||
} else if p.PageNum == 0 {
|
||||
p.PageNum = DefaultPageNum
|
||||
}
|
||||
if p.PageSize < 0 {
|
||||
return ecode.MerlinIllegalPageSizeErr
|
||||
} else if p.PageSize == 0 {
|
||||
p.PageSize = DefaultPageSize
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// QueryBuglyVersionRequest Query Bugly Version Request.
|
||||
type QueryBuglyVersionRequest struct {
|
||||
Pagination
|
||||
Version string `json:"version"`
|
||||
ProjectName string `json:"project_name"`
|
||||
Action int `json:"action"`
|
||||
TaskStatus int `json:"task_status"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
// QueryBuglyBatchRunsRequest Query Bugly Batch Runs Request.
|
||||
type QueryBuglyBatchRunsRequest struct {
|
||||
Pagination
|
||||
Version string `json:"version"`
|
||||
Status int `json:"status"`
|
||||
BatchID string `json:"batch_id"`
|
||||
}
|
||||
|
||||
// PaginateBuglyBatchRuns Paginate Bugly Batch Runs.
|
||||
type PaginateBuglyBatchRuns struct {
|
||||
PaginationRep
|
||||
BuglyBatchRuns []*BuglyBatchRun `json:"bugly_batch_runs"`
|
||||
}
|
||||
|
||||
// QueryBugRecordsRequest Query Bug Records Request.
|
||||
type QueryBugRecordsRequest struct {
|
||||
Pagination
|
||||
ProjectTemplateID int64 `json:"project_template_id"`
|
||||
VersionTemplateID int64 `json:"version_template_id"`
|
||||
Operator string `json:"operator"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// QueryTapdBugPriorityConfsRequest Query Tapd Bug Priority Confs Request.
|
||||
type QueryTapdBugPriorityConfsRequest struct {
|
||||
Pagination
|
||||
ProjectTemplateID int64 `json:"project_template_id"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// PaginateTapdBugPriorityConfs Paginate Tapd Bug Priority Confs.
|
||||
type PaginateTapdBugPriorityConfs struct {
|
||||
PaginationRep
|
||||
TapdBugPriorityConfs []*TapdBugPriorityConf `json:"tapd_bug_priority_confs"`
|
||||
}
|
||||
|
||||
// PaginateBugRecords Paginate Bug Records.
|
||||
type PaginateBugRecords struct {
|
||||
PaginationRep
|
||||
TapdBugRecords []*TapdBugRecord `json:"tapd_bug_records"`
|
||||
}
|
||||
|
||||
// QueryBuglyCookiesRequest Query Bugly Batch Runs Request.
|
||||
type QueryBuglyCookiesRequest struct {
|
||||
Pagination
|
||||
QQAccount int `json:"qq_account"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// PaginateBuglyCookies Paginate Bugly Cookies.
|
||||
type PaginateBuglyCookies struct {
|
||||
PaginationRep
|
||||
BuglyCookies []*BuglyCookie `json:"bugly_cookies"`
|
||||
}
|
||||
|
||||
// PaginateBuglyProjectVersions Paginate Bugly Project Versions.
|
||||
type PaginateBuglyProjectVersions struct {
|
||||
PaginationRep
|
||||
BuglyProjectVersions []*BuglyProjectVersion `json:"bugly_project_versions"`
|
||||
}
|
||||
|
||||
// QueryTapdBugTemplateRequest Query tapd Bug Template Request.
|
||||
type QueryTapdBugTemplateRequest struct {
|
||||
Pagination
|
||||
ProjectName string `json:"project_name"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
// QueryTapdBugVersionTemplateRequest Query Tapd Bug Version Template Request.
|
||||
type QueryTapdBugVersionTemplateRequest struct {
|
||||
Pagination
|
||||
ProjectID int64 `json:"project_template_id"`
|
||||
Version string `json:"version"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
// PaginateTapdBugTemplates Paginate Tapd Bug Template.
|
||||
type PaginateTapdBugTemplates struct {
|
||||
PaginationRep
|
||||
TapdBugTemplateWithProjectNames []*TapdBugTemplateWithProjectName `json:"tapd_bug_templates"`
|
||||
}
|
||||
|
||||
// TapdBugTemplateWithProjectName Paginate Tapd Bug Template.
|
||||
type TapdBugTemplateWithProjectName struct {
|
||||
*TapdBugTemplate
|
||||
ProjectName string `json:"project_name"`
|
||||
}
|
||||
|
||||
// PaginateTapdBugVersionTemplates Paginate Tapd Bug Version Template.
|
||||
type PaginateTapdBugVersionTemplates struct {
|
||||
PaginationRep
|
||||
TapdBugVersionTemplates []*TapdBugVersionTemplate `json:"tapd_bug_version_templates"`
|
||||
}
|
||||
|
||||
// UpdateTapdBugTplRequest Update Tapd Bug Tpl Request.
|
||||
type UpdateTapdBugTplRequest struct {
|
||||
ID int64 `json:"id" `
|
||||
WorkspaceID string `json:"workspace_id"`
|
||||
BuglyProjectId int64 `json:"bugly_project_id" `
|
||||
|
||||
IssueFilterSQL string `json:"issue_filter_sql"`
|
||||
SeverityKey string `json:"severity_key"`
|
||||
|
||||
TapdProperty
|
||||
}
|
||||
|
||||
// UpdateTapdBugVersionTplRequest Update Tapd Bug Tpl Request.
|
||||
type UpdateTapdBugVersionTplRequest struct {
|
||||
ID int64 `json:"id" `
|
||||
Version string `json:"version" `
|
||||
ProjectTemplateID int64 `json:"project_template_id"`
|
||||
|
||||
IssueFilterSQL string `json:"issue_filter_sql"`
|
||||
SeverityKey string `json:"severity_key"`
|
||||
|
||||
TapdProperty
|
||||
}
|
||||
|
||||
// QueryBuglyIssueRequest Query Bugly Issue Request.
|
||||
type QueryBuglyIssueRequest struct {
|
||||
Pagination
|
||||
IssueNo string `json:"issue_no"`
|
||||
Title string `json:"title"`
|
||||
ExceptionMsg string `json:"exception_msg" `
|
||||
KeyStack string `json:"key_stack"`
|
||||
Detail string `json:"detail"`
|
||||
Tags string `json:"tags"`
|
||||
Version string `json:"version" `
|
||||
ProjectID string `json:"project_id"`
|
||||
TapdBugID string `json:"tapd_bug_id"`
|
||||
}
|
||||
|
||||
// PaginateBuglyIssues Paginate Bugly Issues.
|
||||
type PaginateBuglyIssues struct {
|
||||
PaginationRep
|
||||
BuglyIssues []*BuglyIssue `json:"bugly_issues"`
|
||||
}
|
||||
|
||||
// UpdateTapdBugPriorityConfRequest Update Tapd Bug Priority Conf Request.
|
||||
type UpdateTapdBugPriorityConfRequest struct {
|
||||
ID int64 `json:"id" `
|
||||
ProjectTemplateID int64 `json:"project_template_id"`
|
||||
Urgent int `json:"urgent"`
|
||||
High int `json:"high"`
|
||||
Medium int `json:"medium"`
|
||||
StartTime string `json:"start_time"`
|
||||
EndTime string `json:"end_time"`
|
||||
Status int `json:"status"`
|
||||
}
|
||||
|
||||
// QueryBuglyProjectRequest Query Bugly Project Request.
|
||||
type QueryBuglyProjectRequest struct {
|
||||
Pagination
|
||||
ProjectName string `json:"project_name"`
|
||||
ProjectID string `json:"project_id"`
|
||||
PlatformID string `json:"platform_id"`
|
||||
UpdateBy string `json:"update_by"`
|
||||
}
|
||||
|
||||
// PaginateBuglyProjects Paginate Bugly Projects.
|
||||
type PaginateBuglyProjects struct {
|
||||
PaginationRep
|
||||
BuglyProjects []*BuglyProject `json:"bugly_projects"`
|
||||
}
|
||||
|
||||
// BuglyProjectVersion Bugly Project Version.
|
||||
type BuglyProjectVersion struct {
|
||||
BuglyVersion
|
||||
ProjectName string `json:"project_name"`
|
||||
ExceptionType string `json:"exception_type"`
|
||||
}
|
||||
|
||||
// TapdBugTemplateShortResponse Tapd Bug Template Short Response.
|
||||
type TapdBugTemplateShortResponse struct {
|
||||
ID int64 `json:"id"`
|
||||
WorkspaceID string `json:"workspace_id"`
|
||||
BuglyProjectId int64 `json:"bugly_project_id"`
|
||||
BuglyProjectName string `json:"project_name"`
|
||||
}
|
183
app/admin/ep/marthe/model/model.go
Normal file
183
app/admin/ep/marthe/model/model.go
Normal file
@ -0,0 +1,183 @@
|
||||
package model
|
||||
|
||||
import (
|
||||
"time"
|
||||
)
|
||||
|
||||
// BuglyIssue Issue Record.
|
||||
type BuglyIssue struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
IssueNo string `json:"issue_no" gorm:"column:issue_no"`
|
||||
Title string `json:"title" gorm:"column:title"`
|
||||
ExceptionMsg string `json:"exception_msg" gorm:"column:exception_msg"`
|
||||
KeyStack string `json:"key_stack" gorm:"column:key_stack"`
|
||||
Detail string `json:"detail" gorm:"column:detail"`
|
||||
Tags string `json:"tags" gorm:"column:tags"`
|
||||
LastTime time.Time `json:"last_time" gorm:"column:last_time"`
|
||||
HappenTimes int `json:"happen_times" gorm:"column:happen_times"`
|
||||
UserTimes int `json:"user_times" gorm:"column:user_times"`
|
||||
Version string `json:"version" gorm:"column:version"`
|
||||
ProjectID string `json:"project_id" gorm:"column:project_id"`
|
||||
IssueLink string `json:"issue_link" gorm:"column:issue_link"`
|
||||
TapdBugID string `json:"tapd_bug_id" gorm:"column:tapd_bug_id"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
||||
|
||||
// TapdProperty TapdProperty.
|
||||
type TapdProperty struct {
|
||||
Title string `json:"title" gorm:"column:title"`
|
||||
Description string `json:"description" gorm:"column:description"`
|
||||
CurrentOwner string `json:"current_owner" gorm:"column:current_owner"`
|
||||
Platform string `json:"platform" gorm:"column:platform"`
|
||||
Module string `json:"module" gorm:"column:module"`
|
||||
IterationID string `json:"iteration_id" gorm:"column:iteration_id"`
|
||||
ReleaseID string `json:"release_id" gorm:"column:release_id"`
|
||||
Priority string `json:"priority" gorm:"column:priority"`
|
||||
Severity string `json:"severity" gorm:"column:severity"`
|
||||
Source string `json:"source" gorm:"column:source"`
|
||||
CustomFieldFour string `json:"custom_field_four" gorm:"column:custom_field_four"`
|
||||
BugType string `json:"bugtype" gorm:"column:bugtype"`
|
||||
OriginPhase string `json:"originphase" gorm:"column:originphase"`
|
||||
CustomFieldThree string `json:"custom_field_three" gorm:"column:custom_field_three"`
|
||||
Reporter string `json:"reporter" gorm:"column:reporter"`
|
||||
Status string `json:"status" gorm:"column:status"`
|
||||
}
|
||||
|
||||
// TapdBugTemplate TapdBugTemplate.
|
||||
type TapdBugTemplate struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
WorkspaceID string `json:"workspace_id" gorm:"column:workspace_id"`
|
||||
BuglyProjectId int64 `json:"bugly_project_id" gorm:"column:bugly_project_id"`
|
||||
|
||||
TapdProperty
|
||||
|
||||
IssueFilterSQL string `json:"issue_filter_sql" gorm:"column:issue_filter_sql"`
|
||||
SeverityKey string `json:"severity_key" gorm:"column:severity_key"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
}
|
||||
|
||||
// TapdBugVersionTemplate TapdBugVersionTemplate.
|
||||
type TapdBugVersionTemplate struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
Version string `json:"version" gorm:"column:version"`
|
||||
ProjectTemplateID int64 `json:"project_template_id" gorm:"column:project_template_id"`
|
||||
|
||||
TapdProperty
|
||||
|
||||
IssueFilterSQL string `json:"issue_filter_sql" gorm:"column:issue_filter_sql"`
|
||||
SeverityKey string `json:"severity_key" gorm:"column:severity_key"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
}
|
||||
|
||||
// BuglyVersion Bugly Version Record.
|
||||
type BuglyVersion struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
Version string `json:"version" gorm:"column:version"`
|
||||
BuglyProjectID int64 `json:"bugly_project_id" gorm:"column:bugly_project_id"`
|
||||
Action int `json:"action" gorm:"column:action"`
|
||||
TaskStatus int `json:"task_status" gorm:"column:task_status"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
||||
|
||||
// BuglyBatchRun Bugly Batch Run.
|
||||
type BuglyBatchRun struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
BuglyVersionID int64 `json:"bugly_version_id" gorm:"column:bugly_version_id"`
|
||||
Version string `json:"version" gorm:"column:version"`
|
||||
BatchID string `json:"batch_id" gorm:"column:batch_id"`
|
||||
RetryCount int `json:"retry_count" gorm:"retry_times:retry_count"`
|
||||
Status int `json:"status" gorm:"column:status"`
|
||||
ErrorMsg string `json:"error_msg" gorm:"column:error_msg"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
EndTime time.Time `json:"end_time" gorm:"column:end_time"`
|
||||
}
|
||||
|
||||
// BuglyCookie Bugly Cookie.
|
||||
type BuglyCookie struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
QQAccount int `json:"qq_account" gorm:"column:qq_account"`
|
||||
Cookie string `json:"cookie" gorm:"column:cookie"`
|
||||
Token string `json:"token" gorm:"column:token"`
|
||||
UsageCount int `json:"usage_count" gorm:"column:usage_count"`
|
||||
Status int `json:"status" gorm:"column:status"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
||||
|
||||
// User User.
|
||||
type User struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
Name string `json:"username" gorm:"column:name"`
|
||||
EMail string `json:"email" gorm:"column:email"`
|
||||
VisibleBugly bool `json:"visible_bugly" gorm:"column:visible_bugly"`
|
||||
CTime time.Time `gorm:"column:ctime;default:current_timestamp"`
|
||||
UTime time.Time `gorm:"column:mtime;default:current_timestamp on update current_timestamp"`
|
||||
}
|
||||
|
||||
// TapdBugRecord Tapd Bug Insert Log.
|
||||
type TapdBugRecord struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
ProjectTemplateID int64 `json:"project_template_id" gorm:"column:project_template_id"`
|
||||
VersionTemplateID int64 `json:"version_template_id" gorm:"column:version_template_id"`
|
||||
Operator string `json:"operator" gorm:"column:operator"`
|
||||
Count int `json:"count" gorm:"column:count"`
|
||||
Status int `json:"status" gorm:"column:status"`
|
||||
IssueFilterSQL string `json:"issue_filter_sql" gorm:"column:issue_filter_sql"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
||||
|
||||
// ScheduleTask Schedule Task.
|
||||
type ScheduleTask struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
Name string `json:"username" gorm:"column:name"`
|
||||
Status int `json:"status" gorm:"column:status"`
|
||||
CTime time.Time `gorm:"column:ctime;default:current_timestamp"`
|
||||
MTime time.Time `gorm:"column:mtime;default:current_timestamp on update current_timestamp"`
|
||||
}
|
||||
|
||||
// TapdBugPriorityConf Tapd Bug Priority Conf.
|
||||
type TapdBugPriorityConf struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
ProjectTemplateID int64 `json:"project_template_id" gorm:"column:project_template_id"`
|
||||
Urgent int `json:"urgent" gorm:"column:urgent"`
|
||||
High int `json:"high" gorm:"column:high"`
|
||||
Medium int `json:"medium" gorm:"column:medium"`
|
||||
StartTime time.Time `json:"start_time" gorm:"column:start_time"`
|
||||
EndTime time.Time `json:"end_time" gorm:"column:end_time"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
Status int `json:"status" gorm:"column:status"`
|
||||
}
|
||||
|
||||
// ContactInfo Contact Info
|
||||
type ContactInfo struct {
|
||||
ID int64 `json:"id" gorm:"column:id"`
|
||||
UserName string `json:"username" gorm:"column:username"`
|
||||
UserID string `json:"user_id" gorm:"column:user_id"`
|
||||
NickName string `json:"nick_name" gorm:"column:nick_name"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
||||
|
||||
// BuglyProject Bugly Project.
|
||||
type BuglyProject struct {
|
||||
ID int64 `json:"id" gorm:"auto_increment;primary_key;column:id"`
|
||||
ProjectID string `json:"project_id" gorm:"column:project_id"`
|
||||
ProjectName string `json:"project_name" gorm:"column:project_name"`
|
||||
PlatformID string `json:"platform_id" gorm:"column:platform_id"`
|
||||
UpdateBy string `json:"update_by" gorm:"column:update_by"`
|
||||
ExceptionType string `json:"exception_type" gorm:"column:exception_type"`
|
||||
CTime time.Time `json:"ctime" gorm:"column:ctime"`
|
||||
MTime time.Time `json:"mtime" gorm:"column:mtime"`
|
||||
}
|
182
app/admin/ep/marthe/model/tapd.go
Normal file
182
app/admin/ep/marthe/model/tapd.go
Normal file
@ -0,0 +1,182 @@
|
||||
package model
|
||||
|
||||
// ReleaseResponse Release Response
|
||||
type ReleaseResponse struct {
|
||||
Status int `json:"status"`
|
||||
Data *ReleaseWrapper `json:"data"`
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
// ReleaseWrapper Release Wrapper
|
||||
type ReleaseWrapper struct {
|
||||
Release *Release `json:"Release"`
|
||||
}
|
||||
|
||||
// WorkspaceUserResponse Workspace User Response
|
||||
type WorkspaceUserResponse struct {
|
||||
Status int `json:"status"`
|
||||
Data []*WorkspaceUserWrapper `json:"data"`
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
// WorkspaceUserWrapper Workspace User Wrapper
|
||||
type WorkspaceUserWrapper struct {
|
||||
UserWrapper *UserWrapper `json:"UserWorkspace"`
|
||||
}
|
||||
|
||||
// UserWrapper User Wrapper
|
||||
type UserWrapper struct {
|
||||
User string `json:"user"`
|
||||
}
|
||||
|
||||
// Release Release
|
||||
type Release struct {
|
||||
ID string `json:"id"`
|
||||
WorkSpaceID string `json:"workspace_id"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
StartDate string `json:"startdate"`
|
||||
EndDate string `json:"enddate"`
|
||||
Creator string `json:"creator"`
|
||||
Created string `json:"created"`
|
||||
Modified string `json:"modified"`
|
||||
Status string `json:"status"`
|
||||
}
|
||||
|
||||
// BugResponse Bug Response
|
||||
type BugResponse struct {
|
||||
Status int `json:"status"`
|
||||
Data []*BugWrapper `json:"data"`
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
// BugSingleResponse Bug Response
|
||||
type BugSingleResponse struct {
|
||||
Status int `json:"status"`
|
||||
Data *BugWrapper `json:"data"`
|
||||
Info string `json:"info"`
|
||||
}
|
||||
|
||||
// BugWrapper Bug Wrapper
|
||||
type BugWrapper struct {
|
||||
Bug *Bug `json:"Bug"`
|
||||
}
|
||||
|
||||
// Bug Bug
|
||||
type Bug struct {
|
||||
ID string `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Description string `json:"description"`
|
||||
Priority string `json:"priority"`
|
||||
Severity string `json:"severity"`
|
||||
Module string `json:"module"`
|
||||
Status string `json:"status"`
|
||||
Reporter string `json:"reporter"`
|
||||
Deadline string `json:"deadline"`
|
||||
Created string `json:"created"`
|
||||
BugType string `json:"bugtype"`
|
||||
Resolved string `json:"resolved"`
|
||||
Closed string `json:"closed"`
|
||||
Modified string `json:"modified"`
|
||||
LastModify string `json:"lastmodify"`
|
||||
Auditer string `json:"auditer"`
|
||||
DE string `json:"de"`
|
||||
VersionTest string `json:"version_test"`
|
||||
VersionReport string `json:"version_report"`
|
||||
VersionClose string `json:"version_close"`
|
||||
VersionFix string `json:"version_fix"`
|
||||
BaselineFind string `json:"baseline_find"`
|
||||
BaselineJoin string `json:"baseline_join"`
|
||||
BaselineClose string `json:"baseline_close"`
|
||||
BaselineTest string `json:"baseline_test"`
|
||||
SourcePhase string `json:"sourcephase"`
|
||||
TE string `json:"te"`
|
||||
CurrentOwner string `json:"current_owner"`
|
||||
IterationID string `json:"iteration_id"`
|
||||
Resolution string `json:"resolution"`
|
||||
Source string `json:"source"`
|
||||
OriginPhase string `json:"originphase"`
|
||||
Confirmer string `json:"confirmer"`
|
||||
Milestone string `json:"milestone"`
|
||||
Participator string `json:"participator"`
|
||||
Closer string `json:"closer"`
|
||||
Platform string `json:"platform"`
|
||||
OS string `json:"os"`
|
||||
TestType string `json:"testtype"`
|
||||
TestPhase string `json:"testphase"`
|
||||
Frequency string `json:"frequency"`
|
||||
CC string `json:"cc"`
|
||||
RegressionNumber string `json:"regression_number"`
|
||||
Flows string `json:"flows"`
|
||||
Feature string `json:"feature"`
|
||||
TestMode string `json:"testmode"`
|
||||
Estimate string `json:"estimate"`
|
||||
IssueID string `json:"issue_id"`
|
||||
CreatedFrom string `json:"created_from"`
|
||||
InProgressTime string `json:"in_progress_time"`
|
||||
VerifyTime string `json:"verify_time"`
|
||||
RejectTime string `json:"reject_time"`
|
||||
ReopenTime string `json:"reopen_time"`
|
||||
AuditTime string `json:"audit_time"`
|
||||
SuspendTime string `json:"suspend_time"`
|
||||
Due string `json:"due"`
|
||||
Begin string `json:"begin"`
|
||||
ReleaseID string `json:"release_id"`
|
||||
WorkspaceID string `json:"workspace_id"`
|
||||
CustomFieldOne string `json:"custom_field_one"`
|
||||
CustomFieldTwo string `json:"custom_field_two"`
|
||||
CustomFieldThree string `json:"custom_field_three"`
|
||||
CustomFieldFour string `json:"custom_field_four"`
|
||||
CustomFieldFive string `json:"custom_field_five"`
|
||||
CustomField6 string `json:"custom_field_6"`
|
||||
CustomField7 string `json:"custom_field_7"`
|
||||
CustomField8 string `json:"custom_field_8"`
|
||||
CustomField9 string `json:"custom_field_9"`
|
||||
CustomField10 string `json:"custom_field_10"`
|
||||
CustomField11 string `json:"custom_field_11"`
|
||||
CustomField12 string `json:"custom_field_12"`
|
||||
CustomField13 string `json:"custom_field_13"`
|
||||
CustomField14 string `json:"custom_field_14"`
|
||||
CustomField15 string `json:"custom_field_15"`
|
||||
CustomField16 string `json:"custom_field_16"`
|
||||
CustomField17 string `json:"custom_field_17"`
|
||||
CustomField18 string `json:"custom_field_18"`
|
||||
CustomField19 string `json:"custom_field_19"`
|
||||
CustomField20 string `json:"custom_field_20"`
|
||||
CustomField21 string `json:"custom_field_21"`
|
||||
CustomField22 string `json:"custom_field_22"`
|
||||
CustomField23 string `json:"custom_field_23"`
|
||||
CustomField24 string `json:"custom_field_24"`
|
||||
CustomField25 string `json:"custom_field_25"`
|
||||
CustomField26 string `json:"custom_field_26"`
|
||||
CustomField27 string `json:"custom_field_27"`
|
||||
CustomField28 string `json:"custom_field_28"`
|
||||
CustomField29 string `json:"custom_field_29"`
|
||||
CustomField30 string `json:"custom_field_30"`
|
||||
CustomField31 string `json:"custom_field_31"`
|
||||
CustomField32 string `json:"custom_field_32"`
|
||||
CustomField33 string `json:"custom_field_33"`
|
||||
CustomField34 string `json:"custom_field_34"`
|
||||
CustomField35 string `json:"custom_field_35"`
|
||||
CustomField36 string `json:"custom_field_36"`
|
||||
CustomField37 string `json:"custom_field_37"`
|
||||
CustomField38 string `json:"custom_field_38"`
|
||||
CustomField39 string `json:"custom_field_39"`
|
||||
CustomField40 string `json:"custom_field_40"`
|
||||
CustomField41 string `json:"custom_field_41"`
|
||||
CustomField42 string `json:"custom_field_42"`
|
||||
CustomField43 string `json:"custom_field_43"`
|
||||
CustomField44 string `json:"custom_field_44"`
|
||||
CustomField45 string `json:"custom_field_45"`
|
||||
CustomField46 string `json:"custom_field_46"`
|
||||
CustomField47 string `json:"custom_field_47"`
|
||||
CustomField48 string `json:"custom_field_48"`
|
||||
CustomField49 string `json:"custom_field_49"`
|
||||
CustomField50 string `json:"custom_field_50"`
|
||||
}
|
||||
|
||||
// UpdateBug Update Bug
|
||||
type UpdateBug struct {
|
||||
*Bug
|
||||
CurrentUser string `json:"current_user"`
|
||||
}
|
8
app/admin/ep/marthe/model/wechat.go
Normal file
8
app/admin/ep/marthe/model/wechat.go
Normal file
@ -0,0 +1,8 @@
|
||||
package model
|
||||
|
||||
// WechatContact Wechat Contact
|
||||
type WechatContact struct {
|
||||
EnglishName string `json:"english_name"`
|
||||
UserID string `json:"userid"`
|
||||
Name string `json:"name"`
|
||||
}
|
43
app/admin/ep/marthe/server/http/BUILD
Normal file
43
app/admin/ep/marthe/server/http/BUILD
Normal file
@ -0,0 +1,43 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bugly.go",
|
||||
"http.go",
|
||||
"tapd.go",
|
||||
"user.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/marthe/server/http",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/marthe/conf:go_default_library",
|
||||
"//app/admin/ep/marthe/model:go_default_library",
|
||||
"//app/admin/ep/marthe/service:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/net/http/blademaster:go_default_library",
|
||||
"//library/net/http/blademaster/binding:go_default_library",
|
||||
"//library/net/http/blademaster/middleware/permit:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
218
app/admin/ep/marthe/server/http/bugly.go
Normal file
218
app/admin/ep/marthe/server/http/bugly.go
Normal file
@ -0,0 +1,218 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
// bugly version
|
||||
func updateVersion(c *bm.Context) {
|
||||
var (
|
||||
req = &model.AddVersionRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateBuglyVersion(c, username, req))
|
||||
}
|
||||
|
||||
func getVersionAndProjectList(c *bm.Context) {
|
||||
c.JSON(srv.BuglyVersionAndProjectList(c))
|
||||
}
|
||||
|
||||
func queryVersions(c *bm.Context) {
|
||||
var (
|
||||
req = &model.QueryBuglyVersionRequest{}
|
||||
err error
|
||||
)
|
||||
|
||||
if err = req.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryBuglyVersions(c, req))
|
||||
}
|
||||
|
||||
func runVersions(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.RunVersions(v.ID))
|
||||
}
|
||||
|
||||
// bugly cookie
|
||||
func updateCookie(c *bm.Context) {
|
||||
var (
|
||||
req = &model.AddCookieRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateCookie(c, username, req))
|
||||
}
|
||||
|
||||
func queryCookies(c *bm.Context) {
|
||||
var (
|
||||
req = &model.QueryBuglyCookiesRequest{}
|
||||
err error
|
||||
)
|
||||
|
||||
if err = req.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryCookies(c, req))
|
||||
}
|
||||
|
||||
func updateCookieStatus(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
Status int `form:"status"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, srv.UpdateCookieStatus(c, v.ID, v.Status))
|
||||
}
|
||||
|
||||
// bugly issue
|
||||
func queryBuglyIssue(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryBuglyIssueRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryBuglyIssueRecords(c, v))
|
||||
}
|
||||
|
||||
func queryBatchRun(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryBuglyBatchRunsRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryBatchRuns(c, v))
|
||||
}
|
||||
|
||||
// bugly project
|
||||
func updateProject(c *bm.Context) {
|
||||
var (
|
||||
req = &model.AddProjectRequest{}
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateBuglyProject(c, username, req))
|
||||
}
|
||||
|
||||
func queryProjects(c *bm.Context) {
|
||||
var (
|
||||
req = &model.QueryBuglyProjectRequest{}
|
||||
err error
|
||||
)
|
||||
|
||||
if err = req.Verify(); err != nil {
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
|
||||
if err = c.BindWith(req, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryBuglyProjects(c, req))
|
||||
}
|
||||
|
||||
func queryProjectVersions(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(srv.QueryBuglyProjectVersions(c, v.ID))
|
||||
}
|
||||
|
||||
func queryProject(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(srv.QueryBuglyProject(c, v.ID))
|
||||
}
|
||||
|
||||
func queryAllProjects(c *bm.Context) {
|
||||
c.JSON(srv.QueryAllBuglyProjects(c))
|
||||
}
|
||||
|
||||
//test
|
||||
func test(c *bm.Context) {
|
||||
srv.BatchRunTask(model.TaskBatchRunUpdateBugInTapd, srv.BatchRunUpdateBugInTapd)
|
||||
c.JSON(nil, nil)
|
||||
|
||||
}
|
122
app/admin/ep/marthe/server/http/http.go
Normal file
122
app/admin/ep/marthe/server/http/http.go
Normal file
@ -0,0 +1,122 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"go-common/app/admin/ep/marthe/conf"
|
||||
"go-common/app/admin/ep/marthe/service"
|
||||
"go-common/library/log"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/middleware/permit"
|
||||
)
|
||||
|
||||
var (
|
||||
srv *service.Service
|
||||
authSvc *permit.Permit
|
||||
)
|
||||
|
||||
// Init Init.
|
||||
func Init(c *conf.Config, s *service.Service) {
|
||||
srv = s
|
||||
authSvc = permit.New(c.Auth)
|
||||
engine := bm.DefaultServer(c.BM)
|
||||
engine.Ping(ping)
|
||||
outerRouter(engine)
|
||||
if err := engine.Start(); err != nil {
|
||||
log.Error("engine.Start error(%v)", err)
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
func outerRouter(e *bm.Engine) {
|
||||
base := e.Group("/ep/admin/marthe/v1", authSvc.Permit(""))
|
||||
{
|
||||
base.GET("/version", getVersion)
|
||||
|
||||
bugly := base.Group("/bugly")
|
||||
{
|
||||
|
||||
bugly.GET("/test", test)
|
||||
|
||||
project := bugly.Group("/project") //done test
|
||||
{
|
||||
project.GET("", queryProject) //done test
|
||||
project.POST("/update", accessToBugly, updateProject) //done test
|
||||
project.POST("/query", queryProjects) //done test
|
||||
project.GET("/all", queryAllProjects) //done test
|
||||
|
||||
project.GET("/versions", queryProjectVersions) // done test
|
||||
}
|
||||
|
||||
version := bugly.Group("/version") //done test
|
||||
{
|
||||
version.GET("/run", accessToBugly, runVersions) //done test
|
||||
|
||||
version.POST("/update", accessToBugly, updateVersion) //done test
|
||||
version.POST("/query", queryVersions) //done test
|
||||
version.GET("/list", getVersionAndProjectList) // done test
|
||||
version.POST("/batch/query", queryBatchRun)
|
||||
}
|
||||
|
||||
cookie := bugly.Group("/cookie")
|
||||
{
|
||||
cookie.POST("/add", updateCookie) // done test
|
||||
cookie.POST("/update", updateCookie) // done test
|
||||
cookie.POST("/query", queryCookies) // done test
|
||||
cookie.GET("/status/update", updateCookieStatus) //done test
|
||||
}
|
||||
|
||||
issue := bugly.Group("/issue")
|
||||
{
|
||||
issue.POST("/query", queryBuglyIssue) // done test
|
||||
}
|
||||
}
|
||||
|
||||
tapd := base.Group("/tapd")
|
||||
{
|
||||
bug := tapd.Group("/bug")
|
||||
{
|
||||
bug.GET("/project/insert", bugInsertTapdWithProject) // done test access
|
||||
bug.GET("/version/insert", bugInsertTapdWithVersion) // done test access
|
||||
bug.POST("/filtersql/check", checkFilterSql) // done test
|
||||
bug.POST("/record/query", queryBugRecord) // done test
|
||||
|
||||
bug.POST("/template/update", updateTapdBugTpl) // done test access
|
||||
bug.POST("/template/query", queryTapdBugTpl) // done test
|
||||
bug.GET("/template/all", queryAllTapdBugTpl) // done test
|
||||
|
||||
bug.POST("/version/template/update", updateTapdBugVersionTpl) //done test access
|
||||
bug.POST("/version/template/query", queryTapdBugVersionTpl) //done test
|
||||
|
||||
bug.POST("/conf/priority/update", updateTapdBugPriorityConf) //done test
|
||||
bug.POST("/conf/priority/query", queryTapdBugPriorityConf) //done test
|
||||
|
||||
bug.GET("/conf/auth/check", checkAuth)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
user := base.Group("/user")
|
||||
{
|
||||
user.GET("/query", queryUserInfo) // done test
|
||||
user.GET("/wechat/contact/sync", syncWechatContact) // done test
|
||||
user.GET("/visible/bugly", updateVisibleBugly) // done test
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func ping(c *bm.Context) {
|
||||
if err := srv.Ping(c); err != nil {
|
||||
log.Error("ping error(%v)", err)
|
||||
c.AbortWithStatus(http.StatusServiceUnavailable)
|
||||
}
|
||||
}
|
||||
|
||||
func getVersion(c *bm.Context) {
|
||||
v := new(struct {
|
||||
Version string `json:"version"`
|
||||
})
|
||||
v.Version = "v.0.0.0.3"
|
||||
log.Info("marthe current version [%s]", v.Version)
|
||||
c.JSON(v, nil)
|
||||
}
|
187
app/admin/ep/marthe/server/http/tapd.go
Normal file
187
app/admin/ep/marthe/server/http/tapd.go
Normal file
@ -0,0 +1,187 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
"go-common/library/net/http/blademaster/binding"
|
||||
)
|
||||
|
||||
func updateTapdBugTpl(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.UpdateTapdBugTplRequest{}
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateTapdBugTpl(c, username, v))
|
||||
}
|
||||
|
||||
func queryTapdBugTpl(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryTapdBugTemplateRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryTapdBugTpl(c, v))
|
||||
}
|
||||
|
||||
func queryAllTapdBugTpl(c *bm.Context) {
|
||||
c.JSON(srv.QueryAllTapdBugTpl(c))
|
||||
}
|
||||
|
||||
func updateTapdBugVersionTpl(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.UpdateTapdBugVersionTplRequest{}
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateTapdBugVersionTpl(c, username, v))
|
||||
}
|
||||
|
||||
func queryTapdBugVersionTpl(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryTapdBugVersionTemplateRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryTapdBugVersionTpl(c, v))
|
||||
}
|
||||
|
||||
func checkFilterSql(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = new(struct {
|
||||
SQL string `json:"issue_filter_sql"`
|
||||
})
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.CheckTapdBugTplSQL(c, v.SQL))
|
||||
}
|
||||
|
||||
func bugInsertTapdWithProject(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.BugInsertTapdWithProject(c, v.ID, username))
|
||||
}
|
||||
|
||||
func bugInsertTapdWithVersion(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
ID int64 `form:"id"`
|
||||
})
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(srv.BugInsertTapdWithVersion(c, v.ID, username))
|
||||
}
|
||||
|
||||
func queryBugRecord(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryBugRecordsRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryBugRecords(c, v))
|
||||
}
|
||||
|
||||
func updateTapdBugPriorityConf(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.UpdateTapdBugPriorityConfRequest{}
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.UpdateTapdBugPriorityConf(c, username, v))
|
||||
}
|
||||
|
||||
func queryTapdBugPriorityConf(c *bm.Context) {
|
||||
var (
|
||||
err error
|
||||
v = &model.QueryTapdBugPriorityConfsRequest{}
|
||||
)
|
||||
|
||||
if err = c.BindWith(v, binding.JSON); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryTapdBugPriorityConfsRequest(c, v))
|
||||
}
|
||||
|
||||
func checkAuth(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
Username string `form:"username"`
|
||||
WorkspaceID string `form:"workspace_id"`
|
||||
})
|
||||
err error
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.HttpAccessToWorkspace(c, v.WorkspaceID, v.Username))
|
||||
}
|
74
app/admin/ep/marthe/server/http/user.go
Normal file
74
app/admin/ep/marthe/server/http/user.go
Normal file
@ -0,0 +1,74 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"go-common/library/ecode"
|
||||
bm "go-common/library/net/http/blademaster"
|
||||
)
|
||||
|
||||
const (
|
||||
_sessUnKey = "username"
|
||||
)
|
||||
|
||||
func queryUserInfo(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
c.JSON(srv.QueryUserInfo(c, username))
|
||||
|
||||
}
|
||||
|
||||
func syncWechatContact(c *bm.Context) {
|
||||
c.JSON(nil, srv.HttpSyncWechatContacts(c))
|
||||
}
|
||||
|
||||
func updateVisibleBugly(c *bm.Context) {
|
||||
var (
|
||||
v = new(struct {
|
||||
UpdateUsername string `form:"username"`
|
||||
VisibleBugly bool `form:"visible_bugly"`
|
||||
})
|
||||
err error
|
||||
username string
|
||||
)
|
||||
|
||||
if err = c.Bind(v); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
c.JSON(nil, srv.UpdateUserVisibleBugly(c, username, v.UpdateUsername, v.VisibleBugly))
|
||||
}
|
||||
|
||||
func accessToBugly(c *bm.Context) {
|
||||
var (
|
||||
username string
|
||||
err error
|
||||
)
|
||||
if username, err = getUsername(c); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !srv.AccessToBugly(c, username) {
|
||||
c.JSON(nil, ecode.AccessDenied)
|
||||
c.Abort()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func getUsername(c *bm.Context) (username string, err error) {
|
||||
user, exist := c.Get(_sessUnKey)
|
||||
if !exist {
|
||||
err = ecode.AccessKeyErr
|
||||
c.JSON(nil, err)
|
||||
return
|
||||
}
|
||||
username = user.(string)
|
||||
return
|
||||
}
|
46
app/admin/ep/marthe/service/BUILD
Normal file
46
app/admin/ep/marthe/service/BUILD
Normal file
@ -0,0 +1,46 @@
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"bugly.go",
|
||||
"bugly_batch_run.go",
|
||||
"mail.go",
|
||||
"service.go",
|
||||
"tapd.go",
|
||||
"user.go",
|
||||
],
|
||||
importpath = "go-common/app/admin/ep/marthe/service",
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//app/admin/ep/marthe/conf:go_default_library",
|
||||
"//app/admin/ep/marthe/dao:go_default_library",
|
||||
"//app/admin/ep/marthe/model:go_default_library",
|
||||
"//library/ecode:go_default_library",
|
||||
"//library/log:go_default_library",
|
||||
"//library/sync/pipeline/fanout:go_default_library",
|
||||
"//vendor/github.com/robfig/cron:go_default_library",
|
||||
"//vendor/github.com/satori/go.uuid:go_default_library",
|
||||
"//vendor/gopkg.in/gomail.v2:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
386
app/admin/ep/marthe/service/bugly.go
Normal file
386
app/admin/ep/marthe/service/bugly.go
Normal file
@ -0,0 +1,386 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
)
|
||||
|
||||
// UpdateBuglyVersion update Bugly Version.
|
||||
func (s *Service) UpdateBuglyVersion(c context.Context, username string, req *model.AddVersionRequest) (rep map[string]interface{}, err error) {
|
||||
var (
|
||||
bugVersionID int64
|
||||
buglyProject *model.BuglyProject
|
||||
)
|
||||
|
||||
// check project
|
||||
if buglyProject, err = s.dao.QueryBuglyProject(req.BuglyProjectID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyProject.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
if req.ID > 0 {
|
||||
// update
|
||||
var tmpVersion *model.BuglyVersion
|
||||
|
||||
if tmpVersion, err = s.dao.QueryBuglyVersion(req.ID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tmpVersion.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
tmpVersion.BuglyProjectID = req.BuglyProjectID
|
||||
tmpVersion.Version = req.Version
|
||||
tmpVersion.Action = req.Action
|
||||
|
||||
if err = s.dao.UpdateBuglyVersion(tmpVersion); err != nil {
|
||||
return
|
||||
}
|
||||
bugVersionID = tmpVersion.ID
|
||||
|
||||
} else {
|
||||
// add
|
||||
var tmpVersion *model.BuglyVersion
|
||||
|
||||
//check name
|
||||
if tmpVersion, err = s.dao.QueryBuglyVersionByVersion(req.Version); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tmpVersion.ID > 0 {
|
||||
err = ecode.MartheDuplicateErr
|
||||
return
|
||||
}
|
||||
|
||||
buglyVersion := &model.BuglyVersion{
|
||||
ID: req.ID,
|
||||
Version: req.Version,
|
||||
BuglyProjectID: req.BuglyProjectID,
|
||||
Action: req.Action,
|
||||
TaskStatus: model.BuglyVersionTaskStatusReady,
|
||||
UpdateBy: username,
|
||||
}
|
||||
|
||||
if err = s.dao.InsertBuglyVersion(buglyVersion); err != nil {
|
||||
return
|
||||
}
|
||||
bugVersionID = buglyVersion.ID
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["bug_version_id"] = bugVersionID
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyVersions Query Bugly Versions.
|
||||
func (s *Service) QueryBuglyVersions(c context.Context, req *model.QueryBuglyVersionRequest) (rep *model.PaginateBuglyProjectVersions, err error) {
|
||||
var (
|
||||
total int64
|
||||
buglyProjectVersions []*model.BuglyProjectVersion
|
||||
)
|
||||
if total, buglyProjectVersions, err = s.dao.FindBuglyProjectVersions(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBuglyProjectVersions{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
BuglyProjectVersions: buglyProjectVersions,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BuglyVersionAndProjectList Bugly Version and project List.
|
||||
func (s *Service) BuglyVersionAndProjectList(c context.Context) (rep map[string]interface{}, err error) {
|
||||
var (
|
||||
versionList []string
|
||||
projectList []string
|
||||
)
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
|
||||
if versionList, err = s.dao.QueryBuglyVersionList(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if projectList, err = s.dao.QueryBuglyProjectList(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rep["versions"] = versionList
|
||||
|
||||
rep["projects"] = projectList
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCookie update Cookie.
|
||||
func (s *Service) UpdateCookie(c context.Context, username string, req *model.AddCookieRequest) (rep map[string]interface{}, err error) {
|
||||
var cookieID int64
|
||||
|
||||
if req.ID > 0 {
|
||||
buglyCookie := &model.BuglyCookie{
|
||||
ID: req.ID,
|
||||
QQAccount: req.QQAccount,
|
||||
Cookie: req.Cookie,
|
||||
Token: req.Token,
|
||||
Status: req.Status,
|
||||
UpdateBy: username,
|
||||
}
|
||||
if err = s.dao.UpdateCookie(buglyCookie); err != nil {
|
||||
return
|
||||
}
|
||||
cookieID = req.ID
|
||||
} else {
|
||||
buglyCookie := &model.BuglyCookie{
|
||||
QQAccount: req.QQAccount,
|
||||
Cookie: req.Cookie,
|
||||
Token: req.Token,
|
||||
Status: req.Status,
|
||||
UpdateBy: username,
|
||||
}
|
||||
if err = s.dao.InsertCookie(buglyCookie); err != nil {
|
||||
return
|
||||
}
|
||||
cookieID = buglyCookie.ID
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["cookie_id"] = cookieID
|
||||
return
|
||||
}
|
||||
|
||||
// QueryCookies Add Cookie.
|
||||
func (s *Service) QueryCookies(c context.Context, req *model.QueryBuglyCookiesRequest) (rep *model.PaginateBuglyCookies, err error) {
|
||||
var (
|
||||
total int64
|
||||
buglyCookies []*model.BuglyCookie
|
||||
)
|
||||
if total, buglyCookies, err = s.dao.FindCookies(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBuglyCookies{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
BuglyCookies: buglyCookies,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateCookieStatus Update Cookie Status.
|
||||
func (s *Service) UpdateCookieStatus(c context.Context, cookieID int64, status int) (err error) {
|
||||
err = s.dao.UpdateCookieStatus(cookieID, status)
|
||||
return
|
||||
}
|
||||
|
||||
// GetEnableCookie Get Enable Cookie.
|
||||
func (s *Service) GetEnableCookie() (buglyCookie *model.BuglyCookie, err error) {
|
||||
var buglyCookies []*model.BuglyCookie
|
||||
|
||||
if buglyCookies, err = s.dao.QueryCookieByStatus(model.BuglyCookieStatusEnable); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
/*for _, ele := range buglyCookies {
|
||||
if ele.UsageCount < s.c.Bugly.CookieUsageUpper {
|
||||
buglyCookie = ele
|
||||
err = s.dao.UpdateCookieUsageCount(buglyCookie.ID, buglyCookie.UsageCount+1)
|
||||
return
|
||||
}
|
||||
}*/
|
||||
|
||||
if len(buglyCookies) > 0 {
|
||||
buglyCookie = buglyCookies[0]
|
||||
err = s.dao.UpdateCookieUsageCount(buglyCookie.ID, buglyCookie.UsageCount+1)
|
||||
return
|
||||
}
|
||||
|
||||
//not found enable cookie
|
||||
s.DoWhenNoEnableCookie()
|
||||
err = ecode.MartheNoCookie
|
||||
return
|
||||
}
|
||||
|
||||
// DisableCookie Disable Cookie.
|
||||
func (s *Service) DisableCookie(c context.Context, cookieID int64) (err error) {
|
||||
err = s.dao.UpdateCookieStatus(cookieID, model.BuglyCookieStatusDisable)
|
||||
return
|
||||
}
|
||||
|
||||
// DoWhenNoEnableCookie Do When No Enable Cookie.
|
||||
func (s *Service) DoWhenNoEnableCookie() {
|
||||
// todo notice
|
||||
s.SendMail(s.c.Mail.NoticeOwner, "marthe has no enable cookie", "")
|
||||
}
|
||||
|
||||
// QueryBuglyIssueRecords Query Bugly Issue Records
|
||||
func (s *Service) QueryBuglyIssueRecords(c context.Context, req *model.QueryBuglyIssueRequest) (rep *model.PaginateBuglyIssues, err error) {
|
||||
var (
|
||||
total int64
|
||||
buglyIssues []*model.BuglyIssue
|
||||
)
|
||||
if total, buglyIssues, err = s.dao.FindBuglyIssues(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBuglyIssues{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
BuglyIssues: buglyIssues,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// QueryBatchRuns Query Batch Runs
|
||||
func (s *Service) QueryBatchRuns(c context.Context, req *model.QueryBuglyBatchRunsRequest) (rep *model.PaginateBuglyBatchRuns, err error) {
|
||||
var (
|
||||
total int64
|
||||
buglyBatchRuns []*model.BuglyBatchRun
|
||||
)
|
||||
if total, buglyBatchRuns, err = s.dao.FindBuglyBatchRuns(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBuglyBatchRuns{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
BuglyBatchRuns: buglyBatchRuns,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateBuglyProject update bugly project.
|
||||
func (s *Service) UpdateBuglyProject(c context.Context, username string, req *model.AddProjectRequest) (rep map[string]interface{}, err error) {
|
||||
var buglyProjectID int64
|
||||
|
||||
if req.ID > 0 {
|
||||
buglyProject := &model.BuglyProject{
|
||||
ID: req.ID,
|
||||
ProjectID: req.ProjectID,
|
||||
//ProjectName: req.ProjectName,
|
||||
PlatformID: req.PlatformID,
|
||||
ExceptionType: req.ExceptionType,
|
||||
UpdateBy: username,
|
||||
}
|
||||
if err = s.dao.UpdateBuglyProject(buglyProject); err != nil {
|
||||
return
|
||||
}
|
||||
buglyProjectID = req.ID
|
||||
} else {
|
||||
var buglyProjectInDB *model.BuglyProject
|
||||
if buglyProjectInDB, err = s.dao.QueryBuglyProjectByName(req.ProjectName); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyProjectInDB.ID > 0 {
|
||||
err = ecode.MartheDuplicateErr
|
||||
return
|
||||
}
|
||||
|
||||
buglyProject := &model.BuglyProject{
|
||||
ProjectID: req.ProjectID,
|
||||
ProjectName: req.ProjectName,
|
||||
PlatformID: req.PlatformID,
|
||||
ExceptionType: req.ExceptionType,
|
||||
UpdateBy: username,
|
||||
}
|
||||
if err = s.dao.InsertBuglyProject(buglyProject); err != nil {
|
||||
return
|
||||
}
|
||||
buglyProjectID = buglyProject.ID
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["bugly_project_id"] = buglyProjectID
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyProjects Query Bugly Project.
|
||||
func (s *Service) QueryBuglyProjects(c context.Context, req *model.QueryBuglyProjectRequest) (rep *model.PaginateBuglyProjects, err error) {
|
||||
var (
|
||||
total int64
|
||||
buglyProjects []*model.BuglyProject
|
||||
)
|
||||
if total, buglyProjects, err = s.dao.FindBuglyProjects(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBuglyProjects{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
BuglyProjects: buglyProjects,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBuglyProject Query Bugly Project.
|
||||
func (s *Service) QueryBuglyProject(c context.Context, id int64) (buglyProject *model.BuglyProject, err error) {
|
||||
return s.dao.QueryBuglyProject(id)
|
||||
}
|
||||
|
||||
// QueryAllBuglyProjects Query All Bugly Projects.
|
||||
func (s *Service) QueryAllBuglyProjects(c context.Context) (buglyProjects []*model.BuglyProject, err error) {
|
||||
return s.dao.QueryAllBuglyProjects()
|
||||
}
|
||||
|
||||
// QueryBuglyProjectVersions Query Bugly Project Versions.
|
||||
func (s *Service) QueryBuglyProjectVersions(c context.Context, buglyProjectID int64) (rep map[string]interface{}, err error) {
|
||||
var (
|
||||
buglyProject *model.BuglyProject
|
||||
buglyCookie *model.BuglyCookie
|
||||
buglyVersions []*model.BugVersion
|
||||
versions []string
|
||||
)
|
||||
|
||||
defer func() {
|
||||
if err != nil && err == ecode.MartheCookieExpired {
|
||||
s.DisableCookie(c, buglyCookie.ID)
|
||||
}
|
||||
}()
|
||||
|
||||
if buglyProject, err = s.dao.QueryBuglyProject(buglyProjectID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyProject.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
//get enable cookie
|
||||
if buglyCookie, err = s.GetEnableCookie(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyVersions, err = s.dao.BuglyVersion(c, buglyCookie, buglyProject.ProjectID, buglyProject.PlatformID); err != nil || buglyVersions == nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyVersion := range buglyVersions {
|
||||
versions = append(versions, buglyVersion.Name)
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["versions"] = versions
|
||||
return
|
||||
}
|
358
app/admin/ep/marthe/service/bugly_batch_run.go
Normal file
358
app/admin/ep/marthe/service/bugly_batch_run.go
Normal file
@ -0,0 +1,358 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
|
||||
"github.com/satori/go.uuid"
|
||||
)
|
||||
|
||||
// RunVersions Run Versions.
|
||||
func (s *Service) RunVersions(buglyVersionID int64) (rep map[string]interface{}, err error) {
|
||||
lock := s.getBatchRunLock(buglyVersionID)
|
||||
lock.Lock()
|
||||
defer lock.Unlock()
|
||||
|
||||
var (
|
||||
buglyRunVersions []*model.BuglyVersion
|
||||
uid string
|
||||
isEnableRun bool
|
||||
)
|
||||
|
||||
// 获取可以跑的版本号list
|
||||
if buglyRunVersions, err = s.GetBatchRunVersions(); err != nil {
|
||||
log.Error("GetBatchRunVersions err(%v) ", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyRunVersion := range buglyRunVersions {
|
||||
if buglyRunVersion.ID == buglyVersionID {
|
||||
isEnableRun = true
|
||||
uid = uuid.NewV4().String()
|
||||
|
||||
// 插入batchrun表
|
||||
buglyBatchRun := &model.BuglyBatchRun{
|
||||
BuglyVersionID: buglyRunVersion.ID,
|
||||
Version: buglyRunVersion.Version,
|
||||
BatchID: uid,
|
||||
Status: model.BuglyBatchRunStatusRunning,
|
||||
}
|
||||
|
||||
if err = s.dao.InsertBuglyBatchRun(buglyBatchRun); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.batchRunCache.Do(context.Background(), func(ctx context.Context) {
|
||||
if err = s.runPerVersion(uid, buglyRunVersion); err != nil {
|
||||
log.Error("runPerVersion uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// batch run 并且更新batch run表
|
||||
batchStatus := model.BuglyBatchRunStatusDone
|
||||
errMsg := ""
|
||||
endTime := time.Now()
|
||||
|
||||
if err != nil {
|
||||
batchStatus = model.BuglyBatchRunStatusFailed
|
||||
errMsg = err.Error()
|
||||
}
|
||||
|
||||
updateBuglyBatchRun := &model.BuglyBatchRun{
|
||||
ID: buglyBatchRun.ID,
|
||||
Status: batchStatus,
|
||||
ErrorMsg: errMsg,
|
||||
EndTime: endTime,
|
||||
}
|
||||
|
||||
if err = s.dao.UpdateBuglyBatchRun(updateBuglyBatchRun); err != nil {
|
||||
log.Error("runPerVersion UpdateBuglyBatchRun uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
|
||||
}
|
||||
}()
|
||||
})
|
||||
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["uid"] = uid
|
||||
rep["enable_to_run"] = isEnableRun
|
||||
|
||||
if !isEnableRun {
|
||||
err = ecode.MartheTaskInRunning
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// BatchRunVersions Batch Run Versions
|
||||
func (s *Service) BatchRunVersions() (err error) {
|
||||
var (
|
||||
buglyRunVersions []*model.BuglyVersion
|
||||
uid = uuid.NewV4().String()
|
||||
)
|
||||
|
||||
// 获取可以跑的版本号list
|
||||
if buglyRunVersions, err = s.dao.FindEnableAndReadyVersions(); err != nil {
|
||||
log.Error("GetBatchRunVersions err(%v) ", err)
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyRunVersion := range buglyRunVersions {
|
||||
if _, err = s.RunVersions(buglyRunVersion.ID); err != nil {
|
||||
log.Error("runPerVersion uid(%s) version(%s) err(%v) ", uid, buglyRunVersion.Version, err)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) runPerVersion(uid string, buglyRunVersion *model.BuglyVersion) (err error) {
|
||||
var (
|
||||
buglyRet *model.BugRet
|
||||
buglyCookie *model.BuglyCookie
|
||||
requestPageCnt int
|
||||
c = context.Background()
|
||||
lastRunTime time.Time
|
||||
buglyBatchRun *model.BuglyBatchRun
|
||||
buglyProject *model.BuglyProject
|
||||
)
|
||||
|
||||
log.Info("start run version: [%s] batchId: [%s]", buglyRunVersion.Version, uid)
|
||||
|
||||
if buglyProject, err = s.dao.QueryBuglyProject(buglyRunVersion.BuglyProjectID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyProject.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
//get issue total count
|
||||
bugIssueRequest := &model.BugIssueRequest{
|
||||
ProjectID: buglyProject.ProjectID,
|
||||
PlatformID: buglyProject.PlatformID,
|
||||
Version: buglyRunVersion.Version,
|
||||
ExceptionType: buglyProject.ExceptionType,
|
||||
StartNum: 0,
|
||||
Rows: 1,
|
||||
}
|
||||
|
||||
//get last run time
|
||||
if buglyBatchRun, err = s.dao.QueryLastSuccessBatchRunByVersion(buglyRunVersion.Version); err != nil {
|
||||
return
|
||||
}
|
||||
if buglyBatchRun.ID > 0 {
|
||||
lastRunTime = buglyBatchRun.CTime
|
||||
} else {
|
||||
loc, _ := time.LoadLocation("Local")
|
||||
if lastRunTime, err = time.ParseInLocation(model.TimeLayout, model.TimeLayout, loc); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//get enable cookie
|
||||
if buglyCookie, err = s.GetEnableCookie(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if cookie, update cookie as expired
|
||||
defer func() {
|
||||
if err != nil && err == ecode.MartheCookieExpired {
|
||||
s.DisableCookie(c, buglyCookie.ID)
|
||||
}
|
||||
}()
|
||||
|
||||
if buglyRet, err = s.dao.BuglyIssueAndRetry(c, buglyCookie, bugIssueRequest); err != nil || len(buglyRet.BugIssues) < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
//获取issue count 和 page 上限
|
||||
requestPageCnt = int(buglyRet.NumFound/s.c.Bugly.IssuePageSize) + 1
|
||||
requestPageCntMax := s.c.Bugly.IssueCountUpper / s.c.Bugly.IssuePageSize
|
||||
if requestPageCnt > requestPageCntMax {
|
||||
requestPageCnt = requestPageCntMax
|
||||
}
|
||||
|
||||
// update or add issue
|
||||
for i := 0; i < requestPageCnt; i++ {
|
||||
innerBreak := false
|
||||
|
||||
bugIssueRequest.StartNum = s.c.Bugly.IssuePageSize * i
|
||||
bugIssueRequest.Rows = s.c.Bugly.IssuePageSize
|
||||
|
||||
var ret *model.BugRet
|
||||
if ret, err = s.dao.BuglyIssueAndRetry(c, buglyCookie, bugIssueRequest); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
loc, _ := time.LoadLocation("Local")
|
||||
issueLink := "/v2/crash-reporting/errors/%s/%s/report?pid=%s&searchType=detail&version=%s&start=0&date=all"
|
||||
for _, issueDto := range ret.BugIssues {
|
||||
var (
|
||||
issueTime time.Time
|
||||
bugIssueDetail *model.BugIssueDetail
|
||||
tagStr string
|
||||
bugDetail = "no detail"
|
||||
)
|
||||
|
||||
tmpTime := []rune(issueDto.LastTime)
|
||||
issueTime, _ = time.ParseInLocation(model.TimeLayout, string(tmpTime[:len(tmpTime)-4]), loc)
|
||||
|
||||
//issue时间早于库里面最新时间的,跳出
|
||||
if issueTime.Before(lastRunTime) {
|
||||
innerBreak = true
|
||||
break
|
||||
}
|
||||
|
||||
var tmpBuglyIssue *model.BuglyIssue
|
||||
|
||||
if tmpBuglyIssue, err = s.dao.GetBuglyIssue(issueDto.IssueID, issueDto.Version); err != nil {
|
||||
log.Error("d.GetSaveIssues url(%s) err(%v)", "GetSaveIssues", err)
|
||||
continue
|
||||
}
|
||||
|
||||
for _, bugTag := range issueDto.Tags {
|
||||
tagStr = tagStr + bugTag.TagName + ","
|
||||
}
|
||||
|
||||
if tmpBuglyIssue.ID != 0 {
|
||||
//update
|
||||
issueRecord := &model.BuglyIssue{
|
||||
IssueNo: issueDto.IssueID,
|
||||
Title: issueDto.Title,
|
||||
LastTime: issueTime,
|
||||
HappenTimes: issueDto.Count,
|
||||
UserTimes: issueDto.UserCount,
|
||||
Version: issueDto.Version,
|
||||
Tags: tagStr,
|
||||
}
|
||||
s.dao.UpdateBuglyIssue(issueRecord)
|
||||
} else {
|
||||
//create
|
||||
if bugIssueDetail, err = s.dao.BuglyIssueDetailAndRetry(c, buglyCookie, buglyProject.ProjectID, buglyProject.PlatformID, issueDto.IssueID); err == nil {
|
||||
bugDetail = bugIssueDetail.CallStack
|
||||
}
|
||||
|
||||
issueURL := s.c.Bugly.Host + fmt.Sprintf(issueLink, buglyProject.ProjectID, issueDto.IssueID, buglyProject.PlatformID, buglyRunVersion.Version)
|
||||
issueRecord := &model.BuglyIssue{
|
||||
IssueNo: issueDto.IssueID,
|
||||
Title: issueDto.Title,
|
||||
LastTime: issueTime,
|
||||
HappenTimes: issueDto.Count,
|
||||
UserTimes: issueDto.UserCount,
|
||||
Version: issueDto.Version,
|
||||
Tags: tagStr,
|
||||
Detail: bugDetail,
|
||||
ExceptionMsg: issueDto.ExceptionMsg,
|
||||
KeyStack: issueDto.KeyStack,
|
||||
IssueLink: issueURL,
|
||||
ProjectID: buglyProject.ProjectID,
|
||||
}
|
||||
s.dao.InsertBuglyIssue(issueRecord)
|
||||
}
|
||||
}
|
||||
|
||||
if innerBreak {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
log.Info("end run version: [%s] batchId: [%s]", buglyRunVersion.Version, uid)
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// GetBatchRunVersions Get Batch Run Versions.
|
||||
func (s *Service) GetBatchRunVersions() (buglyRunVersions []*model.BuglyVersion, err error) {
|
||||
var (
|
||||
buglyVersions []*model.BuglyVersion
|
||||
buglyBatchRuns []*model.BuglyBatchRun
|
||||
)
|
||||
if buglyVersions, err = s.dao.FindEnableAndReadyVersions(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if buglyBatchRuns, err = s.dao.QueryBuglyBatchRunsByStatus(model.BuglyBatchRunStatusRunning); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 排除正在执行的版本
|
||||
for _, buglyVersion := range buglyVersions {
|
||||
var isVersionRun bool
|
||||
for _, buglyBatchRun := range buglyBatchRuns {
|
||||
if buglyBatchRun.Version == buglyVersion.Version {
|
||||
isVersionRun = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !isVersionRun {
|
||||
buglyRunVersions = append(buglyRunVersions, buglyVersion)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DisableBatchRunOverTime Disable Batch Run OverTime.
|
||||
func (s *Service) DisableBatchRunOverTime() (err error) {
|
||||
var (
|
||||
buglyBatchRuns []*model.BuglyBatchRun
|
||||
tapdBugRecords []*model.TapdBugRecord
|
||||
timeNow = time.Now()
|
||||
)
|
||||
|
||||
//清 未完成 disable batch run
|
||||
if buglyBatchRuns, err = s.dao.QueryBuglyBatchRunsByStatus(model.BuglyBatchRunStatusRunning); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyBatchRun := range buglyBatchRuns {
|
||||
if timeNow.Sub(buglyBatchRun.CTime).Hours() > float64(s.c.Scheduler.BatchRunOverHourTime) {
|
||||
updateBuglyBatchRun := &model.BuglyBatchRun{
|
||||
ID: buglyBatchRun.ID,
|
||||
Status: model.BuglyBatchRunStatusFailed,
|
||||
ErrorMsg: "over time",
|
||||
EndTime: timeNow,
|
||||
}
|
||||
|
||||
if err = s.dao.UpdateBuglyBatchRun(updateBuglyBatchRun); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 清 未完成 disable insert tapd bug
|
||||
if tapdBugRecords, err = s.dao.QueryTapdBugRecordByStatus(model.InsertBugStatusRunning); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tapdBugRecord := range tapdBugRecords {
|
||||
if timeNow.Sub(tapdBugRecord.CTime).Hours() > float64(s.c.Scheduler.BatchRunOverHourTime) {
|
||||
tapdBugRecord.Status = model.InsertBugStatusFailed
|
||||
if err = s.dao.UpdateTapdBugRecord(tapdBugRecord); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) getBatchRunLock(buglyVersionId int64) (batchRunLock *sync.Mutex) {
|
||||
s.syncBatchRunLock.Lock()
|
||||
defer s.syncBatchRunLock.Unlock()
|
||||
|
||||
var ok bool
|
||||
if batchRunLock, ok = s.mapBatchRunLocks[buglyVersionId]; !ok {
|
||||
batchRunLock = new(sync.Mutex)
|
||||
s.mapBatchRunLocks[buglyVersionId] = batchRunLock
|
||||
}
|
||||
return
|
||||
}
|
12
app/admin/ep/marthe/service/mail.go
Normal file
12
app/admin/ep/marthe/service/mail.go
Normal file
@ -0,0 +1,12 @@
|
||||
package service
|
||||
|
||||
import "gopkg.in/gomail.v2"
|
||||
|
||||
// SendMail Send Mail.
|
||||
func (s *Service) SendMail(receiver []string, header, body string) {
|
||||
m := gomail.NewMessage()
|
||||
m.SetHeader("To", receiver...)
|
||||
m.SetHeader("Subject", header)
|
||||
m.SetBody("text/html", body)
|
||||
s.dao.SendMail(m)
|
||||
}
|
106
app/admin/ep/marthe/service/service.go
Normal file
106
app/admin/ep/marthe/service/service.go
Normal file
@ -0,0 +1,106 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"go-common/app/admin/ep/marthe/conf"
|
||||
"go-common/app/admin/ep/marthe/dao"
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/sync/pipeline/fanout"
|
||||
|
||||
"github.com/robfig/cron"
|
||||
)
|
||||
|
||||
// Service struct
|
||||
type Service struct {
|
||||
c *conf.Config
|
||||
dao *dao.Dao
|
||||
batchRunCache *fanout.Fanout
|
||||
tapdBugCache *fanout.Fanout
|
||||
taskCache *fanout.Fanout
|
||||
cron *cron.Cron
|
||||
syncWechatContactsLock sync.Mutex
|
||||
|
||||
syncTapdBugInsertLock sync.Mutex
|
||||
mapTapdBugInsertLocks map[int64]*sync.Mutex
|
||||
|
||||
syncBatchRunLock sync.Mutex
|
||||
mapBatchRunLocks map[int64]*sync.Mutex
|
||||
}
|
||||
|
||||
// New init
|
||||
func New(c *conf.Config) (s *Service) {
|
||||
s = &Service{
|
||||
c: c,
|
||||
dao: dao.New(c),
|
||||
batchRunCache: fanout.New("batchRunCache", fanout.Worker(5), fanout.Buffer(10240)),
|
||||
tapdBugCache: fanout.New("tapdBugCache", fanout.Worker(5), fanout.Buffer(10240)),
|
||||
taskCache: fanout.New("taskCache", fanout.Worker(5), fanout.Buffer(10240)),
|
||||
mapTapdBugInsertLocks: make(map[int64]*sync.Mutex),
|
||||
mapBatchRunLocks: make(map[int64]*sync.Mutex),
|
||||
}
|
||||
|
||||
if c.Scheduler.Active {
|
||||
s.cron = cron.New()
|
||||
|
||||
// 定时批量 跑enable version 抓bugly数据
|
||||
if err := s.cron.AddFunc(c.Scheduler.BatchRunEnableVersion, func() { s.BatchRunTask(model.TaskBatchRunVersions, s.BatchRunVersions) }); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 定时把超过三小时为执行完毕的任务修改为失败
|
||||
if err := s.cron.AddFunc(c.Scheduler.DisableBatchRunOverTime, func() { s.BatchRunTask(model.TaskDisableBatchRunOverTime, s.DisableBatchRunOverTime) }); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 定时更新tapd bug
|
||||
if err := s.cron.AddFunc(c.Scheduler.BatchRunUpdateTapdBug, func() { s.BatchRunTask(model.TaskBatchRunUpdateBugInTapd, s.BatchRunUpdateBugInTapd) }); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 定时更新SyncWechatContact
|
||||
if err := s.cron.AddFunc(c.Scheduler.SyncWechatContact, func() { s.BatchRunTask(model.TaskSyncWechatContact, s.SyncWechatContacts) }); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
s.cron.Start()
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
// Ping Service
|
||||
func (s *Service) Ping(c context.Context) (err error) {
|
||||
return s.dao.Ping(c)
|
||||
}
|
||||
|
||||
// Close Service
|
||||
func (s *Service) Close() {
|
||||
s.dao.Close()
|
||||
}
|
||||
|
||||
// BatchRunTask Batch Run Task.
|
||||
func (s *Service) BatchRunTask(taskName string, task func() error) {
|
||||
var err error
|
||||
scheduleTask := &model.ScheduleTask{
|
||||
Name: taskName,
|
||||
Status: model.TaskStatusRunning,
|
||||
}
|
||||
if err = s.dao.InsertScheduleTask(scheduleTask); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = task()
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
scheduleTask.Status = model.TaskStatusFailed
|
||||
} else {
|
||||
scheduleTask.Status = model.TaskStatusDone
|
||||
}
|
||||
|
||||
if err = s.dao.UpdateScheduleTask(scheduleTask); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
}
|
764
app/admin/ep/marthe/service/tapd.go
Normal file
764
app/admin/ep/marthe/service/tapd.go
Normal file
@ -0,0 +1,764 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
"go-common/library/log"
|
||||
)
|
||||
|
||||
// UpdateTapdBugTpl Update Tapd Bug Tpl.
|
||||
func (s *Service) UpdateTapdBugTpl(c context.Context, username string, req *model.UpdateTapdBugTplRequest) (rep map[string]interface{}, err error) {
|
||||
//check if access to workspace
|
||||
if !s.AccessToWorkspace(req.WorkspaceID, username) {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
|
||||
//check sql
|
||||
if _, err = s.CheckTapdBugTplSQL(c, req.IssueFilterSQL); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
tapdBugTemplate := &model.TapdBugTemplate{
|
||||
ID: req.ID,
|
||||
WorkspaceID: req.WorkspaceID,
|
||||
BuglyProjectId: req.BuglyProjectId,
|
||||
IssueFilterSQL: req.IssueFilterSQL,
|
||||
SeverityKey: req.SeverityKey,
|
||||
UpdateBy: username,
|
||||
|
||||
TapdProperty: req.TapdProperty,
|
||||
}
|
||||
|
||||
if req.ID > 0 {
|
||||
err = s.dao.UpdateTapdBugTemplate(tapdBugTemplate)
|
||||
} else {
|
||||
// add new
|
||||
err = s.dao.InsertTapdBugTemplate(tapdBugTemplate)
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["template_id"] = tapdBugTemplate.ID
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTapdBugTpl Query Tapd Bug Tpl
|
||||
func (s *Service) QueryTapdBugTpl(c context.Context, req *model.QueryTapdBugTemplateRequest) (rep *model.PaginateTapdBugTemplates, err error) {
|
||||
var (
|
||||
total int64
|
||||
tapdBugTemplates []*model.TapdBugTemplate
|
||||
tapdBugTemplateWithProjectNames []*model.TapdBugTemplateWithProjectName
|
||||
)
|
||||
if total, tapdBugTemplates, err = s.dao.FindTapdBugTemplates(req); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tapdBugTemplate := range tapdBugTemplates {
|
||||
var buglyProject *model.BuglyProject
|
||||
if buglyProject, err = s.dao.QueryBuglyProject(tapdBugTemplate.BuglyProjectId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if req.ProjectName == "" || strings.Contains(buglyProject.ProjectName, req.ProjectName) {
|
||||
tapdBugTemplateWithProjectName := &model.TapdBugTemplateWithProjectName{
|
||||
TapdBugTemplate: tapdBugTemplate,
|
||||
ProjectName: buglyProject.ProjectName,
|
||||
}
|
||||
tapdBugTemplateWithProjectNames = append(tapdBugTemplateWithProjectNames, tapdBugTemplateWithProjectName)
|
||||
}
|
||||
}
|
||||
|
||||
rep = &model.PaginateTapdBugTemplates{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
TapdBugTemplateWithProjectNames: tapdBugTemplateWithProjectNames,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// QueryAllTapdBugTpl Query All Tapd Bug Tpl
|
||||
func (s *Service) QueryAllTapdBugTpl(c context.Context) (rep []*model.TapdBugTemplateShortResponse, err error) {
|
||||
var tapdBugTemplates []*model.TapdBugTemplate
|
||||
|
||||
if tapdBugTemplates, err = s.dao.QueryAllTapdBugTemplates(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tapdBugTemplate := range tapdBugTemplates {
|
||||
var buglyProject *model.BuglyProject
|
||||
if buglyProject, err = s.dao.QueryBuglyProject(tapdBugTemplate.BuglyProjectId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
ret := &model.TapdBugTemplateShortResponse{
|
||||
ID: tapdBugTemplate.ID,
|
||||
WorkspaceID: tapdBugTemplate.WorkspaceID,
|
||||
BuglyProjectId: tapdBugTemplate.BuglyProjectId,
|
||||
BuglyProjectName: buglyProject.ProjectName,
|
||||
}
|
||||
rep = append(rep, ret)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateTapdBugVersionTpl Update Tapd Bug Version Tpl.
|
||||
func (s *Service) UpdateTapdBugVersionTpl(c context.Context, username string, req *model.UpdateTapdBugVersionTplRequest) (rep map[string]interface{}, err error) {
|
||||
|
||||
// check sql
|
||||
if req.IssueFilterSQL != "" {
|
||||
if _, err = s.CheckTapdBugTplSQL(c, req.IssueFilterSQL); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
//check project id
|
||||
var tmp *model.TapdBugTemplate
|
||||
|
||||
if tmp, err = s.dao.QueryTapdBugTemplate(req.ProjectTemplateID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tmp.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
//check if access to workspace
|
||||
if !s.AccessToWorkspace(tmp.WorkspaceID, username) {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
|
||||
tapdBugVersionTemplate := &model.TapdBugVersionTemplate{
|
||||
ID: req.ID,
|
||||
Version: req.Version,
|
||||
ProjectTemplateID: req.ProjectTemplateID,
|
||||
|
||||
IssueFilterSQL: req.IssueFilterSQL,
|
||||
SeverityKey: req.SeverityKey,
|
||||
UpdateBy: username,
|
||||
|
||||
TapdProperty: req.TapdProperty,
|
||||
}
|
||||
|
||||
if req.ID > 0 {
|
||||
err = s.dao.UpdateTapdBugVersionTemplate(tapdBugVersionTemplate)
|
||||
} else {
|
||||
// add new
|
||||
err = s.dao.InsertTapdBugVersionTemplate(tapdBugVersionTemplate)
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["version_template_id"] = tapdBugVersionTemplate.ID
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTapdBugVersionTpl Query Tapd Bug Version Tpl
|
||||
func (s *Service) QueryTapdBugVersionTpl(c context.Context, req *model.QueryTapdBugVersionTemplateRequest) (rep *model.PaginateTapdBugVersionTemplates, err error) {
|
||||
var (
|
||||
total int64
|
||||
tapdBugVersionTemplates []*model.TapdBugVersionTemplate
|
||||
)
|
||||
if total, tapdBugVersionTemplates, err = s.dao.FindTapdBugVersionTemplates(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateTapdBugVersionTemplates{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
TapdBugVersionTemplates: tapdBugVersionTemplates,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// CheckTapdBugTplSQL Check Tapd Bug Tpl SQL.
|
||||
func (s *Service) CheckTapdBugTplSQL(c context.Context, sql string) (rep map[string]interface{}, err error) {
|
||||
var buglyIssues []*model.BuglyIssue
|
||||
if buglyIssues, err = s.getBuglyIssuesByFilterSQLWithNoTapdBug(sql); err != nil {
|
||||
err = ecode.MartheFilterSqlError
|
||||
return
|
||||
}
|
||||
rep = make(map[string]interface{})
|
||||
rep["count"] = len(buglyIssues)
|
||||
return
|
||||
}
|
||||
|
||||
// BugInsertTapdWithProject Bug Insert Tapd With Project.
|
||||
func (s *Service) BugInsertTapdWithProject(c context.Context, id int64, username string) (rep map[string]interface{}, err error) {
|
||||
var count int
|
||||
count, err = s.bugInsertTapd(id, 0, username)
|
||||
rep = make(map[string]interface{})
|
||||
rep["tapd_bug_count"] = count
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// BugInsertTapdWithVersion Bug Insert Tapd With Version.
|
||||
func (s *Service) BugInsertTapdWithVersion(c context.Context, id int64, username string) (rep map[string]interface{}, err error) {
|
||||
var count int
|
||||
count, err = s.bugInsertTapd(0, id, username)
|
||||
rep = make(map[string]interface{})
|
||||
rep["tapd_bug_count"] = count
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) bugInsertTapd(projectTemplateId, versionTemplateId int64, username string) (count int, err error) {
|
||||
|
||||
var (
|
||||
tapdBugTemplate *model.TapdBugTemplate
|
||||
tapdBugVersionTemplate *model.TapdBugVersionTemplate
|
||||
buglyIssues []*model.BuglyIssue
|
||||
tapdBugRecords []*model.TapdBugRecord
|
||||
)
|
||||
|
||||
if (projectTemplateId == 0 && versionTemplateId == 0) || (projectTemplateId > 0 && versionTemplateId > 0) {
|
||||
return
|
||||
}
|
||||
|
||||
if projectTemplateId > 0 {
|
||||
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(projectTemplateId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tapdBugTemplate.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
} else if versionTemplateId > 0 {
|
||||
if tapdBugVersionTemplate, err = s.dao.QueryTapdBugVersionTemplate(versionTemplateId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tapdBugVersionTemplate.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
projectTemplateId = tapdBugVersionTemplate.ProjectTemplateID
|
||||
|
||||
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(projectTemplateId); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tapdBugTemplate.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
if err = s.UpdateTplAsVersionTpl(tapdBugVersionTemplate, tapdBugTemplate); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// get map lock, every project tpl 串行
|
||||
insertLock := s.getTapdBugInsertLock(projectTemplateId)
|
||||
insertLock.Lock()
|
||||
defer insertLock.Unlock()
|
||||
|
||||
//check if access to workspace
|
||||
if !s.AccessToWorkspace(tapdBugTemplate.WorkspaceID, username) {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
|
||||
if tapdBugRecords, err = s.dao.QueryTapdBugRecordByProjectIDAndStatus(projectTemplateId, model.InsertBugStatusRunning); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(tapdBugRecords) > 0 {
|
||||
err = ecode.MartheTaskInRunning
|
||||
return
|
||||
}
|
||||
|
||||
if buglyIssues, err = s.getBuglyIssuesByFilterSQLWithNoTapdBug(tapdBugTemplate.IssueFilterSQL); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
count = len(buglyIssues)
|
||||
|
||||
if count > 0 {
|
||||
tapdBugInsertLog := &model.TapdBugRecord{
|
||||
ProjectTemplateID: projectTemplateId,
|
||||
VersionTemplateID: versionTemplateId,
|
||||
Operator: username,
|
||||
Count: count,
|
||||
IssueFilterSQL: tapdBugTemplate.IssueFilterSQL,
|
||||
Status: model.InsertBugStatusRunning,
|
||||
}
|
||||
|
||||
if err = s.dao.InsertTapdBugRecord(tapdBugInsertLog); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
s.tapdBugCache.Do(context.TODO(), func(ctx context.Context) {
|
||||
|
||||
defer func() {
|
||||
if err != nil {
|
||||
tapdBugInsertLog.Status = model.InsertBugStatusFailed
|
||||
} else {
|
||||
tapdBugInsertLog.Status = model.InsertBugStatusDone
|
||||
}
|
||||
err = s.dao.UpdateTapdBugRecord(tapdBugInsertLog)
|
||||
}()
|
||||
|
||||
for _, buglyIssue := range buglyIssues {
|
||||
var (
|
||||
bug *model.Bug
|
||||
bugID string
|
||||
)
|
||||
|
||||
if bug, err = s.getBugModel(buglyIssue, tapdBugTemplate); err != nil {
|
||||
log.Error("getLiveIOSBugModel error (%v)", err)
|
||||
continue
|
||||
}
|
||||
|
||||
if bugID, err = s.dao.CreateBug(bug); err != nil && bugID == "" {
|
||||
log.Error("CreateBug error (%v)", err)
|
||||
continue
|
||||
}
|
||||
log.Info("insert issue no: [%s], bug number [%s]", buglyIssue.IssueNo, bugID)
|
||||
|
||||
if err = s.dao.UpdateBuglyIssueTapdBugID(buglyIssue.ID, bugID); err != nil {
|
||||
log.Error("UpdateIssueRecordTapdBugID error (%v)", err)
|
||||
continue
|
||||
}
|
||||
|
||||
buglyIssue.TapdBugID = bugID
|
||||
|
||||
if err = s.updateBugInTapd(tapdBugTemplate, buglyIssue, time.Now()); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
log.Info("update issue no [%s], bug number [%s]", buglyIssue.IssueNo, buglyIssue.TapdBugID)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) getBugModel(bugIssue *model.BuglyIssue, bugTemplate *model.TapdBugTemplate) (bug *model.Bug, err error) {
|
||||
title := fmt.Sprintf(bugTemplate.Title, bugIssue.IssueNo, bugIssue.Version, bugIssue.Title, strconv.Itoa(bugIssue.HappenTimes), strconv.Itoa(bugIssue.UserTimes))
|
||||
description := fmt.Sprintf(bugTemplate.Description, title, bugIssue.KeyStack,
|
||||
bugIssue.IssueLink, bugIssue.IssueLink, bugIssue.IssueLink,
|
||||
bugIssue.Detail)
|
||||
|
||||
bug = &model.Bug{
|
||||
Title: title,
|
||||
Description: description,
|
||||
Priority: bugTemplate.Priority,
|
||||
Severity: bugTemplate.Severity,
|
||||
Module: bugTemplate.Module,
|
||||
Status: bugTemplate.Status,
|
||||
Reporter: bugTemplate.Reporter,
|
||||
BugType: bugTemplate.BugType,
|
||||
CurrentOwner: bugTemplate.CurrentOwner,
|
||||
Source: bugTemplate.Source,
|
||||
OriginPhase: bugTemplate.OriginPhase,
|
||||
Platform: bugTemplate.Platform,
|
||||
ReleaseID: bugTemplate.ReleaseID,
|
||||
CustomFieldThree: bugTemplate.CustomFieldThree,
|
||||
CustomFieldFour: bugTemplate.CustomFieldFour,
|
||||
WorkspaceID: bugTemplate.WorkspaceID,
|
||||
IterationID: bugTemplate.IterationID,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateTplAsVersionTpl Update Tpl As Version Tpl.
|
||||
func (s *Service) UpdateTplAsVersionTpl(tapdBugVersionTemplate *model.TapdBugVersionTemplate, tapdBugTemplate *model.TapdBugTemplate) (err error) {
|
||||
|
||||
if tapdBugVersionTemplate.ProjectTemplateID != tapdBugTemplate.ID {
|
||||
log.Error("projectID should be [%s],actual [%s]", tapdBugVersionTemplate.ProjectTemplateID, tapdBugTemplate.ID)
|
||||
return
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Title) != "" {
|
||||
tapdBugTemplate.Title = tapdBugVersionTemplate.Title
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Description) != "" {
|
||||
tapdBugTemplate.Description = tapdBugVersionTemplate.Description
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.CurrentOwner) != "" {
|
||||
tapdBugTemplate.CurrentOwner = tapdBugVersionTemplate.CurrentOwner
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Platform) != "" {
|
||||
tapdBugTemplate.Platform = tapdBugVersionTemplate.Platform
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Module) != "" {
|
||||
tapdBugTemplate.Module = tapdBugVersionTemplate.Module
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.IterationID) != "" {
|
||||
tapdBugTemplate.IterationID = tapdBugVersionTemplate.IterationID
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.ReleaseID) != "" {
|
||||
tapdBugTemplate.ReleaseID = tapdBugVersionTemplate.ReleaseID
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Priority) != "" {
|
||||
tapdBugTemplate.Priority = tapdBugVersionTemplate.Priority
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Severity) != "" {
|
||||
tapdBugTemplate.Severity = tapdBugVersionTemplate.Severity
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Source) != "" {
|
||||
tapdBugTemplate.Source = tapdBugVersionTemplate.Source
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.CustomFieldFour) != "" {
|
||||
tapdBugTemplate.CustomFieldFour = tapdBugVersionTemplate.CustomFieldFour
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.BugType) != "" {
|
||||
tapdBugTemplate.BugType = tapdBugVersionTemplate.BugType
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.OriginPhase) != "" {
|
||||
tapdBugTemplate.OriginPhase = tapdBugVersionTemplate.OriginPhase
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.CustomFieldThree) != "" {
|
||||
tapdBugTemplate.CustomFieldThree = tapdBugVersionTemplate.CustomFieldThree
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Reporter) != "" {
|
||||
tapdBugTemplate.Reporter = tapdBugVersionTemplate.Reporter
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.Status) != "" {
|
||||
tapdBugTemplate.Status = tapdBugVersionTemplate.Status
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.IssueFilterSQL) != "" {
|
||||
tapdBugTemplate.IssueFilterSQL = tapdBugVersionTemplate.IssueFilterSQL
|
||||
}
|
||||
|
||||
if strings.TrimSpace(tapdBugVersionTemplate.SeverityKey) != "" {
|
||||
tapdBugTemplate.SeverityKey = tapdBugVersionTemplate.SeverityKey
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// BatchRunUpdateBugInTapd Batch Run Update Bug In Tapd.
|
||||
func (s *Service) BatchRunUpdateBugInTapd() (err error) {
|
||||
var buglyIssues []*model.BuglyIssue
|
||||
if buglyIssues, err = s.dao.GetBuglyIssuesHasInTapd(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyIssue := range buglyIssues {
|
||||
var (
|
||||
tapdBugTemplate *model.TapdBugTemplate
|
||||
tapdBugVersionTemplate *model.TapdBugVersionTemplate
|
||||
)
|
||||
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplateByProjectID(buglyIssue.ProjectID); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if tapdBugTemplate.ID == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
if tapdBugVersionTemplate, err = s.dao.QueryTapdBugVersionTemplateByVersion(buglyIssue.Version); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
if tapdBugVersionTemplate.ID > 0 {
|
||||
if err = s.UpdateTplAsVersionTpl(tapdBugVersionTemplate, tapdBugTemplate); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
err = s.updateBugInTapd(tapdBugTemplate, buglyIssue, time.Now())
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) updateBugInTapd(tapdBugTemplate *model.TapdBugTemplate, bugIssue *model.BuglyIssue, timeNow time.Time) (err error) {
|
||||
var bug *model.Bug
|
||||
|
||||
// update title
|
||||
title := fmt.Sprintf(tapdBugTemplate.Title, bugIssue.IssueNo, bugIssue.Version, bugIssue.Title, strconv.Itoa(bugIssue.HappenTimes), strconv.Itoa(bugIssue.UserTimes))
|
||||
|
||||
if bug, err = s.dao.BugPre(tapdBugTemplate.WorkspaceID, bugIssue.TapdBugID); err != nil {
|
||||
log.Error("BugPre projectId %s, error (%v)", bugIssue.ProjectID, err)
|
||||
return
|
||||
}
|
||||
|
||||
bug.Title = title
|
||||
|
||||
// update priority
|
||||
var (
|
||||
tapdBugPriorityConfs []*model.TapdBugPriorityConf
|
||||
)
|
||||
if tapdBugPriorityConfs, err = s.dao.QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus(tapdBugTemplate.ID, model.TapdBugPriorityConfEnable); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tmpTapdBugPriorityConf := range tapdBugPriorityConfs {
|
||||
if timeNow.After(tmpTapdBugPriorityConf.StartTime) && timeNow.Before(tmpTapdBugPriorityConf.EndTime) {
|
||||
if bugIssue.UserTimes >= tmpTapdBugPriorityConf.Urgent || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.Urgent {
|
||||
bug.Priority = "urgent"
|
||||
} else if bugIssue.UserTimes >= tmpTapdBugPriorityConf.High || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.High {
|
||||
bug.Priority = "high"
|
||||
} else if bugIssue.UserTimes >= tmpTapdBugPriorityConf.Medium || bugIssue.HappenTimes >= tmpTapdBugPriorityConf.Medium {
|
||||
bug.Priority = "medium"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// update serious
|
||||
if strings.TrimSpace(tapdBugTemplate.SeverityKey) != "" {
|
||||
keys := strings.Split(tapdBugTemplate.SeverityKey, ",")
|
||||
for _, key := range keys {
|
||||
if strings.Contains(bug.Description, key) {
|
||||
bug.Severity = "serious"
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
updateBug := &model.UpdateBug{
|
||||
Bug: bug,
|
||||
CurrentUser: bug.CurrentOwner,
|
||||
}
|
||||
|
||||
if err := s.dao.UpdateBug(updateBug); err != nil {
|
||||
log.Error("UpdateBug bugid %s, error (%v)", bug.ID, err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// QueryBugRecords Query Bug Records
|
||||
func (s *Service) QueryBugRecords(c context.Context, req *model.QueryBugRecordsRequest) (rep *model.PaginateBugRecords, err error) {
|
||||
var (
|
||||
total int64
|
||||
tapdBugRecords []*model.TapdBugRecord
|
||||
)
|
||||
if total, tapdBugRecords, err = s.dao.FindBugRecords(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateBugRecords{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
TapdBugRecords: tapdBugRecords,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// QueryTapdBugPriorityConfsRequest Query Tapd Bug Priority Confs Request
|
||||
func (s *Service) QueryTapdBugPriorityConfsRequest(c context.Context, req *model.QueryTapdBugPriorityConfsRequest) (rep *model.PaginateTapdBugPriorityConfs, err error) {
|
||||
var (
|
||||
total int64
|
||||
tapdBugPriorityConfs []*model.TapdBugPriorityConf
|
||||
)
|
||||
if total, tapdBugPriorityConfs, err = s.dao.FindTapdBugPriorityConfs(req); err != nil {
|
||||
return
|
||||
}
|
||||
rep = &model.PaginateTapdBugPriorityConfs{
|
||||
PaginationRep: model.PaginationRep{
|
||||
Total: total,
|
||||
PageSize: req.PageSize,
|
||||
PageNum: req.PageNum,
|
||||
},
|
||||
TapdBugPriorityConfs: tapdBugPriorityConfs,
|
||||
}
|
||||
return
|
||||
|
||||
}
|
||||
|
||||
// UpdateTapdBugPriorityConf Update Tapd Bug Priority Conf.
|
||||
func (s *Service) UpdateTapdBugPriorityConf(c context.Context, username string, req *model.UpdateTapdBugPriorityConfRequest) (rep map[string]interface{}, err error) {
|
||||
var (
|
||||
startTime time.Time
|
||||
endTime time.Time
|
||||
tapdBugPriorityConfsInDB []*model.TapdBugPriorityConf
|
||||
tapdBugTemplate *model.TapdBugTemplate
|
||||
)
|
||||
|
||||
//check project id
|
||||
if tapdBugTemplate, err = s.dao.QueryTapdBugTemplate(req.ProjectTemplateID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if tapdBugTemplate.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
//check if access to workspace
|
||||
if !s.AccessToWorkspace(tapdBugTemplate.WorkspaceID, username) {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
|
||||
if startTime, err = time.ParseInLocation(model.TimeLayout, req.StartTime, time.Local); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if endTime, err = time.ParseInLocation(model.TimeLayout, req.EndTime, time.Local); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// when status == enable, check time if conflict
|
||||
if req.Status == model.TapdBugPriorityConfEnable {
|
||||
if tapdBugPriorityConfsInDB, err = s.dao.QueryTapdBugPriorityConfsByProjectTemplateIdAndStatus(req.ProjectTemplateID, model.TapdBugPriorityConfEnable); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, tapdBugPriorityConfInDB := range tapdBugPriorityConfsInDB {
|
||||
isStartTimeInDuration := tapdBugPriorityConfInDB.StartTime.After(startTime) && tapdBugPriorityConfInDB.StartTime.Before(endTime)
|
||||
isEndTimeInDuration := tapdBugPriorityConfInDB.EndTime.After(startTime) && tapdBugPriorityConfInDB.EndTime.Before(endTime)
|
||||
if isStartTimeInDuration || isEndTimeInDuration {
|
||||
err = ecode.MartheTimeConflictError
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
tapdBugPriorityConf := &model.TapdBugPriorityConf{
|
||||
ID: req.ID,
|
||||
ProjectTemplateID: req.ProjectTemplateID,
|
||||
Urgent: req.Urgent,
|
||||
High: req.High,
|
||||
Medium: req.Medium,
|
||||
UpdateBy: username,
|
||||
Status: req.Status,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
}
|
||||
|
||||
if req.ID > 0 {
|
||||
err = s.dao.UpdateTapdBugPriorityConf(tapdBugPriorityConf)
|
||||
} else {
|
||||
// add new
|
||||
err = s.dao.InsertTapdBugPriorityConf(tapdBugPriorityConf)
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["tapd_bug_priority_conf"] = tapdBugPriorityConf.ID
|
||||
return
|
||||
}
|
||||
|
||||
// AccessToWorkspace Access To Workspace.
|
||||
func (s *Service) AccessToWorkspace(workspaceID, username string) (isAccess bool) {
|
||||
if !s.c.Tapd.BugOperateAuth {
|
||||
return true
|
||||
}
|
||||
|
||||
var (
|
||||
usernames []string
|
||||
contactInfo *model.ContactInfo
|
||||
err error
|
||||
)
|
||||
|
||||
if contactInfo, err = s.dao.QueryContactInfoByUsername(username); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if contactInfo.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if usernames, err = s.dao.WorkspaceUser(workspaceID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, u := range usernames {
|
||||
if u == contactInfo.NickName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HttpAccessToWorkspace Access To Workspace.
|
||||
func (s *Service) HttpAccessToWorkspace(c context.Context, workspaceID, username string) (rep map[string]interface{}, err error) {
|
||||
var (
|
||||
usernames []string
|
||||
contactInfo *model.ContactInfo
|
||||
isAccess bool
|
||||
)
|
||||
|
||||
if contactInfo, err = s.dao.QueryContactInfoByUsername(username); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if contactInfo.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
if usernames, err = s.dao.WorkspaceUser(workspaceID); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, u := range usernames {
|
||||
if u == contactInfo.NickName {
|
||||
isAccess = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
rep = make(map[string]interface{})
|
||||
rep["is_access"] = isAccess
|
||||
rep["names"] = usernames
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) getBuglyIssuesByFilterSQLWithNoTapdBug(issueFilterSQL string) (buglyIssues []*model.BuglyIssue, err error) {
|
||||
var tmpBuglyIssues []*model.BuglyIssue
|
||||
|
||||
if tmpBuglyIssues, err = s.dao.GetBuglyIssuesByFilterSQL(issueFilterSQL); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, buglyIssue := range tmpBuglyIssues {
|
||||
if buglyIssue.TapdBugID == "" {
|
||||
buglyIssues = append(buglyIssues, buglyIssue)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Service) getTapdBugInsertLock(projectTplId int64) (tapdBugInsertLock *sync.Mutex) {
|
||||
s.syncTapdBugInsertLock.Lock()
|
||||
defer s.syncTapdBugInsertLock.Unlock()
|
||||
|
||||
var ok bool
|
||||
if tapdBugInsertLock, ok = s.mapTapdBugInsertLocks[projectTplId]; !ok {
|
||||
tapdBugInsertLock = new(sync.Mutex)
|
||||
s.mapTapdBugInsertLocks[projectTplId] = tapdBugInsertLock
|
||||
}
|
||||
return
|
||||
}
|
134
app/admin/ep/marthe/service/user.go
Normal file
134
app/admin/ep/marthe/service/user.go
Normal file
@ -0,0 +1,134 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"go-common/library/log"
|
||||
|
||||
"go-common/app/admin/ep/marthe/model"
|
||||
"go-common/library/ecode"
|
||||
)
|
||||
|
||||
// QueryUserInfo query user info.
|
||||
func (s *Service) QueryUserInfo(c context.Context, username string) (userInfo *model.User, err error) {
|
||||
if userInfo, err = s.dao.FindUserByUserName(username); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if userInfo.ID == 0 {
|
||||
user := model.User{Name: username, EMail: username + "@bilibili.com"}
|
||||
s.dao.CreateUser(&user)
|
||||
userInfo, err = s.dao.FindUserByUserName(username)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HttpSyncWechatContacts Http Sync Wechat Contacts.
|
||||
func (s *Service) HttpSyncWechatContacts(ctx context.Context) (err error) {
|
||||
s.taskCache.Do(context.TODO(), func(ctx context.Context) {
|
||||
s.SyncWechatContacts()
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
// SyncWechatContacts Sync Wechat Contacts.
|
||||
func (s *Service) SyncWechatContacts() (err error) {
|
||||
s.syncWechatContactsLock.Lock()
|
||||
defer s.syncWechatContactsLock.Unlock()
|
||||
log.Info("start")
|
||||
var (
|
||||
wechatContacts []*model.WechatContact
|
||||
contactInfosInDB []*model.ContactInfo
|
||||
)
|
||||
|
||||
if wechatContacts, err = s.dao.WechatContacts(context.Background()); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if contactInfosInDB, err = s.dao.QueryAllContactInfos(); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, wechatContact := range wechatContacts {
|
||||
var (
|
||||
tmpContactInfoInDB *model.ContactInfo
|
||||
)
|
||||
for _, contactInfoInDB := range contactInfosInDB {
|
||||
if contactInfoInDB.UserID == wechatContact.UserID {
|
||||
tmpContactInfoInDB = contactInfoInDB
|
||||
break
|
||||
}
|
||||
}
|
||||
if tmpContactInfoInDB != nil {
|
||||
//update
|
||||
tmpContactInfoInDB.UserName = wechatContact.EnglishName
|
||||
tmpContactInfoInDB.NickName = wechatContact.Name
|
||||
|
||||
if err = s.dao.UpdateContactInfo(tmpContactInfoInDB); err != nil {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
//add
|
||||
tmpContactInfoInDB = &model.ContactInfo{
|
||||
UserName: wechatContact.EnglishName,
|
||||
NickName: wechatContact.Name,
|
||||
UserID: wechatContact.UserID,
|
||||
}
|
||||
|
||||
if err = s.dao.InsertContactInfo(tmpContactInfoInDB); err != nil {
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Info("end")
|
||||
return
|
||||
}
|
||||
|
||||
// AccessToBugly Access To Bugly.
|
||||
func (s *Service) AccessToBugly(c context.Context, username string) (isAccess bool) {
|
||||
var (
|
||||
userInfo *model.User
|
||||
err error
|
||||
)
|
||||
|
||||
if userInfo, err = s.QueryUserInfo(c, username); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
isAccess = userInfo.VisibleBugly
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UpdateUserVisibleBugly Update User Visible Bugly.
|
||||
func (s *Service) UpdateUserVisibleBugly(c context.Context, username, updateUsername string, visibleBugly bool) (err error) {
|
||||
var (
|
||||
hasRight bool
|
||||
userInfo *model.User
|
||||
)
|
||||
|
||||
for _, super := range s.c.Bugly.SuperOwner {
|
||||
if username == super {
|
||||
hasRight = true
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if !hasRight {
|
||||
err = ecode.AccessDenied
|
||||
return
|
||||
}
|
||||
|
||||
if userInfo, err = s.dao.FindUserByUserName(updateUsername); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if userInfo.ID == 0 {
|
||||
err = ecode.NothingFound
|
||||
return
|
||||
}
|
||||
|
||||
err = s.dao.UpdateUserVisibleBugly(userInfo.ID, visibleBugly)
|
||||
|
||||
return
|
||||
}
|
Reference in New Issue
Block a user