Skip to main content

smart-restart

Rules-as-config restart decider for Python services. Don't restart your whole stack on every git push.

License Status Python

The problem

You ship a one-line bug fix to one service in your monorepo. Your deploy script restarts everything — bot, API, worker, scheduler — and you eat 30 seconds of cold starts and dropped connections, every time.

Most CI/CD scripts pick between two extremes:

  • Restart everything always. Safe, but wasteful and slow.
  • Hand-maintained "if file in dir then restart X." Fast, but rots silently when imports cross boundaries: someone refactors utils/db.py and forgets that worker/jobs.py imports it, the worker keeps the old code, you get a Heisenbug at 3 a.m.

smart-restart is the middle ground: a small decider that takes the list of changed files and a YAML rule set, then prints which actions are needed. Optionally, it walks the AST-derived import graph in reverse so editing a leaf utility correctly triggers restarts for every service that imports it.

It does not run the actions. Your deploy script does. smart-restart just decides.

Quick start

pip install smart-restart  # coming with v0.1.0

Write a restart-rules.yaml:

actions:
  pip_install:
    order: 10        # lower = runs earlier
  restart_api:
    order: 20

rules:
  - pattern: "requirements.txt"
    actions: [pip_install, restart_api]
  - pattern: "src/**"
    actions: [restart_api]
  - pattern: "**/*.md"
    actions: []      # explicitly do nothing

fallback: [restart_api]   # for files that match no rule

Pipe a diff into it:

$ git diff --name-only HEAD~1 HEAD | smart-restart
pip_install
restart_api

That's the output your deploy script consumes. Wire it into bash, Ansible, GitHub Actions, anything that takes stdout.

Import-chain expansion (the interesting bit)

The base decider only knows about files you literally changed. That misses the case where a leaf module changes and dependents don't.

Pass --root <project> and smart-restart will parse every .py file under <project>, build a static import graph, and expand the changed file list to include every transitive importer:

src/
  utils/db.py        # you changed this
  api/handlers.py    # imports utils.db
  worker/jobs.py     # imports utils.db
$ echo "src/utils/db.py" | smart-restart --root src --show-expanded
INFO: import-chain expansion added 2 file(s):
  + smart_restart/api/handlers.py
  + smart_restart/worker/jobs.py
restart_api
restart_worker

If restart-rules.yaml only matches src/api/** to restart_api and src/worker/** to restart_worker, the expansion ensures both fire even though only db.py was in the diff.

--root and src-layout

If your project uses src-layout (code under src/your_pkg/), pass --root src, not --root .. The graph indexes files by their dotted module name; the dotted name has to match what your imports actually say (from your_pkg.foo resolves to <root>/your_pkg/foo.py).

Layout Use
src/your_pkg/... (src-layout) --root src
your_pkg/... (flat / package at root) --root .
Multiple roots (e.g. services/api/, services/worker/) run once per root, merge actions yourself

Why a separate decider

  • One source of truth. Change restart-rules.yaml, every script that consumes the decider stays in sync.
  • Composable. Pipe it into bash, Ansible, GitHub Actions, anything that takes stdout. No framework lock-in.
  • Diffable. Restart rules live in version control, not buried in a shell script.
  • Testable. Pure function, no side effects, hermetic.

Configuration reference

actions:                 # required: action name -> {order: int}
  <name>:
    order: <int>         # lower = runs earlier; default 100

rules:                   # required: list, evaluated top-down, first match wins
  - pattern: <glob>      # ** matches across directories, * within one segment
    actions: [<name>...] # actions to fire (use [] to explicitly skip)

fallback:                # what to do for files that match no rule
  none                   # default: contribute no actions
  | all                  # fire every declared action
  | [<name>...]          # fire just these

First-match-wins semantics: each file is matched against rules top-to-bottom, only the first hit contributes. This lets you put a narrow **/*.md → [] rule above a broad src/** → [restart_api] rule.

Status

🚧 Alpha — extracted from a closed-source dogfood project (~2 years of daily use).

Done in v0.1:

  • Generic rule engine with first-match-wins semantics
  • YAML-declared actions (no hardcoded service names)
  • Import-chain reverse closure (AST-based)
  • Glob patterns with ** recursion
  • Pure decider — no execution, no side effects
  • 37 unit tests, fixture-driven

Deferred to v0.2+:

  • LLM fallback for unmatched files (the upstream project has it; needs to be re-cast as a plugin to keep v0.1 dependency-free)
  • Multi-root graph merge in one invocation
  • Auto-detection of src-layout from pyproject.toml
  • Star-import edge tracking at the symbol level

License

MIT

Metadata

Release files for smart-restart 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for smart-restart 0.1.0
File Size Uploaded Provenance
smart_restart-0.1.0.tar.gz 37.6 kB With provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for smart-restart 0.1.0
File Interpreter ABI Platform
smart_restart-0.1.0-py3-none-any.whl Python 3 none any Details

Total release size: 49.0 kB

Release files / smart_restart-0.1.0.tar.gz

Download URL smart_restart-0.1.0.tar.gz
Size 37.6 kB
Tags Source
SHA-256 checksum
How to use checksums
0d925c5f856b46b4fd9255185c0a82e0fd800acc5fa78dea18da0f40ed161e94
BLAKE2b-256 checksum
How to use checksums
516d6c6590230cb58730e3a783b08f7bd1dc86ea212ff2dcded5279ab5889b48
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

Release files / smart_restart-0.1.0-py3-none-any.whl

Download URL smart_restart-0.1.0-py3-none-any.whl
Size 11.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
fb0207b342f831506dc569eb86779f2b7e0c48d8160b1ceb74ad0a1348a431fa
BLAKE2b-256 checksum
How to use checksums
fba1919a3b516cd869ecd10c4f754fda6f7e8b1a1a9d33823c7125ba64386a88
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

Security for smart-restart 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for smart_restart-0.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on May 5, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page