Support exporting properties to task json

This can be use to indicate the intended actor (such as a CI system)
which a task is expected to be implemented by, possibly along with other
config details the CI system may need.

Change-Id: Ia8c7a3d87ec4dc64779c8c053623ba8ca4b727de
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
index 5502328..8af38b5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/Properties.java
@@ -41,9 +41,18 @@
     expanded.put("_name", definition.name);
 
     unexpanded = definition.properties;
+    unexpanded.putAll(definition.exported);
     expandAllUnexpanded();
     definition.properties = expanded;
 
+    if (definition.exported.isEmpty()) {
+      definition.exported = null;
+    } else {
+      for (String property : definition.exported.keySet()) {
+        definition.exported.put(property, expanded.get(property));
+      }
+    }
+
     this.definition = definition;
     expandNonPropertyFields();
   }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
index 3ce2a37..49d2b33 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskAttributeFactory.java
@@ -48,6 +48,7 @@
 
   public static class TaskAttribute {
     public Boolean applicable;
+    public Map<String, String> exported;
     public Boolean hasPass;
     public String hint;
     public Boolean inProgress;
@@ -140,6 +141,7 @@
               task.inProgress = matchOrNull(c, def.inProgress);
             }
             task.hint = getHint(task.status, def);
+            task.exported = def.exported;
             tasks.add(task);
           }
         }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
index 0f94f29..0bc8fa5 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/task/TaskConfig.java
@@ -37,6 +37,7 @@
 
   public class Task extends Section {
     public String applicable;
+    public Map<String, String> exported;
     public String fail;
     public String failHint;
     public String inProgress;
@@ -55,6 +56,7 @@
       this.isVisible = isVisible;
       this.isTrusted = isTrusted;
       applicable = getString(s, KEY_APPLICABLE, null);
+      exported = getProperties(s, KEY_EXPORT_PREFIX);
       fail = getString(s, KEY_FAIL, null);
       failHint = getString(s, KEY_FAIL_HINT, null);
       inProgress = getString(s, KEY_IN_PROGRESS, null);
@@ -84,6 +86,7 @@
   protected static final String SECTION_ROOT = "root";
   protected static final String SECTION_TASK = "task";
   protected static final String KEY_APPLICABLE = "applicable";
+  protected static final String KEY_EXPORT_PREFIX = "export-";
   protected static final String KEY_FAIL = "fail";
   protected static final String KEY_FAIL_HINT = "fail-hint";
   protected static final String KEY_FILE = "file";
diff --git a/src/main/resources/Documentation/task.md b/src/main/resources/Documentation/task.md
index 9397260..6980a98 100644
--- a/src/main/resources/Documentation/task.md
+++ b/src/main/resources/Documentation/task.md
@@ -291,6 +291,31 @@
         ...
 ```
 
+It is possible to define a custom property value and to export that value
+to the json on the current task by using the following syntax:
+```
+    export-<property-name> = <property-value>
+```
+
+Example:
+```
+    [task "foo"]
+        export-ci-system = jenkins
+```
+
+```
+     "subTasks" : [
+        {
+           "exported" : {
+              "ci-system" : "jenkins"
+           },
+           ...
+           "name" : "foo",
+           ...
+        }
+     ]
+```
+
 Change Query Output
 -------------------
 It is possible to add a task section to the query output of changes using
diff --git a/src/main/resources/Documentation/task_states.md b/src/main/resources/Documentation/task_states.md
index 9c3dd98..222728c 100644
--- a/src/main/resources/Documentation/task_states.md
+++ b/src/main/resources/Documentation/task_states.md
@@ -107,6 +107,7 @@
 
 [root "Root Properties"]
   set-root-property = root-value
+  export-root = ${_name}
   fail = True
   fail-hint = Name(${_name})
   subtask = Subtask Properties
@@ -153,8 +154,9 @@
   set-first-property = first-value
   set-second-property = ${first-property} second-extra ${third-property}
   set-third-property = third-value
+  export-subtask = ${_name}
   fail = True
-  fail-hint = Name(${_name}) root-property(${root-property}) first-property(${first-property}) second-property(${second-property})
+  fail-hint = Name(${_name}) root-property(${root-property}) first-property(${first-property}) second-property(${second-property}) root(${root})
 
 [task "Chained Subtask Properties"]
   pass = True
@@ -511,6 +513,9 @@
                ]
             },
             {
+               "exported" : {
+                  "root" : "Root Properties"
+               },
                "hasPass" : true,
                "hint" : "Name(Root Properties)",
                "name" : "Root Properties",
@@ -522,8 +527,11 @@
                      "status" : "WAITING",
                      "subTasks" : [
                         {
+                           "exported" : {
+                              "subtask" : "Subtask Properties Hints"
+                           },
                            "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value)",
+                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
                            "name" : "Subtask Properties Hints",
                            "status" : "FAIL"
                         },
diff --git a/test/all b/test/all
index 04f9701..ef506c7 100644
--- a/test/all
+++ b/test/all
@@ -303,6 +303,9 @@
             },
             {
                "applicable" : true,
+               "exported" : {
+                  "root" : "Root Properties"
+               },
                "hasPass" : true,
                "hint" : "Name(Root Properties)",
                "name" : "Root Properties",
@@ -316,8 +319,11 @@
                      "subTasks" : [
                         {
                            "applicable" : true,
+                           "exported" : {
+                              "subtask" : "Subtask Properties Hints"
+                           },
                            "hasPass" : true,
-                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value)",
+                           "hint" : "Name(Subtask Properties Hints) root-property(root-value) first-property(first-value) second-property(first-value second-extra third-value) root(Root Properties)",
                            "name" : "Subtask Properties Hints",
                            "status" : "FAIL"
                         },