notiflow 2.0.0

Telegram notifier for CI and the terminal — a GitHub Action and a standalone CLI in one binary
Documentation

notiflow

CI crates.io docs.rs License: MIT

Send a Telegram message when something finishes — a workflow job, a deploy script, a long build.

The GitHub Action and the notiflow CLI are the same Rust binary, so a template that renders in your workflow renders identically in your terminal. No bash, no curl, no jq, no Python: one static executable, on Linux, macOS and Windows.

Documentation · Getting started · Migrating from v1 · Документация на русском

As a GitHub Action

- uses: jtprogru/notiflow@v2
  if: always()
  with:
    bot_token: ${{ secrets.TELEGRAM_BOT_TOKEN }}
    chat_id: ${{ secrets.TELEGRAM_CHAT_ID }}
    status: ${{ job.status }}

if: always() matters — without it the step is skipped exactly when the job failed, which is when you wanted to hear about it. status has to be passed explicitly: a composite action's input defaults cannot read the job context.

Full input and output tables are in the Action reference.

As a CLI

brew install jtprogru/tap/notiflow     # or: cargo install notiflow

export NOTIFLOW_BOT_TOKEN=123456789:AAHdqTcv...
export NOTIFLOW_CHAT_ID=-1001234567890

notiflow send --message "deploy finished"
./deploy.sh | notiflow send --stdin
notiflow render --template '{{.StatusEmoji}} {{.Repo}} @ {{.ShortSha}}' --explain
notiflow whoami

Outside a workflow, {{.Repo}}, {{.Branch}} and {{.ShortSha}} come from the local git checkout, so the same template works in both places.

Release archives are published for seven targets — including static musl builds for alpine and scratch containers — with sha256 checksums, keyless cosign signatures and SLSA build provenance on every release, and detached GPG signatures from v2.0.0 onward. See Installation for the signing key and the verification commands.

What it does for you

Placeholder values are escaped for the active parse mode, so a branch named fix/a.b-c cannot inject markup. Messages over Telegram's 4096-unit limit are cut between markup tokens rather than through them, and open HTML tags are closed. Rate limits are honoured, Retry-After is read from both the body and the header, backoff carries jitter, and a 4xx is never retried. The bot token is masked in the workflow log and scrubbed from every stream the binary writes.

A delivery failure exits 0 by default: notiflow's opinion about Telegram should not overwrite the result your build actually produced. Set fail_on_error when it should.

Upgrading from v1

For a workflow that sends to one chat, @v1 → @v2 is a drop-in change: same inputs, same outputs, same exit codes 10–16.

The one breaking change is that chat_id no longer accepts a comma-separated list — use a job matrix or repeat the step, and you get per-chat outputs and per-chat status instead of a lossy CSV. Everything else that changed is a fix to behaviour that was already broken. All of it is spelled out in the migration guide, and every difference is recorded in a parity corpus that runs both implementations against each other on every commit.

The v1 tag keeps pointing at the bash implementation on the v1.x branch, which receives security fixes only.

Development

make build      # the debug binary
make ci         # lint, test, parity, generated-doc check — what CI runs
make help       # everything else

No workflow contains a build command of its own; every CI step calls a make target, so a red build is reproducible with one command. See Contributing.

License

MIT — see LICENSE.