Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 7 additions & 4 deletions .github/workflows/gradle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '21'
java-version: '17'
distribution: 'temurin'

# Configure Gradle for optimal use in GitHub Actions, including caching of downloaded dependencies.
# See: https://github.com/gradle/actions/blob/main/setup-gradle/README.md
- name: Setup Gradle
uses: gradle/actions/setup-gradle@af1da67850ed9a4cedd57bfd976089dd991e2582 # v4.0.0

- name: Grant execute permission for gradlew
run: chmod +x ./gradlew

- name: Build with Gradle Wrapper
run: ./gradlew build
Expand All @@ -55,10 +58,10 @@ jobs:

steps:
- uses: actions/checkout@v4
- name: Set up JDK 21
- name: Set up JDK 17
uses: actions/setup-java@v4
with:
java-version: '21'
java-version: '17'
distribution: 'temurin'

# Generates and submits a dependency graph, enabling Dependabot Alerts for all project dependencies.
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,7 @@ migrations/
Challenge Backend..pdf

data/

PR_DESCRIPTION.md

PULL_REQUEST.md
21 changes: 15 additions & 6 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,31 +1,40 @@
# Use a base image with a JDK (Java Development Kit)
FROM openjdk:21-jdk-slim AS build
FROM openjdk:17-jdk-slim AS build

# Set the working directory in the container
WORKDIR /app

COPY build.gradle settings.gradle gradlew /app/
COPY gradle /app/gradle

# Fix line ending issues with gradlew (convert CRLF to LF)
RUN apt-get update && apt-get install -y dos2unix && dos2unix ./gradlew && chmod +x ./gradlew
RUN ./gradlew build || return 0

# Copy the source code of your Spring Boot application into the container
COPY . /app

# Fix line endings again for the copied files
RUN find . -type f -name "*.sh" -o -name "gradlew" | xargs dos2unix
RUN chmod +x ./gradlew

# Build the Spring Boot application inside the container
RUN ./gradlew build -x test
RUN ./gradlew bootJar -x test

# Verify the JAR file was created and find its location
RUN find /app/build -name "*.jar" | sort

# Use a base image with a JRE (Java Runtime Environment)
FROM openjdk:21-jdk-slim
FROM openjdk:17-jdk-slim

# Set the working directory in the container
WORKDIR /app

# Copy the compiled Spring Boot JAR file into the container from the build stage
COPY --from=build /app/build/libs/split-travel-0.0.1-SNAPSHOT.jar /app/split-travel-application.jar

COPY --from=build /app/build/libs/twitter-challenge-espenia-0.0.1-SNAPSHOT.jar /app/application.jar

# Expose the port your Spring Boot application is running on (default is 8080)
EXPOSE 8080

# Command to run your Spring Boot application
CMD ["java", "-jar", "/app/split-travel-application.jar"]
CMD ["java", "-jar", "/app/application.jar"]
141 changes: 141 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ Repositorio para el BackEnd de la plataforma challange twitter "Challange Twitte

* [Integrantes](#integrantes)

* [Arquitectura](#arquitectura)

* [Docker](#docker)

* [Dependencias](#dependencias)

* [Wiki](#wiki)
Expand All @@ -28,11 +32,105 @@ Repositorio para el BackEnd de la plataforma challange twitter "Challange Twitte

<hr width="30%" align="left" />

# Arquitectura

El proyecto sigue una arquitectura de Clean Architecture con separación clara de responsabilidades:

## Capas de la Aplicación

1. **Entrypoint (Controllers)**: Maneja las solicitudes HTTP y respuestas.
- Ubicación: `src/main/java/twitter/challenge/espenia/entrypoint/`
- Componentes: `UserController`, `TweetController`

2. **Core (Dominio)**: Contiene la lógica de negocio y modelos de dominio.
- Ubicación: `src/main/java/twitter/challenge/espenia/core/`
- Subdirectorios principales:
- `domain`: Entidades principales (`User`, `Tweet`)
- `usecase`: Servicios y lógica de negocio
- `gateway`: Interfaces para acceso a datos
- `exception`: Excepciones de dominio

3. **Infraestructura**: Implementa mecanismos de persistencia y servicios externos.
- Ubicación: `src/main/java/twitter/challenge/espenia/infra/`
- Componentes:
- `mongodb`: Configuración y documentos de MongoDB
- `gateway`: Implementaciones de las interfaces del gateway

## Flujo de Datos

1. Las peticiones HTTP llegan a los controladores en la capa Entrypoint
2. Los controladores delegan en casos de uso (Core)
3. Los casos de uso utilizan gateways para acceder a los datos
4. La capa de infraestructura implementa estos gateways para interactuar con MongoDB

<hr width="30%" align="left" />

# Docker

El proyecto incluye configuración para despliegue con Docker, facilitando su ejecución en cualquier entorno.

## Requisitos Previos

- Docker
- Docker Compose

## Configuración

### Dockerfile

El proyecto utiliza un enfoque de construcción multi-etapa:

1. **Etapa de construcción**: Compila la aplicación usando JDK 17
2. **Etapa de ejecución**: Ejecuta la aplicación con una imagen liviana

### Docker Compose

El archivo `docker-compose.yml` configura:

- **Servicio principal**: La aplicación Spring Boot
- **MongoDB**: Base de datos NoSQL para almacenamiento
- **Servicio de inicialización**: Configura usuarios y colecciones en MongoDB

## Uso

Para iniciar la aplicación con Docker:

```bash
docker-compose up -d
```

Para detener la aplicación:

```bash
docker-compose down
```

Para ver los logs:

```bash
docker-compose logs -f
```

## Variables de Entorno

El servicio principal utiliza las siguientes variables de entorno que pueden ser modificadas según necesidad:

- `SCOPE_SUFFIX`: Perfil activo (por defecto: `prod`)
- `MONGODB_URI`: URI de conexión a MongoDB
- `MONGODB_DATABASE`: Nombre de la base de datos
- `SERVER_PORT`: Puerto de la aplicación (por defecto: 8090)

<hr width="30%" align="left" />

# Dependencias

| <center>Dependencia</center> | <center>Versión</center> | <center>Descripción</center> |
|:------------------------------------------------------------------|:------------------------:|:------------------------------------------------------------------------------------:|
| [Spring Boot](https://spring.io/projects/spring-boot) | 3.3.5 | La librería base sobre la que se construyen interacciones con el server del BackEnd. |
| [MongoDB](https://www.mongodb.com/) | Latest | Base de datos NoSQL para almacenamiento de usuarios y tweets. |
| [MapStruct](https://mapstruct.org/) | 1.6.3 | Framework para mapeo de objetos entre capas de dominio y persistencia. |
| [Lombok](https://projectlombok.org/) | 1.18.30 | Reduce el código repetitivo mediante anotaciones. |
| [Spring Validation](https://spring.io/guides/gs/validating-form-input/) | 3.3.5 | Validación de datos en los requests. |

<hr width="30%" align="left" />

Expand All @@ -42,6 +140,22 @@ Si bien la documentación del [código fuente](./CONTRIBUTING.md#código-fuente)
el uso de los _end points_ para interactuar con el FrontEnd viene mejor explicado en la
[wiki](https://github.com/espenia/split-travel-be/wiki) del proyecto.

## API Endpoints

### Usuarios

- **GET /api/users/{id}**: Obtiene un usuario por ID
- **GET /api/users/username/{username}**: Obtiene un usuario por nombre de usuario
- **POST /api/users**: Crea un nuevo usuario
- **PATCH /api/users/{id}**: Actualiza un usuario existente
- **DELETE /api/users/{id}**: Elimina un usuario

### Tweets

- **POST /api/tweets**: Crea un nuevo tweet

La documentación completa de la API está disponible en formato Swagger en `docs/specs/swagger.yaml`.

<hr width="30%" align="left" />

# Convenciones
Expand All @@ -51,3 +165,30 @@ Las convenciones utilizadas en el proyecto, como las utilizadas para el
[*pull requests*](./CONTRIBUTING.md#pull-requests) o la formación de
[*issues*](./CONTRIBUTING.md#issues) se encuentran en el [archivo](./CONTRIBUTING.md)
correspondiente.

<hr width="30%" align="left" />

# CI/CD

El proyecto utiliza GitHub Actions para integración continua.

## Workflow de CI

El flujo de trabajo de CI está definido en `.github/workflows/gradle.yml` y se ejecuta automáticamente en:
- Push a la rama `main`
- Pull Requests dirigidas a `main`

### Etapas del Pipeline

1. **Checkout**: Obtiene el código fuente
2. **Setup JDK**: Configura Java 17
3. **Setup Gradle**: Configura Gradle con caché para dependencias
4. **Build**: Compila y ejecuta pruebas

### Ejecución Local

Para ejecutar el build localmente antes de hacer push:

```bash
./gradlew build
```
8 changes: 7 additions & 1 deletion build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ dependencies {
implementation("com.newrelic.agent.java:newrelic-api:$newRelicVersion")
implementation("commons-io:commons-io:$commonsIoVersion")
implementation("jakarta.servlet:jakarta.servlet-api:$jakartaServletApiVersion")
implementation("javax.xml.bind:jaxb-api:$jaxbApiVersion")
implementation("javax.xml.bind:jaxb-api:$jaxbApiVersion")
implementation("org.hibernate.validator:hibernate-validator:8.0.0.Final")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.springframework.boot:spring-boot-starter-data-mongodb")
implementation("org.springframework.boot:spring-boot-starter-jetty")
Expand Down Expand Up @@ -82,3 +83,8 @@ jar {
}
}

bootJar {
archiveBaseName = 'twitter-challenge-espenia'
archiveVersion = '0.0.1-SNAPSHOT'
}

1 change: 1 addition & 0 deletions business.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
to accelerate development i used a local mongo database, in memory needs to be researched
52 changes: 52 additions & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
version: '3.8'

services:
twitter-challenge:
build:
context: . # Use the current directory as the build context
dockerfile: Dockerfile # Use the existing Dockerfile
ports:
- "8090:8090" # Map container port 8090 to host port 8090

environment:
- SCOPE_SUFFIX=prod # Set the active profile to local
- MONGODB_URI=mongodb://mongodb
- MONGODB_DATABASE=challenge-twitter
- MONGODB_USERNAME=user
- MONGODB_PASSWORD=user
- MONGODB_PORT=27017
- SERVER_PORT=8090
restart: unless-stopped
container_name: twitter-challenge-app
volumes:
- ./data:/app/data # Mount the data directory for persistence if needed
depends_on:
- mongo-init

mongodb:
image: mongo:latest
container_name: mongodb
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db # Persist MongoDB data
environment:
- MONGO_INITDB_ROOT_USERNAME=root
- MONGO_INITDB_ROOT_PASSWORD=rootpassword
- MONGO_INITDB_DATABASE=challenge-twitter
restart: unless-stopped
command: mongod --auth

mongo-init:
image: mongo:latest
depends_on:
- mongodb
restart: on-failure
command: >
bash -c "sleep 10 && mongosh --host mongodb -u root -p rootpassword --authenticationDatabase admin --eval '
db = db.getSiblingDB(\"challenge-twitter\");
db.createUser({user: \"user\", pwd: \"user\", roles: [{role: \"readWrite\", db: \"challenge-twitter\"}]});
'"

volumes:
mongodb_data: # Named volume for MongoDB data persistence
Loading
Loading