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
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
README.md
target/
.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
Expand Down
305 changes: 305 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,305 @@
# 🍳 MasterChef API

API REST para la gestión de recetas del programa **Máster Chef Celebrity**, desarrollada con **Spring Boot** y **MongoDB Atlas**.
Este proyecto forma parte de la fase inicial de desarrollo del portal web del programa, donde los televidentes podrán consultar, publicar y gestionar recetas.

---

# 📋 Descripción del Proyecto

La API permite registrar, consultar, actualizar y eliminar recetas de cocina creadas por:
- Participantes del programa.
- Chefs del jurado.
- Televidentes del público general.

Cada receta incluye:
- Título
- Lista de ingredientes
- Pasos de preparación
- Autor (con su tipo: participante, chef o televidente)
- Temporada (solo si pertenece a un participante del programa)

Además, el sistema expone endpoints para:
- Buscar recetas por ingrediente.
- Filtrar recetas según su tipo de autor.
- Consultar recetas por temporada o por número consecutivo.

---

# 🧱 Tecnologías utilizadas

- **Java 21**
- **Spring Boot 3.5.6**
- **MongoDB Atlas (NoSQL en la nube)**
- **Maven**
- **Swagger (Springdoc OpenAPI)** para documentación
- **JUnit 5** para pruebas unitarias
- **GitHub Actions** para CI/CD
- **Azure App Service** para despliegue

---

# ⚙️ Instrucciones de instalación y ejecución local

## 🔹 1. Crear proyecto en SpringBoot

![img.png](docs/imagenes/img.png)

Y ordenamos las carpetas de tal manera que quede como una arquitectura de capas donde vamos a segmentar las responsabilidades.

![img_1.png](docs/imagenes/img_1.png)

Luego empezamos a crear la lógica en cada carpeta para poder realizar las Apis donde:

**Repository:** manejará la conexión con MongoDB.

**Service:** contendrá la lógica de negocio (crear, actualizar, buscar, eliminar).

**Controller:** expondrá los endpoints REST y usará Swagger para documentarlos.

**Model:** las entidades de la base de datos.

## 🔹 2. Creamos la base de datos en MongoDB Atlas

Creamos la base de datos en Atlas ya que es accesible desde cualquier lado incluído azure, gratis, fácil de usar, se conecta con URI y es la mejor opción para el despliegue en azure + swagger.

![img_2.png](docs/imagenes/img_2.png)

Y ya por último ponemos la URL en el application.properties para terminar de configurarlo.

![img_3.png](docs/imagenes/img_3.png)

## 🔹 3. API con pruebas unitarias

Una vez ya tenemos las 12 funcionalidades, realizamos las 3 pruebas que nos piden y ejecutamos el comando mvn test.

![img_4.png](docs/imagenes/img_4.png)

## 🔹 3. Probamos los request y response por cada Endpoint

### POST /api/recetas/televidente

![img_8.png](docs/imagenes/img_8.png)

![img_9.png](docs/imagenes/img_9.png)

### POST /api/recetas/participante

![img_10.png](docs/imagenes/img_10.png)

![img_11.png](docs/imagenes/img_11.png)

### POST /api/recetas/chef

![img_12.png](docs/imagenes/img_12.png)

![img_13.png](docs/imagenes/img_13.png)

### GET /api/recetas

Lista de todas las recetas creadas anteriormente:

![img_14.png](docs/imagenes/img_14.png)

### GET /api/recetas/{id}

![img_15.png](docs/imagenes/img_15.png)

![img_16.png](docs/imagenes/img_16.png)

### GET /api/recetas/televidente

Solo recetas con tipoAutor: TELEVIDENTE

![img_17.png](docs/imagenes/img_17.png)

### GET /api/recetas/participante

Solo recetas con tipoAutor: PARTICIPANTE

![img_18.png](docs/imagenes/img_18.png)

### GET /api/recetas/chef

Solo recetas con tipoAutor: CHEF

![img_19.png](docs/imagenes/img_19.png)

### GET /api/recetas/temporada/{numero}

![img_20.png](docs/imagenes/img_20.png)

![img_21.png](docs/imagenes/img_21.png)

### GET /api/recetas/buscar/{nombre}

![img_22.png](docs/imagenes/img_22.png)

![img_23.png](docs/imagenes/img_23.png)

### DELETE /api/recetas/{id}

![img_24.png](docs/imagenes/img_24.png)

![img_25.png](docs/imagenes/img_25.png)

### PUT /api/recetas/{id}

![img_26.png](docs/imagenes/img_26.png)

![img_27.png](docs/imagenes/img_27.png)

Y con eso terminamos de probar las 12 funcionalidades de nuestra API en Swagger.


Y comprobamos si se guardó en la base de datos en MongoDB

![img_28.png](docs/imagenes/img_28.png)

## 🔹 4. CI/CD con GitHub Actions

Para garantizar la integración y despliegue continuo del proyecto, se configuraron **pipelines de CI/CD** utilizando **GitHub Actions**.
Este flujo permite automatizar la ejecución de pruebas y el despliegue automático en Azure App Service.

---

### Paso 1. Crear la estructura de GitHub Actions

Dentro del proyecto, se creó la siguiente ruta:

```
.github/
└── workflows/
├── ci.yml
└── deploy.yml
```

Esta carpeta le indica a GitHub que debe buscar en ella los archivos YAML que definen los **workflows** (automatizaciones) del repositorio.

---

### Paso 2. Configurar el workflow de Integración Continua (CI)

El archivo **`ci.yml`** se encarga de compilar el proyecto y ejecutar las pruebas unitarias cada vez que se hace un **push o pull request a la rama `develop`**.

```yaml
name: CI - MasterChef API

on:
push:
branches:
- develop
pull_request:
branches:
- develop

jobs:
build:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'

- name: Build with Maven
run: mvn clean install

- name: Run tests
run: mvn test
```

🔹 **Qué hace este pipeline:**
- Detecta cambios en la rama `develop`.
- Descarga el código del repositorio.
- Instala Java 21 (distribución Temurin).
- Compila el proyecto con Maven.
- Ejecuta todas las pruebas unitarias (`mvn test`).

✅ Si las pruebas pasan correctamente, GitHub mostrará el workflow en verde.
En caso de fallar, se marcará en rojo y se impedirá el merge a `main`.

---

### Paso 3. Configurar el workflow de Despliegue Continuo (CD)

El archivo **`deploy.yml`** se encarga de desplegar automáticamente la aplicación en **Azure App Service** cuando se hace **push a la rama `main`**.

```yaml
name: CD - Deploy to Azure App Service

on:
push:
branches:
- main

jobs:
deploy:
runs-on: ubuntu-latest

steps:
- name: Checkout repository
uses: actions/checkout@v3

- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'

- name: Login to Azure
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}

- name: Build with Maven
run: mvn clean package

- name: Deploy to Azure Web App
uses: azure/webapps-deploy@v2
with:
app-name: masterchef
slot-name: production
package: target/*.jar
```

🔹 **Qué hace este pipeline:**
- Se activa automáticamente con cualquier cambio en la rama `main`.
- Compila el proyecto (`mvn clean package`).
- Inicia sesión en Azure usando las credenciales almacenadas en `secrets.AZURE_CREDENTIALS`.
- Despliega el archivo `.jar` resultante en el servicio **Azure App Service** (`masterchef-api`).

---

### Paso 4. Crear el secreto de conexión con Azure

Para permitir que GitHub Actions se comunique con Azure, se generó un **secreto de autenticación**:

1. En el portal de Azure, se creó una credencial mediante **Azure CLI** o el botón *“Obtener credenciales de publicación”*.
2. En GitHub, se fue a:
`Settings → Secrets and variables → Actions → New repository secret`
3. Se creó un nuevo secreto llamado:
```
AZURE_CREDENTIALS
```
y se pegó allí el contenido JSON con las credenciales de Azure.

---

### Paso 5. Validar el flujo completo

- Al hacer un **push o pull request a `develop`**, se ejecuta el workflow **CI**, ejecutando pruebas automáticas.
- Al hacer un **push o merge a `main`**, se activa el **CD**, desplegando automáticamente la aplicación en Azure.
- Una vez finalizado el despliegue, la API queda disponible en la siguiente URL:

🔗 **https://masterchef-feaxhgdabggufyb9.westus3-01.azurewebsites.net/swagger-ui/index.html**

---

📄 **Resultado final:**
Con esta configuración, el proyecto cuenta con un flujo de **integración y despliegue continuo totalmente automatizado**, garantizando calidad en el código y actualizaciones instantáneas en el entorno de producción.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.5.6</version> <!-- usa una versión estable -->
<version>3.5.6</version>
<relativePath/>
</parent>

Expand Down
3 changes: 0 additions & 3 deletions src/main/java/com/masterchef/recetas/model/Receta.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
/**
* cd
*/
package com.masterchef.recetas.model;

import lombok.*;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ void setUp() {

@Test
void testRegistrarReceta() {
// Simula que Mongo guarda la receta correctamente
when(recetaRepository.save(any(Receta.class))).thenReturn(receta);

Receta guardada = recetaService.guardarReceta(receta);
Expand All @@ -57,7 +56,6 @@ void testRegistrarReceta() {

@Test
void testBuscarPorIngrediente() {
// Simula que en la base existen recetas con "Pollo"
when(recetaRepository.findAll()).thenReturn(List.of(receta));

List<Receta> resultados = recetaService.buscarPorIngrediente("Pollo");
Expand Down