Skip to content
This repository has been archived by the owner on Jun 10, 2023. It is now read-only.

F. Scippacercola e E. Battista #2

Open
wants to merge 9 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
13 changes: 13 additions & 0 deletions Dockerfile
@@ -0,0 +1,13 @@
FROM java:8-jdk

ENV JAVA_HOME /usr/lib/jvm/java-8-openjdk-amd64
#ENV GITLAB_OAUTH_TOKEN _YOUR_OAUTH_TOKEN_

RUN mkdir -p /task/bin /task/jre
ADD jre/. /task/jre/

RUN chmod 777 /task/jre/microservice.jar

EXPOSE 19800
WORKDIR /task/jre/
ENTRYPOINT ["/bin/bash", "-c", "java -jar microservice.jar"]
34 changes: 34 additions & 0 deletions Makefile
@@ -0,0 +1,34 @@
NAME = anpr-github-metrics/baseimage
VERSION = 1.0
CONTAINER_NAME = anpr-github-metrics
FRONTEND_CONTAINER_NAME = frontend-github-metrics
BASE_PATH_FRONTEND = $(shell pwd)/frontend

.PHONY: all build test tag_latest release ssh

all: build

build:
echo Remember to configure "mvn" in your '$PATH' and '$JAVA_HOME'
mvn -f backend/pom.xml clean install
mkdir -p docker/jre && cp Dockerfile ./docker/. && cp -R ./backend/target/output/* docker/jre/.
docker build -t $(NAME):$(VERSION) docker

start:
-docker rm -f $(CONTAINER_NAME)
docker run -p 19800:19800 --name $(CONTAINER_NAME) -d --restart always $(NAME):$(VERSION)

start-frontend:
-docker rm -f $(FRONTEND_CONTAINER_NAME)
docker run --name $(FRONTEND_CONTAINER_NAME) --rm -v $(BASE_PATH_FRONTEND):/src -w /src -p 8080:8080 node:6 bash -c "npm install && npm run dev"

tag_latest:
docker tag $(NAME):$(VERSION) $(NAME):latest

release: test tag_latest
@if ! docker images $(NAME) | awk '{ print $$2 }' | grep -q -F $(VERSION); then echo "$(NAME) version $(VERSION) is not yet built. Please run 'make build'"; false; fi
docker push $(NAME)
@echo "*** Don't forget to create a tag by creating an official GitHub release."

test:
mvn -f backend/pom.xml test
85 changes: 85 additions & 0 deletions README.md
@@ -0,0 +1,85 @@
# Anpr-github-metrics

A microserver and a client-side application that computes and shows metrics of Issue Trackers.

# Description

Anpr-github-metrics is a **JS client-side application** that shows metrics on Issue Trackers, using a **processing microservice** in the backed.
- **GUI Extensibility** The JS application is based on *Vue* and is easily extensible for adding new plots and reports to the users.
- **Virtualized environment** The application communicates with a backend microservice (*Dockerized on-the-go*), to guarantee a stable and easy-to-set environment.
- **Standard communication** The communication uses a standard **REST interface** based on **Swagger** ([See Swagger YAML Specification](https://github.com/F-Scippacercola/anpr-github-metrics/blob/master/swagger-api.yml)), to allow the system maintanability.
- **Powerful frameworks** The microservice runs in a **Java SE Virtual Machine** (it is not required a Java EE!) and exploites the services of **Spring** and **Spring Boot**.
- **Maintainability and Extensibility** The microservice adopts a **compile-time plugin architecture**:
1. Currently implements analysis on *GitHub*, but can be extended to other issue tracker (e.g. BugZilla) in moments!.
2. New plugins for computing new metrics can be easily added at compile-time and registered to the microservice.
- **Designed with performance in mind** The microservice uses a **high-concurrent local time-cache** (by using **Google Guava _Cache_ and _Striped Locks_**) to improve the LRU queries. _The caching is completely transparent to the plugins!_ ([See how transparent caching has been implemented](https://github.com/F-Scippacercola/anpr-github-metrics/blob/master/backend/src/main/java/systems/fervento/gitlabissueanalyzer/issuefetcher/CachedIssueFetcher.java))
- **Testability by design** The application exploits strategies and design pattern to improve testability (unit and integration) preferring **Inversion Of Control**, **Builders**, **Fluent APIs**, and :_over all_: **Readable code!**.

![Screenshot 1](https://raw.githubusercontent.com/F-Scippacercola/anpr-github-metrics/master/screenshot1.png)

## Currently Implemented Plugins

The plugin architecture allows to easily add new Issue Trackers and Metrics.
- Currentely implemented Issue Tracker:
* **GitHub**
- Currently implemented Metric Plugins:
1. **TicketGeneral** Computes the total numbers of open and closed tickets of a repository.
2. **IssuesClosedWithoutComments** Retrieves all issues closed without comments.
3. **TicketClosingTime** Finds the average time of a ticket resolution, providing the **time resolution histogram**.
4. **FirstReplyTime** Computes the average time of a first comment to a new issue, providing the **time histogram**.
5. **IssuesCommentedBy** Finds all the issues (open/closed/all) commented (or not commented) by a set of users.
5. **IssuesWithLabels** Finds all the issues (open/closed/all) with (or without) a set of labels.

### Prerequisites

You need to have installed on your computer:
1. Docker
2. Build-tools (maven/make)

### Installing

Download the project, open the console and _cd_ into the project folder. Then, follow these steps:
1. [Optional] decomment (removing #) and set your `GITLAB_OAUTH_TOKEN` in the Dockerfile
2. Compile, build microservice, and start docker instance with the command:

```
make build start
```
3. To run the frontend in the same host run also:
```
make start-frontend
```

_Goto_ http://localhost:8080 and you are on the go! ;-)

## Running the tests

To run the test just call

```
make test
```

## Deployment

By default the service runs on docker on your local machine. Modify the `Makefile` to change the environment.

## Built With

* [Swagger](https://swagger.io/) - The world's most popular API Tooling
* [Docker](https://www.docker.com/) - Docker is the world’s leading software container platform
* [Spring](https://projects.spring.io/spring-framework/) - Spring Framework
* [Google Guava](https://github.com/google/guava) - Google Core Libraries for Java
* [Maven](https://maven.apache.org/) - Dependency Management
* [Vue](https://vuejs.org/) - The Progressive JavaScript Framework
* [Bootstrap 4](https://v4-alpha.getbootstrap.com/) - Bootstrap The most popular HTML, CSS, and JS framework

## Authors

**Ermanno Battista** (ermanno.battista@gmail.com) and **Fabio Scippacercola** (f.scippacercola@gmail.com) - Software Engineers and PhDs. Working in [IVM Tech](http://ivmtech.it/) and starting [Fervento.systems](http://fervento.systems).

## Acknowledgments

* This code was developed in the 28-hour of the [Developers Italia Hackathon](https://developers.italia.it) held on the 7-8th October, 2017.

![Screenshot 2](https://raw.githubusercontent.com/F-Scippacercola/anpr-github-metrics/master/screenshot2.png)
Binary file added backend/.DS_Store
Binary file not shown.
23 changes: 23 additions & 0 deletions backend/nbactions.xml
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<actions>
<action>
<actionName>build</actionName>
<packagings>
<packaging>*</packaging>
</packagings>
<goals>
<goal>install</goal>
</goals>
</action>
<action>
<actionName>rebuild</actionName>
<packagings>
<packaging>*</packaging>
</packagings>
<goals>
<goal>clean</goal>
<goal>install</goal>

</goals>
</action>
</actions>
Empty file.
152 changes: 152 additions & 0 deletions backend/pom.xml
@@ -0,0 +1,152 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>io.swagger</groupId>
<artifactId>swagger-spring</artifactId>
<packaging>jar</packaging>
<name>swagger-spring</name>
<version>1.0.0</version>
<properties>
<java.version>1.8</java.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<springfox-version>2.7.0</springfox-version>
<org.eclipse.egit.github.core.version>2.1.5</org.eclipse.egit.github.core.version>
<weka-stable.version>3.8.1</weka-stable.version>
<guava.version>23.0</guava.version>
<guava.version>23.0</guava.version>
<commons-math3.version>3.2</commons-math3.version>
<spring-test.version>5.0.0</spring-test.version>
<spring-boot-starter-test.version>1.5.6.RELEASE</spring-boot-starter-test.version>
</properties>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.7.RELEASE</version>
</parent>
<build>
<sourceDirectory>src/main/java</sourceDirectory>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>lib/</classpathPrefix>
<mainClass>io.swagger.Swagger2SpringBoot</mainClass>
</manifest>
</archive>
<outputDirectory>${project.build.directory}/output/</outputDirectory>
<finalName>microservice</finalName>
</configuration>
</plugin>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<phase>install</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/output/lib</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>${spring-boot-starter-test.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-math3</artifactId>
<version>${commons-math3.version}</version>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>org.eclipse.mylyn.github</groupId>
<artifactId>org.eclipse.egit.github.core</artifactId>
<version>${org.eclipse.egit.github.core.version}</version>
</dependency>
<dependency>
<groupId>nz.ac.waikato.cms.weka</groupId>
<artifactId>weka-stable</artifactId>
<version>${weka-stable.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
</dependency>
<!--SpringFox dependencies -->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>${springfox-version}</version>
</dependency>

<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-joda</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<!-- Bean Validation API support -->
<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
<version>1.1.0.Final</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-core</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Binary file added backend/src/main/.DS_Store
Binary file not shown.
Binary file added backend/src/main/java/.DS_Store
Binary file not shown.
Binary file added backend/src/main/java/io/.DS_Store
Binary file not shown.
Binary file added backend/src/main/java/io/swagger/.DS_Store
Binary file not shown.
20 changes: 20 additions & 0 deletions backend/src/main/java/io/swagger/RFC3339DateFormat.java
@@ -0,0 +1,20 @@
package io.swagger;

import com.fasterxml.jackson.databind.util.ISO8601DateFormat;
import com.fasterxml.jackson.databind.util.ISO8601Utils;

import java.text.FieldPosition;
import java.util.Date;


public class RFC3339DateFormat extends ISO8601DateFormat {

// Same as ISO8601DateFormat but serializing milliseconds.
@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
String value = ISO8601Utils.format(date, true);
toAppendTo.append(value);
return toAppendTo;
}

}
36 changes: 36 additions & 0 deletions backend/src/main/java/io/swagger/Swagger2SpringBoot.java
@@ -0,0 +1,36 @@
package io.swagger;

import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.ExitCodeGenerator;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ComponentScan;

import springfox.documentation.swagger2.annotations.EnableSwagger2;

@SpringBootApplication
@EnableSwagger2
@ComponentScan(basePackages = { "io.swagger", "io.swagger.api" })
public class Swagger2SpringBoot implements CommandLineRunner {

@Override
public void run(String... arg0) throws Exception {
if (arg0.length > 0 && arg0[0].equals("exitcode")) {
throw new ExitException();
}
}

public static void main(String[] args) throws Exception {
new SpringApplication(Swagger2SpringBoot.class).run(args);
}

class ExitException extends RuntimeException implements ExitCodeGenerator {
private static final long serialVersionUID = 1L;

@Override
public int getExitCode() {
return 10;
}

}
}