Merge pull request 'bugfix/main-13-UpdateConfigurations' (#17) from bugfix/main-13-UpdateConfigurations into main
Reviewed-on: https://openbokeron.uma.es/gitea/OpenBokeron/TallerCiCd/pulls/17
This commit was merged in pull request #17.
This commit is contained in:
7
.env.example
Normal file
7
.env.example
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
BACKEND_TAG=latest
|
||||||
|
FRONTEND_TAG=latest
|
||||||
|
VITE_API_BASE=/taller/api
|
||||||
|
JENKINS_BASE_URL=http://host.docker.internal:8080
|
||||||
|
JENKINS_JOB_NAME=TallerCiCd
|
||||||
|
JENKINS_USER=
|
||||||
|
JENKINS_TOKEN=
|
||||||
@@ -2,13 +2,36 @@ pipeline {
|
|||||||
agent none
|
agent none
|
||||||
|
|
||||||
options {
|
options {
|
||||||
|
disableConcurrentBuilds()
|
||||||
timestamps()
|
timestamps()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parameters {
|
||||||
|
string(
|
||||||
|
name: 'JENKINS_BASE_URL',
|
||||||
|
defaultValue: 'https://openbokeron.org/jenkins',
|
||||||
|
description: 'Base URL del Jenkins objetivo'
|
||||||
|
)
|
||||||
|
string(
|
||||||
|
name: 'JENKINS_JOB_NAME',
|
||||||
|
defaultValue: 'CD',
|
||||||
|
description: 'Nombre del job que se consulta en Jenkins'
|
||||||
|
)
|
||||||
|
string(
|
||||||
|
name: 'VITE_API_BASE',
|
||||||
|
defaultValue: '/taller/api',
|
||||||
|
description: 'Base path/API para el frontend (build time)'
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
environment {
|
environment {
|
||||||
NODE_OPTIONS = '--max_old_space_size=2048'
|
NODE_OPTIONS = '--max_old_space_size=2048'
|
||||||
APP_VERSION = "1.0.${BUILD_NUMBER}"
|
APP_VERSION = "1.0.${BUILD_NUMBER}"
|
||||||
DOCKER_BUILDKIT = '1'
|
DOCKER_BUILDKIT = '1'
|
||||||
|
JENKINS_BASE_URL = "${params.JENKINS_BASE_URL}"
|
||||||
|
JENKINS_JOB_NAME = "${params.JENKINS_JOB_NAME}"
|
||||||
|
VITE_API_BASE = "${params.VITE_API_BASE}"
|
||||||
|
PYTHONDONTWRITEBYTECODE = 1
|
||||||
}
|
}
|
||||||
|
|
||||||
stages {
|
stages {
|
||||||
@@ -18,9 +41,6 @@ pipeline {
|
|||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
stage('Backend: test (main)') {
|
stage('Backend: test (main)') {
|
||||||
when {
|
|
||||||
branch 'main'
|
|
||||||
}
|
|
||||||
agent {
|
agent {
|
||||||
docker {
|
docker {
|
||||||
image 'python:3.11-slim'
|
image 'python:3.11-slim'
|
||||||
@@ -47,9 +67,6 @@ pipeline {
|
|||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
stage('Docker: build images') {
|
stage('Docker: build images') {
|
||||||
when {
|
|
||||||
branch 'main'
|
|
||||||
}
|
|
||||||
agent any
|
agent any
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
@@ -72,13 +89,12 @@ pipeline {
|
|||||||
--build-arg GIT_COMMIT=${COMMIT_SHORT} \
|
--build-arg GIT_COMMIT=${COMMIT_SHORT} \
|
||||||
--build-arg COMMIT_AUTHOR="${COMMIT_AUTHOR}" \
|
--build-arg COMMIT_AUTHOR="${COMMIT_AUTHOR}" \
|
||||||
--build-arg BUILD_NUMBER=${BUILD_NUMBER} \
|
--build-arg BUILD_NUMBER=${BUILD_NUMBER} \
|
||||||
-t cafeteria-backend:${BUILD_NUMBER} \
|
-t cafeteria-backend:${APP_VERSION} \
|
||||||
-t cafeteria-backend:latest \
|
|
||||||
./backend
|
./backend
|
||||||
|
|
||||||
docker build \
|
docker build \
|
||||||
-t cafeteria-frontend:${BUILD_NUMBER} \
|
--build-arg VITE_API_BASE=${VITE_API_BASE} \
|
||||||
-t cafeteria-frontend:latest \
|
-t cafeteria-frontend:${APP_VERSION} \
|
||||||
./frontend
|
./frontend
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
@@ -89,14 +105,7 @@ pipeline {
|
|||||||
========================= */
|
========================= */
|
||||||
|
|
||||||
stage('Deploy (docker compose)') {
|
stage('Deploy (docker compose)') {
|
||||||
when {
|
|
||||||
branch 'main'
|
|
||||||
}
|
|
||||||
agent any
|
agent any
|
||||||
environment {
|
|
||||||
JENKINS_BASE_URL = 'http://jenkins:8080'
|
|
||||||
JENKINS_JOB_NAME = 'Espetos'
|
|
||||||
}
|
|
||||||
steps {
|
steps {
|
||||||
withCredentials([
|
withCredentials([
|
||||||
usernamePassword(
|
usernamePassword(
|
||||||
@@ -108,17 +117,16 @@ pipeline {
|
|||||||
sh '''
|
sh '''
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
echo "Deploying backend ${BUILD_NUMBER}"
|
echo "Deploying ${APP_VERSION}"
|
||||||
|
|
||||||
echo "BACKEND_TAG=${BUILD_NUMBER}" > .env
|
BACKEND_TAG=${APP_VERSION} FRONTEND_TAG=${APP_VERSION} docker compose up -d
|
||||||
echo "FRONTEND_TAG=${BUILD_NUMBER}" >> .env
|
|
||||||
|
|
||||||
docker-compose up -d
|
|
||||||
'''
|
'''
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stage('Cleanup') {
|
stage('Cleanup') {
|
||||||
agent any
|
agent any
|
||||||
steps {
|
steps {
|
||||||
|
|||||||
@@ -41,6 +41,11 @@ pipeline {
|
|||||||
args '-u root'
|
args '-u root'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
environment {
|
||||||
|
PYTHONDONTWRITEBYTECODE = 1
|
||||||
|
}
|
||||||
|
|
||||||
steps {
|
steps {
|
||||||
dir('backend') {
|
dir('backend') {
|
||||||
sh '''
|
sh '''
|
||||||
|
|||||||
11
README.md
11
README.md
@@ -7,6 +7,16 @@
|
|||||||
- Python 3.11+ y `pip`
|
- Python 3.11+ y `pip`
|
||||||
- Node 18+ y `npm`
|
- Node 18+ y `npm`
|
||||||
|
|
||||||
|
## Configuracion de entorno (local/prod)
|
||||||
|
Variables que usa `docker-compose` y el frontend:
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
Notas:
|
||||||
|
- `VITE_API_BASE` por defecto apunta a `/taller/api` y el frontend proxya a la API.
|
||||||
|
- Para Jenkins local en contenedor: `JENKINS_BASE_URL=http://jenkins:8080`. Se hace necesario que back y jenkins estén en la misma red de Docker si se quiere probar en local.
|
||||||
|
- Para VPS: `JENKINS_BASE_URL=https://openbokeron.org/jenkins`.
|
||||||
|
|
||||||
## Backend (FastAPI)
|
## Backend (FastAPI)
|
||||||
```bash
|
```bash
|
||||||
cd backend
|
cd backend
|
||||||
@@ -42,6 +52,7 @@ cd frontend
|
|||||||
npm install
|
npm install
|
||||||
npm run dev -- --host --port 5173
|
npm run dev -- --host --port 5173
|
||||||
```
|
```
|
||||||
|
Abrir `http://localhost:5173/taller/`.
|
||||||
Tests, lint/check:
|
Tests, lint/check:
|
||||||
```bash
|
```bash
|
||||||
cd frontend
|
cd frontend
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM python:3.11-slim AS builder
|
FROM docker.io/library/python:3.11-slim AS builder
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
|
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
@@ -9,7 +9,7 @@ COPY requirements.txt .
|
|||||||
RUN pip wheel --no-cache-dir --no-deps -r requirements.txt -w /build/wheels
|
RUN pip wheel --no-cache-dir --no-deps -r requirements.txt -w /build/wheels
|
||||||
|
|
||||||
|
|
||||||
FROM python:3.11-slim
|
FROM docker.io/library/python:3.11-slim
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
# ---- Build args (desde Jenkins) ----
|
# ---- Build args (desde Jenkins) ----
|
||||||
|
|||||||
@@ -24,7 +24,10 @@ class RuntimeConfig:
|
|||||||
git_commit: str = os.getenv("GIT_COMMIT", "local")
|
git_commit: str = os.getenv("GIT_COMMIT", "local")
|
||||||
build_number: str = os.getenv("BUILD_NUMBER", "-")
|
build_number: str = os.getenv("BUILD_NUMBER", "-")
|
||||||
commit_author: str = os.getenv("COMMIT_AUTHOR", "local")
|
commit_author: str = os.getenv("COMMIT_AUTHOR", "local")
|
||||||
jenkins_base_url: str = os.getenv("JENKINS_BASE_URL", "localhost:8080")
|
jenkins_base_url: str = os.getenv(
|
||||||
|
"JENKINS_BASE_URL",
|
||||||
|
"http://localhost:8080"
|
||||||
|
).rstrip("/")
|
||||||
jenkins_job_name: str = os.getenv("JENKINS_JOB_NAME", "")
|
jenkins_job_name: str = os.getenv("JENKINS_JOB_NAME", "")
|
||||||
jenkins_user: str = os.getenv("JENKINS_USER", "")
|
jenkins_user: str = os.getenv("JENKINS_USER", "")
|
||||||
jenkins_token: str = os.getenv("JENKINS_TOKEN", "")
|
jenkins_token: str = os.getenv("JENKINS_TOKEN", "")
|
||||||
|
|||||||
@@ -2,14 +2,16 @@ services:
|
|||||||
backend:
|
backend:
|
||||||
build:
|
build:
|
||||||
context: ./backend
|
context: ./backend
|
||||||
image: cafeteria-backend:${BACKEND_TAG}
|
image: cafeteria-backend:${BACKEND_TAG:-latest}
|
||||||
|
networks:
|
||||||
|
- cafeteria
|
||||||
ports:
|
ports:
|
||||||
- "8000:8000"
|
- "8000:8000"
|
||||||
environment:
|
environment:
|
||||||
JENKINS_BASE_URL: ${JENKINS_BASE_URL}
|
JENKINS_BASE_URL: ${JENKINS_BASE_URL:-http://jenkins:8080}
|
||||||
JENKINS_JOB_NAME: ${JENKINS_JOB_NAME}
|
JENKINS_JOB_NAME: ${JENKINS_JOB_NAME:-TallerCiCd}
|
||||||
JENKINS_USER: ${JENKINS_USER}
|
JENKINS_USER: ${JENKINS_USER:-}
|
||||||
JENKINS_TOKEN: ${JENKINS_TOKEN}
|
JENKINS_TOKEN: ${JENKINS_TOKEN:-}
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
healthcheck:
|
healthcheck:
|
||||||
test:
|
test:
|
||||||
@@ -26,10 +28,21 @@ services:
|
|||||||
frontend:
|
frontend:
|
||||||
build:
|
build:
|
||||||
context: ./frontend
|
context: ./frontend
|
||||||
image: cafeteria-frontend:${FRONTEND_TAG}
|
args:
|
||||||
|
VITE_API_BASE: ${VITE_API_BASE:-/taller/api}
|
||||||
|
image: cafeteria-frontend:${FRONTEND_TAG:-latest}
|
||||||
|
networks:
|
||||||
|
- cafeteria
|
||||||
ports:
|
ports:
|
||||||
- "80:80"
|
- "8081:8081"
|
||||||
depends_on:
|
depends_on:
|
||||||
backend:
|
backend:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
networks:
|
||||||
|
cafeteria:
|
||||||
|
enable_ipv6: true
|
||||||
|
ipam:
|
||||||
|
config:
|
||||||
|
- subnet: 2001:db8::/64
|
||||||
|
|||||||
@@ -1,12 +1,14 @@
|
|||||||
FROM node:20-slim AS build
|
FROM docker.io/library/node:20-slim AS build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package*.json ./
|
COPY package*.json ./
|
||||||
|
ARG VITE_API_BASE
|
||||||
|
ENV VITE_API_BASE=$VITE_API_BASE
|
||||||
RUN npm install --no-progress
|
RUN npm install --no-progress
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run build
|
RUN npm run build
|
||||||
|
|
||||||
FROM nginx:1.27-alpine AS final
|
FROM docker.io/library/nginx:1.27-alpine AS final
|
||||||
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html/taller
|
||||||
EXPOSE 80
|
EXPOSE 8081
|
||||||
CMD ["nginx", "-g", "daemon off;"]
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
|
|||||||
@@ -1,11 +1,24 @@
|
|||||||
server {
|
server {
|
||||||
listen 80;
|
listen 8081;
|
||||||
server_name _;
|
server_name _;
|
||||||
|
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
index index.html;
|
index index.html;
|
||||||
|
|
||||||
location / {
|
location = /taller {
|
||||||
try_files $uri /index.html;
|
return 301 /taller/;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /taller/api/ {
|
||||||
|
proxy_pass http://backend:8000/;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
|
||||||
|
location /taller/ {
|
||||||
|
try_files $uri $uri/ /taller/index.html;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,8 +96,8 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
|
|
||||||
if (!ENABLE_POLLING) return;
|
if (!ENABLE_POLLING) return;
|
||||||
|
|
||||||
const pricesInterval = setInterval(fetchPrices, 8000);
|
const pricesInterval = setInterval(fetchPrices, 180000);
|
||||||
const ciInterval = setInterval(fetchCiStatus, 10000);
|
const ciInterval = setInterval(fetchCiStatus, 300000);
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(pricesInterval);
|
clearInterval(pricesInterval);
|
||||||
@@ -467,7 +467,7 @@ along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|||||||
<div class="openbokeron-logo">
|
<div class="openbokeron-logo">
|
||||||
<div class="logo-bubble">
|
<div class="logo-bubble">
|
||||||
<img
|
<img
|
||||||
src="/open-bokeron-logo.png"
|
src={`${import.meta.env.BASE_URL}/open-bokeron-logo.png`}
|
||||||
alt="Logo de Open Bokeron"
|
alt="Logo de Open Bokeron"
|
||||||
loading="lazy"
|
loading="lazy"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -16,5 +16,9 @@ You should have received a copy of the GNU General Public License
|
|||||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const API_BASE = import.meta.env.VITE_API_BASE || 'http://localhost:8000';
|
const baseUrl = import.meta.env.BASE_URL || '/';
|
||||||
|
const defaultApiBase = `${baseUrl.replace(/\/$/, '')}/api`;
|
||||||
|
const rawApiBase = import.meta.env.VITE_API_BASE || defaultApiBase;
|
||||||
|
|
||||||
|
export const API_BASE = rawApiBase.replace(/\/$/, '');
|
||||||
export const ENABLE_POLLING = import.meta.env.MODE !== 'test';
|
export const ENABLE_POLLING = import.meta.env.MODE !== 'test';
|
||||||
|
|||||||
@@ -1,7 +1,15 @@
|
|||||||
import { defineConfig } from 'vite';
|
import { defineConfig, loadEnv } from 'vite';
|
||||||
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig(({ mode }) => {
|
||||||
|
const env = loadEnv(mode, process.cwd(), 'VITE_');
|
||||||
|
const basePath = '/taller/';
|
||||||
|
const defaultApiBase = `${basePath.replace(/\/$/, '')}/api`;
|
||||||
|
const apiBase = (env.VITE_API_BASE || defaultApiBase).replace(/\/$/, '');
|
||||||
|
const apiProxyPath = apiBase.startsWith('http') ? null : apiBase;
|
||||||
|
|
||||||
|
return {
|
||||||
|
base: basePath,
|
||||||
plugins: [svelte()],
|
plugins: [svelte()],
|
||||||
test: {
|
test: {
|
||||||
environment: 'jsdom',
|
environment: 'jsdom',
|
||||||
@@ -9,5 +17,18 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
port: 5173,
|
port: 5173,
|
||||||
|
proxy: apiProxyPath
|
||||||
|
? {
|
||||||
|
[apiProxyPath]: {
|
||||||
|
target: 'http://localhost:8000',
|
||||||
|
changeOrigin: true,
|
||||||
|
rewrite: (path) =>
|
||||||
|
path.startsWith(apiProxyPath)
|
||||||
|
? path.slice(apiProxyPath.length) || '/'
|
||||||
|
: path,
|
||||||
},
|
},
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -3,10 +3,15 @@ FROM jenkins/jenkins:lts
|
|||||||
USER root
|
USER root
|
||||||
|
|
||||||
RUN apt-get update \
|
RUN apt-get update \
|
||||||
&& apt-get install -y docker.io curl \
|
&& apt-get install -y ca-certificates curl gnupg \
|
||||||
&& curl -L https://github.com/docker/compose/releases/download/v2.27.0/docker-compose-linux-x86_64 \
|
&& install -m 0755 -d /etc/apt/keyrings \
|
||||||
-o /usr/local/bin/docker-compose \
|
&& curl -fsSL https://download.docker.com/linux/debian/gpg \
|
||||||
&& chmod +x /usr/local/bin/docker-compose \
|
| gpg --dearmor -o /etc/apt/keyrings/docker.gpg \
|
||||||
|
&& chmod a+r /etc/apt/keyrings/docker.gpg \
|
||||||
|
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian $(. /etc/os-release && echo \"$VERSION_CODENAME\") stable" \
|
||||||
|
> /etc/apt/sources.list.d/docker.list \
|
||||||
|
&& apt-get update \
|
||||||
|
&& apt-get install -y docker-ce-cli docker-compose-plugin \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
USER jenkins
|
USER jenkins
|
||||||
|
|||||||
Reference in New Issue
Block a user