diff --git a/atf.inc.php b/atf.inc.php index 4b5f1b6..879455e 100644 --- a/atf.inc.php +++ b/atf.inc.php @@ -2,7 +2,6 @@ namespace taskman; use Amp; use ClickHouseDB; -use Exception; interface IATFDevicePool { @@ -259,7 +258,7 @@ class ATFSession $version = taskman_prop('GAME_VERSION'); $rev_hash = taskman_prop('GAME_REVISION_HASH'); $msg = "version $version($rev_hash) size: $apk_sizeMb Mb ($apk_sizeB B)"; - // atf_slack_post($msg, array('channel' => _atf_slack_chan_qa())); + atf_slack_post($msg, array('channel' => _atf_slack_chan_qa())); $data['guid'] = $this->guid; $data['time'] = time(); @@ -314,22 +313,22 @@ class ATFSession ); } - // function tryShareToQAChannel($msg_slack_id, $error) - // { - // if(!$this->share_with_qa_chan) - // return; + function tryShareToQAChannel($msg_slack_id, $error) + { + if(!$this->share_with_qa_chan) + return; - // //let's skip similar already shared errors - // if($this->_calcSharedErrorSimilarity($error) > 80) - // return; + //let's skip similar already shared errors + if($this->_calcSharedErrorSimilarity($error) > 80) + return; - // $this->shared_qa_errors[] = $error; + $this->shared_qa_errors[] = $error; - // //let's share an exception message to goh-qa channel - // $resp = atf_slack_get_permalink($msg_slack_id); - // if(isset($resp['permalink'])) - // atf_slack_post($resp['permalink'], array('channel' => _atf_slack_chan_qa())); - // } + //let's share an exception message to goh-qa channel + $resp = atf_slack_get_permalink($msg_slack_id); + if(isset($resp['permalink'])) + atf_slack_post($resp['permalink'], array('channel' => _atf_slack_chan_qa())); + } function _calcSharedErrorSimilarity($error) { @@ -368,62 +367,62 @@ class ATFPlan return "Testing plan '{$this->name}' devices:".sizeof($this->getDevices())."(n/a:".sizeof($this->session->ignored_devices).")"; } - // function createSlackThread() - // { - // for($i=0;$i<5;++$i) - // { - // $resp = atf_slack_post($this->getTitle()); - // if(isset($resp['ok'])) - // { - // $this->slack_thread_ts = $resp['ts']; - // return; - // } - // sleep(1); - // } - // throw new Exception("Could not create Slack thread"); - // } + function createSlackThread() + { + for($i=0;$i<5;++$i) + { + $resp = atf_slack_post($this->getTitle()); + if(isset($resp['ok'])) + { + $this->slack_thread_ts = $resp['ts']; + return; + } + sleep(1); + } + throw new Exception("Could not create Slack thread"); + } - // function updateSlackThread() - // { - // $issues_summary = ''; - // foreach($this->getProblemsHistogram() as $code => $count) - // { - // if($code == ATFTask::CODE_GONE) - // $issues_summary .= " gones:$count"; - // else if($code == ATFTask::CODE_NSTART) - // $issues_summary .= " nstrts:$count"; - // else if($code == ATFTask::CODE_STUCK) - // $issues_summary .= " stucks:$count"; - // else if($code == ATFTask::CODE_HUNG) - // $issues_summary .= " hungs:$count"; - // else if($code == ATFTask::CODE_EXCEPTION) - // $issues_summary .= " excepts:$count"; - // else if($code == ATFTask::CODE_WARN) - // $issues_summary .= " warns:$count"; - // } + function updateSlackThread() + { + $issues_summary = ''; + foreach($this->getProblemsHistogram() as $code => $count) + { + if($code == ATFTask::CODE_GONE) + $issues_summary .= " gones:$count"; + else if($code == ATFTask::CODE_NSTART) + $issues_summary .= " nstrts:$count"; + else if($code == ATFTask::CODE_STUCK) + $issues_summary .= " stucks:$count"; + else if($code == ATFTask::CODE_HUNG) + $issues_summary .= " hungs:$count"; + else if($code == ATFTask::CODE_EXCEPTION) + $issues_summary .= " excepts:$count"; + else if($code == ATFTask::CODE_WARN) + $issues_summary .= " warns:$count"; + } - // $running_count = 0; - // $over_count = 0; - // $total_progress = 0; + $running_count = 0; + $over_count = 0; + $total_progress = 0; - // foreach($this->tasks as $task) - // { - // $total_progress += $task->getProgress(); - // if($task->isOver()) - // $over_count++; - // if($task->device) - // $running_count++; - // } - // $progress_txt = ' tasks:' . ($running_count > 0 ? $running_count . '/' : '') . $over_count . '/' . sizeof($this->tasks) . ' (' . round($total_progress/sizeof($this->tasks)*100, 2) . '%)'; + foreach($this->tasks as $task) + { + $total_progress += $task->getProgress(); + if($task->isOver()) + $over_count++; + if($task->device) + $running_count++; + } + $progress_txt = ' tasks:' . ($running_count > 0 ? $running_count . '/' : '') . $over_count . '/' . sizeof($this->tasks) . ' (' . round($total_progress/sizeof($this->tasks)*100, 2) . '%)'; - // atf_slack_update($this->slack_thread_ts, - // array(array( - // "text" => $this->getTitle() . $issues_summary . $progress_txt, - // "color" => $this->_getThreadColor(), - // "mrkdwn_in" => array("text") - // )) - // ); - // } + atf_slack_update($this->slack_thread_ts, + array(array( + "text" => $this->getTitle() . $issues_summary . $progress_txt, + "color" => $this->_getThreadColor(), + "mrkdwn_in" => array("text") + )) + ); + } function getProblemsHistogram() { @@ -486,7 +485,7 @@ class ATFPlan { $this->session->ignored_devices[] = $device; atf_log("Ignoring device *$device*: $reason"); - // atf_slack_post("Ignoring device *$device*: $reason", array('thread_ts' => $this->slack_thread_ts)); + atf_slack_post("Ignoring device *$device*: $reason", array('thread_ts' => $this->slack_thread_ts)); } function getDevices() @@ -544,7 +543,7 @@ class ATFPlan function runAsync(ATFApkInstaller $install, $sleep_time, $hung_threshold, $gone_threshold, $stuck_threshold) { - // $this->createSlackThread(); + $this->createSlackThread(); $this->session->resetBogusDevices(); @@ -562,7 +561,7 @@ class ATFPlan return Amp\call(function() use($task, $install, $sleep_time, $hung_threshold, $gone_threshold, $stuck_threshold) { while(!$this->isOver() && !$task->isOver()) { - // $this->updateSlackThread(); + $this->updateSlackThread(); yield Amp\delay((int)$sleep_time*1000); @@ -596,7 +595,7 @@ class ATFPlan } } - // $this->updateSlackThread(); + $this->updateSlackThread(); }); } @@ -612,7 +611,7 @@ class ATFPlan $task->device = $device; try { - // atf_slack_post("Preparing *{$task->device}*", array('thread_ts' => $this->slack_thread_ts)); + atf_slack_post("Preparing *{$task->device}*", array('thread_ts' => $this->slack_thread_ts)); yield $install->installAsync($device); yield atf_start_ext_cmd_on_device_async($device, $task->getCmd(), $task->getCmdArgs()); @@ -634,20 +633,20 @@ class ATFPlan { return Amp\call(function() use($task) { - // $this->_postScreenToSlack($task); + $this->_postScreenToSlack($task); $fatal_msg = "Fatal problem ({$task->last_fatal_problem} - ".ATFTask::code2string($task->last_fatal_problem)."), attempt:{$task->attempts} *{$task->device}*"; atf_log("[FTL] $fatal_msg"); - // atf_slack_post($fatal_msg, array('thread_ts' => $task->slack_thread_ts)); + atf_slack_post($fatal_msg, array('thread_ts' => $task->slack_thread_ts)); if($task->last_fatal_problem == ATFTask::CODE_GONE || $task->last_fatal_problem == ATFTask::CODE_HUNG) { $app_log = atf_get_logcat_unity($task->device, 300); $app_log = _atf_trim_start($app_log, 2000); - // atf_slack_post("Last logs: ```$app_log``` *{$task->device}*", array('thread_ts' => $task->slack_thread_ts)); + atf_slack_post("Last logs: ```$app_log``` *{$task->device}*", array('thread_ts' => $task->slack_thread_ts)); } if (!taskman_prop('EXT_BOT_ERROR_PAUSE')) @@ -787,7 +786,7 @@ class ATFPlan if($device_is_bogus) { - // $this->_reportErrorFromLogcatToSlack($task, 1000); + $this->_reportErrorFromLogcatToSlack($task, 1000); $this->_incAndCheckBogusDevice($task->device); } @@ -827,21 +826,21 @@ class ATFPlan atf_log($shell_msg); } - // function _postToSlackExtStatusItem(ATFTask $task, array $item) - // { - // $orig_msg = _atf_trim($item['message'], 3000); - // $slack_msg = $orig_msg; + function _postToSlackExtStatusItem(ATFTask $task, array $item) + { + $orig_msg = _atf_trim($item['message'], 3000); + $slack_msg = $orig_msg; - // if($item['error'] == ATFTask::CODE_EXCEPTION) - // $slack_msg = "```$slack_msg```"; + if($item['error'] == ATFTask::CODE_EXCEPTION) + $slack_msg = "```$slack_msg```"; - // $slack_msg = '('.round($item['time'],1).'s) '.$slack_msg.' *'.$task->device.'*'; + $slack_msg = '('.round($item['time'],1).'s) '.$slack_msg.' *'.$task->device.'*'; - // $resp = atf_slack_post($slack_msg, array('thread_ts' => $task->slack_thread_ts)); + $resp = atf_slack_post($slack_msg, array('thread_ts' => $task->slack_thread_ts)); - // if(isset($resp['ok']) && $item['error'] == ATFTask::CODE_EXCEPTION) - // $this->session->tryShareToQAChannel($resp['ts'], $orig_msg); - // } + if(isset($resp['ok']) && $item['error'] == ATFTask::CODE_EXCEPTION) + $this->session->tryShareToQAChannel($resp['ts'], $orig_msg); + } function _analyzeExtStatusItemAsync(ATFTask $task, array $item) { @@ -890,34 +889,34 @@ class ATFPlan else if($msg_type === '[WRN]') { $task->addStatusCode(ATFTask::CODE_WARN); - // $this->_postToSlackExtStatusItem($task, $item); + $this->_postToSlackExtStatusItem($task, $item); } else if($msg_type === null) { - // $this->_postToSlackExtStatusItem($task, $item); + $this->_postToSlackExtStatusItem($task, $item); } }); } - // function _reportErrorFromLogcatToSlack(ATFTask $task, $limit) - // { - // $errors_log = _atf_trim(atf_get_logcat_errors($task->device, $limit), 3000); - // if($errors_log) - // atf_slack_post("```$errors_log``` *{$task->device}*", array('thread_ts' => $task->slack_thread_ts)); - // } + function _reportErrorFromLogcatToSlack(ATFTask $task, $limit) + { + $errors_log = _atf_trim(atf_get_logcat_errors($task->device, $limit), 3000); + if($errors_log) + atf_slack_post("```$errors_log``` *{$task->device}*", array('thread_ts' => $task->slack_thread_ts)); + } - // function _postScreenToSlack(ATFTask $task) - // { - // global $GAME_ROOT; + function _postScreenToSlack(ATFTask $task) + { + global $GAME_ROOT; - // $png_data = atf_screen($task->device); - // if($png_data) - // { - // ensure_write("$GAME_ROOT/build/atf/screen.png", $png_data); - // atf_slack_post_png("screen", "$GAME_ROOT/build/atf/screen.png", array('thread_ts' => $task->slack_thread_ts)); - // } - // } + $png_data = atf_screen($task->device); + if($png_data) + { + ensure_write("$GAME_ROOT/build/atf/screen.png", $png_data); + atf_slack_post_png("screen", "$GAME_ROOT/build/atf/screen.png", array('thread_ts' => $task->slack_thread_ts)); + } + } } @@ -1309,10 +1308,11 @@ function _atf_db() return $db; } + function atf_stats_send($table, array $data) { - $db = _atf_db(); return; + $db = _atf_db(); $db->insert($table, array(array_values($data)), array_keys($data)); } diff --git a/composer.json b/composer.json index 00b070a..c3b7019 100644 --- a/composer.json +++ b/composer.json @@ -6,6 +6,7 @@ "php": ">=7.4" }, "autoload": { - "classmap": ["atf.inc.php"] + "classmap": ["atf.inc.php"], + "classmap": ["slack.inc.php"] } } \ No newline at end of file diff --git a/slack.inc.php b/slack.inc.php new file mode 100644 index 0000000..e027d42 --- /dev/null +++ b/slack.inc.php @@ -0,0 +1,180 @@ + $token, + 'channels' => implode(",", $channels), + 'file' => $cfile, + 'filename' => "test.jpg", + ); + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_HEADER, false); + curl_setopt($ch, CURLOPT_POST, true); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $result = curl_exec($ch); + curl_close($ch); + + $arr = json_decode($result, true); + if(isset($arr['ok']) && $arr['ok'] == 1) + { + if(isset($arr['file']['permalink_public'])) + return $arr['file']['permalink_public']; + } + + return ""; +} + +function _atf_slack_chan() +{ + return get("ATF_SLACK_CHANNEL"); +} + +function _atf_slack_chan_qa() +{ + return get("ATF_SLACK_CHANNEL"); +} + +function _atf_slack_token() +{ + $token = "xoxb-141599046048-1567053090644-2gDAoWGiZxFTtXGLMOOeLG2u"; + return $token; +} + +task('slack_test', function() +{ + // createSlackThread(); + // atf_slack_post('hi', array('channel' => _atf_slack_chan_qa())); +}); + +function atf_slack_post($message, $fields = array()) +{ + if(!get("ATF_SLACK")) + return array('ok' => true, 'ts' => 0); + + $ch = curl_init("https://slack.com/api/chat.postMessage"); + $fields["token"] = _atf_slack_token(); + if(!isset($fields['channel'])) + $fields["channel"] = _atf_slack_chan(); + $fields["text"] = $message; + + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result, true); +} + +function atf_slack_get_permalink($message_ts, $channel = null) +{ + if(!get("ATF_SLACK")) + return array('permalink' => ''); + + $ch = curl_init("https://slack.com/api/chat.getPermalink"); + $fields["token"] = _atf_slack_token(); + if($channel === null) + $channel = _atf_slack_chan(); + $fields["channel"] = $channel; + $fields["message_ts"] = $message_ts; + + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result, true); +} + +function atf_slack_update($ts, array $attachments) +{ + if(!get("ATF_SLACK")) + return array('ok' => true); + + $ch = curl_init("https://slack.com/api/chat.update"); + $fields["token"] = _atf_slack_token(); + $fields["channel"] = _atf_slack_chan(); + $fields["ts"] = $ts; + $fields["attachments"] = json_encode($attachments); + + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); + curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($fields)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result, true); +} + + +function atf_slack_post_png($title, $png_file, $fields = array()) +{ + if(!get("ATF_SLACK")) + return array('ok' => true); + + $file = new CurlFile($png_file, 'image/png'); + + $header = array(); + $header[] = 'Content-Type: multipart/form-data'; + + $fields["token"] = _atf_slack_token(); + $fields["channels"] = _atf_slack_chan(); + $fields['file'] = $file; + $fields['title'] = $title; + + $ch = curl_init("https://slack.com/api/files.upload"); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_HTTPHEADER, $header); + curl_setopt($ch, CURLOPT_POST, 1); + curl_setopt($ch, CURLOPT_POSTFIELDS, $fields); + + $result = curl_exec($ch); + curl_close($ch); + + return json_decode($result, true); +} \ No newline at end of file