Загрузка данных
stages:
- build
- bump-version
- build-deb
- update-img
default:
image: gl.susanin.ai:5050/devops/cicd/ubuntu-builder:latest
variables:
ENTERYPOINT_BUILD_DIR: "build"
CONTROL_SERVER_BUILD_DIR: "control_server_build"
build:entrypoint:
stage: build
cache:
key: "nuitka-ccache-${CI_COMMIT_REF_SLUG}"
paths:
- .ccache/
variables:
CCACHE_DIR: "${CI_PROJECT_DIR}/.ccache/ccache"
NUITKA_CACHE_DIR: "${CI_PROJECT_DIR}/.ccache"
script:
- cd ../
- |
python3 -m nuitka "alabuga/entrypoint.py" \
--clang \
--lto=yes \
--include-package=alabuga \
--nofollow-import-to=map_navigation \
--nofollow-import-to=runtime \
--output-dir="alabuga/${ENTERYPOINT_BUILD_DIR}/" \
--remove-output
artifacts:
paths:
- ${ENTERYPOINT_BUILD_DIR}/
expire_in: 1 week
when: on_success
build:contorl_server:
stage: build
cache:
key: "nuitka-ccache-${CI_COMMIT_REF_SLUG}"
paths:
- .ccache/
variables:
CCACHE_DIR: "${CI_PROJECT_DIR}/.ccache/ccache"
NUITKA_CACHE_DIR: "${CI_PROJECT_DIR}/.ccache"
script:
- cd control_server
- |
python3 -m nuitka "app.py" \
--clang \
--lto=yes \
--include-package=routes \
--include-package=health \
--include-package=netplan_manager \
--include-package=config_manager \
--include-module=compression \
--nofollow-import-to=map_navigation \
--nofollow-import-to=runtime \
--output-dir="control_server_build" \
--remove-output
- cp -rf static control_server_build/
artifacts:
paths:
- control_server/${CONTROL_SERVER_BUILD_DIR}/
expire_in: 1 week
when: on_success
auto_increment_version:
stage: bump-version
rules:
- if: $CI_COMMIT_BRANCH == "main"
needs:
- job: build:entrypoint
- job: build:contorl_server
before_script:
- git config --global user.email "ci-bot@gl.susanin.ai"
- git config --global user.name "GitLab CI Bot"
- git remote set-url origin https://oauth2:${MY_PUSH_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git
script:
- git fetch origin ${CI_COMMIT_BRANCH}
- git checkout ${CI_COMMIT_BRANCH}
- git pull origin ${CI_COMMIT_BRANCH}
- |
python3 -c "
import json
with open('version.json', 'r') as f:
data = json.load(f)
version_parts = data['version'].split('.')
version_parts[-1] = str(int(version_parts[-1]) + 1)
new_version = '.'.join(version_parts)
data['version'] = new_version
with open('version.json', 'w') as f:
json.dump(data, f, indent=2)
print(f'New version calculated: {new_version}')
"
- NEW_VERSION=$(python3 -c "import json; print(json.load(open('version.json'))['version'])")
- echo "Target version is v${NEW_VERSION}"
- git tag -d "v${NEW_VERSION}" 2>/dev/null || true
- git push origin --delete "v${NEW_VERSION}" 2>/dev/null || true
- git add version.json
- git commit -m "bump version to ${NEW_VERSION} [skip ci]"
- git push origin ${CI_COMMIT_BRANCH}
- git tag -a "v${NEW_VERSION}" -m "Release version v${NEW_VERSION}"
- git push origin "v${NEW_VERSION}"
build_deb:
stage: build-deb
needs:
- job: build:entrypoint
artifacts: true
- job: build:contorl_server
artifacts: true
- job: auto_increment_version
artifacts: false
optional: true
variables:
GIT_STRATEGY: clone
script:
# Получаем версии из version.json
- git fetch origin ${CI_COMMIT_BRANCH}
- git checkout origin/${CI_COMMIT_BRANCH} -- version.json
- VERSION=$(jq -r '."version"' version.json)
- CORE_VERSION=$(jq -r '."core"' version.json)
- echo "Building DEB package for version ${VERSION} (app version ${VERSION}) with core ${CORE_VERSION}"
# Клонируем core-so для получения .so файлов и config
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/backend/core-so.git core-so
# Создаем структуру для DEB пакета
- mkdir -p deb-package/DEBIAN
- mkdir -p deb-package/home/ubuntu/control_server
- mkdir -p deb-package/home/ubuntu/map_navigation
- mkdir -p deb-package/home/ubuntu/venv/lib/python3.10/site-packages
- mkdir -p deb-package/etc/systemd/journald.conf.d
# Копируем control_server
- cp -rf control_server/${CONTROL_SERVER_BUILD_DIR}/* deb-package/home/ubuntu/control_server/
# Копируем entrypoint.bin
- cp -f ${ENTERYPOINT_BUILD_DIR}/entrypoint.bin deb-package/home/ubuntu/map_navigation/
- install -m 755 rtsp_restream.sh deb-package/home/ubuntu/map_navigation/rtsp_restream.sh
# Копируем .env (если есть)
- if [ -f .env ]; then cp -f .env deb-package/home/ubuntu/map_navigation/; fi
- if [ -f example.env ]; then cp -f example.env deb-package/home/ubuntu/map_navigation/.env; fi
# Копируем .so файлы из core-so
- cp -f core-so/v${CORE_VERSION}/core/map_navigation.cpython-310-aarch64-linux-gnu.so deb-package/home/ubuntu/venv/lib/python3.10/site-packages/
- cp -f core-so/v${CORE_VERSION}/core/runtime.cpython-310-aarch64-linux-gnu.so deb-package/home/ubuntu/venv/lib/python3.10/site-packages/
# Копируем config папку
- cp -rf core-so/v${CORE_VERSION}/core/config deb-package/home/ubuntu/venv/lib/python3.10/site-packages/
# Копируем version.json в static
- cp -f version.json deb-package/home/ubuntu/control_server/static/
# Ограничиваем размер постоянного системного журнала
- cp -f systemd/journald.conf.d/90-alabuga.conf deb-package/etc/systemd/journald.conf.d/
# Создаем postinst скрипт
- |
cat > deb-package/DEBIAN/postinst << EOF
#!/bin/bash
set -e
# Проверяем, доступен ли systemd (в chroot его нет)
if [ "\$(cat /proc/1/comm)" = "systemd" ]; then
SYSTEMD_AVAILABLE=true
else
SYSTEMD_AVAILABLE=false
fi
echo "Installing Alabuga update package version ${VERSION}"
# ---- Остановка сервисов (только если systemd есть) ----
if [ "\$SYSTEMD_AVAILABLE" = true ]; then
echo "Stopping services..."
for service in map-navigation.service control-server.service rtsp-restream.service mediamtx.service; do
if systemctl is-active --quiet \$service 2>/dev/null; then
systemctl stop \$service
fi
done
else
echo "Systemd not available, skipping service stop"
fi
# ---- Применяем настройки постоянного журнала ----
if [ "\$SYSTEMD_AVAILABLE" = true ]; then
systemctl restart systemd-journald || true
fi
# ---- Установка прав (всегда, ошибки игнорируем) ----
echo "Setting permissions..."
chown -R ubuntu:ubuntu /home/ubuntu/control_server 2>/dev/null || true
chown -R ubuntu:ubuntu /home/ubuntu/map_navigation 2>/dev/null || true
chown -R ubuntu:ubuntu /home/ubuntu/venv/lib/python3.10/site-packages/ 2>/dev/null || true
# ---- Делаем исполняемыми ----
chmod +x /home/ubuntu/map_navigation/entrypoint.bin 2>/dev/null || true
chmod +x /home/ubuntu/control_server/app.bin 2>/dev/null || true
# ---- Создаём симлинк на .env ----
echo "Creating symlink for .env..."
ln -sf /home/ubuntu/map_navigation/.env /home/ubuntu/.env
echo "Symlink created: /home/ubuntu/.env -> /home/ubuntu/map_navigation/.env"
# ---- Запуск сервисов (только если systemd есть) ----
if [ "\$SYSTEMD_AVAILABLE" = true ]; then
# Функция для попытки запуска сервиса
try_start_service() {
local service=\$1
echo "Attempting to start \$service..."
if systemctl start \$service 2>/dev/null; then
echo "\$service started successfully"
return 0
else
echo "Warning: \$service failed to start, continuing installation"
return 1
fi
}
echo "Starting services..."
systemctl daemon-reload
services=(
"map-navigation.service"
"control-server.service"
"rtsp-restream.service"
"mediamtx.service"
)
for service in "\${services[@]}"; do
if systemctl is-enabled --quiet \$service 2>/dev/null; then
try_start_service \$service
else
echo "Service \$service is not enabled, skipping..."
fi
done
echo "Alabuga update package ${VERSION} installed successfully"
# Финальный статус
echo "Final service status:"
for service in "\${services[@]}"; do
if systemctl is-active --quiet \$service 2>/dev/null; then
echo "\$service is running"
else
echo "\$service is not running (this may be normal)"
fi
done
else
echo "Systemd not available, skipping service management"
echo "Alabuga update package ${VERSION} installed successfully (files only)"
fi
EOF
- chmod +x deb-package/DEBIAN/postinst
# Создаем control файл
- |
cat > deb-package/DEBIAN/control << EOF
Package: alabuga-update
Version: ${VERSION}
Section: base
Priority: optional
Architecture: arm64
Maintainer: GitLab CI <ci-bot@gl.susanin.ai>
Description: Alabuga update package v${VERSION}
This package contains updated files for Alabuga system
App Version: ${VERSION}
Core version: ${CORE_VERSION}
EOF
# Создаем md5sums для проверки целостности
- cd deb-package && find home -type f -exec md5sum {} \; > DEBIAN/md5sums && cd ..
# Создаем DEB пакет
- dpkg-deb --build deb-package alabuga-update_${VERSION}_arm64.deb
artifacts:
paths:
- alabuga-update_*.deb
expire_in: 1 week
when: on_success
update-img-cokepi:
stage: update-img
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
GIT_STRATEGY: clone
needs:
- project: backend/babkin_hleb
job: build_deb
ref: master
artifacts: true
- job: build:entrypoint
artifacts: true
- job: build:contorl_server
artifacts: true
- job: auto_increment_version
- job: build_deb
artifacts: true
before_script:
- git fetch origin ${CI_COMMIT_BRANCH}
- git checkout origin/${CI_COMMIT_BRANCH} -- version.json
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/backend/core-so.git core-so
- IMG_TEMPLATE_VERSION=$(jq -r '."img-template"."cokepi"' version.json)
- CORE_VERSION=$(jq -r '."core"' version.json)
- VERSION=$(jq -r '."version"' version.json)
- MAPS=$(jq -r '."maps"' version.json)
- SIZE_M=$(du -sm /opt/img/alabuga/maps/${MAPS} | awk '{print $1}')
- MAPS_SIZE="$((SIZE_M + 1024))M"
- mkdir -p /mnt/cokepi
script:
- cp /opt/img/alabuga/template/cokepi/v${IMG_TEMPLATE_VERSION}.img /opt/img/alabuga/img/cokepi/v${VERSION}.img
- truncate -s +${MAPS_SIZE} /opt/img/alabuga/img/cokepi/v${VERSION}.img
- losetup -P /dev/loop0 /opt/img/alabuga/img/cokepi/v${VERSION}.img
- sgdisk -e /dev/loop0
- parted -s /dev/loop0 resizepart 2 100%
# - partx -u /dev/loop0
- losetup -d /dev/loop0
- losetup -P /dev/loop0 /opt/img/alabuga/img/cokepi/v${VERSION}.img
- e2fsck -f -y /dev/loop0p2
- resize2fs /dev/loop0p2
- mount /dev/loop0p2 /mnt/cokepi
- cp -rf /opt/img/alabuga/maps/${MAPS} /mnt/cokepi/home/ubuntu/data/areas/
- cp alabuga-update_${VERSION}_arm64.deb bread-tracking_${BABKINHLEB_VERSION}_arm64.deb /mnt/cokepi/tmp/
- chroot /mnt/cokepi dpkg -i /tmp/alabuga-update_${VERSION}_arm64.deb
- chroot /mnt/cokepi dpkg -i /tmp/bread-tracking_${BABKINHLEB_VERSION}_arm64.deb
after_script:
- umount /mnt/cokepi 2>/dev/null || true
- losetup -d /dev/loop0 2>/dev/null || true
update-img-orangepi:
stage: update-img
rules:
- if: $CI_COMMIT_BRANCH == "main"
variables:
GIT_STRATEGY: clone
needs:
- project: backend/babkin_hleb
job: build_deb
ref: master
artifacts: true
- job: build:entrypoint
artifacts: true
- job: build:contorl_server
artifacts: true
- job: auto_increment_version
- job: build_deb
artifacts: true
before_script:
- git fetch origin ${CI_COMMIT_BRANCH}
- git checkout origin/${CI_COMMIT_BRANCH} -- version.json
- git clone https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}/backend/core-so.git core-so
- IMG_TEMPLATE_VERSION=$(jq -r '."img-template"."orangepi"' version.json)
- CORE_VERSION=$(jq -r '."core"' version.json)
- VERSION=$(jq -r '."version"' version.json)
- MAPS=$(jq -r '."maps"' version.json)
- SIZE_M=$(du -sm /opt/img/alabuga/maps/${MAPS} | awk '{print $1}')
- MAPS_SIZE="$((SIZE_M + 1024))M"
- mkdir -p /mnt/orangepi
script:
- cp /opt/img/alabuga/template/orangepi/v${IMG_TEMPLATE_VERSION}.img /opt/img/alabuga/img/orangepi/v${VERSION}.img
- truncate -s +${MAPS_SIZE} /opt/img/alabuga/img/orangepi/v${VERSION}.img
- losetup -P /dev/loop1 /opt/img/alabuga/img/orangepi/v${VERSION}.img
- sgdisk -e /dev/loop1
- parted -s /dev/loop1 resizepart 2 100%
# - partx -u /dev/loop1
- losetup -d /dev/loop1
- losetup -P /dev/loop1 /opt/img/alabuga/img/orangepi/v${VERSION}.img
- e2fsck -f -y /dev/loop1p2
- resize2fs /dev/loop1p2
- mount /dev/loop1p2 /mnt/orangepi
- cp -rf /opt/img/alabuga/maps/${MAPS} /mnt/orangepi/home/ubuntu/data/areas/
- cp alabuga-update_${VERSION}_arm64.deb bread-tracking_${BABKINHLEB_VERSION}_arm64.deb /mnt/orangepi/tmp/
- chroot /mnt/orangepi dpkg -i /tmp/alabuga-update_${VERSION}_arm64.deb
- chroot /mnt/orangepi dpkg -i /tmp/bread-tracking_${BABKINHLEB_VERSION}_arm64.deb
after_script:
- umount /mnt/orangepi 2>/dev/null || true
- losetup -d /dev/loop1 2>/dev/null || true