Skip to content

Migrating from Invoke

Invoke (pyinvoke.org) is a Python library for managing shell tasks. Jake provides similar functionality without requiring Python.

InvokeJake
tasks.pyJakefile
@task decoratortask name:
c.run("cmd")Direct command
@task(pre=[dep])[dep]
invoke taskjake task
from invoke import task
@task
def build(c):
"""Build the application"""
c.run("go build -o app")
# Build the application
task build:
go build -o app
from invoke import task
@task
def clean(c):
c.run("rm -rf dist/")
@task
def install(c):
c.run("pip install -r requirements.txt")
@task(pre=[clean, install])
def build(c):
c.run("python setup.py build")
task clean:
rm -rf dist/
task install:
pip install -r requirements.txt
task build: [clean, install]
python setup.py build
from invoke import task
@task
def deploy(c, env="staging", force=False):
"""Deploy to environment"""
cmd = f"./deploy.sh {env}"
if force:
cmd += " --force"
c.run(cmd)

Usage: invoke deploy --env=production --force

task deploy env="staging" force="":
@desc "Deploy to environment"
@if eq({{force}}, "true")
./deploy.sh {{env}} --force
@else
./deploy.sh {{env}}
@end

Usage: jake deploy env=production force=true

@task
def test(c, verbose=False, coverage=False):
cmd = "pytest"
if verbose:
cmd += " -v"
if coverage:
cmd += " --cov"
c.run(cmd)
task test verbose="" coverage="":
@if eq({{verbose}}, "true")
@if eq({{coverage}}, "true")
pytest -v --cov
@else
pytest -v
@end
@else
@if eq({{coverage}}, "true")
pytest --cov
@else
pytest
@end
@end

Or simpler with positional args:

task test:
pytest {{$@}}

Usage: jake test -v --cov

from invoke import task, Collection
@task
def build(c):
c.run("docker build -t myapp .")
@task
def push(c):
c.run("docker push myapp")
docker = Collection("docker")
docker.add_task(build)
docker.add_task(push)
ns = Collection()
ns.add_collection(docker)

Usage: invoke docker.build

docker.jake
task build:
docker build -t myapp .
task push:
docker push myapp
# Jakefile
@import "docker.jake" as docker
task release: [docker.build, docker.push]
echo "Released!"

Usage: jake docker.build

from invoke import task, Config
config = Config(defaults={
"app": {"name": "myapp", "port": 8080}
})
@task
def run(c):
c.run(f"./server --port {c.config.app.port}")
app_name = "myapp"
port = "8080"
task run:
./server --port {{port}}

With environment files:

@dotenv
task run:
./server --port $PORT
@task
def deploy(c):
result = c.run("./deploy.sh", warn=True)
if result.failed:
print("Deploy failed, rolling back...")
c.run("./rollback.sh")
task deploy:
@ignore
./deploy.sh || ./rollback.sh

Or with hooks:

@on_error ./rollback.sh
task deploy:
./deploy.sh
@task
def build_frontend(c):
with c.cd("frontend"):
c.run("npm run build")
task build-frontend:
@cd frontend
npm run build
@task
def build(c):
c.run("go build", env={"CGO_ENABLED": "0"})
task build:
CGO_ENABLED=0 go build

Or globally:

@export CGO_ENABLED=0
task build:
go build
from invoke import task, Collection
@task
def clean(c):
"""Remove build artifacts"""
c.run("rm -rf dist/ build/ *.egg-info")
@task
def install(c):
"""Install dependencies"""
c.run("pip install -r requirements.txt")
@task(pre=[install])
def build(c):
"""Build the package"""
c.run("python setup.py build")
@task(pre=[build])
def test(c, verbose=False):
"""Run tests"""
cmd = "pytest tests/"
if verbose:
cmd += " -v"
c.run(cmd)
@task(pre=[test])
def deploy(c, env="staging"):
"""Deploy to environment"""
if env == "production":
if not input("Deploy to PRODUCTION? (yes/no): ") == "yes":
return
c.run(f"./deploy.sh {env}")
# Docker namespace
@task
def docker_build(c):
c.run("docker build -t myapp .")
@task
def docker_push(c):
c.run("docker push myapp")
docker = Collection("docker")
docker.add_task(docker_build, "build")
docker.add_task(docker_push, "push")
ns = Collection()
ns.add_task(clean)
ns.add_task(install)
ns.add_task(build)
ns.add_task(test)
ns.add_task(deploy)
ns.add_collection(docker)
task clean:
@desc "Remove build artifacts"
rm -rf dist/ build/ *.egg-info
task install:
@desc "Install dependencies"
pip install -r requirements.txt
task build: [install]
@desc "Build the package"
python setup.py build
task test verbose="": [build]
@desc "Run tests"
@if eq({{verbose}}, "true")
pytest tests/ -v
@else
pytest tests/
@end
task deploy env="staging": [test]
@desc "Deploy to environment"
@if eq({{env}}, "production")
@confirm "Deploy to PRODUCTION?"
@end
./deploy.sh {{env}}
@group docker
task docker-build:
@desc "Build Docker image"
docker build -t myapp .
@group docker
task docker-push:
@desc "Push Docker image"
docker push myapp
InvokeJake
invokejake
invoke buildjake build
invoke -ljake --list
invoke deploy --env=prodjake deploy env=prod
invoke docker.buildjake docker-build
invoke -eUses environment
FeatureInvokeJake
LanguagePythonDSL
Dependenciespip installSingle binary
File trackingManualNative file recipes
ParallelManual threads-j flag
Watch modeExternal toolBuilt-in
  1. No Python dependency - Single binary
  2. File dependency tracking - Built-in
  3. Parallel execution - -j flag
  4. Watch mode - jake -w
  5. Faster startup - No interpreter
  1. Python flexibility - Move complex logic to scripts
  2. Programmatic access - No Python API
  3. Fabric integration - Use shell commands