@recaptime-dev's working patches + fork for Phorge, a community fork of Phabricator. (Upstream dev and stable branches are at upstream/main and upstream/stable respectively.) hq.recaptime.dev/wiki/Phorge
phorge phabricator
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Implement step for publishing files as fragments to Phragment in Harbormaster

Summary: This adds a build step in Harbormaster for publishing file artifacts as fragments in Phragment.

Test Plan:
Created a build plan with the following steps:

* Lease Host
* Upload Artifact
* Publish Fragment

Ran the build plan against a buildable and saw the fragment get created in Phragment. Ran the plan again and saw the fragment get updated with a new version. Modified the file that got uploaded and ran the plan again, checked the history of the fragment, and saw the differences represented as a Diff-Match-Patch patch.

Reviewers: epriestley, #blessed_reviewers

Reviewed By: epriestley

CC: Korvin, epriestley, aran

Maniphest Tasks: T4205

Differential Revision: https://secure.phabricator.com/D7742

+123 -1
+2
src/__phutil_library_map__.php
··· 2282 2282 'PonderVoteSaveController' => 'applications/ponder/controller/PonderVoteSaveController.php', 2283 2283 'ProjectCapabilityCreateProjects' => 'applications/project/capability/ProjectCapabilityCreateProjects.php', 2284 2284 'ProjectRemarkupRule' => 'applications/project/remarkup/ProjectRemarkupRule.php', 2285 + 'PublishFragmentBuildStepImplementation' => 'applications/harbormaster/step/PublishFragmentBuildStepImplementation.php', 2285 2286 'QueryFormattingTestCase' => 'infrastructure/storage/__tests__/QueryFormattingTestCase.php', 2286 2287 'ReleephAuthorFieldSpecification' => 'applications/releeph/field/specification/ReleephAuthorFieldSpecification.php', 2287 2288 'ReleephBranch' => 'applications/releeph/storage/ReleephBranch.php', ··· 4947 4948 'PonderVoteSaveController' => 'PonderController', 4948 4949 'ProjectCapabilityCreateProjects' => 'PhabricatorPolicyCapability', 4949 4950 'ProjectRemarkupRule' => 'PhabricatorRemarkupRuleObject', 4951 + 'PublishFragmentBuildStepImplementation' => 'VariableBuildStepImplementation', 4950 4952 'QueryFormattingTestCase' => 'PhabricatorTestCase', 4951 4953 'ReleephAuthorFieldSpecification' => 'ReleephFieldSpecification', 4952 4954 'ReleephBranch' =>
+1 -1
src/applications/harbormaster/step/LeaseHostBuildStepImplementation.php
··· 53 53 $settings = $this->getSettings(); 54 54 55 55 return array( 56 - $settings['name'] => 'host'); 56 + $settings['name'] => HarbormasterBuildArtifact::TYPE_HOST); 57 57 } 58 58 59 59 public function validateSettings() {
+91
src/applications/harbormaster/step/PublishFragmentBuildStepImplementation.php
··· 1 + <?php 2 + 3 + final class PublishFragmentBuildStepImplementation 4 + extends VariableBuildStepImplementation { 5 + 6 + public function getName() { 7 + return pht('Publish Fragment'); 8 + } 9 + 10 + public function getGenericDescription() { 11 + return pht('Publish a fragment based on a file artifact.'); 12 + } 13 + 14 + public function getDescription() { 15 + $settings = $this->getSettings(); 16 + 17 + return pht( 18 + 'Publish file artifact \'%s\' to the fragment path \'%s\'.', 19 + $settings['artifact'], 20 + $settings['path']); 21 + } 22 + 23 + public function execute( 24 + HarbormasterBuild $build, 25 + HarbormasterBuildTarget $build_target) { 26 + 27 + $settings = $this->getSettings(); 28 + $variables = $build_target->getVariables(); 29 + 30 + $path = $this->mergeVariables( 31 + 'vsprintf', 32 + $settings['path'], 33 + $variables); 34 + 35 + $artifact = $build->loadArtifact($settings['artifact']); 36 + 37 + $file = $artifact->loadPhabricatorFile(); 38 + 39 + $fragment = id(new PhragmentFragmentQuery()) 40 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 41 + ->withPaths(array($path)) 42 + ->executeOne(); 43 + 44 + if ($fragment === null) { 45 + PhragmentFragment::createFromFile( 46 + PhabricatorUser::getOmnipotentUser(), 47 + $file, 48 + $path, 49 + PhabricatorPolicies::getMostOpenPolicy(), 50 + PhabricatorPolicies::POLICY_USER); 51 + } else { 52 + if ($file->getMimeType() === "application/zip") { 53 + $fragment->updateFromZIP(PhabricatorUser::getOmnipotentUser(), $file); 54 + } else { 55 + $fragment->updateFromFile(PhabricatorUser::getOmnipotentUser(), $file); 56 + } 57 + } 58 + } 59 + 60 + public function validateSettings() { 61 + $settings = $this->getSettings(); 62 + 63 + if ($settings['path'] === null || !is_string($settings['path'])) { 64 + return false; 65 + } 66 + if ($settings['artifact'] === null || 67 + !is_string($settings['artifact'])) { 68 + return false; 69 + } 70 + 71 + // TODO: Check if the file artifact is provided by previous build steps. 72 + 73 + return true; 74 + } 75 + 76 + public function getSettingDefinitions() { 77 + return array( 78 + 'path' => array( 79 + 'name' => 'Path', 80 + 'description' => 81 + 'The path of the fragment that will be published.', 82 + 'type' => BuildStepImplementation::SETTING_TYPE_STRING), 83 + 'artifact' => array( 84 + 'name' => 'File Artifact', 85 + 'description' => 86 + 'The file artifact that will be published to Phragment.', 87 + 'type' => BuildStepImplementation::SETTING_TYPE_ARTIFACT, 88 + 'artifact_type' => HarbormasterBuildArtifact::TYPE_FILE)); 89 + } 90 + 91 + }
+7
src/applications/harbormaster/step/UploadArtifactBuildStepImplementation.php
··· 51 51 $artifact->save(); 52 52 } 53 53 54 + public function getArtifactMappings() { 55 + $settings = $this->getSettings(); 56 + 57 + return array( 58 + $settings['name'] => HarbormasterBuildArtifact::TYPE_FILE); 59 + } 60 + 54 61 public function validateSettings() { 55 62 $settings = $this->getSettings(); 56 63
+22
src/applications/harbormaster/storage/build/HarbormasterBuildArtifact.php
··· 96 96 return $lease; 97 97 } 98 98 99 + public function loadPhabricatorFile() { 100 + if ($this->getArtifactType() !== self::TYPE_FILE) { 101 + throw new Exception( 102 + "`loadPhabricatorFile` may only be called on file artifacts."); 103 + } 104 + 105 + $data = $this->getArtifactData(); 106 + 107 + // The data for TYPE_FILE is an array with a single PHID in it. 108 + $phid = $data["filePHID"]; 109 + 110 + $file = id(new PhabricatorFileQuery()) 111 + ->setViewer(PhabricatorUser::getOmnipotentUser()) 112 + ->withPHIDs(array($phid)) 113 + ->executeOne(); 114 + if ($file === null) { 115 + throw new Exception("Associated file not found!"); 116 + } 117 + return $file; 118 + } 119 + 120 + 99 121 /* -( PhabricatorPolicyInterface )----------------------------------------- */ 100 122 101 123