master
luziqi 3 years ago
parent 69868b476a
commit 1090ed797a

@ -0,0 +1,53 @@
package common
import (
"errors"
"goqs/dbsql"
"goqs/models"
"strings"
"github.com/imroc/req/v3"
)
var ACCRSS_KEY = "muZd08g0_A4ucMCz"
func GetProduct(product_name string, pf string) (models.Product, error) {
var p models.Product
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
return p, err
}
defer dbsql.Close(db)
db.Model(models.Product{}).Where("name = ? AND platform = ?", product_name, pf).Last(&p)
if db.Error != nil {
return p, db.Error
}
return p, nil
}
func GetBranch(pkg_name string, pkg_url string) (ApkInfo, error) {
var _app ApkInfo
_strs := strings.Split(pkg_url, "/")
filename := _strs[len(_strs)-1]
var rsp RespGetApkInfo
client := req.C()
_, err := client.R().
SetSuccessResult(&rsp).
SetQueryParam("access_key", ACCRSS_KEY).
SetQueryParam("pkg_name", pkg_name).
SetQueryParam("pageIndex", "1").
SetQueryParam("pageSize", "200").
SetQueryParam("sortBy", "utime").
SetQueryParam("orderBy", "DESC").
Get("http://8.214.100.26:8048/api/app-version/get-apk-list")
if err != nil {
return _app, err
}
for _, v := range rsp.Data {
if v.Name == filename {
return v, nil
}
}
return _app, errors.New("没有匹配到对应的包信息")
}

@ -0,0 +1,52 @@
package common
type RespGetApkInfo struct {
IsSuccess bool `json:"isSuccess"`
Data []ApkInfo `json:"data"`
PageIndex int `json:"pageIndex"`
PageSize int `json:"pageSize"`
Total int `json:"total"`
Msg string `json:"msg"`
}
type ApkInfo struct {
ID int `json:"id"`
Name string `json:"name"`
PkgName string `json:"pkg_name"`
Version string `json:"version"`
Pf string `json:"pf"`
Title string `json:"title"`
Status int `json:"status"`
ChangeLog interface{} `json:"change_log"`
PromotionTitle interface{} `json:"promotion_title"`
PromotionBanner interface{} `json:"promotion_banner"`
Ctime int `json:"ctime"`
Utime int `json:"utime"`
BuildNum int `json:"build_num"`
AttachmentOld string `json:"attachment_old"`
AppLog interface{} `json:"app_log"`
Branch string `json:"branch"`
VirusLink string `json:"virus_link"`
Size string `json:"size"`
SizeLink string `json:"size_link"`
DefaultPub interface{} `json:"default_pub"`
Rabit interface{} `json:"rabit"`
ButtonAction int `json:"button_action"`
ButtonText string `json:"button_text"`
Offset int `json:"offset"`
Len int `json:"len"`
Md5 string `json:"md5"`
PkgType string `json:"pkg_type"`
PkgSubType string `json:"pkg_sub_type"`
HostVer interface{} `json:"host_ver"`
LastHostVer interface{} `json:"last_host_ver"`
SignVer int `json:"sign_ver"`
IsLite int `json:"is_lite"`
Attachment string `json:"attachment"`
VersionCode string `json:"version_code"`
Anm string `json:"anm"`
Extra string `json:"extra"`
OriginalApk string `json:"original_apk"`
Abi string `json:"abi"`
IsPressureTag int `json:"is_pressure_tag"`
}

@ -0,0 +1,34 @@
package common
import (
"errors"
"fmt"
"goqs/dbsql"
)
type notify struct {
ID int `json:"id" gorm:"column:id"`
Section string `json:"section" gorm:"column:section"`
Name string `json:"name" gorm:"column:name"`
Token string `json:"token" gorm:"column:token"`
Secret string `json:"secret" gorm:"column:secret"`
IsDel int `json:"-" gorm:"column:is_del"`
}
func (t *notify) TableName() string {
return "notify"
}
func GetNotifyConfig(section, name string) (notify, error) {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
fmt.Println(err)
}
defer dbsql.Close(db)
var n notify
db.Model(notify{}).Where("section = ? AND name = ?", section, name).Last(&n)
if n.ID < 1 {
return n, errors.New("没找到对应的通知设置")
}
return n, nil
}

@ -0,0 +1,63 @@
package common
import (
"goqs/models"
"github.com/blinkbean/dingtalk"
"github.com/spf13/cast"
)
var Bot_Test_Token = "945f845642387d947ebb55abe156907df4cffb806b52177560e2412f4bc7a9d8"
var Bot_Test_Secret = "SEC7baa286949c3a7f27f37bea78c5f08fbc408dfd21401a1afad3a2673e7f35be3"
var Bot_Hising_Token = "e1ba71d5060bf7cefc713153057aae4f6d192607162a636798b2de8abd705327"
var Bot_Hising_Secret = "SEC10cc28497ca0e60758da3953791886b57f913e0797418b3a902e057685bfedac"
// 钉钉推送
func PushDingTalk() {
//945f845642387d947ebb55abe156907df4cffb806b52177560e2412f4bc7a9d8
cli := dingtalk.InitDingTalkWithSecret("", "SEC7baa286949c3a7f27f37bea78c5f08fbc408dfd21401a1afad3a2673e7f35be3")
text_str := ""
cli.SendMarkDownMessage("Monkey执行结果", text_str)
// cli.SendLinkMessage("Monkey执行结果", "#### 看</b>一下啦", "", "http://qa.flatincbr.work/#/monkey/result/77")
// var btn dingtalk.ActionCardMultiBtnModel
// cli.SendActionCardMessage("Monkey执行结果", "看一下啦", dingtalk.WithCardSingleTitle("查看结果"), dingtalk.WithCardSingleURL("http://qa.flatincbr.work/#/monkey/result/77"))
// cli.SendTextMessage("test")
// push.SendActionCardMessage()
}
func PushCorntaskLog(str string) {
cli := dingtalk.InitDingTalkWithSecret(Bot_Test_Token, Bot_Test_Secret)
cli.SendMarkDownMessage("定时任务", str)
}
func PushMonkeyResult(task models.MonkeyTask) {
cli := dingtalk.InitDingTalkWithSecret(Bot_Test_Token, Bot_Test_Secret)
if task.Remark != "debug" {
if task.Project == "hising" {
cli = dingtalk.InitDingTalkWithSecret(Bot_Hising_Token, Bot_Hising_Secret)
}
}
text_str := "#### " + task.Project + " Monkey执行结果 \n "
if task.Platform == "adr" {
text_str += "##### **系统**Android \n "
}
if task.Platform == "ios" {
text_str += "##### **系统**iOS \n "
}
if task.Branch != "" {
text_str += "##### **分支**" + task.Branch + " \n "
}
if task.Version != "" {
text_str += "##### **版本**" + task.Version + " \n "
}
text_str += "##### **崩溃数**" + cast.ToString(task.CrashCount) + " \n "
text_str += "##### [查看结果](http://qa.flatincbr.work/#/monkey/result/" + cast.ToString(task.Id) + ")"
cli.SendMarkDownMessage("Monkey执行结果", text_str)
}

@ -0,0 +1,125 @@
package crontask
import (
"fmt"
"goqs/common"
"goqs/dbsql"
"goqs/models"
"goqs/monkey"
"os/exec"
"strings"
"github.com/robfig/cron/v3"
"github.com/spf13/cast"
)
func Run() {
crontab := cron.New(cron.WithSeconds())
crontab.AddFunc("0 */1 * * * ?", CheckAndroidDevices)
// crontab.AddFunc("0 */1 * * * ?", CheckTaskStatus)
crontab.AddFunc("*/15 * * * * ?", CheckMonkeyTasks)
// crontab.AddFunc("*/10 * * * * ?", GetBugStatusDaily) */1 * * * *
crontab.Start()
fmt.Println("[Crontab] 定时任务启动")
}
func CheckAndroidDevices() {
// fmt.Println("[Crontab] 检查安卓设备")
command := `devices` // | grep product.marketname'
cmd := exec.Command("adb", command)
out, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(err)
}
strs := strings.Split(string(out), "\n")
device := make(map[string]string)
for i, v := range strs {
if i == 0 || len(v) < 4 {
continue
}
_strs := strings.Split(v, "\t")
device[_strs[0]] = _strs[1]
}
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
fmt.Println("[Crontab] 数据库连接失败")
return
}
defer dbsql.Close(db)
var list []models.Device
db.Model(models.Device{}).Where("is_del = 0").Find(&list)
for _, v := range list {
if vv, ok := device[v.Udid]; ok {
// 数据表中的设备adb有获取到
switch v.Status {
case "busy":
continue
case "unauthorized":
if strings.Contains(vv, "device") {
db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "online")
fmt.Println("设备", v.Udid, "已连接")
}
case "offline":
if strings.Contains(vv, "device") {
db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "online")
fmt.Println("设备", v.Udid, "已连接")
} else {
db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "unauthorized")
fmt.Println("设备", v.Udid, "已连接但未认证")
}
case "online":
monkey.KeepDevice(v.Udid)
}
} else {
// 数据表中的设备adb没有获取到视为离线
if v.Status != "offline" {
db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "offline")
fmt.Println("设备", v.Udid, "已离线")
}
}
}
}
func CheckTaskStatus() {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
fmt.Println("[Crontab] 数据库连接失败")
return
}
defer dbsql.Close(db)
var list []models.MonkeyTask
db.Model(models.MonkeyTask{}).Where("status = ?", "RUNNING").Find(&list)
for i, v := range list {
var count int64
db.Model(models.MonkeyActivity{}).Where("task_id = ?", list[i].Id).Count(&count)
list[i].CoveredAcitvities = int(count)
var pids []models.MonkeyPid
db.Model(models.MonkeyPid{}).Where("task_id = ?", v.Id).Find(&pids)
if code := checkTaskPids(pids); code != 0 {
list[i].Status = "FINISH"
db.Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("status", list[i].Status)
common.PushMonkeyResult(v)
}
}
}
func checkTaskPids(pids []models.MonkeyPid) int {
if len(pids) == 0 {
return -1
}
var strs []string
for _, v := range pids {
strs = append(strs, cast.ToString(v.PId))
}
pids_str := strings.Join(strs, "|")
cmd_str := "ps -ef | grep -v -E 'bash|grep' | grep -E '" + pids_str + "'"
fmt.Println(cmd_str)
cmd := exec.Command("bash", "-c", cmd_str)
cmd.Run()
return cmd.ProcessState.ExitCode()
}

@ -0,0 +1,30 @@
package crontask
import (
"goqs/common"
"goqs/dbsql"
"goqs/models"
"goqs/monkey"
)
func CheckMonkeyTasks() {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
return
}
defer dbsql.Close(db)
var list []models.MonkeyTask
db.Model(models.MonkeyTask{}).Where("status = ? AND is_del = 0", "WAITTING").Find(&list)
for _, task := range list {
var device models.Device
db.Table("device").Model(models.Device{}).Where("project = ? AND status = ?", task.Project, "online").First(&device)
if device.ID < 1 {
// 没有空闲设备
continue
}
go monkey.RunAndroidMonkeyCmd(task, device.Udid)
common.PushCorntaskLog("执行Monkey任务" + task.Project + "-" + device.Udid)
}
}

@ -258,3 +258,40 @@ func DeleteDevice(c *gin.Context) {
rsp.Success()
c.JSON(http.StatusOK, rsp)
}
// @Tags 设备管理 /api/device/v1/
// @Summary 更新设备状态
// @Description 更新设备状态,错误的状态会被拒绝
// @accept x-www-form-urlencoded
// @Param udid formData string true "设备udid"
// @Param status formData string true "要更新的设备状态online-在线空闲busy-占用中offline-离线"
// @Success 200 {object} models.Response "返回更新的状态"
// @Router /api/device/v1/update_status [post]
func UpdateDeviceStatus(c *gin.Context) {
rsp := controllers.NewResponse()
if c.PostForm("udid") == "" {
rsp.Error("参数udid错误" + c.PostForm("udid"))
c.JSON(http.StatusOK, rsp)
return
}
if c.PostForm("status") != "offline" && c.PostForm("status") != "online" && c.PostForm("status") != "busy" {
rsp.Error("参数status错误" + c.PostForm("status"))
c.JSON(http.StatusOK, rsp)
return
}
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
}
defer dbsql.Close(db)
db.Model(models.Device{}).Where("udid = ?", c.PostForm("udid")).Update("status", c.PostForm("status"))
rsp.Success()
rsp.Data = c.PostForm("udid")
c.JSON(http.StatusOK, rsp)
}

@ -243,6 +243,42 @@ var doc = `{
}
}
},
"/api/device/v1/update_status": {
"post": {
"description": "更新设备状态,错误的状态会被拒绝",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"设备管理 /api/device/v1/"
],
"summary": "更新设备状态",
"parameters": [
{
"type": "string",
"description": "设备udid",
"name": "udid",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "要更新的设备状态online-在线空闲busy-占用中offline-离线",
"name": "status",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "返回更新的状态",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/monkey/v1/create_task": {
"post": {
"description": "新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中",
@ -621,7 +657,7 @@ var doc = `{
},
"/api/monkey/v1/task/status": {
"post": {
"description": "更新Monkey任务状态进行中为RUNNING已完成为FINIASHED如有错误为ERROR",
"description": "更新Monkey任务状态进行中为RUNNING已完成为FINISH如有错误为ERROR",
"consumes": [
"application/x-www-form-urlencoded"
],
@ -753,6 +789,128 @@ var doc = `{
}
}
},
"/api/monkey/v2/create_task": {
"post": {
"description": "新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"Monkey相关 /api/monkey/v2/"
],
"summary": "新建Monkey任务",
"parameters": [
{
"type": "string",
"description": "项目名",
"name": "project",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "产品名",
"name": "product",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "应用包名",
"name": "package_name",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "测试包下载链接",
"name": "package_url",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "平台adr/ios",
"name": "platform",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "运行时间s默认两小时3600s",
"name": "run_time",
"in": "formData"
},
{
"type": "string",
"description": "安卓启动页名称",
"name": "launch_activity",
"in": "formData"
},
{
"type": "string",
"description": "任务创建者",
"name": "creator",
"in": "formData"
},
{
"type": "string",
"description": "启动来源web-平台启动ci-持续集成",
"name": "referer",
"in": "formData"
},
{
"type": "string",
"description": "调用服务的方式0-cli模式/1-api模式默认cli",
"name": "mode",
"in": "formData"
},
{
"type": "string",
"description": "备注",
"name": "remark",
"in": "formData"
}
],
"responses": {
"200": {
"description": "返回创建的任务id",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/project/v1/app": {
"get": {
"description": "根据应用名称app_name获取应用信息",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"Monkey相关 /api/project/v1/"
],
"summary": "获取应用信息",
"parameters": [
{
"type": "string",
"description": "应用名称",
"name": "app_name",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "返回任务结果",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/webdav/monkey/task/:id/:filename": {
"put": {
"description": "上传Logcat日志",

@ -224,6 +224,42 @@
}
}
},
"/api/device/v1/update_status": {
"post": {
"description": "更新设备状态,错误的状态会被拒绝",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"设备管理 /api/device/v1/"
],
"summary": "更新设备状态",
"parameters": [
{
"type": "string",
"description": "设备udid",
"name": "udid",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "要更新的设备状态online-在线空闲busy-占用中offline-离线",
"name": "status",
"in": "formData",
"required": true
}
],
"responses": {
"200": {
"description": "返回更新的状态",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/monkey/v1/create_task": {
"post": {
"description": "新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中",
@ -602,7 +638,7 @@
},
"/api/monkey/v1/task/status": {
"post": {
"description": "更新Monkey任务状态进行中为RUNNING已完成为FINIASHED如有错误为ERROR",
"description": "更新Monkey任务状态进行中为RUNNING已完成为FINISH如有错误为ERROR",
"consumes": [
"application/x-www-form-urlencoded"
],
@ -734,6 +770,128 @@
}
}
},
"/api/monkey/v2/create_task": {
"post": {
"description": "新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"Monkey相关 /api/monkey/v2/"
],
"summary": "新建Monkey任务",
"parameters": [
{
"type": "string",
"description": "项目名",
"name": "project",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "产品名",
"name": "product",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "应用包名",
"name": "package_name",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "测试包下载链接",
"name": "package_url",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "平台adr/ios",
"name": "platform",
"in": "formData",
"required": true
},
{
"type": "string",
"description": "运行时间s默认两小时3600s",
"name": "run_time",
"in": "formData"
},
{
"type": "string",
"description": "安卓启动页名称",
"name": "launch_activity",
"in": "formData"
},
{
"type": "string",
"description": "任务创建者",
"name": "creator",
"in": "formData"
},
{
"type": "string",
"description": "启动来源web-平台启动ci-持续集成",
"name": "referer",
"in": "formData"
},
{
"type": "string",
"description": "调用服务的方式0-cli模式/1-api模式默认cli",
"name": "mode",
"in": "formData"
},
{
"type": "string",
"description": "备注",
"name": "remark",
"in": "formData"
}
],
"responses": {
"200": {
"description": "返回创建的任务id",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/api/project/v1/app": {
"get": {
"description": "根据应用名称app_name获取应用信息",
"consumes": [
"application/x-www-form-urlencoded"
],
"tags": [
"Monkey相关 /api/project/v1/"
],
"summary": "获取应用信息",
"parameters": [
{
"type": "string",
"description": "应用名称",
"name": "app_name",
"in": "query",
"required": true
}
],
"responses": {
"200": {
"description": "返回任务结果",
"schema": {
"$ref": "#/definitions/models.Response"
}
}
}
}
},
"/webdav/monkey/task/:id/:filename": {
"put": {
"description": "上传Logcat日志",

@ -156,6 +156,30 @@ paths:
summary: 更新设备
tags:
- 设备相关 /api/device/v1/
/api/device/v1/update_status:
post:
consumes:
- application/x-www-form-urlencoded
description: 更新设备状态,错误的状态会被拒绝
parameters:
- description: 设备udid
in: formData
name: udid
required: true
type: string
- description: 要更新的设备状态online-在线空闲busy-占用中offline-离线
in: formData
name: status
required: true
type: string
responses:
"200":
description: 返回更新的状态
schema:
$ref: '#/definitions/models.Response'
summary: 更新设备状态
tags:
- 设备管理 /api/device/v1/
/api/monkey/v1/create_task:
post:
consumes:
@ -408,7 +432,7 @@ paths:
post:
consumes:
- application/x-www-form-urlencoded
description: 更新Monkey任务状态进行中为RUNNING已完成为FINIASHED如有错误为ERROR
description: 更新Monkey任务状态进行中为RUNNING已完成为FINISH如有错误为ERROR
parameters:
- description: 任务id
in: formData
@ -492,6 +516,88 @@ paths:
summary: 获取任务列表
tags:
- Monkey相关 /api/monkey/v1/
/api/monkey/v2/create_task:
post:
consumes:
- application/x-www-form-urlencoded
description: 新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中
parameters:
- description: 项目名
in: formData
name: project
required: true
type: string
- description: 产品名
in: formData
name: product
required: true
type: string
- description: 应用包名
in: formData
name: package_name
required: true
type: string
- description: 测试包下载链接
in: formData
name: package_url
required: true
type: string
- description: 平台adr/ios
in: formData
name: platform
required: true
type: string
- description: 运行时间s默认两小时3600s
in: formData
name: run_time
type: string
- description: 安卓启动页名称
in: formData
name: launch_activity
type: string
- description: 任务创建者
in: formData
name: creator
type: string
- description: 启动来源web-平台启动ci-持续集成
in: formData
name: referer
type: string
- description: 调用服务的方式0-cli模式/1-api模式默认cli
in: formData
name: mode
type: string
- description: 备注
in: formData
name: remark
type: string
responses:
"200":
description: 返回创建的任务id
schema:
$ref: '#/definitions/models.Response'
summary: 新建Monkey任务
tags:
- Monkey相关 /api/monkey/v2/
/api/project/v1/app:
get:
consumes:
- application/x-www-form-urlencoded
description: 根据应用名称app_name获取应用信息
parameters:
- description: 应用名称
in: query
name: app_name
required: true
type: string
responses:
"200":
description: 返回任务结果
schema:
$ref: '#/definitions/models.Response'
summary: 获取应用信息
tags:
- Monkey相关 /api/project/v1/
/webdav/monkey/task/:id/:filename:
put:
consumes:

@ -6,7 +6,16 @@ require (
github.com/KyleBanks/depth v1.2.1 // indirect
github.com/PuerkitoBio/purell v1.1.1 // indirect
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/blinkbean/dingtalk v0.0.0-20210905093040-7d935c0f7e19 // indirect
github.com/bxcodec/faker/v3 v3.8.1 // indirect
github.com/clipperhouse/fsnotify v1.1.0 // indirect
github.com/clipperhouse/gen v4.1.1+incompatible // indirect
github.com/clipperhouse/slice v0.0.0-20200107170738-a74fc3888fd9 // indirect
github.com/clipperhouse/typewriter v0.0.0-20200107164453-d21420026310 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/denisenkom/go-mssqldb v0.12.3 // indirect
github.com/droundy/goopt v0.0.0-20220217183150-48d6390ad4d1 // indirect
github.com/ghodss/yaml v1.0.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/gin-gonic/gin v1.8.1 // indirect
@ -17,21 +26,52 @@ require (
github.com/go-playground/locales v0.14.0 // indirect
github.com/go-playground/universal-translator v0.18.0 // indirect
github.com/go-playground/validator/v10 v10.10.0 // indirect
github.com/go-sql-driver/mysql v1.6.0 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
github.com/gobuffalo/logger v1.0.7 // indirect
github.com/gobuffalo/packd v1.0.2 // indirect
github.com/gobuffalo/packr/v2 v2.8.3 // indirect
github.com/goccy/go-json v0.9.7 // indirect
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 // indirect
github.com/golang-sql/sqlexp v0.1.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/hashicorp/errwrap v1.1.0 // indirect
github.com/hashicorp/go-multierror v1.1.1 // indirect
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/imroc/req/v3 v3.32.3 // indirect
github.com/jimsmart/schema v0.2.1 // indirect
github.com/jinzhu/gorm v1.9.16 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/karrick/godirwalk v1.17.0 // indirect
github.com/leodido/go-urn v1.2.1 // indirect
github.com/lib/pq v1.10.7 // indirect
github.com/logrusorgru/aurora v2.0.3+incompatible // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/markbates/errx v1.1.0 // indirect
github.com/markbates/oncer v1.0.0 // indirect
github.com/markbates/safe v1.0.1 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/ompluscator/dynamic-struct v1.4.0 // indirect
github.com/onsi/ginkgo/v2 v2.6.1 // indirect
github.com/pelletier/go-toml/v2 v2.0.1 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-18 v0.2.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.0 // indirect
github.com/quic-go/qtls-go1-20 v0.1.0 // indirect
github.com/quic-go/quic-go v0.32.0 // indirect
github.com/robfig/cron/v3 v3.0.1 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e // indirect
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
github.com/sirupsen/logrus v1.9.0 // indirect
github.com/smallnest/gen v0.9.29 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/swaggo/files v0.0.0-20220728132757-551d4a08d97a // indirect
github.com/swaggo/gin-swagger v1.5.2 // indirect
@ -40,12 +80,15 @@ require (
github.com/urfave/cli/v2 v2.11.2 // indirect
github.com/wonderivan/logger v1.0.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 // indirect
golang.org/x/net v0.0.0-20220812174116-3211cb980234 // indirect
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab // indirect
golang.org/x/text v0.3.7 // indirect
golang.org/x/tools v0.1.12 // indirect
google.golang.org/protobuf v1.28.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect
golang.org/x/mod v0.9.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/term v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/tools v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.3.6 // indirect

855
go.sum

File diff suppressed because it is too large Load Diff

@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"goqs/controllers"
"goqs/crontask"
"goqs/dbsql"
"goqs/device"
"goqs/env"
@ -27,6 +28,7 @@ func init() {
}
func main() {
go crontask.Run()
env.InitDB()
log.SetLevel(log.DebugLevel)
@ -70,6 +72,8 @@ func main() {
r.GET("/api/monkey/v1/devices", monkey.GetDevices)
r.POST("/api/monkey/v1/task/crash_count", monkey.UpdateTaskCrashCount)
r.PUT("/webdav/monkey/task/:id/:filename", monkey.TaskReport)
// monkey v2
r.POST("/api/monkey/v2/create_task", monkey.CreateTaskV2)
// device
r.GET("/api/device/v1/list", device.GetDevices)
@ -77,6 +81,7 @@ func main() {
r.POST("/api/device/v1/create", device.CreateDevice)
r.POST("/api/device/v1/update", device.UpdateDevice)
r.DELETE("/api/device/v1/delete/:id", device.DeleteDevice)
r.POST("/api/device/v1/update_status", device.UpdateDeviceStatus)
r.Run(port)

@ -0,0 +1,18 @@
package models
type App struct {
Id int `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"`
AppName string `json:"app_name" gorm:"column:app_name"`
Project string `json:"project" gorm:"column:project;type:varchar(255);not null;comment:项目名"`
Product string `json:"product" gorm:"column:product"`
PackageName string `json:"package_name" gorm:"column:package_name;type:varchar(255);not null;comment:应用包名"`
LaunchActivity string `json:"launch_activity" gorm:"column:launch_activity;type:varchar(255);comment:启动Activity页"`
Platform string `json:"platform" gorm:"column:platform"`
CreateTime int `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"`
UpdateTime int `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"`
IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"`
}
func (t *App) TableName() string {
return "app"
}

@ -4,10 +4,10 @@ import "goqs/global"
type AppPage struct {
global.MODEL
PkgName string `json:"pkg_name" gorm:"column:pkg_name;type:varchar(255);not null;comment:应用包名"`
Product string `json:"product" gorm:"column:product;type:varchar(255);not null;comment:产品名"`
PageName string `json:"page_name" gorm:"column:page_name;type:varchar(255);not null;comment:应用页面名称"`
Pf string `json:"pf" gorm:"column:pf;type:varchar(255);not null;comment:应用包名"`
Count int `json:"count" gorm:"column:is_del;type:int(13);not null;comment:计数"`
Count int `json:"count" gorm:"column:count;type:int(13);not null;comment:计数"`
}
func (t *AppPage) TableName() string {

@ -1,10 +1,15 @@
package models
import "errors"
type MonkeyTask struct {
Id int `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"`
Project string `json:"project" gorm:"column:project;type:varchar(255);not null;comment:项目名"`
PackageURL string `json:"package_url" gorm:"column:package_url;type:varchar(255);not null;comment:应用包下载链接"`
Product string `json:"product" gorm:"column:product;type:varchar(255);not null;comment:产品名"`
PackageName string `json:"package_name" gorm:"column:package_name;type:varchar(255);not null;comment:应用包名"`
PackageURL string `json:"package_url" gorm:"column:package_url;type:varchar(255);not null;comment:应用包下载链接"`
Branch string `json:"branch" gorm:"column:branch"`
Version string `json:"version" gorm:"column:version"`
LaunchActivity string `json:"launch_activity" gorm:"column:launch_activity;type:varchar(255);comment:启动Activity页"`
Devices string `json:"devices" gorm:"column:devices;type:varchar(255);comment:存放设备udid"`
RunTime int `json:"run_time" gorm:"column:run_time;type:int(11);not null;comment:运行时间(秒)"`
@ -13,7 +18,9 @@ type MonkeyTask struct {
CoveredAcitvities int `json:"covered_activities" gorm:"-"`
CrashCount int `json:"crash_count" gorm:"column:crash_count;type:int(11);not null;comment:崩溃次数"`
Creator string `json:"creator" gorm:"column:creator;type:varchar(255);comment:创建人"`
Referer string `json:"referer" gorm:"column:referer;type:varchar(255);not null;comment:调用方"`
Status string `json:"status" gorm:"column:status;type:varchar(255);not null;comment:运行状态"`
Remark string `json:"remark" gorm:"column:remark;type:varchar(255);not null;comment:备注"`
CreateTime int `json:"create_time" gorm:"column:create_time;type:int(11);not null;autoCreateTime;comment:创建时间"`
UpdateTime int `json:"update_time" gorm:"column:update_time;type:int(11);not null;autoUpdateTime;comment:更新时间"`
IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"`
@ -22,3 +29,31 @@ type MonkeyTask struct {
func (m *MonkeyTask) TableName() string {
return "monkey_task"
}
func (t *MonkeyTask) Check() error {
if t.Project == "" {
return errors.New("task.Project为空")
}
if t.Product == "" {
return errors.New("task.Product为空")
}
if t.PackageName == "" {
return errors.New("task.PackageName为空")
}
if t.Branch == "" {
return errors.New("task.Branch为空")
}
if t.Version == "" {
return errors.New("task.Version为空")
}
if t.Platform == "" {
return errors.New("task.Platform为空")
}
if t.LaunchActivity == "" && t.Platform == "adr" {
return errors.New("task.LaunchActivity为空platform=adr时需要传入LaunchActivity参数")
}
if t.PackageURL == "" {
return errors.New("task.PackageURL为空")
}
return nil
}

@ -0,0 +1,20 @@
package models
import "time"
type Product struct {
Id int `json:"id" gorm:"column:id;type:int(11);primary_key;not null;autoIncrement;comment:主键"`
ProjectId int `json:"product_id" gorm:"column:product_id"`
ProductLine string `json:"product_line" gorm:"column:product_line"`
Name string `json:"name" gorm:"column:name"`
PackageName string `json:"package_name" gorm:"column:package_name;type:varchar(255);not null;comment:应用包名"`
LaunchActivity string `json:"launch_activity" gorm:"column:launch_activity;type:varchar(255);comment:启动Activity页"`
Platform string `json:"platform" gorm:"column:platform"`
CreateTime time.Time `json:"create_time" gorm:"column:create_time;not null;autoCreateTime;comment:创建时间"`
UpdateTime time.Time `json:"update_time" gorm:"column:update_time;not null;autoUpdateTime;comment:更新时间"`
IsDel int `json:"is_del" gorm:"column:is_del;type:int(1);not null;comment:是否已删除"`
}
func (t *Product) TableName() string {
return "products"
}

@ -53,6 +53,13 @@ func UpdataActivity(c *gin.Context) {
return
}
task, err := getTaskById(res.TaskId, db)
var p models.AppPage
p.Product = task.Product
p.PageName = res.ActivityName
p.Pf = task.Platform
countPage(p, db)
rsp.Success()
rsp.Data = res
c.JSON(http.StatusOK, rsp)

@ -1,84 +1,28 @@
package monkey
import (
"goqs/controllers"
"goqs/dbsql"
"goqs/models"
"net/http"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"gorm.io/gorm"
)
// @Tags Monkey相关 /api/monkey/v1/
// @Summary 上报Monkey应用页
// @Description Android上报activity名
// @accept x-www-form-urlencoded
// @Param task_id formData int true "任务id"
// @Param device_name formData string false "设备id"
// @Param activity_name formData string false "页面名称"
// @Success 200 {object} models.Response "返回更新后的任务信息"
// @Router /api/monkey/v1/task/activity [post]
func UploadPage(c *gin.Context) {
rsp := controllers.NewResponse()
var res models.MonkeyActivity
res.TaskId = cast.ToInt(c.PostForm("task_id"))
if res.TaskId < 1 {
rsp.Error("task_id error:" + c.PostForm("task_id"))
c.JSON(http.StatusOK, rsp)
}
res.DeviceName = c.PostForm("device_name")
if res.DeviceName == "" {
rsp.Error("device_name不能为空")
c.JSON(http.StatusOK, rsp)
}
res.ActivityName = c.PostForm("activity_name")
if res.ActivityName == "" {
rsp.Error("activity_name不能为空")
c.JSON(http.StatusOK, rsp)
}
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
func countPage(p models.AppPage, db *gorm.DB) error {
if db == nil {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
return err
}
defer dbsql.Close(db)
}
defer dbsql.Close(db)
db.Create(&res)
if res.ID < 1 {
rsp.Error("记录activity应用页失败")
c.JSON(http.StatusOK, rsp)
return
}
rsp.Success()
rsp.Data = res
c.JSON(http.StatusOK, rsp)
}
// @Tags Monkey相关 /api/monkey/v1/
// @Summary 获取覆盖页面列表
// @Description 通过monkey任务id获取覆盖的活动页面
// @accept x-www-form-urlencoded
// @Param task_id query int true "任务id"
// @Success 200 {object} models.Response "返回任务覆盖的活动页"
// @Router /api/monkey/v1/task/activity [get]
func GetPages(c *gin.Context) {
rsp := controllers.NewResponse()
var list []models.MonkeyActivity
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
db.Table(p.TableName()).Model(models.AppPage{}).Where("product = ? AND page_name = ?", p.Product, p.PageName).Last(&p)
if p.ID == 0 {
p.Count = 1
db.Create(&p)
return nil
}
defer dbsql.Close(db)
db.Where("task_id = ?", c.Query("task_id")).Find(&list)
p.Count += 1
db.Where("id = ?", p.ID).Update("count", p.Count)
rsp.Success()
rsp.Data = list
c.JSON(http.StatusOK, rsp)
return nil
}

@ -2,6 +2,8 @@ package monkey
import (
"fmt"
"goqs/common"
"goqs/dbsql"
"goqs/models"
"os/exec"
"strings"
@ -15,9 +17,15 @@ import (
// cmd_content := "adb " +
// }
func runAndroidMonkeyCmd(task models.MonkeyTask) {
cmd_content := "cd /home/app/aimonkey && nohup python3 main_run.py" +
func RunAndroidMonkeyCmd(task models.MonkeyTask, udid string) {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
return
}
defer dbsql.Close(db)
db.Model(models.MonkeyTask{}).Where("id = ?", task.Id).Update("status", "INIT")
// python main_adr.py -package music.hising.live.dev -launch_activity sing.lagufun.social.live.ui.activity.SplashActivity
cmd_content := "cd /home/app/monkey && nohup python3 main_adr.py" +
" -task_id " + cast.ToString(task.Id)
if task.PackageURL != "" {
pkg_path := "/home/tmp/pkg/" + cast.ToString(time.Now().Unix()) + ".apk"
@ -29,15 +37,23 @@ func runAndroidMonkeyCmd(task models.MonkeyTask) {
cmd_content += " -pkg_path " + pkg_path
log.Debug("下载完毕,安装包路径", pkg_path)
}
cmd_content += " -package " + task.PackageName +
" -activity " + task.LaunchActivity +
" -time " + cast.ToString(task.RunTime) +
" >> /home/app/logs/task_output/task_" + cast.ToString(task.Id) + ".log 2>&1"
cmd_content += " -package " + task.PackageName
cmd_content += " -launch_activity " + task.LaunchActivity
cmd_content += " -run_time " + cast.ToString(task.RunTime)
if udid != "" {
cmd_content += " -device_udid " + udid
}
cmd_content += " >> /home/app/logs/task_output/task_" + cast.ToString(task.Id) + ".log 2>&1"
log.Debug("开始调用monkey服务")
db.Model(models.MonkeyTask{}).Where("id = ?", task.Id).Last(&task)
if task.Status != "INIT" {
common.PushCorntaskLog("任务状态异常停止发起Monkey任务" + task.Status)
return
}
log.Debug("开始调用monkey服务执行命令")
log.Debug(cmd_content)
cmd := exec.Command("bash", "-c", cmd_content)
err := cmd.Run()
err = cmd.Run()
if err != nil {
log.Error(err)
}
@ -104,6 +120,13 @@ func getAndroidDeviceName(udid string) string {
return device_name
}
func KeepDevice(udid string) error {
//adb shell input keyevent 3
cmd := exec.Command("adb", "-s", udid, "shell", "input", "keyevent", "4")
err := cmd.Run()
return err
}
func killPid(pid int) error {
cmd := exec.Command("kill", "-9", cast.ToString(pid))
err := cmd.Run()

@ -2,6 +2,7 @@ package monkey
import (
"fmt"
"goqs/common"
"goqs/controllers"
"goqs/dbsql"
"goqs/models"
@ -88,12 +89,12 @@ func CreateTask(c *gin.Context) {
rsp.Data = task
c.JSON(http.StatusOK, rsp)
go runAndroidMonkeyCmd(task)
go RunAndroidMonkeyCmd(task, "")
}
// @Tags Monkey相关 /api/monkey/v1/
// @Summary 更新Monkey任务状态
// @Description 更新Monkey任务状态进行中为RUNNING已完成为FINIASHED如有错误为ERROR
// @Description 更新Monkey任务状态进行中为RUNNING已完成为FINISH如有错误为ERROR
// @accept x-www-form-urlencoded
// @Param task_id formData int true "任务id"
// @Param status formData string false "要更新的任务状态"
@ -128,6 +129,10 @@ func UpdateTaskStatus(c *gin.Context) {
task.Status = status
db.Save(&task)
if status == "FINISH" {
common.PushMonkeyResult(task)
}
rsp.Success()
rsp.Data = task
c.JSON(http.StatusOK, rsp)
@ -429,9 +434,30 @@ func StopMonkeyTask(c *gin.Context) {
return
}
defer dbsql.Close(db)
var task models.MonkeyTask
db.Model(models.MonkeyTask{}).Where("id = ?", task_id).First(&task)
// 如果monkey任务未开始(status=WAITTING,INIT)直接更新状态为CANCEL
if task.Status == "WAITTING" || task.Status == "INIT" {
db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("status", "CANCEL")
rsp.Success()
rsp.Data = "from " + task.Status + " to CANCEL"
c.JSON(http.StatusOK, rsp)
return
}
db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("status", "CANCELING")
// 更新设备状态
db.Model(models.MonkeyTask{}).Where("id = ?", task_id).Last(&task)
if strings.Contains(task.Devices, ",") {
} else {
var device models.Device
db.Table("device").Model(models.Device{}).Where("udid = ?", task.Devices).Last(&device)
if device.Status == "busy" {
db.Table("device").Model(models.Device{}).Where("udid = ?", task.Devices).Update("status", "online")
}
}
var list []models.MonkeyPid
db.Where("task_id = ? and is_del = 0", task_id).Find(&list)
db.Table("monkey_pid").Model(models.MonkeyPid{}).Where("task_id = ? and is_del = 0", task_id).Find(&list)
for _, v := range list {
killPid(v.PId)
pids = append(pids, v.PId)

@ -0,0 +1,131 @@
package monkey
import (
"fmt"
"goqs/common"
"goqs/controllers"
"goqs/dbsql"
"goqs/models"
"net/http"
"strings"
"github.com/gin-gonic/gin"
"github.com/spf13/cast"
"gorm.io/gorm"
)
// @Tags Monkey相关 /api/monkey/v2/
// @Summary 新建Monkey任务
// @Description 新建Monkey任务创建成功后将会发送指令到monkey服务初始status为WAITTING-等待中
// @accept x-www-form-urlencoded
// @Param project formData string true "项目名"
// @Param product formData string true "产品名"
// @Param package_name formData string true "应用包名"
// @Param package_url formData string true "测试包下载链接"
// @Param platform formData string true "平台adr/ios"
// @Param run_time formData string false "运行时间s默认两小时3600s"
// @Param launch_activity formData string false "安卓启动页名称"
// @Param creator formData string false "任务创建者"
// @Param referer formData string false "启动来源web-平台启动ci-持续集成"
// @Param mode formData string false "调用服务的方式0-cli模式/1-api模式默认cli"
// @Param remark formData string false "备注"
// @Success 200 {object} models.Response "返回创建的任务id"
// @Router /api/monkey/v2/create_task [post]
func CreateTaskV2(c *gin.Context) {
rsp := controllers.NewResponse()
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
}
defer dbsql.Close(db)
var task models.MonkeyTask
// 必填
task.Project = strings.ToLower(c.PostForm("project"))
task.Product = c.PostForm("product")
task.PackageName = c.PostForm("package_name")
task.PackageURL = c.PostForm("package_url")
task.Platform = c.PostForm("platform")
// 选填项
task.RunTime = cast.ToInt(c.DefaultPostForm("run_time", "3600"))
task.LaunchActivity = c.PostForm("launch_activity")
task.Creator = c.PostForm("creator")
task.Referer = c.DefaultPostForm("referer", "api")
task.Status = "WAITTING"
task.Remark = c.PostForm("remark")
// 安卓需要获取launch_activity
if task.Platform == "adr" {
if c.PostForm("launch_activity") == "" {
fmt.Println("从接口请求producct信息")
product, err := common.GetProduct(task.Product, task.Platform)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
}
task.LaunchActivity = product.LaunchActivity
}
// // 表单无传入,接口请求没有数据返回
// if task.LaunchActivity == "" {
// rsp.Error("缺少LaunchActivity")
// c.JSON(http.StatusOK, rsp)
// return
// }
}
if task.PackageURL != "" {
app, e := common.GetBranch(task.PackageName, task.PackageURL)
if e != nil {
fmt.Println(e)
} else {
if task.Branch == "" {
task.Branch = app.Branch
}
if task.Version == "" {
task.Version = app.Version + "_" + app.VersionCode
}
}
}
err = task.Check()
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
}
db.Model(models.MonkeyTask{}).Create(&task)
if db.Error != nil {
rsp.Error(db.Error.Error())
c.JSON(http.StatusOK, rsp)
return
}
rsp.Success()
rsp.Data = task
c.JSON(http.StatusOK, rsp)
// go RunAndroidMonkeyCmd(task, device.Udid)
}
// 根据id查询monkey任务信息db传nil时会另外新建数据库链接
func getTaskById(id int, db *gorm.DB) (models.MonkeyTask, error) {
var task models.MonkeyTask
if db == nil {
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
return task, err
}
defer dbsql.Close(db)
}
db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", id).Last(&task)
if task.Id == 0 {
return task, db.Error
}
return task, nil
}

@ -0,0 +1,37 @@
package project
import (
"goqs/controllers"
"goqs/dbsql"
"net/http"
"github.com/gin-gonic/gin"
)
// @Tags Monkey相关 /api/project/v1/
// @Summary 获取应用信息
// @Description 根据应用名称app_name获取应用信息
// @accept x-www-form-urlencoded
// @Param app_name query string true "应用名称"
// @Success 200 {object} models.Response "返回任务结果"
// @Router /api/project/v1/app [get]
func GetMonkeyResult(c *gin.Context) {
rsp := controllers.NewResponse()
app_name := c.Query("app_name")
if app_name == "" {
rsp.Error("缺少参数app_name")
return
}
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
rsp.Error(err.Error())
c.JSON(http.StatusOK, rsp)
return
}
defer dbsql.Close(db)
rsp.Success()
c.JSON(http.StatusOK, rsp)
}

@ -2,10 +2,47 @@ package main
import (
"fmt"
"goqs/common"
"goqs/dbsql"
"goqs/models"
"goqs/monkey"
)
func main() {
var task models.MonkeyTask
task.Project = "Hising"
task.Version = "1.00.04_10004006"
task.Platform = "adr"
task.Branch = "xxx/bbb/vasd_sdds"
task.PackageName = "music.hising.live.dev"
common.PushMonkeyResult(task)
return
dbsql.DSN = dbsql.DSN_local
db, err := dbsql.GetConn(dbsql.DSN)
if err != nil {
fmt.Println(err)
return
}
defer dbsql.Close(db)
var list []models.MonkeyTask
db.Model(models.MonkeyTask{}).Order("id DESC").Find(&list)
for _, v := range list {
if v.PackageURL != "" {
app, err := common.GetBranch(v.PackageName, v.PackageURL)
if err != nil {
fmt.Println(v.Id, "-", err, "||", v.PackageURL)
err = nil
} else {
fmt.Println(v.Id, "-", app.Branch)
db.Model(models.MonkeyTask{}).Where("id = ?", v.Id).Update("version", app.Version+"_"+app.VersionCode)
}
}
}
// // common.GetBranch("", "")
}
func Dir() {
err := monkey.CreateDir("files")
if err != nil {
fmt.Println(err)

Loading…
Cancel
Save