daelvn/alfons

[feature request] recursive loading

natnat-mc opened this issue · 7 comments

Alfons currently allows loading a taskfile from a specific path and with a specific language.
This currently allows executing taskfiles located elsewhere in the filesystem, and setting aliases like alias alm='alfons --file /home/codinget/.alfons/moon.moon' to run common tasks from everywhere.

This feature request would add recursive taskfile loading, that would try loading Alfons.moon, Alfons.lua, then ../Alfons.moon, ../Alfons.lua, then ../../Alfons.moon, ../../Alfons.lua, and recursively until either a taskfile is found, or the root is reached.
This would allow for project-wide or multi-project-wide taskfiles to be used from any directory within the project, and applying to the user's current directory.
One use case would be to have a taskfile with common tasks (format, rebuild, clean, package) at the root of a git repository containing several projects, and which could be used with a simple alfons invocation.

So I have something that loads a taskfile from the fs recursively. Link to the commit
The question now is:

  • do I keep Alfons in the directory you invoked it from, to execute local tasks from a common taskfile
  • do I make Alfons change directory to where it found the taskfile to execute project-wide tasks from anywhere in the project
  • do I add a flag to pick which one to do
    • and if yes, what should be the default

Also I don't know if recursive loading should be considered a breaking change: it technically allows stuff that would have previously failed, but stuff that already worked will still continue to work.

I feel like Alfons should move to the directory where the taskfile was found? I think that if I were in a subfolder, and I was loading a taskfile from a folder above, I would have written that taskfile using a project-wide form. If I needed the paths to be local, I would have a local taskfile. At least that's how I see it. I think a flag won't be necessary.

And yeah definitely not a breaking change, this would become 4.5.

I was thinking of taskfiles like this one for local tasks:

tasks:
	format: =>
		sh "fish -c 'clang-format -i **.cpp'"
	compile: =>
		sh "make"
	run: =>
		sh "make run"
	git: =>
		sh "git add ."
		sh "git commit -m 'Add subproject #{fs.dirname!\match '[\\/]([^\\/]+)$'}'"
		sh "git push"

Without moving to the taskfile's directory, that would allow for this to be put in the git root, and used for each subproject of the repo (for monorepos, or class repositories for example), without copying the Alfons.moon to each subproject.

But arguably this isn't really required, since the tasks can issue fs.changeDir env.PWD, so defaulting to changing to the taskfile's directory does make sense.

However, this raises the question: should alfons change to the directory of taskfiles loaded via -f or --file as well, or only when doing recursive search?

But arguably this isn't really required, since the tasks can issue fs.changeDir env.PWD, so defaulting to changing to the taskfile's directory does make sense.

I'm thinking this could be made easier for the user with a helper function that automatically keeps it in the directory you invoked alfons from. Say you call it relative, you could have:

tasks:
	format: =>
		relative!
		sh "fish -c 'clang-format -i **.cpp'"
	compile: =>
		relative!
		sh "make"
	run: =>
		relative!
		sh "make run"
	git: =>
		relative!
		sh "git add ."
		sh "git commit -m 'Add subproject #{fs.dirname!\match '[\\/]([^\\/]+)$'}'"
		sh "git push"

It sounds like it could be done but I'm not sure how practical it is to implement. I'm also unsure if it should be a separate helper function or something like mode "relative":

tasks:
	run: =>
		mode "relative"
		sh "make run"

However, this raises the question: should alfons change to the directory of taskfiles loaded via -f or --file, or only when doing recursive search?

If you're using -f/--file to invoke a taskfile, I would imagine what the user wants is "Get that taskfile from there, and run it here", so I wouldn't say it has to change in this case, and instead only change when doing recursive search.

Alright, I'll look into relative!/mode "relative" (which would probably imply a "project" mode) when I get back home, thanks!

which would probably imply a "project" mode

I... guess? But it is something you would never write yourself, since we agreed on no flag to make it relative. I only suggested a mode function instead of relative! in case more flags are implemented in the future. Which is highly unlikely, but still, I wouldn't want to fuck over future me, or future you.