<?php require_once($INC . "/util.inc.php"); require_once($INC . "/log.inc.php"); require_once($INC . "/sql.inc.php"); require_once($INC . "/prof.inc.php"); require_once($INC . "/events.inc.php"); require_once($INC . '/builder.inc.php'); require_once($INC . "/wh/core.inc.php"); $rg_wh_build_functions = array( 'wh_build_send' => 'rg_wh_build_send', 'wh_build_send_one' => 'rg_wh_build_send_one', 'wh_build_job_done' => 'rg_wh_build_job_done' ); rg_event_register_functions($rg_wh_build_functions); /* * This is called when a job is done */ function rg_wh_build_job_done($db, $ev) { rg_prof_start('wh_build_job_done'); rg_log_ml('wh_build_job_done: ev: ' . print_r($ev, TRUE)); $job = $ev['job']; $req = isset($job['request']) ? $job['request'] : $job; $ret = FALSE; while (1) { $s = $ev['status']; $out = 'Worker: ' . $job['worker_name'] . "\n"; $out .= 'Date (UTC): ' . gmdate('Y-m-d H:i', $job['done']) . "\n"; $out .= 'Elapsed time: ' . ($job['done'] - $job['worker_started']) . 's' . "\n\n"; $out .= 'Packages installation:' . "\n"; $out .= $s['packages'] . "\n\n"; foreach ($s['cmds'] as $index => $i) { if (empty($req['cmds'][$index]['cmd'])) continue; $out .= 'Command[' . $req['cmds'][$index]['cmd'] . ']:' . "\n" . trim($i['log']) . "\n\n"; } // TODO: should we check error code? rg_wh_set_last_output($db, $ev['ui']['uid'], $req['hook_id'], $out); $ret = array(); break; } rg_prof_end('wh_build_job_done'); return $ret; } /* * Helper for rg_wh_build_send */ function rg_wh_build_send_one($db, $ev) { rg_prof_start('wh_build_send_one'); rg_log_ml('wh_build_send_one: event: ' . print_r($ev, TRUE)); $ret = FALSE; $last_output = ''; while (1) { // replace ##tags## rg_wh_replace_tags($ev); $ri = rg_repo_info($db, $ev['ri']['repo_id'], 0, ''); if ($ri['ok'] != 1) { $last_output .= $ri['errmsg']; break; } $a = $ev['wh']['idata']; $a['hook_id'] = $ev['wh']['id']; $a['uid'] = $ev['ui']['uid']; $a['flags'] = $ev['wh']['flags']; $a['url'] = $ri['clone_url_ssh']; $a['head'] = $ev['new_rev']; $a['refname'] = $ev['refname']; $a['refname_short'] = rg_repo_ref_nice($ev['refname']); $a['env'] = $ev['env']; $a['packages'] = $ev['packages']; // TODO: pass e-mail notification // Call the function $r = rg_builder_add($db, $ev['ri']['repo_id'], $a); if ($r['ok'] != 1) { $last_output .= $r['errmsg']; break; } $ret = array(); break; } if (!empty($last_output)) rg_wh_set_last_output($db, $ev['ui']['uid'], $ev['wh']['id'], substr($last_output, 0, 4096)); rg_prof_end('wh_build_send_one'); return $ret; } /* * Generic function which will be called when a webhook must be posted */ function rg_wh_build_send($db, $ev) { rg_prof_start('wh_build_send'); rg_log_ml('wh_build_send: event: ' . print_r($ev, TRUE)); $ret = array(); // First, get the list of hooks $r = rg_wh_list($db, $ev['ui']['uid']); if ($r['ok'] != 1) return FALSE; // Filter foreach ($r['list'] as $id => $wh) { if (strcmp($wh['htype'], 'build') != 0) continue; // Disabled? if (strchr($wh['flags'], 'D')) continue; // If the web hook does not contain our type, skip it if (!strchr($wh['idata']['events'], $ev['wh_event'])) { rg_log('DEBUG: ' . $ev['wh_event'] . ' is not present in ' . $wh['idata']['events']); continue; } if (isset($ev['ri']['name']) && !rg_repo_compare_refs($wh['repo'], $ev['ri']['name'])) { rg_log('hook is not for this repo'); continue; } if (isset($ev['refname']) && !rg_repo_compare_refs($wh['refname'], $ev['refname'])) { rg_log('hook is not for this ref'); continue; } $x = $ev; $x['category'] = 'wh_build_send_one'; $x['packages'] = $wh['idata']['packages']; $envs = $wh['idata']['envs']; unset($wh['idata']['envs']); $x['wh'] = $wh; foreach ($envs as $env => $junk) { $y = $x; $y['env'] = $env; $ret[] = $y; } } rg_prof_end('wh_build_send'); return $ret; } /* * Some cosmetics applied to a webhook */ function rg_wh_build_cosmetic_pre(&$row) { } /* * Some cosmetics applied to a webhook */ function rg_wh_build_cosmetic_post(&$row) { $f = rg_template('user/settings/wh/build/show_one.html', $rg, TRUE/*xss*/); $list = ''; foreach ($row['idata']['cmds'] as $i => &$info) { if (empty($info['cmd'])) continue; $list .= str_replace('##i##', $i, $f); $info['abort_nice'] = $info['abort'] == 1 ? "Yes" : "No"; } unset($info); $row['idata']['HTML:wh_list'] = rg_template_string($list, 0 /*off*/, $row['idata'], TRUE /*xss*/); $f = rg_template('user/settings/wh/build/env_show_one.html', $rg, TRUE/*xss*/); $list = ''; //rg_log_ml('DEBUG: envs: ' . print_r($row['idata']['envs'], TRUE)); foreach ($row['idata']['envs'] as $env => $junk) { $list .= str_replace('##env##', $env, $f); } $row['idata']['HTML:envs_list'] = rg_template_string($list, 0 /*off*/, $row['idata'], TRUE /*xss*/); $row['idata']['HTML:private'] = rg_template( 'user/settings/wh/build/show.html', $row['idata'], TRUE /*xss*/); } /* * Fill private data based on parameters passed */ function rg_wh_build_fill_vars(&$rg) { $a = $rg['wh']['idata']; $a['cmds'] = array(); for ($i = 1; $i <= 5; $i++) { $p = 'wh::idata::cmds::' . $i . '::'; $cmd = trim(rg_var_str($p . 'cmd')); if (empty($cmd)) { $a['cmds'][$i] = array( 'cmd' => '', 'label_ok' => '', 'label_nok' => '', 'abort' => 0 ); continue; } $a['cmds'][$i] = array(); $a['cmds'][$i]['cmd'] = $cmd; $a['cmds'][$i]['label_ok'] = trim(rg_var_str($p . 'label_ok')); $a['cmds'][$i]['label_nok'] = trim(rg_var_str($p . 'label_nok')); $x = trim(rg_var_str($p . 'abort')); $a['cmds'][$i]['abort'] = strcasecmp($x, 'on') == 0 ? 1 : 0; } $a['envs'] = array(); $envs = rg_var_str('wh::idata::envs'); //rg_log_ml('envs: ' . print_r($envs, TRUE)); foreach ($envs as $env => $on) $a['envs'][$env] = strcasecmp($on, 'on') == 0 ? 1 : 0; $a['packages'] = trim(rg_var_str('wh::idata::packages')); $a['packages'] = str_replace(';', ' ', $a['packages']); $a['packages'] = str_replace(',', ' ', $a['packages']); $a['packages'] = str_replace('\r', ' ', $a['packages']); $a['packages'] = str_replace('\n', ' ', $a['packages']); $a['packages'] = str_replace('\t', ' ', $a['packages']); $rg['wh']['idata'] = $a; //rg_log_ml('DEBUG: after fill_vars: ' . print_r($a, TRUE)); } /* * Validate parameters passed */ function rg_wh_build_validate_vars($rg, &$errmsg) { global $rg_wh_build_itypes; $a = $rg['wh']; $ret = FALSE; while (1) { $all_empty = TRUE; //rg_log_ml('DEBUG: cmds:' . print_r($a['idata']['cmds'], TRUE)); if (empty($a['idata']['cmds'])) { $errmsg[] = rg_template('user/settings/wh/build/inv_cmd.txt', $rg, TRUE /*xss*/); break; } //rg_log_ml('DEBUG: envs:' . print_r($a['idata']['envs'], TRUE)); if (empty($a['idata']['envs'])) { $errmsg[] = rg_template('user/settings/wh/build/inv_env.txt', $rg, TRUE /*xss*/); break; } $ret = TRUE; break; } return $ret; } /* * Transfers to $rg the custom parameters - used when showing the form */ function rg_wh_build_add_form_pre($db, &$rg) { $a = $rg['wh']['idata']; $t = array( 'cmd' => '', 'label_ok' => '', 'label_nok' => '', 'abort' => 0 ); for ($i = 1; $i <= 5; $i++) { if (!isset($a['cmds'][$i])) $a['cmds'][$i] = $t; } if (!isset($a['envs'])) $a['envs'] = array(); if (!isset($a['packages'])) $a['packages'] = ''; if (!isset($a['events'])) $a['events'] = 'P'; $rg['wh']['idata'] = $a; } /* * Transfers to $rg the custom parameters - used when showing the form */ function rg_wh_build_add_form_post($db, &$rg) { $f = rg_template_blind('user/settings/wh/build/form_cmd.html'); $cmds = ''; for ($i = 1; $i <= 5; $i++) $cmds .= str_replace('##i##', $i, $f); //rg_log_ml('DEBUG: cmds=' . $cmds); $rg['HTML:cmds'] = rg_template_string($cmds, 0 /*off*/, $rg, TRUE /*xss*/); $envs = rg_worker_environments($db, $rg['login_ui']['uid']); $f = rg_template_blind('user/settings/wh/build/form_env.html'); $_s = ''; foreach ($envs as $env) $_s .= str_replace('##env##', $env, $f); rg_log_ml('envs: ' . $_s); $rg['HTML:envs'] = rg_template_string($_s, 0 /*off*/, $rg, TRUE /*xss*/); //rg_log_ml('DEBUG:rg: ' . print_r($rg, TRUE)); $rg['HTML:custom_form'] = rg_template('user/settings/wh/build/form.html', $rg, TRUE /*xss*/); } /* * Add custom hints */ function rg_wh_build_fill_hints($rg, &$hints) { $hints[]['HTML:hint'] = rg_template('user/settings/wh/build/hints.html', $rg, TRUE /*xss*/); } $info = array( 'htype' => 'build', 'description' => 'Clones, builds and tests (Continuous Integration)', 'cb' => array( 'cosmetic_pre' => 'rg_wh_build_cosmetic_pre', 'cosmetic_post' => 'rg_wh_build_cosmetic_post', 'fill_vars' => 'rg_wh_build_fill_vars', 'validate_vars' => 'rg_wh_build_validate_vars', 'add_form_pre' => 'rg_wh_build_add_form_pre', 'add_form_post' => 'rg_wh_build_add_form_post', 'fill_hints' => 'rg_wh_build_fill_hints' ), 'have_events' => TRUE, 'flags' => array() ); rg_wh_register_type('build', $info); $cb = array(); rg_wh_register_subtype('build', 'generic', 'Generic', $cb);