module('drone')->extend([ 'fetchDeploys' => function ($limit = 50) { $settings = $this->app->storage->findOne('drone/settings') ?? FALSE; if (!$settings || !isset($settings['url'], $settings['owner'], $settings['project'], $settings['target'], $settings['token']) || !$settings['active']) { return []; } // $url = $settings['api_url'] . '/sites/' . $settings['site_id'] . '/deploys' . '?access_token=' . $settings['access_token']; $url = trim($settings['url'], "/") . '/api/repos/' . $settings['owner'] . '/' . $settings['project'] . '/builds'; $branch = $settings['branch'] ? $settings['branch'] : 'master'; $headers = [ 'Content-Type: application/json', 'Accept: application/json', 'Authorization: Bearer ' . $settings['token'] ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $deploys = []; $unfiltered_deploys = curl_exec($ch); curl_close($ch); $unfiltered_deploys = json_decode($unfiltered_deploys); $build = $settings['build']; if ($unfiltered_deploys && is_array($unfiltered_deploys)) { foreach($unfiltered_deploys as $deploy) { if ($deploy->{target} == $branch && ($deploy->event == 'push' || ($deploy->event == 'promote' && $deploy->deploy_to == $settings['target']))) { // find latest successful build if (!$build) { if ($deploy->event == 'push' && $deploy->status == 'success') { $build = $deploy->number; } else { $build = $deploy->parent; } } $limit--; if ($limit>0) { $deploys[] = $deploy; } } } } // Parse dates and check if any deploy is on building status. $building = false; foreach ($deploys as $idx => $deploy) { $deploys[$idx]->building = false; if (!in_array($deploy->status, ['success', 'failure'])) { $building = true; $deploys[$idx]->building = true; } $deploys[$idx]->created_at = date('Y-m-d H:i', $deploy->created); $deploys[$idx]->updated_at = date('Y-m-d H:i', $deploy->updated); if ($deploy->finished) { $deploys[$idx]->deploy_time = $deploy->finished - $deploy->started; } } return [ 'deploys' => $deploys, 'building' => $building, 'build' => $build ]; }, 'fetchLogs' => function ($build) { $settings = $this->app->storage->findOne('drone/settings') ?? FALSE; if (!$settings || !isset($settings['url'], $settings['owner'], $settings['project'], $settings['target'], $settings['token']) || !$settings['active']) { return []; } $url = trim($settings['url'], "/") . '/api/repos/' . $settings['owner'] . '/' . $settings['project'] . '/builds/'. $build; $headers = [ 'Content-Type: application/json', 'Accept: application/json', 'Authorization: Bearer ' . $settings['token'] ]; $logstr = ""; $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $b = curl_exec($ch); curl_close($ch); $b = json_decode($b); $colors = [ '/\\033?\[(?:0;)?30m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?31m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?32m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?33m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?34m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?35m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?36m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[(?:0;)?37m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;30m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;31m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;32m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;33m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;34m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;35m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;36m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[1;37m(.*?)\\033?\[0m/s' => '$1', '/\\033?\[0m/s' => '', ]; foreach ($b->stages as $stage) { foreach ($stage->steps as $step) { $logstr .= '
Stage: '.$stage->name.'
'; $logstr .= '

'.$step->name.'


'; $step_url = $url . '/logs/' . $stage->number . '/' . $step->number; $ch = curl_init($step_url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $logs = curl_exec($ch); curl_close($ch); $logs = json_decode($logs); $lastTime = 0; foreach ($logs as $l) { if (preg_match('/^\\+/', $l->out)) { $logstr .= '

'.htmlspecialchars($l->out).'

'; } else { if ($l->time != $lastTime) { $logstr .= '
'.$l->time.'s
'; $lastTime = $l->time; } $logstr .= preg_replace(array_keys($colors), $colors, htmlspecialchars($l->out)); } } } } return [ 'out' => $logstr ]; }, 'createDeploy' => function ($fromBuild) { $settings = $this->app->storage->findOne('drone/settings'); if (!$fromBuild || !$settings || !isset($settings['url'], $settings['owner'], $settings['project'], $settings['target'], $settings['token']) || !$settings['active']) { return array( "error" => "missing settings" ); } $url = trim($settings['url'], "/") . '/api/repos/' . $settings['owner'] . '/' . $settings['project'] . '/builds/' . $fromBuild . '/promote?target=' . $settings['target']; $headers = [ 'Content-Type: application/json', 'Accept: application/json', 'Authorization: Bearer ' . $settings['token'] ]; $ch = curl_init($url); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0); curl_setopt($ch, CURLOPT_TIMEOUT, 5); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST'); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); // curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); $result = curl_exec($ch); $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); $decoded = json_decode($result); if ($httpcode >= 400) { $decoded->error = "ERROR: $httpcode"; } return $decoded; }, ]); // Include admin. include_once __DIR__ . '/admin.php'; }