кодекс вайб деплой
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
dv 2026-04-15 09:53:15 +03:00
parent f81021d2d0
commit 8cb0c58004
2 changed files with 47 additions and 58 deletions

View file

@ -1,21 +1,13 @@
# ─────────────────────────────────────────────────────────────────────────────
# Woodpecker CI Pipeline
# Woodpecker CI/CD
#
# Шаги:
# 1. docker-build — сборка и пуш образа (push в main)
# 2. docker-build-tag — сборка и пуш образа с semver-тегом (git tag v*)
# 3. deploy — деплой на сервер (выполняется на агенте role=work_woodpecker)
#
# Секреты (Settings → Secrets репозитория):
# forgejo_host — хост реестра, например git.example.com
# forgejo_image — полный путь образа, например git.example.com/user/intradesk-monitor
# forgejo_username — логин (обычно = gitea.actor)
# forgejo_token — токен с правом package:write
# ─────────────────────────────────────────────────────────────────────────────
# Required secrets:
# forgejo_host - registry host (example: git.example.com)
# forgejo_image - full image path (example: git.example.com/user/intradesk-monitor)
# forgejo_username - registry username
# forgejo_token - registry token with package:write
steps:
# ── 1а. Сборка при push в main ─────────────────────────────────────────────
# Build and push on main branch updates.
- name: docker-build
image: woodpeckerci/plugin-docker-buildx
settings:
@ -29,51 +21,45 @@ steps:
from_secret: forgejo_token
tags:
- latest
- "sha-${CI_COMMIT_SHA:0:8}"
# Берём inline-кэш из latest; ARG GIT_COMMIT теперь в конце Dockerfile — кэш не сбивается
- "sha-${CI_COMMIT_SHA}"
cache_from:
from_secret: forgejo_image
# mode=max кэширует все промежуточные слои (apk, npm install) в отдельный манифест
cache_to:
from_secret: forgejo_image_cache # значение: <registry>/<repo>:buildcache
rewrite_timestamp: false
build_args:
- "GIT_COMMIT=${CI_COMMIT_SHA:0:8}"
- "GIT_COMMIT=${CI_COMMIT_SHA}"
- "BUILDKIT_INLINE_CACHE=1"
when:
- event: push
branch: main
# ── 1б. Сборка при git tag v* (semver) ────────────────────────────────────
# Build and push on Git tag (release) events.
- name: docker-build-tag
image: woodpeckerci/plugin-docker-buildx
settings:
registry:
from_secret: forgejo_host
repo:
from_secret: forgejo_image_2
from_secret: forgejo_image
username:
from_secret: forgejo_username
password:
from_secret: forgejo_token
tags:
- "${CI_COMMIT_TAG}" # v1.2.3
- "${CI_COMMIT_TAG}"
- latest
- "sha-${CI_COMMIT_SHA:0:8}" # всегда — нужно для отката
- "sha-${CI_COMMIT_SHA}"
cache_from:
from_secret: forgejo_image # значение: git.example.com/user/intradesk-monitor:latest
from_secret: forgejo_image
rewrite_timestamp: false
build_args:
- "GIT_COMMIT=${CI_COMMIT_SHA:0:8}"
- "GIT_COMMIT=${CI_COMMIT_SHA}"
- "BUILDKIT_INLINE_CACHE=1"
when:
- event: tag
# ── 2. Деплой на продакшн-сервер ──────────────────────────────────────────
# Выполняется на Woodpecker-агенте с меткой role=work_woodpecker.
# Требует: репозиторий помечен «trusted» в настройках Woodpecker-сервера
# (иначе монтирование volumes запрещено).
# Deploy for both push(main) and tag events.
- name: deploy
image: docker:cli
image: docker:27-cli
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/intra_monitor:/deploy
@ -82,10 +68,8 @@ steps:
set -e
cd /deploy
# Проверяем наличие .env на сервере
test -f .env || (echo "Missing /opt/intra_monitor/.env on deploy host" && exit 1)
# Сохраняем ID текущего образа (для отката)
CONTAINER=$(docker compose ps -q intradesk-monitor 2>/dev/null | head -1)
if [ -n "$CONTAINER" ]; then
OLD_IMAGE=$(docker inspect --format='{{.Image}}' "$CONTAINER")
@ -93,16 +77,14 @@ steps:
echo "Snapshot for rollback: $OLD_IMAGE"
fi
# Удаляем legacy-контейнер со статичным именем, чтобы избежать name conflict
if docker ps -a --format '{{.Names}}' | grep -Eq '^intradesk-monitor$'; then
docker rm -f intradesk-monitor || true
fi
# Обновляем образ и перезапускаем
docker compose -p intradesk-monitor pull
docker compose -p intradesk-monitor pull intradesk-monitor
docker compose -p intradesk-monitor up -d --remove-orphans
echo "Deployed: ${CI_COMMIT_SHA:0:8} (${CI_COMMIT_MESSAGE})"
echo "Deployed commit: ${CI_COMMIT_SHA} tag: ${CI_COMMIT_TAG}"
labels:
role: work_woodpecker
when:

View file

@ -1,35 +1,42 @@
FROM node:20-alpine
# syntax=docker/dockerfile:1.7
FROM node:20-alpine AS deps
WORKDIR /app
ENV NODE_ENV=production
ENV LANG=C.UTF-8
ENV LC_ALL=C.UTF-8
# Зависимости для better-sqlite3 (нужна компиляция)
# Слой кэшируется пока не меняется базовый образ
# Build dependencies for native Node modules (better-sqlite3).
RUN apk add --no-cache python3 make g++
COPY package*.json ./
RUN npm install --omit=dev --no-audit --no-fund \
&& npm cache clean --force
# Use npm cache between builds; fallback to npm install when lock file is absent.
RUN --mount=type=cache,target=/root/.npm \
if [ -f package-lock.json ]; then \
npm ci --omit=dev --no-audit --no-fund; \
else \
npm install --omit=dev --no-audit --no-fund; \
fi
# Код приложения — копируется после зависимостей
COPY server.js ./
COPY refresh-service.js ./
COPY public/ ./public/
FROM node:20-alpine AS runtime
WORKDIR /app
# Build-аргумент объявлен ПОСЛЕ тяжёлых слоёв — не сбивает кэш при каждом коммите
ARG GIT_COMMIT=unknown
ENV GIT_COMMIT=${GIT_COMMIT}
ENV NODE_ENV=production \
LANG=C.UTF-8 \
LC_ALL=C.UTF-8 \
PORT=3000 \
DB_PATH=/data/intradesk.db
# Runtime libs required by native modules.
RUN apk add --no-cache libstdc++
COPY --from=deps /app/node_modules ./node_modules
COPY server.js refresh-service.js ./
COPY public ./public
# Папка для базы данных
RUN mkdir -p /data
EXPOSE 3000
ARG GIT_COMMIT=unknown
LABEL org.opencontainers.image.revision=$GIT_COMMIT
ENV PORT=3000
ENV DB_PATH=/data/intradesk.db
EXPOSE 3000
HEALTHCHECK --interval=30s --timeout=5s --start-period=15s --retries=3 \
CMD node -e "const http=require('http');const req=http.get('http://127.0.0.1:3000/healthz',res=>process.exit(res.statusCode===200?0:1));req.on('error',()=>process.exit(1));"