InvokeというPython製軽量タスクランナーがある。
@task
デコレータを設定した関数を作り、c.run()で以下のようにコマンドを実行する。
tasks.py
from invoke import *
@task
def install(c):
c.run("pip install -r requirements.txt")
これを実行するには以下のようにする。
$ pip3 install invoke
$ invoke install
繰り返し文も以下のようにfor文でかける。
tasks.py
@task
def build(c):
packages = ["Client", "Server", "Tester"]
for name in packages:
c.run(f"go build cmd/{name} -o out/{name}")
依存関係は、@task
の引数に依存先の関数を渡す。
tasks.py
@task
def build(c):
c.run("go build -o out")
@task(build)
def test(c):
c.run("go test")
@task(test)
def release(c):
c.run("zip out.zip out/")
終了コードによる分岐をする場合、warn=True
を引数に加え、戻り値の.ok
、.failed
を使う。
tasks.py
@task
def build(c):
if c.run("test -e ./node_modules", warn=True).failed:
c.run("npm install")
if c.run("test -e out", warn=True).ok:
c.run("rm -rf out")
c.run("tsc")
ディレクトリを移動するには、with句でc.cd()
を呼ぶ
tasks.py
@task
def build(c):
with c.cd("client"):
c.run("go build")
c.run("go test")
with c.cd("server"):
c.run("go build")
c.run("go test")
関数に引数を設定すると、コマンドのパラメータになる。
tasks.py
@task
def release(c, gs_path, force=False):
if force:
c.run("git push -f")
else:
c.run("git push")
r = c.run(f"gsutil rsync . {gs_path}")
$ invoke release --gs-path gs://release-gcs/ --force
sedの代わりに使うには、標準出力はr.stdout
で出力できるが、標準入力として使うには一度tempfileに出力して使う。
tasks.py
import tempfile
@task
def release(c):
r = c.run("cat deployment.yaml")
yaml = r.stdout.replace("__IP__", "3.4.5.6")
with tempfile.NamedTemporaryFile() as tmp:
with os.open(tmp.name) as f:
f.write(yaml)
c.run(f"cat {tmp.nmae} | kubectl apply -f -")
このあたりをチートシートにした小冊子を作って、技術書典5でフリーペーパーとして配りました。ダウンロードもできますのでよければ活用ください!