Skip to content

feat(tasks): support multi-line tasks#5957

Merged
ruben-arts merged 3 commits intomainfrom
claude/fix-pix-1708-q2cbg
Apr 24, 2026
Merged

feat(tasks): support multi-line tasks#5957
ruben-arts merged 3 commits intomainfrom
claude/fix-pix-1708-q2cbg

Conversation

@baszalmstra
Copy link
Copy Markdown
Contributor

Description

deno_task_shell collapses bare newlines to whitespace, so a multi-line TOML task like

[tasks]
test = """
echo hello
echo hello2
"""

was executed as echo hello echo hello2, printing hello echo hello2.

The fix joins non-empty, non-comment lines with && before parsing, so each line runs as a separate command and execution stops on the first failure. Backslash line continuations are merged, and lines already ending in a shell control operator (&&, ||, |, ;, &) aren't double-separated.

Fixes #5937

How Has This Been Tested?

  • Added unit tests test_as_script_multiline and test_as_script_multiline_preserves_existing_operator in crates/pixi_task/src/executable_task.rs.
  • Ran the repro from the issue locally; output is now:
    Pixi task (test): echo hello
    echo hello2
    hello
    hello2
    
  • Verified fail-fast: a middle false line aborts the task with exit code 1 and the subsequent line is not run.

AI Disclosure

  • This PR contains AI-generated content.
    • I have tested any AI-generated content in my PR.
    • I take responsibility for any AI-generated content in my PR.

Tools: Claude (Claude Code)

Checklist:

  • I have performed a self-review of my own code
  • I have added sufficient tests to cover my changes.

Generated by Claude Code

claude added 3 commits April 24, 2026 11:02
Join lines of a multi-line task script with `&&` before handing the
command off to `deno_task_shell`, which otherwise collapses newlines to
whitespace. Execution now stops on the first failing command.

Fixes #5937
The previous multi-line join split every newline, including those inside
single- or double-quoted arguments. That broke tasks like
`python -c "..."` whose quoted body legitimately spans lines.

Replace the simple `lines()`/join with a quote-aware walker that only
treats newlines outside quotes as command separators. Backslash line
continuations are still merged.
@ruben-arts ruben-arts enabled auto-merge (squash) April 24, 2026 12:16
@ruben-arts ruben-arts merged commit 06a5053 into main Apr 24, 2026
37 checks passed
@ruben-arts ruben-arts deleted the claude/fix-pix-1708-q2cbg branch April 24, 2026 12:16
@bollwyvl
Copy link
Copy Markdown
Contributor

bollwyvl commented May 1, 2026

While the current behavior was a little surprising at first, I think most folk have adapted and likey rely on it,

One place where the "newlines become whitespace" is useful is to shell out to some workspace-managed executor, especially with args, which might have its own whitespace/quote/escape rules which probably wouldn't be caught by the home-rolled parser.

cmd = """python -c "import stuff; [
  stuff.do(),
  stuff.do_another('''{{ some_arg}}''')
]" """

Anyhow, as-is, this behavior will be a fairly brutal breaking change. Perhaps it could be opt-in, initially, or at least be opted out of at the workspace or task level?

@baszalmstra
Copy link
Copy Markdown
Contributor Author

If I implemented this correctly, the example you gave should not change, except that the newlines become whitespaces. I make sure to break up newlines only when not inside a ' or ".

@bollwyvl
Copy link
Copy Markdown
Contributor

bollwyvl commented May 1, 2026

Sure, I see the caveat about the python case right in the comment; my concern is just that cmd already goes through n parsers (minijinja, maybe some extra-kooky env stuff?, finally d_t_s). Pretty much any change to the effective grammar is going to wreck somebody's day, even if it isn't necessarily mine (which will likely already have been wrecked by n-pass parsers in recipe.yaml (better than most) and .gitlab-ci.yml (kind of a nightmare)).

hjmjohnson added a commit to InsightSoftwareConsortium/ITK that referenced this pull request May 8, 2026
…ility

pixi 0.68.0 (released 2026-05-08) changes how multi-line task cmds are
parsed.  Per pixi PR prefix-dev/pixi#5957, bare newlines that were
previously joined as whitespace are now joined with '&&', so

    cmd = '''cmake
      -Bbuild
      -S.
      ...'''

is no longer executed as 'cmake -Bbuild -S. ...' but as 'cmake &&
-Bbuild && -S. && ...'.  cmake then runs with no arguments and prints
its Usage banner; the next line tries to execute '-Bbuild' as a
command and fails with 'command not found'; the task exits 127.
Backslash line continuations preserve the legacy single-command
behavior on both pre- and post-0.68 pixi versions.

Affected tasks (all multi-line cmake invocations under
[tool.pixi.feature.cxx.tasks]):

  configure
  configure-ci
  configure-debug
  configure-release
  configure-python
  configure-debug-python

The two python-exe tasks already terminate the first line with '&&'
so they are not double-separated by 0.68's logic and need no
modification.

Fixes the global ITK CI Pixi-Cxx breakage observed across all open
PRs since pixi 0.68.0 became the default in prefix-dev/setup-pixi.
@bollwyvl
Copy link
Copy Markdown
Contributor

bollwyvl commented May 8, 2026

and lo, this did indeed ruin my day (and at least itk's)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tasks): support multi-line tasks

4 participants