diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 8694eb3..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,60 +0,0 @@ ---- -on: - release: - types: [created] - -jobs: - build: - runs-on: ubuntu-latest - env: - REGISTRY_HOST: ghcr.io - steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - name: Extract version - shell: bash - run: | - echo "name=$(echo ${GITHUB_REPOSITORY#*/})" >> "$GITHUB_OUTPUT" - echo "ver=$(echo ${GITHUB_REF#refs/*/})" >> "$GITHUB_OUTPUT" - echo "minor_ver=$(TMP_VAR=${GITHUB_REF#refs/*/}; echo ${TMP_VAR%.*})" >> "$GITHUB_OUTPUT" - echo "major_ver=$(TMP_VAR=${GITHUB_REF#refs/*/}; echo ${TMP_VAR%.*.*})" >> "$GITHUB_OUTPUT" - id: extract_name_and_version - - uses: docker/setup-qemu-action@c7c53464625b32c7a7e944ae62b3e17d2b600130 # v3 - - uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3 - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - username: ${{ secrets.DOCKERHUB_USER }} - password: ${{ secrets.DOCKERHUB_PASS }} - - uses: docker/login-action@c94ce9fb468520275223c153574b00df6fe4bcc9 # v3 - with: - registry: ${{ env.REGISTRY_HOST }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - run: sed -i 's/0.1.0/'"${{ steps.extract_name_and_version.outputs.ver }}"'/' pyproject.toml - - run: sed -i 's/0.1.0/'"${{ steps.extract_name_and_version.outputs.ver }}"'/' feedforbot/__version__.py - - uses: docker/build-push-action@10e90e3645eae34f1e60eeb005ba3a3d33f178e8 # v6 - with: - context: . - file: ./Dockerfile - push: true - tags: | - "${{ env.REGISTRY_HOST }}/${{ github.repository }}:latest" - "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.major_ver }}" - "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }}" - "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.ver }}" - "${{ github.repository }}:latest" - "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.major_ver }}" - "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }}" - "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.ver }}" - labels: | - org.opencontainers.image.title=feedforbot - org.opencontainers.image.description=Forward links from RSS/Atom feeds to messengers - org.opencontainers.image.source=https://github.com/${{ github.repository }} - org.opencontainers.image.url=https://github.com/${{ github.repository }} - org.opencontainers.image.authors=Aleksandr Shpak - org.opencontainers.image.version=${{ steps.extract_name_and_version.outputs.ver }} - org.opencontainers.image.created=${{ github.event.release.created_at }} - org.opencontainers.image.revision=${{ github.sha }} - org.opencontainers.image.licenses=MIT - provenance: false - cache-from: type=registry,ref=${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }} - cache-to: type=inline diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index c315cd5..54dbe92 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -7,21 +7,92 @@ on: push: branches: [main] paths: - - 'tmfeed/config.yml' + - 'tmfeed/feedforbot.config.yml' jobs: + build: + name: ๐Ÿ—๏ธ Build image + runs-on: ubuntu-latest + if: >- + github.event_name == 'release' + && !contains(github.event.release.tag_name, 'rc') + env: + REGISTRY_HOST: ghcr.io + steps: + - name: ๐Ÿ“ฅ Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: ๐Ÿท๏ธ Extract version + shell: bash + run: | + echo "name=$(echo ${GITHUB_REPOSITORY#*/})" >> "$GITHUB_OUTPUT" + echo "ver=$(echo ${GITHUB_REF#refs/*/})" >> "$GITHUB_OUTPUT" + echo "minor_ver=$(TMP_VAR=${GITHUB_REF#refs/*/}; echo ${TMP_VAR%.*})" >> "$GITHUB_OUTPUT" + echo "major_ver=$(TMP_VAR=${GITHUB_REF#refs/*/}; echo ${TMP_VAR%.*.*})" >> "$GITHUB_OUTPUT" + id: extract_name_and_version + - name: ๐Ÿงฐ Set up QEMU + uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4 + - name: ๐Ÿงฐ Set up Buildx + uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4 + - name: ๐Ÿ” Login to Docker Hub + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 + with: + username: ${{ secrets.DOCKERHUB_USER }} + password: ${{ secrets.DOCKERHUB_PASS }} + - name: ๐Ÿ” Login to GHCR + uses: docker/login-action@4907a6ddec9925e35a0a9e82d7399ccc52663121 # v4 + with: + registry: ${{ env.REGISTRY_HOST }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: โœ๏ธ Patch version in pyproject.toml + run: sed -i 's/0.1.0/'"${{ steps.extract_name_and_version.outputs.ver }}"'/' pyproject.toml + - name: โœ๏ธ Patch version in __version__.py + run: sed -i 's/0.1.0/'"${{ steps.extract_name_and_version.outputs.ver }}"'/' feedforbot/__version__.py + - name: ๐Ÿณ Build and push image + uses: docker/build-push-action@bcafcacb16a39f128d818304e6c9c0c18556b85f # v7 + with: + context: . + file: ./Dockerfile + push: true + tags: | + "${{ env.REGISTRY_HOST }}/${{ github.repository }}:latest" + "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.major_ver }}" + "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }}" + "${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.ver }}" + "${{ github.repository }}:latest" + "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.major_ver }}" + "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }}" + "${{ github.repository }}:${{ steps.extract_name_and_version.outputs.ver }}" + labels: | + org.opencontainers.image.title=feedforbot + org.opencontainers.image.description=Forward links from RSS/Atom feeds to messengers + org.opencontainers.image.source=https://github.com/${{ github.repository }} + org.opencontainers.image.url=https://github.com/${{ github.repository }} + org.opencontainers.image.authors=Aleksandr Shpak + org.opencontainers.image.version=${{ steps.extract_name_and_version.outputs.ver }} + org.opencontainers.image.created=${{ github.event.release.created_at }} + org.opencontainers.image.revision=${{ github.sha }} + org.opencontainers.image.licenses=MIT + provenance: false + cache-from: type=registry,ref=${{ env.REGISTRY_HOST }}/${{ github.repository }}:${{ steps.extract_name_and_version.outputs.minor_ver }} + cache-to: type=inline + deploy: + name: ๐Ÿš€ Deploy tmfeed runs-on: ubuntu-latest + needs: [build] if: >- - github.event_name == 'push' - || ( - github.event_name == 'release' - && !contains(github.event.release.tag_name, 'rc') + always() + && (needs.build.result == 'success' || needs.build.result == 'skipped') + && ( + github.event_name == 'push' + || !contains(github.event.release.tag_name, 'rc') ) steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 + - name: ๐Ÿ“ฅ Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 - - name: Determine image tag + - name: ๐Ÿท๏ธ Determine image tag id: image run: | if [ "${{ github.event_name }}" = "release" ]; then @@ -30,24 +101,24 @@ jobs: echo "tag=latest" >> "$GITHUB_OUTPUT" fi - - name: Set up SSH + - name: ๐Ÿ”‘ Set up SSH run: | mkdir -p ~/.ssh echo "${{ secrets.DEPLOY_SSH_KEY }}" > ~/.ssh/id_ed25519 chmod 600 ~/.ssh/id_ed25519 ssh-keyscan -H ${{ vars.DEPLOY_HOST }} >> ~/.ssh/known_hosts - - name: Install Ansible + - name: ๐Ÿงฐ Install Ansible run: pip install ansible - - name: Run deploy playbook + - name: ๐Ÿš€ Run deploy playbook working-directory: tmfeed env: FEEDFORBOT_TOKEN: ${{ secrets.FEEDFORBOT_TOKEN }} FEEDFORBOT_SENTRY: ${{ secrets.FEEDFORBOT_SENTRY }} FEEDFORBOT_IMAGE: "ghcr.io/${{ github.repository }}:${{ steps.image.outputs.tag }}" run: >- - ansible-playbook deploy.yml + ansible-playbook deploy.playbook.yml -i "${{ vars.DEPLOY_HOST }}," -u "${{ vars.DEPLOY_USER }}" --private-key ~/.ssh/id_ed25519 diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 680a0c8..1ba9c7c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,6 +6,7 @@ on: jobs: lint: + name: ๐Ÿ” Lint runs-on: ubuntu-latest strategy: matrix: @@ -19,11 +20,17 @@ jobs: - "linters" - "tests" steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - name: ๐Ÿ“ฅ Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: ๐Ÿงฐ Set up uv + uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6 + - name: ๐Ÿ Set up Python ${{ matrix.PYTHON_VERSION }} + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: ${{ matrix.PYTHON_VERSION }} - - uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2 - - run: uv sync --group dev - - run: just ${{ matrix.JUST_JOB }} + - name: ๐Ÿงฐ Set up just + uses: extractions/setup-just@dd310ad5a97d8e7b41793f8ef055398d51ad4de6 # v2 + - name: ๐Ÿ“ฆ Sync dependencies + run: uv sync --group dev + - name: โœ… Run ${{ matrix.JUST_JOB }} + run: just ${{ matrix.JUST_JOB }} diff --git a/.github/workflows/pypi.yml b/.github/workflows/pypi.yml index c658d2c..dad1117 100644 --- a/.github/workflows/pypi.yml +++ b/.github/workflows/pypi.yml @@ -5,22 +5,30 @@ on: jobs: build: + name: ๐Ÿ“ฆ Publish to PyPI runs-on: ubuntu-latest steps: - - uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4 - - uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6 - - uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5 + - name: ๐Ÿ“ฅ Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + - name: ๐Ÿงฐ Set up uv + uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6 + - name: ๐Ÿ Set up Python + uses: actions/setup-python@a309ff8b426b58ec0e2a45f0f869d46889d02405 # v6 with: python-version: "3.12" - - name: Extract version + - name: ๐Ÿท๏ธ Extract version shell: bash run: | echo "ver=$(echo ${GITHUB_REF#refs/*/})" >> "$GITHUB_OUTPUT" id: extract_version - - run: sed -i 's/0.1.0/'"${{ steps.extract_version.outputs.ver }}"'/' pyproject.toml - - run: sed -i 's/0.1.0/'"${{ steps.extract_version.outputs.ver }}"'/' feedforbot/__version__.py - - run: uv build - - run: uv publish + - name: โœ๏ธ Patch version in pyproject.toml + run: sed -i 's/0.1.0/'"${{ steps.extract_version.outputs.ver }}"'/' pyproject.toml + - name: โœ๏ธ Patch version in __version__.py + run: sed -i 's/0.1.0/'"${{ steps.extract_version.outputs.ver }}"'/' feedforbot/__version__.py + - name: ๐Ÿ—๏ธ Build package + run: uv build + - name: ๐Ÿš€ Publish to PyPI + run: uv publish env: UV_PUBLISH_USERNAME: ${{ secrets.PYPI_LOGIN }} UV_PUBLISH_PASSWORD: ${{ secrets.PYPI_PASS }} diff --git a/Justfile b/Justfile index c19d97a..4c8f77f 100644 --- a/Justfile +++ b/Justfile @@ -27,4 +27,4 @@ help: # Deploy tmfeed to VDS tmfeed-deploy: - set -a && source tmfeed/.env && set +a && ansible-playbook -i tmfeed/inventory.ini tmfeed/deploy.yml + set -a && source tmfeed/.env && set +a && ansible-playbook -i tmfeed/inventory.ini tmfeed/deploy.playbook.yml diff --git a/README.md b/README.md index 6f0d373..18726a9 100644 --- a/README.md +++ b/README.md @@ -1,47 +1,32 @@ -FeedForBot -========== +FeedForBot ๐Ÿ“ก +============= [![PyPI Version](https://img.shields.io/pypi/v/feedforbot.svg)](https://pypi.python.org/pypi/feedforbot) [![PyPI Downloads](https://img.shields.io/pypi/dm/feedforbot.svg)](https://pypi.python.org/pypi/feedforbot) [![Docker Pulls](https://img.shields.io/docker/pulls/shpaker/feedforbot)](https://hub.docker.com/r/shpaker/feedforbot) [![GHCR](https://img.shields.io/badge/GHCR-feedforbot-blue?logo=github)](https://ghcr.io/shpaker/feedforbot) +[![Lint](https://github.com/shpaker/feedforbot/actions/workflows/lint.yml/badge.svg)](https://github.com/shpaker/feedforbot/actions/workflows/lint.yml) [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) -Monitors RSS/Atom feeds on a cron schedule and forwards new entries -to Telegram. Supports multiple feeds, Jinja2 message templates, -pluggable caching (files, in-memory, Redis) to avoid duplicate -sends, and optional Sentry integration for error tracking. - -Features --------- - -- **Multiple feeds** โ€” run any number of listener/transport pairs, - each with its own cron schedule -- **Jinja2 templates** โ€” full control over message formatting with - access to article fields (`{{ TITLE }}`, `{{ URL }}`, `{{ TEXT }}`, - `{{ CATEGORIES }}`, `{{ AUTHORS }}`, etc.). Templates run in a - sandbox with HTML autoescape, so article fields with `&`, `<`, `>` - are safe by default -- **Pluggable cache** โ€” files (`~/.feedforbot/`), in-memory, or - Redis (shared across instances), selected via `--cache-dsn`; - first run populates the cache silently to avoid flooding the - channel. Optional `cache_limit` caps retention per scheduler -- **Built-in healthcheck** โ€” optional HTTP endpoint at `/health` - for Docker/Kubernetes probes -- **Resilient delivery** โ€” Telegram `429 flood-wait` responses are - retried automatically after `Retry-After`; malformed feed entries - are skipped with a warning instead of failing the whole tick -- **Graceful shutdown** โ€” `SIGTERM` / `SIGINT` drain in-flight ticks - and close HTTP/Redis/file handles cleanly (second signal forces - immediate exit) -- **Sentry integration** โ€” optional error tracking via `sentry-sdk` -- **Docker ready** โ€” multi-arch images on GHCR and Docker Hub, - runs as non-root (`appuser`) -- **Protocol-driven** โ€” extend with custom listeners, transports, - and cache backends by implementing simple protocols - -Installation ------------- +> RSS/Atom in, Telegram out. ๐Ÿช„ Fresh entries arrive, templated into +> tidy messages, deduped via your cache of choice โ€” on a cron schedule, +> with a healthcheck and graceful shutdown baked in. + +โœจ Features +----------- + +- ๐Ÿ“ฌ **Multiple feeds** โ€” any number of listeners/transports, each on its own cron +- ๐ŸŽจ **Jinja2 templates** โ€” sandbox + HTML autoescape, full access to article fields +- ๐Ÿ’พ **Pluggable cache** โ€” files, in-memory, or Redis; first run silent to avoid flood +- ๐Ÿฉบ **Healthcheck** โ€” HTTP `/health` for Docker/Kubernetes probes +- ๐Ÿ›ก๏ธ **Resilient delivery** โ€” auto-retry on Telegram flood-wait, skip malformed entries +- ๐Ÿงน **Graceful shutdown** โ€” SIGTERM/SIGINT drain ticks and close handles cleanly +- ๐Ÿ› **Sentry integration** โ€” optional error tracking +- ๐Ÿณ **Docker ready** โ€” multi-arch GHCR + Docker Hub images, runs as non-root +- ๐Ÿงฉ **Protocol-driven** โ€” custom listeners/transports/caches via simple protocols + +๐Ÿ“ฆ Installation +--------------- Requires **Python 3.10+**. @@ -49,16 +34,16 @@ Requires **Python 3.10+**. pip install feedforbot -U ``` -For the full CLI (Click, structlog, YAML config, Sentry): +For the full CLI (Click, structlog, YAML config, Sentry, Redis): ```commandline pip install "feedforbot[cli]" -U ``` -Quick start ------------ +๐Ÿš€ Quick start +-------------- -### As a library +### ๐Ÿ As a library ```python from feedforbot import Scheduler, TelegramBotTransport, RSSListener @@ -74,7 +59,7 @@ scheduler = Scheduler( scheduler.run() # blocks, checks the feed every 5 minutes ``` -### Async โ€” multiple schedulers +### โšก Async โ€” multiple schedulers ```python import asyncio @@ -106,7 +91,7 @@ async def main() -> None: asyncio.run(main()) ``` -### CLI with YAML config +### ๐Ÿ“ CLI with YAML config Create a `schedulers.yml` โ€” a top-level list of listener+transport entries: @@ -151,9 +136,9 @@ feedforbot --verbose schedulers.yml ``` On the first run the cache is populated without sending messages, -so existing feed entries won't flood the channel. +so existing feed entries won't flood the channel. ๐Ÿคซ -#### Config reference +#### ๐Ÿ“‹ Config reference Each list entry supports: @@ -172,7 +157,7 @@ Each list entry supports: An empty top-level list is rejected at parse time. -#### Cache CLI flag +#### ๐Ÿ’พ Cache CLI flag Cache backend selection is a CLI concern (not part of the schedulers file). `--cache-dsn` takes a URL-style DSN; scheme selects the backend: @@ -184,7 +169,7 @@ Cache backend selection is a CLI concern (not part of the schedulers file). | `memory:` | In-process cache (lost on restart) | | `redis://host:6379/0` | Shared Redis cache (requires `feedforbot[cli]` or `pip install redis`). Useful for multi-instance deployments and docker-compose setups where a separate Redis container holds state. | -#### Template variables +#### ๐Ÿงฉ Template variables All fields from `ArticleModel` are available in uppercase: @@ -203,7 +188,7 @@ Templates render in a Jinja2 sandbox with HTML autoescape enabled `<`, `>` are escaped automatically โ€” you don't need to guard against Telegram rejecting the message for invalid HTML. -#### CLI options +#### ๐ŸŽ›๏ธ CLI options | Option | Description | |--------|-------------| @@ -215,11 +200,11 @@ Telegram rejecting the message for invalid HTML. | `--healthcheck-port` | Port for the HTTP healthcheck server (disabled when unset) | | `--healthcheck-host` | Bind host for the healthcheck server; default `127.0.0.1`. Use `0.0.0.0` inside containers when the port is exposed to the host | -Docker ------- +๐Ÿณ Docker +--------- Images are published to both **GHCR** and **Docker Hub** on every -release. Tags follow semver: `latest`, `4`, `4.0`, `4.0.0`. +release. Tags follow semver: `latest`, `5`, `5.0`, `5.0.0`. ```commandline docker run -v $(pwd)/schedulers.yml:/schedulers.yml \ @@ -233,8 +218,8 @@ docker run -v $(pwd)/schedulers.yml:/schedulers.yml \ The container runs as a non-root user (`appuser`). -Healthcheck ------------ +๐Ÿฉบ Healthcheck +-------------- The CLI includes a built-in HTTP healthcheck server. Pass `--healthcheck-port` to expose a lightweight endpoint that responds @@ -266,8 +251,8 @@ services: retries: 3 ``` -Docker Compose with Redis -------------------------- +๐Ÿงฑ Docker Compose with Redis +---------------------------- For multi-instance deployments or when you want cache state to survive container rebuilds without a host volume for JSON files, @@ -312,9 +297,9 @@ services: ``` A working Ansible playbook that deploys this layout is in -[tmfeed/deploy.yml](tmfeed/deploy.yml). +[tmfeed/deploy.playbook.yml](tmfeed/deploy.playbook.yml). -License -------- +๐Ÿ“„ License +---------- [MIT](LICENSE) diff --git a/feedforbot/py.typed b/feedforbot/py.typed new file mode 100644 index 0000000..e69de29 diff --git a/pyproject.toml b/pyproject.toml index 69df369..517b61a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,6 +5,22 @@ description = "Forward links from RSS/Atom feeds to messengers" authors = [{ name = "Aleksandr Shpak", email = "shpaker@gmail.com" }] readme = "README.md" requires-python = ">=3.10" +classifiers = [ + "Development Status :: 5 - Production/Stable", + "Intended Audience :: Developers", + "Intended Audience :: System Administrators", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Programming Language :: Python :: 3.14", + "Topic :: Communications :: Chat", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: News/Diary", + "Typing :: Typed", +] dependencies = [ "croniter>=6.0", "beautifulsoup4>=4.13,<5", diff --git a/tmfeed/deploy.yml b/tmfeed/deploy.playbook.yml similarity index 67% rename from tmfeed/deploy.yml rename to tmfeed/deploy.playbook.yml index ec330a4..6c532dd 100644 --- a/tmfeed/deploy.yml +++ b/tmfeed/deploy.playbook.yml @@ -4,7 +4,7 @@ vars: feedforbot_token: "{{ lookup('env', 'FEEDFORBOT_TOKEN') }}" feedforbot_sentry: "{{ lookup('env', 'FEEDFORBOT_SENTRY') | default('', true) }}" - feedforbot_image: "{{ lookup('env', 'FEEDFORBOT_IMAGE') | default('ghcr.io/shpaker/feedforbot:latest', true) }}" + feedforbot_image: "{{ lookup('env', 'FEEDFORBOT_IMAGE') }}" feedforbot_dir: "/home/{{ ansible_user }}/feedforbot" tasks: @@ -13,6 +13,11 @@ msg: "FEEDFORBOT_TOKEN is not set in .env" when: feedforbot_token == "" + - name: Fail if image is not set + fail: + msg: "FEEDFORBOT_IMAGE is not set" + when: feedforbot_image == "" + - name: Install required packages become: true apt: @@ -62,7 +67,7 @@ - name: Deploy config.yml copy: - src: "config.yml" + src: "feedforbot.config.yml" dest: "{{ feedforbot_dir }}/config.yml" mode: "0644" register: config_changed @@ -75,41 +80,10 @@ register: token_injected - name: Deploy docker-compose.yml - copy: + template: + src: "feedforbot.compose.yml.j2" dest: "{{ feedforbot_dir }}/docker-compose.yml" mode: "0644" - content: | - services: - redis: - image: redis:7-alpine - container_name: feedforbot-redis - restart: always - volumes: - - ./redis_data:/data - command: ["redis-server", "--save", "60", "1", "--appendonly", "no"] - healthcheck: - test: ["CMD", "redis-cli", "ping"] - interval: 10s - timeout: 3s - retries: 3 - start_period: 5s - - feedforbot: - image: {{ feedforbot_image }} - container_name: feedforbot - restart: always - depends_on: - redis: - condition: service_healthy - volumes: - - ./config.yml:/config.yml:ro - command: -v --cache-dsn redis://redis:6379/0 --healthcheck-port 8080 {{ ('--sentry ' + feedforbot_sentry) if feedforbot_sentry != '' else '' }} /config.yml - healthcheck: - test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"] - interval: 30s - timeout: 5s - retries: 3 - start_period: 10s register: compose_changed - name: Start or recreate feedforbot @@ -150,7 +124,8 @@ - name: Show status debug: - msg: - - "FeedForBot is running!" - - "{{ health_result.stdout }}" - - "{{ compose_status.stdout }}" + msg: "FeedForBot is running! {{ health_result.stdout }}" + + - name: Show docker compose ps + debug: + var: compose_status.stdout_lines diff --git a/tmfeed/feedforbot.compose.yml.j2 b/tmfeed/feedforbot.compose.yml.j2 new file mode 100644 index 0000000..9341ca4 --- /dev/null +++ b/tmfeed/feedforbot.compose.yml.j2 @@ -0,0 +1,31 @@ +services: + redis: + image: redis:7-alpine + container_name: feedforbot-redis + restart: always + volumes: + - ./redis_data:/data + command: ["redis-server", "--save", "60", "1", "--appendonly", "no"] + healthcheck: + test: ["CMD", "redis-cli", "ping"] + interval: 10s + timeout: 3s + retries: 3 + start_period: 5s + + feedforbot: + image: {{ feedforbot_image }} + container_name: feedforbot + restart: always + depends_on: + redis: + condition: service_healthy + volumes: + - ./config.yml:/config.yml:ro + command: -v --cache-dsn redis://redis:6379/0 --healthcheck-port 8080 {{ ('--sentry ' + feedforbot_sentry) if feedforbot_sentry != '' else '' }} /config.yml + healthcheck: + test: ["CMD", "python", "-c", "import urllib.request; urllib.request.urlopen('http://localhost:8080/health')"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s diff --git a/tmfeed/config.yml b/tmfeed/feedforbot.config.yml similarity index 100% rename from tmfeed/config.yml rename to tmfeed/feedforbot.config.yml