Skip to content

feat: --once single-cycle mode + commented config templates - #29

Merged
SebastienPittet merged 3 commits into
masterfrom
feat/run-once-and-config-examples
Oct 26, 2026
Merged

SebastienPittet merged 3 commits into
masterfrom
feat/run-once-and-config-examples

Conversation

@SebastienPittet

Copy link
Copy Markdown
Owner

Why

configuration.toml does not exist anywhere — it never was committed, and it is git-ignored on
purpose because it holds the bot token. So after cloning there is no template, and the README only
shows the TOML inline in prose. Two consequences: the entry point is not obvious, and there is
nothing to copy.

What

1. Commented templates (configuration.toml.example, .env.example)

Both carry the feed list from the README, as a real list rather than a single URL:

RSS_URLS = [
    "https://korben.info/feed",
    "https://www.ictjournal.ch/taxonomy/term/404/feed",
    ...
]

.env.example uses the comma-separated form and says why one line beats a quoted multi-line value
once a shell or a ConfigMap renders it. Every key is documented: units (TIME_INTERVAL_MIN in
minutes, ENTRY_MAX_TIME_OLD in seconds), @channel vs numeric id, the admin requirement, and the
optional LOG_LEVEL / HEARTBEAT_FILE.

Why .example and not .toml/.env: the names configuration.example.toml and .env are both
matched by existing .gitignore rules (lines 132 and 168), so a template with either name would be
silently uncommittable and would never reach the repo.

2. Two tests so the templates cannot rot

test_toml_example_committed_in_repo_is_valid parses the committed TOML;
test_env_example_committed_in_repo_is_valid asserts .env.example yields the exact same feed
tuple
. Edit one list without the other, or break a URL, and CI fails. An example nobody executes is
an example that lies.

3. --once: one cycle, then exit

Validating a token or a new feed meant starting the scheduler and watching logs for minutes.

python -m bot --once     # 0 published OK, 1 cycle crashed, 2 bad configuration

It short-circuits before the signal handlers and the scheduler are installed, honours
HEARTBEAT_FILE, and takes the same injectable clock as run_cycle, so the tests are deterministic
(the fixture clock is in the future relative to the wall clock, which is_recent correctly rejects —
that surfaced immediately and is why the signature carries now).

Written TDD: test(cli): … (red) (ImportError on run_once), then feat(cli): … (green).

4. README "Running the bot"

bot/ is a package, so python bot/telegram_rss_bot.py fails with
ModuleNotFoundError: No module named 'bot'. Documented: python -m bot from the repository root —
the same command as the Docker ENTRYPOINT and Kubernetes — plus the fact that --config resolves
against the current directory, not the repo, which is the usual cause of a confusing
"Missing required environment variables" after editing a TOML file that is then silently ignored.

Checks

ruff check, ruff format --check, mypy clean; 89 passed, of which 5 are the new --once
tests and 2 the config-template guards.

Deliberately not done

No configuration.toml is created or committed, and .gitignore is untouched: ignoring the real
file is the point. Nothing here changes runtime behaviour unless you pass --once.

Validating a bot token or a new feed meant starting the scheduler and watching logs for minutes. --once runs exactly one cycle and returns: 0 on success, 1 when the cycle crashed, 2 on a configuration error (unchanged). It short-circuits before signal and scheduler setup, so it never leaves a stray timer behind, and it honours HEARTBEAT_FILE like the scheduled job.
…point

configuration.toml and .env are git-ignored by design (they hold the bot token), so a fresh clone had no template at all and the README only showed the TOML inline. Adds configuration.toml.example and .env.example, both carrying the feed list from the README as a TOML array (and the comma-separated form for env), plus a 'Running the bot' section covering python -m bot, --config resolution and --once.

Two tests parse both committed examples and assert they yield the identical 8-feed list, so the templates rot loudly instead of quietly.
@SebastienPittet
SebastienPittet merged commit 7ecfd10 into master Oct 26, 2026
11 checks passed
SebastienPittet added a commit that referenced this pull request Oct 26, 2026
#30)

PR #29 carried size/S (pull-request-size) and size/L (custom) at once; the two also disagree on capitalisation (size/m vs size/M), one label name to GitHub.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant