[ Index ]

PHP Cross Reference of Phabricator

title

Body

[close]

/src/applications/harbormaster/step/ -> HarbormasterCommandBuildStepImplementation.php (source)

   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  }


Generated: Sun Nov 30 09:20:46 2014 Cross-referenced by PHPXref 0.7.1