TWIR Deploy Notify is a small Rust CLI that turns the latest This Week in Rust issue into a series of Telegram posts.
What it does:
- Finds the newest TWIR Markdown issue file in
this-week-in-rust/content. - Parses the issue into sections.
- Generates Telegram friendly messages:
- one Telegram post per section
- automatically splits sections and overly long lines to fit Telegram limits
- appends the issue link (derived from issue number and date) to each post
- Sends the posts to the configured Telegram chat.
- Pins the first sent message and removes the service notification.
- Cleans up any previously generated
output_*.mdfiles before writing new ones.
- TWIR issues are long, and Telegram has message size limits.
- You want consistent formatting and splitting without manual editing.
- You want a repeatable way to publish the latest issue to one or more chats.
- Rust toolchain (stable).
- A local clone of
rust-lang/this-week-in-rustwith thecontentdirectory available. - Telegram bot token and chat id.
Clone TWIR into a twir subdirectory (sparse checkout of content):
git clone --depth 1 --filter=blob:none --sparse https://github.com/rust-lang/this-week-in-rust twir && cd twir && git sparse-checkout set content && cd ..cargo run --bin twir-deploy-notify -- twir/content/<file-name>.mdGenerate plain text instead of Telegram markup:
cargo run --bin twir-deploy-notify -- --plain twir/content/<file-name>.mdEnable detailed logs:
RUST_LOG=info cargo run --bin twir-deploy-notify -- twir/content/<file-name>.mdEnvironment variables for sending to Telegram:
DEV_BOT_TOKENandDEV_CHAT_IDdev chat credentialsPROD_BOT_TOKENandPROD_CHAT_IDproduction chat credentials- If
*_CHAT_IDis numeric, it is automatically prefixed with-100when sending requests to Telegram
- If
TWIR_SKIP_DEVELOPER_SENDoptional boolean that skips the developer sendTWIR_SKIP_PRODUCTION_SENDoptional boolean that skips the production send
If neither credential pair is fully configured, the CLI exits with an error. Partial configuration (only one variable from a pair) is also treated as an error.
See LICENSE_QQRM_LAPOCHKA.
Production delivery stores its checkpoint in the separate delivery-state branch using GitHub's contents API. The workflow token is scoped to the restore/send steps and consumed by the checkpoint helper; checkout does not persist credentials. The remote file is a versioned JSON envelope containing base64-encoded application state and a pending SHA-256 digest. No token, chat ID, or API response is stored.
Before each send, a pending operation is committed. Only an acknowledged send promotes the application state and clears pending in the same API write. Authentication, network, corrupt-state and checkpoint conflicts stop delivery. A missing branch is the only first-run condition; existing legacy state is migrated where available. A missing file in an existing state branch is an error. Caches and run artifacts are no longer the authority after migration.
A timeout, process crash, or failed checkpoint after an acknowledgement leaves pending set. Subsequent scheduled runs stop before sending. This provides safe interruption, not exactly-once delivery: Telegram has no idempotency key for this operation.
To reconcile:
- Pause the production workflow and inspect the failed run and Telegram channel. Do not blindly retry or remove state.
- Read the checkpoint file on
delivery-stateand decode itsstatefield locally. If the pending message was delivered, add its confirmed entry to the application state. If it was definitely not delivered, retain the previous application state. If the outcome is still unknown, leave pending intact. - Encode the reconciled state, set
pendingto null, and update that same file with its current blob SHA to reject concurrent changes. Keep tokens, chat IDs and response bodies out of the commit. Record the evidence in the recovery change. - For local runs, update the local state consistently and remove only its
.pendingsidecar after reconciliation. Resume the workflow. Already confirmed entries are skipped.
Cargo and Actions updates share a weekly Dependabot maintenance batch with a seven-day cooldown; security fixes use a dedicated group. Rust toolchain updates remain tracked separately. Native auto-merge requires the exact PR head to pass ci-gate and workflow-security-gate, with no review requirement. Failed or skipped required jobs cannot pass a gate. The privileged controller reads metadata only; it never checks out PR code or consumes PR artifacts.
Existing release and delivery triggers are preserved. A merge performed using GITHUB_TOKEN does not guarantee a follow-up push workflow. Guaranteed automatic post-merge releases need a separate GitHub App token or verified release controller; this change does not claim that coverage.
TWIR checkpoints contain only content/target hashes, part count and acknowledged Telegram message IDs. A changed unfinished issue or target is rejected. The existing channel pin guard remains active; pinning happens after the entire issue is durable. Only a service message whose chat and pinned message ID match is eligible for deletion. For reconciliation, append a verified message ID to the ordered message_ids list; never invent one.
Every mutation compares the remote blob SHA with the snapshot recorded at restore (or the prior successful write). A stale runner cannot replace newer progress, even across branches; a SHA conflict stops before another send.