App::GitHooks(3pm)

πŸ“¦
version 1.9.0 Β· 2 versions
, in fedora 43

🌸 App::GitHooks πŸ’…

okay bestie, so this is the manual page for App::GitHooks β€” yes, the (3pm) one, we're in Perl territory, come on in, the water's fine 🫢

✨ NAME ✨

App::GitHooks β€” Extensible plugins system for git hooks. that's literally it, that's the whole vibe πŸ’–

πŸŽ€ VERSION πŸŽ€

Version 1.9.0 β€” mark it, know it, slay it.


🌈 DESCRIPTION 🌈

So App::GitHooks is this extensible and easy to configure git hooks framework, and the way it works is that it supports so many plugins. it's giving plug-and-play, no cap πŸ‘‘

Here's an example of it in action, running the pre-commit hook checks before the commit message can be entered:

Here is another example, with a Perl file that fails compilation this time:

(yeah those are the demo moments β€” one is the happy path running pre-commit checks before you even get to type a commit message, the other is the sad path where a Perl file just will not compile 😭)


πŸ¦‹ SYNOPSIS πŸ¦‹

  1. Install this distribution (with cpanm or your preferred CPAN client):
cpanm App::GitHooks
  1. Install the plugins you are interested in (with cpanm or your prefered CPAN client), as App::GitHooks does not bundle them. See the list of plugins below, but for example:
cpanm App::GitHooks::Plugin::BlockNOCOMMIT
cpanm App::GitHooks::Plugin::DetectCommitNoVerify
...
  1. Go to the git repository for which you want to set up git hooks, and run:
githooks install
  1. Enjoy!

like genuinely, enjoy. that's step four. iconic ✨


🌸 GIT REQUIREMENTS 🌸

App::GitHooks requires git v1.7.4.1 or above. no, we are not negotiating, that's the floor bestie πŸ’…


πŸ’œ VALID GIT HOOK NAMES πŸ’œ

  • applypatch-msg
  • pre-applypatch
  • post-applypatch
  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • pre-rebase
  • post-checkout
  • post-merge
  • pre-receive
  • update
  • post-receive
  • post-update
  • pre-auto-gc
  • post-rewrite

πŸ‘‘ OFFICIALLY SUPPORTED PLUGINS πŸ‘‘

  • App::GitHooks::Plugin::BlockNOCOMMIT β€” Prevent committing code with #NOCOMMIT mentions. yeah it will catch you, bestie πŸ™ˆ
  • App::GitHooks::Plugin::BlockProductionCommits β€” Prevent commits in a production environment. do not commit in prod, i am begging 😭
  • App::GitHooks::Plugin::DetectCommitNoVerify β€” Find out when someone uses --no-verify and append the pre-commit checks to the commit message. snitch behavior and honestly? deserved πŸ”₯
  • App::GitHooks::Plugin::ForceRegularUpdate β€” Force running a specific tool at regular intervals. consistency queen πŸ’…
  • App::GitHooks::Plugin::MatchBranchTicketID β€” Detect discrepancies between the ticket ID specified by the branch name and the one in the commit message. the branch and the message have to agree, periodt πŸ’–
  • App::GitHooks::Plugin::PerlCompile β€” Verify that Perl files compile without errors. no broken Perl on my watch 🧚
  • App::GitHooks::Plugin::PerlCritic β€” Verify that all changes and addition to the Perl files pass PerlCritic checks. critic said what it said πŸŽ€
  • App::GitHooks::Plugin::PerlInterpreter β€” Enforce a specific Perl interpreter on the first line of Perl files. shebang enforcement, lowkey vital 🌸
  • App::GitHooks::Plugin::PgBouncerAuthSyntax β€” Verify that the syntax of PgBouncer auth files is correct. syntax check but make it pgbouncer ⭐
  • App::GitHooks::Plugin::PrependTicketID β€” Derive a ticket ID from the branch name and prepend it to the commit-message. free ticket ID, you're welcome πŸ’œ
  • App::GitHooks::Plugin::RequireCommitMessage β€” Require a commit message. an actual one. words. please πŸ™
  • App::GitHooks::Plugin::RequireTicketID β€” Verify that staged Ruby files compile.
  • App::GitHooks::Plugin::ValidatePODFormat β€” Validate POD format in Perl and POD files. POD stays pretty or it doesn't stay at all ✨

πŸ“ CONTRIBUTED PLUGINS πŸ“

  • App::GitHooks::Plugin::RubyCompile β€” Verify that staged Ruby files compile. ruby girlies we got you πŸ’–
  • App::GitHooks::Plugin::PreventTrailingWhitespace β€” Prevent trailing whitespace from being committed. the invisible menace, finally defeated πŸ¦‹

⭐ CONFIGURATION OPTIONS ⭐

πŸ’… Configuration format πŸ’…

App::GitHooks uses Config::Tiny, so the configuration should follow the following format:

general_key_1 = value
general_key_2 = value

[section_1]
section_1_key 1 = value

The file is divided between the global configuration options at the beginning of the file (such as general_key_1 above) and plugin specific configuration options which are located in distinct sections (such as section_1_key in the [section_1] section). so: top of file = everyone's business, sectioned = that plugin's business. iykyk πŸ’…

🌸 Configuration file locations 🌸

App::GitHooks supports setting custom options by creating one of the following files, which are searched in descending order of preference:

  • A file of any name anywhere on your system, if you set the environment variable GITHOOKSRC_FORCE to its path.

Note that you should normally use GITHOOKSRC. This option is provided mostly for testing purposes, when configuration options for testing in a reliable manner are of the utmost importance and take precedence over any repository-specific settings.

  • A .githooksrc file at the root of the git repository.

The settings will then only apply to that repository.

  • A file of any name anywhere on your system, if you set the environment variable GITHOOKSRC to its path.

Note that .githooksrc files at the top of a repository or in a user's home directory will take precedence over a file specified by the GITHOOKSRC environment variable.

  • A .githooksrc file in the home directory of the current user.

The settings will then apply to all the repositories that have hooks set up. Note that if .githooksrc file is defined at the root of a repository, that configuration file will take precedence over the one defined in the home directory of the current user (as it is presumably more specific). Auto-merge of options across multiple .githooksrc files in an inheritance fashion is not currently supported.

bestie note: there is no auto-merge across multiple .githooksrc files in an inheritance fashion right now. one wins, the others sit down. don't come for me, that's just what the page says 😭

πŸ’œ General configuration options πŸ’œ

  • project_prefixes β€” A comma-separated list of project prefixes, in case you want to use this in extract_ticket_id_from_commit or extract_ticket_id_from_branch.
project_prefixes = OPS, DEV
  • extract_ticket_id_from_commit β€” A regular expression with _one_ capturing group that will be applied to the first line of a commit message to extract the ticket ID referenced, if there is one.
extract_ticket_id_from_commit = /^($project_prefixes-\d+|--): /
  • extract_ticket_id_from_branch β€” A regular expression with _one_ capturing group that will be applied to branch names to extract a ticket ID. This allows creating one branch per ticket and having the hooks check that the commit messages and the branch names are in sync.
extract_ticket_id_from_branch = /^($project_prefixes-?\d+)/
  • normalize_branch_ticket_id β€” A replacement expression that normalizes the ticket ID captured with extract_ticket_id_from_branch.
normalize_branch_ticket_id = s/^(.*?)-?(\d+)$/\U$1-$2/
  • skip_directories β€” A regular expression to filter the directory names that should be skipped when analyzing files as part of file-level checks.
skip_directories = /^cpan(?:-[^\/]+)?\//
  • force_plugins β€” A comma-separated list of the plugins that must be present on the system and will be executed. If any plugins from this list are missing, the action will error out. If any other plugins not in this list are installed on the system, they will be ignored.
force_plugins = App::GitHooks::Plugin::ValidatePODFormat, App::GitHooks::Plugin::RequireCommitMessage
  • min_app_githooks_version β€” Specify the minimum version of App::GitHooks.
min_app_githooks_version = 1.9.0

🧚 Testing-specific options 🧚

  • limit_plugins β€” Deprecated. Use force_plugins instead.
  • force_interactive β€” Force the application to consider that the terminal is interactive (1) or non-interactive (0) independently of whether the actual STDOUT is interactive or not.
  • force_use_colors β€” Force the output to use colors (1) or to not use colors (0) independently of the ability of STDOUT to display colors.
  • force_is_utf8 β€” Allows the output to use utf-8 characters (1) or not (0), independently of whether the output declares supporting utf-8.
  • commit_msg_no_edit β€” Allows skipping the loop to edit the message when the commit message checks failed.

🌈 ENVIRONMENT VARIABLES 🌈

🌸 GITHOOKS_SKIP 🌸

Comma separated list of hooks to skip. A warning is issued for each hook that would otherwise be triggered.

GITHOOKS_SKIP=pre-commit,update

πŸ’– GITHOOKS_DISABLE πŸ’–

Works similarly to GITHOOKS_SKIP, but it skips all the possible hooks. Set it to a true value, e.g. 1.

GITHOOKS_DISABLE=1

✨ GITHOOKSRC ✨

Contains path to a custom configuration file, see "Configuration file locations" above.

πŸ’… GITHOOKSRC_FORCE πŸ’…

Similar to GITHOOKSRC but with a higher priority. See "Configuration file locations" above.


πŸŽ€ FUNCTIONS πŸŽ€

πŸ¦‹ run() πŸ¦‹

Run the specified hook.

App::GitHooks::run(
    name      => $name,
    arguments => \@arguments,
);

Arguments:

  • name (mandatory) β€” The name of the git hook calling this class. See the "VALID GIT HOOK NAMES" section for acceptable values.
  • arguments (optional) β€” An arrayref of arguments passed originally to the git hook.
  • exit (optional, default 1) β€” Indicate whether the method should exit (1) or simply return the exit status without actually exiting (0).

✨ METHODS ✨

🌸 new()

Bestie, this is where it all begins β€” you're making a brand new App::GitHooks object. ✨

my $app = App::GitHooks->new(
    name      => $name,
    arguments => \@arguments,
);

What you can pass in:

  • name (mandatory) β€” the name of the git hook that's calling this class. Wanna know which values count as acceptable? Go peek at the "VALID GIT HOOK NAMES" section, it's got you. πŸ’–
  • arguments (optional) β€” an arrayref of the arguments that were originally passed to the git hook.

πŸ¦‹ clone()

Clones the current object and overrides its properties with whatever arguments you hand it. It's giving "make a copy but make it your copy". πŸ’…

my $cloned_app = $app->clone(
    name => $hook_name, # optional
);
  • name (optional) β€” the name of the invoking hook.

πŸ’œ get_hook_plugins()

Returns an arrayref of all the plugins installed and available for one specific git hook on the current system. Obsessed. πŸ”₯

my $plugins = $app->get_hook_plugins(
    $hook_name
);

Arguments:

  • $hook_name β€” the name of the git hook you want to find available plugins for.

🌈 get_all_plugins()

Returns a hashref of the plugins available for every git hook. The whole roster, no cap. πŸ‘‘

my $all_plugins = $self->get_all_plugins();

πŸŽ€ get_config()

Grabs the configuration information for the current project.

my $config = $app->get_config();

⭐ force_non_interactive()

Okay so by default App::GitHooks figures out all by itself whether it's running in interactive mode β€” but this lets you force it to run in non-interactive mode instead. Main character energy: you decide. πŸ’…

# Retrieve the current setting.
my $force_non_interactive = $app->force_non_interactive();

# Force non-interactive mode.
$app->force_non_interactive( 1 );

# Go back to the default behavior of detecting the current mode.
$app->force_non_interactive( 0 );

πŸ’€ get_failure_character()

Returns a character to use to indicate a failure.

my $failure_character = $app->get_failure_character()

🌸 get_success_character()

Returns a character to use to indicate a success.

my $success_character = $app->get_success_character()

πŸ™ˆ get_warning_character()

Returns a character to use to indicate a warning.

my $warning_character = $app->get_warning_character()

🧚 get_staged_changes()

Returns an App::GitHooks::StagedChanges object that corresponds to the changes staged in the current project. It literally knows what you staged. πŸ‘€

my $staged_changes = $app->get_staged_changes();

πŸ“ use_colors()

Lets you turn off the use of colors in App::GitHooks's output. (I know, tragic, but sometimes you gotta. 😭)

# Retrieve the current setting.
my $use_colors = $app->use_colors();

# Disable colors in the output.
$app->use_colors( 0 );

πŸ’– ACCESSORS πŸ’–

get_repository()

Returns the underlying Git::Repository object for the current project.

my $repository = $app->get_repository();

get_remote_name()

Gets the name of the repository.

my $remote_name = $app->get_remote_name();

get_hook_name

Returns the name of the git hook that called the current instance. The way that it just knows who called it. ✨

my $hook_name = $app->get_hook_name();

get_command_line_arguments()

Returns the arguments that were passed originally to the git hook.

my $command_line_arguments = $app->get_command_line_arguments();

get_terminal()

Returns the App::GitHooks::Terminal object associated with the current instance.

my $terminal = $app->get_terminal();

🌈 DISPLAY METHODS 🌈

wrap()

Formats information while respecting the format width and the indentation. Aesthetic formatting, periodt. πŸ’…

my $string = $app->wrap( $information, $indent );

color()

Prints text with colors. Slay. πŸ”₯

$app->color( $color, $text );

πŸ”’ PRIVATE FUNCTIONS πŸ”’

_to_camelcase()

Converts a dash-separated string to camelcase.

my $camelcase_string = App::GitHooks::_to_camelcase( $string );

This function is useful for converting git hook names (commit-msg) into module names (CommitMsg). Lowkey a glow-up. ✨


_should_skip()

See the environment variables GITHOOKS_SKIP and GITHOOKS_DISABLE up above. This function returns the variable name that would be the reason to skip the given hook β€” or nothing at all.

return if _should_skip( $name );

πŸ“ NOTES πŸ“

Manual installation

Symlink your git hooks under .git/hooks to a file with the following content:

#!/usr/bin/perl

use strict;
use warnings;

use App::GitHooks;

App::GitHooks->run(
        name      => $0,
        arguments => \@ARGV,
);

After that, literally all you need to do is install the plugins you're interested in! Bestie, that's it. πŸŽ€

This distribution also includes a hooks/ directory that you can symlink / copy to .git/hooks/ instead, so you get all the hooks set up properly in one swoop. Efficiency icon behavior. πŸ‘‘

Important: adjust #!/usr/bin/perl as needed β€” if that line is not a valid interpreter, your git actions will fail with error: cannot run .git/hooks/[hook name]: No such file or directory. πŸ’€

πŸ› BUGS πŸ›

Please report any bugs or feature requests through the web interface at <https://github.com/guillaumeaubert/App-GitHooks/issues/new>. I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. We're in this together fr fr. 🫢


🫢 SUPPORT 🫢

You can find documentation for this module with the perldoc command.

perldoc App::GitHooks

You can also look for information at:

  • GitHub's request tracker

<https://github.com/guillaumeaubert/App-GitHooks/issues>

  • AnnoCPAN: Annotated CPAN documentation

<http://annocpan.org/dist/app-githooks>

  • CPAN Ratings

<http://cpanratings.perl.org/d/app-githooks>

  • MetaCPAN

<https://metacpan.org/release/App-GitHooks>


πŸ‘‘ AUTHOR πŸ‘‘

Guillaume Aubert <https://metacpan.org/author/AUBERTG>, "aubertg at cpan.org".


Copyright 2013-2017 Guillaume Aubert.

This code is free software; you can redistribute it and/or modify it under the same terms as Perl 5 itself.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file for more details.


And that's the whole page, bestie β€” the docs themselves are perl v5.42.0, dated 2025-07-25, and they're the App::GitHooks(3pm) manual. Go forth and let your hooks be iconic. πŸ’…βœ¨πŸ¦‹

πŸ“¦ where this page comes from