Blog
Guides

Organize lots of automations with groups

DK
Dan Kowalsky
Founder ·

Your first few automations can sit side by side in one list. By the twentieth, people need to find things. Groups put related functions together, like a sub-app, both in the web app and on the command line.

Make a group

Create a Group and decorate functions with its deploy:

from typing import Literal

from callables import Group

backups = Group(
    "backups",
    title="Database backups",
    description="Postgres dumps to object storage",
    secrets=["SPACES_KEY", "SPACES_SECRET"],
)


@backups.deploy(title="Back up now", secrets=["DATABASE_URL"])
def run(env: Literal["prod", "staging"] = "prod", keep: int = 7) -> str:
    ...


@backups.deploy(title="List backups")
def list_all(days: int = 30) -> list[dict]:
    ...

In the web app, the project shows a Database backups section with both actions inside it.

Secrets for the whole group

Secrets declared on the group are given to every action in it. Above, both actions get SPACES_KEY and SPACES_SECRET, and Back up now also gets DATABASE_URL. You declare shared keys once instead of on every function.

Names

  • A group name uses lowercase letters, digits, - and _.
  • An action's full name is <group>.<name>, like backups.run. That's the name you use with call local.
  • Define each group once and import it wherever you need it. Two different Group(...) objects with the same name are an error.

Run them from the terminal

Groups become subcommands, with flags from the type hints:

call backups --help
call backups run --env staging --keep 3
call local backups.list_all -i days=7

Groups and next actions

Actions can point at each other with next, across groups too. Use the action itself, or its full name as a string, like "users.make_admin", when it's defined further down. See building an admin panel.

Moving existing functions into a group

A function's name is its identity on the platform. Moving an existing function into a group changes its name, from run to backups.run, so it starts with a fresh run history and sharing settings. Do it early, or plan for re-sharing.

Plain @deploy functions keep working next to groups. They appear in the project without a section.

Turn your scripts into tools your team can run

Add @deploy to a Python function and push. Your team gets a form, schedules and run history.

See how it works