Especially for Github Actions, which is stateless. If you want to reuse computation within their VMs (i.e. not do a fresh build / test / whatever), you can't rely on Just or Make
A problem with Make is that it literally shells out, and the syntax collides. For example, the PID in Make is $$$$, because it's $$ in shell, and then you have to escape $ as $$ with Make.
I believe Just has similar syntax collisions. It's fine for simple things, but when it gets complex, now you have {{ just vars }} as well as $shell_vars.
It's simpler to "just" use shell vars, and to "just" use shell.
Shell already has a lot of footguns, and both Just and Make only add to that, because they add their own syntax on top, while also depending on shell.
Make targets look suspiciously like functions (or procedures), but they actually aren't.
Good facilities for arguments, builtins like absolute locations -- there are a ton of benefits (see the README).
Here is an example of a "complex" Makefile I use to help manage Helm deployments (https://github.com/peterwwillis/devops-infrastructure/blob/m...). It uses canned recipes, functions (for loops), default targets, it includes targets and variables from other Makefiles, conditionally crafts argument lists, and more. (It's intended to be a "default" Makefile that is overridden by an additional Makefile.inc file)
I could absolutely rewrite that in a shell script, but I would need to add a ton of additional code to match the existing functionality. Lines of code (and complexity) correlates to bugs, so fewer lines of code = less bugs, so it's easier to maintain, even considering the Make-specific knowledge required.
They say "use the best tool for the job". As far as I've found, for a job like that, Make fits the best. If some day somebody completely re-writes all the functionality of Make in a less-obnoxious way, I'll use that.
They are still phony at heart in this case, even if you don't declare them .PHONY.
Make really wants to produce files; if your targets don't produce the files they are named for you are going to run into trouble (or have to be rather careful to avoid the sharp edges).
> They say "use the best tool for the job". As far as I've found, for a job like that, Make fits the best. If some day somebody completely re-writes all the functionality of Make in a less-obnoxious way, I'll use that.
You could try eg Shake (https://shakebuild.com/), but it requires some Haskell.
It is so much better to run scripts with Just than it is doing it with Make. And although I frankly tend to prefer using a bash script directly (much as described by the parent commenter), Just is much less terrible than Make.
Now the only problem is convincing teams to stop following the Make dogma, because it is so massively ingrained and it has so many probems and weirdnesses that just don't add anything if you just want a command executor.
The PHONY stuff, the variable scaping, the every-line-is-a-separate-shell, and just a lot of stuff that don't help at all.