diff --git a/bootstrap.php b/bootstrap.php index 9fc98f4..3463f8e 100644 --- a/bootstrap.php +++ b/bootstrap.php @@ -83,6 +83,97 @@ if (COCKPIT_ADMIN && !COCKPIT_API_REQUEST) { '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); + + foreach ($logs as $l) { + if (preg_match('/^\\+/', $l->out)) { + $logstr .= '

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

'; + } else { + $logstr .= preg_replace(array_keys($colors), $colors, htmlspecialchars($l->out)); + } + } + } + } + + return [ + 'out' => $logstr + ]; + }, + 'createDeploy' => function ($fromBuild) { $settings = $this->app->storage->findOne('drone/settings'); diff --git a/views/deploys/index.php b/views/deploys/index.php index 01e133b..7990cea 100644 --- a/views/deploys/index.php +++ b/views/deploys/index.php @@ -1,7 +1,56 @@
@@ -42,6 +91,16 @@
+
+
+ +

{ deploy && deploy.title }

+
+

+      
+
+
+
@@ -52,6 +111,9 @@ + @@ -64,6 +126,9 @@ + @@ -77,10 +142,12 @@ - + + +
@lang('Build') # + @lang('Event') + @lang('Title') @lang('Deploy time') + @lang('Log') +
{ deploy.number }{ deploy.event }: { deploy.message }{ deploy.event }{ deploy.message } { deploy.created_at } { deploy.updated_at } { deploy.deploy_time }s
@@ -99,6 +166,7 @@ this.on('mount', function() { $this.loading = false; $this.modal = UIkit.modal(App.$('.uk-modal-details', this.root), {modal:true}); + $this.modalLogs = UIkit.modal(App.$('.uk-modal-logs', this.root), {modal:true}); if ($this.building) { setTimeout(function() { $this.fetchData(); @@ -113,11 +181,29 @@ editor = $this.refs.codemirror.editor; editor.setValue(JSON.stringify($this.deploy, null, 2), true); editor.setOption("readOnly", true); + editor.setOption("mode", "javascript"); editor.setSize($this.modal.dialog[0].clientWidth - 50, $this.modal.dialog[0].clientHeight - 70); editor.refresh(); $this.trigger('ready'); } + showdeployLog(e) { + $this.deploy = e.item.deploy; + App.callmodule('drone:fetchLogs', $this.deploy['number'], 'manage.view').then(function(data) { + if (data && data.result && data.result.out) { + area = App.$('.uk-modal-logs pre'); + area.html(data.result.out); + $this.modalLogs.show(); + area.css('width', $this.modalLogs.dialog[0].clientWidth - 50); + area.css('height', $this.modalLogs.dialog[0].clientHeight - 70); + $this.trigger('ready'); + } else { + App.ui.notify(App.i18n.get("Cannot fetch logs from Drone! Try again later."), "danger"); + } + $this.update(); + }); + } + createDeploy() { if ($this.building) { App.ui.notify(App.i18n.get("A deploy is already in progress, please wait until finishes."), "warning"); @@ -135,6 +221,7 @@ editor = $this.refs.codemirror.editor; editor.setValue(JSON.stringify(data, null, 2), true); editor.setOption("readOnly", true); + editor.setOption("mode", "javascript"); editor.setSize($this.modal.dialog[0].clientWidth - 50, $this.modal.dialog[0].clientHeight - 70); editor.refresh(); }