xaizek / fragile (License: AGPLv3+) (since 2018-12-07)
Simple lightweight CI, attempting to be somewhat Unix-like in its philosophy.
Commit c390a3f807a8f8dc81302a30e98368160a098513

Discover errors and warnings in builders' output
Author: xaizek
Author date (UTC): 2016-01-28 21:23
Committer name: xaizek
Committer date (UTC): 2016-01-28 21:23
Parent(s): 9cf7e6858e796596984dcbf3b7dbabae1c0d1701
Signing key:
Tree: 2d7b88d44fc19ca769ccdb15178b957b15371b4c
File Lines added Lines deleted
build.php 9 2
daemon.php 66 2
style.css 48 0
File build.php changed (mode: 100644) (index c63d98d..4b551c7)
... ... try {
48 48
49 49 print "<hr/>\n"; print "<hr/>\n";
50 50
51 print "<pre>\n";
52 print $build->getOutput();
51 $rawOutput = $build->getOutput();
52 $parts = preg_split('/\n\n/', $rawOutput, 2);
53
54 if ($parts[0] != '') {
55 print "<div class='buildreport'>$parts[0]</div>";
56 print "<hr/>";
57 }
58 print "<pre>";
59 print $parts[1];
53 60 print "</pre>\n"; print "</pre>\n";
54 61 } }
55 62 } catch (PDOException $e) { } catch (PDOException $e) {
File daemon.php changed (mode: 100644) (index 83d27a0..964f228)
... ... function runBuild($build)
102 102
103 103 $build->setStatus('running'); $build->setStatus('running');
104 104
105 $output = '';
105 $rawOutput = '';
106 106
107 107 $buildPath = BUILDS_PATH . "/$build->buildername"; $buildPath = BUILDS_PATH . "/$build->buildername";
108 108 createPath($buildPath); createPath($buildPath);
 
... ... function runBuild($build)
110 110 $handle = popen("cd $buildPath && " $handle = popen("cd $buildPath && "
111 111 . BUILDERS_PATH . '/' . $build->buildername . ' 2>&1', 'r'); . BUILDERS_PATH . '/' . $build->buildername . ' 2>&1', 'r');
112 112 while (!feof($handle)) { while (!feof($handle)) {
113 $output .= fgets($handle);
113 $rawOutput .= fgets($handle);
114 114 // TODO: append output to database record every N lines (e.g. 100) // TODO: append output to database record every N lines (e.g. 100)
115 115 } }
116 116 $exitcode = pclose($handle); $exitcode = pclose($handle);
117 117
118 $output = makeReport($rawOutput);
118 119 $build->setResult(($exitcode == 0) ? 'OK' : 'FAIL', $output, $exitcode); $build->setResult(($exitcode == 0) ? 'OK' : 'FAIL', $output, $exitcode);
119 120 } }
120 121
 
... ... function createPath($path)
137 138 return true; return true;
138 139 } }
139 140
141 /**
142 * @brief Formats output to produce build report.
143 *
144 * Result consists of two parts separated by double newline symbol. The first
145 * parts contains index of errors and warnings, the second one is formatted
146 * output.
147 *
148 * @param rawOutput Output from builder script as is.
149 *
150 * @returns Multiline build report.
151 */
152 function makeReport($rawOutput)
153 {
154 $errors = [];
155 $warnings = [];
156
157 $input = preg_split('/\n/', $rawOutput);
158 $output = [];
159 $msgnum = 1;
160 foreach ($input as $line) {
161 $re = '/^(.*)(error|warning|Error|Warning|ERROR|WARNING)(:\s+)(.*)$/';
162 preg_match($re, $line, $matches);
163 if (sizeof($matches) == 0) {
164 array_push($output, $line);
165 continue;
166 }
167
168 $anchor = "<a name='m$msgnum'/>";
169 $link = "<a href='#m$msgnum'>" . htmlentities($matches[4]) . "</a>";
170
171 if (strcasecmp($matches[2], 'error') == 0) {
172 array_push($errors, $link);
173 $style = 'error';
174 } else {
175 array_push($warnings, $link);
176 $style = 'warning';
177 }
178
179 $line = "$matches[1]"
180 . "<span class='$style-title'>$matches[2]</span>"
181 . "$matches[3]"
182 . "<span class='$style-msg'>$matches[4]</span>";
183
184 array_push($output, $anchor . $line);
185
186 ++$msgnum;
187 }
188
189 $header = '';
190 if (sizeof($errors) != 0) {
191 $header .= "Errors:<ol><li>";
192 $header .= join("</li><li>", $errors);
193 $header .= "</li></ol>\n";
194 }
195 if (sizeof($warnings) != 0) {
196 $header .= "Warnings:<ol><li>";
197 $header .= join("</li><li>", $warnings);
198 $header .= "</li></ol>\n";
199 }
200
201 return $header . "\n\n" . join("\n", $output);
202 }
203
140 204 ?> ?>
File style.css changed (mode: 100644) (index 1e4b7c7..b5e3452)
... ... span.title
158 158 font-size: 0.85em; font-size: 0.85em;
159 159 font-weight: bold; font-weight: bold;
160 160 } }
161
162 pre span.error-title
163 {
164 color: white;
165 background-color: red;
166 font-weight: bold;
167 padding: 1px;
168 }
169
170 pre span.error-msg
171 {
172 color: red;
173 font-weight: bold;
174 }
175
176 pre span.warning-title
177 {
178 color: black;
179 background-color: yellow;
180 font-weight: bold;
181 padding: 1px;
182 }
183
184 pre span.warning-msg
185 {
186 font-weight: bold;
187 }
188
189 div.buildreport
190 {
191 margin-left: 15px;
192 }
193
194 div.buildreport a, div.buildreport a:hover
195 {
196 color: black;
197 }
198
199 div.buildreport a:hover
200 {
201 color: #555;
202 }
203
204 div ol
205 {
206 margin-top: 5px;
207 margin-bottom: 10px;
208 }
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/fragile

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/fragile

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master