diff --git a/ci-eye.iml b/ci-eye.iml
index 48c61c6..da19e6d 100644
--- a/ci-eye.iml
+++ b/ci-eye.iml
@@ -9,8 +9,8 @@
-
-
+
+
diff --git a/src/main/java/org/netmelody/cieye/core/utility/ProjectAbbreviator.java b/src/main/java/org/netmelody/cieye/core/utility/ProjectAbbreviator.java
new file mode 100644
index 0000000..b8ec8dd
--- /dev/null
+++ b/src/main/java/org/netmelody/cieye/core/utility/ProjectAbbreviator.java
@@ -0,0 +1,24 @@
+package org.netmelody.cieye.core.utility;
+
+import java.util.regex.Pattern;
+
+public class ProjectAbbreviator {
+
+ public String abbreviate(String projectName) {
+ StringBuilder out = new StringBuilder();
+ String[] nameParts = Pattern.compile("[-\\s]+").split(projectName);
+ if (nameParts.length == 1) {
+ return projectName;
+ } else {
+ for (String s : nameParts) {
+ out.append(s.charAt(0));
+ }
+ return out.toString();
+ }
+ }
+
+
+ public static String nameWithProjectAbbreviation(String projectName, String buildName) {
+ return new ProjectAbbreviator().abbreviate(projectName) + ": " + buildName;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/netmelody/cieye/server/observation/IntelligenceAgency.java b/src/main/java/org/netmelody/cieye/server/observation/IntelligenceAgency.java
index 940856d..7157acb 100644
--- a/src/main/java/org/netmelody/cieye/server/observation/IntelligenceAgency.java
+++ b/src/main/java/org/netmelody/cieye/server/observation/IntelligenceAgency.java
@@ -70,6 +70,7 @@ private PollingSpyHandler spyFor(Feature feature) {
private PollingSpyHandler createSpyFor(Feature feature) {
final ObservationAgency agency = foreignAgencies.agencyFor(feature.type());
final CiSpy spy = agency.provideSpyFor(feature, network, directory);
+ agencies.put(feature.type(), agency);
return new PollingSpyHandler(spy, feature);
}
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/BuildTypeAnalyser.java b/src/main/java/org/netmelody/cieye/spies/teamcity/BuildTypeAnalyser.java
index 8da3da3..8564933 100644
--- a/src/main/java/org/netmelody/cieye/spies/teamcity/BuildTypeAnalyser.java
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/BuildTypeAnalyser.java
@@ -1,24 +1,19 @@
package org.netmelody.cieye.spies.teamcity;
-import static org.netmelody.cieye.core.domain.Percentage.percentageOf;
+import org.netmelody.cieye.core.domain.RunningBuild;
+import org.netmelody.cieye.core.domain.Sponsor;
+import org.netmelody.cieye.core.domain.Status;
+import org.netmelody.cieye.core.domain.TargetDetail;
+import org.netmelody.cieye.core.observation.KnownOffendersDirectory;
+import org.netmelody.cieye.spies.teamcity.jsondomain.*;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
-import org.netmelody.cieye.core.domain.RunningBuild;
-import org.netmelody.cieye.core.domain.Sponsor;
-import org.netmelody.cieye.core.domain.Status;
-import org.netmelody.cieye.core.domain.TargetDetail;
-import org.netmelody.cieye.core.observation.KnownOffendersDirectory;
-import org.netmelody.cieye.spies.teamcity.jsondomain.Build;
-import org.netmelody.cieye.spies.teamcity.jsondomain.BuildDetail;
-import org.netmelody.cieye.spies.teamcity.jsondomain.BuildType;
-import org.netmelody.cieye.spies.teamcity.jsondomain.BuildTypeDetail;
-import org.netmelody.cieye.spies.teamcity.jsondomain.Change;
-import org.netmelody.cieye.spies.teamcity.jsondomain.ChangeDetail;
-import org.netmelody.cieye.spies.teamcity.jsondomain.Investigation;
+import static org.netmelody.cieye.core.domain.Percentage.percentageOf;
+import static org.netmelody.cieye.core.utility.ProjectAbbreviator.nameWithProjectAbbreviation;
public final class BuildTypeAnalyser {
@@ -29,12 +24,12 @@ public BuildTypeAnalyser(TeamCityCommunicator communicator, KnownOffendersDirect
this.communicator = communicator;
this.detective = detective;
}
-
+
public TargetDetail targetFrom(BuildType buildType) {
final BuildTypeDetail buildTypeDetail = communicator.detailsFor(buildType);
- if (buildTypeDetail.paused) {
- return new TargetDetail(communicator.endpoint() + buildType.href, buildType.webUrl(), buildType.name, Status.DISABLED, 0L);
+ if (buildTypeDetail.paused || buildTypeDetail.externalStatusDisabled()) {
+ return new TargetDetail(communicator.endpoint() + buildType.href, buildType.webUrl(), nameWithProjectAbbreviation(buildType.projectName, buildType.name), Status.DISABLED, 0L);
}
final Set sponsors = new HashSet();
@@ -67,7 +62,7 @@ public TargetDetail targetFrom(BuildType buildType) {
}
}
- return new TargetDetail(communicator.endpoint() + buildType.href, buildType.webUrl(), buildType.name, currentStatus, startTime, runningBuilds, sponsors);
+ return new TargetDetail(communicator.endpoint() + buildType.href, buildType.webUrl(), nameWithProjectAbbreviation(buildType.projectName, buildType.name), currentStatus, startTime, runningBuilds, sponsors);
}
private Set sponsorsOf(BuildDetail build) {
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCityCommunicator.java b/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCityCommunicator.java
index b592ea3..5864a79 100644
--- a/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCityCommunicator.java
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCityCommunicator.java
@@ -37,7 +37,7 @@ public final class TeamCityCommunicator {
public TeamCityCommunicator(Contact contact, String endpoint) {
this.contact = contact;
this.endpoint = endpoint;
- this.prefix = (contact.privileged() ? "/httpAuth" : "/guestAuth") + "/app/rest";
+ this.prefix = (contact.privileged() ? "/httpAuth" : "/guestAuth") + "/app/rest/7.0";
}
public String endpoint() {
@@ -91,18 +91,18 @@ public void commentOn(Build lastCompletedBuild, String note) {
public List changesOf(BuildDetail buildDetail) {
final JsonElement json = contact.makeJsonRestCall(endpoint + buildDetail.changes.href);
final JsonElement change = json.isJsonObject() ? json.getAsJsonObject().get("change") : JsonNull.INSTANCE;
-
+
if (null == change || !(change.isJsonArray() || change.isJsonObject())) {
return ImmutableList.of();
}
-
+
final Gson gson = new Gson();
final List changes = new ArrayList();
final Iterable changesJson = change.isJsonArray() ? change.getAsJsonArray() : ImmutableList.of(change);
for (JsonElement jsonElement : changesJson) {
changes.add(gson.fromJson(jsonElement, Change.class));
}
-
+
return changes;
}
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCitySpy.java b/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCitySpy.java
index ce29aac..8222ab0 100644
--- a/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCitySpy.java
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/TeamCitySpy.java
@@ -4,6 +4,7 @@
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Maps.newHashMap;
import static org.netmelody.cieye.core.domain.Status.UNKNOWN;
+import static org.netmelody.cieye.core.utility.ProjectAbbreviator.nameWithProjectAbbreviation;
import java.util.Collection;
import java.util.List;
@@ -42,7 +43,7 @@ public TargetDigestGroup targetsConstituting(Feature feature) {
final List digests = newArrayList();
for (BuildType buildType : buildTypes) {
- final TargetDigest targetDigest = new TargetDigest(communicator.endpoint() + buildType.href, buildType.webUrl(), buildType.name, UNKNOWN);
+ final TargetDigest targetDigest = new TargetDigest(communicator.endpoint() + buildType.href, buildType.webUrl(), nameWithProjectAbbreviation(buildType.projectName, buildType.name), UNKNOWN);
digests.add(targetDigest);
recognisedBuildTypes.put(targetDigest.id(), buildType);
}
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettings.java b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettings.java
new file mode 100644
index 0000000..3230832
--- /dev/null
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettings.java
@@ -0,0 +1,28 @@
+package org.netmelody.cieye.spies.teamcity.jsondomain;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
+
+import java.util.List;
+
+import static java.lang.Boolean.parseBoolean;
+
+public class BuildSettings {
+ public List property;
+
+ public boolean externalStatusDisabled() {
+ Optional allowExternalStatus = Iterables.tryFind(property, new Predicate() {
+ @Override
+ public boolean apply(BuildSettingsProperty input) {
+ return "allowExternalStatus".equals(input.name);
+ }
+ });
+
+ if (allowExternalStatus.isPresent()) {
+ return !Boolean.parseBoolean(allowExternalStatus.get().value);
+ } else {
+ return false;
+ }
+ }
+}
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsProperty.java b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsProperty.java
new file mode 100644
index 0000000..1918b63
--- /dev/null
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsProperty.java
@@ -0,0 +1,6 @@
+package org.netmelody.cieye.spies.teamcity.jsondomain;
+
+public class BuildSettingsProperty {
+ public String name;
+ public String value;
+}
diff --git a/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildTypeDetail.java b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildTypeDetail.java
index 9aedce0..d0b1121 100644
--- a/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildTypeDetail.java
+++ b/src/main/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildTypeDetail.java
@@ -6,6 +6,11 @@ public final class BuildTypeDetail extends BuildType {
public boolean paused;
public Project project;
public BuildsHref builds;
+ public BuildSettings settings;
+
+ public boolean externalStatusDisabled() {
+ return settings != null && settings.externalStatusDisabled();
+ }
//vcs-root
//parameters
//runParameters
diff --git a/src/main/webapp/resources/cieye.js b/src/main/webapp/resources/cieye.js
index 4efc4fc..be1718b 100644
--- a/src/main/webapp/resources/cieye.js
+++ b/src/main/webapp/resources/cieye.js
@@ -280,11 +280,19 @@ ORG.NETMELODY.CIEYE.newRadiatorWidget = function() {
}
var result = true;
- $.each(targetsJson, function(index, targetJson) {
- if (targetJson.builds.length !== 0 || (targetJson.status !== "GREEN" && targetJson.status !== "DISABLED")) {
+ $.each(targetsJson, function(i, targetJson) {
+ if (targetJson.status !== "GREEN" && targetJson.status !== "DISABLED") {
result = false;
return false;
}
+ if (targetJson.builds.length > 0) {
+ $.each(targetJson.builds, function (i2, build) {
+ if (build.status !== "GREEN") {
+ result = false;
+ return false;
+ }
+ });
+ }
});
return result;
}
diff --git a/src/test/java/org/netmelody/cieye/core/utility/ProjectAbbreviatorTest.java b/src/test/java/org/netmelody/cieye/core/utility/ProjectAbbreviatorTest.java
new file mode 100644
index 0000000..5d58efb
--- /dev/null
+++ b/src/test/java/org/netmelody/cieye/core/utility/ProjectAbbreviatorTest.java
@@ -0,0 +1,24 @@
+package org.netmelody.cieye.core.utility;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.equalTo;
+
+public class ProjectAbbreviatorTest {
+
+ @Test
+ public void doesNotAbbreviateIfNoSpaceInName() throws Throwable {
+ Assert.assertThat("myProjectName", equalTo(new ProjectAbbreviator().abbreviate("myProjectName")));
+ }
+
+ @Test
+ public void abbreviatesToFirstLettersOfWordsIfThereAreSpaces() throws Throwable {
+ Assert.assertThat("MpN", equalTo(new ProjectAbbreviator().abbreviate("My project Name")));
+ }
+
+ @Test
+ public void abbreviatesToFirstLettersOfWordsIfThereAreHyphens() throws Throwable {
+ Assert.assertThat("MpNh", equalTo(new ProjectAbbreviator().abbreviate("My-project Name-hyphens")));
+ }
+}
\ No newline at end of file
diff --git a/src/test/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsTest.java b/src/test/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsTest.java
new file mode 100644
index 0000000..c48187f
--- /dev/null
+++ b/src/test/java/org/netmelody/cieye/spies/teamcity/jsondomain/BuildSettingsTest.java
@@ -0,0 +1,41 @@
+package org.netmelody.cieye.spies.teamcity.jsondomain;
+
+import org.junit.Test;
+
+import static com.google.common.collect.Lists.newArrayList;
+import static org.hamcrest.CoreMatchers.equalTo;
+import static org.junit.Assert.assertThat;
+
+public class BuildSettingsTest {
+
+ @Test
+ public void isDisabledWhenAllowExternalStatusIsFalse() {
+ BuildSettings buildSettings = createBuildSettingsWithAllowExternalStatus("false");
+
+ assertThat(buildSettings.externalStatusDisabled(), equalTo(true));
+ }
+
+ @Test
+ public void isNotDisabledWhenAllowExternalStatusIsTrue() {
+ BuildSettings buildSettings = createBuildSettingsWithAllowExternalStatus("true");
+
+ assertThat(buildSettings.externalStatusDisabled(), equalTo(false));
+ }
+
+ @Test
+ public void isNotDisabledWhenAllowExternalStatusIsNotPresent() {
+ BuildSettings buildSettings = new BuildSettings();
+ buildSettings.property = newArrayList();
+
+ assertThat(buildSettings.externalStatusDisabled(), equalTo(false));
+ }
+
+ private BuildSettings createBuildSettingsWithAllowExternalStatus(String allowExternalStatus) {
+ BuildSettings buildSettings = new BuildSettings();
+ final BuildSettingsProperty property = new BuildSettingsProperty();
+ property.name = "allowExternalStatus";
+ property.value = allowExternalStatus;
+ buildSettings.property = newArrayList(property);
+ return buildSettings;
+ }
+}