Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F2890757
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Award Token
Flag For Later
Advanced/Developer...
View Handle
View Hovercard
Size
10 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/applications/harbormaster/artifact/HarbormasterArtifact.php b/src/applications/harbormaster/artifact/HarbormasterArtifact.php
index 8d3d8dd169..172469fccb 100644
--- a/src/applications/harbormaster/artifact/HarbormasterArtifact.php
+++ b/src/applications/harbormaster/artifact/HarbormasterArtifact.php
@@ -1,60 +1,64 @@
<?php
abstract class HarbormasterArtifact extends Phobject {
private $buildArtifact;
abstract public function getArtifactTypeName();
public function getArtifactTypeSummary() {
return $this->getArtifactTypeDescription();
}
abstract public function getArtifactTypeDescription();
abstract public function getArtifactParameterSpecification();
abstract public function getArtifactParameterDescriptions();
abstract public function willCreateArtifact(PhabricatorUser $actor);
+ public function readArtifactHTTPParameter($key, $value) {
+ return $value;
+ }
+
public function validateArtifactData(array $artifact_data) {
$artifact_spec = $this->getArtifactParameterSpecification();
PhutilTypeSpec::checkMap($artifact_data, $artifact_spec);
}
public function renderArtifactSummary(PhabricatorUser $viewer) {
return null;
}
public function releaseArtifact(PhabricatorUser $actor) {
return;
}
public function getArtifactDataExample() {
return null;
}
public function setBuildArtifact(HarbormasterBuildArtifact $build_artifact) {
$this->buildArtifact = $build_artifact;
return $this;
}
public function getBuildArtifact() {
return $this->buildArtifact;
}
final public function getArtifactConstant() {
return $this->getPhobjectClassConstant('ARTIFACTCONST', 32);
}
final public static function getAllArtifactTypes() {
return id(new PhutilClassMapQuery())
->setAncestorClass(__CLASS__)
->setUniqueMethod('getArtifactConstant')
->execute();
}
final public static function getArtifactType($type) {
return idx(self::getAllArtifactTypes(), $type);
}
}
diff --git a/src/applications/harbormaster/artifact/HarbormasterURIArtifact.php b/src/applications/harbormaster/artifact/HarbormasterURIArtifact.php
index 311492de20..345621f0f5 100644
--- a/src/applications/harbormaster/artifact/HarbormasterURIArtifact.php
+++ b/src/applications/harbormaster/artifact/HarbormasterURIArtifact.php
@@ -1,109 +1,119 @@
<?php
final class HarbormasterURIArtifact extends HarbormasterArtifact {
const ARTIFACTCONST = 'uri';
public function getArtifactTypeName() {
return pht('URI');
}
public function getArtifactTypeSummary() {
return pht('Stores a URI.');
}
public function getArtifactTypeDescription() {
return pht(
"Stores a URI.\n\n".
"With `ui.external`, you can use this artifact type to add links to ".
"build results in an external build system.");
}
public function getArtifactParameterSpecification() {
return array(
'uri' => 'string',
'name' => 'optional string',
'ui.external' => 'optional bool',
);
}
+ public function readArtifactHTTPParameter($key, $value) {
+ // TODO: This is hacky and artifact parameters should be replaced more
+ // broadly, likely with EditFields. See T11887.
+ switch ($key) {
+ case 'ui.external':
+ return (bool)$value;
+ }
+ return $value;
+ }
+
public function getArtifactParameterDescriptions() {
return array(
'uri' => pht('The URI to store.'),
'name' => pht('Optional label for this URI.'),
'ui.external' => pht(
'If true, display this URI in the UI as an link to '.
'additional build details in an external build system.'),
);
}
public function getArtifactDataExample() {
return array(
'uri' => 'https://buildserver.mycompany.com/build/123/',
'name' => pht('View External Build Results'),
'ui.external' => true,
);
}
public function renderArtifactSummary(PhabricatorUser $viewer) {
return $this->renderLink();
}
public function isExternalLink() {
$artifact = $this->getBuildArtifact();
return (bool)$artifact->getProperty('ui.external', false);
}
public function renderLink() {
$artifact = $this->getBuildArtifact();
$uri = $artifact->getProperty('uri');
try {
$this->validateURI($uri);
} catch (Exception $ex) {
return pht('<Invalid URI>');
}
$name = $artifact->getProperty('name', $uri);
return phutil_tag(
'a',
array(
'href' => $uri,
'target' => '_blank',
),
$name);
}
public function willCreateArtifact(PhabricatorUser $actor) {
$artifact = $this->getBuildArtifact();
$uri = $artifact->getProperty('uri');
$this->validateURI($uri);
}
private function validateURI($raw_uri) {
$uri = new PhutilURI($raw_uri);
$protocol = $uri->getProtocol();
if (!strlen($protocol)) {
throw new Exception(
pht(
'Unable to identify the protocol for URI "%s". URIs must be '.
'fully qualified and have an identifiable protocol.',
$raw_uri));
}
$protocol_key = 'uri.allowed-protocols';
$protocols = PhabricatorEnv::getEnvConfig($protocol_key);
if (empty($protocols[$protocol])) {
throw new Exception(
pht(
'URI "%s" does not have an allowable protocol. Configure '.
'protocols in `%s`. Allowed protocols are: %s.',
$raw_uri,
$protocol_key,
implode(', ', array_keys($protocols))));
}
}
}
diff --git a/src/applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php b/src/applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php
index 56702bf99e..1a04be934f 100644
--- a/src/applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php
+++ b/src/applications/harbormaster/conduit/HarbormasterCreateArtifactConduitAPIMethod.php
@@ -1,129 +1,146 @@
<?php
final class HarbormasterCreateArtifactConduitAPIMethod
extends HarbormasterConduitAPIMethod {
public function getAPIMethodName() {
return 'harbormaster.createartifact';
}
public function getMethodSummary() {
return pht('Create a build artifact.');
}
public function getMethodDescription() {
$types = HarbormasterArtifact::getAllArtifactTypes();
$types = msort($types, 'getArtifactTypeName');
$head_key = pht('Key');
$head_type = pht('Type');
$head_desc = pht('Description');
$head_atype = pht('Artifact Type');
$head_name = pht('Name');
$head_summary = pht('Summary');
$out = array();
$out[] = pht(
'Use this method to attach artifacts to build targets while running '.
'builds. Artifacts can be used to carry data through a complex build '.
'workflow, provide extra information to users, or store build results.');
$out[] = null;
$out[] = pht(
'When creating an artifact, you will choose an `artifactType` from '.
'this table. These types of artifacts are supported:');
$out[] = "| {$head_atype} | {$head_name} | {$head_summary} |";
$out[] = '|-------------|--------------|--------------|';
foreach ($types as $type) {
$type_name = $type->getArtifactTypeName();
$type_const = $type->getArtifactConstant();
$type_summary = $type->getArtifactTypeSummary();
$out[] = "| `{$type_const}` | **{$type_name}** | {$type_summary} |";
}
$out[] = null;
$out[] = pht(
'Each artifact also needs an `artifactKey`, which names the artifact. '.
'Finally, you will provide some `artifactData` to fill in the content '.
'of the artifact. The data you provide depends on what type of artifact '.
'you are creating.');
foreach ($types as $type) {
$type_name = $type->getArtifactTypeName();
$type_const = $type->getArtifactConstant();
$out[] = $type_name;
$out[] = '--------------------------';
$out[] = null;
$out[] = $type->getArtifactTypeDescription();
$out[] = null;
$out[] = pht(
'Create an artifact of this type by passing `%s` as the '.
'`artifactType`. When creating an artifact of this type, provide '.
'these parameters as a dictionary to `artifactData`:',
$type_const);
$spec = $type->getArtifactParameterSpecification();
$desc = $type->getArtifactParameterDescriptions();
$out[] = "| {$head_key} | {$head_type} | {$head_desc} |";
$out[] = '|-------------|--------------|--------------|';
foreach ($spec as $key => $key_type) {
$key_desc = idx($desc, $key);
$out[] = "| `{$key}` | //{$key_type}// | {$key_desc} |";
}
$example = $type->getArtifactDataExample();
if ($example !== null) {
$json = new PhutilJSON();
$rendered = $json->encodeFormatted($example);
$out[] = pht('For example:');
$out[] = '```lang=json';
$out[] = $rendered;
$out[] = '```';
}
}
return implode("\n", $out);
}
protected function defineParamTypes() {
return array(
'buildTargetPHID' => 'phid',
'artifactKey' => 'string',
'artifactType' => 'string',
'artifactData' => 'map<string, wild>',
);
}
protected function defineReturnType() {
return 'wild';
}
protected function execute(ConduitAPIRequest $request) {
$viewer = $request->getUser();
$build_target_phid = $request->getValue('buildTargetPHID');
$build_target = id(new HarbormasterBuildTargetQuery())
->setViewer($viewer)
->withPHIDs(array($build_target_phid))
->executeOne();
if (!$build_target) {
throw new Exception(
pht(
'No such build target "%s"!',
$build_target_phid));
}
+ $artifact_type = $request->getValue('artifactType');
+
+ // Cast "artifactData" parameters to acceptable types if this request
+ // is submitting raw HTTP parameters. This is not ideal. See T11887 for
+ // discussion.
+ $artifact_data = $request->getValue('artifactData');
+ if (!$request->getIsStrictlyTyped()) {
+ $impl = HarbormasterArtifact::getArtifactType($artifact_type);
+ if ($impl) {
+ foreach ($artifact_data as $key => $value) {
+ $artifact_data[$key] = $impl->readArtifactHTTPParameter(
+ $key,
+ $value);
+ }
+ }
+ }
+
$artifact = $build_target->createArtifact(
$viewer,
$request->getValue('artifactKey'),
- $request->getValue('artifactType'),
- $request->getValue('artifactData'));
+ $artifact_type,
+ $artifact_data);
return array(
'data' => $this->returnArtifactList(array($artifact)),
);
}
}
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sun, Jan 19, 14:02 (3 w, 3 d ago)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1125331
Default Alt Text
(10 KB)
Attached To
Mode
rP Phorge
Attached
Detach File
Event Timeline
Log In to Comment