. # See the README and LICENSE files for details # # # GoogleCode - MantisBT interaction on SVN commit # # This code can be used to capture the Google Code "Post-Commit # Web Hooks" and, if the commit log contains a references to an # issue, automatically add a comment for this issue. # More info on GC Post-Commit Hooks: # http://code.google.com/p/support/wiki/PostCommitWebHooks # # To make it works, you need to : # - place this file under the '/scripts/' directory of your Mantis # installation, # - add the account, the regexp and the GC auth. key used to add # the comments in the Mantis configuration. # ex: # $g_source_control_account = 'svn_mantis-robot'; // this account must exist # $g_source_control_regexp = '/\bissue [#]{0,1}(\d+)\b/i'; # $g_source_control_fixed_regexp = '/\bfix [#]{0,1}(\d+)\b/i'; # $g_source_control_googlecode_secretkey = array( # 'gc_project_name' => 'dont forget me!', # 'gc_project_name_2' => 'facultatif', # ); # # - configure your googlecode project (admin / source) and # give the URL of this script. # For ex: http://mantis.your-domain.net/scripts/checkin_googlecode.php # # Note: A big part of this code comes from script/checkin.php # # TODO: # - make it work with Hg too, # - a request can be sent more than once, duplicating # messages. I don't see how to avoid it cleanly. # - if a key has been badly pasted, it fails (as designed) quite silently. # Any idea of improvment on this ? # include MantisBT core global $g_bypass_headers; $g_bypass_headers = 1; require_once( dirname ( dirname( __FILE__ ) ) . DIRECTORY_SEPARATOR . 'core.php' ); # Check that the username is set and exists $conf_username = config_get( 'source_control_account' ); if( is_blank( $conf_username ) || ( user_get_id_by_name( $conf_username ) === false ) ) { header('HTTP/1.0 500 Inexistent MantisBT account'); echo "ERROR : Inexistent source control account ('$conf_username').\n"; exit( 1 ); } # Login as source control user if( !auth_attempt_script_login( $conf_username ) ) { header('HTTP/1.0 500 Invalid MantisBT user'); echo "ERROR : Invalid MantisBT user."; exit( 1 ); } # Retrieve the JSON send by GoogleCode $data_raw = file_get_contents('php://input'); if ( empty($data_raw) or ! ($data = json_decode($data_raw, true)) ) { header('HTTP/1.0 500 Invalid or no data transmitted'); echo "ERROR : Invalid or no data transmitted."; exit( 1 ); } # Retrieve the config items we need $conf_commit_regexp = config_get( 'source_control_regexp' ); $conf_commit_fixed_regexp = config_get( 'source_control_fixed_regexp' ); $conf_googlecode_secretkey = false; $t_googlecode_secretkey_config_item = config_get( 'source_control_googlecode_secretkey' ); if ( ! empty($t_googlecode_secretkey_config_item)) { # This config item could be an array or a string (in order to simplify mono-mantis project conf.) if (is_array($t_googlecode_secretkey_config_item)) { if (array_key_exists($data['project_name'], $t_googlecode_secretkey_config_item)) { $conf_googlecode_secretkey = $t_googlecode_secretkey_config_item[$data['project_name']]; } } else { $conf_googlecode_secretkey = $t_googlecode_secretkey_config_item; } } # Check the signature of the JSON if ($conf_googlecode_secretkey) { if ($_SERVER['HTTP_GOOGLE_CODE_PROJECT_HOSTING_HOOK_HMAC'] != hash_hmac('md5', $data_raw, $conf_googlecode_secretkey)) { # We are quite strict here : if the key has been configured and the # hash doesn't match, we throw a HTTP-203 (to disable Google retries # and be visible in the webserver log) and we just ignore the request header('HTTP/1.0 203 Bad signature'); echo "ERROR : bad signature, message will be ignored.\n"; exit( 1 ); } } # Loop over each revisions in the json data foreach($data['revisions'] as $rev) { $t_comment = $rev['message']; $t_issues = array(); $t_fixed_issues = array(); # Run the regexp if( preg_match_all( $conf_commit_regexp, $rev['message'], $t_matches ) ) { $t_count = count( $t_matches[0] ); for( $i = 0;$i < $t_count;++$i ) { $t_issues[] = $t_matches[1][$i]; } } # Run the "fixed" regexp if( preg_match_all( $conf_commit_fixed_regexp, $rev['message'], $t_matches ) ) { $t_count = count( $t_matches[0] ); for( $i = 0;$i < $t_count;++$i ) { $t_fixed_issues[] = $t_matches[1][$i]; } } # Add info about modifications (commit ID and files added, removed, ...) $t_comment .= "\n\n"; $t_comment .= "Commit: " . $rev['revision'] . "\n"; foreach (array('added', 'modified', 'removed') as $t_action) { if ( ! empty($rev[$t_action])) { foreach ($rev[$t_action] as $t_file) { $t_comment .= ucfirst($t_action) . ' : ' . $t_file . "\n"; } } } # Add the footer in case no key has been configured # TODO : not really clean. And may be a bad idea. if ( ! $conf_googlecode_secretkey ) { $t_comment .= "[warning : no post-commit auth. key has been configured. These data could be a fake.]\n"; } if ( count($t_issues) > 0 or count($t_fixed_issues) > 0 ) { # history parameters are reserved for future use. $t_history_old_value = ''; $t_history_new_value = ''; # add note to each bug only once $t_issues = array_unique( $t_issues ); $t_fixed_issues = array_unique( $t_fixed_issues ); # Call the custom function to register the checkin on each issue. foreach( $t_issues as $t_issue_id ) { if( !in_array( $t_issue_id, $t_fixed_issues ) ) { helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, false ) ); } } foreach( $t_fixed_issues as $t_issue_id ) { helper_call_custom_function( 'checkin', array( $t_issue_id, $t_comment, $t_history_old_value, $t_history_new_value, true ) ); } } } exit( 0 );