From a15bfba3309a5395e4c621d6677d9b95ecc0e12e Mon Sep 17 00:00:00 2001 From: Egor Deev Date: Mon, 5 Oct 2026 19:16:13 +0000 Subject: [PATCH] =?UTF-8?q?Docker,=20CI=20=D0=B8=20=D0=BB=D0=B8=D1=86?= =?UTF-8?q?=D0=B5=D0=BD=D0=B7=D0=B8=D1=8F=20MIT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CI: ruff и обработка тестовых кружочков (со звуком и без, градиент и блюр). Образ по тегу v* публикуется в GHCR и dcr.deev.su. --- .env.example | 2 ++ .github/workflows/ci.yml | 48 ++++++++++++++++++++++++++++++++++++ .github/workflows/docker.yml | 42 +++++++++++++++++++++++++++++++ .gitignore | 6 +++++ Dockerfile | 19 ++++++++++++++ LICENSE | 21 ++++++++++++++++ compose.yaml | 11 +++++++++ 7 files changed, 149 insertions(+) create mode 100644 .env.example create mode 100644 .github/workflows/ci.yml create mode 100644 .github/workflows/docker.yml create mode 100644 .gitignore create mode 100644 Dockerfile create mode 100644 LICENSE create mode 100644 compose.yaml diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..7fcca50 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +# Токен бота от @BotFather +BOT_TOKEN=123456:your-token diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..9f7c3ec --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,48 @@ +name: CI + +on: + push: + branches: [main] + pull_request: + +jobs: + check: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.12" + - run: pip install ruff==0.14.0 -r requirements.txt + - name: Ruff (синтаксис и ошибки) + run: ruff check --select E9,F code + - name: Обработка тестового кружочка (градиент и блюр, со звуком и без) + working-directory: code + env: + BOT_TOKEN: "123456:TEST" + run: | + python - <<'PY' + import os, shutil, subprocess + import imageio_ffmpeg + from scripts import Movie, process_frames + import handlers # noqa: F401 — бот импортируется без ошибок + + ff = imageio_ffmpeg.get_ffmpeg_exe() + src = { + "audio": ["-f", "lavfi", "-i", "testsrc=size=240x240:rate=30:duration=1", + "-f", "lavfi", "-i", "sine=duration=1", "-shortest"], + "silent": ["-f", "lavfi", "-i", "color=c=black:size=240x240:rate=30:duration=1"], + } + for name, args in src.items(): + for mode in ("grad", "blur"): + path = f"/tmp/{name}-{mode}" + shutil.rmtree(path, ignore_errors=True) + os.makedirs(path + "/frames"); os.makedirs(path + "/background") + subprocess.run([ff, "-loglevel", "error", "-y", *args, "-c:v", "libx264", + "-pix_fmt", "yuv420p", path + "/v.mp4"], check=True) + movie = Movie(path + "/v.mp4", "v", path) + assert movie.split_into_frames() + result = movie.unity_into_video(process_frames(path + "/frames", path + "/background", mode)) + assert os.path.getsize(result) > 0 + print(name, mode, "ok") + PY diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml new file mode 100644 index 0000000..c3927ed --- /dev/null +++ b/.github/workflows/docker.yml @@ -0,0 +1,42 @@ +name: Docker + +on: + push: + tags: ["v*"] + workflow_dispatch: + +jobs: + image: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + steps: + - uses: actions/checkout@v4 + - uses: docker/setup-buildx-action@v3 + - uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - uses: docker/login-action@v3 + with: + registry: dcr.deev.su + username: ${{ secrets.ZOT_USERNAME }} + password: ${{ secrets.ZOT_PASSWORD }} + - id: meta + uses: docker/metadata-action@v5 + with: + images: | + ghcr.io/edeev/circlechek + dcr.deev.su/edeev/circlechek + tags: | + type=semver,pattern={{version}} + type=semver,pattern={{major}}.{{minor}} + type=raw,value=latest + - uses: docker/build-push-action@v6 + with: + context: . + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b2504c0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.env +__pycache__/ +*.pyc +data/*/* +!data/*/.gitkeep +data/*.log diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..941a252 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,19 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 + +WORKDIR /app +COPY requirements.txt . +RUN pip install --no-cache-dir -r requirements.txt + +COPY code/ code/ +RUN useradd --create-home --uid 1000 app \ + && mkdir -p data/circles data/video_notes data/videos \ + && chown -R app:app /app +USER app +VOLUME ["/app/data"] + +# пути к данным в коде — относительно папки code/ (../data) +WORKDIR /app/code +CMD ["python", "bot.py"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..1051c59 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Egor Deev + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000..cda362d --- /dev/null +++ b/compose.yaml @@ -0,0 +1,11 @@ +services: + bot: + build: . + image: ghcr.io/edeev/circlechek:latest + env_file: .env + volumes: + - data:/app/data + restart: unless-stopped + +volumes: + data: