Skip to content

Commit

Permalink
feat: Support podman container manager ⚓ (#145)
Browse files Browse the repository at this point in the history
- Add `podman` container manager. Essentially the same as `docker` except we mount with 
  `--userns=keep-id:uid=1000,gid=1000`.
- Multiple managers can be specified with `git hooks config container-manager-types --set --global "docker, podman`.


Update-Info: Container manager `podman` is now supported. See Readme.
  • Loading branch information
gabyx authored Feb 20, 2024
1 parent 5b92a58 commit db6769c
Show file tree
Hide file tree
Showing 21 changed files with 561 additions and 176 deletions.
1 change: 1 addition & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ workflows:
"test-corehookspath",
"test-whitespace",
"test-testsuite",
"test-testsuite-podman",
"test-rules",
]
filters: &filters
Expand Down
60 changes: 48 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -700,20 +700,27 @@ the missing Git LFS hooks will be installed too.

## Running Hooks in Containers

You can run hooks containerized over a container manager such as `docker`
(others such as `podman` etc. are not yet implemented). This relieves the
maintainer of a Githooks shared repo from dealing with _"It works on my
machine!"_
You can run hooks containerized over a container manager such as `docker`. This
relieves the maintainer of a Githooks shared repo from dealing with _"It works
on my machine!"_

To enable containerized hook runs set the Git config variable either locally or
globally with

```shell
git hooks config enable-containerized-hooks [--global] --set
git hooks config enable-containerized-hooks [--global] --set true
```

to `true` or use the environment variable
`GITHOOKS_CONTAINERIZED_HOOKS_ENABLED=true`.
or use the environment variable `GITHOOKS_CONTAINERIZED_HOOKS_ENABLED=true`.

Optionally set the container manager (default is `docker`) like

```shell
git hooks config container-manager-types [--global] --set "podman,docker"
```

The container manager types can be a list from \[`docker`, `podman`\] where the
first valid one is used to run the hooks.

Running a hook in a container is achieved by specifying the image reference
(image name) inside a [hook run configuration](#hook-run-configuration), e.g.
Expand All @@ -731,7 +738,7 @@ image:
reference: "my-shellcheck:1.2.0"
```

which will launch the command `./myscript/checkit.sh` in a docker container
which will launch the command `./myscript/checkit.sh` in a container
`my-shellcheck:1.2.0`. The current Git repository where this hook is launched is
mounted as the current working directory and the relative path
`./myscript/checkit.sh` will be mangled to a path in the mounted read-only
Expand All @@ -743,11 +750,40 @@ have access to the same environment variables as on your host system. All
Githooks [environment variables](#environment-variables) are forwarded however
to the container run.

Running commands in containers which modify files on writable volumes has some
caveats and quirks with permissions which are host system dependent. Hongli Lai
summarized these troubles in a
**Note:** The images you run must be `rootless` (contain a `USER` statement) and
this user must have user/group id `1000` (Todo: We can loosen this requirement
if really needed). See the
[example](https://github.com/gabyx/Githooks-Shell/blob/main/githooks/container/Dockerfile).

### Podman Manager (rootless)

**This manager is strongly preferred due to better security and less hassle with
volume mounts.**

The containers are run with the following flags to `podman`:

- `--userns=keep-id:uid=1000,gid=1000`:
[_User namespace mapping_](https://docs.podman.io/en/v4.4/markdown/options/userns.container.html).
Maps the user/group id of the user running Githooks (your host user) to the
container user/group id `1000`. This means a host user with user/group id e.g.
4000 will be seen inside the container as user/group id 1000. This also works
for all volume mounts which will have `1000:1000` permission inside the
container.

### Docker Manager

The containers are run with the following flags to `docker`:

- `--user:<uid>:<gid>`: The container is run as the same user id and group id as
the user which runs Githooks (your host user). See the note below why this is
the case.

**Note:** Running commands in containers which modify files on writable volumes
has some caveats and quirks with permissions which are host system dependent.
Hongli Lai summarized these troubles in a
[very good article](https://www.fullstaq.com/knowledge-hub/blogs/docker-and-the-host-filesystem-owner-matching-problem).
Long story short, **you should use
Long story short if the images are run with the `docker` manager, **you should
use
[`MatchHostFsOwner`](https://github.com/FooBarWidget/matchhostfsowner/releases)**
which counter acts these permission problems neatly by installing
[this into your hook's sidecar container](https://github.com/gabyx/Githooks-Shell/blob/main/githooks/container/Dockerfile#L29).
Expand Down
1 change: 1 addition & 0 deletions docs/cli/git_hooks_config.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ git hooks config
* [git hooks](git_hooks.md) - Githooks CLI application
* [git hooks config clone-branch](git_hooks_config_clone-branch.md) - Changes the Githooks clone url used for any update.
* [git hooks config clone-url](git_hooks_config_clone-url.md) - Changes the Githooks clone url used for any update.
* [git hooks config container-manager-types](git_hooks_config_container-manager-types.md) - Set container manger types to use (see `enable-containerized-hooks`).
* [git hooks config delete-detected-lfs-hooks](git_hooks_config_delete-detected-lfs-hooks.md) - Change the behavior for detected LFS hooks during install.
* [git hooks config disable](git_hooks_config_disable.md) - Disables Githooks in the current repository or globally.
* [git hooks config disable-shared-hooks-update](git_hooks_config_disable-shared-hooks-update.md) - Disable/enable automatic updates of shared hooks.
Expand Down
29 changes: 29 additions & 0 deletions docs/cli/git_hooks_config_container-manager-types.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
## git hooks config container-manager-types

Set container manger types to use (see `enable-containerized-hooks`).

### Synopsis

Set container manager types to use where the first valid one is taken and used.
If unset `docker` is used.

```
git hooks config container-manager-types [flags]
```

### Options

```
--print Print the setting.
--set Set the setting.
--reset Reset the setting.
--local Use the local Git configuration (default).
--global Use the global Git configuration.
-h, --help help for container-manager-types
```

### SEE ALSO

* [git hooks config](git_hooks_config.md) - Manages various Githooks configuration.

###### Auto generated by spf13/cobra
17 changes: 8 additions & 9 deletions docs/dialog/dialog.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,11 @@ dialog

### SEE ALSO

- [dialog entry](dialog_entry.md) - Shows a entry dialog.
- [dialog file-save](dialog_file-save.md) - Shows a file save dialog.
- [dialog file-selection](dialog_file-selection.md) - Shows a file selection
dialog.
- [dialog message](dialog_message.md) - Shows a message dialog.
- [dialog notify](dialog_notify.md) - Shows a notification.
- [dialog options](dialog_options.md) - Shows a options selection dialog.

###### Auto generated by spf13/cobra
* [dialog entry](dialog_entry.md) - Shows a entry dialog.
* [dialog file-save](dialog_file-save.md) - Shows a file save dialog.
* [dialog file-selection](dialog_file-selection.md) - Shows a file selection dialog.
* [dialog message](dialog_message.md) - Shows a message dialog.
* [dialog notify](dialog_notify.md) - Shows a notification.
* [dialog options](dialog_options.md) - Shows a options selection dialog.

###### Auto generated by spf13/cobra
14 changes: 7 additions & 7 deletions docs/dialog/dialog_entry.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,16 @@ Shows a entry dialog.

### Synopsis

Shows a entry dialog similar to `zenity`. Currently extra buttons are not
supported on all platforms. Unix/Windows supports multiple extra buttons, MacOS
does not.
Shows a entry dialog similar to `zenity`.
Currently extra buttons are not supported on all platforms.
Unix/Windows supports multiple extra buttons, MacOS does not.

# Exit Codes:

- `0` : User pressed `Ok`.
- `1` : User pressed `Cancel` or closed the dialog.
- `2` : The user pressed an extra button. The output contains the index of that
button.
- `2` : The user pressed an extra button.
The output contains the index of that button.

```
dialog entry
Expand Down Expand Up @@ -54,6 +54,6 @@ dialog entry

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
10 changes: 5 additions & 5 deletions docs/dialog/dialog_file-save.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ Shows a file save dialog.
### Synopsis

Shows a file save dialog similar to `zenity`.

# Exit Codes:

- `0` : User pressed `Ok`. The output contains the selected paths separated by
`--separator`. All paths use forward slashes on any platform.
- `0` : User pressed `Ok`. The output contains the selected paths
separated by `--separator`. All paths use forward slashes
on any platform.
- `1` : User pressed `Cancel` or closed the dialog.
- `5` : The dialog was closed due to timeout.

Expand Down Expand Up @@ -48,6 +48,6 @@ dialog file-save

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
9 changes: 5 additions & 4 deletions docs/dialog/dialog_file-selection.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Shows a file selection dialog similar to `zenity`.

# Exit Codes:

- `0` : User pressed `Ok`. The output contains the selected paths separated by
`--separator`. All paths use forward slashes on any platform.
- `0` : User pressed `Ok`. The output contains the selected paths
separated by `--separator`. All paths use forward slashes
on any platform.
- `1` : User pressed `Cancel` or closed the dialog.
- `5` : The dialog was closed due to timeout.

Expand Down Expand Up @@ -47,6 +48,6 @@ dialog file-selection

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
13 changes: 7 additions & 6 deletions docs/dialog/dialog_message.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,16 @@ Shows a message dialog.

Shows a message dialog similar to `zenity`.

Currently only one extra button is supported on all platforms. Only Unix
supports multiple extra buttons. Use `options` to have more choices.
Currently only one extra button is supported on all platforms.
Only Unix supports multiple extra buttons.
Use `options` to have more choices.

# Exit Codes:

- `0` : User pressed `Ok`.
- `1` : User pressed `Cancel` or closed the dialog.
- `2` : The user pressed an extra button. The output contains the index of that
button.
- `2` : The user pressed an extra button.
The output contains the index of that button.

```
dialog message
Expand Down Expand Up @@ -54,6 +55,6 @@ dialog message

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
4 changes: 2 additions & 2 deletions docs/dialog/dialog_notify.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,6 @@ dialog notify

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
17 changes: 9 additions & 8 deletions docs/dialog/dialog_options.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,18 @@ Shows a options selection dialog.

Shows a list selection dialog similar to `zenity`.

Extra buttons are only supported on Unix and Windows. If not using `--multiple`
you can also use the button style options with `--style 1` which uses buttons
instead of a listbox.
Extra buttons are only supported on Unix and Windows.
If not using `--multiple` you can also use the
button style options with `--style 1` which uses buttons instead
of a listbox.

# Exit Codes:

- `0` : `Ok` was pressed. The output contains the indices of the selected items
separated by `--separator`.
separated by `--separator`.
- `1` : `Cancel` was pressed or the dialog was closed.
- `2` : The user pressed an extra button. The output contains the index of that
button on the first line.
- `2` : The user pressed an extra button.
The output contains the index of that button on the first line.
- `5` : The dialog was closed due to timeout.

```
Expand Down Expand Up @@ -61,6 +62,6 @@ dialog options

### SEE ALSO

- [dialog](dialog.md) - Githooks dialog application similar to `zenity`.
* [dialog](dialog.md) - Githooks dialog application similar to `zenity`.

###### Auto generated by spf13/cobra
###### Auto generated by spf13/cobra
56 changes: 56 additions & 0 deletions githooks/cmd/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,34 @@ func runSearchDir(ctx *ccm.CmdContext, opts *SetOptions) {
}
}

func runContainerManagerTypes(ctx *ccm.CmdContext, opts *SetOptions, gitOpts *GitOptions) {
opt := hooks.GitCKContainerManager
localOrGlobal := "locally" // nolint: goconst
if gitOpts.Global {
localOrGlobal = "globally" // nolint: goconst
}

scope := wrapToGitScope(ctx.Log, gitOpts)
switch {
case opts.Set:
val := strings.Join(opts.Values, ",")
err := ctx.GitX.SetConfig(opt, val, scope)
ctx.Log.AssertNoErrorPanicF(err, "Could not set Git config '%s'.", opt)
ctx.Log.InfoF("Container manager types is set to '%s' %s.", val, localOrGlobal)

case opts.Reset:
err := ctx.GitX.UnsetConfig(opt, scope)
ctx.Log.AssertNoErrorPanicF(err, "Could not unset Git config '%s'.", opt)
ctx.Log.InfoF("Container manager types is unset %s.", localOrGlobal)

case opts.Print:
conf := ctx.GitX.GetConfig(opt, scope)
ctx.Log.InfoF("Container manager types is set to '%s' %s.", conf, localOrGlobal)
default:
cm.Panic("Wrong arguments.")
}
}

func runContainerizedHooksEnable(ctx *ccm.CmdContext, opts *SetOptions, gitOpts *GitOptions) {
opt := hooks.GitCKContainerizedHooksEnabled
localOrGlobal := "locally" // nolint: goconst
Expand Down Expand Up @@ -725,6 +753,33 @@ func configContainerizedHooksEnabledCmd(
configCmd.AddCommand(ccm.SetCommandDefaults(ctx.Log, enableCmd))
}

func configContainerManagerTypesCmd(
ctx *ccm.CmdContext,
configCmd *cobra.Command,
setOpts *SetOptions,
gitOpts *GitOptions) {

enableCmd := &cobra.Command{
Use: "container-manager-types [flags]",
Short: "Set container manger types to use (see 'enable-containerized-hooks').",
Long: `Set container manager types to use where the first valid one is taken and used.
If unset 'docker' is used.`,
Run: func(cmd *cobra.Command, args []string) {
if !gitOpts.Local && !gitOpts.Global {
gitOpts.Local = true
}

runContainerManagerTypes(ctx, setOpts, gitOpts)
}}

optsPSR := createOptionMap(true, false, true)

configSetOptions(enableCmd, setOpts, &optsPSR, ctx.Log, 1, 2) // nolint: gomnd
enableCmd.Flags().BoolVar(&gitOpts.Local, "local", false, "Use the local Git configuration (default).")
enableCmd.Flags().BoolVar(&gitOpts.Global, "global", false, "Use the global Git configuration.")
configCmd.AddCommand(ccm.SetCommandDefaults(ctx.Log, enableCmd))
}

func configSearchDirCmd(ctx *ccm.CmdContext, configCmd *cobra.Command, setOpts *SetOptions) {

searchDirCmd := &cobra.Command{
Expand Down Expand Up @@ -1076,6 +1131,7 @@ func NewCmd(ctx *ccm.CmdContext) *cobra.Command {
configCloneBranchCmd(ctx, configCmd, &setOpts)

configContainerizedHooksEnabledCmd(ctx, configCmd, &setOpts, &gitOpts)
configContainerManagerTypesCmd(ctx, configCmd, &setOpts, &gitOpts)

configSharedCmd(ctx, configCmd, &setOpts, &gitOpts)
configDisableSharedHooksUpdate(ctx, configCmd, &setOpts, &gitOpts)
Expand Down
Loading

0 comments on commit db6769c

Please sign in to comment.