feat(experiments): rename SCOPED_INCLUDES to SCOPED_TASKFILES and add env namespace

Rename the experiment from SCOPED_INCLUDES to SCOPED_TASKFILES to better
reflect its expanded scope. This experiment now provides:

1. Variable scoping (existing): includes see only their own vars + parent vars
2. Environment namespace (new): env vars accessible via {{.env.XXX}}

With TASK_X_SCOPED_TASKFILES=1:
- {{.VAR}} accesses vars only (scoped per include)
- {{.env.VAR}} accesses env (OS + Taskfile env:, inherited)
- {{.TASK}} and other special vars remain at root level

This is a breaking change for the experimental feature:
- {{.PATH}} no longer works, use {{.env.PATH}} instead
- Env vars are no longer at root level in templates
This commit is contained in:
Valentin Maerten
2025-12-29 16:31:51 +01:00
parent efaea39503
commit edee501b6b
19 changed files with 212 additions and 74 deletions

View File

@@ -1,20 +0,0 @@
version: "3"
vars:
ROOT_VAR: from_root
includes:
a: ./inc_a
b: ./inc_b
tasks:
default:
desc: Test scoped includes - vars should be isolated
cmds:
- task: a:print
- task: b:print
print-root-var:
desc: Print ROOT_VAR from root
cmds:
- echo "ROOT_VAR={{.ROOT_VAR}}"

View File

@@ -1,18 +0,0 @@
version: "3"
vars:
VAR: value_from_a
UNIQUE_A: only_in_a
tasks:
print:
desc: Print vars from include A
cmds:
- echo "A:VAR={{.VAR}}"
- echo "A:UNIQUE_A={{.UNIQUE_A}}"
- echo "A:ROOT_VAR={{.ROOT_VAR}}"
try-access-b:
desc: Try to access B's unique var (should fail in scoped mode)
cmds:
- echo "A:UNIQUE_B={{.UNIQUE_B}}"

View File

@@ -1,13 +0,0 @@
version: "3"
vars:
VAR: value_from_b
UNIQUE_B: only_in_b
tasks:
print:
desc: Print vars from include B
cmds:
- echo "B:VAR={{.VAR}}"
- echo "B:UNIQUE_B={{.UNIQUE_B}}"
- echo "B:ROOT_VAR={{.ROOT_VAR}}"

38
testdata/scoped_taskfiles/Taskfile.yml vendored Normal file
View File

@@ -0,0 +1,38 @@
version: "3"
env:
ROOT_ENV: env_from_root
SHARED_ENV: shared_from_root
vars:
ROOT_VAR: from_root
includes:
a: ./inc_a
b: ./inc_b
tasks:
default:
desc: Test scoped includes - vars should be isolated
cmds:
- task: a:print
- task: b:print
print-root-var:
desc: Print ROOT_VAR from root
cmds:
- echo "ROOT_VAR={{.ROOT_VAR}}"
print-env:
desc: Print env vars using {{.env.XXX}} syntax
cmds:
- echo "ROOT_ENV={{.env.ROOT_ENV}}"
- echo "SHARED_ENV={{.env.SHARED_ENV}}"
- echo "PATH_EXISTS={{if .env.PATH}}yes{{else}}no{{end}}"
test-env-separation:
desc: Test that env is NOT at root level in scoped mode
cmds:
# In scoped mode, {{.ROOT_ENV}} should be empty (env not at root)
# In legacy mode, {{.ROOT_ENV}} would have the value
- echo "ROOT_ENV_AT_ROOT={{.ROOT_ENV}}"

View File

@@ -0,0 +1,36 @@
version: "3"
env:
INC_A_ENV: env_from_a
SHARED_ENV: shared_from_a
vars:
VAR: value_from_a
UNIQUE_A: only_in_a
tasks:
print:
desc: Print vars from include A
cmds:
- echo "A:VAR={{.VAR}}"
- echo "A:UNIQUE_A={{.UNIQUE_A}}"
- echo "A:ROOT_VAR={{.ROOT_VAR}}"
try-access-b:
desc: Try to access B's unique var (should fail in scoped mode)
cmds:
- echo "A:UNIQUE_B={{.UNIQUE_B}}"
print-env:
desc: Print env vars from include A
cmds:
- echo "A:INC_A_ENV={{.env.INC_A_ENV}}"
- echo "A:ROOT_ENV={{.env.ROOT_ENV}}"
- echo "A:SHARED_ENV={{.env.SHARED_ENV}}"
test-env-in-var:
desc: Test using env in a var template
vars:
COMPOSED: "env={{.env.ROOT_ENV}}"
cmds:
- echo "{{.COMPOSED}}"

View File

@@ -0,0 +1,24 @@
version: "3"
env:
INC_B_ENV: env_from_b
SHARED_ENV: shared_from_b
vars:
VAR: value_from_b
UNIQUE_B: only_in_b
tasks:
print:
desc: Print vars from include B
cmds:
- echo "B:VAR={{.VAR}}"
- echo "B:UNIQUE_B={{.UNIQUE_B}}"
- echo "B:ROOT_VAR={{.ROOT_VAR}}"
print-env:
desc: Print env vars from include B
cmds:
- echo "B:INC_B_ENV={{.env.INC_B_ENV}}"
- echo "B:ROOT_ENV={{.env.ROOT_ENV}}"
- echo "B:SHARED_ENV={{.env.SHARED_ENV}}"

View File

@@ -0,0 +1,3 @@
ROOT_ENV=env_from_root
SHARED_ENV=shared_from_root
PATH_EXISTS=yes

View File

@@ -0,0 +1 @@
ROOT_ENV_AT_ROOT=

View File

@@ -0,0 +1,3 @@
A:INC_A_ENV=env_from_a
A:ROOT_ENV=env_from_root
A:SHARED_ENV=shared_from_a