This commit is contained in:
root 2019-04-22 02:59:20 +00:00
commit beccf3fe43
25440 changed files with 4054998 additions and 0 deletions

34
.bazelrc Normal file
View File

@ -0,0 +1,34 @@
startup --expand_configs_in_place
startup --max_idle_secs=10800 --connect_timeout_secs=5
startup --host_jvm_args=-XX:+UseParallelGC --host_jvm_args=-Xmx6g --host_jvm_args=-Xms1g
startup --idle_server_tasks --noexperimental_oom_more_eagerly --experimental_oom_more_eagerly_threshold=100
# Show us information about failures.
# build --watchfs
build:ci -j 4
build --experimental_repository_cache_hardlinks
build --experimental_guard_against_concurrent_changes
build --experimental_strict_action_env
build --announce_rc
build --remote_http_cache=http://bazel-cache.bilibili.co/go-common --remote_local_fallback
build --remote_max_connections=0
build:ci --genrule_strategy=standalone --spawn_strategy=standalone
build:office --genrule_strategy=sandboxed --spawn_strategy=sandboxed
build --verbose_failures
build:unit --features=race
test --test_output=errors
test --test_arg=-test.v
test:unit --features=race
test --test_summary=detailed
# Include git version info
build --workspace_status_command build/print-workspace-status.sh
# Make /tmp hermetic
#build --sandbox_tmpfs_path=/tmp
build --experimental_multi_threaded_digest
build --remote_timeout=5
# This flag requires Bazel 0.5.0+
#build --sandbox_fake_username
# Enable go race detection.
test:unit --features=race

33
.generated_files Normal file
View File

@ -0,0 +1,33 @@
# Files that should be ignored by tools which do not want to consider generated
# code.
#
# https://github.com/kubernetes/contrib/blob/master/mungegithub/mungers/size.go
#
# This file is a series of lines, each of the form:
# <type> <name>
#
# Type can be:
# path - an exact path to a single file
# file-name - an exact leaf filename, regardless of path
# path-prefix - a prefix match on the file path
# file-prefix - a prefix match of the leaf filename (no path)
# paths-from-repo - read a file from the repo and load file paths
#
file-prefix zz_generated.
file-name BUILD.bazel
file-name BUILD
file-name types.generated.go
file-name generated.pb.go
file-name generated.proto
file-name types_swagger_doc_generated.go
path-prefix Godeps/
path-prefix vendor/
path-prefix api/swagger-spec/
path-prefix pkg/generated/
paths-from-repo docs/.generated_docs
file-suffix pb.go

44
.gitignore vendored Normal file
View File

@ -0,0 +1,44 @@
# idea ignore
.idea/
*.ipr
*.iml
*.iws
biligo/
.vscode/
*.swp
# temp ignore
*.log
*.cache
*.diff
*.exe
*.exe~
*.patch
*.tmp
*debug.test
# system ignore
.DS_Store
Thumbs.db
# project
*.cert
*.key
.test
iprepo.txt
app/*/*/cmd/cmd
app/*/*/*/cmd/cmd
app/*/*/cmd/debug
app/*/*/*/cmd/debug
app/tool/kratos/kratos
bazel-bin
bazel-genfiles
bazel-go-common
bazel-out
bazel-testlogs
bazel-test
_output

66
.gitlab-ci.yml Normal file
View File

@ -0,0 +1,66 @@
variables:
CI_SERVER_URL: http://git.bilibili.co
# CI_DEBUG_TRACE: "true"
stages:
- COMPILE
- LINT
- TEST
compile part:
stage: COMPILE
script:
- bash .rider/make_update.sh
- bazel info
- pwd
- bash .rider/bazel_build.sh "part"
only:
- branches
retry: 1
compile(merge master):
stage: COMPILE
script:
- git pull origin master
- bash .rider/make_update.sh
- bazel info
- pwd
- bash .rider/bazel_build.sh
only:
- branches
retry: 1
gometalinter:
stage: LINT
allow_failure: true
script:
- echo "gometalinter"
- pwd
- bash .rider/lint.sh
only:
- branches
saga check:
stage: LINT
allow_failure: false
script:
- echo "saga check"
- pwd
- bash .rider/sagacheck.sh
except:
- master
unit test:
stage: TEST
# allow_failure: true
script:
- echo "go unit test run"
- pwd
- bash .rider/unit_test.sh
only:
- branches
tags:
- uat-unittest

View File

@ -0,0 +1,27 @@
<!-- Title规范 : <基础库|服务名|doc> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
-->
### Version
<!-- 发生bug的版本号(retag) : v2.1.0 -->
### Range of affected
<!-- 影响范围:服务、用户等 -->
### Bug behavior
### Correct behavior
### Logs / Screenshots
```
一些log、截图等不需要可以删除
```
### How to fix
<!-- /cc @xxx @yyy 抄送某人 -->
/label ~bug

View File

@ -0,0 +1,19 @@
<!-- Title规范 : <基础库|服务名|doc> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
-->
### Desc
<!-- 描述 -->
### Doc list
- [ ] + README.md
- [ ] m app/service/CONTRIBUTORS.md
- [ ] - app/service/*/CHANGELOG.md
### Links / Refs
* <ref>
* <ref>
/lable ~documentation

View File

@ -0,0 +1,20 @@
<!-- Title规范 : <基础库|服务名|doc> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
-->
### Desc
<!-- 描述 -->
### Roadmap
* <step>
* <step>
### Links / Refs
* <ref>
* <ref>
<!-- /cc @xxx @yyy 抄送某人 -->
/label ~feature

View File

@ -0,0 +1,20 @@
<!-- Title规范 : <基础库|服务名|doc> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
-->
### Desc
<!-- 描述 -->
### Goals
* <goal>
* <goal>
### Links / Refs
* <ref>
* <ref>
<!-- /cc @xxx @yyy 抄送某人 -->
/label ~refactor

View File

@ -0,0 +1,22 @@
<!-- Title规范 : <基础库|服务名|doc> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
-->
### Background
<!-- 背景介绍 -->
### Suggestion
<!-- 详细的建议内容 -->
### Expected behaviour
<!-- 预期表现 -->
### Links / Refs
* <ref>
* <ref>
<!-- /cc @xxx @yyy 抄送某人 -->
/lable ~suggestion

View File

@ -0,0 +1,18 @@
<!-- Title规范 : <基础库|服务名|doc|其他> : <标题>
栗子:
1. library/log : xxxxxxxx
2. account-service : xxxxxxxx
3. doc : xxxxxxxx
4. 搞个大新闻 : xxxxxxxx
-->
### Version
* v1.0.0 : library/log
* v2.1.0 : account-service
### Related issue
fix #<issue number>
### Review tips
<!-- 写给 reviewer 的 tips -->
* <tip>
* <tip>

20
.gometalinter.json Normal file
View File

@ -0,0 +1,20 @@
{
"Linters": {},
"Vendor": true,
"Deadline": "5m",
"Cyclo": 50,
"Enable": [
"gofmt",
"vet",
"golint",
"vetshadow",
"gocyclo",
"staticcheck",
"deadcode"
],
"Exclude": [
".+\\.pb\\.go",
".+\\.pb\\.gw\\.go"
],
"MinConfidence": 0.81
}

1
.kazelcfg.json Normal file
View File

@ -0,0 +1 @@
build/root/.kazelcfg.json

19
.rider/.gometalinter.json Normal file
View File

@ -0,0 +1,19 @@
{
"Linters": {},
"Vendor": true,
"Deadline": "5m",
"Cyclo": 50,
"Enable": [
"gofmt",
"vet",
"golint",
"vetshadow",
"gocyclo",
"deadcode"
],
"Exclude": [
".+\\.pb\\.go",
".+\\.pb\\.gw\\.go"
],
"MinConfidence": 0.81
}

92
.rider/CHANGELOG.md Normal file
View File

@ -0,0 +1,92 @@
## .rider
###Version 2.20
1. 去除megacheck, unused, gosimple三项
###Version 2.19
1. ut开放library目录执行
###Version 2.18
1. 更新unit_test.sh的ReadDir()逻辑
###Version 2.17
1. sagacheck 添加bgr工具作为规则引擎
###Version 2.16
1. bazel coverage --config=ci
###Version 2.15
1. ut增加自定义lint检查
2. ut 覆盖率文件过滤monkey.go文件
3. ut magic流程增加评论用户校验
###Version 2.14
1. ut执行增加 convey json.
2. ut执行增加过滤器
###Version 2.13
1. ut脚本增加覆盖率原始文件上传
### Version 2.12
1. ut脚本去除包含多重子目录测试结果冗余问题
### Version 2.11
1. ut脚本修复未建mr跳过测试
### Version 2.10
1. ut脚本magic方法bug修复
### Version 2.9
1. ut脚本bazel test增加超时及测试报告文件检查
2. ut脚本start方法增加请求commit statues获取实际commit author
3. ut脚本upload方法增加入参校验
### Version 2.8
1. ut脚本加入app/(admin|interface)/main的测试
2. ut脚本加入结束执行后saga评论报告
### Version 2.7
1. 单元测试改为bazel test
2. 去除部分debug打印信息
### Version 2.6
1. 添加跳过check检测开关
### Version 2.5.3
1. upload接口异常打印日志
### Version 2.5.2
1. 加入bazel test相关处理
### Version 2.5.1
1. 优化ut脚本流程控制
### Version 2.5
1. ut脚本只执行service/main下dao层和library下的单测
2. 增加达标标准判断
2.1 通过率=100% && 覆盖率>=30% && 当前pkg同比上次执行的单测覆盖增长率>=0
3. 输出当前执行概况日志
### Version 2.4
1. 删除编译失败的时候打包变化文件的机制
2. 测试权限
### Version 2.3
1.修正检测changelog大小写的问题
2.修改全量编译的job名称
### Version 2.2
1. 重构pipeline代码
2. 修改ut为不允许失败
### Version 2.1
1. cyclo函数复杂度调整到50
2. gometalinter过滤掉vendor包
### Version 2.0
1. 合并优化代码到lint.sh
2. 修改匹配变化文件的逻辑
### Version 1.0
1. 将compile重试次数改为1次
2. 修正lint_if_changed.sh匹配文件的bug

20
.rider/CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,20 @@
# Owner
fangrongchang
tangyongqiang
chenjianrong
zhaobingqing
chengxing
hedan
# Author
muyang
fangrongchang
tangyongqiang
chenjianrong
zhaobingqing
chengxing
fengshanshan
hedan
# Reviewer
all

20
.rider/OWNERS Normal file
View File

@ -0,0 +1,20 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- chengxing
- chenjianrong
- fangrongchang
- fengshanshan
- hedan
- muyang
- tangyongqiang
- zhaobingqing
reviewers:
- chengxing
- chenjianrong
- fangrongchang
- fengshanshan
- hedan
- muyang
- tangyongqiang
- zhaobingqing

48
.rider/bazel_build.sh Normal file
View File

@ -0,0 +1,48 @@
#!/bin/bash
type=${1}
echo "$(date) build..." >> /data/gitlab-runner/build.log
function compileall()
{
make build-keep-going
}
function compilepart()
{
pkgs=`.rider/changepkgs.sh`
exitCode=$?
if [[ ${exitCode} -ne 0 ]]; then
echo ".rider/changepkgs.sh fail"
exit ${exitCode}
fi
if [[ "${pkgs}" = "" ]]; then
echo "no changepkgs"
exit 0
fi
echo -e "change packages:\n${pkgs}\n"
paths=""
for pkg in ${pkgs}
do
if [[ "${paths}" != "" ]]; then
paths="${paths} union allpaths(//app/..., //${pkg}:all)"
else
paths="allpaths(//app/..., //${pkg}:all)"
fi
done
echo "bazel build..."
query=`bazel query "${paths}"`
echo -e "${query}\n"
bazel build --config=ci --watchfs -k $(echo -e "${query}" | grep -v all-srcs | grep -v package-srcs | grep -v _proto)
#bazel build $(bazel query "${paths}" |grep -v all-srcs |grep -v package-srcs)
}
if [[ "${type}" = "part" ]]; then
compilepart
else
compileall
fi

21
.rider/changefiles.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
#set -x
suffix=${1}
url="${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/repository/commits/${CI_COMMIT_SHA}/merge_requests?private_token=${CI_PRIVATE_TOKEN}"
json=$(curl -s ${url})
if [[ "$json" != "[]" && "$json" != "" ]]; then
target_branch=$(echo ${json} | jq -r '.[0].target_branch')
source_branch=$(echo ${json} | jq -r '.[0].source_branch')
files=$(git diff origin/${target_branch}...origin/${source_branch} --name-only --diff-filter=ACM | grep -E -i "${suffix}")
else
# url="${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/pipelines?private_token=${CI_PRIVATE_TOKEN}&status=success&ref=${CI_COMMIT_REF_NAME}"
# commit=$(curl -s ${url} | jq -r 'first(.[] | .sha)')
## echo "Last green commit is '${commit}'."
# files=$(git diff ${commit} --name-only --diff-filter=ACM | grep -E "${suffix}")
files=$(git diff origin/master...origin/${CI_COMMIT_REF_NAME} --name-only --diff-filter=ACM | grep -E -i "${suffix}")
fi
echo -e "${files}"

28
.rider/changepkgs.sh Normal file
View File

@ -0,0 +1,28 @@
#!/bin/bash
#set -x
files=`.rider/changefiles.sh "*\.go$"`
exitCode=$?
if [[ ${exitCode} -ne 0 ]]; then
echo ".rider/changefiles.sh fail"
exit ${exitCode}
fi
pkgs=""
for file in ${files}
do
pkg="${file%/*}"
if [ $? -eq 0 ]; then
if [[ "${pkgs}" = "" ]]; then
pkgs="${pkg}"
else
pkgs="${pkgs}\n${pkg}"
fi
fi
done
echo -e "${pkgs}" > .rider/.pkgs
pkgs=`sort .rider/.pkgs|uniq`
echo -e "${pkgs}"

39
.rider/lint.sh Normal file
View File

@ -0,0 +1,39 @@
#!/bin/bash
#set -x
pkgs=`.rider/changepkgs.sh|grep -v ^vendor/`
exitCode=$?
if [[ ${exitCode} -ne 0 ]]; then
echo ".rider/changepkgs.sh fail"
exit ${exitCode}
fi
if [[ "${pkgs}" = "" ]]; then
echo "no changepkgs"
exit 0
fi
echo -e "change packages:\n${pkgs}\n"
if [ ! -d "${CI_PROJECT_DIR}/../src" ];then
mkdir ${CI_PROJECT_DIR}/../src
fi
ln -fs ${CI_PROJECT_DIR} ${CI_PROJECT_DIR}/../src
export GOPATH=${CI_PROJECT_DIR}/..
echo "GOPATH: $GOPATH"
cd $GOPATH/src/go-common
exitCode=0
echo -e "\ngometalinter:"
output=`gometalinter --config=.rider/.gometalinter.json ${pkgs}`
exitCode=$?
if [[ "${output}" != "" ]]; then
exitCode=1
echo -e "${output}"
fi
exit ${exitCode}

24
.rider/make_update.sh Normal file
View File

@ -0,0 +1,24 @@
#!/bin/bash
#set -x
if [ ! -d "${CI_PROJECT_DIR}/../src" ];then
mkdir ${CI_PROJECT_DIR}/../src
fi
ln -fs ${CI_PROJECT_DIR} ${CI_PROJECT_DIR}/../src
export GOPATH=${CI_PROJECT_DIR}/..
echo "GOPATH: $GOPATH"
vendor=${CI_PROJECT_DIR}/vendor
for dir in $(ls $vendor)
do
if [ -d $vendor/$dir ]; then
ln -fs $vendor/$dir $GOPATH/src
fi
done
sleep $[ ( $RANDOM % 60 ) + 1 ]s
cd ${CI_PROJECT_DIR}/../src/go-common
#mkdir -p .git/hooks/pre-commit
make bazel-update

28
.rider/sagacheck.sh Normal file
View File

@ -0,0 +1,28 @@
#!/bin/bash
if [ ! -d "${CI_PROJECT_DIR}/../src" ];then
mkdir ${CI_PROJECT_DIR}/../src
fi
ln -fs ${CI_PROJECT_DIR} ${CI_PROJECT_DIR}/../src
export GOPATH=${CI_PROJECT_DIR}/..
exitCode=0
# CHANGELOG check
echo "====CHANGELOG check:===="
files=`.rider/changefiles.sh "CHANGELOG.md"`
if [[ "${files}" = "" ]]; then
echo "未发现CHANGELOG.md文件变更请'添加'或'修改'CHANGELOG.md"
exit 1
else
echo -e "变更如下:\n${files}"
fi
# BGR rule
echo -e "\n====Bili golang rule check:===="
diffFiles=`.rider/changefiles.sh`
cd $GOPATH/src/go-common
go build ./app/tool/bgr
./bgr -script=./app/tool/bgr -hit=main -type=file ${diffFiles}
exitCode=$?
exit ${exitCode}

267
.rider/unit_test.sh Normal file
View File

@ -0,0 +1,267 @@
#!/bin/bash
declare -a dirs=(dao)
declare -a packages
declare -a projects
declare mergeUser
declare commitUser
declare mergeID
#init env
function Init(){
if [ ! -d "${CI_PROJECT_DIR}/../src" ];then
mkdir ${CI_PROJECT_DIR}/../src
fi
ln -fs ${CI_PROJECT_DIR} ${CI_PROJECT_DIR}/../src
export GOPATH=${CI_PROJECT_DIR}/..
}
function GetPackages(){
reg="library/(.*)/(.*).go"
for dir in ${dirs[@]}
do
reg+="|app/(service|interface|admin|job)/main/(.*)/${dir}/(.*).go"
done
files=`.rider/changefiles.sh ${suffix} | grep -E "${reg}"`
if [[ "${files}" = "" ]]; then
echo "shell.GetPackages: no change files"
exit 0
fi
for file in ${files}
do
# if [[ "${file}" =~ "library"* || "${file}" =~ "/mock" ]]; then
if [[ "${file}" =~ "/mock" ]]; then
continue
fi
package="go-common/$(dirname ${file})"
if [[ ${packages} =~ ${package} ]]; then
continue
fi
packages+=${package}" "
packageSplit=(${package//\// })
project=$(printf "%s/" ${packageSplit[@]:0:6})
if [[ ${projects} =~ ${project} || ${project} =~ "/library" ]]; then
continue
fi
projects+=${project%*/}" "
done
if [[ ${packages} = "" || ${projects} = "" ]]; then
echo "shell.GetPackages no change packages"
exit 0
fi
}
# GetUserInfo get userinfo by gitlab result.
function GetUserInfo(){
gitMergeRequestUrl="${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/repository/commits/${CI_COMMIT_SHA}/merge_requests?private_token=${CI_PRIVATE_TOKEN}"
gitCommitUrl="${CI_SERVER_URL}/api/v4/projects/${CI_PROJECT_ID}/repository/commits/${CI_COMMIT_SHA}/statuses?private_token=${CI_PRIVATE_TOKEN}"
mergeJson=$(curl -s ${gitMergeRequestUrl})
commitJson=$(curl -s ${gitCommitUrl})
if [[ "${mergeJson}" = "[]" ]] || [[ "${commitJson}" = "[]" ]]; then
echo "Test not run, maybe you should try create a merge request first!"
exit 0
fi
mergeID=$(echo ${mergeJson} | jq -r '.[0].iid')
mergeUser=$(echo ${mergeJson} | jq -r '.[0].author.username')
commitUser=$(echo ${commitJson} | jq -r '.[0].author.username')
}
# Magic ignore method Check()
function Magic(){
url="http://git.bilibili.co/api/v4/projects/${CI_PROJECT_ID}/merge_requests/${mergeID}/notes?private_token=${CI_PRIVATE_TOKEN}"
json=$(curl -s ${url})
admin="haoguanwei,chenjianrong,hedan,fengshanshan,zhaobingqing"
len=$(echo ${json} | jq '.|length')
for i in $(seq 0 $len)
do
comment=$(echo ${json} | jq -r ".[$i].body")
user=$(echo ${json} | jq -r ".[$i].author.username")
if [[ ${comment} = "+skiput" && ${admin} =~ ${user} ]]; then
exit 0
fi
done
}
# Check determine whether the standard is up to standard
#$1: commit_id
function Check(){
curl -s "${CI_UATSVEN_URL}/x/admin/apm/ut/git/report?project_id=${CI_PROJECT_ID}&merge_id=${mergeID}&commit_id=${CI_COMMIT_SHA}"
checkURL="${CI_UATSVEN_URL}/x/admin/apm/ut/check?commit_id=${CI_COMMIT_SHA}"
json=$(curl -s ${checkURL})
code=$(echo ${json} | jq -r '.code')
if [[ ${code} -ne 0 ]]; then
echo -e "curl ${checkURL} response(${json})"
exit 1
fi
package=$(echo ${json} | jq -r '.data.package')
coverage=$(echo ${json} | jq -r '.data.coverage')
passRate=$(echo ${json} | jq -r '.data.pass_rate')
standard=$(echo ${json} | jq -r '.data.standard')
increase=$(echo ${json} | jq -r '.data.increase')
tyrant=$(echo ${json} | jq -r '.data.tyrant')
lastCID=$(echo ${json} | jq -r '.data.last_cid')
if ${tyrant}; then
echo -e "\t续命失败!\n\t大佬本次执行结果未达标哦(灬ꈍ ꈍ灬)请再次优化ut重新提交🆙"
echo -e "\t---------------------------------------------------------------------"
printf "\t%-14s %-14s %-14s %-14s\n" "本次覆盖率(%)" "本次通过率(%)" "本次增长量(%)" 执行pkg
printf "\t%-13.2f %-13.2f %-13.2f %-12s\n" ${coverage} ${passRate} ${increase} ${package}
echo -e "\t(达标标准:覆盖率>=${standard} && 通过率=100% && 同比当前package历史最高覆盖率的增长率>=0)"
echo -e "\t---------------------------------------------------------------------"
echo -e "本次执行详细结果查询地址请访问http://sven.bilibili.co/#/ut?merge_id=${mergeID}&&pn=1&ps=20"
exit 1
else
echo -e "\t恭喜你续命成功可以请求合并MR了!"
fi
}
function ReadDir(){
# get go-common/app all dir path
gopath=${GOPATH%..}
PathDirs=`find ${gopath}app -maxdepth 3 -type d`
value=""
for dir in ${PathDirs}
do
if [[ -d "$dir" ]];then
for file in `find ${dir} -maxdepth 1 -type f |grep "OWNERS"`
do
owner=""
substr=${dir#*"go-common"}
while read line
do
if [[ "${line}" = "#"* ]] || [[ "${line}" = "" ]] || [[ "${line}" = "approvers:" ]];then
continue
elif [[ "${line}" = "labels:"* ]];then
break
else
owner+="${line:1},"
fi
done < ${file}
value+="{\"path\":\"go-common${substr}\",\"owner\":\"${owner%,}\"},"
done
fi
done
# delete "," at the end of value
value=${value%,}
echo "[${value}]" > path.out
}
# UTLint check the *_test.go files in the pkg
# $1: pkg
function UTLint()
{
cd $GOPATH
declare -i numCase=0
declare -i numAssertion=0
files=$(ls $1 | grep -E "(.*)_test\.go")
if [[ ${#files} -eq 0 ]];then
echo "RunPKGUT.UTLint no *_test.go files in pkg($1)"
exit 1
fi
for file in ${files}
do
numCase+=`grep -c -E "^func Test(.+)\(t \*testing\.T\) \{$" $1/${file}`
numAssertion+=`grep -c -E "^(.*)So\((.+)\)$" $1/${file}`
done
if [[ ${numCase} -eq 0 || ${numAssertion} -eq 0 ]];then
echo -e "RunPKGUT.UTLint no test case or assertion in pkg($1)"
exit 1
fi
}
# BazelTest execute bazel coverage and go tool
# $1: pkg
function BazelTest(){
cd $GOPATH/go-common
pkg=${1//go-common//}":go_default_test"
path=${1//go-common\//}
bazel coverage --config=ci --instrumentation_filter="//${path}[:],-//${path}/mock[/:]" --test_env=DEPLOY_ENV=uat --test_timeout=60 --test_env=APP_ID=bazel.test --test_output=all --cache_test_results=auto --test_arg=-convey-json ${pkg} > result.out
if [[ ! -s result.out ]]; then
echo "==================================WARNING!======================================"
echo "No test case found,请完善如下路径测试用例: ${pkg} "
exit 1
else
echo $?
cp $GOPATH/go-common/bazel-out/k8-fastbuild/testlogs/${path}/go_default_test/coverage.dat ./
go tool cover -html=coverage.dat -o cover.html
fi
}
# BazelTest execute bazel coverage for All files
# $1: pkg(go-common/app/admin/main/xxx/dao)
function BazelTestAll(){
cd $GOPATH/go-common
pkg=${1//go-common//}"/..."
path=${1//go-common\//}
echo "RunProjUT.BazelTestAll(${1}) pkg(${pkg}) path(${path}) pwd($(pwd))"
bazel coverage --config=ci --instrumentation_filter="//${path}[/:],-//${path}/mock[/:]" --test_env=DEPLOY_ENV=uat --test_timeout=60 --test_env=APP_ID=bazel.test --test_output=all --cache_test_results=auto --test_arg=-convey-json ${pkg} > result.out
find bazel-out/k8-fastbuild/testlogs/${path} -name "coverage.dat" | xargs cat | sort -nr | rev | uniq -s 1 | rev > coverage.dat
coverage=$(cat coverage.dat | awk '{sum += $2;covSum += $2 * $3;} END {print covSum/sum*100}')
sed -if "s/coverage: .*%/coverage: ${coverage}%/g" result.out
go tool cover -html=coverage.dat -o cover.html
}
# upload data to apm
# $1: file result.out path
function Upload () {
if [[ ! -f "result.out" ]] || [[ ! -f "cover.html" ]] || [[ ! -f "coverage.dat" ]]; then
echo "==================================WARNING!======================================"
echo "No test found!~ 请完善如下路径测试用例: ${1} "
exit 1
fi
url="${CI_UATSVEN_URL}/x/admin/apm/ut/upload?merge_id=${mergeID}&username=${mergeUser}&author=${commitUser}&commit_id=${CI_COMMIT_SHA}&pkg=${1}"
json=$(curl -s ${url} -H "Content-type: multipart/form-data" -F "html_file=@cover.html" -F "report_file=@result.out" -F "data_file=@coverage.dat")
if [[ "${json}" = "" ]]; then
echo "RunPKGUT.Upload curl ${url} fail"
exit 1
fi
msg=$(echo ${json} | jq -r '.message')
data=$(echo ${json} | jq -r '.data')
code=$(echo ${json} | jq -r '.code')
if [[ ${code} -ne 0 ]]; then
echo "=============================================================================="
echo -e "RunPKGUT.Upload Response. message(${msg})"
echo -e "RunPKGUT.Upload Response. data(${data})\n\n"
echo -e "RunPKGUT.Upload Upload Fail! status(${code})"
exit ${code}
fi
}
function RunPKGUT(){
for package in ${packages}
do
echo "RunPKGUT.UTLint Start. pkg(${package})"
UTLint ${package}
echo "RunPKGUT.BazelTest Start. pkg(${package})"
BazelTest ${package}
echo "RunPKGUT.Upload Start. pkg(${package})"
Upload ${package}
done
return 0
}
function RunProjUT(){
for project in ${projects}
do
echo "RunProjUT.BazelTestAll Start. project(${project})"
BazelTestAll ${project}
echo "RunProjUT.Upload BazelTest Start. project(${project})"
Upload ${project%/*}
done
}
function UploadApp(){
ReadDir
url="${CI_UATSVEN_URL}/x/admin/apm/ut/upload/app"
curl -s ${url} -H "Content-type: multipart/form-data" -F "path_file=@path.out" > /dev/null
echo "UploadApp() UpPath has finshed."
}
# run
Init
GetPackages
GetUserInfo
Magic
RunPKGUT
RunProjUT
UploadApp
Check

1
BUILD.bazel Normal file
View File

@ -0,0 +1 @@
build/root/BUILD.root

481
CHANGELOG.md Normal file
View File

@ -0,0 +1,481 @@
### Go-Common
### Version 7.19
1. 更新vendor下github.com/xanzy/go-gitlab包
### Version 7.18
1. 删除无用的git文件
### Version 7.17
1. 添加 WithContext 方法, Conn 待实现
2. 使用 traceConn 实现 trace 埋点
3. GetMulti 检查 key 列表不为空, 空列表直接返回空 map
4. legalKey 检查 key 不为空
### Version 7.16.8
1. 修改saga check无需在master分支跑
### Version 7.16.7
1. pipeline编译暂时去掉merge master
### Version 7.16.5
1. pipeline增加bazel局部编译job
### Version 7.16.4
1. pipeline增加unitest的执行stage
### Version 7.16.3
1. gometalinter暂时不检查pb
### Version 7.16.3
1. 修正gometalinter的bug
2.合并make update到COMPILE里
### Version 7.16.2
1. 增加saga-admin的功能
### Version 7.16.1
1. 将编译次数改为一次
2. 增加gometalinter
### Version 7.15.2
1. 树状结构展示个业务方权限责任人
### Version 7.15.1
1. 去掉发邮件的stage
2. 调整makeupdate为独立的stage
### Version 7.14.3
1. 由于历史代码太多无法通过lint所以暂时允许lint失败
2. 增加将lint不通过的文件列表打印出来
### Version 7.14.2
1. Runner触发以后先Merge Master然后触发Compile
### Version 7.14.1
1. 为bazel info添加-k参数
### Version 7.14.0
1. memcache large value storage
### Version 7.13.2
1. 修复ecode.OK也打Error日志
### Version 7.13.1
1. 调整cache chan prom数据记录时机
### Version 7.13.0
1. 全链路传递超时时间
### Version 7.13.1
1. HTTP Client 升级修复此升级导致的identity基础库bug
### Version 7.13.0
1. HTTP Client 升级,通用参数统一配置
### Version 7.12.0
1. log保留\n替换\r为空
### Version 7.11.0
1. 迁移account interface到Kratos
### Version 7.10.1
1. 修复hbase依赖btree
### Version 7.10.0
1. 迁移account service到Kratos
### Version 7.9.0
1. 增加stack 信息记录,
2. 修改statHandler为一个方法调用
### Version 7.8.1
1. 更新ecode的readme和changelog
### Version 7.8.0
1. 增加pkg/errors 包,用于记录错误信息堆栈信息
2. 在ecode的example中增加error使用example
### Version 7.7.2
1. 修复了memcache存入数据, Object & Value 为nil的情况
### Version 7.7.1
1. 修复redigo
2. 修复了databus sdk Commit的饥饿问题
### Version 7.7.0
1. 迁移golang库里的redigo到go-common里的cache/redis
2. 修复了cache/redis 普罗米修斯耗时、异常上报
### Version 7.6.0
1. 新增spy service rpc client
2. 增加history
### Version 7.5.0
> 1. cache/memcache 升级支持protobuf
> 2. cache/memcache 破坏性增加了conn.Scan去掉了item.Scan方法
> 3. business/client/identify 缓存gob改成了protobuf
> 4. vendor新增了github.com/gogo/protobuf的依赖
### Version 7.4.2
> 1. 更新vendor里golang库到最新版
### Version 7.4.1
> 1. 更新ecode文档
### Version 7.4.0
> 1. ecode 获取code message由从数据库全量更新改为通过接口增量更新
> 2. 升级配置,不兼容老的版本,参考 http://info.bilibili.co/pages/viewpage.action?pageId=3684076
### Version 7.3.0
> 1.支持vendor
> 2.继承了location-service
### Version 7.2.0
> 1.big-repo 修改business目录
### Version 7.1.0
> 1.添加secure model
> 2.修改location model
### Version 7.0.0
> 1.合并go-business
> 2.合并rouer
> 3.拆分interceptor
### Version 6.24.5
> 1.http client的breaker状态变更支持上报prometheus
### Version 6.24.4
> 1.rpc server支持recover
### Version 6.24.3
> 1.修复databus中offset为0不能commit的问题
### Version 6.24.2
> 1.增加syscall/signal 对 macos(darwin) 的支持
### Version 6.24.1
> 1.强制要求http和rpc client设置breaker否则会运行panic
### Version 6.24.0
> 1.去disconf使用config-service SDK作为唯一Client
### Version 6.23.0
> 1.memcache新增序列化和压缩
> 2.新版memcache接口
> 3.net/http新增错误普罗米修斯上报
<b>memcache不再兼容带有破坏性修改</b>
### Version 6.22.2
> 1.去掉vendor
### Version 6.22.1
1. 修复 syslog 在linux环境下空指针错误
### Version 6.22.0
1.新增vendor支持第三方依赖包
### Version 6.21.1
1.fix mc Stat, 以及增加单元测试
### Version 6.21.0
兼容了windows编译
1. 增加了Windows上Signal信号处理的Fake方法
2. 增加了Syslog兼容的Fake方法
喜欢windows开发的同学可以
syslog -> go-common/syslogsyslog日志收集
os/Signal ->go-common/os/signalsyscall -> go-common/syscall信号处理
### Version 6.20.0
> 1.迁移golang库中的gomemcache交由go-common/cache/memcache维护
> 2.优化了net/trace包内私有方法
### Version 6.19.2
> 1.修复database/sql Stmt函数漏初始化db变量导致的panic
### Version 6.19.1
> 1.解决先前版本readme的冲突
### Version 6.19.0
> 1.add RESTful httpclient
### Version 6.18.0
> 1.修复mysql lifetime,迁移mysql配置
### Version 6.17.1
> 1.修复log-agent sdk收集日志中有换行符未转义的bug
### Version 6.17.0
> 1.新增log-agent日志收集sdk以unix socket方式发送日志
### Version 6.16.0
> 1.修改httpconf
> 1.改为读写锁读取配置
### Version 6.15.0
> 1.修改net/netutil熔断器支持全局开关
### Version 6.14.0
> 1.config sdk增加读取appoint参数用作回退时读取指定配置文件
### Version 6.14.0
> 1.config sdk增加读取appoint参数用作回退时读取指定配置文件
### Version 6.13.0
> 1.调整router handler参数将函数内部join pattern改为外部传入完整pattern
### Version 6.12.1
> 1.修复db 事务初始化的bug
### Version 6.12.0
> 1.stat支持prometheus功能实现统计和监控
### Version 6.11.0
> 1. 对reids进行了修改以后不依赖conf包了配置直接写在redis本包
### Version 6.10.0
> 1. 增加rpc sharding
### Version 6.9.0
> 1.配置中心client 启动参数增加token字段区分应用和环境
### Version 6.8.0
> 1.依赖zookeeper的rpc client由连接池改为单连接
> 2.breaker新增了callback通知状态变更
### Version 6.7.2
> 1.修改zookeeper注册参数
### Version 6.7.1
> 1.配置中心增加获得配置文件路径方法
### Version 6.7.0
1.fix rpc权重为0时client不创建长连接
2.rpc增加配置是否注册zookeeper
### Version 6.6.4
> 1.fix mc expire max ttl
### Version 6.6.3
> 1. 将配置中心启动参数设置成和disconf的一样
### Version 6.6.2
> 1. 优化了net/http Client的buffer过小导致的syscall过多
### Version 6.6.1
> 1.fix http client超时设置不准确的问题去掉了读包体和反序列化的时间
### Version 6.6.0
> 1.rpc Broadcast 添加reply参数,支持对任意方法进行广播
### Version 6.5.2
> 1.fix 新版配置中心和老版本init冲突问题
### Version 6.5.1
> 1.fix rpc Boardcast的bug
### Version 6.5.0
> 1. 新版本配置中心conf/Client
### Version 6.4.1
> 1. 修复remoteip获取
### Version 6.4.0
> 1. 去除rpcx
### Version 6.3.1
> 1.fix配置文件名覆盖的问题
### Version 6.3.0
> 1. net/rpc支持了Boardcast广播调用
### Version 6.2.5
> 1. net/rpc支持了group路由策略
### Version 6.2.4
> 1. 优化了statsd批量发包
### Version 6.2.3
> 1. 修复了trace comment 在annocation的bug
### Version 6.2.2
> 1. 优化了net/rpc反射带来的性能问题
> 2. net/rpc内置了ping
### Version 6.2.1
> 1. 临时加回net/rpcx, TODO remove
> 2. net/trace.Trace2 奔溃和race修复
### Version 6.2.0
> 1. 去除了net/rpcx
### Version 6.1.3
> 1. 新增了memcache Get2/Gets
### Version 6.1.2
> 1. net/rpc使用CPU个数建立连接
### Version 6.1.1
> 1. 兼容net/rpc server的Client trace传递
### Version 6.1.0
> 1. 升级databus sdk注意配置文件有变更
#### Version 6.0.0
> 1. xtime->time, xlog->log perf->net/http/perf
> 2. rpc支持设置方法级别超时
> 3. rpc支持breaker熔断
> 4. database 修复Row和标准库不兼容使用database Rows替换标准库的Rows使用
> 5. 新的rpc框架net/rpc
> 6. net/trace支持Family初始化
#### Version 5.2.2
> 1.Zone结构体加json tag
#### Version 5.2.0
> 1.更改http包名和路径
> 2.增加http单元测试
> 3.statd去掉hostname
> 4.ip结构体增加isp字段
#### Version 5.1.2
> 1.xip改为支持对象访问去掉全局对象和函数
#### Version 5.1.1
> 1.修复上报trace的位置
#### Version 5.1.0
> 1.支持熔断
> 2.rpc server判断zk是否注册
> 3.修复Infoc连接重连
> 4.xhttp xrpc xweb改为httpx rpcx webx
> 5.修复trace level的bug
#### Version 5.0.0
> 0.注意一定要使用Go1.7及以上版本
> 1.用golang/rpcx替换官方库
> 2.使用go1.7的context包
> 3.增加traceon业务监控上报
> 4.xhttp中ip方法挪到xip包
> 5.rpc服务暴露close接口
> 6.修复ugc配置中心等待30s的bug
> 7.修复rpc client因权重变更导致panic的bug
> 8.使用context.WithTimeout替代timer
#### Version 4.4.1
> 1.日志新增按文件大小rotate
#### Version 4.4.0
> 1.infoc支持udp和tcp方式
> 2.去掉stdout、stderr输出到syslog的逻辑
#### Version 4.3.2
> 1.fix rpc timeout连接泄露的bug
> 2.rpc单连接改为多连接
#### Version 4.3.1
> 1.支持从环境变量获取配置
> 2.syslog支持打印标准输出和错误
#### Version 4.3.0
> 1.支持配置中心
#### Version 4.2.0
> 1.修复xredis keys的bug
> 2.修复xmemcache批量删除bug
> 3.新增 databus v2 客户端
#### Version 4.1.3
> 1.trace 优化
> 2.去掉sp 运营商字段
#### Version 4.1.2
> 1.trace id改为int64
> 2.trace http client增加host
> 3.ip新增运营商字段
#### Version 4.1.1
> 1.fix kafka monitor
#### Version 4.1.0
> 1.去掉ecode和router
### Version 4.0.0
> 1.business移到go-business
> 2.新增InternalIp()获取本机ip
> 3.rpc ping加超时
> 4.增加ecode配置
> 5.新增支持syslog
#### Version 3.6.6
> 1.修复xip边界值时死循环问题
#### Version 3.6.5
> 1.space接口只保留s_img、l_img
> 2.archive-service新增viewPage的rpc方法
#### Version 3.6.4
> 1.VIP相关接口及错误码
### Version 3.6.3
> 1.修复ip递归查找导致的栈溢出
#### Version 3.6.2
> 1.account-service profile的http接口、批量获取relation接口
> 2.账号新增official_verify字段
#### Version 3.6.1
> 1.修复degrade中变量名错误
> 2.简化redis的auth逻辑使用option

9
CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,9 @@
# Owner
maojian
haoguanwei
# Author
all
# Reviewer
all

40
HERO.md Normal file
View File

@ -0,0 +1,40 @@
# HERO
## 人类Human
- 大法师Arch mage-- AM
- 山丘之王Mountain King-- MK
- 圣骑士Paladin-- PAL
- 血法师Blood Mage-- BMG
## 兽族Orc
- 先知Far Seer-- FS
- 暗影猎手Shadow hunter-- XY
- 牛头人酋长Tauren Chieftain-- NT
- 剑圣BladeMaster-- BM
## 暗夜Night Elf
- 守望者Warden-- WD
- 月之女祭师Priess Of the moon-- POM
- 恶魔猎手Demon Hunter-- DH
- 丛林守护者Keepper of the grove-- KOG
## 亡灵Undead
- 地穴领主Crypt Lord-- CL
- 死亡骑士Death Knight-- DK
- 巫妖Lich-- LICH
- 恐惧魔王Dread Lord-- DL
## 中立
- 熊猫酒仙Pandarenbrewer-- XM
- 火焰领主Flame Lord-- FL
- 地精炼金术士Goblin Alchemist-- LJ
- 深渊魔王Pit Lord-- PL
- 黑暗游侠Dark Ranger-- BR
- 驯兽师BEASTMASTER-- SW
- 地精修补匠Tinker-- TINKER
- 娜迦女海巫Naga Seawitch-- Naga

1
Makefile Normal file
View File

@ -0,0 +1 @@
build/root/Makefile

5
OWNERS Normal file
View File

@ -0,0 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- haoguanwei
- maojian

526
README.md Normal file
View File

@ -0,0 +1,526 @@
### Kratos
##### 项目规范
1,每个目录 需要有独立的README.md CHANGELOG.md CONTRIBUTORS.md具体可以参考
http://git.bilibili.co/platform/go-common/tree/master/business/service/archive
2,以后每个业务或者基础组件维护自己的版本号在CHANGELOG.md中rider 构建以后的tag关联成自己的版本号
3,整个大仓库不再有tag只有master 主干分支所有mr发送前一定要注意先merge master
4,使用Rider构建以后retag回滚可以基于Rider的retag来回滚而不是回滚大仓库的代码
5,提供RPC内部服务放置在business/service中任务队列放置在business/job中对外网关服务放置在business/interface管理后台服务放置在business/admin
6,每个业务自建cmd文件夹,将main.go文件和test配置文件迁移进去
7,构建的时候自定义脚本选择krotos_buil.sh,自定义参数选择自己所在业务的路径 ps例如 interface/web-show
8,大仓库的mr合并方式为在mr中留言"+merge",鉴权依据服务根目录下 CONTRIBUTORS.md 文件解析,具体可以参考:
http://info.bilibili.co/pages/viewpage.action?pageId=7539410
## 负责人信息
<details>
<summary>展开查看</summary>
<pre><code>.
├── Owner: maojian,haoguanwei
├── app
│ ├── Owner: maojian,haoguanwei,linmiao
│ ├── admin
│ │ ├── ep
│ │ │ ├── merlin
│ │ │ │ └── Owner: maojian,yuanmin,fengyifeng,xuneng
│ │ │ └── saga
│ │ │ └── Owner: tangyongqiang
│ │ ├── main
│ │ │ ├── activity
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── answer
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── apm
│ │ │ │ └── Owner: haoguanwei,lintanghui
│ │ │ ├── app
│ │ │ │ └── Owner: haoguanwei,peiyifei
│ │ │ ├── appstatic
│ │ │ │ └── Owner: liweijia,renwei
│ │ │ ├── bfs-apm
│ │ │ │ └── Owner: wangweizhen
│ │ │ ├── block
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── cache
│ │ │ │ └── Owner: lintanghui
│ │ │ ├── config
│ │ │ │ └── Owner: haoguanwei,lintanghui
│ │ │ ├── coupon
│ │ │ │ └── Owner: yubaihai,zhaogangtao
│ │ │ ├── creative
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── credit
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── dm
│ │ │ │ └── Owner: liangkai,renwei
│ │ │ ├── esports
│ │ │ │ └── Owner: liweijia,renwei
│ │ │ ├── filter
│ │ │ │ └── Owner: zhaogangtao,muyang
│ │ │ ├── growup
│ │ │ │ └── Owner: gaopeng
│ │ │ ├── laser
│ │ │ │ └── Owner: haoguanwei,shencen,wangzhe01
│ │ │ ├── manager
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── member
│ │ │ │ └── Owner: linmiao,haoguanwei,zhoujiahui,zhoujixiang,chenjianrong
│ │ │ ├── point
│ │ │ │ └── Owner: yubaihai,zhaogangtao
│ │ │ ├── push
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── relation
│ │ │ │ └── Owner: linmiao,zhoujiahui
│ │ │ ├── reply
│ │ │ │ └── Owner: chenzhihui,lujinhui
│ │ │ ├── search
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei,guanhuaxin
│ │ │ ├── sms
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── spy
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── tag
│ │ │ │ └── Owner: renwei,renyashun
│ │ │ ├── tv
│ │ │ │ └── Owner: liweijia,renwei
│ │ │ ├── up
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── upload
│ │ │ │ └── Owner: haoguanwei,zhapuyu
│ │ │ ├── usersuit
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── videoup
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── videoup-task
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── vip
│ │ │ │ └── Owner: zhaogangtao
│ │ │ └── workflow
│ │ │ └── Owner: haoguanwei,zhapuyu,zhuangzhewei,zhoushuguang
│ │ └── openplatform
│ │ └── sug
│ │ └── Owner: changxuanran,xucheng
│ ├── common
│ │ └── openplatform
│ │ └── Owner: liuzhan,huangshancheng
│ ├── interface
│ │ ├── live
│ │ │ ├── Owner: liuzhen
│ │ │ └── push-live
│ │ │ └── Owner: kuangxibin
│ │ └── main
│ │ ├── account
│ │ │ └── Owner: wanghuan01,zhoujiahui,zhaogangtao,chenjianrong,zhoujixiang
│ │ ├── activity
│ │ │ └── Owner: liweijia
│ │ ├── answer
│ │ │ └── Owner: zhaogangtao
│ │ ├── app-channel
│ │ │ └── Owner: peiyifei
│ │ ├── app-feed
│ │ │ └── Owner: peiyifei
│ │ ├── app-interface
│ │ │ └── Owner: peiyifei
│ │ ├── app-player
│ │ │ └── Owner: peiyifei
│ │ ├── app-resource
│ │ │ └── Owner: peiyifei
│ │ ├── app-show
│ │ │ └── Owner: peiyifei
│ │ ├── app-tag
│ │ │ └── Owner: peiyifei
│ │ ├── app-view
│ │ │ └── Owner: peiyifei
│ │ ├── app-wall
│ │ │ └── Owner: peiyifei
│ │ ├── article
│ │ │ └── Owner: changxuanran,lijiadong,qiuliang
│ │ ├── broadcast
│ │ │ └── Owner: chenzhihui,caoguoliang,guhao
│ │ ├── captcha
│ │ │ └── Owner: chenzhihui
│ │ ├── creative
│ │ │ └── Owner: shencen,wangzhe01
│ │ ├── credit
│ │ │ └── Owner: zhaogangtao
│ │ ├── dm
│ │ │ └── Owner: liangkai,renwei
│ │ ├── dm2
│ │ │ └── Owner: liangkai,renwei
│ │ ├── esports
│ │ │ └── Owner: liweijia,zhapuyu
│ │ ├── favorite
│ │ │ └── Owner: chenzhihui,lujinhui
│ │ ├── feedback
│ │ │ └── Owner: peiyifei
│ │ ├── growup
│ │ │ └── Owner: gaopeng
│ │ ├── history
│ │ │ └── Owner: renwei,wangxu01
│ │ ├── kvo
│ │ │ └── Owner: liweijia,zhapuyu
│ │ ├── laser
│ │ │ └── Owner: haoguanwei,shencen
│ │ ├── player
│ │ │ └── Owner: liweijia,zhapuyu
│ │ ├── playlist
│ │ │ └── Owner: liweijia
│ │ ├── push
│ │ │ └── Owner: renwei,zhapuyu
│ │ ├── push-archive
│ │ │ └── Owner: zhapuyu,shencen,renwei,liweijia,wangzhe01
│ │ ├── reply
│ │ │ └── Owner: lujinhui,chenzhihui,caoguoliang
│ │ ├── report-click
│ │ │ └── Owner: zhangshengchao,chenzhihui,renyashun
│ │ ├── shorturl
│ │ │ └── Owner: peiyifei,zhapuyu
│ │ ├── space
│ │ │ └── Owner: liweijia,zhapuyu
│ │ ├── spread
│ │ │ └── Owner: zhapuyu,renwei
│ │ ├── tag
│ │ │ └── Owner: renwei,renyashun
│ │ ├── tv
│ │ │ └── Owner: renwei,liweijia
│ │ ├── upload
│ │ │ └── Owner: peiyifei,zhapuyu
│ │ ├── videoup
│ │ │ └── Owner: shencen,wangzhe01
│ │ ├── web
│ │ │ └── Owner: liweijia,zhapuyu
│ │ ├── web-feed
│ │ │ └── Owner: zhapuyu,liweijia,renwei
│ │ ├── web-goblin
│ │ │ └── Owner: liweijia,renwei
│ │ └── web-show
│ │ └── Owner: liweijia
│ ├── job
│ │ ├── live
│ │ │ ├── Owner: liuzhen
│ │ │ └── wallet
│ │ │ └── Owner: lixiang,zhouzhichao
│ │ ├── main
│ │ │ ├── account-notify
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── account-summary
│ │ │ │ └── Owner: zhoujiahui
│ │ │ ├── activity
│ │ │ │ └── Owner: liweijia
│ │ │ ├── answer
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── app
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── app-wall
│ │ │ │ └── Owner: peiyifei,renwei,haoguanwei
│ │ │ ├── archive
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── archive-kisjd
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── article
│ │ │ │ └── Owner: qiuliang,changxuanran,lijiadong
│ │ │ ├── block
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── broadcast
│ │ │ │ └── Owner: chenzhihui,caoguoliang,guhao
│ │ │ ├── click
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── coin
│ │ │ │ └── Owner: lintanghui,linmiao,zhapuyu
│ │ │ ├── coupon
│ │ │ │ └── Owner: zhaogangtao,yubaihai
│ │ │ ├── creative
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── credit
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── credit-timer
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── dm
│ │ │ │ └── Owner: liangkai,renwei
│ │ │ ├── dm2
│ │ │ │ └── Owner: liangkai,renwei
│ │ │ ├── favorite
│ │ │ │ └── Owner: lujinhui,chenzhihui
│ │ │ ├── feed
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── figure
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── figure-timer
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── growup
│ │ │ │ └── Owner: gaopeng
│ │ │ ├── history
│ │ │ │ └── Owner: renwei,wangxu01
│ │ │ ├── identify
│ │ │ │ └── Owner: linmiao,wanghuan01
│ │ │ ├── member
│ │ │ │ └── Owner: chenjianrong,zhoujiahui,linmiao,zhoujixiang
│ │ │ ├── passport
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-auth
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-encrypt
│ │ │ │ └── Owner: linmiao
│ │ │ ├── passport-game-cloud
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-game-data
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-game-local
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── playlist
│ │ │ │ └── Owner: liweijia
│ │ │ ├── point
│ │ │ │ └── Owner: yubaihai,zhaogangtao
│ │ │ ├── push
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── relation
│ │ │ │ └── Owner: linmiao,zhoujiahui
│ │ │ ├── reply
│ │ │ │ └── Owner: chenzhihui,lujinhui,caoguoliang
│ │ │ ├── search
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei,guanhuaxin
│ │ │ ├── sms
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── spy
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── stat
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── tag
│ │ │ │ └── Owner: renwei,renyashun
│ │ │ ├── tv
│ │ │ │ └── Owner: renwei,liweijia
│ │ │ ├── upload
│ │ │ │ └── Owner: zhapuyu,renwei,zhuangzhewei
│ │ │ ├── usersuit
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── videoup
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── videoup-report
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── vip
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── web-goblin
│ │ │ │ └── Owner: liweijia,renwei
│ │ │ └── workflow
│ │ │ └── Owner: haoguanwei,zhapuyu
│ │ └── openplatform
│ │ └── open-market
│ │ └── Owner: changxuanran,liuyan02,qiuliang
│ ├── service
│ │ ├── ep
│ │ │ └── saga-agent
│ │ │ └── Owner: muyang,tangyongqiang,fangrongchang
│ │ ├── live
│ │ │ ├── Owner: liuzhen
│ │ │ ├── userexp
│ │ │ │ └── Owner: kuangxibing
│ │ │ └── wallet
│ │ │ └── Owner: lixiang,zhouzhichao
│ │ ├── main
│ │ │ ├── account
│ │ │ │ └── Owner: wanghuan01,zhoujiahui
│ │ │ ├── antispam
│ │ │ │ └── Owner: chenzhihui,lujinhui
│ │ │ ├── archive
│ │ │ │ └── Owner: haoguanwei,peiyifei
│ │ │ ├── assist
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── block
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── bns
│ │ │ │ └── Owner: haoguawnei weicheng
│ │ │ ├── broadcast
│ │ │ │ └── Owner: chenzhihui,caoguoliang,guhao
│ │ │ ├── canal
│ │ │ │ └── Owner: haoguanwei
│ │ │ ├── coin
│ │ │ │ └── Owner: lintanghui,linmiao,zhapuyu
│ │ │ ├── config
│ │ │ │ └── Owner: maojian
│ │ │ ├── coupon
│ │ │ │ └── Owner: zhaogangtao,yubaihai
│ │ │ ├── dapper
│ │ │ │ └── Owner: maojian,haoguanwei
│ │ │ ├── databus
│ │ │ │ └── Owner: haoguanwei
│ │ │ ├── discovery
│ │ │ │ └── Owner: haoguanwei,lintanghui
│ │ │ ├── dynamic
│ │ │ │ └── Owner: liweijia,zhapuyu
│ │ │ ├── favorite
│ │ │ │ └── Owner: chenzhihui,lujinhui
│ │ │ ├── feed
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── figure
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── filter
│ │ │ │ └── Owner: zhaogangtao,muyang
│ │ │ ├── identify
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── identify-game
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── location
│ │ │ │ └── Owner: peiyifei,haoguanwei
│ │ │ ├── member
│ │ │ │ └── Owner: zhaogangtao,wanghuan01,zhoujiahui,chenjianrong,zhoujixiang
│ │ │ ├── msm
│ │ │ │ └── Owner: maojian
│ │ │ ├── notify
│ │ │ │ └── Owner: haoguanwei,lintanghui
│ │ │ ├── passport
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-auth
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── passport-game
│ │ │ │ └── Owner: wanghuan01
│ │ │ ├── point
│ │ │ │ └── Owner: yubaihai,zhaogangtao
│ │ │ ├── push
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── push-strategy
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── relation
│ │ │ │ └── Owner: linmiao,zhoujiahui
│ │ │ ├── resource
│ │ │ │ └── Owner: haoguanwei,peiyifei
│ │ │ ├── search
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei,guanhuaxin
│ │ │ ├── secure
│ │ │ │ └── Owner: zhaogangtao,lintanghui
│ │ │ ├── seq-server
│ │ │ │ └── Owner: peiyifei
│ │ │ ├── share
│ │ │ │ └── Owner: peiyifei,haoguanwei
│ │ │ ├── sms
│ │ │ │ └── Owner: renwei,zhapuyu
│ │ │ ├── spy
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── tag
│ │ │ │ └── Owner: renwei,renyashun
│ │ │ ├── thumbup
│ │ │ │ └── Owner: liweijia,zhapuyu,renwei
│ │ │ ├── up
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── upcredit
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── usersuit
│ │ │ │ └── Owner: zhaogangtao
│ │ │ ├── videoup
│ │ │ │ └── Owner: shencen,wangzhe01
│ │ │ ├── vip
│ │ │ │ └── Owner: lintanghui,zhaogangtao
│ │ │ └── workflow
│ │ │ └── Owner: haoguanwei,zhapuyu,zhoushuguang
│ │ └── openplatform
│ │ ├── abtest
│ │ │ └── Owner: lijiadong,qiuliang
│ │ ├── anti-fraud
│ │ │ └── Owner: wanglitao,wangminda,jiayanxiang
│ │ ├── ticket-item
│ │ │ └── Owner: yangyucheng
│ │ └── ticket-sales
│ │ └── Owner: liuzhan,yangyucheng
│ └── tool
│ ├── cache
│ │ └── Owner: zhapuyu
│ ├── ci
│ │ └── Owner: tangyongqiang
│ ├── creater
│ │ └── Owner: chenjianrong
│ ├── gdoc
│ │ └── Owner: lintanghui
│ ├── saga
│ │ └── Owner: muyang,tangyongqiang
│ └── warden
│ └── Owner: weicheng
└── library
├── cache
│ ├── memcache
│ │ └── Owner: maojian
│ └── redis
│ └── Owner: maojian
├── container
│ └── pool
│ └── Owner: zhapuyu
├── database
│ ├── elastic
│ │ └── Owner: haoguanwei,renwei,zhapuyu
│ └── sql
│ └── Owner:
├── ecode
│ ├── Owner: all
│ └── tip
│ └── Owner: all
├── exp
│ └── feature
│ └── Owner: zhoujiahui
├── log
│ └── Owner: maojian
├── naming
│ └── discovery
│ └── Owner: lintanghui,caoguoliang
├── net
│ ├── http
│ │ ├── Owner: maojian
│ │ └── blademaster
│ │ ├── Owner:
│ │ ├── middleware
│ │ │ ├── Owner:
│ │ │ ├── antispam
│ │ │ │ └── Owner:
│ │ │ ├── auth
│ │ │ │ └── Owner: maojian,zhoujiahui
│ │ │ ├── cache
│ │ │ │ └── Owner:
│ │ │ ├── identify
│ │ │ │ └── Owner:
│ │ │ ├── limit
│ │ │ │ └── aqm
│ │ │ │ └── Owner:
│ │ │ ├── proxy
│ │ │ │ └── Owner:
│ │ │ ├── rate
│ │ │ │ └── Owner:
│ │ │ ├── supervisor
│ │ │ │ └── Owner:
│ │ │ ├── tag
│ │ │ │ └── Owner: maojian
│ │ │ └── verify
│ │ │ └── Owner: maojian,zhoujiahui
│ │ └── render
│ │ └── Owner:
│ ├── metadata
│ │ └── Owner:
│ ├── netutil
│ │ └── breaker
│ │ └── Owner:
│ ├── rpc
│ │ └── warden
│ │ ├── Owner: maojian,caoguoliang
│ │ ├── balancer
│ │ │ └── wrr
│ │ │ └── Owner: caoguoliang
│ │ └── resolver
│ │ └── Owner: caoguoliang
│ └── trace
│ └── Owner: maojian
├── rate
│ └── limit
│ └── bench
│ └── stress
│ └── Owner: lintanghui
├── stat
│ └── sys
│ └── cpu
│ └── Owner: caoguoliang
└── sync
└── errgroup
└── Owner:
</code></pre>
</details>

1
WORKSPACE Normal file
View File

@ -0,0 +1 @@
build/root/WORKSPACE

23
app/BUILD Normal file
View File

@ -0,0 +1,23 @@
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:all-srcs",
"//app/common:all-srcs",
"//app/infra:all-srcs",
"//app/interface:all-srcs",
"//app/job:all-srcs",
"//app/service:all-srcs",
"//app/tool:all-srcs",
],
tags = ["automanaged"],
)

10
app/CONTRIBUTORS.md Normal file
View File

@ -0,0 +1,10 @@
# Owner
maojian
haoguanwei
renwei
# Author
all
# Reviewer
all

6
app/OWNERS Normal file
View File

@ -0,0 +1,6 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- haoguanwei
- maojian
- renwei

13
app/README.md Normal file
View File

@ -0,0 +1,13 @@
# go-common/business
业务仓库目录
| 目录 | 描述 |
| -------- | -------------- |
| service | rpc service |
| client | rpc client sdk |
| interface| gateway |
| admin | 运营管理服务 |
| job | 后台异步服务job|
| model | 业务实体model |
| ecode | 统一错误码 |

21
app/admin/BUILD Normal file
View File

@ -0,0 +1,21 @@
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/bbq:all-srcs",
"//app/admin/ep:all-srcs",
"//app/admin/live/live-admin:all-srcs",
"//app/admin/main:all-srcs",
"//app/admin/openplatform:all-srcs",
],
tags = ["automanaged"],
)

5
app/admin/OWNERS Normal file
View File

@ -0,0 +1,5 @@
# See the OWNERS docs at https://go.k8s.io/owners
labels:
- admin
- new-project

3
app/admin/README.md Normal file
View File

@ -0,0 +1,3 @@
# go-common/app/admin
运营管理服务

16
app/admin/bbq/BUILD Normal file
View File

@ -0,0 +1,16 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/bbq/comment:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

9
app/admin/bbq/OWNERS Normal file
View File

@ -0,0 +1,9 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- daiwei
labels:
- admin
- bbq
reviewers:
- daiwei

View File

@ -0,0 +1,20 @@
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [
":package-srcs",
"//app/admin/bbq/comment/cmd:all-srcs",
"//app/admin/bbq/comment/internal/dao:all-srcs",
"//app/admin/bbq/comment/internal/model:all-srcs",
"//app/admin/bbq/comment/internal/server/http:all-srcs",
"//app/admin/bbq/comment/internal/service:all-srcs",
],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1,2 @@
### v1.0.0
1. 上线功能xxx

View File

@ -0,0 +1,6 @@
# Owner
daiwei
# Author
# Reviewer

View File

@ -0,0 +1,10 @@
# See the OWNERS docs at https://go.k8s.io/owners
approvers:
- daiwei
labels:
- admin
- admin/bbq/comment
- bbq
options:
no_parent_owners: true

View File

@ -0,0 +1,12 @@
# comment-admin
## 项目简介
1.
## 编译环境
## 依赖包
## 编译执行

View File

@ -0,0 +1,42 @@
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"],
importpath = "go-common/app/admin/bbq/comment/cmd",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/bbq/comment/internal/server/http:go_default_library",
"//app/admin/bbq/comment/internal/service:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/ecode/tip:go_default_library",
"//library/log: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"],
)

View File

@ -0,0 +1,48 @@
package main
import (
"context"
"flag"
"os"
"os/signal"
"syscall"
"time"
"go-common/app/admin/bbq/comment/internal/server/http"
"go-common/app/admin/bbq/comment/internal/service"
"go-common/library/conf/paladin"
ecode "go-common/library/ecode/tip"
"go-common/library/log"
)
func main() {
flag.Parse()
if err := paladin.Init(); err != nil {
panic(err)
}
log.Init(nil) // debug flag: log.dir={path}
defer log.Close()
log.Info("comment-admin start")
ecode.Init(nil)
svc := service.New()
httpSrv := http.New(svc)
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
log.Info("get a signal %s", s.String())
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
ctx, cancel := context.WithTimeout(context.Background(), 35*time.Second)
defer cancel()
httpSrv.Shutdown(ctx)
log.Info("comment-admin exit")
svc.Close()
time.Sleep(time.Second)
return
case syscall.SIGHUP:
default:
return
}
}
}

View File

@ -0,0 +1,2 @@
# This is a TOML document. Boom

View File

View File

@ -0,0 +1,4 @@
[server]
addr = "0.0.0.0:8000"
timeout = "1s"

View File

@ -0,0 +1,13 @@
demoExpire = "24h"
[demo]
name = "comment"
proto = "tcp"
addr = "127.0.0.1:11211"
active = 50
idle = 10
dialTimeout = "100ms"
readTimeout = "200ms"
writeTimeout = "300ms"
idleTimeout = "80s"

View File

@ -0,0 +1,11 @@
[demo]
addr = "127.0.0.1:3306"
dsn = "{user}:{password}@tcp(127.0.0.1:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8"
readDSN = ["{user}:{password}@tcp(127.0.0.2:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8mb4,utf8","{user}:{password}@tcp(127.0.0.3:3306)/{database}?timeout=1s&readTimeout=1s&writeTimeout=1s&parseTime=true&loc=Local&charset=utf8,utf8mb4"]
active = 20
idle = 10
idleTimeout ="4h"
queryTimeout = "200ms"
execTimeout = "300ms"
tranTimeout = "400ms"

View File

@ -0,0 +1,13 @@
demoExpire = "24h"
[demo]
name = "comment"
proto = "tcp"
addr = "127.0.0.1:6389"
idle = 10
active = 10
dialTimeout = "1s"
readTimeout = "1s"
writeTimeout = "1s"
idleTimeout = "10s"

View 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 = ["dao.go"],
importpath = "go-common/app/admin/bbq/comment/internal/dao",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//library/cache/memcache:go_default_library",
"//library/cache/redis:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/database/sql:go_default_library",
"//library/log:go_default_library",
"//library/time: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"],
)

View File

@ -0,0 +1,95 @@
package dao
import (
"context"
"time"
"go-common/library/cache/memcache"
"go-common/library/cache/redis"
"go-common/library/conf/paladin"
"go-common/library/database/sql"
"go-common/library/log"
xtime "go-common/library/time"
)
// Dao dao.
type Dao struct {
db *sql.DB
redis *redis.Pool
redisExpire int32
mc *memcache.Pool
mcExpire int32
}
func checkErr(err error) {
if err != nil {
panic(err)
}
}
// New new a dao and return.
func New() (dao *Dao) {
var (
dc struct {
Demo *sql.Config
}
rc struct {
Demo *redis.Config
DemoExpire xtime.Duration
}
mc struct {
Demo *memcache.Config
DemoExpire xtime.Duration
}
)
checkErr(paladin.Get("mysql.toml").UnmarshalTOML(&dc))
checkErr(paladin.Get("redis.toml").UnmarshalTOML(&rc))
checkErr(paladin.Get("memcache.toml").UnmarshalTOML(&mc))
dao = &Dao{
// mysql
db: sql.NewMySQL(dc.Demo),
// redis
redis: redis.NewPool(rc.Demo),
redisExpire: int32(time.Duration(rc.DemoExpire) / time.Second),
// memcache
mc: memcache.NewPool(mc.Demo),
mcExpire: int32(time.Duration(mc.DemoExpire) / time.Second),
}
return
}
// Close close the resource.
func (d *Dao) Close() {
d.mc.Close()
d.redis.Close()
d.db.Close()
}
// Ping ping the resource.
func (d *Dao) Ping(ctx context.Context) (err error) {
if err = d.pingMC(ctx); err != nil {
return
}
if err = d.pingRedis(ctx); err != nil {
return
}
return d.db.Ping(ctx)
}
func (d *Dao) pingMC(ctx context.Context) (err error) {
conn := d.mc.Get(ctx)
defer conn.Close()
if err = conn.Set(&memcache.Item{Key: "ping", Value: []byte("pong"), Expiration: 0}); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}
func (d *Dao) pingRedis(ctx context.Context) (err error) {
conn := d.redis.Get(ctx)
defer conn.Close()
if _, err = conn.Do("SET", "ping", "pong"); err != nil {
log.Error("conn.Set(PING) error(%v)", err)
}
return
}

View File

@ -0,0 +1,28 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["model.go"],
importpath = "go-common/app/admin/bbq/comment/internal/model",
tags = ["automanaged"],
visibility = ["//visibility:public"],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)

View File

@ -0,0 +1 @@
package model

View File

@ -0,0 +1,35 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["http.go"],
importpath = "go-common/app/admin/bbq/comment/internal/server/http",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/bbq/comment/internal/service:go_default_library",
"//library/conf/paladin:go_default_library",
"//library/log:go_default_library",
"//library/net/http/blademaster:go_default_library",
"//library/net/http/blademaster/middleware/verify: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"],
)

View File

@ -0,0 +1,61 @@
package http
import (
"net/http"
"go-common/app/admin/bbq/comment/internal/service"
"go-common/library/conf/paladin"
"go-common/library/log"
bm "go-common/library/net/http/blademaster"
"go-common/library/net/http/blademaster/middleware/verify"
)
var (
svc *service.Service
)
// New new a bm server.
func New(s *service.Service) (engine *bm.Engine) {
var (
hc struct {
Server *bm.ServerConfig
}
)
if err := paladin.Get("http.toml").UnmarshalTOML(&hc); err != nil {
if err != paladin.ErrNotExist {
panic(err)
}
}
svc = s
engine = bm.DefaultServer(hc.Server)
initRouter(engine, verify.New(nil))
if err := engine.Start(); err != nil {
panic(err)
}
return
}
func initRouter(e *bm.Engine, v *verify.Verify) {
e.Ping(ping)
e.Register(register)
g := e.Group("/x/comment")
{
g.GET("/start", v.Verify, howToStart)
}
}
func ping(ctx *bm.Context) {
if err := svc.Ping(ctx); err != nil {
log.Error("ping error(%v)", err)
ctx.AbortWithStatus(http.StatusServiceUnavailable)
}
}
func register(c *bm.Context) {
c.JSON(map[string]interface{}{}, nil)
}
// example for http request handler.
func howToStart(c *bm.Context) {
c.String(0, "Golang 大法好 !!!")
}

View File

@ -0,0 +1,32 @@
package(default_visibility = ["//visibility:public"])
load(
"@io_bazel_rules_go//go:def.bzl",
"go_library",
)
go_library(
name = "go_default_library",
srcs = ["service.go"],
importpath = "go-common/app/admin/bbq/comment/internal/service",
tags = ["automanaged"],
visibility = ["//visibility:public"],
deps = [
"//app/admin/bbq/comment/internal/dao:go_default_library",
"//library/conf/paladin: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"],
)

View File

@ -0,0 +1,37 @@
package service
import (
"context"
"go-common/app/admin/bbq/comment/internal/dao"
"go-common/library/conf/paladin"
)
// Service service.
type Service struct {
ac *paladin.Map
dao *dao.Dao
}
// New new a service and return.
func New() (s *Service) {
var ac = new(paladin.TOML)
if err := paladin.Watch("application.toml", ac); err != nil {
panic(err)
}
s = &Service{
ac: ac,
dao: dao.New(),
}
return s
}
// Ping ping the resource.
func (s *Service) Ping(ctx context.Context) (err error) {
return s.dao.Ping(ctx)
}
// Close close the resource.
func (s *Service) Close() {
s.dao.Close()
}

21
app/admin/ep/BUILD Normal file
View File

@ -0,0 +1,21 @@
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:all-srcs",
"//app/admin/ep/melloi:all-srcs",
"//app/admin/ep/merlin:all-srcs",
"//app/admin/ep/saga:all-srcs",
"//app/admin/ep/tapd:all-srcs",
],
tags = ["automanaged"],
)

6
app/admin/ep/OWNERS Normal file
View File

@ -0,0 +1,6 @@
# See the OWNERS docs at https://go.k8s.io/owners
labels:
- admin
- ep
- new-project

22
app/admin/ep/marthe/BUILD Normal file
View 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"],
)

View File

@ -0,0 +1,4 @@
##### marthe
##### Version 1. 0. 1
1. 拉取bugly原始数据以自定义的格式落库

View File

@ -0,0 +1,14 @@
# Owner
maojian
yuanmin
fengyifeng
xuneng
# Author
yuanmin
fengyifeng
xuneng
# Reviewer
zhapuyu
wangxu01

View 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

View File

@ -0,0 +1,19 @@
# Marthe-service
# 项目简介
### 背景/Background
* 目前移动端crash信息会上报到buglybugly系统查询数据比较慢且没有足够的数据分析功能影响开发查询分析crash的效率
* 目前项目需求bug等信息记录在tapd, 同样tapd系统现有的报表功能并不满足我们PMO的需求使PMO拿不到充足的数据做分析
* 于是Marthe项目为了解决这些问题孕育而生
### 概览Overview
* Marthe会根据开发和测试的需求从bugly拉取原始数据并进行二次处理
# 编译环境
# 依赖包
# 编译执行

View 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"],
)

View 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"

View 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"

View 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
}
}
}

View 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"],
)

View 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
}

View 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",
],
)

View 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
}

View 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)
}
}

View 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()
}

View 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)
}
}
}

View 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
}

View 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)
})
}

View 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
}

View 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)
})
}

View 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
}

View 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)
})
}

View 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
}

View 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
}

View 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)
})
}

View 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
}

View 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)
}

View 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)
})
}

View 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
}

View File

@ -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)
})
}

View 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
}

View 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)
})
}

View 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
}

View 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)
})
}

View 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
}

View File

@ -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)
})
}

View 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)
}

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