diff --git a/.drone.yml b/.drone.yml index f1be2bc..5d4dd02 100644 --- a/.drone.yml +++ b/.drone.yml @@ -1,89 +1,59 @@ +## Universal .drone.yml for all project types +## Configure your project via service.yaml (see ci-templates/docs/requirements.md) + kind: pipeline type: kubernetes -name: deploy-frontend - -# Триггеры: запускать на push в ветки main и develop -trigger: - branch: - - master - - develop - event: - - push +name: ci steps: -# --- Шаг 1: Сборка и отправка образа в Harbor --- -# Этот шаг выполняется для любой из веток (main или develop) -- name: build-and-push - image: plugins/docker - settings: - # Укажите ваш домен Harbor - registry: registry.vigdorov.ru - # Имя репозитория в Harbor (например, в проекте library) - repo: registry.vigdorov.ru/library/examples-for-kids-app - # Тег будет равен первым 7 символам хеша коммита (например, a1b2c3d) - tags: - - ${DRONE_COMMIT_SHA:0:7} - # Используем секреты, которые мы создали в Drone - username: - from_secret: HARBOR_USER - password: - from_secret: HARBOR_PASSWORD + - name: prepare + image: alpine:3.19 + environment: + GITEA_TOKEN: + from_secret: GITEA_TOKEN + commands: + - apk add --no-cache git bash yq + - git clone --depth 1 https://token:$GITEA_TOKEN@git.vigdorov.ru/vigdorov/ci-templates.git .ci + - chmod +x .ci/scripts/*.sh + - bash .ci/scripts/prepare.sh -# --- Шаг 2: Развертывание в DEV-окружение --- -- name: deploy-dev - image: alpine/k8s:1.28.2 # Образ с kubectl и другими утилитами - # Запускать этот шаг ТОЛЬКО для ветки 'develop' - when: - branch: - - develop - environment: - # Используем секрет с kubeconfig - KUBECONFIG: - from_secret: KUBE_CONFIG - commands: - # Готовим переменные для dev-окружения - - 'export APP_NAMESPACE="dev-ns"' # Будем деплоить в отдельный неймспейс - - 'export HOSTNAME="dev_examples-for-kids.vigdorov.ru"' - - 'export IMAGE_TAG="${DRONE_COMMIT_SHA:0:7}"' - - 'export IMAGE_NAME="ci.vigdorov.ru/library/examples-for-kids-app"' - - 'export SECRET_NAME="wildcard-cert"' - # Создаем неймспейс, если его нет - - 'kubectl create namespace $APP_NAMESPACE --dry-run=client -o yaml | kubectl apply -f -' - # Заменяем метки в шаблонах на реальные значения и применяем - - 'sed -e "s|__IMAGE__|$IMAGE_NAME:$IMAGE_TAG|g" k8s/deployment.yaml | kubectl apply -n $APP_NAMESPACE -f -' - - 'kubectl apply -n $APP_NAMESPACE -f k8s/service.yaml' - - 'sed -e "s|__HOSTNAME__|$HOSTNAME|g" -e "s|__SECRET_NAME__|$SECRET_NAME|g" k8s/ingress.yaml | kubectl apply -n $APP_NAMESPACE -f -' - - 'echo "Deployed to DEV: https://$HOSTNAME"' + - name: build + image: gcr.io/kaniko-project/executor:v1.23.2-debug + depends_on: [prepare] + environment: + HARBOR_USER: + from_secret: HARBOR_USER + HARBOR_PASSWORD: + from_secret: HARBOR_PASSWORD + commands: + - /busybox/sh .ci/scripts/build.sh -# --- Шаг 3: Развертывание в PROD-окружение --- -- name: deploy-prod - image: alpine/k8s:1.28.2 - # Запускать этот шаг ТОЛЬКО для ветки 'main' - when: - branch: - - master - environment: - KUBE_CONFIG_CONTENT: - from_secret: KUBE_CONFIG - commands: - # Создаем kubeconfig файл из секрета - - 'mkdir -p ~/.kube' - - 'echo "$KUBE_CONFIG_CONTENT" > ~/.kube/config' - - 'chmod 600 ~/.kube/config' - # Заменяем localhost на внешний IP сервера - - 'sed -i "s|https://127.0.0.1:6443|https://10.10.10.100:6443|g" ~/.kube/config' - # Готовим переменные для prod-окружения - - 'export APP_NAMESPACE="prod-ns"' - - 'export HOSTNAME="examples-for-kids.vigdorov.ru"' - - 'export IMAGE_TAG="${DRONE_COMMIT_SHA:0:7}"' - - 'export IMAGE_NAME="registry.vigdorov.ru/library/examples-for-kids-app"' - - 'export SECRET_NAME="wildcard-cert"' - # Проверяем подключение к кластеру - - 'kubectl cluster-info' - # Создаем неймспейс - - 'kubectl create namespace $APP_NAMESPACE --dry-run=client -o yaml | kubectl apply -f -' - # Разворачиваем приложение - - 'sed -e "s|__IMAGE__|$IMAGE_NAME:$IMAGE_TAG|g" k8s/deployment.yaml | kubectl apply -n $APP_NAMESPACE -f -' - - 'kubectl apply -n $APP_NAMESPACE -f k8s/service.yaml' - - 'sed -e "s|__HOSTNAME__|$HOSTNAME|g" -e "s|__SECRET_NAME__|$SECRET_NAME|g" k8s/ingress.yaml | kubectl apply -n $APP_NAMESPACE -f -' - - 'echo "Deployed to PROD: https://$HOSTNAME"' \ No newline at end of file + - name: deploy + image: alpine/helm:3.14 + depends_on: [build] + environment: + KUBE_CONFIG: + from_secret: KUBE_CONFIG + commands: + - apk add --no-cache bash yq kubectl + - bash .ci/scripts/deploy.sh + + - name: notify + image: appleboy/drone-telegram + depends_on: [deploy] + settings: + token: + from_secret: TELEGRAM_TOKEN + to: + from_secret: TELEGRAM_CHAT_ID + format: markdown + message: > + {{#success build.status}}✅{{else}}❌{{/success}} **{{repo.name}}** + Branch: `{{commit.branch}}` + {{commit.message}} + when: + status: [success, failure] + +trigger: + branch: [master, develop] + event: [push] diff --git a/.gitignore b/.gitignore index 6f30d39..85fb85a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,6 @@ /node_modules /.vscode -/build +/dist /coverage **/junit.xml .dependencies-cache diff --git a/CLAUDE.md b/CLAUDE.md index b52077d..e373cdc 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -30,13 +30,13 @@ examples-for-kids/ ├── src/ # Исходный код ├── public/ # Статические файлы ├── coverage/ # Отчеты покрытия тестами -├── k8s/ # Kubernetes манифесты -├── Dockerfile # Docker сборка -└── .drone.yml # CI/CD пайплайн +├── service.yaml # Конфиг для ci-templates +└── .drone.yml # CI/CD пайплайн (универсальный) ``` ## Деплой -- CI/CD через Drone -- Docker образ -- Kubernetes deployment +- Тип: `web-frontend` (ci-templates) +- Dockerfile, nginx.conf, Helm chart — предоставляются ci-templates автоматически +- Конфигурация через `service.yaml` +- Домен: examples-for-kids.vigdorov.ru diff --git a/Dockerfile b/Dockerfile deleted file mode 100644 index 1f036a6..0000000 --- a/Dockerfile +++ /dev/null @@ -1,14 +0,0 @@ -# build environment -FROM node:18 as builder -WORKDIR /app -COPY package*.json ./ -RUN npm ci -COPY . . -RUN npm run build - -# production environment -FROM nginx:alpine -COPY --from=builder /app/build /usr/share/nginx/html -COPY nginx.conf /etc/nginx/nginx.conf -EXPOSE 80 -CMD ["nginx", "-g", "daemon off;"] \ No newline at end of file diff --git a/k8s/deployment.yaml b/k8s/deployment.yaml deleted file mode 100644 index 48f20fc..0000000 --- a/k8s/deployment.yaml +++ /dev/null @@ -1,22 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: examples-for-kids-app -spec: - replicas: 1 - selector: - matchLabels: - app: examples-for-kids-app - template: - metadata: - labels: - app: examples-for-kids-app - spec: - imagePullSecrets: - - name: harbor-creds # Имя секрета, который мы создали на Шаге 1 - containers: - - name: examples-for-kids-app - # __IMAGE__ - это метка, которую заменит Drone - image: __IMAGE__ - ports: - - containerPort: 80 \ No newline at end of file diff --git a/k8s/ingress.yaml b/k8s/ingress.yaml deleted file mode 100644 index 4fa109a..0000000 --- a/k8s/ingress.yaml +++ /dev/null @@ -1,23 +0,0 @@ -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: examples-for-kids-ingress -spec: - ingressClassName: traefik - tls: - - hosts: - # __HOSTNAME__ - метка для домена - - __HOSTNAME__ - # __SECRET_NAME__ - метка для имени секрета с сертификатом - secretName: __SECRET_NAME__ - rules: - - host: __HOSTNAME__ - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: examples-for-kids-app-service - port: - number: 80 \ No newline at end of file diff --git a/k8s/service.yaml b/k8s/service.yaml deleted file mode 100644 index 11803b0..0000000 --- a/k8s/service.yaml +++ /dev/null @@ -1,11 +0,0 @@ -apiVersion: v1 -kind: Service -metadata: - name: examples-for-kids-app-service -spec: - selector: - app: examples-for-kids-app - ports: - - protocol: TCP - port: 80 - targetPort: 80 \ No newline at end of file diff --git a/nginx.conf b/nginx.conf deleted file mode 100644 index 7677d44..0000000 --- a/nginx.conf +++ /dev/null @@ -1,29 +0,0 @@ -events {} - -http { - include /etc/nginx/mime.types; - default_type application/octet-stream; - - server { - listen 80; - - location /stub_status { - stub_status on; - allow all; - } - - location / { - root /usr/share/nginx/html; - index index.html; - try_files $uri $uri/ $uri.html =404; - } - - location /assets/ { - root /usr/share/nginx/html; - } - - location ~* \.(js|css|ico|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)$ { - root /usr/share/nginx/html; - } - } -} \ No newline at end of file diff --git a/service.yaml b/service.yaml new file mode 100644 index 0000000..7d4bf68 --- /dev/null +++ b/service.yaml @@ -0,0 +1,6 @@ +service: + name: examples-for-kids + type: web-frontend + +deploy: + domain: examples-for-kids.vigdorov.ru diff --git a/webpack.config.js b/webpack.config.js index b8497ac..2eae9e2 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -8,7 +8,7 @@ module.exports = { entry: './src/script.js', output: { filename: 'main.js', - path: path.resolve(__dirname, 'build'), + path: path.resolve(__dirname, 'dist'), }, devServer: { open: true,