This commit is contained in:
parent
f81021d2d0
commit
8cb0c58004
2 changed files with 47 additions and 58 deletions
|
|
@ -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:
|
||||
|
|
|
|||
47
Dockerfile
47
Dockerfile
|
|
@ -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));"
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue