Skip to content

Conversation

@sezaru
Copy link

@sezaru sezaru commented Jul 24, 2023

This PR basically removes the option to define the MFA arity function, instead it expects all MFA functions to have arity 1.

The reason for that is that git will send dynamic arity for the same hooks depending in the git command arguments you are passing.

For example, for the hook prepare_commit_msg, if I run this command: git commit, git will send 1 argument to the MFA, in that case I would need to set the MFA with arity 1. But, if I run this command git commit -am "some message", then git will send 2 arguments to the MFA.

And since we can't define 2 arities for the same MFA, this breaks the current logic.

Removing the arity option and expecting arity 1 always solves the issue since the MFA will always receive a list of arguments.

So, for the above case, I could implement the MFA function using pattern match for each arity expected like this:

def run([arg1, arg2]), do: ...
def run([arg1], do: ...

Or, do something like this if you are only interested in the first argument (like I do):

def run([commit_msg_file | _]), do: ...

@qgadrian
Copy link
Owner

qgadrian commented Aug 2, 2023

Thanks @sezaru!
It indeed makes more sense without having fixed arguments ☺️

I left a comment about an unrelated change, once we clarify we can merge this PR.

You can also all the hooks which are configured with `mix git_hooks.run all`.
"""

@requirements ["app.start"]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was not aware of this annotation (for reference). I'm still not sure how this is needed, but in any case, shouldn't be @requirements ["compile"] instead?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So, about this, I'm not sure if that is the best approach either, and there is a Mix command that we can add to the code itself so this only runs when the user is actually using MFA (since this makes the hooks take more time to start since it needs to first start the project itself).

Maybe there is another alternative for that or maybe I'm just using it wrong, but basically what this does is making your project code available when the MFA hooks are running. In other words, if you create a MFA inside your project, and try to use it, the hook will not find your MFA module since it was never loaded in the first place.

The only way I found to workaround this without having to use the @requirements trick was to move my MFA hooks to a separated project and use it as a dependency to my main project, when my MFA modules are inside a dependency it becomes available for some reason and the hooks work fine.

If my explanation is not clear enough I can try to create a small project just to showcase the issue.

Also, at least for me, adding @requirements ["compile"] didn't made my project code/modules available during the hooks execution, did it work for you?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @qgadrian , I just pushed a new commit that changes the current behavior for MFAs a little bit.

Basically I removed the @requirements ["app.start"] and replaced it with an on-demand load of the app.

The logic will try to run the MFA as before the first time (so, in case the MFA is from a dependency, this will work just fine and it will be way faster since there is no need to load the app at all), if the MFA run fails with a UndefinedFunctionError, then the code will load the full app with Mix.Task.run("app.start") and re-run the MFA code.

In my tests this is working great and, as long as the hook code is in a dependency, not the main project, it will run pretty fast.

What do you think?

Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sezaru what about always starting the app in that case? If it is already running it will be a :noop, so it should be deterministic.
But in any case, I will give it a try as I haven't set up any example project yet to check the MFA hooks configuration.

@qgadrian qgadrian force-pushed the master branch 3 times, most recently from dba067b to 32ec97b Compare November 29, 2024 04:54
Eduardo and others added 5 commits January 21, 2025 17:51
Some people might be using `mfa` for their module configuration.
Removing the arity support will break their config and, most probably,
their workflow pipeline.

This commit adds backward compatibility for the arity, and a deprecation
warning will be included in the next release.
@qgadrian qgadrian force-pushed the makes_mfa_more_flexible branch from 3db3572 to cc7b48b Compare January 21, 2025 17:19
@qgadrian
Copy link
Owner

Added backward compatibility for current configs using Elixir's mfa so next release won't potentially break their pipeline

@qgadrian qgadrian merged commit 1ec355e into qgadrian:master Jan 21, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants