diff --git a/common/create_bug.go b/common/create_bug.go new file mode 100644 index 0000000..7075ab6 --- /dev/null +++ b/common/create_bug.go @@ -0,0 +1,88 @@ +package common + +import ( + "errors" + "fmt" + "time" + + "github.com/imroc/req/v3" + "github.com/tidwall/gjson" +) + +const API_tbapi = "http://qa.flatincbr.work:5354" + +type BugInfo struct { + ProjectName string `json:"project_name"` // tb项目名称 + ProjectID string `json:"project_id"` // tb项目id + ExecutorID string `json:"executor_id"` // tb缺陷的处理人 + Title string `json:"title"` // tb缺陷的标题 + Content string `json:"content"` // tb缺陷的备注 + InvolveMembers []string `json:"involve_members"` // tb缺陷的参与人 + Pf string `json:"pf"` // 所属平台,除了adr/ios其它不处理 +} + +func NewBug(project_name string) BugInfo { + var v BugInfo + v.ProjectName = project_name + return v +} + +// 指定执行者 +func (b *BugInfo) SetExecutor(id string) *BugInfo { + b.ExecutorID = id + return b +} + +// 指定参与者 +func (b *BugInfo) SetInvolveMember(id ...string) *BugInfo { + b.InvolveMembers = id + return b +} + +// 设置标题 +func (b *BugInfo) SetTitle(title string) *BugInfo { + b.Title = title + return b +} + +// 设置备注内容 +func (b *BugInfo) SetContent(content string) *BugInfo { + b.Content = content + return b +} + +// 设置所属平台:adr/ios +func (b *BugInfo) SetPlatform(pf string) *BugInfo { + b.Pf = pf + return b +} + +func (b *BugInfo) Create() (string, error) { + // buf, err := json.Marshal(b) + // if err != nil { + // fmt.Println("序列化失败:", err) + // return "", err + // } + // fmt.Println(string(buf)) + + client := req.C(). + SetTimeout(10 * time.Second) + resp, err := client.R(). + SetBodyJsonMarshal(b). + Post(API_tbapi + "/api/tb/v2/bug/create") + if err != nil { + fmt.Println("Teambition提单失败:", err) + return "", err + } + if resp.IsErrorState() { + fmt.Println("Teambition提单失败:", resp.StatusCode, resp.String()) + return "", err + } + bug_id := gjson.Get(resp.String(), "data").String() + if len(bug_id) == 0 { + return "", errors.New("请求成功,但返回bug_id为空") + } + fmt.Println("Teambition提单成功, id =", bug_id) + + return bug_id, nil +} diff --git a/docs/docs.go b/docs/docs.go index 1171a6a..f039307 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -959,6 +959,35 @@ const docTemplate = `{ } } }, + "/api/monkey/v2/task/get_anomalies": { + "get": { + "description": "通过任务id获取Monkey异常信息", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v2/" + ], + "summary": "获取Monkey异常信息", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务结果", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v2/task/handle/set": { "post": { "description": "更新Monkey任务跟进状态", @@ -995,6 +1024,59 @@ const docTemplate = `{ } } }, + "/api/monkey/v2/task/store_anomaly": { + "post": { + "description": "上报Monkey异常", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v2/" + ], + "summary": "上报Monkey异常", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "crash_log_list", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "activity_name_info", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "status", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/project/v1/app": { "get": { "description": "根据应用名称app_name获取应用信息", diff --git a/docs/swagger.json b/docs/swagger.json index 5965983..7b7d818 100644 --- a/docs/swagger.json +++ b/docs/swagger.json @@ -947,6 +947,35 @@ } } }, + "/api/monkey/v2/task/get_anomalies": { + "get": { + "description": "通过任务id获取Monkey异常信息", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v2/" + ], + "summary": "获取Monkey异常信息", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "query", + "required": true + } + ], + "responses": { + "200": { + "description": "返回任务结果", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/monkey/v2/task/handle/set": { "post": { "description": "更新Monkey任务跟进状态", @@ -983,6 +1012,59 @@ } } }, + "/api/monkey/v2/task/store_anomaly": { + "post": { + "description": "上报Monkey异常", + "consumes": [ + "application/x-www-form-urlencoded" + ], + "tags": [ + "Monkey相关 /api/monkey/v2/" + ], + "summary": "上报Monkey异常", + "parameters": [ + { + "type": "integer", + "description": "任务id", + "name": "task_id", + "in": "formData", + "required": true + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "crash_log_list", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "activity_name_info", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "device_name", + "in": "formData" + }, + { + "type": "string", + "description": "要更新的任务状态", + "name": "status", + "in": "formData" + } + ], + "responses": { + "200": { + "description": "返回更新后的任务信息", + "schema": { + "$ref": "#/definitions/models.Response" + } + } + } + } + }, "/api/project/v1/app": { "get": { "description": "根据应用名称app_name获取应用信息", diff --git a/docs/swagger.yaml b/docs/swagger.yaml index fefdf8f..c5e3761 100644 --- a/docs/swagger.yaml +++ b/docs/swagger.yaml @@ -635,6 +635,25 @@ paths: summary: 获取Monkey任务的执行命令 tags: - Monkey相关 /api/monkey/v2/ + /api/monkey/v2/task/get_anomalies: + get: + consumes: + - application/x-www-form-urlencoded + description: 通过任务id获取Monkey异常信息 + parameters: + - description: 任务id + in: query + name: task_id + required: true + type: integer + responses: + "200": + description: 返回任务结果 + schema: + $ref: '#/definitions/models.Response' + summary: 获取Monkey异常信息 + tags: + - Monkey相关 /api/monkey/v2/ /api/monkey/v2/task/handle/set: post: consumes: @@ -659,6 +678,41 @@ paths: summary: 更新任务跟进状态 tags: - Monkey相关 /api/monkey/v2/ + /api/monkey/v2/task/store_anomaly: + post: + consumes: + - application/x-www-form-urlencoded + description: 上报Monkey异常 + parameters: + - description: 任务id + in: formData + name: task_id + required: true + type: integer + - description: 要更新的任务状态 + in: formData + name: crash_log_list + type: string + - description: 要更新的任务状态 + in: formData + name: activity_name_info + type: string + - description: 要更新的任务状态 + in: formData + name: device_name + type: string + - description: 要更新的任务状态 + in: formData + name: status + type: string + responses: + "200": + description: 返回更新后的任务信息 + schema: + $ref: '#/definitions/models.Response' + summary: 上报Monkey异常 + tags: + - Monkey相关 /api/monkey/v2/ /api/project/v1/app: get: consumes: diff --git a/go.mod b/go.mod index bfbbc04..c9a3b49 100644 --- a/go.mod +++ b/go.mod @@ -54,6 +54,9 @@ require ( github.com/quic-go/qtls-go1-20 v0.1.0 // indirect github.com/quic-go/quic-go v0.32.0 // indirect github.com/satori/go.uuid v1.2.0 // indirect + github.com/tidwall/gjson v1.14.4 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect github.com/ugorji/go/codec v1.2.7 // indirect golang.org/x/crypto v0.7.0 // indirect golang.org/x/exp v0.0.0-20221205204356-47842c84f3db // indirect diff --git a/go.sum b/go.sum index 7f0b8d0..f75eb84 100644 --- a/go.sum +++ b/go.sum @@ -164,6 +164,12 @@ github.com/swaggo/gin-swagger v1.5.2/go.mod h1:Cbj/MlHApPOjZdf4joWFXLLgmZVPyh54G github.com/swaggo/swag v1.8.1/go.mod h1:ugemnJsPZm/kRwFUnzBlbHRd0JY9zE1M4F+uy2pAaPQ= github.com/swaggo/swag v1.8.4 h1:oGB351qH1JqUqK1tsMYEE5qTBbPk394BhsZxmUfebcI= github.com/swaggo/swag v1.8.4/go.mod h1:jMLeXOOmYyjk8PvHTsXBdrubsNd9gUJTTCzL5iBnseg= +github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= +github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= diff --git a/models/monkey_anomaly.go b/models/monkey_anomaly.go new file mode 100644 index 0000000..9ae8033 --- /dev/null +++ b/models/monkey_anomaly.go @@ -0,0 +1,33 @@ +package models + +import ( + "autogo/global" + "encoding/json" + "fmt" +) + +type MonkeyAnomaly struct { + global.MODEL + TaskId int `json:"task_id"` + Udid string `json:"udid"` + AnomalyInfos string `json:"-" gorm:"anomaly_infos"` + Anomalies []string `json:"anomalies" gorm:"-"` + CoverdPages string `json:"coverd_pages"` + Logs string `json:"logs"` +} + +func (m *MonkeyAnomaly) TableName() string { + return "monkey_anomalies" +} + +func (m *MonkeyAnomaly) JsonReady() { + var strs []string + if len(m.AnomalyInfos) > 3 { + err := json.Unmarshal([]byte(m.AnomalyInfos), &strs) + if err != nil { + fmt.Println("[JsonReady]", "序列化失败") + return + } + m.Anomalies = strs + } +} diff --git a/models/monkey_task.go b/models/monkey_task.go index cd72f0d..1601fca 100644 --- a/models/monkey_task.go +++ b/models/monkey_task.go @@ -66,7 +66,7 @@ func (task *MonkeyTask) Cmd(udid string, filename string) string { // } // 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 = "docker run -d --rm --net=host --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) + " " diff --git a/monkey/anomaly.go b/monkey/anomaly.go new file mode 100644 index 0000000..42e68f4 --- /dev/null +++ b/monkey/anomaly.go @@ -0,0 +1,161 @@ +package monkey + +import ( + "autogo/common" + "autogo/controllers" + "autogo/dbsql" + "autogo/models" + "encoding/json" + "fmt" + "net/http" + "strings" + + "github.com/gin-gonic/gin" + "github.com/spf13/cast" +) + +type anomaly struct { + TaskId int `json:"task_id"` + Udid string `json:"udid"` + Anomalies []string `json:"anomalies"` + CoverdPages []string `json:"coverd_pages"` + Logs []string `json:"logs"` +} + +// @Tags Monkey相关 /api/monkey/v2/ +// @Summary 上报Monkey异常 +// @Description 上报Monkey异常 +// @accept x-www-form-urlencoded +// @Param task_id formData int true "任务id" +// @Param crash_log_list formData string false "要更新的任务状态" +// @Param activity_name_info formData string false "要更新的任务状态" +// @Param device_name formData string false "要更新的任务状态" +// @Param status formData string false "要更新的任务状态" +// @Success 200 {object} models.Response "返回更新后的任务信息" +// @Router /api/monkey/v2/task/store_anomaly [post] +func StoreMonkeyAnomaly(c *gin.Context) { + rsp := controllers.NewResponse() + + var ano anomaly + err := c.ShouldBindJSON(&ano) + if err != nil { + c.JSON(http.StatusOK, rsp.Error("json解析失败: "+err.Error())) + return + } + + var res models.MonkeyAnomaly + res.TaskId = cast.ToInt(ano.TaskId) + if res.TaskId < 1 { + rsp.Error("task_id error:" + c.PostForm("task_id")) + c.JSON(http.StatusOK, rsp) + return + } + if len(ano.Anomalies) > 0 { + buf, _ := json.Marshal(ano.Anomalies) + res.Anomalies = ano.Anomalies + res.AnomalyInfos = string(buf) + } + if len(ano.CoverdPages) > 0 { + res.CoverdPages = strings.Join(ano.CoverdPages, ",") + } + res.Udid = ano.Udid + if len(ano.Logs) > 0 { + res.Logs = strings.Join(ano.Logs, ",") + } + + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Table(res.TableName()).Model(models.MonkeyAnomaly{}).Create(&res) + if res.ID < 1 { + rsp.Error("保存Monkey异常失败") + c.JSON(http.StatusOK, rsp) + return + } + + rsp.Success() + rsp.Data = res + c.JSON(http.StatusOK, rsp) + + go createTbBug(res) +} + +// @Tags Monkey相关 /api/monkey/v2/ +// @Summary 获取Monkey异常信息 +// @Description 通过任务id获取Monkey异常信息 +// @accept x-www-form-urlencoded +// @Param task_id query int true "任务id" +// @Success 200 {object} models.Response "返回任务结果" +// @Router /api/monkey/v2/task/get_anomalies [get] +func GetMonkeyAnomaliesByTaskId(c *gin.Context) { + rsp := controllers.NewResponse() + + var list []models.MonkeyAnomaly + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + rsp.Error(err.Error()) + c.JSON(http.StatusOK, rsp) + return + } + defer dbsql.Close(db) + db.Where("task_id = ?", c.Query("task_id")).Find(&list) + for i, _ := range list { + list[i].JsonReady() + } + + rsp.Success() + rsp.Data = list + c.JSON(http.StatusOK, rsp) +} + +func createTbBug(ano models.MonkeyAnomaly) { + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + fmt.Println("[createTbBug]", err) + return + } + defer dbsql.Close(db) + + var task models.MonkeyTask + db.Model(models.MonkeyTask{}).Where("id = ?", ano.TaskId).Last(&task) + if task.Id < 1 { + fmt.Println("[createTbBug]", "没有找到monkey任务,id -", ano.TaskId) + return + } + + content := "" + content += "**关联Monkey报告:** [点击查看](http://qa.flatincbr.work/#/monkey/result/" + cast.ToString(ano.TaskId) + ")" + "\n\n
\n\n" + content += "**上报时间:**" + ano.CreateTime.Format("2006-01-02 15:04:05") + "\n\n
\n\n" + content += "**应用版本:**" + task.Version + "\n\n
\n\n" + content += "**信息预览:**" + "\n\n" + for _, v := range ano.Anomalies { + for i, vv := range strings.Split(v, "\n") { + content += "> " + vv + "\n" + if i > 10 { + break + } + } + content += "> " + "——————————————————————" + "\n" + } + content += "> " + "(...更多请查看Monkey报告)" + "\n" + content += "\n" + + bug := common.NewBug("crushu") //task.Project + bug.SetExecutor("62733beb6918b259138d7577"). + SetInvolveMember("62733beb6918b259138d7577"). + SetTitle("【Monkey测试】任务id=" + cast.ToString(task.Id) + "发生异常"). + SetPlatform(task.Platform). + SetContent(content) + + id, err := bug.Create() + if err != nil { + fmt.Println(err) + return + } + fmt.Println("缺陷创建成功:", "https://www.teambition.com/task/"+id) + +} diff --git a/monkey/task.go b/monkey/task.go index 728598f..c5b8af8 100644 --- a/monkey/task.go +++ b/monkey/task.go @@ -455,7 +455,19 @@ func StopMonkeyTask(c *gin.Context) { list := GetTaskFromDocker(task_id) for _, v := range list { StopDockerContainer(v.Name) - db.Table("device").Model(models.Device{}).Where("udid = ?", v.Device).Update("status", "online") + } + + // 重置设备状态 + var task models.MonkeyTask + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", task_id).Last(&task) + if strings.Contains(task.Devices, ",") { + // 多台设备 + for _, v := range strings.Split(task.Devices, ",") { + db.Table("device").Model(models.Device{}).Where("udid = ?", v).Update("status", "online") + } + } else if len(task.Devices) > 1 { + // 有一台设备 + db.Table("device").Model(models.Device{}).Where("udid = ?", task.Devices).Update("status", "online") } db.Table("monkey_task").Model(models.MonkeyTask{}).Where("id = ?", task_id).Update("status", "CANCEL") diff --git a/test/test.go b/test/cli/test.go similarity index 75% rename from test/test.go rename to test/cli/test.go index 76af90d..2e446c7 100644 --- a/test/test.go +++ b/test/cli/test.go @@ -1,231 +1,255 @@ -package main - -import ( - "autogo/common" - "autogo/dbsql" - "autogo/device" - "autogo/models" - "autogo/monkey" - "fmt" - "net/http" - "os/exec" - "strings" - "time" - - "github.com/imroc/req/v3" -) - -func main() { - buglyHelper() - return - cmd := exec.Command("docker", "ps") - output, err := cmd.Output() - if err != nil { - fmt.Println(err) - return - } - - lines := strings.Split(string(output), "\n") - for i, line := range lines { - if i == 0 { - continue // skip header line - } - fields := strings.Fields(line) - if len(fields) >= 7 { - fmt.Printf("Container ID: %s, Name: %s\n", fields[0], fields[len(fields)-1]) - getRuntime(fields[0]) - } - } - fmt.Println("end") -} - -func buglyHelper() { - var rsp BuglyRsp - url := `https://bugly.qq.com/v2/search?start=0&userSearchPage=%2Fv2%2Fworkbench%2Fapps&pid=2&platformId=2&date=last_7_day&sortOrder=desc&useSearchTimes=2&rows=10&sortField=matchCount&appId=447d39aea1&fsn=f0726b64-a3ac-4e0d-a89d-c9148c82a5e6` - client := req.C(). - SetTimeout(5 * time.Second) - resp, err := client.R(). - SetCookies(cookies()...). - SetHeader("X-Token", "536325371"). - SetHeader("Accept", "application/json;charset=utf-8"). - SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36"). - // SetHeader("Cookie", "ptui_loginuin=188107463; RK=vOtUmiA9WS; ptcz=d265861b48af6f48ea0f924ded6af2b654f74146c1dc4d8632cb48e67edf7484; _ga=GA1.2.1584569153.1684823271; _qpsvr_localtk=0.9318772864960871; token-skey=b9694495-0a28-882a-01f9-d038d9e43bc7; token-lifeTime=1686922095; bugly-session=s:xz-9qL2pRzO3Mz8Wu_I7Svl2SLCWJfLE.MqN7buOfwmbUlRkdLauxXaddtaS3lebknTnCdPQOmtw; referrer=eyJpdiI6IkFcLzJDUTlValNtS0lUaGRFdkg3d2pRPT0iLCJ2YWx1ZSI6Ims4YUp6cUxyZlc0N25hOEJ2QWpZUlZQa2RKc1o3N3RiRHZXVVI1MlJLZ1RrSEtaQ2VmY1BtNEhMUjg4QjJSaExnc05cLzdiaGc2SHFtOTgzdnljMmlxUjd3d0FNZWdZdFwvNjdsT2ZYaG84M21Yd25FV1N0UTJyZTd3TDBId3hiQzNhN1wvS2RTZ1ZvdVFDYStKeEIrcGNnWWs1bno3dHdjTkVWdHIrYmRYTWNUb3Z1UGVvMXdoSE50djJBZ05hZ2pXUiIsIm1hYyI6IjgwNDI0ZjI2MjI0ZDFhMDA3MjBhYjQ4MWIwYjJiZTIzY2U5YjNkZjYyNGFkNTA5NGFjN2U4Y2U3ZTQwMDVlYWQifQ==; bugly_session=eyJpdiI6IjNmQzhJamU1cUlVd08yZHdWMkpTcmc9PSIsInZhbHVlIjoiZ3dFUXZUWmZ6XC8rbTZITG1DRVdrdDUrM1p0RE5nemgzeVhJa2huYWhieVB4SVFRMnlyWFFCU2JCQVpmRHNRQjdubnhhRWVJcUd3OEdzSk1zKzF2WGt3PT0iLCJtYWMiOiIwZjc4MGFmMDk1YzUyZTQ4Zjc5MjcwMDMyNGUzNmMxYjE5MjRlNTQ2MjliMzA3NmQyMGVjODRiZDgyMDU2NGQ1In0="). - SetHeader("Accept", "application/json;charset=utf-8"). - SetHeader("Accept-Encoding", "gzip, deflate, br"). - SetHeader("Accept-Language", "zh-CN,zh;q=0.9"). - SetHeader("Connection", "keep-alive"). - SetSuccessResult(&rsp). - // SetResult(&rsp). - Get(url) - if err != nil { - fmt.Println(err) - return - } - if resp.IsErrorState() { - fmt.Println(resp.StatusCode) - return - } - fmt.Println(len(rsp.Ret.IssueList)) -} - -func cookies() []*http.Cookie { - var cookies []*http.Cookie - var c1 http.Cookie - c1.Name = "bugly-session" - c1.Value = "s:xz-9qL2pRzO3Mz8Wu_I7Svl2SLCWJfLE.MqN7buOfwmbUlRkdLauxXaddtaS3lebknTnCdPQOmtw" - cookies = append(cookies, &c1) - - var c3 http.Cookie - c3.Name = "bugly_session" - c3.Value = "eyJpdiI6IlpuTkc5aXcwRHdUR1JGdDhIUmJMbGc9PSIsInZhbHVlIjoiRTZhVmxya3R3Sjl6UzBKQjRLa0EyNXlVV0lVYlNWVnpvVWFrbzVRS0k5am9UK3Y2MHN5czc3XC9JV0ZJNCtBQkdBbW4rZFh5RmFrcWYzODhOanV0OE9BPT0iLCJtYWMiOiI2MmJlYTI2MWE0M2U4NTFlNjJhYzkwZTAyOTQ3MTgxZmYwMTc0ZGJjOGE4MTE0ZjQ1Y2VmN2I5NjJkYTk2ZGY5In0=" - cookies = append(cookies, &c3) - return cookies -} - -func getRuntime(containerID string) { - - // 执行 docker inspect 命令获取容器创建时间 - cmd := exec.Command("docker", "inspect", "-f", "{{.Created}}", containerID) - output, err := cmd.Output() - if err != nil { - fmt.Println(err) - return - } - - // 将输出结果转换为时间格式 - createdTime, err := time.Parse(time.RFC3339Nano, strings.TrimSpace(string(output))) - if err != nil { - fmt.Println(err) - return - } - - // 计算容器已经运行的时间 - uptime := time.Since(createdTime) - - // 将容器运行时间转换为秒级时间戳输出 - uptimeInSeconds := int64(uptime.Seconds()) - fmt.Printf("Container %s has been running for %d seconds\n", containerID, uptimeInSeconds) -} - -func sib() { - if device.CheckSib() { - fmt.Println("sib已安装") - fmt.Println(device.GetIOSDevices()) - } else { - fmt.Println("sib未安装") - } -} - -func tmp1() { - dbsql.DSN = dbsql.DSN_local - db, err := dbsql.GetConn(dbsql.DSN) - if err != nil { - fmt.Println(err) - return - } - defer dbsql.Close(db) - var task models.MonkeyTask - db.Last(&task) - 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) - } - } - } -} - -func Dir() { - err := monkey.CreateDir("files") - if err != nil { - fmt.Println(err) - } - err = monkey.CreateDir("files/1") - if err != nil { - fmt.Println(err) - } - err = monkey.CreateAndWriteFile("files/1/2.txt", []byte("hidiuniduini")) - if err != nil { - fmt.Println(err) - } -} - -type BuglyRsp struct { - Status int `json:"status"` - Msg string `json:"msg"` - Ret struct { - AppID string `json:"appId"` - PlatformID string `json:"platformId"` - IssueList []struct { - IssueID int `json:"issueId"` - IssueHash string `json:"issueHash"` - IssueCount int `json:"issueCount"` - CrashInfo struct { - CrashID string `json:"crashId"` - TagID int `json:"tagId"` - } `json:"crashInfo"` - IssueVersions []struct { - Version string `json:"version"` - Count int `json:"count"` - DeviceCount int `json:"deviceCount"` - } `json:"issueVersions"` - FtName string `json:"ftName"` - IssueDocMap struct { - ID string `json:"id"` - IssueID int `json:"issueId"` - Status int `json:"status"` - Count int `json:"count"` - SysCount int `json:"sysCount"` - ProductVersion string `json:"productVersion"` - DeviceCount int `json:"deviceCount"` - SysDeviceCount int `json:"sysDeviceCount"` - LastUpdateTime string `json:"lastUpdateTime"` - FirstUploadTime string `json:"firstUploadTime"` - LastUploadTime string `json:"lastUploadTime"` - ExpName string `json:"expName"` - ExpFingure string `json:"expFingure"` - IsSystemStack int `json:"isSystemStack"` - KeyStack string `json:"keyStack"` - Type string `json:"type"` - AverageBattery float64 `json:"averageBattery"` - AverageMemory float64 `json:"averageMemory"` - AverageSD float64 `json:"averageSD"` - AverageStorage float64 `json:"averageStorage"` - CrossVersionIssueID int `json:"crossVersionIssueId"` - VersionIssueIds []int `json:"versionIssueIds"` - SubIssueVersions string `json:"subIssueVersions"` - ExpMessage string `json:"expMessage"` - RootCount int `json:"rootCount"` - SysRootCount int `json:"sysRootCount"` - ExpAddr string `json:"expAddr"` - RefSdkAppID string `json:"refSdkAppId"` - RefSdkIssueID string `json:"refSdkIssueId"` - CrashRecordCount int `json:"crashRecordCount"` - } `json:"issueDocMap"` - CrossVersionIssueID int `json:"crossVersionIssueId"` - EsCount int `json:"esCount"` - EsDeviceCount int `json:"esDeviceCount"` - } `json:"issueList"` - NumFound int `json:"numFound"` - CrashNums int `json:"crashNums"` - AnrNums int `json:"anrNums"` - ErrorNums int `json:"errorNums"` - } `json:"ret"` -} +package main + +import ( + "autogo/common" + "autogo/dbsql" + "autogo/device" + "autogo/models" + "autogo/monkey" + "autogo/test" + "fmt" + "net/http" + "os/exec" + "strings" + "time" + + "github.com/imroc/req/v3" + "github.com/spf13/cast" +) + +func main() { + test.GetMonkeyResult() + return + + db, err := dbsql.GetConn(dbsql.DSN_local) + if err != nil { + return + } + defer dbsql.Close(db) + var list []models.MonkeyTask + db.Model(models.MonkeyTask{}).Where("crash_count > 0 AND is_del = 0").Find(&list) + str := "" + for _, v := range list { + str += "\"" + cast.ToString(v.Id) + "\" " + } + fmt.Println(str) + + return + buglyHelper() + return + cmd := exec.Command("docker", "ps") + output, err := cmd.Output() + if err != nil { + fmt.Println(err) + return + } + + lines := strings.Split(string(output), "\n") + for i, line := range lines { + if i == 0 { + continue // skip header line + } + fields := strings.Fields(line) + if len(fields) >= 7 { + fmt.Printf("Container ID: %s, Name: %s\n", fields[0], fields[len(fields)-1]) + getRuntime(fields[0]) + } + } + fmt.Println("end") +} + +func buglyHelper() { + var rsp BuglyRsp + url := `https://bugly.qq.com/v2/search?start=0&userSearchPage=%2Fv2%2Fworkbench%2Fapps&pid=2&platformId=2&date=last_7_day&sortOrder=desc&useSearchTimes=3&rows=10&sortField=matchCount&appId=447d39aea1&fsn=8799e426-34c8-4a75-bd0d-1e186509eb5e` + client := req.C(). + SetTimeout(5 * time.Second) + resp, err := client.R(). + SetCookies(cookies()...). + SetHeader("X-Token", "957369952"). + SetHeader("Accept", "application/json;charset=utf-8"). + SetHeader("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.75 Safari/537.36"). + // SetHeader("Cookie", "bugly-session=s%3AqQZzQXsgw0wv_lFKAOT88ND_yh_B1f6H.au%2F78LCSHj5zhwqe%2FljmOXGP7TBW3yHnMwypYesrn34;bugly_session=eyJpdiI6InV1R3R0TmZ2S01HTkVBSGpucThXZXc9PSIsInZhbHVlIjoiam1lM3o1cVJISjNyZVJ6U3JJYzhmK1M1UVJiUlhCS1wvRTh6T1d4XC93NDdiY3FITVNJQXRpVFd6Y1BBV1wvZTBhOWR0MHBxNTlRdGNYdExoS2VWK2swckE9PSIsIm1hYyI6IjliMDExNTdmMzgyODFmNTEyYzVmMGQ3MGMxYTdjOTZmMDNjYzVjYzlkYzcxMmVjNmUyMzk4YWE2OTRmNzY4NzAifQ%3D%3D;"). + SetHeader("Accept", "application/json;charset=utf-8"). + SetHeader("Accept-Encoding", "gzip, deflate, br"). + SetHeader("Accept-Language", "zh-CN,zh;q=0.9"). + SetHeader("Connection", "keep-alive"). + SetSuccessResult(&rsp). + // SetResult(&rsp). + Get(url) + if err != nil { + fmt.Println(err) + return + } + if resp.IsErrorState() { + fmt.Println(resp.StatusCode) + return + } + if len(rsp.Ret.IssueList) > 0 { + fmt.Println(len(rsp.Ret.IssueList)) + } else { + fmt.Println(resp.String()) + } + +} + +func cookies() []*http.Cookie { + var cookies []*http.Cookie + // var c1 http.Cookie + // c1.Name = "bugly-session" + // c1.Value = "s:qQZzQXsgw0wv_lFKAOT88ND_yh_B1f6H.au/78LCSHj5zhwqe/ljmOXGP7TBW3yHnMwypYesrn34" + // cookies = append(cookies, &c1) + + var c3 http.Cookie + c3.Name = "bugly_session" + c3.Value = "eyJpdiI6InV1R3R0TmZ2S01HTkVBSGpucThXZXc9PSIsInZhbHVlIjoiam1lM3o1cVJISjNyZVJ6U3JJYzhmK1M1UVJiUlhCS1wvRTh6T1d4XC93NDdiY3FITVNJQXRpVFd6Y1BBV1wvZTBhOWR0MHBxNTlRdGNYdExoS2VWK2swckE9PSIsIm1hYyI6IjliMDExNTdmMzgyODFmNTEyYzVmMGQ3MGMxYTdjOTZmMDNjYzVjYzlkYzcxMmVjNmUyMzk4YWE2OTRmNzY4NzAifQ==" + cookies = append(cookies, &c3) + return cookies +} + +func getRuntime(containerID string) { + + // 执行 docker inspect 命令获取容器创建时间 + cmd := exec.Command("docker", "inspect", "-f", "{{.Created}}", containerID) + output, err := cmd.Output() + if err != nil { + fmt.Println(err) + return + } + + // 将输出结果转换为时间格式 + createdTime, err := time.Parse(time.RFC3339Nano, strings.TrimSpace(string(output))) + if err != nil { + fmt.Println(err) + return + } + + // 计算容器已经运行的时间 + uptime := time.Since(createdTime) + + // 将容器运行时间转换为秒级时间戳输出 + uptimeInSeconds := int64(uptime.Seconds()) + fmt.Printf("Container %s has been running for %d seconds\n", containerID, uptimeInSeconds) +} + +func sib() { + if device.CheckSib() { + fmt.Println("sib已安装") + fmt.Println(device.GetIOSDevices()) + } else { + fmt.Println("sib未安装") + } +} + +func tmp1() { + dbsql.DSN = dbsql.DSN_local + db, err := dbsql.GetConn(dbsql.DSN) + if err != nil { + fmt.Println(err) + return + } + defer dbsql.Close(db) + var task models.MonkeyTask + db.Last(&task) + 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) + } + } + } +} + +func Dir() { + err := monkey.CreateDir("files") + if err != nil { + fmt.Println(err) + } + err = monkey.CreateDir("files/1") + if err != nil { + fmt.Println(err) + } + err = monkey.CreateAndWriteFile("files/1/2.txt", []byte("hidiuniduini")) + if err != nil { + fmt.Println(err) + } +} + +type BuglyRsp struct { + Status int `json:"status"` + Msg string `json:"msg"` + Ret struct { + AppID string `json:"appId"` + PlatformID string `json:"platformId"` + IssueList []struct { + IssueID int `json:"issueId"` + IssueHash string `json:"issueHash"` + IssueCount int `json:"issueCount"` + CrashInfo struct { + CrashID string `json:"crashId"` + TagID int `json:"tagId"` + } `json:"crashInfo"` + IssueVersions []struct { + Version string `json:"version"` + Count int `json:"count"` + DeviceCount int `json:"deviceCount"` + } `json:"issueVersions"` + FtName string `json:"ftName"` + IssueDocMap struct { + ID string `json:"id"` + IssueID int `json:"issueId"` + Status int `json:"status"` + Count int `json:"count"` + SysCount int `json:"sysCount"` + ProductVersion string `json:"productVersion"` + DeviceCount int `json:"deviceCount"` + SysDeviceCount int `json:"sysDeviceCount"` + LastUpdateTime string `json:"lastUpdateTime"` + FirstUploadTime string `json:"firstUploadTime"` + LastUploadTime string `json:"lastUploadTime"` + ExpName string `json:"expName"` + ExpFingure string `json:"expFingure"` + IsSystemStack int `json:"isSystemStack"` + KeyStack string `json:"keyStack"` + Type string `json:"type"` + AverageBattery float64 `json:"averageBattery"` + AverageMemory float64 `json:"averageMemory"` + AverageSD float64 `json:"averageSD"` + AverageStorage float64 `json:"averageStorage"` + CrossVersionIssueID int `json:"crossVersionIssueId"` + VersionIssueIds []int `json:"versionIssueIds"` + SubIssueVersions string `json:"subIssueVersions"` + ExpMessage string `json:"expMessage"` + RootCount int `json:"rootCount"` + SysRootCount int `json:"sysRootCount"` + ExpAddr string `json:"expAddr"` + RefSdkAppID string `json:"refSdkAppId"` + RefSdkIssueID string `json:"refSdkIssueId"` + CrashRecordCount int `json:"crashRecordCount"` + } `json:"issueDocMap"` + CrossVersionIssueID int `json:"crossVersionIssueId"` + EsCount int `json:"esCount"` + EsDeviceCount int `json:"esDeviceCount"` + } `json:"issueList"` + NumFound int `json:"numFound"` + CrashNums int `json:"crashNums"` + AnrNums int `json:"anrNums"` + ErrorNums int `json:"errorNums"` + } `json:"ret"` +} diff --git a/test/monkey_result.go b/test/monkey_result.go new file mode 100644 index 0000000..63ddc55 --- /dev/null +++ b/test/monkey_result.go @@ -0,0 +1,71 @@ +package test + +import ( + "autogo/common" + "autogo/dbsql" + "autogo/models" + "encoding/json" + "fmt" + "strings" + + "github.com/spf13/cast" +) + +func GetMonkeyResult() { + var res models.MonkeyResult + dbsql.SetDSN("Flatincbr.com") + db, err := dbsql.GetConn(dbsql.DSN_local) + if err != nil { + fmt.Println(err) + return + } + defer dbsql.Close(db) + db.Model(models.MonkeyResult{}).Last(&res) + + var strs []string + json.Unmarshal([]byte(res.CrashLogs), &strs) + if len(strs) > 0 { + res.CrashLogList = strs + } + json.Unmarshal([]byte(res.ActivityNameInfo), &strs) + if len(strs) > 0 { + res.ActivityList = strs + } + json.Unmarshal([]byte(res.Logs), &strs) + if len(strs) > 0 { + res.LogList = strs + } + + var task models.MonkeyTask + db.Table(task.TableName()).Model(models.MonkeyTask{}).Where("id = ?", res.TaskId).Last(&task) + + // buf, _ := json.Marshal(res) + content := "" + content += "**关联Monkey报告:** [点击查看](http://qa.flatincbr.work/#/monkey/result/" + cast.ToString(res.TaskId) + ")" + "\n\n
\n\n" + content += "**上报时间:**" + res.CreateTime.Format("2006-01-02 15:04:05") + "\n\n
\n\n" + content += "**应用版本:**" + task.Version + "\n\n
\n\n" + content += "**信息预览:**" + "\n\n" + for i, v := range strings.Split(res.CrashLogList[0], "\n") { + content += "> " + v + "\n" + if i > 10 { + break + } + } + content += "> " + "(...更多请查看Monkey报告)" + "\n" + content += "\n" + // fmt.Println(content) + + bug := common.NewBug("crushu") + bug.SetExecutor("62733beb6918b259138d7577"). + SetInvolveMember("62733beb6918b259138d7577"). + SetTitle("【Monkey测试】测试缺陷标题byProjectName"). + SetPlatform("adr"). + SetContent(content) + + id, err := bug.Create() + if err != nil { + fmt.Println(err) + return + } + fmt.Println("缺陷创建成功:", "https://www.teambition.com/task/"+id) +}