]>
git.proxmox.com Git - ceph.git/blob - ceph/src/rocksdb/arcanist_util/config/RocksDBCommonHelper.php
2 // Copyright 2004-present Facebook. All Rights Reserved.
3 // This source code is licensed under the BSD-style license found in the
4 // LICENSE file in the root directory of this source tree. An additional grant
5 // of patent rights can be found in the PATENTS file in the same directory.
7 // Name of the environment variables which need to be set by the entity which
8 // triggers continuous runs so that code at the end of the file gets executed
9 // and Sandcastle run starts.
10 define("ENV_POST_RECEIVE_HOOK", "POST_RECEIVE_HOOK");
11 define("ENV_HTTPS_APP_VALUE", "HTTPS_APP_VALUE");
12 define("ENV_HTTPS_TOKEN_VALUE", "HTTPS_TOKEN_VALUE");
14 define("PRIMARY_TOKEN_FILE", '/home/krad/.sandcastle');
15 define("CONT_RUN_ALIAS", "leveldb");
17 //////////////////////////////////////////////////////////////////////
18 /* Run tests in sandcastle */
19 function postURL($diffID, $url) {
20 assert(strlen($diffID) > 0);
21 assert(is_numeric($diffID));
22 assert(strlen($url) > 0);
24 $cmd = 'echo \'{"diff_id": ' . $diffID . ', '
25 . '"name":"click here for sandcastle tests for D' . $diffID . '", '
26 . '"link":"' . $url . '"}\' | '
28 . 'differential.updateunitresults';
32 function buildUpdateTestStatusCmd($diffID, $test, $status) {
33 assert(strlen($diffID) > 0);
34 assert(is_numeric($diffID));
35 assert(strlen($test) > 0);
36 assert(strlen($status) > 0);
38 $cmd = 'echo \'{"diff_id": ' . $diffID . ', '
39 . '"name":"' . $test . '", '
40 . '"result":"' . $status . '"}\' | '
42 . 'differential.updateunitresults';
46 function updateTestStatus($diffID, $test) {
47 assert(strlen($diffID) > 0);
48 assert(is_numeric($diffID));
49 assert(strlen($test) > 0);
51 shell_exec(buildUpdateTestStatusCmd($diffID, $test, "waiting"));
54 function getSteps($applyDiff, $diffID, $username, $test) {
55 assert(strlen($username) > 0);
56 assert(strlen($test) > 0);
59 assert(strlen($diffID) > 0);
60 assert(is_numeric($diffID));
62 $arcrc_content = (PHP_OS
== "Darwin" ?
63 exec("cat ~/.arcrc | gzip -f | base64") :
64 exec("cat ~/.arcrc | gzip -f | base64 -w0"));
65 assert(strlen($arcrc_content) > 0);
67 // Sandcastle machines don't have arc setup. We copy the user certificate
68 // and authenticate using that in Sandcastle.
70 "name" => "Setup arcrc",
71 "shell" => "echo " . $arcrc_content . " | base64 --decode"
72 . " | gzip -d > ~/.arcrc",
76 // arc demands certain permission on its config.
77 // also fix the sticky bit issue in sandcastle
78 $fix_permission = array(
79 "name" => "Fix environment",
80 "shell" => "chmod 600 ~/.arcrc && chmod +t /dev/shm",
84 // Construct the steps in the order of execution.
86 $steps[] = $fix_permission;
89 // fbcode is a sub-repo. We cannot patch until we add it to ignore otherwise
90 // Git thinks it is an uncommited change.
91 $fix_git_ignore = array(
92 "name" => "Fix git ignore",
93 "shell" => "echo fbcode >> .git/info/exclude",
97 $steps[] = $fix_git_ignore;
99 // This will be the command used to execute particular type of tests.
103 // Patch the code (keep your fingures crossed).
105 "name" => "Patch " . $diffID,
106 "shell" => "arc --arcrc-file ~/.arcrc "
107 . "patch --nocommit --diff " . $diffID,
113 updateTestStatus($diffID, $test);
114 $cmd = buildUpdateTestStatusCmd($diffID, $test, "running") . "; ";
117 // Run the actual command.
118 $cmd = $cmd . "J=$(nproc) ./build_tools/precommit_checker.py " . $test
119 . "; exit_code=$?; ";
122 $cmd = $cmd . "([[ \$exit_code -eq 0 ]] &&"
123 . buildUpdateTestStatusCmd($diffID, $test, "pass") . ")"
124 . "||" . buildUpdateTestStatusCmd($diffID, $test, "fail")
128 // shell command to sort the tests based on exit code and print
129 // the output of the log files.
131 while read code log_file;
132 do echo \"################ cat \$log_file [exit_code : \$code] ################\";
134 done < <(tail -n +2 LOG | sort -k7,7n -k4,4gr | awk '{print \$7,\$NF}')";
136 // Shell command to cat all log files
137 $cat_all_logs = "for f in `ls t/!(run-*)`; do echo \$f;cat \$f; done";
139 // If LOG file exist use it to cat log files sorted by exit code, otherwise
141 $logs_cmd = "if [ -f LOG ]; then {$cat_sorted_logs}; else {$cat_all_logs}; fi";
143 $cmd = $cmd . " cat /tmp/precommit-check.log"
144 . "; shopt -s extglob; {$logs_cmd}"
145 . "; shopt -u extglob; [[ \$exit_code -eq 0 ]]";
146 assert(strlen($cmd) > 0);
149 "name" => "Run " . $test,
152 "parser" => "python build_tools/error_filter.py " . $test,
155 $steps[] = $run_test;
158 // Clean up the user arc config we are using.
160 "name" => "Arc cleanup",
161 "shell" => "rm -f ~/.arcrc",
168 assert(count($steps) > 0);
172 function getSandcastleConfig() {
173 $sandcastle_config = array();
176 $cwd_token_file = "{$cwd}/.sandcastle";
177 // This is a case when we're executed from a continuous run. Fetch the values
178 // from the environment.
179 if (getenv(ENV_POST_RECEIVE_HOOK
)) {
180 $sandcastle_config[0] = getenv(ENV_HTTPS_APP_VALUE
);
181 $sandcastle_config[1] = getenv(ENV_HTTPS_TOKEN_VALUE
);
183 // This is a typical `[p]arc diff` case. Fetch the values from the specific
184 // configuration files.
185 for ($i = 0; $i < 50; $i++
) {
186 if (file_exists(PRIMARY_TOKEN_FILE
) ||
187 file_exists($cwd_token_file)) {
190 // If we failed to fetch the tokens, sleep for 0.2 second and try again
193 assert(file_exists(PRIMARY_TOKEN_FILE
) ||
194 file_exists($cwd_token_file));
196 // Try the primary location first, followed by a secondary.
197 if (file_exists(PRIMARY_TOKEN_FILE
)) {
198 $cmd = 'cat ' . PRIMARY_TOKEN_FILE
;
200 $cmd = 'cat ' . $cwd_token_file;
203 assert(strlen($cmd) > 0);
204 $sandcastle_config = explode(':', rtrim(shell_exec($cmd)));
207 // In this case be very explicit about the implications.
208 if (count($sandcastle_config) != 2) {
209 echo "Sandcastle configuration files don't contain valid information " .
210 "or the necessary environment variables aren't defined. Unable " .
211 "to validate the code changes.";
215 assert(strlen($sandcastle_config[0]) > 0);
216 assert(strlen($sandcastle_config[1]) > 0);
217 assert(count($sandcastle_config) > 0);
219 return $sandcastle_config;
222 // This function can be called either from `[p]arc diff` command or during
223 // the Git post-receive hook.
224 function startTestsInSandcastle($applyDiff, $workflow, $diffID) {
225 // Default options don't terminate on failure, but that's what we want. In
226 // the current case we use assertions intentionally as "terminate on failure
228 assert_options(ASSERT_BAIL
, true);
230 // In case of a diff we'll send notificatios to the author. Else it'll go to
231 // the entire team because failures indicate that build quality has regressed.
232 $username = $applyDiff ?
exec("whoami") : CONT_RUN_ALIAS
;
233 assert(strlen($username) > 0);
237 assert(strlen($diffID) > 0);
238 assert(is_numeric($diffID));
241 // List of tests we want to run in Sandcastle.
242 $tests = array("unit", "unit_non_shm", "unit_481", "clang_unit", "tsan",
243 "asan", "lite_test", "valgrind", "release", "release_481",
244 "clang_release", "punit", "clang_analyze", "code_cov",
245 "java_build", "no_compression", "unity", "ubsan");
247 $send_email_template = array(
249 'triggers' => array('fail'),
250 'emails' => array($username . '@fb.com'),
253 // Construct a job definition for each test and add it to the master plan.
254 foreach ($tests as $test) {
255 $stepName = "RocksDB diff " . $diffID . " test " . $test;
258 $stepName = "RocksDB continuous integration test " . $test;
263 "report" => array($send_email_template),
264 "steps" => getSteps($applyDiff, $diffID, $username, $test)
268 // We cannot submit the parallel execution master plan to Sandcastle and
269 // need supply the job plan as a determinator. So we construct a small job
270 // that will spit out the master job plan which Sandcastle will parse and
271 // execute. Why compress the job definitions? Otherwise we run over the max
273 $cmd = "echo " . base64_encode(json_encode($arg))
274 . (PHP_OS
== "Darwin" ?
275 " | gzip -f | base64" :
276 " | gzip -f | base64 -w0");
277 assert(strlen($cmd) > 0);
279 $arg_encoded = shell_exec($cmd);
280 assert(strlen($arg_encoded) > 0);
282 $runName = "Run diff " . $diffID . "for user " . $username;
285 $runName = "RocksDB continuous integration build and test run";
293 $command["steps"][] = array(
294 "name" => "Generate determinator",
295 "shell" => "echo " . $arg_encoded . " | base64 --decode | gzip -d"
296 . " | base64 --decode",
297 "determinator" => true,
301 // Submit to Sandcastle.
302 $url = 'https://interngraph.intern.facebook.com/sandcastle/create';
305 'command' => 'SandcastleUniversalCommand',
307 'capabilities' => array(
308 'vcs' => 'rocksdb-int-git',
311 'hash' => 'origin/master',
313 'alias' => 'rocksdb-precommit',
314 'tags' => array('rocksdb'),
315 'description' => 'Rocksdb precommit job',
318 // Fetch the configuration necessary to submit a successful HTTPS request.
319 $sandcastle_config = getSandcastleConfig();
321 $app = $sandcastle_config[0];
322 $token = $sandcastle_config[1];
324 $cmd = 'curl -s -k -F app=' . $app . ' '
325 . '-F token=' . $token . ' -F job=\'' . json_encode($job)
326 .'\' "' . $url . '"';
328 $output = shell_exec($cmd);
329 assert(strlen($output) > 0);
331 // Extract Sandcastle URL from the response.
332 preg_match('/url": "(.+)"/', $output, $sandcastle_url);
334 assert(count($sandcastle_url) > 0, "Unable to submit Sandcastle request.");
335 assert(strlen($sandcastle_url[1]) > 0, "Unable to extract Sandcastle URL.");
338 echo "\nSandcastle URL: " . $sandcastle_url[1] . "\n";
339 // Ask Phabricator to display it on the diff UI.
340 postURL($diffID, $sandcastle_url[1]);
342 echo "Continuous integration started Sandcastle tests. You can look at ";
343 echo "the progress at:\n" . $sandcastle_url[1] . "\n";
347 // Continuous run cript will set the environment variable and based on that
348 // we'll trigger the execution of tests in Sandcastle. In that case we don't
349 // need to apply any diffs and there's no associated workflow either.
350 if (getenv(ENV_POST_RECEIVE_HOOK
)) {
351 startTestsInSandcastle(
352 false /* $applyDiff */,
353 NULL /* $workflow */,