diff --git a/src/applications/harbormaster/controller/HarbormasterStepEditController.php b/src/applications/harbormaster/controller/HarbormasterStepEditController.php --- a/src/applications/harbormaster/controller/HarbormasterStepEditController.php +++ b/src/applications/harbormaster/controller/HarbormasterStepEditController.php @@ -72,9 +72,9 @@ $e_name = true; $v_name = $step->getName(); - $e_description = true; + $e_description = null; $v_description = $step->getDescription(); - $e_depends_on = true; + $e_depends_on = null; $v_depends_on = $step->getDetail('dependsOn', array()); $errors = array(); @@ -82,9 +82,7 @@ if ($request->isFormPost()) { $e_name = null; $v_name = $request->getStr('name'); - $e_description = null; $v_description = $request->getStr('description'); - $e_depends_on = null; $v_depends_on = $request->getArr('dependsOn'); $xactions = $field_list->buildFieldTransactionsFromRequest( @@ -139,6 +137,12 @@ ->setError($e_name) ->setValue($v_name)); + $form->appendChild(id(new AphrontFormDividerControl())); + + $field_list->appendFieldsToForm($form); + + $form->appendChild(id(new AphrontFormDividerControl())); + $form ->appendControl( id(new AphrontFormTokenizerControl()) @@ -152,8 +156,6 @@ ->setError($e_depends_on) ->setValue($v_depends_on)); - $field_list->appendFieldsToForm($form); - $form ->appendChild( id(new PhabricatorRemarkupControl()) diff --git a/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php b/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php --- a/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php +++ b/src/applications/harbormaster/customfield/HarbormasterBuildStepCoreCustomField.php @@ -72,4 +72,8 @@ return; } + public function getBuildTargetFieldValue() { + return $this->getProxy()->getFieldValue(); + } + } diff --git a/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php b/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php --- a/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php +++ b/src/applications/harbormaster/customfield/HarbormasterBuildStepCustomField.php @@ -1,4 +1,8 @@ 'text', 'required' => true, ), + 'repositoryPHIDs' => array( + 'name' => pht('Also Clone'), + 'type' => 'datasource', + 'datasource.class' => 'DiffusionRepositoryDatasource', + ), ); } @@ -108,22 +113,40 @@ $variables = $build_target->getVariables(); $repository_phid = idx($variables, 'repository.phid'); + $also_phids = $build_target->getFieldValue('repositoryPHIDs'); + + $all_phids = $also_phids; + $all_phids[] = $repository_phid; - $repository = id(new PhabricatorRepositoryQuery()) + $repositories = id(new PhabricatorRepositoryQuery()) ->setViewer($viewer) - ->withPHIDs(array($repository_phid)) - ->executeOne(); - if (!$repository) { - throw new PhabricatorWorkerPermanentFailureException( - pht( - 'Unable to load repository with PHID "%s".', - $repository_phid)); + ->withPHIDs($all_phids) + ->execute(); + $repositories = mpull($repositories, null, 'getPHID'); + + foreach ($all_phids as $phid) { + if (empty($repositories[$phid])) { + throw new PhabricatorWorkerPermanentFailureException( + pht( + 'Unable to load repository with PHID "%s".', + $phid)); + } } $commit = idx($variables, 'repository.commit'); $map = array(); + foreach ($also_phids as $also_phid) { + $also_repo = $repositories[$also_phid]; + $map[$also_repo->getCloneName()] = array( + 'phid' => $also_repo->getPHID(), + 'branch' => 'master', + ); + } + + $repository = $repositories[$repository_phid]; + $directory = $repository->getCloneName(); $map[$directory] = array( 'phid' => $repository->getPHID(), diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php b/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php --- a/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php +++ b/src/applications/harbormaster/storage/build/HarbormasterBuildTarget.php @@ -263,6 +263,28 @@ return $log; } + public function getFieldValue($key) { + $field_list = PhabricatorCustomField::getObjectFields( + $this->getBuildStep(), + PhabricatorCustomField::ROLE_VIEW); + + $fields = $field_list->getFields(); + $full_key = "std:harbormaster:core:{$key}"; + + $field = idx($fields, $full_key); + if (!$field) { + throw new Exception( + pht( + 'Unknown build step field "%s"!', + $key)); + } + + $field = clone $field; + $field->setValueFromStorage($this->getDetail($key)); + return $field->getBuildTargetFieldValue(); + } + + /* -( Status )------------------------------------------------------------- */ diff --git a/src/applications/harbormaster/worker/HarbormasterTargetWorker.php b/src/applications/harbormaster/worker/HarbormasterTargetWorker.php --- a/src/applications/harbormaster/worker/HarbormasterTargetWorker.php +++ b/src/applications/harbormaster/worker/HarbormasterTargetWorker.php @@ -28,6 +28,7 @@ $target = id(new HarbormasterBuildTargetQuery()) ->withIDs(array($id)) ->setViewer($this->getViewer()) + ->needBuildSteps(true) ->executeOne(); if (!$target) { diff --git a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php --- a/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php +++ b/src/infrastructure/customfield/standard/PhabricatorStandardCustomFieldPHIDs.php @@ -152,6 +152,61 @@ } } + public function validateApplicationTransactions( + PhabricatorApplicationTransactionEditor $editor, + $type, + array $xactions) { + + $errors = parent::validateApplicationTransactions( + $editor, + $type, + $xactions); + + // If the user is adding PHIDs, make sure the new PHIDs are valid and + // visible to the actor. It's OK for a user to edit a field which includes + // some invalid or restricted values, but they can't add new ones. + + foreach ($xactions as $xaction) { + $old = phutil_json_decode($xaction->getOldValue()); + $new = phutil_json_decode($xaction->getNewValue()); + + $add = array_diff($new, $old); + + if (!$add) { + continue; + } + + $objects = id(new PhabricatorObjectQuery()) + ->setViewer($editor->getActor()) + ->withPHIDs($add) + ->execute(); + $objects = mpull($objects, null, 'getPHID'); + + $invalid = array(); + foreach ($add as $phid) { + if (empty($objects[$phid])) { + $invalid[] = $phid; + } + } + + if ($invalid) { + $error = new PhabricatorApplicationTransactionValidationError( + $type, + pht('Invalid'), + pht( + 'Some of the selected PHIDs in field "%s" are invalid or '. + 'restricted: %s.', + $this->getFieldName(), + implode(', ', $invalid)), + $xaction); + $errors[] = $error; + $this->setFieldError(pht('Invalid')); + } + } + + return $errors; + } + public function shouldAppearInHerald() { return true; } diff --git a/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php b/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php --- a/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php +++ b/src/infrastructure/daemon/workers/management/PhabricatorWorkerManagementWorkflow.php @@ -43,7 +43,9 @@ // fake it when doing manual CLI stuff. This makes sure CLI yields have // their expires times set properly. foreach ($tasks as $task) { - $task->setServerTime(PhabricatorTime::getNow()); + if ($task instanceof PhabricatorWorkerActiveTask) { + $task->setServerTime(PhabricatorTime::getNow()); + } } return $tasks;