diff --git a/src/__phutil_library_map__.php b/src/__phutil_library_map__.php --- a/src/__phutil_library_map__.php +++ b/src/__phutil_library_map__.php @@ -991,12 +991,17 @@ 'HarbormasterConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterConduitAPIMethod.php', 'HarbormasterController' => 'applications/harbormaster/controller/HarbormasterController.php', 'HarbormasterCreateArtifactConduitAPIMethod' => 'applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php', + 'HarbormasterCustomFieldRepository' => 'applications/harbormaster/customfield/HarbormasterCustomFieldRepository.php', 'HarbormasterDAO' => 'applications/harbormaster/storage/HarbormasterDAO.php', 'HarbormasterExternalBuildStepGroup' => 'applications/harbormaster/stepgroup/HarbormasterExternalBuildStepGroup.php', 'HarbormasterFileArtifact' => 'applications/harbormaster/artifact/HarbormasterFileArtifact.php', 'HarbormasterHTTPRequestBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterHTTPRequestBuildStepImplementation.php', 'HarbormasterHostArtifact' => 'applications/harbormaster/artifact/HarbormasterHostArtifact.php', 'HarbormasterLeaseHostBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseHostBuildStepImplementation.php', + 'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php', + 'HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation.php', + 'HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation.php', + 'HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation' => 'applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation.php', 'HarbormasterLintMessagesController' => 'applications/harbormaster/controller/HarbormasterLintMessagesController.php', 'HarbormasterLintPropertyView' => 'applications/harbormaster/view/HarbormasterLintPropertyView.php', 'HarbormasterManagePlansCapability' => 'applications/harbormaster/capability/HarbormasterManagePlansCapability.php', @@ -4738,12 +4743,17 @@ 'HarbormasterConduitAPIMethod' => 'ConduitAPIMethod', 'HarbormasterController' => 'PhabricatorController', 'HarbormasterCreateArtifactConduitAPIMethod' => 'HarbormasterConduitAPIMethod', + 'HarbormasterCustomFieldRepository' => 'PhabricatorStandardCustomFieldPHIDs', 'HarbormasterDAO' => 'PhabricatorLiskDAO', 'HarbormasterExternalBuildStepGroup' => 'HarbormasterBuildStepGroup', 'HarbormasterFileArtifact' => 'HarbormasterArtifact', 'HarbormasterHTTPRequestBuildStepImplementation' => 'HarbormasterBuildStepImplementation', 'HarbormasterHostArtifact' => 'HarbormasterArtifact', 'HarbormasterLeaseHostBuildStepImplementation' => 'HarbormasterBuildStepImplementation', + 'HarbormasterLeaseWorkingCopyBuildStepImplementation' => 'HarbormasterBuildStepImplementation', + 'HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation' => 'HarbormasterLeaseWorkingCopyBuildStepImplementation', + 'HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation' => 'HarbormasterLeaseWorkingCopyBuildStepImplementation', + 'HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation' => 'HarbormasterLeaseWorkingCopyBuildStepImplementation', 'HarbormasterLintMessagesController' => 'HarbormasterController', 'HarbormasterLintPropertyView' => 'AphrontView', 'HarbormasterManagePlansCapability' => 'PhabricatorPolicyCapability', diff --git a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php --- a/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php +++ b/src/applications/drydock/blueprint/DrydockWorkingCopyBlueprintImplementation.php @@ -271,6 +271,13 @@ $this->log(pht('Checked out commit')); } else if ($lease->getAttribute('resolved.target') === 'diff') { $this->log(pht( + 'Fetching diff tag from origin')); + $cmd->exec( + 'git fetch origin +refs/tags/phabricator/diff/%d:'. + 'refs/tags/phabricator/diff/%d', + $lease->getAttribute('resolved.diffID'), + $lease->getAttribute('resolved.diffID')); + $this->log(pht( 'Checking out target diff at tag "phabricator/diff/%d"', $lease->getAttribute('resolved.diffID'))); $cmd->execx( diff --git a/src/applications/harbormaster/customfield/HarbormasterCustomFieldRepository.php b/src/applications/harbormaster/customfield/HarbormasterCustomFieldRepository.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/customfield/HarbormasterCustomFieldRepository.php @@ -0,0 +1,43 @@ +getFieldValue(); + + $control = id(new AphrontFormTokenizerControl()) + ->setUser($this->getViewer()) + ->setLabel($this->getFieldName()) + ->setName($this->getFieldKey()) + ->setDatasource(new DiffusionRepositoryDatasource()) + ->setCaption($this->getCaption()) + ->setValue(nonempty($value, array())); + + $limit = $this->getFieldConfigValue('limit'); + if ($limit) { + $control->setLimit($limit); + } + + return $control; + } + + public function appendToApplicationSearchForm( + PhabricatorApplicationSearchEngine $engine, + AphrontFormView $form, + $value) { + + $control = id(new AphrontFormTokenizerControl()) + ->setLabel($this->getFieldName()) + ->setName($this->getFieldKey()) + ->setDatasource(new DiffusionRepositoryDatasource()) + ->setValue(nonempty($value, array())); + + $form->appendControl($control); + } + +} diff --git a/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyBuildStepImplementation.php @@ -0,0 +1,103 @@ +getSettings(); + + // This build step is reentrant, because waitUntilActive may + // throw PhabricatorWorkerYieldException. Check to see if there + // is already a lease on the build target, and if so, wait until + // that lease is active instead of creating a new one. + $artifacts = id(new HarbormasterBuildArtifactQuery()) + ->setViewer(PhabricatorUser::getOmnipotentUser()) + ->withBuildTargetPHIDs(array($build_target->getPHID())) + ->execute(); + $artifact = count($artifacts) > 0 ? head($artifacts) : null; + + if ($artifact === null) { + $custom_attributes = DrydockCustomAttributes::parse( + idx($settings, 'attributes', '')); + + // Create the lease. + $lease = id(new DrydockLease()) + ->setResourceType('working-copy') + ->setOwnerPHID($build_target->getPHID()) + ->setAttributes( + array( + 'platform' => $settings['platform'], + 'buildablePHID' => $build->getBuildablePHID(), + ) + $this->getLeaseAttributes($build, $build_target, $settings) + + $custom_attributes) + ->queueForActivation(); + + // Create the associated artifact. + $artifact = $build_target->createArtifact( + PhabricatorUser::getOmnipotentUser(), + $settings['name'], + HarbormasterHostArtifact::ARTIFACTCONST, + array( + 'drydockLeasePHID' => $lease->getPHID(), + )); + } else { + // Load the lease. + $impl = $artifact->getArtifactImplementation(); + $lease = $impl->loadArtifactLease(PhabricatorUser::getOmnipotentUser()); + } + + // Wait until the lease is fulfilled. + try { + $lease->waitUntilActive(); + } catch (PhabricatorWorkerYieldException $ex) { + throw $ex; + } catch (Exception $ex) { + throw new HarbormasterBuildFailureException($ex->getMessage()); + } + } + + public function getArtifactOutputs() { + return array( + array( + 'name' => pht('Leased Working Copy'), + 'key' => $this->getSetting('name'), + 'type' => HarbormasterHostArtifact::ARTIFACTCONST, + ), + ); + } + + abstract protected function getLeaseFieldSpecifications(); + + public function getFieldSpecifications() { + return array( + 'name' => array( + 'name' => pht('Artifact Name'), + 'type' => 'text', + 'required' => true, + ), + 'platform' => array( + 'name' => pht('Host Platform'), + 'type' => 'text', + 'required' => true, + ), + ) + $this->getLeaseFieldSpecifications() + array( + 'attributes' => array( + 'name' => pht('Required Attributes'), + 'type' => 'textarea', + 'caption' => pht( + 'A newline separated list of required working copy attributes. '. + 'Each attribute should be specified in a key=value format.'), + 'monospace' => true, + ), + ); + } + +} diff --git a/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromBuildableBuildStepImplementation.php @@ -0,0 +1,30 @@ + $build->getBuildablePHID(), + ); + } + + protected function getLeaseFieldSpecifications() { + return array(); + } + +} diff --git a/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromRepositoryBuildStepImplementation.php @@ -0,0 +1,44 @@ + + head(phutil_json_decode(idx($settings, 'repositoryPHID'))), + 'ref' => idx($settings, 'ref'), + ); + } + + protected function getLeaseFieldSpecifications() { + return array( + 'repositoryPHID' => array( + 'name' => pht('Repository'), + 'type' => 'repository', + 'required' => true, + ), + 'ref' => array( + 'name' => pht('Reference to Checkout'), + 'type' => 'text', + 'required' => true, + 'caption' => pht('e.g. master'), + ), + ); + } + +} diff --git a/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation.php b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation.php new file mode 100644 --- /dev/null +++ b/src/applications/harbormaster/step/HarbormasterLeaseWorkingCopyFromURLBuildStepImplementation.php @@ -0,0 +1,43 @@ + idx($settings, 'url'), + 'ref' => idx($settings, 'ref'), + ); + } + + protected function getLeaseFieldSpecifications() { + return array( + 'url' => array( + 'name' => pht('Repository URL'), + 'type' => 'text', + 'required' => true, + ), + 'ref' => array( + 'name' => pht('Reference to Checkout'), + 'type' => 'text', + 'required' => true, + 'caption' => pht('e.g. master'), + ), + ); + } + +}