@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add HarbormasterRunnerWorker, for running CI tests

Summary:
This is very preliminary and doesn't actually do anything useful. In theory, it uses Drydock to check out a working copy and run tests. In practice, it's not actually capable of running any of our tests (because of complicated interdependency stuff), but does check out a working copy and //try// to run tests there.

Adds various sorts of utility methods to various things as well.

Test Plan: Ran `reparse.php --harbormaster --trace <commit>`, observed attempt to run tests via Drydock.

Reviewers: btrahan

Reviewed By: btrahan

CC: aran

Maniphest Tasks: T2015, T1049

Differential Revision: https://secure.phabricator.com/D4215

+142 -5
+12 -3
scripts/repository/reparse.php
··· 55 55 'delete existing relationship entries between your '. 56 56 'package and some old commits!)', 57 57 ), 58 + array( 59 + 'name' => 'harbormaster', 60 + 'help' => 'EXPERIMENTAL. Execute Harbormaster.', 61 + ), 58 62 // misc options 59 63 array( 60 64 'name' => 'force', ··· 73 77 $reparse_change = $args->getArg('change'); 74 78 $reparse_herald = $args->getArg('herald'); 75 79 $reparse_owners = $args->getArg('owners'); 80 + $reparse_harbormaster = $args->getArg('harbormaster'); 76 81 $reparse_what = $args->getArg('revision'); 77 82 $force = $args->getArg('force'); 78 83 $force_local = $args->getArg('force-local'); ··· 83 88 } 84 89 85 90 if (!$reparse_message && !$reparse_change && !$reparse_herald && 86 - !$reparse_owners) { 91 + !$reparse_owners && !$reparse_harbormaster) { 87 92 usage("Specify what information to reparse with --message, --change, ". 88 - "--herald, and/or --owners"); 93 + "--herald, --harbormaster, and/or --owners"); 89 94 } 90 95 if ($reparse_owners && !$force) { 91 96 echo phutil_console_wrap( ··· 202 207 $classes[] = 'PhabricatorRepositoryCommitOwnersWorker'; 203 208 } 204 209 210 + if ($reparse_harbormaster) { 211 + $classes[] = 'HarbormasterRunnerWorker'; 212 + } 213 + 205 214 $spec = array( 206 215 'commitID' => $commit->getID(), 207 216 'only' => true, ··· 218 227 foreach ($classes as $class) { 219 228 $worker = newv($class, array($spec)); 220 229 echo "Running '{$class}'...\n"; 221 - $worker->doWork(); 230 + $worker->executeTask(); 222 231 } 223 232 } 224 233 }
+2
src/__phutil_library_map__.php
··· 456 456 'FeedPublisherWorker' => 'applications/feed/worker/FeedPublisherWorker.php', 457 457 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', 458 458 'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php', 459 + 'HarbormasterRunnerWorker' => 'applications/harbormaster/worker/HarbormasterRunnerWorker.php', 459 460 'HarbormasterScratchTable' => 'applications/harbormaster/storage/HarbormasterScratchTable.php', 460 461 'HeraldAction' => 'applications/herald/storage/HeraldAction.php', 461 462 'HeraldActionConfig' => 'applications/herald/config/HeraldActionConfig.php', ··· 1744 1745 'FeedPublisherWorker' => 'PhabricatorWorker', 1745 1746 'HarbormasterDAO' => 'PhabricatorLiskDAO', 1746 1747 'HarbormasterObject' => 'HarbormasterDAO', 1748 + 'HarbormasterRunnerWorker' => 'PhabricatorWorker', 1747 1749 'HarbormasterScratchTable' => 'HarbormasterDAO', 1748 1750 'HeraldAction' => 'HeraldDAO', 1749 1751 'HeraldApplyTranscript' => 'HeraldDAO',
+11
src/applications/drydock/blueprint/DrydockBlueprint.php
··· 22 22 return get_class($this); 23 23 } 24 24 25 + protected function loadLease($lease_id) { 26 + $lease = id(new DrydockLease())->load($lease_id); 27 + if (!$lease) { 28 + throw new Exception("No such lease '{$lease_id}'!"); 29 + } 30 + 31 + $resource = $lease->loadResource(); 32 + $lease->attachResource($resource); 33 + return $lease; 34 + } 35 + 25 36 26 37 /* -( Lease Acquisition )-------------------------------------------------- */ 27 38
+7
src/applications/drydock/blueprint/DrydockWorkingCopyBlueprint.php
··· 86 86 DrydockLease $lease, 87 87 $type) { 88 88 89 + switch ($type) { 90 + case 'command': 91 + return $this 92 + ->loadLease($resource->getAttribute('lease.host')) 93 + ->getInterface($type); 94 + } 95 + 89 96 throw new Exception("No interface of type '{$type}'."); 90 97 } 91 98
+24
src/applications/drydock/interface/command/DrydockCommandInterface.php
··· 2 2 3 3 abstract class DrydockCommandInterface extends DrydockInterface { 4 4 5 + private $workingDirectory; 6 + 7 + public function setWorkingDirectory($working_directory) { 8 + $this->workingDirectory = $working_directory; 9 + return $this; 10 + } 11 + 12 + public function getWorkingDirectory() { 13 + return $this->workingDirectory; 14 + } 15 + 5 16 final public function getInterfaceType() { 6 17 return 'command'; 7 18 } ··· 23 34 } 24 35 25 36 abstract public function getExecFuture($command); 37 + 38 + protected function applyWorkingDirectoryToArgv(array $argv) { 39 + if ($this->getWorkingDirectory() !== null) { 40 + $cmd = $argv[0]; 41 + $cmd = "(cd %s; {$cmd})"; 42 + $argv = array_merge( 43 + array($cmd), 44 + array($this->getWorkingDirectory()), 45 + array_slice($argv, 1)); 46 + } 47 + 48 + return $argv; 49 + } 26 50 27 51 }
+2
src/applications/drydock/interface/command/DrydockLocalCommandInterface.php
··· 4 4 5 5 public function getExecFuture($command) { 6 6 $argv = func_get_args(); 7 + $argv = $this->applyWorkingDirectoryToArgv($argv); 8 + 7 9 return newv('ExecFuture', $argv); 8 10 } 9 11
+2
src/applications/drydock/interface/command/DrydockSSHCommandInterface.php
··· 4 4 5 5 public function getExecFuture($command) { 6 6 $argv = func_get_args(); 7 + $argv = $this->applyWorkingDirectoryToArgv($argv); 8 + 7 9 $full_command = call_user_func_array('csprintf', $argv); 8 10 9 11 // NOTE: The "-t -t" is for psuedo-tty allocation so we can "sudo" on some
+30 -2
src/applications/drydock/storage/DrydockLease.php
··· 11 11 protected $taskID; 12 12 13 13 private $resource; 14 + private $releaseOnDestruction; 15 + 16 + /** 17 + * Flag this lease to be released when its destructor is called. This is 18 + * mostly useful if you have a script which acquires, uses, and then releases 19 + * a lease, as you don't need to explicitly handle exceptions to properly 20 + * release the lease. 21 + */ 22 + public function releaseOnDestruction() { 23 + $this->releaseOnDestruction = true; 24 + return $this; 25 + } 26 + 27 + public function __destruct() { 28 + if ($this->releaseOnDestruction) { 29 + if ($this->isActive()) { 30 + $this->release(); 31 + } 32 + } 33 + } 14 34 15 35 public function getLeaseName() { 16 36 return pht('Lease %d', $this->getID()); ··· 103 123 return $this; 104 124 } 105 125 126 + private function isActive() { 127 + switch ($this->status) { 128 + case DrydockLeaseStatus::STATUS_ACTIVE: 129 + case DrydockLeaseStatus::STATUS_ACQUIRING: 130 + return true; 131 + } 132 + return false; 133 + } 134 + 106 135 private function assertActive() { 107 - if (($this->status != DrydockLeaseStatus::STATUS_ACTIVE) && 108 - ($this->status != DrydockLeaseStatus::STATUS_ACQUIRING)) { 136 + if (!$this->isActive()) { 109 137 throw new Exception( 110 138 "Lease is not active! You can not interact with resources through ". 111 139 "an inactive lease.");
+52
src/applications/harbormaster/worker/HarbormasterRunnerWorker.php
··· 1 + <?php 2 + 3 + final class HarbormasterRunnerWorker extends PhabricatorWorker { 4 + 5 + public function getRequiredLeaseTime() { 6 + return 60 * 60 * 24; 7 + } 8 + 9 + protected function doWork() { 10 + $data = $this->getTaskData(); 11 + $id = idx($data, 'commitID'); 12 + 13 + $commit = id(new PhabricatorRepositoryCommit())->loadOneWhere( 14 + 'id = %d', 15 + $id); 16 + 17 + if (!$commit) { 18 + throw new PhabricatorWorkerPermanentFailureException( 19 + "Commit '{$id}' does not exist!"); 20 + } 21 + 22 + $repository = id(new PhabricatorRepository())->loadOneWhere( 23 + 'id = %d', 24 + $commit->getRepositoryID()); 25 + 26 + if (!$repository) { 27 + throw new PhabricatorWorkerPermanentFailureException( 28 + "Unable to load repository for commit '{$id}'!"); 29 + } 30 + 31 + $lease = id(new DrydockLease()) 32 + ->setResourceType('working-copy') 33 + ->setAttributes( 34 + array( 35 + 'repositoryID' => $repository->getID(), 36 + 'commit' => $commit->getCommitIdentifier(), 37 + )) 38 + ->releaseOnDestruction() 39 + ->waitUntilActive(); 40 + 41 + $cmd = $lease->getInterface('command'); 42 + list($json) = $cmd 43 + ->setWorkingDirectory($lease->getResource()->getAttribute('path')) 44 + ->execx('arc unit --everything --json'); 45 + $lease->release(); 46 + 47 + // TODO: Do something actually useful with this. Requires Harbormaster 48 + // buildout. 49 + echo $json; 50 + } 51 + 52 + }