aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md24
-rw-r--r--src/main/java/io/trygvis/esper/testing/AbstractDto.java28
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildDto.java10
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXml.java41
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsDao.java78
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJobDto.java10
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerActor.java29
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerDto.java25
-rw-r--r--src/main/java/io/trygvis/esper/testing/jenkins/JenkinsUserDto.java17
-rw-r--r--src/main/java/io/trygvis/esper/testing/sql/SqlF.java15
-rw-r--r--src/main/java/io/trygvis/esper/testing/sql/SqlOption.java83
-rw-r--r--src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java2
-rw-r--r--src/main/resources/ddl-core.sql38
-rw-r--r--src/main/resources/ddl-jenkins.sql12
-rw-r--r--src/main/webapp/apps/jenkinsApp/server.html10
-rw-r--r--src/test/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXmlTest.java3
16 files changed, 339 insertions, 86 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..56800b5
--- /dev/null
+++ b/README.md
@@ -0,0 +1,24 @@
+# Core Concepts
+
+* Person
+* Build - an execution of a CI job. Can have a user that triggered the job, either directly or through a commit
+* Commit - a change in the source control system
+* Product(?) - a set of git repositories, svn trunks and jenkins jobs/builds. Many persons can be participating in
+ developing the product (creates a team concept).
+* Gang Programming Session - a session with multiple people working together on the same problem.
+
+# Badges
+
+## Unbreakable - Per Person
+
+N builds started by U in a row that didn't break the build
+
+## Well Tested - Per Product
+
+Product P has increased the number of tests the last N (commits|days).
+
+## Gang Programmer
+
+Level 1: 3 programmers
+Level 2: 4 programmers
+Level 3: 5 programmers
diff --git a/src/main/java/io/trygvis/esper/testing/AbstractDto.java b/src/main/java/io/trygvis/esper/testing/AbstractDto.java
new file mode 100644
index 0000000..6c2e778
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/AbstractDto.java
@@ -0,0 +1,28 @@
+package io.trygvis.esper.testing;
+
+import org.joda.time.*;
+
+import java.util.*;
+
+public abstract class AbstractDto {
+ public final UUID uuid;
+ public final DateTime createdDate;
+
+ protected AbstractDto(UUID uuid, DateTime createdDate) {
+ this.uuid = uuid;
+ this.createdDate = createdDate;
+ }
+
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AbstractDto)) return false;
+
+ AbstractDto that = (AbstractDto) o;
+
+ return uuid.equals(that.uuid);
+ }
+
+ public int hashCode() {
+ return uuid.hashCode();
+ }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildDto.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildDto.java
index 28f597d..8076eaa 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildDto.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildDto.java
@@ -1,13 +1,12 @@
package io.trygvis.esper.testing.jenkins;
+import io.trygvis.esper.testing.*;
import org.joda.time.*;
import java.net.*;
import java.util.*;
-public class JenkinsBuildDto {
- public final UUID uuid;
- public final DateTime created_date;
+public class JenkinsBuildDto extends AbstractDto {
public final UUID job;
public final String entryId;
public final URI url;
@@ -16,9 +15,8 @@ public class JenkinsBuildDto {
public final int duration;
public final DateTime timestamp;
- JenkinsBuildDto(UUID uuid, DateTime created_date, UUID job, String entryId, URI url, String result, int number, int duration, DateTime timestamp) {
- this.uuid = uuid;
- this.created_date = created_date;
+ JenkinsBuildDto(UUID uuid, DateTime createdDate, UUID job, String entryId, URI url, String result, int number, int duration, DateTime timestamp) {
+ super(uuid, createdDate);
this.job = job;
this.entryId = entryId;
this.url = url;
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXml.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXml.java
index 169a65c..cb92736 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXml.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXml.java
@@ -17,9 +17,7 @@ import fj.data.Option;
import io.trygvis.esper.testing.Util;
import static fj.data.List.iterableList;
-import static fj.data.Option.none;
-import static fj.data.Option.some;
-import static fj.data.Option.somes;
+import static fj.data.Option.*;
import static io.trygvis.esper.testing.Util.childText;
import static io.trygvis.esper.testing.Util.parseInt;
import static io.trygvis.esper.testing.jenkins.JenkinsBuildXml.ChangeSetItemXml.parseChangeSetItem;
@@ -109,16 +107,13 @@ public class JenkinsBuildXml {
public final String msg;
- /**
- * Only subversion has this field
- */
- public final Option<String> user;
+ public final Option<AuthorXml> author;
- public ChangeSetItemXml(String commitId, DateTime date, String msg, Option<String> user) {
+ public ChangeSetItemXml(String commitId, DateTime date, String msg, Option<AuthorXml> author) {
this.commitId = commitId;
this.date = date;
this.msg = msg;
- this.user = user;
+ this.author = author;
}
private static final F<String, Option<DateTime>> parseDate = new F<String, Option<DateTime>>() {
@@ -145,13 +140,37 @@ public class JenkinsBuildXml {
Option<String> commitId = childText(item, "commitId");
Option<DateTime> date = childText(item, "date").bind(parseDate);
Option<String> msg = childText(item, "msg");
- Option<String> user = childText(item, "user");
if (commitId.isNone() || date.isNone() || msg.isNone()) {
return none();
}
- return some(new ChangeSetItemXml(commitId.some(), date.some(), msg.some(), user));
+ Option<AuthorXml> author = fromNull(item.getChild("author")).bind(AuthorXml.parseAuthorXml);
+
+ return some(new ChangeSetItemXml(commitId.some(), date.some(), msg.some(), author));
+ }
+ };
+ }
+
+ public static class AuthorXml {
+ public final String absoluteUrl;
+ public final String fullName;
+
+ public AuthorXml(String absoluteUrl, String fullName) {
+ this.absoluteUrl = absoluteUrl;
+ this.fullName = fullName;
+ }
+
+ public static final F<Element, Option<AuthorXml>> parseAuthorXml = new F<Element, Option<AuthorXml>>() {
+ public Option<AuthorXml> f(Element element) {
+ Option<String> absoluteUrl = childText(element, "absoluteUrl");
+ Option<String> fullName = childText(element, "fullName");
+
+ if(absoluteUrl.isNone() || fullName.isNone()) {
+ return none();
+ }
+
+ return some(new AuthorXml(absoluteUrl.some(), fullName.some()));
}
};
}
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsDao.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsDao.java
index bf1954e..2cfff80 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsDao.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsDao.java
@@ -1,6 +1,7 @@
package io.trygvis.esper.testing.jenkins;
import fj.data.*;
+import io.trygvis.esper.testing.sql.*;
import org.joda.time.*;
import java.net.*;
@@ -9,6 +10,7 @@ import java.util.*;
import java.util.List;
import static fj.data.Option.*;
+import static io.trygvis.esper.testing.sql.SqlOption.fromRs;
import static java.lang.System.*;
public class JenkinsDao {
@@ -21,6 +23,8 @@ public class JenkinsDao {
public static final String JENKINS_BUILD = "uuid, created_date, job, entry_id, url, result, number, duration, timestamp";
+ public static final String JENKINS_USER = "uuid, created_date, server, absolute_url";
+
public JenkinsDao(Connection c) {
this.c = c;
}
@@ -60,22 +64,35 @@ public class JenkinsDao {
return list;
}
- private JenkinsBuildDto jenkinsBuild(ResultSet rs) throws SQLException {
- int i = 1;
- return new JenkinsBuildDto(
- UUID.fromString(rs.getString(i++)),
- new DateTime(rs.getTimestamp(i++).getTime()),
- UUID.fromString(rs.getString(i++)),
- rs.getString(i++),
- URI.create(rs.getString(i++)),
- rs.getString(i++),
- rs.getInt(i++),
- rs.getInt(i++),
- new DateTime(rs.getTimestamp(i).getTime()));
- }
+ public static final SqlF<ResultSet, JenkinsBuildDto> jenkinsBuild = new SqlF<ResultSet, JenkinsBuildDto>() {
+ public JenkinsBuildDto apply(ResultSet rs) throws SQLException {
+ int i = 1;
+ return new JenkinsBuildDto(
+ UUID.fromString(rs.getString(i++)),
+ new DateTime(rs.getTimestamp(i++).getTime()),
+ UUID.fromString(rs.getString(i++)),
+ rs.getString(i++),
+ URI.create(rs.getString(i++)),
+ rs.getString(i++),
+ rs.getInt(i++),
+ rs.getInt(i++),
+ new DateTime(rs.getTimestamp(i).getTime()));
+ }
+ };
+
+ public static final SqlF<ResultSet, JenkinsUserDto> jenkinsUser = new SqlF<ResultSet, JenkinsUserDto>() {
+ public JenkinsUserDto apply(ResultSet rs) throws SQLException {
+ int i = 1;
+ return new JenkinsUserDto(
+ UUID.fromString(rs.getString(i++)),
+ new DateTime(rs.getTimestamp(i++).getTime()),
+ UUID.fromString(rs.getString(i++)),
+ rs.getString(i));
+ }
+ };
public List<JenkinsServerDto> selectServers(boolean enabledOnly) throws SQLException {
- String sql = "SELECT " + JENKINS_SERVER + " FROM jenkins_server ";
+ String sql = "SELECT " + JENKINS_SERVER + " FROM jenkins_server";
if (enabledOnly) {
sql += " WHERE enabled=true";
@@ -137,17 +154,11 @@ public class JenkinsDao {
}
}
- public Option<JenkinsBuildDto> selectBuildByEntryId(String id) throws SQLException {
+ public SqlOption<JenkinsBuildDto> selectBuildByEntryId(String id) throws SQLException {
try (PreparedStatement s = c.prepareStatement("SELECT " + JENKINS_BUILD + " FROM jenkins_build WHERE entry_id=?")) {
int i = 1;
s.setString(i, id);
- ResultSet rs = s.executeQuery();
-
- if (!rs.next()) {
- return none();
- }
-
- return some(jenkinsBuild(rs));
+ return fromRs(s.executeQuery()).map(jenkinsBuild);
}
}
@@ -169,4 +180,27 @@ public class JenkinsDao {
return uuid;
}
}
+
+ public UUID insertUser(UUID server, String absoluteUrl) throws SQLException {
+ try (PreparedStatement s = c.prepareStatement("INSERT INTO jenkins_user(" + JENKINS_USER + ") VALUES(?, ?, ?, ?)")) {
+ UUID uuid = UUID.randomUUID();
+ int i = 1;
+ s.setString(i++, uuid.toString());
+ s.setTimestamp(i++, new Timestamp(currentTimeMillis()));
+ s.setString(i++, server.toString());
+ s.setString(i, absoluteUrl);
+ s.executeUpdate();
+
+ return uuid;
+ }
+ }
+
+ public SqlOption<JenkinsUserDto> selectUser(UUID server, String absoluteUrl) throws SQLException {
+ try (PreparedStatement s = c.prepareStatement("SELECT " + JENKINS_USER + " FROM jenkins_user WHERE server=? AND absolute_url=?")) {
+ int i = 1;
+ s.setString(i++, server.toString());
+ s.setString(i, absoluteUrl);
+ return fromRs(s.executeQuery()).map(jenkinsUser);
+ }
+ }
}
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJobDto.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJobDto.java
index 8ee731c..f4ef401 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJobDto.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsJobDto.java
@@ -1,21 +1,19 @@
package io.trygvis.esper.testing.jenkins;
import fj.data.*;
+import io.trygvis.esper.testing.*;
import org.joda.time.*;
import java.net.*;
import java.util.*;
-public class JenkinsJobDto {
- public final UUID uuid;
- public final DateTime created_date;
+public class JenkinsJobDto extends AbstractDto {
public final UUID server;
public final URI url;
public final Option<String> displayName;
- JenkinsJobDto(UUID uuid, DateTime created_date, UUID server, URI url, Option<String> displayName) {
- this.uuid = uuid;
- this.created_date = created_date;
+ JenkinsJobDto(UUID uuid, DateTime createdDate, UUID server, URI url, Option<String> displayName) {
+ super(uuid, createdDate);
this.server = server;
this.url = url;
this.displayName = displayName;
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerActor.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerActor.java
index ebc46ce..ad22157 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerActor.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerActor.java
@@ -2,12 +2,14 @@ package io.trygvis.esper.testing.jenkins;
import fj.data.*;
import io.trygvis.esper.testing.object.*;
+import io.trygvis.esper.testing.sql.*;
import org.slf4j.*;
import java.net.*;
import java.sql.*;
import java.util.List;
import java.util.*;
+import java.util.Set;
import static io.trygvis.esper.testing.jenkins.JenkinsClient.*;
import static java.lang.System.*;
@@ -38,8 +40,10 @@ public class JenkinsServerActor implements TransactionalActor {
int i = 0;
+ Set<String> authorUrls = new TreeSet<>();
+
for (JenkinsEntryXml entry : list) {
- Option<JenkinsBuildDto> o = dao.selectBuildByEntryId(entry.id);
+ SqlOption<JenkinsBuildDto> o = dao.selectBuildByEntryId(entry.id);
if (o.isSome()) {
logger.debug("Old build: " + entry.id);
@@ -62,6 +66,25 @@ public class JenkinsServerActor implements TransactionalActor {
}
String result = build.result.some();
+ if(build.changeSet.isSome()) {
+ JenkinsBuildXml.ChangeSetXml changeSetXml = build.changeSet.some();
+
+ for (JenkinsBuildXml.ChangeSetItemXml item : changeSetXml.items) {
+ if(item.author.isNone()) {
+ continue;
+ }
+
+ String url = item.author.some().absoluteUrl;
+
+ boolean newUser = authorUrls.add(url);
+
+ if(newUser && dao.selectUser(server.uuid, url).isNone()) {
+ logger.info("New user: {}", url);
+ dao.insertUser(server.uuid, url);
+ }
+ }
+ }
+
URI jobUrl = extrapolateJobUrlFromBuildUrl(build.url.toASCIIString());
Option<JenkinsJobDto> jobDtoOption = dao.selectJobByUrl(jobUrl);
@@ -71,7 +94,7 @@ public class JenkinsServerActor implements TransactionalActor {
if (jobDtoOption.isSome()) {
job = jobDtoOption.some().uuid;
} else {
- logger.info("New job: " + jobUrl + ", fetching info");
+ logger.info("New job: {}, fetching info", jobUrl);
Option<JenkinsJobXml> jobXmlOption = client.fetchJob(apiXml(jobUrl));
@@ -83,7 +106,7 @@ public class JenkinsServerActor implements TransactionalActor {
job = dao.insertJob(server.uuid, xml.url, xml.type, xml.displayName);
- logger.info("New job: " + xml.displayName.orSome(xml.url.toASCIIString()) + ", uuid=" + job);
+ logger.info("New job: {}, uuid={}", xml.displayName.orSome(xml.url.toASCIIString()), job);
}
i++;
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerDto.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerDto.java
index 225b786..6ad8e36 100644
--- a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerDto.java
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsServerDto.java
@@ -1,35 +1,18 @@
package io.trygvis.esper.testing.jenkins;
+import io.trygvis.esper.testing.*;
import org.joda.time.*;
import java.net.*;
import java.util.*;
-public class JenkinsServerDto {
- public final UUID uuid;
- public final DateTime created_date;
+public class JenkinsServerDto extends AbstractDto {
public final URI url;
public final boolean enabled;
- JenkinsServerDto(UUID uuid, DateTime created_date, URI url, boolean enabled) {
- this.uuid = uuid;
- this.created_date = created_date;
+ JenkinsServerDto(UUID uuid, DateTime createdDate, URI url, boolean enabled) {
+ super(uuid, createdDate);
this.url = url;
this.enabled = enabled;
}
-
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- JenkinsServerDto that = (JenkinsServerDto) o;
-
- return uuid.equals(that.uuid);
- }
-
- @Override
- public int hashCode() {
- return uuid.hashCode();
- }
}
diff --git a/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsUserDto.java b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsUserDto.java
new file mode 100644
index 0000000..d3ea996
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/jenkins/JenkinsUserDto.java
@@ -0,0 +1,17 @@
+package io.trygvis.esper.testing.jenkins;
+
+import io.trygvis.esper.testing.*;
+import org.joda.time.*;
+
+import java.util.*;
+
+public class JenkinsUserDto extends AbstractDto {
+ public final UUID server;
+ public final String absoluteUrl;
+
+ public JenkinsUserDto(UUID uuid, DateTime createdDate, UUID server, String absoluteUrl) {
+ super(uuid, createdDate);
+ this.server = server;
+ this.absoluteUrl = absoluteUrl;
+ }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/sql/SqlF.java b/src/main/java/io/trygvis/esper/testing/sql/SqlF.java
new file mode 100644
index 0000000..fb05e4c
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/sql/SqlF.java
@@ -0,0 +1,15 @@
+package io.trygvis.esper.testing.sql;
+
+import java.sql.*;
+
+public abstract class SqlF<A, B> {
+ public abstract B apply(A a) throws SQLException;
+
+ public <C> SqlF<A, C> andThen(final SqlF<B, C> f) {
+ return new SqlF<A, C>() {
+ public C apply(A a) throws SQLException {
+ return f.apply(SqlF.this.apply(a));
+ }
+ };
+ }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/sql/SqlOption.java b/src/main/java/io/trygvis/esper/testing/sql/SqlOption.java
new file mode 100644
index 0000000..058435e
--- /dev/null
+++ b/src/main/java/io/trygvis/esper/testing/sql/SqlOption.java
@@ -0,0 +1,83 @@
+package io.trygvis.esper.testing.sql;
+
+import java.sql.*;
+
+public abstract class SqlOption<A> {
+ public static <A> SqlOption<A> none() {
+ return new None<>();
+ }
+
+ public static <A> SqlOption<A> some(A a) {
+ return new Some<>(a);
+ }
+
+ public static SqlOption<ResultSet> fromRs(ResultSet rs) throws SQLException {
+ if (!rs.next()) {
+ return none();
+ }
+
+ return some(rs);
+ }
+
+ // -----------------------------------------------------------------------
+ //
+ // -----------------------------------------------------------------------
+
+ public abstract <B> SqlOption<B> map(SqlF<A, B> f) throws SQLException;
+
+ public <B> SqlOption<B> flatMap(SqlF<A, SqlOption<B>> f) throws SQLException {
+ SqlOption<SqlOption<B>> x = map(f);
+
+ if (x.isNone()) {
+ return none();
+ }
+
+ return x.get();
+ }
+
+ public abstract A get() throws SQLException;
+
+ public abstract boolean isSome();
+
+ public boolean isNone() {
+ return !isSome();
+ }
+
+ // -----------------------------------------------------------------------
+ //
+ // -----------------------------------------------------------------------
+
+ private static class None<A> extends SqlOption<A> {
+ public <B> SqlOption<B> map(SqlF<A, B> f) {
+ return none();
+ }
+
+ public A get() throws SQLException {
+ throw new SQLException("get() on None");
+ }
+
+ public boolean isSome() {
+ return false;
+ }
+ }
+
+ private static class Some<A> extends SqlOption<A> {
+ private final A a;
+
+ private Some(A a) {
+ this.a = a;
+ }
+
+ public <B> SqlOption<B> map(SqlF<A, B> f) throws SQLException {
+ return some(f.apply(a));
+ }
+
+ public A get() {
+ return a;
+ }
+
+ public boolean isSome() {
+ return true;
+ }
+ }
+}
diff --git a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java b/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
index 24ed367..b9e997f 100644
--- a/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
+++ b/src/main/java/io/trygvis/esper/testing/web/JenkinsResource.java
@@ -60,7 +60,7 @@ public class JenkinsResource {
private JenkinsServerJson getJenkinsServerJson(Daos daos, JenkinsServerDto server) throws SQLException {
int count = daos.jenkinsDao.selectJobCountForServer(server.uuid);
- return new JenkinsServerJson(server.uuid, server.created_date, server.url, server.enabled, count);
+ return new JenkinsServerJson(server.uuid, server.createdDate, server.url, server.enabled, count);
}
private <T> T get(DatabaseAccess.DaosCallback<Option<T>> callback) throws SQLException {
diff --git a/src/main/resources/ddl-core.sql b/src/main/resources/ddl-core.sql
index 8201c31..fb85585 100644
--- a/src/main/resources/ddl-core.sql
+++ b/src/main/resources/ddl-core.sql
@@ -1,17 +1,37 @@
BEGIN;
-DROP TABLE IF EXISTS subscription_gitorious_repository;
-DROP TABLE IF EXISTS subscriber;
+CREATE TABLE table_poller_status (
+ poller_name VARCHAR(100) NOT NULL,
+ last_created_date TIMESTAMP,
+ last_run TIMESTAMP,
+ duration INT,
+ status VARCHAR(1000),
+ CONSTRAINT pk_job_status PRIMARY KEY (poller_name)
+);
+
+CREATE TABLE person (
+ uuid CHAR(36) NOT NULL,
+ created_date TIMESTAMP NOT NULL,
+--The users from the different jenkins servers this user has claimed
+ jenkins_users CHAR(36) [],
+ CONSTRAINT pk_person PRIMARY KEY (uuid)
+);
-CREATE TABLE subscriber (
- name VARCHAR(100) PRIMARY KEY
+-- Badges received
+CREATE TABLE person_badge (
+ uuid CHAR(36) NOT NULL,
+ created_date TIMESTAMP NOT NULL,
+ CONSTRAINT pk_person_badge PRIMARY KEY (uuid)
);
-CREATE TABLE subscription_gitorious_repository (
- subscriber_name VARCHAR(100) REFERENCES subscriber (name),
- gitorious_repository_project_slug VARCHAR(100),
- gitorious_repository_name VARCHAR(100),
- CONSTRAINT gitorious_repository FOREIGN KEY (gitorious_repository_project_slug, gitorious_repository_name) REFERENCES gitorious_repository (project_slug, name)
+-- Badges the person is working on
+CREATE TABLE person_badge_progress (
+ uuid CHAR(36) NOT NULL,
+ created_date TIMESTAMP NOT NULL,
+
+ name VARCHAR(100) NOT NULL,
+
+ CONSTRAINT pk_person_badge_progress PRIMARY KEY (uuid)
);
COMMIT;
diff --git a/src/main/resources/ddl-jenkins.sql b/src/main/resources/ddl-jenkins.sql
index 01275eb..65b3e35 100644
--- a/src/main/resources/ddl-jenkins.sql
+++ b/src/main/resources/ddl-jenkins.sql
@@ -46,6 +46,18 @@ CREATE TABLE jenkins_build (
CONSTRAINT uq_jenkins_build__id UNIQUE (entry_id)
);
+CREATE INDEX ix_jenkins_build__created_date ON jenkins_build (created_date);
+
+CREATE TABLE jenkins_user (
+ uuid CHAR(36) NOT NULL,
+ created_date TIMESTAMP NOT NULL,
+ server CHAR(36) NOT NULL,
+ absolute_url VARCHAR(1000) NOT NULL,
+ CONSTRAINT pk_jenkins_user PRIMARY KEY (uuid),
+ CONSTRAINT fk_jenkins_user__server FOREIGN KEY (server) REFERENCES jenkins_server (uuid),
+ CONSTRAINT uq_jenkins_user__absolute_url UNIQUE (absolute_url)
+);
+
INSERT INTO jenkins_server (uuid, created_date, url, enabled) VALUES
('782a75f6-40a4-11e2-aca6-20cf30557fa0', CURRENT_TIMESTAMP, 'https://builds.apache.org', FALSE),
('4c473c86-40ad-11e2-ae61-20cf30557fa0', CURRENT_TIMESTAMP, 'http://ci.jruby.org', FALSE),
diff --git a/src/main/webapp/apps/jenkinsApp/server.html b/src/main/webapp/apps/jenkinsApp/server.html
index 9213c73..9b27dfe 100644
--- a/src/main/webapp/apps/jenkinsApp/server.html
+++ b/src/main/webapp/apps/jenkinsApp/server.html
@@ -11,19 +11,15 @@
<tbody>
<tr>
<th>URL</th>
- <td>{{server.url}}</td>
+ <td><a href="{{server.url}}">{{server.url}}</a></td>
</tr>
<tr>
<th>Enabled</th>
<td>{{server.enabled}}</td>
</tr>
<tr>
- <th>Visit</th>
- <td><a href="{{server.url}}">{{server.url}}</a></td>
- </tr>
- <tr>
- <th>Job Count</th>
- <td>{{server.jobCount}}</td>
+ <th>Stats</th>
+ <td>{{server.jobCount}} jobs, {{server.buildCount}} builds</td>
</tr>
</tbody>
</table>
diff --git a/src/test/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXmlTest.java b/src/test/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXmlTest.java
index 46f89a1..4337758 100644
--- a/src/test/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXmlTest.java
+++ b/src/test/java/io/trygvis/esper/testing/jenkins/JenkinsBuildXmlTest.java
@@ -53,6 +53,9 @@ public class JenkinsBuildXmlTest extends TestCase {
assertItem(changeSet.items.get(5), "41b5de23dd2d7ccbc170252a43b8996316b93075", "No need to look up TZ here. In all cases leading up to here,", new DateTime(2012, 12, 6, 0, 5, 37, 0, minus5));
assertItem(changeSet.items.get(6), "def4c054ae82848c92b015a3267ace2c2cedd193", "Identify the correct JIRA ticket.", new DateTime(2012, 12, 6, 0, 8, 8, 0, minus5));
assertItem(changeSet.items.get(7), "82f12220d01c2c07398107fa5f5a2d50feb7c8c4", "As ugly as it might be, maintaining a map of exceptional time zone", new DateTime(2012, 12, 6, 0, 17, 26, 0, minus5));
+
+ assertTrue(changeSet.items.get(0).author.isSome());
+ assertEquals("http://ci.jruby.org/user/Charles%20Oliver%20Nutter", changeSet.items.get(0).author.some().absoluteUrl);
}
}