6 Commits
Author SHA1 Message Date
austnv c17eb9584b fix: add docker push step to build.yml
Build and Deploy Backend / build-and-deploy (push) Failing after 32s
2026-06-26 13:06:13 +03:00
austnv a3c7b5bdd1 v0.7.5
Build and Deploy Backend / build-and-deploy (push) Successful in 33s
2026-06-26 12:55:38 +03:00
austnv 6c7adb1028 feat: add country_code field to hosts response 2026-06-26 12:51:45 +03:00
austnv 3661882c05 fix: volume data/tariffs.json -> data/
Build and Deploy Backend / build-and-deploy (push) Successful in 46s
2026-06-26 12:40:55 +03:00
austnv abcdb040ef fix: release author 2026-06-21 22:43:36 +03:00
austnv 718b9deebe fix: delete docker image from workflow file 2026-06-21 22:41:01 +03:00
5 changed files with 48 additions and 7 deletions
+26 -4
View File
@@ -14,6 +14,8 @@ jobs:
# 1. Клонируем код # 1. Клонируем код
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v4
with:
fetch-depth: 0 # Важно для получения всех тегов
# 2. Настраиваем Docker Buildx # 2. Настраиваем Docker Buildx
- name: Set up Docker Buildx - name: Set up Docker Buildx
@@ -27,6 +29,23 @@ jobs:
username: ${{ gitea.repository_owner }} username: ${{ gitea.repository_owner }}
password: ${{ secrets.ACCESS_TOKEN }} password: ${{ secrets.ACCESS_TOKEN }}
# 4. Собираем и пушим Docker образ
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: |
git.uvpn.shop/${{ gitea.repository }}:latest
git.uvpn.shop/${{ gitea.repository }}:${{ gitea.ref_name }}
cache-from: type=gha
cache-to: type=gha,mode=max
build-args: |
BUILD_VERSION=${{ gitea.ref_name }}
BUILD_DATE=$(date -u +'%Y-%m-%dT%H:%M:%SZ')
VCS_REF=${{ github.sha }}
# 5. Создаем Gitea Release через API
- name: Create Gitea Release via API - name: Create Gitea Release via API
run: | run: |
# Получаем описание из тега (если есть) # Получаем описание из тега (если есть)
@@ -40,7 +59,7 @@ jobs:
{ {
"tag_name": "${{ gitea.ref_name }}", "tag_name": "${{ gitea.ref_name }}",
"name": "Release ${{ gitea.ref_name }}", "name": "Release ${{ gitea.ref_name }}",
"body": "## Релиз ${{ gitea.ref_name }}\n\n📝 ${TAG_MESSAGE_ESCAPED}\n\n---\n\n**🐳 Docker образ:** \`git.uvpn.shop/${{ gitea.repository }}:${{ gitea.sha }}\`\n**🏷️ Тег:** \`${{ gitea.ref_name }}\`\n**👤 Автор:** ${{ gitea.actor }}\n\n✅ Автоматически собрано и развёрнуто", "body": "## Релиз ${{ gitea.ref_name }}\n\n📝 ${TAG_MESSAGE_ESCAPED}\n\n---\n\n**🏷️ Тег:** \`${{ gitea.ref_name }}\`\n**👤 Автор:** @${{ gitea.actor }}\n**📦 Образ:** \`git.uvpn.shop/${{ gitea.repository }}:${{ gitea.ref_name }}\`\n\n✅ Автоматически собрано и развёрнуто",
"draft": false, "draft": false,
"prerelease": false "prerelease": false
} }
@@ -70,13 +89,13 @@ jobs:
exit 1 exit 1
fi fi
# 5. Устанавливаем SSH-ключ для деплоя # 6. Устанавливаем SSH-ключ для деплоя
- name: Install SSH key - name: Install SSH key
uses: webfactory/ssh-agent@v0.9.0 uses: webfactory/ssh-agent@v0.9.0
with: with:
ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }} ssh-private-key: ${{ secrets.DEPLOY_SSH_KEY }}
# 6. Деплой на сервер # 7. Деплой на сервер
- name: Deploy on server - name: Deploy on server
run: | run: |
ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF' ssh -o StrictHostKeyChecking=no ${{ secrets.DEPLOY_USER }}@${{ secrets.DEPLOY_HOST }} << 'EOF'
@@ -86,7 +105,7 @@ jobs:
# Логинимся в реестр Gitea (чтобы docker pull мог скачать образ) # Логинимся в реестр Gitea (чтобы docker pull мог скачать образ)
echo "${{ secrets.ACCESS_TOKEN }}" | docker login git.uvpn.shop -u ${{ gitea.repository_owner }} --password-stdin echo "${{ secrets.ACCESS_TOKEN }}" | docker login git.uvpn.shop -u ${{ gitea.repository_owner }} --password-stdin
# Скачиваем свежий образ # Скачиваем свежий образ с тегом latest или конкретным тегом
docker compose pull docker compose pull
# Перезапускаем контейнер с новым образом # Перезапускаем контейнер с новым образом
@@ -95,4 +114,7 @@ jobs:
# Очищаем неиспользуемые образы # Очищаем неиспользуемые образы
docker image prune -f docker image prune -f
# Проверяем статус контейнера
docker compose ps
EOF EOF
+17
View File
@@ -1,6 +1,12 @@
FROM ghcr.io/astral-sh/uv:python3.12-alpine AS builder FROM ghcr.io/astral-sh/uv:python3.12-alpine AS builder
ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy ENV UV_COMPILE_BYTECODE=1 UV_LINK_MODE=copy
WORKDIR /app WORKDIR /app
# Аргументы для метаданных
ARG BUILD_VERSION=unknown
ARG BUILD_DATE=unknown
ARG VCS_REF=unknown
RUN --mount=type=cache,target=/root/.cache/uv \ RUN --mount=type=cache,target=/root/.cache/uv \
--mount=type=bind,source=uv.lock,target=uv.lock \ --mount=type=bind,source=uv.lock,target=uv.lock \
--mount=type=bind,source=pyproject.toml,target=pyproject.toml \ --mount=type=bind,source=pyproject.toml,target=pyproject.toml \
@@ -8,7 +14,18 @@ RUN --mount=type=cache,target=/root/.cache/uv \
FROM python:3.12-alpine FROM python:3.12-alpine
WORKDIR /app WORKDIR /app
# Метки для образа
LABEL org.opencontainers.image.title="uVPN Backend"
LABEL org.opencontainers.image.description="uVPN Shop Backend Service"
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
LABEL org.opencontainers.image.created="${BUILD_DATE}"
LABEL org.opencontainers.image.revision="${VCS_REF}"
LABEL org.opencontainers.image.source="https://git.uvpn.shop/${{ gitea.repository }}"
LABEL org.opencontainers.image.licenses="MIT"
COPY --from=builder /app/.venv /app/.venv COPY --from=builder /app/.venv /app/.venv
COPY . /app COPY . /app
ENV PATH="/app/.venv/bin:$PATH" ENV PATH="/app/.venv/bin:$PATH"
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
+1 -1
View File
@@ -3,7 +3,7 @@ services:
image: git.uvpn.shop/uvpn/backend:latest image: git.uvpn.shop/uvpn/backend:latest
container_name: uvpn-backend container_name: uvpn-backend
volumes: volumes:
- /opt/remnawave-minishop/data/tariffs.json:/app/data/tariffs.json - /opt/remnawave-minishop/data/:/app/data/
env_file: env_file:
- .env - .env
networks: networks:
+1 -1
View File
@@ -1,6 +1,6 @@
[project] [project]
name = "uvpn-backend" name = "uvpn-backend"
version = "0.7.3" version = "0.7.6"
description = "FastAPI backend with Docker for uvpn.shop" description = "FastAPI backend with Docker for uvpn.shop"
readme = "README.md" readme = "README.md"
requires-python = ">=3.12" requires-python = ">=3.12"
+3 -1
View File
@@ -3,6 +3,7 @@ import logging
from os import getenv from os import getenv
from remnawave import RemnawaveSDK from remnawave import RemnawaveSDK
from remnawave.models.hosts import GetAllHostsResponseDto from remnawave.models.hosts import GetAllHostsResponseDto
from remnawave.models.nodes import GetOneNodeResponseDto
import re import re
@@ -40,7 +41,8 @@ async def get_nodes():
{ {
'name': clean_host_name(host.remark), 'name': clean_host_name(host.remark),
'address': host.address, 'address': host.address,
'port': host.port 'port': host.port,
'country_code': (await remnawave.nodes.get_one_node(uuid=host.nodes[0])).country_code
} }
for host in hosts.root if not host.is_disabled and not host.is_hidden for host in hosts.root if not host.is_disabled and not host.is_hidden