Skip to content

Conversation

@prady0t
Copy link
Contributor

@prady0t prady0t commented Dec 18, 2025

Description

With this PR, a user can specify a default environment per task. Some work is still left in:

  • Adding a task with the --default_environment flag with pixi task add, should also add the default environment to pixi.toml
  • Adding tests
  • Overriding with -e option.

Fixes #5140

How Has This Been Tested?

Using a pixi.toml file with the option default_environment runs the task in that environment (if it can).

[tool.pixi.tasks]
doc = { cmd = ["make", "html"], cwd = "docs", default-environment = "doc" }

AI Disclosure

Some detailed comments are generated by Github copilot for a more accurate description.

Checklist:

  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • I have added sufficient tests to cover my changes.
  • I have verified that changes that would impact the JSON schema have been made in schema/model.py.

Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
@prady0t prady0t marked this pull request as draft December 18, 2025 12:49
Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
@prady0t
Copy link
Contributor Author

prady0t commented Dec 21, 2025

@ruben-arts This is ready to be reviewed.

@prady0t prady0t marked this pull request as ready for review December 21, 2025 10:17
schema/model.py Outdated
default_environment: NonEmptyStr | None = Field(
None,
description="A default environment to run the task",
json_schema_extra={
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually, with the above comment about EnvironmentName, this json_schema_extra could be removed entirely: the lack of title is generally fine (unless really explaining some obtuse term), and the regex would flow more predictably from the typing.

json_schema_extra should probably be reserved for really tricky things that don't have an "elegant" pydantic analogue.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only reason I added json-scheme-extra was so that I could specify the title as default-environment, not Default-Environment, in schema.json (which seems to be the default generation); however, you are right, the title hardly matters here. Thanks for the review.

Signed-off-by: Pradyot Ranjan <[email protected]>
description: EnvironmentName | None = Field(
None,
description="A short description of the task",
examples=["Build the project"],
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, remove the example field, as it may be misleading/not required.

Copy link
Contributor Author

@prady0t prady0t left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@bollwyvl Removed the json-scheme-extra part.

@ruben-arts
Copy link
Contributor

I updated the branch to fix some other issues, for testing.

@ruben-arts
Copy link
Contributor

Hey @prady0t,

I was testing with this toml file:

[workspace]
channels = []
platforms = ["osx-arm64"]

[tasks]
test = "echo test"
test2 = "echo test2"
dep.depends-on = ["test3", "test6"]

[feature.test.tasks]
test3 = { cmd = "echo test3", default-environment = "three" }
test4 = "echo test4"

[feature.test2.tasks]
test5 = "echo test5"
test6 = { cmd = "echo test6", default-environment = "four" }

[environments]
one = []
two = ["test"]
three = ["test2", "test"]
four = ["test2"]
five = ["test", "test2"]
six = { features = ["test"], no-default-feature = true}
seven = { features = ["test2"], no-default-feature = true}

But in no case would it actually use the default-environment.

Could you test it yourself and add some tests.

The other decisions you made look fine to me, so I'm looking forward to testing them.

@prady0t
Copy link
Contributor Author

prady0t commented Dec 22, 2025

For me, it just gives different environments where tests could be run.

Please select an environment to run the task in: ›
❯ two
  three
  five
  six

Let me find a way to use the specified default environment when the task can be solved for multiple environments.

@ruben-arts
Copy link
Contributor

Let me find a way to use the specified default environment when the task can be solved for multiple environments.

I might have misunderstood, but isn't that the whole idea of this feature?

@prady0t
Copy link
Contributor Author

prady0t commented Dec 23, 2025

I might have misunderstood, but isn't that the whole idea of this feature?

Exactly. Currently, the default-environment is applied after task resolution, and hence, if multiple environments are specified, it prompts the user. Due to task ambiguity

There's another bug for the same manifest; remove the default-environment part for test3 and run with the -e three flag; the user still gets prompted for multiple environments. Is that desired behaviour? If so i just checked if explicit_environment is provided or not; if not, treat default_environment as explicit environment.

The current bug can be fixed by adding a check for a task with default_environment in disambiguate_task_interactive in run.rs, but how should the -e flag be treated after that?

Comment on lines +445 to +457
// If any of the candidate tasks declares a `default-environment` that
// corresponds to one of the candidate environments, prefer that
// environment automatically.
if let Some(idx) = problem.environments.iter().position(|(env, task)| {
if let Some(default_env_name) = task.default_environment() {
default_env_name == env.name()
} else {
false
}
}) {
return Some(problem.environments[idx].clone());
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This works for the currently discussed bug, but now you cannot override this using -e flag.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the priority should be

  1. --environment in the pixi run cli (like it's now)
  2. the default-environment field in the task definition. (new)
  3. the default environment when possible (like it's now)
  4. the disambiguation function (like it's now)

@prady0t
Copy link
Contributor Author

prady0t commented Dec 23, 2025

@ruben-arts these changes should be good to go. I've also added a few tests.

Comment on lines 226 to 235
// If the task itself declares a `default_environment`, prefer that
// environment when constructing the root node (if it exists in the
// project). Do not fail if the named environment is missing; fall
// back to the resolved `run_env`.
if let Some(default_env_name) = task.default_environment()
&& let Some(env) = project.environment(default_env_name)
{
run_env = env;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Completely removed these checks since the disambiguator already checks for it, this helps explicitly declared environment. to take over

} else {
task_env
};

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason as above

Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
@ruben-arts
Copy link
Contributor

The latest changes don't work for overriding the default environment yet.

[workspace]
channels = []
platforms = ["osx-arm64"]

[tasks]
test = { cmd = "echo test", default-environment = "test" }

[feature.test.dependencies]
# pytest = "*"

[environments]
test = ["test"]

Gives:

> pixi run test
✨ Pixi task (test in default): echo test                                                                                                         
test

While I expected it to run in test.

Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
Signed-off-by: Pradyot Ranjan <[email protected]>
@prady0t
Copy link
Contributor Author

prady0t commented Dec 23, 2025

Added a check for when the task is in default and default-environmnet is added.

@lucascolley lucascolley changed the title feat(task): --default_environment flag for specifying the default environment for a task. feat(task): --default_environment flag for specifying the default environment for a task Dec 27, 2025
@nichmor
Copy link
Contributor

nichmor commented Dec 29, 2025

tested with both pixi.toml that you guys have attached. Also verified if priorities with -e or default-environment are respected - everything works fine.

Copy link
Contributor

@nichmor nichmor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed a small empty field from tests - I like it!

@nichmor nichmor enabled auto-merge (squash) December 29, 2025 10:45
@nichmor nichmor merged commit 8525a02 into prefix-dev:main Dec 29, 2025
41 checks passed
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.

Allow specifying a default environment for tasks

4 participants