Skip to content

Commit aad6b57

Browse files
author
epriestley
committedDec 26, 2013
Add bin/harbormaster to make builds easier to debug
Summary: Ref T1049. Adds `bin/harbormaster` and `bin/harbormaster build` for applying plans from the console. Since this gets `--trace`, it's much easier to debug what's going on. This doesn't work properly with some of the Drydock steps yet, I need to look at those. I think `setRunAllTasksInProcess` probably obsoletes some of the mechanisms. It might also not work with "Wait for Builds" but I didn't check. Test Plan: Used `bin/harbormaster` to run a bunch of builds. Ran builds from web UI. Reviewers: btrahan Reviewed By: btrahan CC: aran Maniphest Tasks: T1049 Differential Revision: https://secure.phabricator.com/D7825
1 parent ac19c55 commit aad6b57

12 files changed

+259
-37
lines changed
 

‎bin/harbormaster

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../scripts/setup/manage_harbormaster.php

‎scripts/setup/manage_harbormaster.php

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
#!/usr/bin/env php
2+
<?php
3+
4+
$root = dirname(dirname(dirname(__FILE__)));
5+
require_once $root.'/scripts/__init_script__.php';
6+
7+
$args = new PhutilArgumentParser($argv);
8+
$args->setTagline('manage Harbormaster');
9+
$args->setSynopsis(<<<EOSYNOPSIS
10+
**harbormaster** __command__ [__options__]
11+
Manage and debug Harbormaster.
12+
13+
EOSYNOPSIS
14+
);
15+
$args->parseStandardArguments();
16+
17+
$workflows = id(new PhutilSymbolLoader())
18+
->setAncestorClass('HarbormasterManagementWorkflow')
19+
->loadObjects();
20+
$workflows[] = new PhutilHelpArgumentWorkflow();
21+
22+
$args->parseWorkflows($workflows);

‎src/__phutil_library_map__.php

+9
Original file line numberDiff line numberDiff line change
@@ -707,6 +707,7 @@
707707
'HarbormasterBuildViewController' => 'applications/harbormaster/controller/HarbormasterBuildViewController.php',
708708
'HarbormasterBuildWorker' => 'applications/harbormaster/worker/HarbormasterBuildWorker.php',
709709
'HarbormasterBuildable' => 'applications/harbormaster/storage/HarbormasterBuildable.php',
710+
'HarbormasterBuildableInterface' => 'applications/harbormaster/interface/HarbormasterBuildableInterface.php',
710711
'HarbormasterBuildableListController' => 'applications/harbormaster/controller/HarbormasterBuildableListController.php',
711712
'HarbormasterBuildableQuery' => 'applications/harbormaster/query/HarbormasterBuildableQuery.php',
712713
'HarbormasterBuildableSearchEngine' => 'applications/harbormaster/query/HarbormasterBuildableSearchEngine.php',
@@ -715,6 +716,8 @@
715716
'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php',
716717
'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php',
717718
'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php',
719+
'HarbormasterManagementBuildWorkflow' => 'applications/harbormaster/management/HarbormasterManagementBuildWorkflow.php',
720+
'HarbormasterManagementWorkflow' => 'applications/harbormaster/management/HarbormasterManagementWorkflow.php',
718721
'HarbormasterObject' => 'applications/harbormaster/storage/HarbormasterObject.php',
719722
'HarbormasterPHIDTypeBuild' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuild.php',
720723
'HarbormasterPHIDTypeBuildItem' => 'applications/harbormaster/phid/HarbormasterPHIDTypeBuildItem.php',
@@ -2747,6 +2750,7 @@
27472750
array(
27482751
0 => 'DifferentialDAO',
27492752
1 => 'PhabricatorPolicyInterface',
2753+
2 => 'HarbormasterBuildableInterface',
27502754
),
27512755
'DifferentialDiffContentMail' => 'DifferentialMail',
27522756
'DifferentialDiffCreateController' => 'DifferentialController',
@@ -2814,6 +2818,7 @@
28142818
2 => 'PhabricatorPolicyInterface',
28152819
3 => 'PhabricatorFlaggableInterface',
28162820
4 => 'PhrequentTrackableInterface',
2821+
5 => 'HarbormasterBuildableInterface',
28172822
),
28182823
'DifferentialRevisionCommentListView' => 'AphrontView',
28192824
'DifferentialRevisionCommentView' => 'AphrontView',
@@ -3131,6 +3136,7 @@
31313136
array(
31323137
0 => 'HarbormasterDAO',
31333138
1 => 'PhabricatorPolicyInterface',
3139+
2 => 'HarbormasterBuildableInterface',
31343140
),
31353141
'HarbormasterBuildableListController' =>
31363142
array(
@@ -3144,6 +3150,8 @@
31443150
'HarbormasterController' => 'PhabricatorController',
31453151
'HarbormasterDAO' => 'PhabricatorLiskDAO',
31463152
'HarbormasterHTTPRequestBuildStepImplementation' => 'VariableBuildStepImplementation',
3153+
'HarbormasterManagementBuildWorkflow' => 'HarbormasterManagementWorkflow',
3154+
'HarbormasterManagementWorkflow' => 'PhutilArgumentWorkflow',
31473155
'HarbormasterObject' => 'HarbormasterDAO',
31483156
'HarbormasterPHIDTypeBuild' => 'PhabricatorPHIDType',
31493157
'HarbormasterPHIDTypeBuildItem' => 'PhabricatorPHIDType',
@@ -4342,6 +4350,7 @@
43424350
1 => 'PhabricatorPolicyInterface',
43434351
2 => 'PhabricatorFlaggableInterface',
43444352
3 => 'PhabricatorTokenReceiverInterface',
4353+
4 => 'HarbormasterBuildableInterface',
43454354
),
43464355
'PhabricatorRepositoryCommitChangeParserWorker' => 'PhabricatorRepositoryCommitParserWorker',
43474356
'PhabricatorRepositoryCommitData' => 'PhabricatorRepositoryDAO',

‎src/applications/differential/storage/DifferentialDiff.php

+23-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
final class DifferentialDiff
44
extends DifferentialDAO
5-
implements PhabricatorPolicyInterface {
5+
implements
6+
PhabricatorPolicyInterface,
7+
HarbormasterBuildableInterface {
68

79
protected $revisionID;
810
protected $authorPHID;
@@ -339,4 +341,24 @@ public function describeAutomaticCapability($capability) {
339341
return null;
340342
}
341343

344+
345+
346+
/* -( HarbormasterBuildableInterface )------------------------------------- */
347+
348+
349+
public function getHarbormasterBuildablePHID() {
350+
return $this->getPHID();
351+
}
352+
353+
public function getHarbormasterContainerPHID() {
354+
if ($this->getRevisionID()) {
355+
$revision = id(new DifferentialRevision())->load($this->getRevisionID());
356+
if ($revision) {
357+
return $revision->getPHID();
358+
}
359+
}
360+
361+
return null;
362+
}
363+
342364
}

‎src/applications/differential/storage/DifferentialRevision.php

+14-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ final class DifferentialRevision extends DifferentialDAO
55
PhabricatorTokenReceiverInterface,
66
PhabricatorPolicyInterface,
77
PhabricatorFlaggableInterface,
8-
PhrequentTrackableInterface {
8+
PhrequentTrackableInterface,
9+
HarbormasterBuildableInterface {
910

1011
protected $title = '';
1112
protected $originalTitle;
@@ -412,4 +413,16 @@ public function isClosed() {
412413
return DifferentialRevisionStatus::isClosedStatus($this->getStatus());
413414
}
414415

416+
417+
/* -( HarbormasterBuildableInterface )------------------------------------- */
418+
419+
420+
public function getHarbormasterBuildablePHID() {
421+
return $this->loadActiveDiff()->getPHID();
422+
}
423+
424+
public function getHarbormasterContainerPHID() {
425+
return $this->getPHID();
426+
}
427+
415428
}

‎src/applications/harbormaster/controller/HarbormasterPlanRunController.php

+11-12
Original file line numberDiff line numberDiff line change
@@ -41,16 +41,10 @@ public function processRequest() {
4141
->withNames(array($v_name))
4242
->executeOne();
4343

44-
if ($object instanceof DifferentialRevision) {
45-
$revision = $object;
46-
$object = $object->loadActiveDiff();
44+
if ($object instanceof HarbormasterBuildableInterface) {
4745
$buildable
48-
->setBuildablePHID($object->getPHID())
49-
->setContainerPHID($revision->getPHID());
50-
} else if ($object instanceof PhabricatorRepositoryCommit) {
51-
$buildable
52-
->setBuildablePHID($object->getPHID())
53-
->setContainerPHID($object->getRepository()->getPHID());
46+
->setBuildablePHID($object->getHarbormasterBuildablePHID())
47+
->setContainerPHID($object->getHarbormasterContainerPHID());
5448
} else {
5549
$e_name = pht('Invalid');
5650
$errors[] = pht('Enter the name of a revision or commit.');
@@ -62,6 +56,7 @@ public function processRequest() {
6256

6357
if (!$errors) {
6458
$buildable->save();
59+
$buildable->applyPlan($plan);
6560

6661
$buildable_uri = '/B'.$buildable->getID();
6762
return id(new AphrontRedirectResponse())->setURI($buildable_uri);
@@ -80,8 +75,12 @@ public function processRequest() {
8075
->setUser($viewer)
8176
->appendRemarkupInstructions(
8277
pht(
83-
"Enter the name of a commit or revision to run this plan on.\n\n".
84-
"For example: `rX123456` or `D123`"))
78+
"Enter the name of a commit or revision to run this plan on (for ".
79+
"example, `rX123456` or `D123`).\n\n".
80+
"For more detailed output, you can also run manual builds from ".
81+
"the command line:\n\n".
82+
" phabricator/ $ ./bin/harbormaster build <object> --plan %s",
83+
$plan->getID()))
8584
->appendChild(
8685
id(new AphrontFormTextControl())
8786
->setLabel('Buildable Name')
@@ -90,7 +89,7 @@ public function processRequest() {
9089
->setValue($v_name));
9190

9291
$dialog = id(new AphrontDialogView())
93-
->setWidth(AphrontDialogView::WIDTH_FORM)
92+
->setWidth(AphrontDialogView::WIDTH_FULL)
9493
->setUser($viewer)
9594
->setTitle($title)
9695
->appendChild($form)

‎src/applications/harbormaster/event/HarbormasterUIEventListener.php

+16-9
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,19 @@ private function handlePropertyEvent($ui_event) {
2424
return;
2525
}
2626

27-
$target = null;
28-
if ($object instanceof PhabricatorRepositoryCommit) {
29-
$target = $object;
30-
} elseif ($object instanceof DifferentialRevision) {
31-
$target = $object->loadActiveDiff();
32-
} else {
27+
if ($object instanceof HarbormasterBuildable) {
28+
// Although HarbormasterBuildable implements the correct interface, it
29+
// does not make sense to show a build's build status. In the best case
30+
// it is meaningless, and in the worst case it's confusing.
31+
return;
32+
}
33+
34+
if (!($object instanceof HarbormasterBuildableInterface)) {
35+
return;
36+
}
37+
38+
$buildable_phid = $object->getBuildablePHID();
39+
if (!$buildable_phid) {
3340
return;
3441
}
3542

@@ -39,7 +46,8 @@ private function handlePropertyEvent($ui_event) {
3946

4047
$buildables = id(new HarbormasterBuildableQuery())
4148
->setViewer($user)
42-
->withBuildablePHIDs(array($target->getPHID()))
49+
->withManualBuildables(false)
50+
->withBuildablePHIDs(array($buildable_phid))
4351
->execute();
4452
if (!$buildables) {
4553
return;
@@ -62,8 +70,7 @@ private function handlePropertyEvent($ui_event) {
6270

6371
foreach ($builds as $build) {
6472
$item = new PHUIStatusItemView();
65-
$item->setTarget(
66-
$build_handles[$build->getPHID()]->renderLink());
73+
$item->setTarget($build_handles[$build->getPHID()]->renderLink());
6774

6875
switch ($build->getBuildStatus()) {
6976
case HarbormasterBuild::STATUS_INACTIVE:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
interface HarbormasterBuildableInterface {
4+
5+
public function getHarbormasterBuildablePHID();
6+
public function getHarbormasterContainerPHID();
7+
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?php
2+
3+
final class HarbormasterManagementBuildWorkflow
4+
extends HarbormasterManagementWorkflow {
5+
6+
public function didConstruct() {
7+
$this
8+
->setName('build')
9+
->setExamples('**build** [__options__] __buildable__ --plan __id__')
10+
->setSynopsis(pht('Run plan __id__ on __buildable__.'))
11+
->setArguments(
12+
array(
13+
array(
14+
'name' => 'plan',
15+
'param' => 'id',
16+
'help' => pht('ID of build plan to run.'),
17+
),
18+
array(
19+
'name' => 'buildable',
20+
'wildcard' => true,
21+
),
22+
));
23+
}
24+
25+
public function execute(PhutilArgumentParser $args) {
26+
$viewer = PhabricatorUser::getOmnipotentUser();
27+
28+
$names = $args->getArg('buildable');
29+
if (count($names) != 1) {
30+
throw new PhutilArgumentUsageException(
31+
pht('Specify exactly one buildable, by object name.'));
32+
}
33+
34+
$name = head($names);
35+
36+
$buildable = id(new PhabricatorObjectQuery())
37+
->setViewer($viewer)
38+
->withNames($names)
39+
->executeOne();
40+
if (!$buildable) {
41+
throw new PhutilArgumentUsageException(
42+
pht('No such buildable "%s"!', $name));
43+
}
44+
45+
if (!($buildable instanceof HarbormasterBuildableInterface)) {
46+
throw new PhutilArgumentUsageException(
47+
pht('Object "%s" is not a buildable!', $name));
48+
}
49+
50+
$plan_id = $args->getArg('plan');
51+
if (!$plan_id) {
52+
throw new PhutilArgumentUsageException(
53+
pht('Use --plan to specify a build plan to run.'));
54+
}
55+
56+
$plan = id(new HarbormasterBuildPlanQuery())
57+
->setViewer($viewer)
58+
->withIDs(array($plan_id))
59+
->executeOne();
60+
if (!$plan) {
61+
throw new PhutilArgumentUsageException(
62+
pht('Build plan "%s" does not exist.', $plan_id));
63+
}
64+
65+
$console = PhutilConsole::getConsole();
66+
67+
$buildable = HarbormasterBuildable::initializeNewBuildable($viewer)
68+
->setIsManualBuildable(true)
69+
->setBuildablePHID($buildable->getHarbormasterBuildablePHID())
70+
->setContainerPHID($buildable->getHarbormasterContainerPHID())
71+
->save();
72+
73+
$console->writeOut(
74+
"%s\n",
75+
pht(
76+
'Applying plan %s to new buildable %s...',
77+
$plan->getID(),
78+
'B'.$buildable->getID()));
79+
80+
$console->writeOut(
81+
"\n %s\n\n",
82+
PhabricatorEnv::getProductionURI('/B'.$buildable->getID()));
83+
84+
PhabricatorWorker::setRunAllTasksInProcess(true);
85+
$buildable->applyPlan($plan);
86+
87+
$console->writeOut("%s\n", pht('Done.'));
88+
89+
return 0;
90+
}
91+
92+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<?php
2+
3+
abstract class HarbormasterManagementWorkflow
4+
extends PhutilArgumentWorkflow {
5+
6+
public function isExecutable() {
7+
return true;
8+
}
9+
10+
}

0 commit comments

Comments
 (0)
Failed to load comments.