From 9b9862fee98f12f7050f20c6f24f8f65e5f2eb57 Mon Sep 17 00:00:00 2001 From: luziqi Date: Tue, 13 Jun 2023 20:39:55 +0800 Subject: [PATCH] update --- cli/sib.go | 54 +++++++++++++++++++++++++++++++ common/config.go | 44 ++++++++++++++----------- crontask/ios.go | 39 ++++++++++++++++++++++ crontask/monkey.go | 17 +++++++++- device/ios.go | 75 +++++++++++++++++++++++++++++++++++++++++++ models/monkey_task.go | 38 +++++++++++++--------- monkey/cli_docker.go | 2 +- monkey/ios.go | 46 ++++++++++++++++++++++++++ monkey/task.go | 6 ++++ 9 files changed, 286 insertions(+), 35 deletions(-) create mode 100644 cli/sib.go create mode 100644 crontask/ios.go create mode 100644 device/ios.go create mode 100644 monkey/ios.go diff --git a/cli/sib.go b/cli/sib.go new file mode 100644 index 0000000..0a19e9d --- /dev/null +++ b/cli/sib.go @@ -0,0 +1,54 @@ +package cli + +import ( + "bufio" + "fmt" + "os/exec" + "strings" +) + +type SibDevice struct { + UDID string `json:"udid"` + Status string `json:"status"` + Src string `json:"src"` +} + +func GetIOSDevices() map[string]SibDevice { + m_devices := make(map[string]SibDevice) + cmd := exec.Command("sib", "devices") + stdout, err := cmd.StdoutPipe() + if err != nil { + fmt.Println(err) + return m_devices + } + if err := cmd.Start(); err != nil { + fmt.Println(err) + return m_devices + } + scanner := bufio.NewScanner(stdout) + for scanner.Scan() { + output := scanner.Text() + if strings.Contains(output, "no device") { + // 没设备 + return m_devices + } + if len(output) < 20 { + //空行 + continue + } + if strs := strings.Fields(output); len(strs) >= 3 { + var d SibDevice + d.UDID = strs[0] + d.Status = strs[1] + d.Src = strs[2] + m_devices[d.UDID] = d + } + } + if err := scanner.Err(); err != nil { + return m_devices + } + if err := cmd.Wait(); err != nil { + return m_devices + } + return m_devices +} diff --git a/common/config.go b/common/config.go index 833e656..61ec0c0 100644 --- a/common/config.go +++ b/common/config.go @@ -30,24 +30,32 @@ 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 + if strings.Contains(filename, ".apk") { + 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/admin/pkg-name-list") + if err != nil { + return _app, err + } + for _, v := range rsp.Data { + if v.Name == filename { + return v, nil + } } + return _app, errors.New("没有匹配到对应的包信息") + } else { + // iOS先不处理 + _app.Branch = "unknow" + _app.Version = "0.0.0" + _app.VersionCode = "000" + return _app, nil } - return _app, errors.New("没有匹配到对应的包信息") } diff --git a/crontask/ios.go b/crontask/ios.go new file mode 100644 index 0000000..6767ba3 --- /dev/null +++ b/crontask/ios.go @@ -0,0 +1,39 @@ +package crontask + +import ( + "autogo/cli" + "autogo/dbsql" + "autogo/models" + "fmt" +) + +func CheckIOSDevices() { + m := cli.GetIOSDevices() + + 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("platform = ? AND is_del = 0", "ios").Find(&list) + for _, v := range list { + if vv, ok := m[v.Udid]; ok { + if vv.Status != "online" && v.Status != vv.Status { + db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", vv.Status) + fmt.Println("[Crontab]", v.Udid, "连接状态异常:", v.Status) + } else if v.Status == "offline" && vv.Status == "online" { + db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "online") + fmt.Println("[Crontab]", v.Udid, "已连接") + } + } else { + if v.Status == "online" || v.Status == "busy" { + db.Model(models.Device{}).Where("udid = ?", v.Udid).Update("status", "offline") + fmt.Println("[Crontab]", v.Udid, "已离线") + } + } + } + +} diff --git a/crontask/monkey.go b/crontask/monkey.go index 4f82277..a250a22 100644 --- a/crontask/monkey.go +++ b/crontask/monkey.go @@ -29,7 +29,7 @@ func CheckMonkeyTasks() { product_name = strings.Split(task.Product, "-")[0] } var device models.Device - db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND status = ?", task.Project, product_name, "online").First(&device) + db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&device) if device.ID < 1 { // 没有空闲设备 continue @@ -37,6 +37,21 @@ func CheckMonkeyTasks() { db.Table("device").Model(models.Device{}).Where("udid = ?", device.Udid).Update("status", "busy") go monkey.RunAndroidMonkeyCmd(task, device.Udid) common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + device.Udid) + } else if task.Platform == "ios" { + product_name := task.Product + if strings.Contains(task.Product, "-") { + product_name = strings.Split(task.Product, "-")[0] + } + var device models.Device + db.Table("device").Model(models.Device{}).Where("project = ? AND product_name = ? AND platform = ? AND status = ?", task.Project, product_name, task.Platform, "online").First(&device) + if device.ID < 1 { + // 没有空闲设备 + continue + } + db.Table("device").Model(models.Device{}).Where("udid = ?", device.Udid).Update("status", "busy") + // go monkey.RunAndroidMonkeyCmd(task, device.Udid) + go monkey.RuniOSMonkeyByDocker(task, device.Udid) + common.PushCorntaskLog("执行Monkey任务:" + task.Project + "-" + device.Udid) } } diff --git a/device/ios.go b/device/ios.go new file mode 100644 index 0000000..b7e707b --- /dev/null +++ b/device/ios.go @@ -0,0 +1,75 @@ +package device + +import ( + "encoding/json" + "fmt" + "os/exec" + "strings" +) + +func GetIOSDevices() []sibDevice { + out := struct { + DeviceList []sibDevice + }{} + cmd := exec.Command("sib", "devices", "-f", "-d") + output, err := cmd.Output() + if err != nil { + fmt.Println(err) + return out.DeviceList + } + + err = json.Unmarshal(output, &out) + if err != nil { + fmt.Println(err) + return out.DeviceList + } + return out.DeviceList +} + +type sibDevice struct { + RemoteAddr string `json:"remoteAddr"` + DeviceID int `json:"deviceId"` + ConnectionSpeed int `json:"connectionSpeed"` + ConnectionType string `json:"connectionType"` + LocationID int `json:"locationId"` + ProductID int `json:"productId"` + SerialNumber string `json:"serialNumber"` + Status string `json:"status"` + DeviceDetail struct { + GenerationName string `json:"generationName"` + DeviceName string `json:"deviceName"` + DeviceColor string `json:"deviceColor"` + DeviceClass string `json:"deviceClass"` + ProductVersion string `json:"productVersion"` + ProductType string `json:"productType"` + ProductName string `json:"productName"` + ModelNumber string `json:"modelNumber"` + SerialNumber string `json:"serialNumber"` + SimStatus string `json:"simStatus"` + CPUArchitecture string `json:"cpuArchitecture"` + ProtocolVersion string `json:"protocolVersion"` + RegionInfo string `json:"regionInfo"` + TelephonyCapability bool `json:"telephonyCapability"` + TimeZone string `json:"timeZone"` + UniqueDeviceID string `json:"uniqueDeviceID"` + WifiAddress string `json:"wifiAddress"` + WirelessBoardSerialNumber string `json:"wirelessBoardSerialNumber"` + BluetoothAddress string `json:"bluetoothAddress"` + BuildVersion string `json:"buildVersion"` + } `json:"deviceDetail"` +} + +// 检查sib是否已安装 +func CheckSib() bool { + cmd := exec.Command("sib") + output, err := cmd.Output() + if err != nil { + fmt.Println(err) + return false + } + if strings.Contains(string(output), "SonicCloudOrg") { + return true + } else { + return false + } +} diff --git a/models/monkey_task.go b/models/monkey_task.go index 38c9ff1..41406db 100644 --- a/models/monkey_task.go +++ b/models/monkey_task.go @@ -49,23 +49,31 @@ func (task *MonkeyTask) Cmd(udid string, filename string) string { cmd_str += "-v /home/app/uat:/home/app/uat" + " " cmd_str += "monkey-adr" - // cmd_str = "cd /home/app/monkey && nohup python3 main_adr.py" + - // " -task_id " + cast.ToString(task.Id) - // if task.PackageURL != "" { + // cmd_str = "cd /home/app/monkey && nohup python3 main_adr.py" + + // " -task_id " + cast.ToString(task.Id) + // if task.PackageURL != "" { - // cmd_str += " -pkg_path " + filename - - // } - // cmd_str += " -package " + task.PackageName - // if task.LaunchActivity != "" { - // cmd_str += " -launch_activity " + task.LaunchActivity - // } - // cmd_str += " -run_time " + cast.ToString(task.RunTime) - // if udid != "" { - // cmd_str += " -device_udid " + udid - // } - // cmd_str += " >> /home/app/logs/task_output/task_" + cast.ToString(task.Id) + ".log 2>&1" + // cmd_str += " -pkg_path " + filename + // } + // cmd_str += " -package " + task.PackageName + // if task.LaunchActivity != "" { + // cmd_str += " -launch_activity " + task.LaunchActivity + // } + // cmd_str += " -run_time " + cast.ToString(task.RunTime) + // if udid != "" { + // cmd_str += " -device_udid " + udid + // } + // cmd_str += " >> /home/app/logs/task_output/task_" + cast.ToString(task.Id) + ".log 2>&1" + case "ios": + cmd_str = "docker run -d --rm --name monkey_task_" + cast.ToString(task.Id) + "_" + udid + " " + cmd_str += "-e TASK_ID=" + cast.ToString(task.Id) + " " + cmd_str += "-e BUNDLE_ID=" + task.PackageName + " " + cmd_str += "-e RUNTIME=" + cast.ToString(task.RunTime) + " " + cmd_str += "-e DEVICE=" + udid + " " + cmd_str += "-v /home/tmp/pkg/" + filename + ":/tmp/test.ipa" + " " + cmd_str += "-v /var/run/usbmuxd:/var/run/usbmuxd" + " " + cmd_str += "monkey-ios" } return cmd_str } diff --git a/monkey/cli_docker.go b/monkey/cli_docker.go index 1d16a5a..bcf8bc0 100644 --- a/monkey/cli_docker.go +++ b/monkey/cli_docker.go @@ -50,7 +50,7 @@ func StopDockerContainer(container_name string) bool { out, err := cmd.CombinedOutput() if err != nil { fmt.Println("[docker] Error stopping container:", err) - return false + return true } fmt.Println("[docker] Container stopped successfully:", string(out)) return true diff --git a/monkey/ios.go b/monkey/ios.go new file mode 100644 index 0000000..0d15e3d --- /dev/null +++ b/monkey/ios.go @@ -0,0 +1,46 @@ +package monkey + +import ( + "autogo/common" + "autogo/dbsql" + "autogo/models" + "os/exec" + "time" + + log "github.com/sirupsen/logrus" + "github.com/spf13/cast" +) + +func RuniOSMonkeyByDocker(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") + + filename := cast.ToString(time.Now().Unix()) + ".ipa" + pkg_path := "/home/tmp/pkg/" + filename + log.Debug("正在下载ipa:", task.PackageURL) + err = exec.Command("wget", task.PackageURL, "-O", pkg_path).Run() + if err != nil { + log.Error(err) + } + log.Debug("下载完毕,安装包路径", pkg_path) + + // python main_adr.py -package music.hising.live.dev -launch_activity sing.lagufun.social.live.ui.activity.SplashActivity + cmd_content := task.Cmd(udid, filename) + + 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() + if err != nil { + log.Error(err) + } +} diff --git a/monkey/task.go b/monkey/task.go index be07187..b56a566 100644 --- a/monkey/task.go +++ b/monkey/task.go @@ -192,6 +192,7 @@ func UpdateTaskCrashCount(c *gin.Context) { // @accept x-www-form-urlencoded // @Param page_size query int false "每页大小,默认为10" // @Param page_index query int false "第几页,默认为第一页" +// @Param project query int false "项目名称" // @Success 200 {object} models.Response "返回更新后的任务信息" // @Router /api/monkey/v1/tasks [get] func GetTasks(c *gin.Context) { @@ -211,6 +212,8 @@ func GetTasks(c *gin.Context) { } p.Size = pageSize + project := c.DefaultQuery("project", "") + db, err := dbsql.GetConn(dbsql.DSN) if err != nil { c.JSON(http.StatusOK, rsp.Error(err.Error())) @@ -222,6 +225,9 @@ func GetTasks(c *gin.Context) { db = db.Model(&models.MonkeyTask{}) var lenght int64 + if project != "" { + db = db.Where("project = ?", project) + } db = db.Where("is_del = 0").Count(&lenght) db = dbsql.SetPageQuery(db, pageIndex, pageSize) db.Order("id desc").Find(&list)