Feature request: Configurable subtask forcing
Intro
I'm interested in using Taskfile with the gentle force experiment activated, however I would like to have a bit more control over which tasks get "forced", and which don't. I can imagine doing this with something like a force: [flag] argument similar to run, which I will explain below. Of course, other solutions would be welcome as well :)
Status Quo
To showcase my current challenge, I'll use this example Taskfile, which I hope is clear enough without description (If not, I can edit this..)
version: '3'
vars:
COUNTRIES: DEU USA CHN
tasks:
prepare_country:
requires:
vars: [iso3]
label: 'prepare_country iso3={{.iso3}}'
cmds:
- 'echo "PREPARING: {{.iso3}}"'
- touch data/prepared_{{.iso3}}.csv
sources:
- data/input_{{.iso3}}.csv
generates:
- data/prepared_{{.iso3}}.csv
analyze_country:
deps:
- task: prepare_country
vars:
iso3: '{{.iso3}}'
requires:
vars: [iso3]
label: 'analyze_country iso3={{.iso3}}'
cmds:
- 'echo "ANALYZING: {{.iso3}}"'
- touch data/analyzed_{{.iso3}}.csv
sources:
- data/prepared_{{.iso3}}.csv
generates:
- data/analyzed_{{.iso3}}.csv
analyze_all:
cmds:
- for: { var: COUNTRIES }
task: analyze_country
vars:
iso3: '{{.ITEM}}'
Where the files data/input_[country].csv were manually created on my filesystem.
When I invoke the analyze_all task with the command...
TASK_X_GENTLE_FORCE=1 task analyze_all --force
...then all tasks and sub tasks are executed. If I run that same command again, then all tasks are skipped (besides of course the analyze_all task which isn't actually doing meaningful work). As far as I can tell, this is as-expected with the current implementation of Gentle Forcing.
That said, what I would like to have happen is that executing TASK_X_GENTLE_FORCE=1 task analyze_all --force would somehow know that I want to force the "primary children" of the analyze_all task, i.e. the analyze_country tasks, but not their dependencies (i.e. the prepare_country tasks).
Proposal
In general I really like the Gentle Force behaviour, and I don't suggest changing it. However in this edge case I would be happy with something like a force: when_forced argument which I could add to the subtask invocations in my analyze_all task. This could look like:
version: '3'
vars:
COUNTRIES: DEU USA CHN
tasks:
prepare_country:
requires:
vars: [iso3]
label: 'prepare_country iso3={{.iso3}}'
cmds:
- 'echo "PREPARING: {{.iso3}}"'
- touch data/prepared_{{.iso3}}.csv
sources:
- data/input_{{.iso3}}.csv
generates:
- data/prepared_{{.iso3}}.csv
analyze_country:
deps:
- task: prepare_country
vars:
iso3: '{{.iso3}}'
requires:
vars: [iso3]
label: 'analyze_country iso3={{.iso3}}'
cmds:
- 'echo "ANALYZING: {{.iso3}}"'
- touch data/analyzed_{{.iso3}}.csv
sources:
- data/prepared_{{.iso3}}.csv
generates:
- data/analyzed_{{.iso3}}.csv
analyze_all:
cmds:
- for: { var: COUNTRIES }
task: analyze_country
force: when_forced # <------------------ HERE
vars:
iso3: '{{.ITEM}}'
In this case force: when_forced could mean "force this sub task if the current task is forced".
Other possible values could include:
force: always, so that subtask is always executedforce: never, which could be the default and would maintain the current behaviour of Gentle Force