++ed by:
RRWO TSIBLEY

2 PAUSE user(s)
1 non-PAUSE user(s).

Jakob Voß
and 2 contributors

NAME

Plack::App::GitHub::WebHook - GitHub WebHook receiver as Plack application

SYNOPSIS

Basic usage

    use Plack::App::GitHub::WebHook;

    Plack::App::GitHub::WebHook->new(
        hook => sub {
            my $payload = shift;
            ...
        }
    )->to_app;

Multiple task hooks

A hook can consist of multiple tasks, given by an array reference. The tasks are called one by one until a task returns a false value.

    use Plack::App::GitHub::WebHook;
    use IPC::Run3;

    Plack::App::GitHub::WebHook->new(
        hook => [
            sub { $_[0]->{repository}{name} eq 'foo' }, # filter
            { Filter => { repository_name => 'foo' } }, # equivalent filter
            sub { my ($payload) = @_; ...  }, # some action
            sub { run3 \@cmd ... }, # some more action
        ]
    )->to_app;

Access restriction

By default access is restricted to known GitHub WebHook IPs.

    Plack::App::GitHub::WebHook->new(
        hook => sub { ... },
        access => [
            allow => "204.232.175.64/27",
            allow => "192.30.252.0/22",
            deny  => 'all'
        ]
    )->to_app;

    # this is equivalent to
    use Plack::Builder;
    builder {
        mount 'notify' => builder {
            enable 'Access', rules => [
                allow => "204.232.175.64/27",
                allow => "192.30.252.0/22",
                deny  => 'all'
            ]
            Plack::App::GitHub::WebHook->new(
                hook => sub { ... }
            );
        }
    };

Synchronize with a GitHub repository

The following application automatically pulls the master branch of a GitHub repository into a local working directory $work_tree.

    use Git::Repository
    use Plack::App::GitHub::WebHook;

    Plack::App::GitHub::WebHook->new(
        events => ['pull'],
        safe => 1,
        hook => [
            sub { $_[0]->{ref} eq 'refs/heads/master' },
            sub {
                if ( -d "$work_tree/.git") {
                    Git::Repository->new( work_tree => $work_tree )
                                   ->run(qw(pull origin master));
                } else {
                    my $origin = $_[0]->{repository}->{clone_url};
                    Git::Repository->run( 'clone', $origin, $work_tree );
                }
                1;
            },
            # sub { ...optional action after each pull... } 
        ],
    )->to_app;

DESCRIPTION

This PSGI application receives HTTP POST requests with body parameter payload set to a JSON object. The default use case is to receive GitHub WebHooks, for instance PushEvents.

The response of a HTTP request to this application is one of:

HTTP 403 Forbidden

If access was not granted (for instance because it did not origin from GitHub).

HTTP 405 Method Not Allowed

If the request was no HTTP POST.

HTTP 400 Bad Request

If the payload was no well-formed JSON or the X-GitHub-Event header did not match configured events.

HTTP 200 OK

Otherwise, if the hook was called and returned a true value.

HTTP 202 Accepted

Otherwise, if the hook was called and returned a false value.

This module requires at least Perl 5.10.

CONFIGURATION

hook

A code reference or an array of code references with tasks that are executed on an incoming webhook. Each task gets passed the encoded payload. If the task returns a true value, next the task is called or HTTP status code 200 is returned. Information can be passed from one task to the next by modifying the payload.

If a task returns a false value or if no task was given, HTTP status code 202 is returned immediately. This mechanism can be used for conditional hooks or to detect hooks that were called successfully but failed to execute for some reason.

safe

Wrap all hook tasks in eval { ... } blocks to catch exceptions. A dying task in safe mode is equivalent to a task that returns a false value.

access

Access restrictions, as passed to Plack::Middleware::Access. See SYNOPSIS for the default value. A recent list of official GitHub WebHook IPs is vailable at https://api.github.com/meta. One should only set the access value on instantiation, or manually call prepare_app after modification.

events

A list of event types expected to be send with the X-GitHub-Event header (e.g. ['pull']).

SEE ALSO

  • GitHub WebHooks are documented at http://developer.github.com/webhooks/.

  • WWW::GitHub::PostReceiveHook uses Web::Simple to receive GitHub web hooks. A listener as exemplified by the module can also be created like this:

        use Plack::App::GitHub::WebHook;
        use Plack::Builder;
        build {
            mount '/myProject' => 
                Plack::App::GitHub::WebHook->new(
                    hook => sub { my $payload = shift; }
                );
            mount '/myOtherProject' => 
                Plack::App::GitHub::WebHook->new(
                    hook => sub { run3 \@cmd ... }
                );
        };
  • Net::GitHub and Pithub provide access to GitHub APIs.

  • App::GitHubWebhooks2Ikachan is an application that also receives GitHub WebHooks.

AUTHOR

Jakob Voss <jakob.voss@gbv.de>

LICENSE

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