https://www.mediawiki.org/wiki/Special:Code/MediaWiki/114637

Revision: 114637
Author:   awjrichards
Date:     2012-03-30 23:11:37 +0000 (Fri, 30 Mar 2012)
Log Message:
-----------
Initial import of 'DippyBird', a tool to perform bulk actions on Gerrit 
changesets. Currently supports submitting (with approval +2, verify +1) 
changesets, can eaisly extend to review, abandon, etc.

Added Paths:
-----------
    trunk/tools/gerrit-dippybird/
    trunk/tools/gerrit-dippybird/._dippy-bird.php
    trunk/tools/gerrit-dippybird/dippy-bird.php

Added: trunk/tools/gerrit-dippybird/._dippy-bird.php
===================================================================
(Binary files differ)


Property changes on: trunk/tools/gerrit-dippybird/._dippy-bird.php
___________________________________________________________________
Added: svn:mime-type
   + application/octet-stream

Added: trunk/tools/gerrit-dippybird/dippy-bird.php
===================================================================
--- trunk/tools/gerrit-dippybird/dippy-bird.php                         (rev 0)
+++ trunk/tools/gerrit-dippybird/dippy-bird.php 2012-03-30 23:11:37 UTC (rev 
114637)
@@ -0,0 +1,426 @@
+<?php
+
+$dippy_bird = new DippyBird();
+$dippy_bird->run();
+
+
+class DippyBird {
+       protected $configOpts = array(
+               'port' => array(
+                       'required' => true,
+                       'value' => null,
+               ),
+               'server' => array(
+                       'required' => true,
+                       'value' => null,
+               ),
+               'username' => array(
+                       'required' => true,
+                       'value' => null,
+               ),
+               'query' => array(
+                       'required' => true,
+                       'value' => null,
+               ),
+               'action' => array(
+                       'required' => false,
+                       'value' => null,
+               ),
+               'pretend' => array(
+                       'required' => false,
+                       'value' => false,
+               ),
+               'verbose' => array(
+                       'required' => false,
+                       'value' => false,
+               ),
+               'debug' => array(
+                       'required' => false,
+                       'value' => false,
+               ),
+       );
+       
+       protected $validActions = array(
+               //'approve' => 'executeApprove',
+               //'verify' => 'executeVerify',
+               'submit' => 'executeSubmit',
+               //'abandon' => 'executeAbandon',
+       );
+
+       public function __construct() {
+               // if a config file is present, load it
+               $config_file = dirname( __FILE__ ) . "/" . "config.ini";
+               if ( file_exists( $config_file ) ) {
+                       $this->loadConfiguration( $config_file );
+               }
+       }
+
+       public function run() {
+               $this->handleOpts();
+               if ( !$this->isConfigSane() ) {
+                       // bail and fail
+                       $msg = "There is something wrong in your arguments or 
configuration.";
+                       $this->bail( 1, $msg );
+               }
+               
+               // determine the 'action' to take
+               $action = $this->getConfigOpt( 'action' );
+               $action_method = $this->getActionMethod( $action );
+               
+               // fetch the results of the query
+               $results = $this->executeQuery();
+               
+               // execute the action to take on the query results
+               $this->{$action_method}( $results );
+               
+               echo "Thanks for playing!" . PHP_EOL;
+               echo "<3," . PHP_EOL;
+               echo "Dippy bird" . PHP_EOL;
+       }
+
+       public function executeQuery() {
+               // config options we need
+               $opts = array( 'port', 'server', 'username', 'query' );
+               $config_opts = $this->getConfigOptsByArray( $opts );
+               $cmd = "ssh -p {$config_opts['port']} 
{$config_opts['username']}@{$config_opts['server']} gerrit query 
{$config_opts['query']} --format=JSON --current-patch-set";
+               if ( $this->getConfigOpt( 'verbose' ) ) {
+                       echo "Executing query: " . $cmd . PHP_EOL;
+               }
+               $results = array();
+               exec( escapeshellcmd( $cmd ), $results, $status );
+               if ( $status === 0 ) {
+                       if ( $this->getConfigOpt( 'debug' ) ) {
+                               echo "Query results: " . print_r( $results, 
true ) . PHP_EOL;
+                       }
+                       return $results;
+               } else {
+                       $msg = "There was a problem executing your query." . 
PHP_EOL;
+                       $msg .= "Exiting with status: $status";
+                       $this->bail( $status, $msg );
+               }
+       }
+       
+       public function executeSubmit( $results ) {
+               // If there are less than two items in the array, there are no 
changesets on which to operate
+               if ( count( $results ) < 2 ) {
+                       // nothing to process
+                       return;
+               }
+               
+               // prepare to do... stuff
+               $submitted = 0;
+               $opts = array( 'port', 'server', 'username' );
+               $config_opts = $this->getConfigOptsByArray( $opts );
+               
+               // get the patchset ids form the result set
+               $patchset_ids = self::extractPatchSetIds( $results );
+               
+               // loop through patchsets and submit them one by one
+               foreach ( $patchset_ids as $patchset_id ) {
+                       // prepare command to execute
+                       $cmd = "ssh -p {$config_opts['port']} 
{$config_opts['username']}@{$config_opts['server']} gerrit approve --verified 1 
--code-review 2 --submit $patchset_id";
+
+                       if ( $this->getConfigOpt( 'verbose' ) ) {
+                               echo "Executing: " . $cmd . PHP_EOL;
+                       }
+                       
+                       // should we do this for reals?!
+                       if ( !$this->getConfigOpt( 'pretend' ) ) {
+                               exec( escapeshellcmd( $cmd ), $cmd_results, 
$status );
+                               if ( $status !== 0 ) {
+                                       $msg = "Problem executing submit" . 
PHP_EOL;
+                                       $this->bail( 1, $msg );
+                               }
+                       }
+                       $submitted++;
+               }
+               echo "$submitted changesets submitted." . PHP_EOL;
+       }
+       
+       /**
+        * Extract patchset ids
+        * @param array JSON representations of gerrit changesets
+        * @return array
+        */
+       public static function extractPatchSetIds( $results ) {
+               $patchset_ids = array();
+               foreach ( $results as $result ) {
+                       $patchset_id = self::extractPatchSetId( $result );
+                       if ( !is_null( $patchset_id )) {
+                               $patchset_ids[] = $patchset_id;
+                       }
+               }
+               return $patchset_ids;
+       }
+
+       /** 
+        * Extract patchset id
+        * @param string JSON representation of gerrit changeset
+        * @return mixed patchset id or null
+        */
+       public static function extractPatchSetId( $result ) {
+               $changeset = json_decode( $result, true );
+               if( isset( $changeset['currentPatchSet']['revision'] ) ) {
+                       return $changeset['currentPatchSet']['revision'];
+               }
+               return null;
+       }
+
+       /**
+        * Set $this->configOpts by array of key -> value pairs
+        * @param array
+        */
+       public function setConfigByArray( array $config ) {
+               // don't bother if the array is empty
+               if ( empty( $config ) ) {
+                       return;
+               }
+               
+               // only set valid config opts
+               foreach ( $config as $key => $value ) {
+                       if ( isset( $this->configOpts[ $key ] ) ) {
+                               $this->configOpts[ $key ]['value'] = $value;
+                       }
+               }
+       }
+       
+       /**
+        * Load configuration options from an ini file
+        * @param string Path to configuration file
+        */
+       protected function loadConfiguration( $config_file ) {
+               $config = parse_ini_file( $config_file );
+
+               // do some option clean up....
+               
+               $this->setConfigByArray( $config );
+       }
+       
+       /**
+        * Handle runtime command line options
+        */
+       protected function handleOpts() {
+               $user_opts = getopt( $this->getShortOpts(), 
$this->getLongOpts() );
+
+               // handle 'help' message
+               if ( isset( $user_opts['help'] ) || isset( $user_opts['h'] ) ) {
+                       $this->bail();
+               }
+
+               $config = array();
+               
+               foreach ( $user_opts as $key => $value ) {
+                       switch ( $key ) {
+                               case 'port':
+                               case 'P':
+                                       $config['port'] = $value;
+                                       break;
+                               case 'server':
+                               case 's':
+                                       $config['server'] = $value;
+                                       break;
+                               case 'username':
+                               case 'u':
+                                       $config['username'] = $value;
+                                       break;
+                               case 'query':
+                               case 'q':
+                                       $config['query'] = $value;
+                                       break;
+                               case 'action':
+                               case 'a':
+                                       $config['action'] = $value;
+                                       break;
+                               case 'pretend':
+                               case 'p':
+                                       $config['pretend'] = true;
+                                       break;
+                               case 'verbose':
+                               case 'v':
+                                       $config['verbose'] = true;
+                                       break;
+                               case 'debug':
+                               case 'd':
+                                       // if debug, also set verbose to true
+                                       $config['verbose'] = true;
+                                       $config['debug'] = true;
+                                       break;
+                               default:
+                                       break;
+                       }
+               }
+               
+               $this->setConfigByArray( $config );
+       }
+       
+       /**
+        * Check sanity of configuration values
+        *
+        * If a value is required but unset, config is not sane.
+        */
+       protected function isConfigSane() {
+               foreach ( $this->configOpts as $opt => $info ) {
+                       if ( $info['required'] === true && is_null( 
$info['value'] ) ) {
+                               return false;
+                       }
+               }
+               return true;
+       }
+       
+       /**
+        * Get the 'long' options available
+        */
+       public function getLongOpts() {
+               $long_opts = array(
+                       "port:",
+                       "server:",
+                       "username:",
+                       "query:", 
+                       "action:",
+                       "pretend",
+                       "help",
+                       "verbose",
+                       "debug",
+               );
+               return $long_opts;
+       }
+       
+       /**
+        * Get the 'short' options available
+        */
+       public function getShortOpts() {
+               $short_opts =   "P:";   // port
+               $short_opts .=  "s:";   // server
+               $short_opts .=  "u:";   // username
+               $short_opts .=  "q:";   // gerrit query
+               $short_opts .=  "a:";   // action
+               $short_opts .=  "p";    // pretend
+               $short_opts .= "h";     // help
+               $short_opts .= "v";     // verbose
+               $short_opts .= "d";             // debug
+               return $short_opts;
+       }
+       
+       /**
+        * Fetch usage message
+        */
+       public function getUsage() {
+               $usage = <<<USAGE
+
+Purpose: Perform bulk actions on Gerrit changesets
+
+Description: Given a gerrit search query, perform a selected 'aciton'. Valid
+actions currently include:
+       submit: Verify, approve, and submit changeset
+
+Usage: php dippy-bird.php --username=<username> --server=<gerrit servername>
+               --port=<gerrit port> [--verbose] [--debug] [--help]
+               --action=<action> --query=<query>
+       
+Required parameters:
+       --username, -u          Username you use to log in to Gerrit
+       --server, -s            Hostname of the Gerrit server
+       --port, -P              Port where Gerrit is running
+       --query, -q             Gerrit query (See docs: http://bit.ly/H9bYiq)
+       --action, -a            Action to take after running query
+       
+Optional options:
+       --pretend, -p           Executes query but not action
+       --verbose, -v           Run in 'verbose' mode
+       --debug, -d             Run in 'debug' mode
+       --help, -h              Display this help message
+
+Configuration options can also be set using the longoption names placed in
+a 'config.ini' file in the same directory as this script.
+
+USAGE;
+               return $usage;
+       }
+       
+       /**
+        * Print usage message and die
+        * @param int Status code with which to exit
+        */
+       public function bail( $status = 0, $msg = null ) {
+               if ( !is_null( $msg ) ) {
+                       echo $msg . PHP_EOL;
+               }
+               echo $this->getUsage();
+               echo PHP_EOL;
+               exit( intval( $status ) );
+       }
+       
+       /**
+        * Fetch $this->configOpts
+        */
+       public function getConfigOpts() {
+               return $this->configOpts;
+       }
+       
+       /**
+        * Fetch a specified configuration option
+        *
+        * @param $opt string The name of the option
+        * @param $verbose bool If true, returns full config opt array, 
otherwise
+        *              just returns the config opt's value
+        * @return mixed string|array|null Returns null if the config opt does
+        *              not exist.
+        */
+       public function getConfigOpt( $opt, $verbose = false ) {
+               if ( isset( $this->configOpts[ $opt ] ) ) {
+                       if ( $verbose === false ) {
+                               return $this->configOpts[ $opt ]['value'];
+                       } else {
+                               return $this->configOpts[ $opt ];
+                       }
+               }
+               return null;
+       }
+       
+       /**
+        * Fetch multiple config option values
+        * @param array Config option names to fetch
+        * @return array Option name => value
+        */
+       public function getConfigOptsByArray( array $opts ) {
+               $config_opts = array();
+               foreach ( $opts as $opt ) {
+                       $config_opts[ $opt ] = $this->getConfigOpt( $opt );
+               }
+               return $config_opts;
+       }
+       
+       /**
+        * Determine whether or not requested action is valid to take
+        *
+        * Valid actions are defined in $this->validActions
+        * @param string
+        * @return bool
+        */
+       public function isValidAction( $action ) {
+               if ( isset( $this->validActions[ $action ] ) ) {
+                       return true;
+               }
+               return false;
+       }
+       
+       /** 
+        * Fetch the method name corresponding to a specific 'action'
+        * 
+        * If the action is not valid, fail and bail.
+        * @param string
+        * @return string
+        */
+       public function getActionMethod( $action ) {
+               if ( !$this->isValidAction( $action ) ) {
+                       $msg = "Invalid action requested" . PHP_EOL;
+                       $msg .= "Valid actions include:" . PHP_EOL;
+                       foreach( $this->validActions as $action => $method ) {
+                               $msg .= "\t$action" . PHP_EOL;
+                       }
+                       $this->bail( 1, $msg );
+               } 
+               return $this->validActions[ $action ];
+       }
+       
+}
\ No newline at end of file


_______________________________________________
MediaWiki-CVS mailing list
MediaWiki-CVS@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs

Reply via email to