Index: trunk/tools/testswarm/scripts/testswarm-mw-fetcher-run.php |
— | — | @@ -51,6 +51,7 @@ |
52 | 52 | 'debug' => false, |
53 | 53 | 'root' => '/var/lib/testswarm/mediawiki-trunk', |
54 | 54 | 'svnUrl' => 'http://svn.wikimedia.org/svnroot/mediawiki/trunk/phase3', |
| 55 | + 'testPattern' => '/checkouts/mw/trunk/r$1/tests/qunit/?filter=$2', |
55 | 56 | 'minRev' => 105305, |
56 | 57 | ); |
57 | 58 | break; |
— | — | @@ -63,4 +64,18 @@ |
64 | 65 | require_once( __DIR__ . '/testswarm-mw-fetcher.php' ); |
65 | 66 | |
66 | 67 | $main = new TestSwarmMWMain( $options ); |
67 | | -$main->tryFetchNextRev(); |
| 68 | +$rev = $main->tryFetchNextRev(); |
| 69 | + |
| 70 | +if( $rev === false ) { |
| 71 | + print "No new revision, nothing left to do. Exiting.\n"; |
| 72 | + exit; |
| 73 | +} |
| 74 | + |
| 75 | +$fetcher_conf = parse_ini_file( "/etc/testswarm/fetcher.ini", true ); |
| 76 | +$api = new TestSwarmAPI( |
| 77 | + $main |
| 78 | + , $fetcher_conf['TestSwarmAPI']['username'] |
| 79 | + , $fetcher_conf['TestSwarmAPI']['authtoken'] |
| 80 | + , $fetcher_conf['TestSwarmAPI']['url'] |
| 81 | +); |
| 82 | +$api->doAddJob( $rev ); |
Index: trunk/tools/testswarm/scripts/fetcher-sample.ini |
— | — | @@ -0,0 +1,28 @@ |
| 2 | +; Configuration MediaWiki testswarm fetcher |
| 3 | +; |
| 4 | +; This file is read by the testswarm-mw-fetcher-run.php script to |
| 5 | +; authenticate itself on your TestSwarm installation. |
| 6 | +; It must be available as /etc/testswarm/fetcher.ini |
| 7 | +; |
| 8 | +; You will have to manually create a username using your local TestSwarm |
| 9 | +; installation web interface. Upon user creation, TestSwarm generates an |
| 10 | +; authentication token which can be used by scripts without revealing |
| 11 | +; the user password. |
| 12 | +; |
| 13 | +[TestSwarmAPI] |
| 14 | + |
| 15 | +; Username on testswarm used for submitting job |
| 16 | +username = "MediaWiki" |
| 17 | + |
| 18 | +; The token is 32 hexadecimals characters and need to be fetched from |
| 19 | +; the database manually: |
| 20 | +; |
| 21 | +; mysql -p -u testswarm testswarm |
| 22 | +; mysql> SELECT auth FROM users WHERE name='MediaWiki' \G |
| 23 | +; *************************** 1. row *************************** |
| 24 | +; auth: 1234567890123456789012345678912345678912 |
| 25 | +; 1 row in set (0.00 sec) |
| 26 | +authtoken = "" |
| 27 | + |
| 28 | +; URL for your TestSwarm repository |
| 29 | +url = "http://localhost/testswarm/" |
Index: trunk/tools/testswarm/scripts/testswarm-mw-fetcher.php |
— | — | @@ -54,12 +54,15 @@ |
55 | 55 | /** Path to log file */ |
56 | 56 | protected $logPath; |
57 | 57 | |
| 58 | + /** URL pattern to add one test. $1 is rev, $2 testname */ |
| 59 | + protected $testPattern = "/checkouts/mw/trunk/r$1/tests/qunit/?filter=$2"; |
58 | 60 | |
59 | 61 | /** GETTERS **/ |
60 | 62 | |
61 | 63 | public function getSvnCmd() { return $this->svnCmd; } |
62 | 64 | public function getSvnUrl() { return $this->svnUrl; } |
63 | 65 | public function getLogPath() { return $this->logPath; } |
| 66 | + public function getTestPattern() { return $this->testPattern; } |
64 | 67 | |
65 | 68 | |
66 | 69 | /** SETTERS **/ |
— | — | @@ -114,6 +117,10 @@ |
115 | 118 | $this->minRev = $options['minRev']; |
116 | 119 | } |
117 | 120 | |
| 121 | + if ( isset( $options['testPattern'] ) ) { |
| 122 | + $this->testPattern = $options['testPattern']; |
| 123 | + } |
| 124 | + |
118 | 125 | return $this; |
119 | 126 | } |
120 | 127 | |
— | — | @@ -124,19 +131,23 @@ |
125 | 132 | public function tryFetchNextRev() { |
126 | 133 | $this->prepareRootDirs(); |
127 | 134 | |
| 135 | + $result = false; |
128 | 136 | // Now find out the next revision in the remote repository |
129 | | - $next = $this->getNextCheckoutRevId(); |
130 | | - if ( !$next ) { |
| 137 | + $nextRev = $this->getNextCheckoutRevId(); |
| 138 | + if ( !$nextRev ) { |
131 | 139 | $this->debug( 'No next revision', __METHOD__ ); |
132 | | - return false; |
133 | 140 | } else { |
134 | 141 | // And install it |
135 | | - $fetcher = new TestSwarmMWFetcher( &$this, $next ); |
136 | | - return $fetcher->run(); |
| 142 | + $fetcher = new TestSwarmMWFetcher( &$this, $nextRev ); |
| 143 | + $result = $fetcher->run(); |
| 144 | + if( $result === true ) { |
| 145 | + return $nextRev; |
| 146 | + } |
137 | 147 | } |
| 148 | + |
| 149 | + return $result; |
138 | 150 | } |
139 | 151 | |
140 | | - |
141 | 152 | /** SVN REVISION HELPERS **/ |
142 | 153 | |
143 | 154 | /** |
— | — | @@ -214,8 +225,6 @@ |
215 | 226 | } else { |
216 | 227 | $next = $this->getNextFollowingRevId( $cur ); |
217 | 228 | } |
218 | | - |
219 | | - $this->debug( __METHOD__ . ": Going to use r{$next}" ); |
220 | 229 | return $next; |
221 | 230 | } |
222 | 231 | |
— | — | @@ -247,8 +256,8 @@ |
248 | 257 | * @return Array of paths relevant for an install. |
249 | 258 | */ |
250 | 259 | public function getPathsForRev( $id ) { |
251 | | - if ( !is_int( $id ) ) { |
252 | | - throw new Exception( __METHOD__ . ': Given non numerical revision' ); |
| 260 | + if ( !is_numeric( $id ) ) { |
| 261 | + throw new Exception( __METHOD__ . ": Given non numerical revision " . var_export($id, true) ); |
253 | 262 | } |
254 | 263 | |
255 | 264 | return array( |
— | — | @@ -296,7 +305,6 @@ |
297 | 306 | * @param $path String Path to create ex: /tmp/my/foo/bar |
298 | 307 | */ |
299 | 308 | public function mkdir( $path ) { |
300 | | - $this->debug( "Attempting to create directory '$path'...", __METHOD__ ); |
301 | 309 | if ( !file_exists( $path ) ) { |
302 | 310 | if ( @mkdir( $path, 0777, true ) ) { |
303 | 311 | $this->debug( "Created directory '$path'", __METHOD__ ); |
— | — | @@ -304,8 +312,6 @@ |
305 | 313 | print "Could not create directory '$path'. Exiting.\n"; |
306 | 314 | exit(1); |
307 | 315 | } |
308 | | - } else { |
309 | | - $this->debug( "Creating directory '$path' aborted. Directory already exist", __METHOD__ ); |
310 | 316 | } |
311 | 317 | } |
312 | 318 | |
— | — | @@ -387,8 +393,8 @@ |
388 | 394 | $this->main->log( "Run for r{$this->svnRevId} started", __METHOD__ ); |
389 | 395 | |
390 | 396 | $this->doCheckout(); |
391 | | - $this->doInstall(); |
392 | | - $this->doAppendSettings(); |
| 397 | + #$this->doInstall(); |
| 398 | + #$this->doAppendSettings(); |
393 | 399 | |
394 | 400 | /** |
395 | 401 | * @todo FIXME: |
— | — | @@ -396,6 +402,7 @@ |
397 | 403 | * - Make POST request to TestSwarm install to add jobs for these test runs |
398 | 404 | * (CURL addjob.php with login/auth token) |
399 | 405 | */ |
| 406 | + return true; |
400 | 407 | } |
401 | 408 | |
402 | 409 | /** |
— | — | @@ -501,3 +508,94 @@ |
502 | 509 | return true; |
503 | 510 | } |
504 | 511 | } |
| 512 | + |
| 513 | +class TestSwarmAPI { |
| 514 | + public $URL; |
| 515 | + private $user; |
| 516 | + private $authToken; |
| 517 | + |
| 518 | + /** |
| 519 | + * Initialize a testswarm instance |
| 520 | + * @param $user String A testswarm username |
| 521 | + * @param $authtoken String associated user authentication token |
| 522 | + * @param $URL String URL to the testswarm instance. Default: |
| 523 | + * http://localhost/testswarm |
| 524 | + */ |
| 525 | + public function __construct( TestSwarmMWMain $context, $user, $authtoken, |
| 526 | + $URL = 'http://localhost/testswarm' |
| 527 | + ) { |
| 528 | + $this->context = $context; |
| 529 | + $this->URL = $URL; |
| 530 | + $this->user = $user; |
| 531 | + $this->authToken = $authtoken; |
| 532 | + |
| 533 | + // FIXME check user auth before continuing. |
| 534 | + } |
| 535 | + |
| 536 | + /** |
| 537 | + * Add a job to the Testswarm instance |
| 538 | + * FIXME: lot of hardcoded options there 8-) |
| 539 | + */ |
| 540 | + public function doAddJob( $revision ) { |
| 541 | + $params = array( |
| 542 | + "state" => "addjob", |
| 543 | + "output" => "dump", |
| 544 | + "user" => $this->user, |
| 545 | + "auth" => $this->authToken, |
| 546 | + "max" => 3, |
| 547 | + "job_name" => "MediaWiki trunk r{$revision}", |
| 548 | + "browsers" => "popularbetamobile", |
| 549 | + ); |
| 550 | + $query = http_build_query( $params ); |
| 551 | + |
| 552 | + $localPaths = $this->context->getPathsForRev( $revision ); |
| 553 | + |
| 554 | + $filenames = array_map( 'basename', |
| 555 | + glob( $localPaths['mw'] . "/tests/qunit/suites/resources/*/*.js" ) |
| 556 | + ); |
| 557 | + |
| 558 | + # Append each of our test file to the job query submission |
| 559 | + foreach( $filenames as $filename) { |
| 560 | + if ( substr( $filename, -8 ) === '.test.js' ) { |
| 561 | + $suiteName = substr( $filename, 0, -8 ); |
| 562 | + $pattern = $this->context->getTestPattern(); |
| 563 | + |
| 564 | + $testUrl = str_replace( array( '$1', '$2' ), |
| 565 | + array( rawurlencode($revision), rawurlencode($suiteName) ), |
| 566 | + $pattern |
| 567 | + ); |
| 568 | + $query .= |
| 569 | + "&suites[]=" . rawurlencode( $suiteName ) . |
| 570 | + "&urls[]=" . $testUrl."\n"; |
| 571 | + } |
| 572 | + } |
| 573 | + |
| 574 | + //print "Testswarm base URL: {$this->URL}\n"; |
| 575 | + //print "Queries: $query\n"; |
| 576 | + |
| 577 | + # Forge curl request and submit it |
| 578 | + $ch = curl_init(); |
| 579 | + curl_setopt_array( $ch, array( |
| 580 | + CURLOPT_RETURNTRANSFER => 1 |
| 581 | + , CURLOPT_USERAGENT => "TestSwarm-fetcher (ContInt; hashar)" |
| 582 | + , CURLOPT_SSL_VERIFYHOST => FALSE |
| 583 | + , CURLOPT_SSL_VERIFYPEER => FALSE |
| 584 | + , CURLOPT_POST => TRUE |
| 585 | + , CURLOPT_URL => $this->URL |
| 586 | + , CURLOPT_POSTFIELDS => $query |
| 587 | + )); |
| 588 | + $ret = curl_exec( $ch ); |
| 589 | + $err = curl_errno( $ch ); |
| 590 | + $error = curl_error( $ch ); |
| 591 | + |
| 592 | + if( !$ret ) { |
| 593 | + $this->context->log( |
| 594 | + "Curl returned an error: #$err, $error\n" |
| 595 | + ); |
| 596 | + return false; |
| 597 | + } |
| 598 | + |
| 599 | + $this->context->log( $ret ); |
| 600 | + return true; |
| 601 | + } |
| 602 | +} |
Property changes on: trunk/tools/testswarm/scripts |
___________________________________________________________________ |
Added: svn:ignore |
505 | 603 | + fetcher.ini |