You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Add if: keyword to control when a task or command is ran? #608
I'm currently getting around the issue by having a task called donothing that gets called when the task should not run. It would be nice if we could conditionally run tasks somehow. Maybe something like this:
Reacted by Zrean Tofiq, Marcos Soutullo Rodriguez, Matti N., Karan Sakhuja, Robin Joseph, Stéphane Wirtel, 0xpussycat, Sorin Sbarnea, Cat C, James Marino and 48 more
Reacted by thinkgos, fabiomarinetti and Devin Buhl
NOTE: We already have preconditions, which is similar but makes the call fail when an error is returned, which means if still makes sense to have for skipping without failing.
Reacted by Sorin Sbarnea, Matthew Hodgkins, Zadkiel AHARONIAN, Tit Petric, x80486, Kostas, Kevin Chen, merusso, Brahm Lower, Vikas Kumar and 7 more
isn't that what status is supposed to do? decide to skip a step?
Unlike status which will skip a task if it is up to date, and continue executing tasks that depend on it, a precondition will fail a task, along with any other tasks that depend on it.
isn't that what status is supposed to do? decide to skip a step?
You have a good point, we'd have some intersection between these two features.
status currently prints Task "foo" is up-to-date messages, though. This is accurate for statuses but not for other reasons why you'd want to skip a task.
Also, if would be the opposite of status with regarding the expected status: if runs on zero, status runs on non-zero statuses.
So, I don't have a strong opinion, but maybe it would still make sense to have both if and status. Alternatively, we could add if: only to commands and not to the task itself.
Another thing we might want to keep in mind is handling the --force command line parameter. Currently, this will just ignore status which forces the user to wrap everything in ifs (even using status) for logic that doesn't relate to a particular project. In my use case, I share the same set of Taskfiles across hundreds of repositories of many different types - it is not feasible to generate the Taskfiles for each project type.. it would take too long.
I would like to see an if: that can be added at the least to the task and cmd level. It should also not be impacted by any --force logic. Take the following example:
---
version: '3'
tasks:
mytask:
cmds:
- gsettings set org.gnome.settings-daemon.plugins.color night-light-enabled true
if:
- ls /usr/bin/*session | grep gnome-session
status:
- [[ $(gsettings get org.gnome.settings-daemon.plugins.color night-light-enabled) == 'true' ]]
Both the if: and status: are used in this example. The if: parameter makes sure GNOME is being run on the system and the status: is used to achieve idempotency. This would make even more sense if we were running a command that requires a reboot. In this example, we would need the --force command to obey the if: or else we would get an error if GNOME is not on the system.
Currently, with any complex flows that rely on status, things can easily get messy when using --force but the --force command could potentially be pretty useful for cache busting. I see adding an if: parameter as a possible solution.
Reacted by Andrey Nering, Maximilian Roos, Vikas Kumar, merusso, Johannes Aubart and Daniele Maccari
Probably the best use-case for if would be to add steps that depend only on specific platforms, like Windows, Linux, MacOS. Adding extra code for platform on each called shells script is a PITA, one that could be easily avoided with an "if".
Reacted by JonZeolla, Marek Sierociński and Dave Patton
I really over-use status, which requires some mental gymnastics ("Only run this on ARM machines, which means status needs to be 0 on x86 machines, so raise an error on ARM"!), and isn't compatible with --force ("now we're running it on x86 machines?!")
Though I do empathize that it still has lots of overlap with status...
@andreynering i have a couple of env vars where if would be useful. I'd be willing to open up a PR if there isn't anything in flight, going with your proposal in the reply. In combination with #1220 this would allow us to put most of our release pipeline into taskfiles, enabling matrix tests and targeting along with that "run offline" concept.
@titpetric Contributions are welcome! I would advise you to wait until #1220 is merged to avoid any conflicts. Also, that would allow you to test both features together.
I would not go down the path of IF and ELSE. If you really need such a complexity then just write a bash script and be done with it.
Better is to use STATUS to evaluate the condition for which a TASK should run. That effectively gives you the IF/ELSE logic you need, and you will get a better outcome. So, for you that might mean a TASK where the status checks for the absence of an installed dependency, and when missing, the commands install that dependency.
I don't think status covers what an if would mean.
Aside from semantics, where using "status" as an "if" simply doesn't make sense, I think an if option would be very useful.
If I take the following:
tasks:
generate:
cmds:
- git checkout branchname/{{.RELEASE}}
- if: {{.TAG eq "true"}}
cmd: git tag -a {{.RELEASE}} -m "Tagging {{.RELEASE}}
- git push -a
That if construct is a lot more readable than using a status, which does a test, and furthermore, it allows me to run task generate TAG=true RELEASE=1.2.3
Currently, the task is constructed like so
tasks:
generate:
cmds:
- git checkout branchname/{{.RELEASE}}
- {{if .TAG | eq "true"}}git tag -a {{.RELEASE}} -m "Tagging {{.RELEASE}}{{end}}
- git push -a
The tag command is a lot less readable, causing more chance of confusion and errors
Reacted by Devin Buhl, Maxi Fernandez, Misaka Mikoto, Mathew Onipe and devopstales
I would also like to have another kind of conditional in addition to status and preconditions.
My usecase is that I'm working on a library-style shared repository with Taskfiles, which can then be imported in all of our projects, so that we have the same tasks available everywhere.
I have a task generate-code which runs some kind of code generation, and also a generate-docs one. However, I don't want to call both of them manually, so I also have a task generate which simply combines both of them.
The problem is that not all of our projects are configured to generate documentation, so that task needs to check whether it should run or not.
I can use status for this, however it will print task: Task "generate-docs" is up to date when run in repos without documentation generation configured, which does not quite fit the situation, and more importantly, it will break when run with --force, which a developer might want to use for other reasons.
I cannot use preconditions, since this would cause the task to fail, which is not what I want here.
I cannot use a shell if, because I'm using the task: generate-docs syntax in the generate task and there is no shell involved. With the above example, I could have the generate-docs task run a shell script which checks the condition and just does nothing if the corresponding configuration is missing, but this is just a simplified example and there are scenarios with more deeply nested task structures, where this is not feasible.
To solve this, I'd like to have an option to skip the execution of a specific task based on a condition, but it must also skip the task when --force is set and must skip it without failing it. I don't really care whether this happens in form of a new field for either status or preconditions, or as a completely new field if/when/skip/whatever.
Iterate through all rules
1.. If a rule's if condition succeeds, decide what to do based on when
on_success - add the job to the pipeline if no previous pipeline failed (default behavior)
on_failure - add the job to the pipeline if any previous pipeline failed
never - DO NOT add the job to the pipeline, regardless of any previous status
always - add the job to the pipeline, regardless of any previous status
manual - add the job to the pipeline, but make it a manual action (have to click in UI)
delayed - add the job to the pipeline, but run with a delay
If a when does not match (only for on_success and on_failure), continue checking rules
If no rule's if matches, do not add the the job to the pipeline
This could be used (with minor alterations) for Task. But since there is no "failed" or "success" state (at least not being worked with, it is either success or the whole task ... command fails and execution is halted), it could be renamed to mode, with values fail (raise an error), skip (silently skip the task), warn (skip the task, show a warning, but continue execution). Possibly even force to always run and skip all other checks.
It could even be combined with rest of conditional executions - like status, deps, preconditions, sources, and generates.
tasks:
install:
rules:
# Skip when packages are installed
- if: "test -d node_modules"mode: skip# Runs by default, imagine an "- if: test 1 = 1"build:
rules:
# Skip on PROD
- if: "test {{ .ENV }} = PROD"mode: skip# Only rebuild when files changed
- sources: src/**/*generates: dist/main.jscmd: yarn build
Currently, we have status (skip on success, execute on failure), preconditions (execute on success, fail on failure), deps (same as preconditions, but those are tasks and run in parallel).
Activity
[-]Ability to Run Tasks Conditionally[/-][+]Add `if:` keyword to control when a task or command is ran?[/+]andreynering commentedon Dec 30, 2021
Hi @ProfessorManhattan,
Something I had in mind for a while is that we could potentially have an
ifkeyword for tasks and commands:or
NOTE: We already have
preconditions, which is similar but makes the call fail when an error is returned, which meansifstill makes sense to have for skipping without failing.ghostsquad commentedon Jan 7, 2022
isn't that what
statusis supposed to do? decide to skip a step?andreynering commentedon Jan 11, 2022
You have a good point, we'd have some intersection between these two features.
statuscurrently printsTask "foo" is up-to-datemessages, though. This is accurate for statuses but not for other reasons why you'd want to skip a task.Also,
ifwould be the opposite ofstatuswith regarding the expected status:ifruns on zero,statusruns on non-zero statuses.So, I don't have a strong opinion, but maybe it would still make sense to have both
ifandstatus. Alternatively, we could addif:only to commands and not to the task itself.ProfessorManhattan commentedon Jan 16, 2022
Thanks @andreynering
Another thing we might want to keep in mind is handling the
--forcecommand line parameter. Currently, this will just ignore status which forces the user to wrap everything in ifs (even using status) for logic that doesn't relate to a particular project. In my use case, I share the same set of Taskfiles across hundreds of repositories of many different types - it is not feasible to generate the Taskfiles for each project type.. it would take too long.I would like to see an
if:that can be added at the least to the task and cmd level. It should also not be impacted by any--forcelogic. Take the following example:Both the
if:andstatus:are used in this example. Theif:parameter makes sure GNOME is being run on the system and thestatus:is used to achieve idempotency. This would make even more sense if we were running a command that requires a reboot. In this example, we would need the--forcecommand to obey theif:or else we would get an error if GNOME is not on the system.Currently, with any complex flows that rely on status, things can easily get messy when using
--forcebut the--forcecommand could potentially be pretty useful for cache busting. I see adding anif:parameter as a possible solution.ssbarnea commentedon Jun 14, 2022
Probably the best use-case for if would be to add steps that depend only on specific platforms, like Windows, Linux, MacOS. Adding extra code for platform on each called shells script is a PITA, one that could be easily avoided with an "if".
andreynering commentedon Jan 5, 2023
For those interested, there's an ongoing discussion about a possible key specificly to select given OS/Arch on a task or command:
max-sixty commentedon Jan 6, 2023
A +1 for
if.I really over-use
status, which requires some mental gymnastics ("Only run this on ARM machines, which means status needs to be 0 on x86 machines, so raise an error on ARM"!), and isn't compatible with--force("now we're running it on x86 machines?!")Though I do empathize that it still has lots of overlap with
status...titpetric commentedon Jun 30, 2023
@andreynering i have a couple of env vars where
ifwould be useful. I'd be willing to open up a PR if there isn't anything in flight, going with your proposal in the reply. In combination with #1220 this would allow us to put most of our release pipeline into taskfiles, enabling matrix tests and targeting along with that "run offline" concept.andreynering commentedon Jun 30, 2023
@titpetric Contributions are welcome! I would advise you to wait until #1220 is merged to avoid any conflicts. Also, that would allow you to test both features together.
JonZeolla commentedon Aug 1, 2023
FYI #1220 has been merged
max-sixty commentedon Aug 1, 2023
Though IIUC this is a bit different —
forrather thanif?7 remaining items
trulede commentedon Oct 18, 2024
I would not go down the path of IF and ELSE. If you really need such a complexity then just write a bash script and be done with it.
Better is to use STATUS to evaluate the condition for which a TASK should run. That effectively gives you the IF/ELSE logic you need, and you will get a better outcome. So, for you that might mean a TASK where the status checks for the absence of an installed dependency, and when missing, the commands install that dependency.
This is I think, not very complicated to try.
Firesphere commentedon Oct 24, 2024
I don't think
statuscovers what anifwould mean.Aside from semantics, where using "status" as an "if" simply doesn't make sense, I think an
ifoption would be very useful.If I take the following:
That
ifconstruct is a lot more readable than using a status, which does a test, and furthermore, it allows me to runtask generate TAG=true RELEASE=1.2.3Currently, the task is constructed like so
The tag command is a lot less readable, causing more chance of confusion and errors
Diaphteiros commentedon Mar 10, 2025
I would also like to have another kind of conditional in addition to
statusandpreconditions.My usecase is that I'm working on a library-style shared repository with Taskfiles, which can then be imported in all of our projects, so that we have the same tasks available everywhere.
I have a task
generate-codewhich runs some kind of code generation, and also agenerate-docsone. However, I don't want to call both of them manually, so I also have a taskgeneratewhich simply combines both of them.The problem is that not all of our projects are configured to generate documentation, so that task needs to check whether it should run or not.
I can use
statusfor this, however it will printtask: Task "generate-docs" is up to datewhen run in repos without documentation generation configured, which does not quite fit the situation, and more importantly, it will break when run with--force, which a developer might want to use for other reasons.I cannot use
preconditions, since this would cause the task to fail, which is not what I want here.I cannot use a shell
if, because I'm using thetask: generate-docssyntax in thegeneratetask and there is no shell involved. With the above example, I could have thegenerate-docstask run a shell script which checks the condition and just does nothing if the corresponding configuration is missing, but this is just a simplified example and there are scenarios with more deeply nested task structures, where this is not feasible.To solve this, I'd like to have an option to skip the execution of a specific task based on a condition, but it must also skip the task when
--forceis set and must skip it without failing it. I don't really care whether this happens in form of a new field for eitherstatusorpreconditions, or as a completely new fieldif/when/skip/whatever.Diaphteiros commentedon Mar 10, 2025
@gedw99 I'm not sure I fully understand what you mean. Can you give me an example somehow?
DerpgonCz commentedon May 21, 2025
To add to this, GitLab CI has a nice system for deciding whether to add a job to the pipeline: https://docs.gitlab.com/ci/jobs/job_rules/#rules-examples
Basically:
1.. If a rule's
ifcondition succeeds, decide what to do based onwhenon_success- add the job to the pipeline if no previous pipeline failed (default behavior)on_failure- add the job to the pipeline if any previous pipeline failednever- DO NOT add the job to the pipeline, regardless of any previous statusalways- add the job to the pipeline, regardless of any previous statusmanual- add the job to the pipeline, but make it a manual action (have to click in UI)delayed- add the job to the pipeline, but run with a delaywhendoes not match (only foron_successandon_failure), continue checking rulesifmatches, do not add the the job to the pipelineThis could be used (with minor alterations) for Task. But since there is no "failed" or "success" state (at least not being worked with, it is either success or the whole
task ...command fails and execution is halted), it could be renamed tomode, with valuesfail(raise an error),skip(silently skip the task),warn(skip the task, show a warning, but continue execution). Possibly evenforceto always run and skip all other checks.It could even be combined with rest of conditional executions - like
status,deps,preconditions,sources, andgenerates.Currently, we have
status(skip on success, execute on failure),preconditions(execute on success, fail on failure),deps(same aspreconditions, but those are tasks and run in parallel).vitonsky commentedon Dec 6, 2025
Is there any updates on it?
Issue was created in 2021, it's about 5 years ago. Will it be implemented?
andreynering commentedon Dec 7, 2025
@vitonsky We for sure want to have this. It's mostly a matter of finding the time to implement it.
andreynering commentedon Jan 21, 2026
Hello everyone. This is finally implemented on:
It should be released soon!