Page MenuHomePhabricator

D7825.id17702.diff
No OneTemporary

D7825.id17702.diff

Index: bin/harbormaster
===================================================================
--- /dev/null
+++ bin/harbormaster
@@ -0,0 +1 @@
+../scripts/setup/manage_harbormaster.php
\ No newline at end of file
Index: scripts/setup/manage_harbormaster.php
===================================================================
--- /dev/null
+++ scripts/setup/manage_harbormaster.php
@@ -0,0 +1,22 @@
+#!/usr/bin/env php
+<?php
+
+$root = dirname(dirname(dirname(__FILE__)));
+require_once $root.'/scripts/__init_script__.php';
+
+$args = new PhutilArgumentParser($argv);
+$args->setTagline('manage Harbormaster');
+$args->setSynopsis(<<<EOSYNOPSIS
+**harbormaster** __command__ [__options__]
+ Manage and debug Harbormaster.
+
+EOSYNOPSIS
+ );
+$args->parseStandardArguments();
+
+$workflows = id(new PhutilSymbolLoader())
+ ->setAncestorClass('HarbormasterManagementWorkflow')
+ ->loadObjects();
+$workflows[] = new PhutilHelpArgumentWorkflow();
+
+$args->parseWorkflows($workflows);
Index: src/__phutil_library_map__.php
===================================================================
--- src/__phutil_library_map__.php
+++ src/__phutil_library_map__.php
@@ -707,6 +707,7 @@
'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php',
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
+ 'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php',
'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php',
'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php',
'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php',
@@ -715,6 +716,8 @@
'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php',
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php',
+ 'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php',
+ 'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php',
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
'HarbormasterPHIDTypeBuild' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuild.php',
'HarbormasterPHIDTypeBuildItem' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildItem.php',
@@ -2747,6 +2750,7 @@
array(
0 => 'DifferentialDAO',
1 => 'PhabricatorPolicyInterface',
+ 2 => 'HarbormasterBuildableInterface',
),
'DifferentialDiffContentMail' => 'DifferentialMail',
'DifferentialDiffCreateController' => 'DifferentialController',
@@ -2814,6 +2818,7 @@
2 => 'PhabricatorPolicyInterface',
3 => 'PhabricatorFlaggableInterface',
4 => 'PhrequentTrackableInterface',
+ 5 => 'HarbormasterBuildableInterface',
),
'DifferentialRevisionCommentListView' => 'AphrontView',
'DifferentialRevisionCommentView' => 'AphrontView',
@@ -3131,6 +3136,7 @@
array(
0 => 'HarbormasterDAO',
1 => 'PhabricatorPolicyInterface',
+ 2 => 'HarbormasterBuildableInterface',
),
'HarbormasterBuildableListController' =>
array(
@@ -3144,6 +3150,8 @@
'HarbormasterController' => 'PhabricatorController',
'HarbormasterDAO' => 'PhabricatorLiskDAO',
'HarbormasterHTTPRequestBuildStepImplementation' => 'VariableBuildStepImplementation',
+ 'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow',
+ 'HarbormasterManagementWorkflow' => 'PhutilArgumentWorkflow',
'HarbormasterObject' => 'HarbormasterDAO',
'HarbormasterPHIDTypeBuild' => 'PhabricatorPHIDType',
'HarbormasterPHIDTypeBuildItem' => 'PhabricatorPHIDType',
@@ -4342,6 +4350,7 @@
1 => 'PhabricatorPolicyInterface',
2 => 'PhabricatorFlaggableInterface',
3 => 'PhabricatorTokenReceiverInterface',
+ 4 => 'HarbormasterBuildableInterface',
),
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',
Index: src/applications/differential/storage/DifferentialDiff.php
===================================================================
--- src/applications/differential/storage/DifferentialDiff.php
+++ src/applications/differential/storage/DifferentialDiff.php
@@ -2,7 +2,9 @@
final class DifferentialDiff
extends DifferentialDAO
- implements PhabricatorPolicyInterface {
+ implements
+ PhabricatorPolicyInterface,
+ HarbormasterBuildableInterface {
protected $revisionID;
protected $authorPHID;
@@ -339,4 +341,24 @@
return null;
}
+
+
+/* -( HarbormasterBuildableInterface )------------------------------------- */
+
+
+ public function getHarbormasterBuildablePHID() {
+ return $this->getPHID();
+ }
+
+ public function getHarbormasterContainerPHID() {
+ if ($this->getRevisionID()) {
+ $revision = id(new DifferentialRevision())->load($this->getRevisionID());
+ if ($revision) {
+ return $revision->getPHID();
+ }
+ }
+
+ return null;
+ }
+
}
Index: src/applications/differential/storage/DifferentialRevision.php
===================================================================
--- src/applications/differential/storage/DifferentialRevision.php
+++ src/applications/differential/storage/DifferentialRevision.php
@@ -5,7 +5,8 @@
PhabricatorTokenReceiverInterface,
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
- PhrequentTrackableInterface {
+ PhrequentTrackableInterface,
+ HarbormasterBuildableInterface {
protected $title = '';
protected $originalTitle;
@@ -412,4 +413,16 @@
return DifferentialRevisionStatus::isClosedStatus($this->getStatus());
}
+
+/* -( HarbormasterBuildableInterface )------------------------------------- */
+
+
+ public function getHarbormasterBuildablePHID() {
+ return $this->loadActiveDiff()->getPHID();
+ }
+
+ public function getHarbormasterContainerPHID() {
+ return $this->getPHID();
+ }
+
}
Index: src/applications/harbormaster/controller/HarbormasterPlanRunController.php
===================================================================
--- src/applications/harbormaster/controller/HarbormasterPlanRunController.php
+++ src/applications/harbormaster/controller/HarbormasterPlanRunController.php
@@ -41,16 +41,10 @@
->withNames(array($v_name))
->executeOne();
- if ($object instanceof DifferentialRevision) {
- $revision = $object;
- $object = $object->loadActiveDiff();
+ if ($object instanceof HarbormasterBuildableInterface) {
$buildable
- ->setBuildablePHID($object->getPHID())
- ->setContainerPHID($revision->getPHID());
- } else if ($object instanceof PhabricatorRepositoryCommit) {
- $buildable
- ->setBuildablePHID($object->getPHID())
- ->setContainerPHID($object->getRepository()->getPHID());
+ ->setBuildablePHID($object->getHarbormasterBuildablePHID())
+ ->setContainerPHID($object->getHarbormasterContainerPHID());
} else {
$e_name = pht('Invalid');
$errors[] = pht('Enter the name of a revision or commit.');
@@ -62,6 +56,7 @@
if (!$errors) {
$buildable->save();
+ $buildable->applyPlan($plan);
$buildable_uri = '/B'.$buildable->getID();
return id(new AphrontRedirectResponse())->setURI($buildable_uri);
@@ -80,8 +75,12 @@
->setUser($viewer)
->appendRemarkupInstructions(
pht(
- "Enter the name of a commit or revision to run this plan on.\n\n".
- "For example: `rX123456` or `D123`"))
+ "Enter the name of a commit or revision to run this plan on (for ".
+ "example, `rX123456` or `D123`).\n\n".
+ "For more detailed output, you can also run manual builds from ".
+ "the command line:\n\n".
+ " phabricator/ $ ./bin/harbormaster build <object> --plan %s",
+ $plan->getID()))
->appendChild(
id(new AphrontFormTextControl())
->setLabel('Buildable Name')
@@ -90,7 +89,7 @@
->setValue($v_name));
$dialog = id(new AphrontDialogView())
- ->setWidth(AphrontDialogView::WIDTH_FORM)
+ ->setWidth(AphrontDialogView::WIDTH_FULL)
->setUser($viewer)
->setTitle($title)
->appendChild($form)
Index: src/applications/harbormaster/event/HarbormasterUIEventListener.php
===================================================================
--- src/applications/harbormaster/event/HarbormasterUIEventListener.php
+++ src/applications/harbormaster/event/HarbormasterUIEventListener.php
@@ -24,12 +24,19 @@
return;
}
- $target = null;
- if ($object instanceof PhabricatorRepositoryCommit) {
- $target = $object;
- } elseif ($object instanceof DifferentialRevision) {
- $target = $object->loadActiveDiff();
- } else {
+ if ($object instanceof HarbormasterBuildable) {
+ // Although HarbormasterBuildable implements the correct interface, it
+ // does not make sense to show a build's build status. In the best case
+ // it is meaningless, and in the worst case it's confusing.
+ return;
+ }
+
+ if (!($object instanceof HarbormasterBuildableInterface)) {
+ return;
+ }
+
+ $buildable_phid = $object->getBuildablePHID();
+ if (!$buildable_phid) {
return;
}
@@ -39,7 +46,8 @@
$buildables = id(new HarbormasterBuildableQuery())
->setViewer($user)
- ->withBuildablePHIDs(array($target->getPHID()))
+ ->withManualBuildables(false)
+ ->withBuildablePHIDs(array($buildable_phid))
->execute();
if (!$buildables) {
return;
@@ -62,8 +70,7 @@
foreach ($builds as $build) {
$item = new PHUIStatusItemView();
- $item->setTarget(
- $build_handles[$build->getPHID()]->renderLink());
+ $item->setTarget($build_handles[$build->getPHID()]->renderLink());
switch ($build->getBuildStatus()) {
case HarbormasterBuild::STATUS_INACTIVE:
Index: src/applications/harbormaster/interface/HarbormasterBuildableInterface.php
===================================================================
--- /dev/null
+++ src/applications/harbormaster/interface/HarbormasterBuildableInterface.php
@@ -0,0 +1,8 @@
+<?php
+
+interface HarbormasterBuildableInterface {
+
+ public function getHarbormasterBuildablePHID();
+ public function getHarbormasterContainerPHID();
+
+}
Index: src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php
===================================================================
--- /dev/null
+++ src/applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php
@@ -0,0 +1,92 @@
+<?php
+
+final class HarbormasterManagementBuildWorkflow
+ extends HarbormasterManagementWorkflow {
+
+ public function didConstruct() {
+ $this
+ ->setName('build')
+ ->setExamples('**build** [__options__] __buildable__ --plan __id__')
+ ->setSynopsis(pht('Run plan __id__ on __buildable__.'))
+ ->setArguments(
+ array(
+ array(
+ 'name' => 'plan',
+ 'param' => 'id',
+ 'help' => pht('ID of build plan to run.'),
+ ),
+ array(
+ 'name' => 'buildable',
+ 'wildcard' => true,
+ ),
+ ));
+ }
+
+ public function execute(PhutilArgumentParser $args) {
+ $viewer = PhabricatorUser::getOmnipotentUser();
+
+ $names = $args->getArg('buildable');
+ if (count($names) != 1) {
+ throw new PhutilArgumentUsageException(
+ pht('Specify exactly one buildable, by object name.'));
+ }
+
+ $name = head($names);
+
+ $buildable = id(new PhabricatorObjectQuery())
+ ->setViewer($viewer)
+ ->withNames($names)
+ ->executeOne();
+ if (!$buildable) {
+ throw new PhutilArgumentUsageException(
+ pht('No such buildable "%s"!', $name));
+ }
+
+ if (!($buildable instanceof HarbormasterBuildableInterface)) {
+ throw new PhutilArgumentUsageException(
+ pht('Object "%s" is not a buildable!', $name));
+ }
+
+ $plan_id = $args->getArg('plan');
+ if (!$plan_id) {
+ throw new PhutilArgumentUsageException(
+ pht('Use --plan to specify a build plan to run.'));
+ }
+
+ $plan = id(new HarbormasterBuildPlanQuery())
+ ->setViewer($viewer)
+ ->withIDs(array($plan_id))
+ ->executeOne();
+ if (!$plan) {
+ throw new PhutilArgumentUsageException(
+ pht('Build plan "%s" does not exist.', $plan_id));
+ }
+
+ $console = PhutilConsole::getConsole();
+
+ $buildable = HarbormasterBuildable::initializeNewBuildable($viewer)
+ ->setIsManualBuildable(true)
+ ->setBuildablePHID($buildable->getHarbormasterBuildablePHID())
+ ->setContainerPHID($buildable->getHarbormasterContainerPHID())
+ ->save();
+
+ $console->writeOut(
+ "%s\n",
+ pht(
+ 'Applying plan %s to new buildable %s...',
+ $plan->getID(),
+ 'B'.$buildable->getID()));
+
+ $console->writeOut(
+ "\n %s\n\n",
+ PhabricatorEnv::getProductionURI('/B'.$buildable->getID()));
+
+ PhabricatorWorker::setRunAllTasksInProcess(true);
+ $buildable->applyPlan($plan);
+
+ $console->writeOut("%s\n", pht('Done.'));
+
+ return 0;
+ }
+
+}
Index: src/applications/harbormaster/management/HarbormasterManagementWorkflow.php
===================================================================
--- /dev/null
+++ src/applications/harbormaster/management/HarbormasterManagementWorkflow.php
@@ -0,0 +1,10 @@
+<?php
+
+abstract class HarbormasterManagementWorkflow
+ extends PhutilArgumentWorkflow {
+
+ public function isExecutable() {
+ return true;
+ }
+
+}
Index: src/applications/harbormaster/storage/HarbormasterBuildable.php
===================================================================
--- src/applications/harbormaster/storage/HarbormasterBuildable.php
+++ src/applications/harbormaster/storage/HarbormasterBuildable.php
@@ -1,7 +1,9 @@
<?php
final class HarbormasterBuildable extends HarbormasterDAO
- implements PhabricatorPolicyInterface {
+ implements
+ PhabricatorPolicyInterface,
+ HarbormasterBuildableInterface {
protected $buildablePHID;
protected $containerPHID;
@@ -86,21 +88,27 @@
continue;
}
- $build = HarbormasterBuild::initializeNewBuild(
- PhabricatorUser::getOmnipotentUser());
- $build->setBuildablePHID($buildable->getPHID());
- $build->setBuildPlanPHID($plan->getPHID());
- $build->setBuildStatus(HarbormasterBuild::STATUS_PENDING);
- $build->save();
-
- PhabricatorWorker::scheduleTask(
- 'HarbormasterBuildWorker',
- array(
- 'buildID' => $build->getID()
- ));
+ $buildable->applyPlan($plan);
}
}
+ public function applyPlan(HarbormasterBuildPlan $plan) {
+ $viewer = PhabricatorUser::getOmnipotentUser();
+ $build = HarbormasterBuild::initializeNewBuild($viewer)
+ ->setBuildablePHID($this->getPHID())
+ ->setBuildPlanPHID($plan->getPHID())
+ ->setBuildStatus(HarbormasterBuild::STATUS_PENDING)
+ ->save();
+
+ PhabricatorWorker::scheduleTask(
+ 'HarbormasterBuildWorker',
+ array(
+ 'buildID' => $build->getID()
+ ));
+
+ return $this;
+ }
+
public function getConfiguration() {
return array(
self::CONFIG_AUX_PHID => true,
@@ -184,4 +192,21 @@
'buildable.');
}
+
+
+/* -( HarbormasterBuildableInterface )------------------------------------- */
+
+
+ public function getHarbormasterBuildablePHID() {
+ // NOTE: This is essentially just for convenience, as it allows you create
+ // a copy of a buildable by specifying `B123` without bothering to go
+ // look up the underlying object.
+ return $this->getBuildablePHID();
+ }
+
+ public function getHarbormasterContainerPHID() {
+ return $this->getContainerPHID();
+ }
+
+
}
Index: src/applications/repository/storage/PhabricatorRepositoryCommit.php
===================================================================
--- src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -5,7 +5,8 @@
implements
PhabricatorPolicyInterface,
PhabricatorFlaggableInterface,
- PhabricatorTokenReceiverInterface {
+ PhabricatorTokenReceiverInterface,
+ HarbormasterBuildableInterface {
protected $repositoryID;
protected $phid;
@@ -231,4 +232,17 @@
return id(new PhabricatorRepositoryCommit())
->loadFromArray($dict);
}
+
+
+/* -( HarbormasterBuildableInterface )------------------------------------- */
+
+
+ public function getHarbormasterBuildablePHID() {
+ return $this->getPHID();
+ }
+
+ public function getHarbormasterContainerPHID() {
+ return $this->getRepository()->getPHID();
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Sat, Nov 23, 10:25 AM (16 h, 14 m)
Storage Engine
blob
Storage Format
Encrypted (AES-256-CBC)
Storage Handle
6777224
Default Alt Text
D7825.id17702.diff (17 KB)

Event Timeline