27f9ceb038
PR Checks / test-and-build (pull_request) Successful in 27m45s
Slow ARM64 runners hit the default timeout while initializing the container image scan after pulling. Extend the timeout so image scans can complete reliably.
196 lines
7.5 KiB
YAML
196 lines
7.5 KiB
YAML
name: Deploy Telegram Bot
|
|
|
|
on:
|
|
push:
|
|
branches:
|
|
- main
|
|
|
|
env:
|
|
VERSION: 3.11.0
|
|
|
|
jobs:
|
|
# ЧАСТЬ 1: Собираем образы и кладем в Gitea (чтобы делиться с ребятами)
|
|
build-and-push:
|
|
runs-on: ubuntu-latest # Замени на метку твоего раннера, если она другая
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Login to Gitea Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: git.codeanddice.ru # НАПРИМЕР: gitea.my-server.com
|
|
username: toutsu
|
|
password: ${{ secrets.GIT_TOKEN }}
|
|
|
|
- name: Build Bot image
|
|
run: |
|
|
docker build \
|
|
--label "org.opencontainers.image.source=https://git.codeanddice.ru/${{ gitea.repository }}" \
|
|
-f src/GmRelay.Bot/Dockerfile \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-bot:latest \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-bot:${{ env.VERSION }} \
|
|
.
|
|
|
|
- name: Push Bot image
|
|
run: |
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-bot:latest
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-bot:${{ env.VERSION }}
|
|
|
|
- name: Build Discord Bot image
|
|
run: |
|
|
docker build \
|
|
--label "org.opencontainers.image.source=https://git.codeanddice.ru/${{ gitea.repository }}" \
|
|
-f src/GmRelay.DiscordBot/Dockerfile \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-discord-bot:latest \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-discord-bot:${{ env.VERSION }} \
|
|
.
|
|
|
|
- name: Push Discord Bot image
|
|
run: |
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-discord-bot:latest
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-discord-bot:${{ env.VERSION }}
|
|
|
|
- name: Build Web image
|
|
run: |
|
|
docker build \
|
|
--label "org.opencontainers.image.source=https://git.codeanddice.ru/${{ gitea.repository }}" \
|
|
-f src/GmRelay.Web/Dockerfile \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-web:latest \
|
|
-t git.codeanddice.ru/toutsu/gmrelay-web:${{ env.VERSION }} \
|
|
.
|
|
|
|
- name: Push Web image
|
|
run: |
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-web:latest
|
|
docker push git.codeanddice.ru/toutsu/gmrelay-web:${{ env.VERSION }}
|
|
|
|
# ЧАСТЬ 1.5: Сканируем собранные образы на уязвимости
|
|
scan-images:
|
|
needs: build-and-push
|
|
runs-on: ubuntu-latest
|
|
steps:
|
|
- name: Login to Gitea Container Registry
|
|
uses: docker/login-action@v3
|
|
with:
|
|
registry: git.codeanddice.ru
|
|
username: toutsu
|
|
password: ${{ secrets.GIT_TOKEN }}
|
|
|
|
- name: Install Trivy
|
|
run: |
|
|
# Install Trivy from the official Docker image instead of the
|
|
# upstream install.sh. Rationale:
|
|
# 1. install.sh resolves the positional tag against the
|
|
# GitHub releases API; when a release is unpublished or
|
|
# yanked, the script fails with
|
|
# `unable to find '<tag>' - use 'latest' or see ...`
|
|
# when the release once existed. We hit this with
|
|
# v0.71.0.
|
|
# 2. Docker Hub tags are content-addressed and rarely
|
|
# removed, so a pinned image tag is much more stable.
|
|
# 3. The image is multi-arch (linux/amd64, linux/arm64,
|
|
# linux/ppc64le, linux/s390x) so the same tag works on
|
|
# the GitHub-hosted runner and on the ARM64 Pi runner.
|
|
set -euo pipefail
|
|
TRIVY_VERSION="0.70.0"
|
|
docker pull --quiet "aquasec/trivy:${TRIVY_VERSION}"
|
|
docker create --name trivy-tmp "aquasec/trivy:${TRIVY_VERSION}"
|
|
docker cp trivy-tmp:/usr/local/bin/trivy /usr/local/bin/trivy
|
|
docker rm trivy-tmp >/dev/null
|
|
chmod +x /usr/local/bin/trivy
|
|
trivy --version
|
|
|
|
- name: Pull images for scan
|
|
run: |
|
|
docker pull git.codeanddice.ru/toutsu/gmrelay-bot:${{ env.VERSION }}
|
|
docker pull git.codeanddice.ru/toutsu/gmrelay-discord-bot:${{ env.VERSION }}
|
|
docker pull git.codeanddice.ru/toutsu/gmrelay-web:${{ env.VERSION }}
|
|
|
|
- name: Scan Bot image
|
|
run: |
|
|
trivy image \
|
|
--timeout 30m \
|
|
--severity HIGH,CRITICAL \
|
|
--exit-code 1 \
|
|
--format table \
|
|
git.codeanddice.ru/toutsu/gmrelay-bot:${{ env.VERSION }}
|
|
|
|
- name: Scan Discord Bot image
|
|
run: |
|
|
trivy image \
|
|
--timeout 30m \
|
|
--severity HIGH,CRITICAL \
|
|
--exit-code 1 \
|
|
--format table \
|
|
git.codeanddice.ru/toutsu/gmrelay-discord-bot:${{ env.VERSION }}
|
|
|
|
- name: Scan Web image
|
|
run: |
|
|
trivy image \
|
|
--timeout 30m \
|
|
--severity HIGH,CRITICAL \
|
|
--exit-code 1 \
|
|
--format table \
|
|
git.codeanddice.ru/toutsu/gmrelay-web:${{ env.VERSION }}
|
|
|
|
# ЧАСТЬ 2: Запускаем эти образы на самом сервере
|
|
deploy:
|
|
needs: scan-images
|
|
runs-on: ubuntu-latest # Тот же локальный раннер
|
|
steps:
|
|
- name: Checkout repository
|
|
uses: actions/checkout@v4
|
|
|
|
- name: Create .env file with secrets
|
|
run: |
|
|
echo "TELEGRAM_BOT_TOKEN=${{ secrets.TELEGRAM_BOT_TOKEN }}" > .env
|
|
echo "POSTGRES_PASSWORD=${{ secrets.POSTGRES_PASSWORD }}" >> .env
|
|
echo "DISCORD_BOT_TOKEN=${{ secrets.DISCORD_BOT_TOKEN }}" >> .env
|
|
echo "TELEGRAM_BOT_USERNAME=${{ secrets.TELEGRAM_BOT_USERNAME }}" >> .env
|
|
echo "TELEGRAM_MINI_APP_URL=${{ secrets.TELEGRAM_MINI_APP_URL }}" >> .env
|
|
echo "DISCORD_CLIENT_ID=${{ secrets.DISCORD_CLIENT_ID }}" >> .env
|
|
echo "DISCORD_CLIENT_SECRET=${{ secrets.DISCORD_CLIENT_SECRET }}" >> .env
|
|
echo "DISCORD_REDIRECT_URI=${{ secrets.DISCORD_REDIRECT_URI }}" >> .env
|
|
|
|
- name: Deploy Containers
|
|
run: |
|
|
# Авторизуемся локальным докером в нашей Gitea
|
|
docker login git.codeanddice.ru/ -u toutsu -p ${{ secrets.GIT_TOKEN }}
|
|
|
|
# Pull гарантирует, что мы получили нужную версию.
|
|
docker compose pull bot discord web
|
|
|
|
# Запускаем! Флаг -d оставит их работать в фоне.
|
|
docker compose up -d
|
|
|
|
# Ждём, пока сервисы перейдут в healthy или упадут
|
|
SERVICES="bot discord web"
|
|
MAX_WAIT=40
|
|
INTERVAL=5
|
|
ELAPSED=0
|
|
|
|
while [ $ELAPSED -lt $MAX_WAIT ]; do
|
|
NOT_HEALTHY=0
|
|
for svc in $SERVICES; do
|
|
HEALTH=$(docker compose ps $svc --format="{{.Health}}" 2>/dev/null | head -n1)
|
|
if [ "$HEALTH" != "healthy" ]; then
|
|
STATE=$(docker compose ps $svc --format="{{.State}}" 2>/dev/null | head -n1)
|
|
echo "❌ $svc not healthy yet (state: ${STATE:-unknown})"
|
|
NOT_HEALTHY=$((NOT_HEALTHY + 1))
|
|
fi
|
|
done
|
|
|
|
if [ $NOT_HEALTHY -eq 0 ]; then
|
|
echo "✅ All services are healthy!"
|
|
exit 0
|
|
fi
|
|
|
|
sleep $INTERVAL
|
|
ELAPSED=$((ELAPSED + INTERVAL))
|
|
done
|
|
|
|
echo "⏰ Timed out waiting for services to become healthy"
|
|
docker compose ps
|
|
exit 1
|