[ Index ] |
PHP Cross Reference of Phabricator |
[Summary view] [Print] [Text view]
1 <?php 2 3 final class HarbormasterCommandBuildStepImplementation 4 extends HarbormasterBuildStepImplementation { 5 6 private $platform; 7 8 public function getName() { 9 return pht('Run Command'); 10 } 11 12 public function getGenericDescription() { 13 return pht('Run a command on Drydock host.'); 14 } 15 16 public function getDescription() { 17 return pht( 18 'Run command %s on host %s.', 19 $this->formatSettingForDescription('command'), 20 $this->formatSettingForDescription('hostartifact')); 21 } 22 23 public function escapeCommand($pattern, array $args) { 24 array_unshift($args, $pattern); 25 26 $mode = PhutilCommandString::MODE_DEFAULT; 27 if ($this->platform == 'windows') { 28 $mode = PhutilCommandString::MODE_POWERSHELL; 29 } 30 31 return id(new PhutilCommandString($args)) 32 ->setEscapingMode($mode); 33 } 34 35 public function execute( 36 HarbormasterBuild $build, 37 HarbormasterBuildTarget $build_target) { 38 39 $settings = $this->getSettings(); 40 $variables = $build_target->getVariables(); 41 42 $artifact = $build->loadArtifact($settings['hostartifact']); 43 44 $lease = $artifact->loadDrydockLease(); 45 46 $this->platform = $lease->getAttribute('platform'); 47 48 $command = $this->mergeVariables( 49 array($this, 'escapeCommand'), 50 $settings['command'], 51 $variables); 52 53 $this->platform = null; 54 55 $interface = $lease->getInterface('command'); 56 57 $future = $interface->getExecFuture('%C', $command); 58 59 $log_stdout = $build->createLog($build_target, 'remote', 'stdout'); 60 $log_stderr = $build->createLog($build_target, 'remote', 'stderr'); 61 62 $start_stdout = $log_stdout->start(); 63 $start_stderr = $log_stderr->start(); 64 65 $build_update = 5; 66 67 // Read the next amount of available output every second. 68 $futures = Futures(array($future)); 69 foreach ($futures->setUpdateInterval(1) as $key => $future_iter) { 70 if ($future_iter === null) { 71 72 // Check to see if we should abort. 73 if ($build_update <= 0) { 74 $build->reload(); 75 if ($this->shouldAbort($build, $build_target)) { 76 $future->resolveKill(); 77 throw new HarbormasterBuildAbortedException(); 78 } else { 79 $build_update = 5; 80 } 81 } else { 82 $build_update -= 1; 83 } 84 85 // Command is still executing. 86 87 // Read more data as it is available. 88 list($stdout, $stderr) = $future->read(); 89 $log_stdout->append($stdout); 90 $log_stderr->append($stderr); 91 $future->discardBuffers(); 92 } else { 93 // Command execution is complete. 94 95 // Get the return value so we can log that as well. 96 list($err) = $future->resolve(); 97 98 // Retrieve the last few bits of information. 99 list($stdout, $stderr) = $future->read(); 100 $log_stdout->append($stdout); 101 $log_stderr->append($stderr); 102 $future->discardBuffers(); 103 104 break; 105 } 106 } 107 108 $log_stdout->finalize($start_stdout); 109 $log_stderr->finalize($start_stderr); 110 111 if ($err) { 112 throw new HarbormasterBuildFailureException(); 113 } 114 } 115 116 public function getArtifactInputs() { 117 return array( 118 array( 119 'name' => pht('Run on Host'), 120 'key' => $this->getSetting('hostartifact'), 121 'type' => HarbormasterBuildArtifact::TYPE_HOST, 122 ), 123 ); 124 } 125 126 public function getFieldSpecifications() { 127 return array( 128 'command' => array( 129 'name' => pht('Command'), 130 'type' => 'text', 131 'required' => true, 132 'caption' => pht( 133 'Under Windows, this is executed under PowerShell.'. 134 'Under UNIX, this is executed using the user\'s shell.'), 135 ), 136 'hostartifact' => array( 137 'name' => pht('Host'), 138 'type' => 'text', 139 'required' => true, 140 ), 141 ); 142 } 143 144 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
Generated: Sun Nov 30 09:20:46 2014 | Cross-referenced by PHPXref 0.7.1 |