1
0
Fork 0
mirror of https://git.anardil.net/austin/devbot.git synced 2026-10-24 15:52:05 +00:00
A lightweight, cross-platform, inspectable task scheduler
  • Haskell 99.3%
  • Shell 0.6%
  • Makefile 0.1%
Find a file
Gandalf- 542af05b9b homepage is code.anardil.net, public.anardil.net is retired (#289)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-21 00:02:20 -04:00
Devbot devbot: a monitor's ignore prunes what it matches 2026-10-12 12:43:28 -07:00
etc keep the last good schedule when a config reload fails 2026-09-19 09:27:46 -07:00
src devbot: make ready, the baseline warnings, export lists, Config by name 2026-10-10 21:36:20 -07:00
test devbot: a monitor's ignore prunes what it matches 2026-10-12 12:43:28 -07:00
.gitignore gitignore 2026-06-22 08:13:52 -07:00
CLAUDE.md devbot: build apocrypha at 1b5dd9b, a serverless query's lock beside the database 2026-10-12 15:00:12 -07:00
devbot.cabal homepage is code.anardil.net, public.anardil.net is retired (#289) 2026-10-21 00:02:20 -04:00
hie.yaml toolchain stuff 2026-05-30 18:43:18 -07:00
LICENSE Initial commit 2019-01-12 15:45:39 -08:00
Makefile devbot: build apocrypha at e422e27 (#223's crash fixes), optimized 2026-10-11 16:16:10 -07:00
README.md devbot: a monitor's ignore prunes what it matches 2026-10-12 12:43:28 -07:00
stack.yaml devbot: build apocrypha at 1b5dd9b, a serverless query's lock beside the database 2026-10-12 15:00:12 -07:00
stack.yaml.lock devbot: build apocrypha at 1b5dd9b, a serverless query's lock beside the database 2026-10-12 15:00:12 -07:00

Devbot

Devbot is a command orchestration tool, similar to cron. Actions are sequences of commands, potentially requiring a condition, that are run at intervals and checked for errors. Devbot is platform independent, and runs on Linux, Windows, MacOS, and BSD.

Devbot's goals are to be: simple to use, robust, easily inspectable, and lightweight.

devbot usage:
  start       - start devbot
  daemon      - start devbot in the background
  stop        - stop devbot and all services

  list        - show a list summary of runtime data and config
  table       - show a table summary of runtime data and config
  status      - give a single character summary of run state

  schema      - show the config file schema
  config      - show the config file path
  parse <exp> - show how devbot will interpet an interval expression

Devbot

Devbot works by loading a config file into an internal database on start up, building a schedule to match the requirements provided, and waiting for the right time to run each action.

The internal database contains the current configuration, runtime information, and meta data. If devbot is interrupted, runtime information is not lost. This means that an action meant to run in 5 hours will still run on schedule if devbot is stopped for a hour and started again.

Events are periodic tasks. Events do not need to be short lived, but another instance of the event will not be started if the previous run has not yet completed. The action field may be a string or array of strings, which will be executed by the system's default shell. On Linux, this is usually /bin/sh. On Windows, this is usually cmd.

Except on Windows, each item in an array action definition will be executed in a single shell, like you would expect to happen with a shell or batch script. This allows usage like the following:

- cd $HOME/my-project
- git fetch
- git pull

On Linux, devbot will convert this to an equivalent of the following, so you don't have to!

{ cd $HOME/my-project; } && { git fetch; } && { git pull; }

If you want each item in the action field to be run simultaneously instead of serially in a single shell, you can set the parallel option to true. This example shows how you can have devbot run several rsync jobs in parallel.

events:
  backup-my-stuff:
    action:
      - rsync -av ~/Documents   some-machine:backups/Documents
      - rsync -av ~/Pictures   other-machine:backups/Pictures
      - rsync -av ~/Downloads remote-machine:backups/Downloads
    parallel: true
    interval: daily

If an action exits with failure, it's treated as an error and the event will be retried. Retries backoff exponentially to limit system thrashing when a command cannot successfully complete. devbot list and devbot table show events with errors in red.

A require names a command from requirements that must succeed before the event runs; until it does, devbot checks again every 30 seconds. A name requirements doesn't define is a config error. A monitor command runs before the action, which only runs when the command's output has changed since the last good run; a monitor command that fails is an error, like a failed action. Both are checked once, as a run begins: a run with several actions doesn't check them again between actions, so a requirement can't stop it partway. Requirement and monitor commands get 30 seconds: past that, the command and everything it started are killed, and it counts as failed. A monitor path runs the action when anything under it has changed since the last good run started, so an action that writes there (a git commit) wants an ignore regex such as /\.git(/|$). ignore is matched against each path the walk builds (path with ~ expanded, then / and each name below it) and prunes what it matches: a matched directory isn't read at all, so nothing under it can run the action or fail the check, and a matched path is never a change. Otherwise a path that is missing, or a directory under it that can't be read, is an error too.

Services are long running tasks, usually other daemons. It's not expected that services restart or exit. If they do, they will be restarted by devbot. When the config changes or devbot stops, the service and everything it started are stopped. If devbot itself is killed, its services keep running, and the next devbot starts them again beside the old ones. A service whose command can't be run is reported, and tried again a minute later. There are many service management tools and frameworks available; devbot's goal is to be simple and cross platform. If you want to run syncthing on a couple Linux and Windows machines, the devbot config would be identical:

services:
  syncthing:
    action: syncthing -no-browser -verbose

Example configuration

events:

  dotfiles-fetch:
    action:
      - cd ~/working/devbot
      - git fetch
    interval: twice per day
    require:  network

  backup-my-stuff:
    action:
      - rsync -av ~/Documents   some-machine:backups/Documents
      - rsync -av ~/Pictures   other-machine:backups/Pictures
      - rsync -av ~/Downloads remote-machine:backups/Downloads
    parallel: true
    interval: every other day
    require:  network

services:
  syncthing:
    action: syncthing

requirements:
  network: nc -w 1 -z 8.8.8.8 53

devbot list

Shows the current state of all actions, how often they run, any errors, any requirements, what commands are run, and the next time to run.

dotfiles-fetch
    cd ~/DotFiles
    git fetch
    every 12 hours, took 1 second, requires network, next in 19 hours

backup-my-stuff:
    rsync -av ~/Documents   some-machine:backups/Documents
    rsync -av ~/Pictures   other-machine:backups/Pictures
    rsync -av ~/Downloads remote-machine:backups/Downloads
    every 48 hours, took 3 minutes, requires network, next in 32 hours

service: syncthing
    uptime 5 days, 3 hours

devbot table

Shows another, more condensed, view of the current runtime information.

         events         |    every     |     next     |     last     |  require  |  options
                        |              |              |              |           |
        heatbeat        |     hour     |  25 minutes  |   1 second   |           |
     internet-check     |  5 minutes   |   1 minute   |  9 seconds   |           |
  public-files-publish  |   6 hours    |   4 hours    |  47 seconds  |  network  |
     sensor-create      |  15 minutes  |  10 minutes  |  4 seconds   |           |
     sensor-publish     |  15 minutes  |  11 minutes  |  3 seconds   |  network  |    P
      share-zipper      |     day      |   5 hours    |  25 seconds  |           |
    timelapse-create    |     hour     |  25 minutes  |  3 seconds   |           |


  services  |  uptime   |            action
            |           |
  database  |  7 hours  |  apocrypha-server --headless

devbot status

Shows the current state of the devbot daemon as a single character, useful for embedding in your tmux status line.

  • Running ✓
  • Stopped ✗

devbot schema

Shows the accepted configuration file schema, for easy reference when making config file modifications.

devbot parse

Devbot is very flexible in how it can interpret event intervals. You can use the devbot parse command to test that expressions can be parsed, and verify that they evaluate to what you expect.

$ devbot parse every hour
parsed as: 3600 seconds
listed as: 1 hour

$ devbot parse hourly
parsed as: 3600 seconds
listed as: 1 hour

$ devbot parse every other hour
parsed as: 7200 seconds
listed as: 2 hours

$ devbot parse twice hourly
parsed as: 1800 seconds
listed as: 30 minutes

$ devbot parse twice every 100 years
parsed as: 1451520000 seconds
listed as: 50 years

$ devbot parse 89 times per month
parsed as: 27182 seconds
listed as: 7 hours

$ devbot parse 309 times per week
parsed as: 1957 seconds
listed as: 32 minutes