Repository navigation
fix(template): substitute tokens in command and [env] - #8
Merged
Merged
Conversation
RECIPE_CONTRACT says tokens are substituted in `[args]`,
`[outputs.<role>.alias]` and `[env]`, and every shipped example recipe
puts them in `command`. Neither `command` nor `[env]` was actually
rendered: `recipe.command` was cloned verbatim and `[env]` values were
shell-quoted as-is, so a token like {outputs.result.path} reached the job
as a literal string and blew up inside the user's program at runtime.
render_value's unresolved-token guard never saw those strings either, so
the documented promise that "any leftover {...} token at submission time
is a hard error" did not hold for the two places users actually hit.
Render both through render_value. The examples additionally used
{outputs.<role>.dir}, which is not a token the table defines — corrected
to .path, which is what the code and the docs table agree on.
Tests cover a token in `command`, a token in `[env]`, an unknown token
failing at submit rather than at runtime, and inline JSON in a `bash -c`
command surviving untouched (find_unresolved_token only matches the
labctl token shape).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
maharajamihir
force-pushed
the
mihir/template-command-and-env
branch
from
August 17, 2026 17:54
ff2cd94 to
13b552d
Compare
avocadoali
approved these changes
Aug 17, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The bug
docs/RECIPE_CONTRACT.mdsays template tokens are substituted in[args],[outputs.<role>.alias]and[env]. Every shipped example recipe puts them incommand:Neither
commandnor[env]was actually rendered.recipe.commandwas cloned verbatim, and[env]values were shell-quoted as-is. So a token reaches the job as a literal string:Worse, it fails silently at submit time:
render_value's unresolved-token guard only runs on strings that pass through it, so the documented promise —— did not hold for the two places users actually hit. The job submits happily and dies minutes (or hours) later inside their program.
I found this the slow way: three failed runs in a row while getting a first recipe working, each time assuming I'd got the token name wrong.
The examples compound it by using
{outputs.<role>.dir}, which isn't in the token table at all — the code only ever defined.path.The fix
commandelements and[env]values throughrender_value, like every other user-authored string.dirto.pathcommandas a templated site, and note that only the labctl token shape{word(.word)*}counts, so inline JSON in abash -ccommand is left aloneBehaviour change worth reviewing
A recipe that previously shipped an unresolved token in
commandnow fails at submit instead of at runtime. That's the intended behaviour and matches the documented contract, but it is a behaviour change: anything currently relying on a literal{...}reaching the job will break loudly. Given the examples themselves were broken, I judged loud failure better than silent breakage — happy to gate it behind a flag if you'd rather.Tests
Four new unit tests: a token in
commandis substituted; a token in[env]is substituted; an unknown token fails at submit rather than runtime; inline JSON braces in abash -ccommand survive untouched.cargo test36 + 9 pass,cargo fmt --checkclean.Note
examples/recipes/hetjob.tomlin #5 uses.dirtoo — I'll update that branch so the two don't conflict.🤖 Generated with Claude Code