diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php --- a/src/applications/differential/storage/DifferentialRevision.php +++ b/src/applications/differential/storage/DifferentialRevision.php @@ -870,10 +870,19 @@ foreach ($builds as $key => $build) { $plan = $build->getBuildPlan(); - $hold_key = $behavior->getPlanOption($plan)->getKey(); - $hold_never = ($hold_key === $key_never); - $hold_building = ($hold_key === $key_building); + // See T13526. If the viewer can't see the build plan, pretend it has + // generic options. This is often wrong, but "often wrong" is better than + // "fatal". + if ($plan) { + $hold_key = $behavior->getPlanOption($plan)->getKey(); + + $hold_never = ($hold_key === $key_never); + $hold_building = ($hold_key === $key_building); + } else { + $hold_never = false; + $hold_building = false; + } // If the build "Never" holds drafts from promoting, we don't care what // the status is. diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php --- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php @@ -235,6 +235,16 @@ $restartable = HarbormasterBuildPlanBehavior::BEHAVIOR_RESTARTABLE; $plan = $this->getBuildPlan(); + // See T13526. Users who can't see the "BuildPlan" can end up here with + // no object. This is highly questionable. + if (!$plan) { + throw new HarbormasterRestartException( + pht('No Build Plan Permission'), + pht( + 'You can not restart this build because you do not have '. + 'permission to access the build plan.')); + } + $option = HarbormasterBuildPlanBehavior::getBehavior($restartable) ->getPlanOption($plan); $option_key = $option->getKey(); @@ -389,6 +399,12 @@ public function assertCanIssueCommand(PhabricatorUser $viewer, $command) { $plan = $this->getBuildPlan(); + // See T13526. Users without permission to access the build plan can + // currently end up here with no "BuildPlan" object. + if (!$plan) { + return false; + } + $need_edit = true; switch ($command) { case HarbormasterBuildCommand::COMMAND_RESTART: