just(justfile):替代 Makefile 做项目脚本入口

起因

每个项目都有一堆需要跑的命令:测试、lint、构建、迁移、部署。
用 npm script 写 → 只适合 Node 项目;写在 README → 复制粘贴慢;
用 Makefile → tab 缩进诡异、.PHONY 麻烦、shell quoting 各种坑、
Windows 上 make 不一定有。

just 是 Rust 写的命令运行器,专为"项目级 task runner"设计,
没有 make 的历史包袱。

安装

# macOS
brew install just

# Debian / Ubuntu
sudo apt install just     # Ubuntu 24.04+
# 或下载二进制
curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh \
  | bash -s -- --to /usr/local/bin

# Windows
scoop install just

just --version

justfile 例

放在项目根目录 justfile(无后缀):

# 默认 recipe(just 不带参数时跑)
default: list

# 列所有 recipe
list:
    @just --list

# 测试
test:
    pytest -x

# 跑某个测试
test-one TEST:
    pytest -x -v {{TEST}}

# 启动开发服务器
dev:
    uvicorn app.main:app --reload

# Lint + format
lint:
    ruff check .
    mypy src/

fmt:
    ruff format .
    ruff check --fix .

# 跑数据库迁移
migrate:
    alembic upgrade head

migrate-create MESSAGE:
    alembic revision --autogenerate -m "{{MESSAGE}}"

# 多步组合
ci: lint test
    @echo "✅ all green"

# 部署到生产
deploy ENV='staging':
    @echo "Deploying to {{ENV}}"
    ./scripts/deploy.sh {{ENV}}

# 用 docker 构建镜像
build VERSION:
    docker build -t myapp:{{VERSION}} .
    docker tag myapp:{{VERSION}} myapp:latest

# 清理
clean:
    rm -rf dist build .pytest_cache .ruff_cache __pycache__
just              # 同 `just default`
just test
just test-one tests/test_user.py::test_create
just migrate-create "add email field"
just ci
just deploy prod

与 Makefile 对比

# Makefile
.PHONY: test lint deploy

test:
    pytest -x

lint:
    ruff check .
    mypy src/

deploy:
    @echo "Deploying"
    ./scripts/deploy.sh $(ENV)
make test
make deploy ENV=prod   # 注意要写 ENV=prod,just 是位置参数 deploy prod

just 的胜出:

  • 不需要 .PHONY(recipe 永远跑)
  • 不需要 tab(空格即可,4 / 2 都行)
  • 命令默认 echo(不需要 @
  • 多行字符串 / heredoc 简单
  • 参数语法直接(位置 + 默认值)
  • 跨平台(Windows / Linux / Mac 一致)

高级特性

多 shell

# 默认 sh -cu
hello:
    echo "from sh"

# 用 bash
[shell: bash]
fancy:
    echo $BASH_VERSION
    arr=(1 2 3); echo "${arr[@]}"

# 用 python
[shell: python]
math:
    print(2 ** 10)

# 用 powershell
[shell: pwsh -c]
greet:
    Write-Host "from PowerShell"

跨平台条件

[unix]
clean:
    rm -rf build/

[windows]
clean:
    Remove-Item -Recurse -Force build/

依赖

build: lint test
    cargo build --release

release VERSION: build
    git tag v{{VERSION}}
    git push origin v{{VERSION}}

just release 1.2.3 → 自动先跑 build → build 先跑 lint + test。

变量

version := `git describe --tags --always`
docker_repo := "ghcr.io/myorg/myapp"

build:
    docker build -t {{docker_repo}}:{{version}} .
    docker push {{docker_repo}}:{{version}}

env 读 .env

set dotenv-load

dev:
    echo "Connecting to $DATABASE_URL"

set dotenv-load 让 just 自动读 .env

分组

[group('test')]
test-unit:
    pytest tests/unit

[group('test')]
test-e2e:
    playwright test

[group('deploy')]
deploy-staging:
    ./deploy.sh staging
just --list --groups
# test:
#   test-unit
#   test-e2e
# deploy:
#   deploy-staging

private recipes

[private]
_setup:
    pip install -r requirements.txt

dev: _setup
    flask run

_ 开头 = private(不出现在 just --list),但能被依赖。

嵌套 justfile

monorepo 里每个子目录一个 justfile:

myapp/
├── justfile          # 顶层(全局 recipe)
├── backend/
│   └── justfile      # backend 特定
└── frontend/
    └── justfile      # frontend 特定

顶层调用子项目:

test-all:
    just backend/test
    just frontend/test

或者用 just --justfile 指定:

just --justfile backend/justfile test
just -f backend/justfile test       # 简写

tab 补全

# bash
just --completions bash > /usr/local/etc/bash_completion.d/just

# zsh
just --completions zsh > ~/.zsh/completions/_just

# fish
just --completions fish > ~/.config/fish/completions/just.fish

之后 tab 补全所有 recipe 名 + 参数。

与 CI

GitHub Actions:

- uses: extractions/setup-just@v2
- run: just ci

效果

  • 新人 clone 仓库 → just --list 一眼看到所有可用命令
  • README 不再充满"how to run tests / lint / deploy",一句"see justfile"
  • Makefile 时代的 tab/space 翻车问题归零
  • 跨平台一致,Windows 同事不再单独写 .ps1 脚本

踩过的坑

  1. recipe 名带 _-:just 都支持,但 shell tab 补全有时不识别。
    recipe 名优先短 + 不带 _

  2. 不在 git 根:默认 just 在当前目录找 justfile。子目录里跑根的
    recipe 需要 cd 上去或 just -f ../justfile recipejust 也支持
    .justfile(隐藏)让 ls 不见。

  3. shell 退出码处理:单条 recipe 里某命令失败默认整个 recipe 停。
    要继续:- 前缀(同 make):
    just deploy: -kill -9 $(pidof oldservice) systemctl start newservice

  4. 变量 $var vs {{var}}$var 是 shell 变量(运行时展开),
    {{var}} 是 just 变量(justfile 解析时展开)。混了会报错。

  5. CI 装 just 加二进制 cache:每次 CI build 都装一次浪费时间,
    extractions/setup-just action 自带 cache。

精确评价 共 0 人评价
可复现性
可复现 · 0 不可复现 · 0
文风
文风流畅 · 0 文风晦涩 · 0
立场
支持 · 0 反对 · 0

登录后即可对本帖作出评价。

评论区 0 条 · 所有人可在此交流

登录后参与评论。

还没有评论,来说两句。