diff --git a/.woodpecker.yml b/.woodpecker.yml index 32c3aff2..d0372dda 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -68,25 +68,78 @@ steps: event: pull_request # =========================================== - # MASTER DEPLOY: Parallel Docker builds (Kaniko) - # Push to local registry (10.100.9.70:5000) for fast K8s pulls + # BUILD: Frontend assets in CI (not Docker) + # =========================================== + build-cannaiq: + image: node:22-alpine + commands: + - cd cannaiq + - npm ci --prefer-offline + - npm run build + - ls -la dist/ + depends_on: [] + when: + branch: [master, develop] + event: push + + build-findadispo: + image: node:22-alpine + commands: + - cd findadispo/frontend + - npm ci --prefer-offline + - npm run build + - ls -la build/ + depends_on: [] + when: + branch: [master, develop] + event: push + + build-findagram: + image: node:22-alpine + commands: + - cd findagram/frontend + - npm ci --prefer-offline + - npm run build + - ls -la build/ + depends_on: [] + when: + branch: [master, develop] + event: push + + build-backend: + image: node:22-alpine + commands: + - apk add --no-cache python3 make g++ + - cd backend + - npm ci --prefer-offline + - npm run build + - npm prune --production + - ls -la dist/ + depends_on: [] + when: + branch: [master, develop] + event: push + + # =========================================== + # DOCKER: Simple copy builds (no npm inside) # =========================================== docker-backend: image: gcr.io/kaniko-project/executor:debug commands: - /kaniko/executor - --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/backend - --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/backend/Dockerfile + --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq + --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/backend/Dockerfile.ci --destination=10.100.9.70:5000/cannaiq/backend:latest --destination=10.100.9.70:5000/cannaiq/backend:sha-${CI_COMMIT_SHA:0:8} --build-arg=APP_BUILD_VERSION=sha-${CI_COMMIT_SHA:0:8} --build-arg=APP_GIT_SHA=${CI_COMMIT_SHA} --build-arg=APP_BUILD_TIME=${CI_PIPELINE_CREATED} - --build-arg=CONTAINER_IMAGE_TAG=sha-${CI_COMMIT_SHA:0:8} --registry-mirror=mirror.gcr.io --insecure-registry=10.100.9.70:5000 --cache=true - depends_on: [] + --cache-ttl=168h + depends_on: + - build-backend when: branch: [master, develop] event: push @@ -95,14 +148,16 @@ steps: image: gcr.io/kaniko-project/executor:debug commands: - /kaniko/executor - --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/cannaiq - --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/cannaiq/Dockerfile + --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq + --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/cannaiq/Dockerfile.ci --destination=10.100.9.70:5000/cannaiq/frontend:latest --destination=10.100.9.70:5000/cannaiq/frontend:sha-${CI_COMMIT_SHA:0:8} --registry-mirror=mirror.gcr.io --insecure-registry=10.100.9.70:5000 --cache=true - depends_on: [] + --cache-ttl=168h + depends_on: + - build-cannaiq when: branch: [master, develop] event: push @@ -111,14 +166,16 @@ steps: image: gcr.io/kaniko-project/executor:debug commands: - /kaniko/executor - --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findadispo/frontend - --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findadispo/frontend/Dockerfile + --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq + --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findadispo/frontend/Dockerfile.ci --destination=10.100.9.70:5000/cannaiq/findadispo:latest --destination=10.100.9.70:5000/cannaiq/findadispo:sha-${CI_COMMIT_SHA:0:8} --registry-mirror=mirror.gcr.io --insecure-registry=10.100.9.70:5000 --cache=true - depends_on: [] + --cache-ttl=168h + depends_on: + - build-findadispo when: branch: [master, develop] event: push @@ -127,20 +184,22 @@ steps: image: gcr.io/kaniko-project/executor:debug commands: - /kaniko/executor - --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findagram/frontend - --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findagram/frontend/Dockerfile + --context=/woodpecker/src/git.spdy.io/Creationshop/cannaiq + --dockerfile=/woodpecker/src/git.spdy.io/Creationshop/cannaiq/findagram/frontend/Dockerfile.ci --destination=10.100.9.70:5000/cannaiq/findagram:latest --destination=10.100.9.70:5000/cannaiq/findagram:sha-${CI_COMMIT_SHA:0:8} --registry-mirror=mirror.gcr.io --insecure-registry=10.100.9.70:5000 --cache=true - depends_on: [] + --cache-ttl=168h + depends_on: + - build-findagram when: branch: [master, develop] event: push # =========================================== - # STAGE 3: Deploy to K8s (pull from local registry) + # DEPLOY: Pull from local registry # =========================================== deploy: image: bitnami/kubectl:latest @@ -151,13 +210,10 @@ steps: - mkdir -p ~/.kube - echo "$KUBECONFIG_CONTENT" | tr -d '[:space:]' | base64 -d > ~/.kube/config - chmod 600 ~/.kube/config - # Deploy backend first - kubectl set image deployment/scraper scraper=10.100.9.70:5000/cannaiq/backend:sha-${CI_COMMIT_SHA:0:8} -n cannaiq - kubectl rollout status deployment/scraper -n cannaiq --timeout=300s - # Deploy workers - - REPLICAS=$(kubectl get deployment scraper-worker -n cannaiq -o jsonpath='{.spec.replicas}'); if [ "$REPLICAS" = "0" ]; then echo "Scaling workers from 0 to 5"; kubectl scale deployment/scraper-worker --replicas=5 -n cannaiq; fi + - REPLICAS=$(kubectl get deployment scraper-worker -n cannaiq -o jsonpath='{.spec.replicas}'); if [ "$REPLICAS" = "0" ]; then kubectl scale deployment/scraper-worker --replicas=5 -n cannaiq; fi - kubectl set image deployment/scraper-worker worker=10.100.9.70:5000/cannaiq/backend:sha-${CI_COMMIT_SHA:0:8} -n cannaiq - # Deploy frontends - kubectl set image deployment/cannaiq-frontend cannaiq-frontend=10.100.9.70:5000/cannaiq/frontend:sha-${CI_COMMIT_SHA:0:8} -n cannaiq - kubectl set image deployment/findadispo-frontend findadispo-frontend=10.100.9.70:5000/cannaiq/findadispo:sha-${CI_COMMIT_SHA:0:8} -n cannaiq - kubectl set image deployment/findagram-frontend findagram-frontend=10.100.9.70:5000/cannaiq/findagram:sha-${CI_COMMIT_SHA:0:8} -n cannaiq diff --git a/backend/Dockerfile.ci b/backend/Dockerfile.ci new file mode 100644 index 00000000..92c0fcdc --- /dev/null +++ b/backend/Dockerfile.ci @@ -0,0 +1,43 @@ +# CI Dockerfile - assets pre-built in CI step +# No npm install or build - just copy and run +FROM node:22-slim + +# Build arguments for version info +ARG APP_BUILD_VERSION=dev +ARG APP_GIT_SHA=unknown +ARG APP_BUILD_TIME=unknown + +ENV APP_BUILD_VERSION=${APP_BUILD_VERSION} +ENV APP_GIT_SHA=${APP_GIT_SHA} +ENV APP_BUILD_TIME=${APP_BUILD_TIME} + +# Install runtime dependencies only (Chromium for Puppeteer) +RUN apt-get update && apt-get install -y \ + curl \ + chromium \ + fonts-liberation \ + libnss3 \ + libxss1 \ + libasound2 \ + libatk-bridge2.0-0 \ + libgtk-3-0 \ + --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + +ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=true +ENV PUPPETEER_EXECUTABLE_PATH=/usr/bin/chromium + +WORKDIR /app + +# Copy pre-built assets from CI +COPY backend/package*.json ./ +COPY backend/node_modules ./node_modules +COPY backend/dist ./dist +COPY backend/migrations ./migrations +COPY backend/public/downloads ./public/downloads + +RUN mkdir -p /app/public/images/products + +EXPOSE 3010 + +CMD ["node", "dist/index.js"] diff --git a/cannaiq/Dockerfile.ci b/cannaiq/Dockerfile.ci new file mode 100644 index 00000000..5b4d82e1 --- /dev/null +++ b/cannaiq/Dockerfile.ci @@ -0,0 +1,25 @@ +# CI Dockerfile - assets pre-built in CI step +FROM nginx:alpine + +# Copy pre-built assets from CI +COPY cannaiq/dist /usr/share/nginx/html + +# SPA routing config +RUN echo 'server { \ + listen 80; \ + server_name _; \ + root /usr/share/nginx/html; \ + index index.html; \ + gzip on; \ + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; \ + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { \ + expires 1y; \ + add_header Cache-Control "public, immutable"; \ + } \ + location / { \ + try_files $uri $uri/ /index.html; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/findadispo/frontend/Dockerfile.ci b/findadispo/frontend/Dockerfile.ci new file mode 100644 index 00000000..5c8cdc5b --- /dev/null +++ b/findadispo/frontend/Dockerfile.ci @@ -0,0 +1,25 @@ +# CI Dockerfile - assets pre-built in CI step +FROM nginx:alpine + +# Copy pre-built assets from CI (CRA builds to /build) +COPY findadispo/frontend/build /usr/share/nginx/html + +# SPA routing config +RUN echo 'server { \ + listen 80; \ + server_name _; \ + root /usr/share/nginx/html; \ + index index.html; \ + gzip on; \ + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; \ + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { \ + expires 1y; \ + add_header Cache-Control "public, immutable"; \ + } \ + location / { \ + try_files $uri $uri/ /index.html; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"] diff --git a/findagram/frontend/Dockerfile.ci b/findagram/frontend/Dockerfile.ci new file mode 100644 index 00000000..5424711e --- /dev/null +++ b/findagram/frontend/Dockerfile.ci @@ -0,0 +1,25 @@ +# CI Dockerfile - assets pre-built in CI step +FROM nginx:alpine + +# Copy pre-built assets from CI (CRA builds to /build) +COPY findagram/frontend/build /usr/share/nginx/html + +# SPA routing config +RUN echo 'server { \ + listen 80; \ + server_name _; \ + root /usr/share/nginx/html; \ + index index.html; \ + gzip on; \ + gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript; \ + location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { \ + expires 1y; \ + add_header Cache-Control "public, immutable"; \ + } \ + location / { \ + try_files $uri $uri/ /index.html; \ + } \ +}' > /etc/nginx/conf.d/default.conf + +EXPOSE 80 +CMD ["nginx", "-g", "daemon off;"]