Workflow деплоя в Portainer (создание/обновление стека photo-editor через API)
This commit is contained in:
64
.gitea/workflows/deploy.yml
Normal file
64
.gitea/workflows/deploy.yml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
name: deploy-portainer
|
||||||
|
|
||||||
|
# Ручной запуск: вкладка Actions → Run workflow.
|
||||||
|
# Создаёт или обновляет стек photo-editor на Portainer
|
||||||
|
# (https://ptr.byte-mate.ru) из deploy/docker-compose.yml.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: deploy
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Deploy stack to Portainer
|
||||||
|
env:
|
||||||
|
PORTAINER_URL: https://ptr.byte-mate.ru
|
||||||
|
PORTAINER_API_KEY: ${{ secrets.PORTAINER_API_KEY }}
|
||||||
|
STACK_NAME: photo-editor
|
||||||
|
# Если не задано — берётся первый endpoint из /api/endpoints
|
||||||
|
ENDPOINT_ID: ${{ vars.PORTAINER_ENDPOINT_ID }}
|
||||||
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
if [ -z "${PORTAINER_API_KEY:-}" ]; then
|
||||||
|
echo "::error::Секрет PORTAINER_API_KEY не задан"
|
||||||
|
echo "::error::Создайте API-ключ в Portainer (Account → API keys) и добавьте его в секреты репозитория."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
AUTH="Authorization: Bearer ${PORTAINER_API_KEY}"
|
||||||
|
|
||||||
|
# Определяем endpoint (окружение Docker), если не задан вручную
|
||||||
|
if [ -z "${ENDPOINT_ID:-}" ]; then
|
||||||
|
ENDPOINT_ID=$(curl -fsSk -H "$AUTH" "$PORTAINER_URL/api/endpoints" | jq -r '.[0].Id')
|
||||||
|
echo "Endpoint id автоопределён: ${ENDPOINT_ID}"
|
||||||
|
fi
|
||||||
|
echo "Endpoint id: ${ENDPOINT_ID}"
|
||||||
|
|
||||||
|
# Ищем существующий стек
|
||||||
|
STACK_ID=$(curl -fsSk -H "$AUTH" \
|
||||||
|
"$PORTAINER_URL/api/stacks?filters=%7B%22EndpointId%22%3A${ENDPOINT_ID}%7D" \
|
||||||
|
| jq -r ".[] | select(.Name==\"${STACK_NAME}\") | .Id" | head -1 || true)
|
||||||
|
|
||||||
|
if [ -n "${STACK_ID}" ]; then
|
||||||
|
echo "Обновляю стек ${STACK_NAME} (id=${STACK_ID})"
|
||||||
|
curl -fsSk -X PUT -H "$AUTH" \
|
||||||
|
-F "StackFileContent=@deploy/docker-compose.yml" \
|
||||||
|
"$PORTAINER_URL/api/stacks/${STACK_ID}?endpointId=${ENDPOINT_ID}" >/dev/null
|
||||||
|
else
|
||||||
|
echo "Создаю стек ${STACK_NAME}"
|
||||||
|
curl -fsSk -X POST -H "$AUTH" \
|
||||||
|
-F "Name=${STACK_NAME}" \
|
||||||
|
-F "EndpointId=${ENDPOINT_ID}" \
|
||||||
|
-F "StackFileContent=@deploy/docker-compose.yml" \
|
||||||
|
"$PORTAINER_URL/api/stacks/create/standalone" >/dev/null
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "✅ Стек ${STACK_NAME} развёрнут на ${PORTAINER_URL}"
|
||||||
23
deploy/docker-compose.yml
Normal file
23
deploy/docker-compose.yml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# Файл развёртывания на хосте Portainer.
|
||||||
|
# Используется workflow .gitea/workflows/deploy.yml (публикует образ,
|
||||||
|
# уже собранный workflow build-container).
|
||||||
|
services:
|
||||||
|
photo-editor:
|
||||||
|
image: git.byte-mate.ru/coder/photo-editor:latest
|
||||||
|
pull_policy: always
|
||||||
|
container_name: kadr-photo-editor
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
# История версий — именованный том, переживает обновление стека
|
||||||
|
- kadr-history:/app/history
|
||||||
|
# Аутентификация и конфиг Codex с хоста Portainer.
|
||||||
|
# Альтернатива — переменная OPENAI_API_KEY ниже.
|
||||||
|
- /root/.codex:/root/.codex
|
||||||
|
environment:
|
||||||
|
- COMFY_URL=http://192.168.31.240:8188
|
||||||
|
# - OPENAI_API_KEY=${OPENAI_API_KEY}
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
|
volumes:
|
||||||
|
kadr-history:
|
||||||
Reference in New Issue
Block a user