Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM tomcat:8.5.50-jdk8-openjdk

ARG WAR_FILE
ARG CONTEXT

COPY ${WAR_FILE} /usr/local/tomcat/webapps/${CONTEXT}.war
91 changes: 91 additions & 0 deletions Jenkinsfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
pipeline{
agent any
stages{
stage('Build Backend'){
steps{
bat 'mvn clean package -DskipTests=true'
}
}
stage('Unit Tests'){
steps{
bat 'mvn test'
}
}
//stage('Sonar Analysis'){
// environment{
// scannerHome = tool 'SONAR_SCANNER'
// }
// steps{
// withSonarQubeEnv('SONAR_LOCAL')

// bat "${scannerHome}/bin/sonar-scanner -e -Dsonar.projectKey=DeployBack -Dsonar.host.url=http://localhost:9000 -Dsonar.login=cf6826d57f1e453e08ecbd6cf862472061f66 -Dsonar.java.binaries=target -Dsonar.coverage.exclusions=**/.mvn/**,**/src/test/**,**/model/**,**Application.java"
// }
//}
//stage('Quality Gate'){
// steps{
// sleep(20)
// timeout(time:1,unit:'MINUTES'){
// waitForQualityGate abortPipeline: true
//
// }
//}
stage('Deploy Backend'){
steps{
deploy adapters: [tomcat8(credentialsId: 'TomcatAdmin', path: '', url: 'http://localhost:8001')], contextPath: 'tasks-backend', war: 'target/tasks-backend.war'
}
}
stage('API Test'){
steps{
dir('api-test'){
git credentialsId: '23956211-31cd-44a1-80c5-5d627a0f1d03', url: 'https://github.com/HenriqueGalli/tasks-api-test'
bat 'mvn test'
}
}
}
stage('Deploy Frontend'){
steps{
dir('frontend'){
git credentialsId: '23956211-31cd-44a1-80c5-5d627a0f1d03', url: 'https://github.com/HenriqueGalli/tasks-frontend'
bat 'mvn clean package'
deploy adapters: [tomcat8(credentialsId: 'TomcatAdmin', path: '', url: 'http://localhost:8001')], contextPath: 'tasks', war: 'target/tasks.war'
}

}
}
stage('Functional Tests'){
steps{
dir('functional-test'){
git credentialsId: '23956211-31cd-44a1-80c5-5d627a0f1d03', url: 'https://github.com/HenriqueGalli/functional-test'
bat 'mvn test'
}
}
}
stage('Deploy prod'){
steps{
bat 'docker-compose build'
bat 'docker-compose up -d'
}
}
stage('Health Check'){
steps{
sleep(10)
dir('functional-test'){
bat 'mvn verify -Dskip.surefire.tests'
}
}
}
}
post{
always{
junit allowEmptyResults: true, testResults: 'target/surefire-reports/*.xml,api-test/target/surefire-reports/*.xml,functional-test/target/surefire-reports/*.xml,functional-test/target/failsafe-reports/*.xml'
archiveArtifacts artifacts: 'target/tasks-backend.war, frontend/target/tasks.war', onlyIfSuccessful:true
}
unsuccessful{
emailext attachLog: true, body: 'See the attached log', subject: 'Build Failed', to: '[email protected]'
}
fixed{
emailext attachLog: true, body: 'See the attached log below', subject: 'Build is fixed', to: '[email protected]'
}
}
}

62 changes: 62 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
version: "3"
services:
db:
container_name: pg-prod
image: postgres:9.6
networks:
- prod_net_back
environment:
- POSTGRES_PASSWORD=passwd
- POSTGRES_DB=tasks
volumes:
- prod_postgresql:/var/lib/postgresql
- prod_postgresql_data:/var/lib/postgresql/data

backend:
container_name: backend-prod
image: back_prod:build_${BUILD_NUMBER}
build:
context: .
args:
- WAR_FILE=target/tasks-backend.war
- CONTEXT=tasks-backend
networks:
- prod_net_back
- prod_net_front
#ports:
# - 9998:8080
environment:
- DATABASE_HOST=db
- DATABASE_PORT=5432
- DATABASE_USER=postgres
- DATABASE_PASSWD=passwd
- DATABASE_UPDATE=none
depends_on:
- db

frontend:
container_name: frontend-prod
image: front_prod:build_${BUILD_NUMBER}
build:
context: .
args:
- WAR_FILE=frontend/target/tasks.war
- CONTEXT=tasks
networks:
- prod_net_front
ports:
- 9999:8080
environment:
- BACKEND_HOST=backend
- BACKEND_PORT=8080
- APP_VERSION=build_${BUILD_NUMBER}
#depends_on:
# - backend

networks:
prod_net_front:
prod_net_back:

volumes:
prod_postgresql:
prod_postgresql_data:
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,18 @@

import java.util.List;

import javax.net.ssl.HttpsURLConnection;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestController;

import br.ce.wcaquino.taskbackend.model.Task;
Expand Down Expand Up @@ -42,4 +47,11 @@ public ResponseEntity<Task> save(@RequestBody Task todo) throws ValidationExcept
Task saved = todoRepo.save(todo);
return new ResponseEntity<Task>(saved, HttpStatus.CREATED);
}

@DeleteMapping(value = "/{id}")
@ResponseStatus(code=HttpStatus.NO_CONTENT)
public void delete(@PathVariable Long id) {
todoRepo.deleteById(id);
}

}
2 changes: 1 addition & 1 deletion src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ spring.datasource.hikari.connectionTimeout=20000
spring.datasource.hikari.maximumPoolSize=5

## PostgreSQL
spring.datasource.url=jdbc:postgresql://${DATABASE_HOST:127.0.0.1}:${DATABASE_PORT:5433}/tasks
spring.datasource.url=jdbc:postgresql://${DATABASE_HOST:192.168.99.100}:${DATABASE_PORT:5433}/tasks
spring.datasource.username=${DATABASE_USER:postgres}
spring.datasource.password=${DATABASE_PASSWD:password}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package br.ce.wcaquino.taskbackend.controller;

import java.time.LocalDate;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

import br.ce.wcaquino.taskbackend.model.Task;
import br.ce.wcaquino.taskbackend.repo.TaskRepo;
import br.ce.wcaquino.taskbackend.utils.ValidationException;

public class TaskControllerTest {

@Mock
private TaskRepo taskRepo;

@InjectMocks
private TaskController controller;

@Before
public void setup() {
MockitoAnnotations.initMocks(this);
}

@Test
public void naoDeveSalvarTarefaSemDescricao() {
Task todo = new Task();
todo.setDueDate(LocalDate.now());

try {
controller.save(todo);
Assert.fail("Nao deveria chegar nesse ponto");
} catch (ValidationException e) {
Assert.assertEquals("Fill the task description", e.getMessage());
}
}

@Test
public void naoDeveSalvarTarefaSemData() {
Task todo = new Task();
todo.setTask("Descricao");

try {
controller.save(todo);
Assert.fail("Nao deveria chegar nesse ponto");
} catch (ValidationException e) {
Assert.assertEquals("Fill the due date", e.getMessage());
}
}

@Test
public void naoDeveSalvarTarefaComDataPassada() {
Task todo = new Task();
todo.setTask("Descricao");
todo.setDueDate(LocalDate.of(2010,01,01));

try {
controller.save(todo);
Assert.fail("Nao deveria chegar nesse ponto");
} catch (ValidationException e) {
Assert.assertEquals("Due date must not be in past", e.getMessage());
}
}

@Test
public void deveSalvarTarefaComSucesso() throws ValidationException {
Task todo = new Task();
todo.setTask("Descricao");
todo.setDueDate(LocalDate.now());
controller.save(todo);

Mockito.verify(taskRepo).save(todo);

}
}
30 changes: 30 additions & 0 deletions src/test/java/br/ce/wcaquino/taskbackend/utils/DateUtilsTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package br.ce.wcaquino.taskbackend.utils;

import java.time.LocalDate;

import org.junit.Assert;
import org.junit.Test;

public class DateUtilsTest {

@Test
public void deveRetornarTrueParaDatasFuturas() {
LocalDate date = LocalDate.of(2030, 01, 01);
Assert.assertTrue(DateUtils.isEqualOrFutureDate(date));

}

@Test
public void deveRetornarFalseParaDatasPassadas() {
LocalDate date = LocalDate.of(2010, 01, 01);
Assert.assertFalse(DateUtils.isEqualOrFutureDate(date));

}

@Test
public void deveRetornarTrueParaDataAtual() {
LocalDate date = LocalDate.now();
Assert.assertTrue(DateUtils.isEqualOrFutureDate(date));

}
}