Compare commits
No commits in common. "501addc9097e8610c1a89866cb70804492e55813" and "cb088439568a652e2b7831e41a2a6b76afd583e2" have entirely different histories.
501addc909
...
cb08843956
@ -23,12 +23,8 @@ jobs:
|
||||
|
||||
- name: Deploy
|
||||
shell: sh
|
||||
timeout-minutes: 12
|
||||
timeout-minutes: 15
|
||||
run: |
|
||||
BRANCH="${GITHUB_REF_NAME}"
|
||||
echo "Deploying branch: ${BRANCH}"
|
||||
ssh -o StrictHostKeyChecking=no \
|
||||
-o ServerAliveInterval=30 \
|
||||
-o ServerAliveCountMax=30 \
|
||||
-p 2234 devops@172.17.0.1 \
|
||||
"sudo bash /opt/services/scripts/depcanina.sh ${BRANCH}"
|
||||
ssh -o StrictHostKeyChecking=no -p 2234 devops@172.17.0.1 "bash /opt/services/scripts/depcanina.sh ${BRANCH}"
|
||||
|
||||
@ -5,8 +5,6 @@ ENV NEXT_PUBLIC_API_URL=https://stageapi.canina.ir/api
|
||||
COPY frontend/application/package*.json ./
|
||||
RUN npm ci --prefer-offline --no-audit
|
||||
COPY frontend/application ./
|
||||
ARG NEXT_PUBLIC_API_URL
|
||||
ENV NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
|
||||
RUN npm run build
|
||||
|
||||
FROM node:20-alpine AS admin-builder
|
||||
@ -15,8 +13,6 @@ ENV VITE_API_URL=https://stageapi.canina.ir/api
|
||||
COPY frontend/admin-panel/package*.json ./
|
||||
RUN npm ci --prefer-offline --no-audit
|
||||
COPY frontend/admin-panel ./
|
||||
ARG VITE_API_URL
|
||||
ENV VITE_API_URL=$VITE_API_URL
|
||||
RUN npm run build
|
||||
|
||||
FROM node:20-alpine
|
||||
|
||||
@ -15,7 +15,6 @@ COPY --from=builder /app/node_modules ./node_modules
|
||||
COPY --from=builder /app/dist ./dist
|
||||
COPY --from=builder /app/prisma ./prisma
|
||||
COPY --from=builder /app/prisma/scientificTerms.ts ./prisma/scientificTerms.ts
|
||||
RUN chown -R node:node /app
|
||||
EXPOSE 3000
|
||||
USER node
|
||||
CMD ["sh", "-c", "npx prisma migrate deploy && node dist/main"]
|
||||
|
||||
@ -2,7 +2,7 @@ import { PrismaClient } from '@prisma/client';
|
||||
|
||||
const prisma = new PrismaClient();
|
||||
|
||||
export async function main() {
|
||||
async function main() {
|
||||
console.log('Seeding Home Page Components...');
|
||||
|
||||
// 1. Seed Hero Banners
|
||||
|
||||
@ -151,7 +151,7 @@ const PRODUCT_TAGLINES_MAP: Record<string, string> = {
|
||||
'canina-novagard-green-pfotenpflege': "مومیایی محافظ پنجهها برای التیام خشکی، قرمزی و ترک خوردگی پنجهها در برف و سرما"
|
||||
};
|
||||
|
||||
export async function main() {
|
||||
async function main() {
|
||||
console.log('Seeding products from seed-products-data.json...');
|
||||
|
||||
// 2. Read JSON data
|
||||
|
||||
@ -296,10 +296,8 @@ async function main() {
|
||||
// 3. Seed Products & Categories
|
||||
console.log('Seeding Products & Categories...');
|
||||
try {
|
||||
const seedProducts = require('./seed-products');
|
||||
if (seedProducts && typeof seedProducts.main === 'function') {
|
||||
await seedProducts.main();
|
||||
}
|
||||
const { execSync } = require('child_process');
|
||||
execSync('npx ts-node prisma/seed-products.ts', { stdio: 'inherit' });
|
||||
} catch (err) {
|
||||
console.error('Failed to seed products:', err);
|
||||
}
|
||||
@ -307,10 +305,8 @@ async function main() {
|
||||
// 4. Seed Home Components & Testimonials
|
||||
console.log('Seeding Home Components...');
|
||||
try {
|
||||
const seedHome = require('./seed-home');
|
||||
if (seedHome && typeof seedHome.main === 'function') {
|
||||
await seedHome.main();
|
||||
}
|
||||
const { execSync } = require('child_process');
|
||||
execSync('npx ts-node prisma/seed-home.ts', { stdio: 'inherit' });
|
||||
} catch (err) {
|
||||
console.error('Failed to seed home components:', err);
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@ import axios from 'axios';
|
||||
|
||||
export const BASE_DOMAIN = import.meta.env.VITE_API_URL
|
||||
? import.meta.env.VITE_API_URL.replace(/\/api$/, '')
|
||||
: (import.meta.env.DEV ? 'http://127.0.0.1:4001' : '');
|
||||
: (import.meta.env.DEV ? 'http://127.0.0.1:4001' : 'https://api.canina.ir');
|
||||
|
||||
const baseURL = `${BASE_DOMAIN}/api`;
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import axios from 'axios';
|
||||
|
||||
const baseURL = process.env.NEXT_PUBLIC_API_URL || (process.env.NODE_ENV === 'development' ? 'http://localhost:4001/api' : '/api');
|
||||
const baseURL = process.env.NEXT_PUBLIC_API_URL || (process.env.NODE_ENV === 'development' ? 'http://localhost:4001/api' : 'https://api.canina.ir/api');
|
||||
|
||||
const api = axios.create({
|
||||
baseURL,
|
||||
|
||||
@ -15,18 +15,13 @@ const nextConfig: NextConfig = {
|
||||
],
|
||||
},
|
||||
async rewrites() {
|
||||
// Only proxy /api in development; in production nginx handles it
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
return [
|
||||
{
|
||||
source: '/api/:path*',
|
||||
destination: 'http://localhost:4001/api/:path*',
|
||||
},
|
||||
];
|
||||
}
|
||||
return [];
|
||||
},
|
||||
};
|
||||
|
||||
export default nextConfig;
|
||||
|
||||
|
||||
10
nginx.conf
10
nginx.conf
@ -1,6 +1,6 @@
|
||||
server {
|
||||
listen 8080;
|
||||
server_name __APP_HOST__;
|
||||
server_name canina.ir stage.canina.ir;
|
||||
|
||||
# Security Headers
|
||||
server_tokens off;
|
||||
@ -21,19 +21,18 @@ server {
|
||||
|
||||
# Backend API
|
||||
location /api {
|
||||
proxy_pass http://__BACKEND_HOST__:3000;
|
||||
proxy_pass http://backend:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
client_max_body_size 50M;
|
||||
}
|
||||
}
|
||||
|
||||
server {
|
||||
listen 8080;
|
||||
server_name __ADMIN_HOST__;
|
||||
server_name admin.canina.ir stageadmin.canina.ir;
|
||||
|
||||
root /app/admin_static;
|
||||
index index.html;
|
||||
@ -52,12 +51,11 @@ server {
|
||||
|
||||
# Backend API for Admin
|
||||
location /api {
|
||||
proxy_pass http://__BACKEND_HOST__:3000;
|
||||
proxy_pass http://backend:3000;
|
||||
proxy_http_version 1.1;
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
proxy_set_header Connection 'upgrade';
|
||||
proxy_set_header Host $host;
|
||||
proxy_cache_bypass $http_upgrade;
|
||||
client_max_body_size 50M;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,72 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
db_prod:
|
||||
image: postgres:16-alpine
|
||||
container_name: canino_db_prod
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: canino_prod
|
||||
POSTGRES_PASSWORD: caninopassword_prod
|
||||
POSTGRES_DB: caninodb_prod
|
||||
volumes:
|
||||
- canina_prod_db:/var/lib/postgresql/data
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
redis_prod:
|
||||
image: redis:7-alpine
|
||||
container_name: canino_redis_prod
|
||||
restart: always
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
backend_prod:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: canino_backend_prod
|
||||
restart: always
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://canino_prod:caninopassword_prod@db_prod:5432/caninodb_prod?schema=public
|
||||
- REDIS_HOST=redis_prod
|
||||
- REDIS_PORT=6379
|
||||
- PORT=3000
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.canina-api-prod.rule=Host(`api.canina.ir`)"
|
||||
- "traefik.http.routers.canina-api-prod.entrypoints=websecure"
|
||||
- "traefik.http.routers.canina-api-prod.tls=true"
|
||||
- "traefik.http.services.canina-api-prod.loadbalancer.server.port=3000"
|
||||
depends_on:
|
||||
- db_prod
|
||||
- redis_prod
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
frontend_prod:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
NEXT_PUBLIC_API_URL: "https://api.canina.ir/api"
|
||||
VITE_API_URL: "https://api.canina.ir"
|
||||
container_name: canino_frontend_prod
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.canina-prod.rule=Host(`canina.ir`) || Host(`admin.canina.ir`)"
|
||||
- "traefik.http.routers.canina-prod.entrypoints=websecure"
|
||||
- "traefik.http.routers.canina-prod.tls=true"
|
||||
- "traefik.http.services.canina-prod.loadbalancer.server.port=8080"
|
||||
depends_on:
|
||||
- backend_prod
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
networks:
|
||||
traefik_public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
canina_prod_db:
|
||||
@ -1,72 +0,0 @@
|
||||
version: '3.8'
|
||||
|
||||
services:
|
||||
db_stage:
|
||||
image: postgres:16-alpine
|
||||
container_name: canino_db_stage
|
||||
restart: always
|
||||
environment:
|
||||
POSTGRES_USER: canino_stage
|
||||
POSTGRES_PASSWORD: caninopassword_stage
|
||||
POSTGRES_DB: caninodb_stage
|
||||
volumes:
|
||||
- canina_stage_db:/var/lib/postgresql/data
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
redis_stage:
|
||||
image: redis:7-alpine
|
||||
container_name: canino_redis_stage
|
||||
restart: always
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
backend_stage:
|
||||
build:
|
||||
context: ./backend
|
||||
dockerfile: Dockerfile
|
||||
container_name: canino_backend_stage
|
||||
restart: always
|
||||
environment:
|
||||
- DATABASE_URL=postgresql://canino_stage:caninopassword_stage@db_stage:5432/caninodb_stage?schema=public
|
||||
- REDIS_HOST=redis_stage
|
||||
- REDIS_PORT=6379
|
||||
- PORT=3000
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.canina-api-stage.rule=Host(`stageapi.canina.ir`)"
|
||||
- "traefik.http.routers.canina-api-stage.entrypoints=websecure"
|
||||
- "traefik.http.routers.canina-api-stage.tls=true"
|
||||
- "traefik.http.services.canina-api-stage.loadbalancer.server.port=3000"
|
||||
depends_on:
|
||||
- db_stage
|
||||
- redis_stage
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
frontend_stage:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
args:
|
||||
NEXT_PUBLIC_API_URL: "https://stageapi.canina.ir/api"
|
||||
VITE_API_URL: "https://stageapi.canina.ir"
|
||||
container_name: canino_frontend_stage
|
||||
restart: always
|
||||
labels:
|
||||
- "traefik.enable=true"
|
||||
- "traefik.http.routers.canina-stage.rule=Host(`stage.canina.ir`) || Host(`stageadmin.canina.ir`)"
|
||||
- "traefik.http.routers.canina-stage.entrypoints=websecure"
|
||||
- "traefik.http.routers.canina-stage.tls=true"
|
||||
- "traefik.http.services.canina-stage.loadbalancer.server.port=8080"
|
||||
depends_on:
|
||||
- backend_stage
|
||||
networks:
|
||||
- traefik_public
|
||||
|
||||
networks:
|
||||
traefik_public:
|
||||
external: true
|
||||
|
||||
volumes:
|
||||
canina_stage_db:
|
||||
@ -1,77 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
export DOCKER_BUILDKIT=1
|
||||
export COMPOSE_DOCKER_CLI_BUILD=1
|
||||
|
||||
BRANCH="${1:-develop}"
|
||||
echo "Starting Deployment for branch: ${BRANCH}"
|
||||
|
||||
if [ "$BRANCH" == "develop" ]; then
|
||||
COMPOSE_FILE="compose.stage.yml"
|
||||
TARGET_DIR="/opt/services/canina/stage"
|
||||
BACKEND_HOST="backend_stage"
|
||||
APP_HOST="stage.canina.ir"
|
||||
ADMIN_HOST="stageadmin.canina.ir"
|
||||
API_URL="https://stageapi.canina.ir"
|
||||
CONTAINER_PREFIX="canino_backend_stage"
|
||||
else
|
||||
COMPOSE_FILE="compose.prod.yml"
|
||||
TARGET_DIR="/opt/services/canina/prod"
|
||||
BACKEND_HOST="backend_prod"
|
||||
APP_HOST="canina.ir"
|
||||
ADMIN_HOST="admin.canina.ir"
|
||||
API_URL="https://api.canina.ir"
|
||||
CONTAINER_PREFIX="canino_backend_prod"
|
||||
fi
|
||||
|
||||
mkdir -p "$TARGET_DIR"
|
||||
cd "$TARGET_DIR"
|
||||
|
||||
if [ ! -d ".git" ]; then
|
||||
echo "Cloning repository..."
|
||||
git clone -b "$BRANCH" https://git.parsaaghayi.ir/parsa/canina.git .
|
||||
else
|
||||
echo "Pulling latest changes..."
|
||||
git fetch origin "$BRANCH"
|
||||
git reset --hard "origin/$BRANCH"
|
||||
fi
|
||||
|
||||
echo "Fixing .dockerignore..."
|
||||
sed -i '/node_modules/d' .dockerignore 2>/dev/null || true
|
||||
sed -i '/node_modules/d' backend/.dockerignore 2>/dev/null || true
|
||||
sed -i '/^backend$/d' .dockerignore 2>/dev/null || true
|
||||
|
||||
echo "Disabling TS checks for fast deploy..."
|
||||
sed -i 's|tsc -b \&\& vite build|vite build|g' frontend/admin-panel/package.json 2>/dev/null || true
|
||||
sed -i 's|tsc \&\& vite build|vite build|g' frontend/admin-panel/package.json 2>/dev/null || true
|
||||
|
||||
# Copy scientificTerms.ts if needed
|
||||
cp frontend/application/lib/data/scientificTerms.ts backend/prisma/scientificTerms.ts 2>/dev/null || true
|
||||
|
||||
# Prepare docker-compose.yml in TARGET_DIR
|
||||
cp "/opt/services/canina/$COMPOSE_FILE" "$TARGET_DIR/docker-compose.yml"
|
||||
sed -i 's/- REDIS_PORT: 6379/- REDIS_PORT=6379/g' "$TARGET_DIR/docker-compose.yml" 2>/dev/null || true
|
||||
|
||||
# Prepare nginx.conf for current environment
|
||||
echo "Patching nginx.conf for environment..."
|
||||
cp nginx.conf nginx.conf.tmp
|
||||
sed -i "s/__BACKEND_HOST__/${BACKEND_HOST}/g" nginx.conf.tmp
|
||||
sed -i "s/__APP_HOST__/${APP_HOST}/g" nginx.conf.tmp
|
||||
sed -i "s/__ADMIN_HOST__/${ADMIN_HOST}/g" nginx.conf.tmp
|
||||
mv nginx.conf.tmp nginx.conf
|
||||
|
||||
echo "Building Docker images..."
|
||||
docker compose build --build-arg NEXT_PUBLIC_API_URL="${API_URL}/api" --build-arg VITE_API_URL="${API_URL}"
|
||||
|
||||
echo "Starting containers..."
|
||||
docker compose up -d
|
||||
|
||||
echo "Waiting for backend to start..."
|
||||
sleep 15
|
||||
|
||||
echo "Running migrations and seeding database..."
|
||||
docker exec "$CONTAINER_PREFIX" npx prisma migrate deploy || true
|
||||
docker exec "$CONTAINER_PREFIX" npx prisma db seed || true
|
||||
|
||||
echo "Deployment for $BRANCH completed successfully!"
|
||||
Loading…
Reference in New Issue
Block a user