diff --git a/src/applications/differential/storage/DifferentialDiff.php b/src/applications/differential/storage/DifferentialDiff.php
--- a/src/applications/differential/storage/DifferentialDiff.php
+++ b/src/applications/differential/storage/DifferentialDiff.php
@@ -333,6 +333,38 @@
     return null;
   }
 
+  public function getBuildVariables() {
+    $results = array();
+
+    $results['buildable.diff'] = $this->getID();
+    $revision = $this->getRevision();
+    $results['buildable.revision'] = $revision->getID();
+    $repo = $revision->getRepository();
+
+    if ($repo) {
+      $results['repository.callsign'] = $repo->getCallsign();
+      $results['repository.vcs'] = $repo->getVersionControlSystem();
+      $results['repository.uri'] = $repo->getPublicCloneURI();
+    }
+
+    return $results;
+  }
+
+  public function getAvailableBuildVariables() {
+    return array(
+      'buildable.diff' =>
+        pht('The differential diff ID, if applicable.'),
+      'buildable.revision' =>
+        pht('The differential revision ID, if applicable.'),
+      'repository.callsign' =>
+        pht('The callsign of the repository in Phabricator.'),
+      'repository.vcs' =>
+        pht('The version control system, either "svn", "hg" or "git".'),
+      'repository.uri' =>
+        pht('The URI to clone or checkout the repository from.'),
+    );
+  }
+
 
 /* -(  PhabricatorApplicationTransactionInterface  )------------------------- */
 
diff --git a/src/applications/differential/storage/DifferentialRevision.php b/src/applications/differential/storage/DifferentialRevision.php
--- a/src/applications/differential/storage/DifferentialRevision.php
+++ b/src/applications/differential/storage/DifferentialRevision.php
@@ -361,6 +361,14 @@
     return $this->getPHID();
   }
 
+  public function getBuildVariables() {
+    return array();
+  }
+
+  public function getAvailableBuildVariables() {
+    return array();
+  }
+
 
 /* -(  PhabricatorSubscribableInterface  )----------------------------------- */
 
diff --git a/src/applications/harbormaster/interface/HarbormasterBuildableInterface.php b/src/applications/harbormaster/interface/HarbormasterBuildableInterface.php
--- a/src/applications/harbormaster/interface/HarbormasterBuildableInterface.php
+++ b/src/applications/harbormaster/interface/HarbormasterBuildableInterface.php
@@ -5,4 +5,8 @@
   public function getHarbormasterBuildablePHID();
   public function getHarbormasterContainerPHID();
 
+  public function getBuildVariables();
+
+  public function getAvailableBuildVariables();
+
 }
diff --git a/src/applications/harbormaster/storage/HarbormasterBuildable.php b/src/applications/harbormaster/storage/HarbormasterBuildable.php
--- a/src/applications/harbormaster/storage/HarbormasterBuildable.php
+++ b/src/applications/harbormaster/storage/HarbormasterBuildable.php
@@ -250,5 +250,13 @@
     return $this->getContainerPHID();
   }
 
+  public function getBuildVariables() {
+    return array();
+  }
+
+  public function getAvailableBuildVariables() {
+    return array();
+  }
+
 
 }
diff --git a/src/applications/harbormaster/storage/build/HarbormasterBuild.php b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
--- a/src/applications/harbormaster/storage/build/HarbormasterBuild.php
+++ b/src/applications/harbormaster/storage/build/HarbormasterBuild.php
@@ -235,22 +235,9 @@
     $buildable = $this->getBuildable();
     $object = $buildable->getBuildableObject();
 
-    $repo = null;
-    if ($object instanceof DifferentialDiff) {
-      $results['buildable.diff'] = $object->getID();
-      $revision = $object->getRevision();
-      $results['buildable.revision'] = $revision->getID();
-      $repo = $revision->getRepository();
-    } else if ($object instanceof PhabricatorRepositoryCommit) {
-      $results['buildable.commit'] = $object->getCommitIdentifier();
-      $repo = $object->getRepository();
-    }
+    $object_variables = $object->getBuildVariables();
 
-    if ($repo) {
-      $results['repository.callsign'] = $repo->getCallsign();
-      $results['repository.vcs'] = $repo->getVersionControlSystem();
-      $results['repository.uri'] = $repo->getPublicCloneURI();
-    }
+    $results = $object_variables + $results;
 
     $results['step.timestamp'] = time();
     $results['build.id'] = $this->getID();
@@ -259,22 +246,23 @@
   }
 
   public static function getAvailableBuildVariables() {
-    return array(
-      'buildable.diff' =>
-        pht('The differential diff ID, if applicable.'),
-      'buildable.revision' =>
-        pht('The differential revision ID, if applicable.'),
-      'buildable.commit' => pht('The commit identifier, if applicable.'),
-      'repository.callsign' =>
-        pht('The callsign of the repository in Phabricator.'),
-      'repository.vcs' =>
-        pht('The version control system, either "svn", "hg" or "git".'),
-      'repository.uri' =>
-        pht('The URI to clone or checkout the repository from.'),
+    $objects = id(new PhutilSymbolLoader())
+      ->setAncestorClass('HarbormasterBuildableInterface')
+      ->loadObjects();
+
+    $variables = array();
+    $variables[] = array(
       'step.timestamp' => pht('The current UNIX timestamp.'),
       'build.id' => pht('The ID of the current build.'),
       'target.phid' => pht('The PHID of the current build target.'),
     );
+
+    foreach ($objects as $object) {
+      $variables[] = $object->getAvailableBuildVariables();
+    }
+
+    $variables = array_mergev($variables);
+    return $variables;
   }
 
   public function isComplete() {
diff --git a/src/applications/repository/storage/PhabricatorRepositoryCommit.php b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
--- a/src/applications/repository/storage/PhabricatorRepositoryCommit.php
+++ b/src/applications/repository/storage/PhabricatorRepositoryCommit.php
@@ -282,6 +282,31 @@
     return $this->getRepository()->getPHID();
   }
 
+  public function getBuildVariables() {
+    $results = array();
+
+    $results['buildable.commit'] = $this->getCommitIdentifier();
+    $repo = $this->getRepository();
+
+    $results['repository.callsign'] = $repo->getCallsign();
+    $results['repository.vcs'] = $repo->getVersionControlSystem();
+    $results['repository.uri'] = $repo->getPublicCloneURI();
+
+    return $results;
+  }
+
+  public function getAvailableBuildVariables() {
+    return array(
+      'buildable.commit' => pht('The commit identifier, if applicable.'),
+      'repository.callsign' =>
+        pht('The callsign of the repository in Phabricator.'),
+      'repository.vcs' =>
+        pht('The version control system, either "svn", "hg" or "git".'),
+      'repository.uri' =>
+        pht('The URI to clone or checkout the repository from.'),
+    );
+  }
+
 
 /* -(  PhabricatorCustomFieldInterface  )------------------------------------ */