<?php
require_once(__DIR__ . '/../events.inc.php');
require_once(__DIR__ . '/../builder.inc.php');
require_once(__DIR__ . '/core.inc.php');
require_once(__DIR__ . '/../user/pkg_map.inc.php');
require_once(__DIR__ . '/../user/packages_rpm.inc.php');
$_f = 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($_f);
/*
* 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_enter('wh_build_job_done');
//rg_log_enter_ml('DEBUG: ev: ' . rg_array2string($ev));
$job = $ev['job'];
$req = isset($job['request']) ? $job['request'] : $job;
$ret = FALSE;
do {
// For example building a rpm repo
if (isset($req['hook_id'])) {
$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['uid'],
$req['hook_id'], $out);
if (rg_debug()) {
$k = 'DEBUG::' . $ev['uid']
. '::webhooks::' . $req['hook_id'];
rg_log_debug('setting key [' . $k . '] to '
. print_r($ev, TRUE));
rg_cache_set($k, $ev, RG_SOCKET_NO_WAIT);
}
}
$ret = array();
if (isset($req['event_callbacks'])) {
unset($ev['request']['event_callbacks']);
foreach ($req['event_callbacks'] as $cb) {
rg_log_debug('adding ev for callback ' . $cb);
$ev['category'] = $cb;
$ret[] = $ev;
}
}
} while (0);
//rg_log_debug('ret: ' . rg_array2string($ret));
rg_log_exit();
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_debug('wh_build_send_one: event: ' . rg_array2string($ev));
$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['repo_id'] = $ev['ri']['repo_id'];
$a['repo_username'] = $ev['ri']['repo_username'];
$a['hook_id'] = $ev['wh']['id'];
$a['uid'] = $ev['ui_login']['uid'];
$a['username'] = $ev['ui_login']['username'];
$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['log_sid'] = $ev['log_sid'];
$a['packages'] = $ev['packages'];
// TODO: pass e-mail notification
$r = rg_pkg_maps_get($db, $a['uid'], $ri['name'],
$a['refname_short']);
if ($r['ok'] != 1) {
rg_log('cannot get maps: ' . $r['errmsg']);
$last_output .= $r['errmsg'];
break;
}
$a['pkg_maps'] = $r['pkg_maps'];
$a['pkg_repos'] = $r['pkg_repos'];
$a['pkg_subrepos'] = $r['pkg_subrepos'];
rg_pkg_prepare_for_rgfs($db, $a);
$a['exec'] = array();
$a['exec']['prepare_rpms'] = 1;
$a['exec']['copy_to_rgfs'] = 1;
$r = rg_pkg_prepare_for_dotrepo($db, $a);
if ($r['ok'] != 1) {
rg_log('Cannot prepare ev: ' . $r['errmsg']);
break;
}
// Call the function
$r = rg_builder_add($db, $ev['ri']['repo_id'], 10 /*prio*/, $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_login']['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: ' . rg_array2string($ev));
$ret = array();
// First, get the list of hooks
$r = rg_wh_list($db, $ev['ui_login']['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_debug('hook is not for this repo');
continue;
}
if (isset($ev['refname'])
&& !rg_repo_compare_refs($wh['refname'], $ev['refname'])) {
rg_log_debug('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_debug('envs: ' . rg_array2string($row['idata']['envs']));
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_debug('envs: ' . rg_array2string($envs));
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_debug('after fill_vars: ' . rg_array2string($a));
}
/*
* 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_debug('cmds:' . rg_array2string($a['idata']['cmds']));
if (empty($a['idata']['cmds'])) {
$errmsg[] = rg_template('user/settings/wh/build/inv_cmd.txt',
$rg, TRUE /*xss*/);
break;
}
//rg_log_debug('envs:' . rg_array2string($a['idata']['envs']));
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_debug('cmds=' . $cmds);
$rg['HTML:cmds'] =
rg_template_string($cmds, 0 /*off*/, $rg, TRUE /*xss*/);
$ui_login = rg_ui_login();
$envs = rg_worker_environments($db, $ui_login['uid']);
$f = rg_template_blind('user/settings/wh/build/form_env.html');
$_s = '';
foreach ($envs as $env)
$_s .= str_replace('##env##', rg_xss_safe($env), $f);
//rg_log_debug('envs: ' . $_s);
$rg['HTML:envs'] =
rg_template_string($_s, 0 /*off*/, $rg, TRUE /*xss*/);
//rg_log_debug('rg: ' . rg_array2string($rg));
$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);