Page MenuHomePhorge

No OneTemporary

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

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)

Event Timeline