Skip to main content

Migration Playbook (Make/Just -> Broski)

This guide is for teams migrating real projects without downtime.

What problems Broski solves​

  1. Rebuild ambiguity: --explain gives concrete cache miss reasons.
  2. Timestamp fragility: graph fingerprints are content-based.
  3. Split tooling: one runner for graph and interactive flows.
  4. Hidden environment drift: explicit @env, @secret_env, @load.
  5. Manual dependency ordering: explicit task graph.

What Broski does not solve​

  1. Remote/distributed cache orchestration.
  2. Automatic semantic dependency inference.
  3. Full Windows parity for every strict isolation path.

Progressive Adoption​

Use this order to keep migration low-risk:

  1. Copy-paste your existing shell commands into a broskifile.
  2. Confirm behavior is unchanged (broski run <task>).
  3. Add @in and @out only to slow or expensive tasks.
  4. Use --explain to verify the miss/hit reasons are what you expect.
  5. Introduce advanced annotations (@requires, @env, @isolation) only where they solve a real issue.

Migration strategy​

  1. Keep current Make/Just runner while bootstrapping Broski.
  2. Port one CI-critical flow (build, test, ci) first.
  3. Add strict contracts (@in, @out) to graph tasks.
  4. Validate behavior using --dry-run and --explain.
  5. Port developer workflows (dev, watch, serve) as interactive tasks.
  6. Switch CI entrypoint to Broski after parity.
  7. Remove old runner after two green cycles.

Concept mapping​

Existing conceptMakeJustBroski
Tasktargetrecipetask header
Dependency edgetarget depsrecipe depstask: dep_a dep_b
Parametersvariablesrecipe args[arg] and [arg="default"]
Env injectionshell envshell env@env, @secret_env, @load
Long-running dev taskreciperecipe@mode interactive
Deterministic artifact cachenot first-classnot first-classgraph mode + manifest fingerprints
Rebuild reasonlimited/manuallimited--explain

Conversion patterns​

Pattern A: Make CI chain​

build:
    cargo build --release

test:
    cargo test

ci: build test
version = "0.5"

build:
    @in src/**/* Cargo.toml Cargo.lock
    @out target/release
    cargo build --release

test: build
    @in src/**/* tests/**/* Cargo.toml Cargo.lock
    @out .broski/stamps/test.ok
    cargo test
    touch .broski/stamps/test.ok

ci: test
    @mode interactive
    echo "ci complete"

Verify:

broski run ci --dry-run --explain
broski run ci --explain

Pattern B: Just args -> Broski params​

build target mode="release":
  cargo build --bin {{target}} --{{mode}}
build [target] [mode="release"]:
    @in src/**/* Cargo.toml
    @out dist/{{ target }}
    cargo build --bin {{ target }} --{{ mode }}

Run:

broski build api
broski build api debug

Pattern C: setup + dev workflow​

setup:
  pip install -r requirements.txt
  npm install

dev:
  docker compose up
setup:
    @mode interactive
    @requires python3 npm
    pip install -r requirements.txt
    npm install

dev:
    @mode interactive
    @requires docker
    docker compose up

Anti-pattern reference​

Detailed anti-pattern guidance now has dedicated pages:

CI migration checklist​

  • broski run ci --dry-run succeeds
  • broski run ci --explain shows deterministic reasons
  • build/test tasks declare @in and @out
  • interactive tasks explicitly use @mode interactive
  • required binaries covered by @requires
  • old CI runner removed only after parity and green history

Local developer checklist​

  • broski list shows clean public task surface
  • destructive tasks protected with @confirm
  • helper tasks hidden with @private
  • onboarding path documented in README and quickstart

Rollback plan​

If migration fails in CI:

  1. keep old runner as fallback entrypoint;
  2. disable Broski entrypoint for one cycle;
  3. run broski run ci --explain on failing commit;
  4. fix contracts (@in/@out/env) and re-enable.