Try the new plugin

This commit is contained in:
dvirlabs 2025-06-18 06:21:45 +03:00
parent fdb03f983c
commit cec81e48c9
11 changed files with 116 additions and 96 deletions

View File

@ -1,72 +1,38 @@
when:
event:
- push
- pull_request
branch:
- master
steps:
- name: tag
image: alpine
commands:
- export TAG_DATE=$(date +%Y%m%d)
- export SHORT_SHA=${CI_COMMIT_SHA:0:7}
- echo "TAGS=latest,$TAG_DATE-$SHORT_SHA" > .tags.env
build-frontend:
name: Build & Push Frontend with wp-kaniko-sync
image: harbor.dvirlabs.com/devtools/wp-kaniko-sync:latest
settings:
PLUGIN_CONTEXT: frontend
PLUGIN_DOCKERFILE: frontend/Dockerfile
PLUGIN_REPO: my-apps/labmap-frontend
PLUGIN_REGISTRY: harbor.dvirlabs.com
PLUGIN_NAME: frontend
PLUGIN_GIT_REPO: git.dvirlabs.com/dvirlabs/my-apps.git
PLUGIN_VALUES_FILE: manifests/labmap/values.yaml
PLUGIN_VALUES_PATH: frontend.tag
PLUGIN_GIT_USERNAME:
from_secret: GIT_USERNAME
PLUGIN_GIT_TOKEN:
from_secret: GIT_TOKEN
- name: setup-docker-config
image: alpine
commands:
- mkdir -p /kaniko/.docker
- |
cat <<EOF > /kaniko/.docker/config.json
{
"auths": {
"harbor.dvirlabs.com": {
"auth": "ZHZpcmxhYnM6S1loaHBlMUhwNk5DR2IxWDJVQ0VDRUtjS25mSFhodEY="
}
}
}
EOF
volumes:
- name: docker-config
path: /kaniko/.docker/
build-backend:
name: Build & Push Backend with wp-kaniko-sync
image: harbor.dvirlabs.com/devtools/wp-kaniko-sync:latest
settings:
PLUGIN_CONTEXT: backend
PLUGIN_DOCKERFILE: backend/Dockerfile
PLUGIN_REPO: my-apps/labmap-backend
PLUGIN_REGISTRY: harbor.dvirlabs.com
PLUGIN_NAME: backend
PLUGIN_GIT_REPO: git.dvirlabs.com/dvirlabs/my-apps.git
PLUGIN_VALUES_FILE: manifests/labmap/values.yaml
PLUGIN_VALUES_PATH: backend.tag
PLUGIN_GIT_USERNAME:
from_secret: GIT_USERNAME
PLUGIN_GIT_TOKEN:
from_secret: GIT_TOKEN
- name: build-frontend
image: gcr.io/kaniko-project/executor:latest
environment:
DOCKER_CONFIG: /kaniko/.docker/
volumes:
- name: docker-config
path: /kaniko/.docker/
commands:
- |
for TAG in $(cut -d= -f2 .tags.env | tr ',' '\n'); do
/kaniko/executor \
--dockerfile=frontend/Dockerfile \
--context=frontend \
--destination=harbor.dvirlabs.com/my-apps/navix-frontend:$TAG \
--insecure \
--skip-tls-verify
done
- name: build-backend
image: gcr.io/kaniko-project/executor:latest
environment:
DOCKER_CONFIG: /kaniko/.docker/
volumes:
- name: docker-config
path: /kaniko/.docker/
commands:
- |
for TAG in $(cut -d= -f2 .tags.env | tr ',' '\n'); do
/kaniko/executor \
--dockerfile=backend/Dockerfile \
--context=backend \
--destination=harbor.dvirlabs.com/my-apps/navix-backend:$TAG \
--insecure \
--skip-tls-verify
done
volumes:
- name: docker-config
temp: {}
when:
branch: [ master, develop ]
event: [ push, tag ]

View File

@ -1,4 +1,4 @@
from fastapi import FastAPI
from fastapi import FastAPI, APIRouter
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
import os
@ -7,11 +7,10 @@ import yaml
from pathlib import Path
from pydantic import BaseModel
from minio import Minio
from datetime import timedelta
app = FastAPI()
# Allow CORS for all origins
router = APIRouter()
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
@ -22,13 +21,12 @@ app.add_middleware(
load_dotenv()
# Load ENV variables
# ENV
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT")
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY")
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY")
MINIO_BUCKET = os.getenv("MINIO_BUCKET")
# MinIO connection with access and secret keys
minio_client = Minio(
MINIO_ENDPOINT,
access_key=MINIO_ACCESS_KEY,
@ -36,22 +34,21 @@ minio_client = Minio(
secure=True
)
BUCKET = "navix-icons"
BUCKET = MINIO_BUCKET or "navix-icons"
@app.get("/")
async def root():
@router.get("/")
def root():
return {"message": "Welcome to the FastAPI application!"}
# Path to apps.yaml (relative to backend/)
APPS_FILE = Path(__file__).parent / "apps.yaml"
@app.get("/apps")
@router.get("/apps")
def get_apps():
if not APPS_FILE.exists():
return {"error": "apps.yaml not found"}
with open(APPS_FILE, "r") as f:
return yaml.safe_load(f)
class AppData(BaseModel):
name: str
icon: str
@ -62,7 +59,7 @@ class AppEntry(BaseModel):
section: str
app: AppData
@app.post("/add_app")
@router.post("/add_app")
def add_app(entry: AppEntry):
if not APPS_FILE.exists():
current = {"sections": []}
@ -70,7 +67,6 @@ def add_app(entry: AppEntry):
with open(APPS_FILE, "r") as f:
current = yaml.safe_load(f) or {"sections": []}
# Find or create section
for section in current["sections"]:
if section["name"] == entry.section:
section["apps"].append(entry.app.dict())
@ -86,13 +82,13 @@ def add_app(entry: AppEntry):
return {"status": "added"}
@app.get("/icon/{filename}")
@router.get("/icon/{filename}")
def get_public_icon_url(filename: str):
url = f"https://{MINIO_ENDPOINT}/{MINIO_BUCKET}/{filename}"
url = f"https://{MINIO_ENDPOINT}/{BUCKET}/{filename}"
return JSONResponse(content={"url": url})
app.include_router(router, prefix="/api")
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)

View File

@ -6,15 +6,24 @@ RUN npm install --legacy-peer-deps
COPY . .
RUN npm run build
# Stage 2: NGINX
# Stage 2: Runtime (NGINX)
FROM nginx:alpine
# Install dos2unix to fix Windows line endings
RUN apk add --no-cache dos2unix
# Clean default nginx html
RUN rm -rf /usr/share/nginx/html/*
# Copy built frontend
COPY --from=builder /app/dist /usr/share/nginx/html
# Runtime env injection
# Copy entrypoint and normalize line endings
COPY docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh
RUN dos2unix /docker-entrypoint.sh && chmod +x /docker-entrypoint.sh
# Fallback env.js (to avoid 404 before initContainer writes real one)
RUN echo "window.env = {}" > /usr/share/nginx/html/env.js
CMD ["/docker-entrypoint.sh"]
# Set entrypoint
ENTRYPOINT ["/docker-entrypoint.sh"]

View File

@ -1,11 +1,11 @@
#!/bin/sh
set -e
# Generate env.js at runtime
# Generate env.js at runtime from env var
cat <<EOF > /usr/share/nginx/html/env.js
window.env = {
VITE_API_URL: "${VITE_API_URL}"
}
};
EOF
exec nginx -g "daemon off;"

View File

@ -5,6 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/navix-logo.svg" />
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@500&family=Rajdhani:wght@500&display=swap" rel="stylesheet">
<script src="/env.js"></script>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Navix</title>
</head>

View File

@ -1,4 +1,4 @@
const API_BASE = window?.env?.VITE_API_URL || '';
const API_BASE = window?.env?.VITE_API_URL || '/api';
export async function fetchSections() {
const res = await fetch(`${API_BASE}/apps`);

View File

@ -0,0 +1,14 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
server: {
proxy: {
'/apps': 'http://localhost:8000',
'/add_app': 'http://localhost:8000',
'/icon': 'http://localhost:8000',
}
}
});

View File

@ -0,0 +1,23 @@
{{- if .Values.backend.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: navix-backend
annotations:
{{- range $key, $value := .Values.backend.ingress.annotations }}
{{ $key }}: {{ $value | quote }}
{{- end }}
spec:
ingressClassName: {{ .Values.backend.ingress.className }}
rules:
- host: {{ .Values.backend.ingress.hosts[0].host }}
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: navix-backend
port:
number: {{ .Values.backend.service.port }}
{{- end }}

View File

@ -5,5 +5,5 @@ metadata:
data:
env.js: |
window.env = {
VITE_API_URL: "http://navix-backend.{{ .Release.Namespace }}.svc.cluster.local:8000"
VITE_API_URL: "{{ .Values.frontend.env.VITE_API_URL }}"
};

View File

@ -17,6 +17,8 @@ frontend:
paths:
- path: /
pathType: Prefix
env:
VITE_API_URL: "/api"
backend:
image:
@ -32,4 +34,13 @@ backend:
MINIO_ENDPOINT: "s3.dvirlabs.com"
MINIO_BUCKET: "navix-icons"
ingress:
enabled: false
enabled: true
className: traefik
annotations:
traefik.ingress.kubernetes.io/router.entrypoints: websecure
traefik.ingress.kubernetes.io/router.tls: "true"
hosts:
- host: navix.dvirlabs.com
paths:
- path: /api
pathType: Prefix