kisslinux / kiss

KISS Linux - Package Manager
https://kisslinux.github.io
MIT License
464 stars 62 forks source link

[RFC] System-wide hooks #229

Closed illiliti closed 3 years ago

illiliti commented 3 years ago

The main idea is to provide packages that install system hooks. Current design has no way to do that without hacks.

I propose to implement something like we already have in init -> https://github.com/kisslinux/init/blob/master/lib/init/rc.lib#L50-L57 (this was originally implemented to make way for https://github.com/illiliti/kiss-encryption)

This feature allows having package-based approach, which means that users will be able to share their hooks as packages(which is nice!).

EDIT: Context -> https://libera.irclog.whitequark.org/kisslinux/2021-07-14#30270813

jedahan commented 3 years ago

Just to experiment with, I have this in https://github.com/jedahan/kiss-repo

If you look at kiss-hooks-build-duration, which depends on kiss-hooks, you can see three files in total installed:

# /etc/profile.d/kiss-hooks.sh 
export KISS_HOOK=/etc/kiss/hooks/kiss-hooks
#/etc/kiss/hooks/kiss-hooks
for hook in /etc/kiss/hooks/*.sh; do
    [ -e "$hook" ] || [ -L "$hook" ] || continue
    TYPE=${TYPE} PKG=${PKG} DEST=${DEST} . "$hook"
done

and #/etc/kiss/hooks/build-duration.sh, which is just a copy paste from https://kisslinux.xyz/package-manager#6.4

jedahan commented 3 years ago

Another implementation could be something like KISS_HOOKS_PATH variable, that uses :-delimited list of paths to all hooks, to be iterated over.

This would not simplify the packaging of hooks, but it would make them even more separate as each hook could just self-install export KISS_HOOKS_PATH=/path/to/my/installed/hook:$KISS_HOOKS_PATH to a file in /etc/profile.d.

jedahan commented 3 years ago

Another option would be having KISS_HOOKS_PATH be paths to directories of hooks, and having each file in that directory named after the $TYPE it is hooking into, similar to how git does it. Have to think more about the downsides of this one.

illiliti commented 3 years ago

I don't like KISS_HOOKS_PATH approach because it's can't be reliably used by packages. I prefer fixed directory.

/etc/kiss/hooks for user hooks. /usr/lib/kiss/hooks or /usr/share/kiss/hooks(preferred) for system-wide hooks installed by packages.

illiliti commented 3 years ago

Moreover, this idea gives more flexibility to user. We can drop hacky stuff like [0] and create a standalone package to remove garbage in /usr/share.

[0] https://github.com/kisslinux/repo/blob/master/extra/mpv/build#L16-L18

jedahan commented 3 years ago

I updated kiss-hooks to now default to looking in /etc/kiss/hooks/*.sh and /usr/share/kiss/hooks/*.sh. These can be override by changing KISS_HOOKS_PATH, which works similar to KISS_PATH.

jedahan commented 3 years ago

One more improvement: kiss-hooks@0.3 will now source hooks named after their type (e.g. post-package,pre-extract,pre-build,build-fail,post-build,pre-remove,pre-install,post-install, ...) so if you prefer git-style one-file-per hook, you can do that instead.

This is in addition to the regular sourcing of all files matching *.sh for all hooks.

jedahan commented 3 years ago

Latest kiss-hooks, only tested with busybox sh. Save it somewhere, and set KISS_HOOK to where you save it.

#!/bin/sh
_kiss_hooks_path=${KISS_HOOKS_PATH:-'/etc/kiss/hooks:/usr/share/kiss/hooks'}
IFS=:
for _hook_path in ${_kiss_hooks_path}; do set +f
  for _hook in "$_hook_path/"*; do
    [ -e "$_hook" ] || [ -L "$_hook" ] || continue
    case ${_hook##*/} in
      $TYPE|*.sh)
        TYPE=${TYPE} PKG=${PKG} DEST=${DEST} . "$_hook"
        ;;
    esac
  done
done
unset IFS
dylanaraps commented 3 years ago

NOTE: If this feature is added it will not be based around . file. Any system-wide hooks will not have access to package manager internals nor will they be able to modify the package manager behavior at runtime. They will merely be executables which are run at the designated time.

Also, what packages need this? Is there even a use-case?

Edit: If this is about making user hooks packages, I'm against this entirely.

illiliti commented 3 years ago

Any system-wide hooks will not have access to package manager internals nor will they be able to modify the package manager behavior at runtime.

Modifying internals is a drilling and error-prone. I would consider this as anti-pattern.

Is there even a use-case?

Use-case is to provide hooks as packages instead of messing with inconsistency and hacks of KISS_HOOK.

Moreover, this idea gives more flexibility to user. We can drop hacky stuff like [0] and create a standalone package to remove garbage in /usr/share.

[0] https://github.com/kisslinux/repo/blob/master/extra/mpv/build#L16-L18

dylanaraps commented 3 years ago

I will be removing the . file behavior entirely and replacing it with simply executing the files (like we do for build). If hooks then need information, it should be provided via arguments (edit: or environment variables where it makes sense) to the hook (which we can expand on later).

Edit: https://github.com/kisslinux/kiss/commit/d765dbd043d5a69a15875f2cd0ff81cdaaa2d97f

jedahan commented 3 years ago

NOTE: If this feature is added it will not be based around . file. Any system-wide hooks will not have access to package manager internals nor will they be able to modify the package manager behavior at runtime. They will merely be executables which are run at the designated time.

That seems like excellent changes

Also, what packages need this?

I do not have any packages that need this

Is there even a use-case?

Yeah, a few. My use cases are making it easy to spin up new vms, have the same hooks installed on multiple machines, etc.

Edit: If this is about making user hooks packages, I'm against this entirely.

I do not think it is a good idea to make official hooks packages.

I do think its useful too be able to package up hooks for all the benefits packaging up any software provides.


I think the original motivation of this issue, is a general 'hooks could use some love', correct me if I am wrong @illiliti .

The transition from hooks as 'sourced shell scripts' to simple executables is a big improvement.

dylanaraps commented 3 years ago

I do think its useful too be able to package up hooks for all the benefits packaging up any software provides.

Nothing stops you from packaging hooks right now (and installing them somewhere). You'd just need to have a matching KISS_HOOK environment variable (pointing to the chosen system location) on each machine with the package installed.

The transition from hooks as 'sourced shell scripts' to simple executables is a big improvement.

What else are you looking for specifically? I'm opposed to some kind of KISS_HOOK_PATH for multi-file hooks as this can be mimicked very easily using the current method (using KISS_HOOK to spawn child based on hook type).

jedahan commented 3 years ago

I do think its useful too be able to package up hooks for all the benefits packaging up any software provides.

Nothing stops you from packaging hooks right now (and installing them somewhere). You'd just need to have a matching KISS_HOOK environment variable (pointing to the chosen system location) on each machine with the package installed.

Yeah, I am packaging hooks right now, and it works well.

The transition from hooks as 'sourced shell scripts' to simple executables is a big improvement.

What else are you looking for specifically? I'm opposed to some kind of KISS_HOOK_PATH for multi-file hooks as this can be mimicked very easily using the current method (using KISS_HOOK to spawn child based on hook type).

I am content with the current behavior, as I was able to do exactly what I wanted with our current system.

That said, is there a downside to renaming KISS_HOOK to KISS_HOOKS, and allowing it to be a : delimited set of paths to hooks to execute? In the case where there is only one item, it works exactly the same as today. The benefit is that people would not need to either merge all hooks into one mega-hook, or re-derive the wrapper script I ended up writing anyway.

Basically it boils down to 'if enough people end up writing a wrapper script for their hooks, maybe it should support that use-case. Just to be clear: I think this is a super low priority thing, as I can get the behavior I want today. I'll let others speak for themselves, though my understanding that the [RFC] tag in the title of this issue was more about exploration and discussion to see if there were 'better' ways, in a vague sense.

dylanaraps commented 3 years ago

I understand now. Pushed a commit which makes KISS_HOOK take a colon separated list of absolute file paths. Basically, if we want packages to provide system-wide hooks, have them install to /var/db/kiss/hooks and let the user add the hook to their KISS_HOOK variable. It's entirely opt-in then.

I pushed a second commit to make hooks in the system-wide directory usable by their basename.

ls -1 /var/db/kiss/hooks
test_hook
no-docs

export KISS_HOOK=no-docs:test_hook:/path/to/absolute/hook

And... finally, I pushed a third commit to add kiss hooks which lists all hooks in the system-wide directory.

dylanaraps commented 3 years ago

Pushed one more commit to show the package name in kiss hooks (same output as kiss a). Let me know your thoughts.

dylanaraps commented 3 years ago

Thinking about this some more. Would it make more sense for the system-wide layout to be: /var/db/kiss/installed/hooks/pkg_name/<list of hooks>. This way we can have multiple hooks with the same name. You'd then match with:

Edit: Let's just keep it simple.

Current behavior in master:

jedahan commented 3 years ago

Very cool. I think it would be even simpler to not have the implicit /var/db/kiss/hooks prefix to make it similar to KISS_PATH, or to have KISS_PATH contain implicit /var/db/kiss/repos to be more similar to hooks, but maybe that is too nitpicky.

Even with no more changes, thank you for spending the time to understand and improve hooks in general.

dylanaraps commented 3 years ago

OK. We can drop the special handling of /var/db/kiss/hooks and keep it totally free.

Thanks for the feedback.

Next up we should discuss what extra information you'd like the package manager to expose to hooks and also any other hook types which you'd like to see added. No rush on this, whenever you have the time. Will open a new issue for it.

dylanaraps commented 3 years ago

OK. Now the behavior is as follows:

dylanaraps commented 3 years ago

New issue opened here: https://github.com/kisslinux/kiss/issues/234