Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/nichtich/plack-app-github-webhook
GitHub WebHook receiver as Plack application
https://github.com/nichtich/plack-app-github-webhook
github-webhooks perl
Last synced: 5 days ago
JSON representation
GitHub WebHook receiver as Plack application
- Host: GitHub
- URL: https://github.com/nichtich/plack-app-github-webhook
- Owner: nichtich
- License: other
- Created: 2013-07-26T09:33:28.000Z (over 11 years ago)
- Default Branch: master
- Last Pushed: 2019-10-11T19:00:07.000Z (about 5 years ago)
- Last Synced: 2024-10-30T16:24:24.731Z (about 2 months ago)
- Topics: github-webhooks, perl
- Language: Perl
- Homepage: https://metacpan.org/pod/Plack::App::GitHub::WebHook
- Size: 84 KB
- Stars: 1
- Watchers: 3
- Forks: 2
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: Changes
- License: LICENSE
Awesome Lists containing this project
README
# NAME
Plack::App::GitHub::WebHook - GitHub WebHook receiver as Plack application
# STATUS
[![Build Status](https://travis-ci.org/nichtich/Plack-App-GitHub-WebHook.png)](https://travis-ci.org/nichtich/Plack-App-GitHub-WebHook)
[![Coverage Status](https://coveralls.io/repos/nichtich/Plack-App-GitHub-WebHook/badge.png?branch=master)](https://coveralls.io/r/nichtich/Plack-App-GitHub-WebHook?branch=master)
[![Kwalitee Score](http://cpants.cpanauthors.org/dist/Plack-App-GitHub-WebHook.png)](http://cpants.cpanauthors.org/dist/Plack-App-GitHub-WebHook)# SYNOPSIS
use Plack::App::GitHub::WebHook;
# Basic Usage
Plack::App::GitHub::WebHook->new(
hook => sub {
my $payload = shift;
...
},
events => ['pull'], # optional
secret => $secret, # optional
access => 'github', # default
)->to_app;# Multiple hooks
use IPC::Run3;
Plack::App::GitHub::WebHook->new(
hook => [
sub { $_[0]->{repository}{name} eq 'foo' },
sub {
my ($payload, $event, $delivery, $logger) = @_;
run3 \@cmd, undef, $logger->{info}, $logger->{error};
},
sub { ... }, # some more action
]
)->to_app;# DESCRIPTION
This [PSGI](https://metacpan.org/pod/PSGI) application receives HTTP POST requests with body parameter
`payload` set to a JSON object. The default use case is to receive
[GitHub WebHooks](http://developer.github.com/webhooks/), for instance
[PushEvents](http://developer.github.com/v3/activity/events/types/#pushevent).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.
- HTTP 500 Internal Server Error
If a hook died with an exception, the error is returned as content body. Use
configuration parameter `safe` to disable HTTP 500 errors.This module requires at least Perl 5.10.
# CONFIGURATION
- hook
A hook can be any of a code reference, an object instance with method `code`,
a class name, or a class name mapped to parameters. You can also pass a list of
hooks as array reference. Class names are prepended by [GitHub::WebHook](https://metacpan.org/pod/GitHub::WebHook)
unless prepended by `+`.hook => sub {
my ($payload, $event, $delivery, $logger) = @_;
...
}hook => 'Foo'
hook => '+GitHub::WebHook::Foo'
hook => GitHub::WebHook::Foo->newhook => { Bar => [ doz => 'baz' ] }
hook => GitHub::WebHook::Bar->new( doz => 'baz' )
Each hook gets passed the encoded payload, the type of webhook
[event](https://developer.github.com/webhooks/#events), a unique delivery ID,
and a [logger object](#logging). If the hook returns a true value, the next
the hook is called or HTTP status code 200 is returned. If a hook returns a
false value (or if no hook was given), HTTP status code 202 is returned
immediately. Information can be passed from one hook to the next by modifying
the payload.- events
A list of [event types](http://developer.github.com/v3/activity/events/types/)
expected to be send with the `X-GitHub-Event` header (e.g. `['pull']`).- logger
Object or function reference to hande [logging events](#logging). An object
must implement method `log` that is called with named arguments:$logger->log( level => $level, message => $message );
For instance [Log::Dispatch](https://metacpan.org/pod/Log::Dispatch) can be used as logger this way.
A function reference is called with hash reference arguments:$logger->({ level => $level, message => $message });
By default [PSGI::Extensions](https://metacpan.org/pod/psgix.logger) is used as logger (if set).
- secret
Secret token set at GitHub Webhook setting to validate payload. See
[https://developer.github.com/webhooks/securing/](https://developer.github.com/webhooks/securing/) for details. Requires
[Plack::Middleware::HubSignature](https://metacpan.org/pod/Plack::Middleware::HubSignature).- access
Access restrictions, as passed to [Plack::Middleware::Access](https://metacpan.org/pod/Plack::Middleware::Access). A recent list
of official GitHub WebHook IPs is vailable at [https://api.github.com/meta](https://api.github.com/meta).
The default valueaccess => 'github'
is a shortcut for these official IP ranges
access => [
allow => "204.232.175.64/27",
allow => "192.30.252.0/22",
deny => 'all'
]and
access => [
allow => 'github',
...
]is a shortcut for
access => [
allow => "204.232.175.64/27",
allow => "192.30.252.0/22",
...
]To disable access control via IP ranges use any of
access => 'all'
access => []- safe
Wrap all hooks in `eval { ... }` blocks to catch exceptions. Error
messages are send to the PSGI error stream `psgi.errors`. A dying hook in
safe mode is equivalent to a hook that returns a false value, so it will result
in a HTTP 202 response.If you want errors to result in a HTTP 500 response, don't use this option but
wrap the application in an eval block such as this:sub {
eval { $app->(@_) } || do {
my $msg = $@ || 'Server Error';
[ 500, [ 'Content-Length' => length $msg ], [ $msg ] ];
};
};# LOGGING
Each hook is passed a logger object to facilitate logging to
[PSGI::Extensions](https://metacpan.org/pod/psgix.logger). The logger provides logging methods for each
log level and a general log method:sub sample_hook {
my ($payload, $event, $delivery, $log) = @_;$log->debug('message'); $log->{debug}->('message');
$log->info('message'); $log->{info}->('message');
$log->warn('message'); $log->{warn}->('message');
$log->error('message'); $log->{error}->('message');
$log->fatal('message'); $log->{fatal}->('message');$log->log( warn => 'message' );
run3 \@system_command, undef,
$log->{info}, # STDOUT to log level info
$log->{error}; # STDERR to log level error
}Trailing newlines on log messages are trimmed.
# EXAMPLES
## Synchronize with a GitHub repository
The following application automatically pulls the master branch of a GitHub
repository into a local working directory.use Plack::App::GitHub::WebHook;
use IPC::Run3;my $branch = "master";
my $work_tree = "/some/path";Plack::App::GitHub::WebHook->new(
events => ['push','ping'],
hook => [
sub {
my ($payload, $event, $delivery, $log) = @_;
$log->info("$event $delivery");
$event eq 'ping' or $payload->{ref} eq "refs/heads/$branch";
},
sub {
my ($payload, $event, $delivery, $log) = @_;
my $origin = $payload->{repository}->{clone_url}
or die "missing clone_url\n";
my $cmd;
if ( -d "$work_tree/.git") {
chdir $work_tree;
$cmd = ['git','pull',$origin,$branch];
} else {
$cmd = ['git','clone',$origin,'-b',$branch,$work_tree];
}
$log->info(join ' ', '$', @$cmd);
run3 $cmd, undef, $log->{debug}, $log->{warn};
1;
},
# sub { ...optional action after each pull... }
],
)->to_app;See [GitHub::WebHook::Clone](https://metacpan.org/pod/GitHub::WebHook::Clone) for before copy and pasting this code.
# DEPLOYMENT
Many deployment methods exist. An easy option might be to use Apache webserver
with mod\_cgi and [Plack::Handler::CGI](https://metacpan.org/pod/Plack::Handler::CGI). First install Apache, Plack and
Plack::App::GitHub::WebHook:sudo apt-get install apache2
sudo apt-get install cpanminus libplack-perl
sudo cpanm Plack::App::GitHub::WebHookThen add this section to `/etc/apache2/sites-enabled/default` (or another host
configuration) and restart Apache.
Options +ExecCGI -Indexes +SymLinksIfOwnerMatch
AddHandler cgi-script .cgi
You can now put webhook applications in directory `/var/www/webhooks` as long
as they are executable, have file extension `.cgi` and shebang line
`#!/usr/bin/env plackup`. You might further want to run webhooks scripts as
another user instead of `www-data` by using Apache module SuExec.# SEE ALSO
- GitHub WebHooks are documented at [http://developer.github.com/webhooks/](http://developer.github.com/webhooks/).
- See [GitHub::WebHook](https://metacpan.org/pod/GitHub::WebHook) for a collection of handlers for typical tasks.
- [WWW::GitHub::PostReceiveHook](https://metacpan.org/pod/WWW::GitHub::PostReceiveHook) uses [Web::Simple](https://metacpan.org/pod/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](https://metacpan.org/pod/Net::GitHub) and [Pithub](https://metacpan.org/pod/Pithub) provide access to GitHub APIs.
- [Github::Hooks::Receiver](https://metacpan.org/pod/Github::Hooks::Receiver) and [App::GitHubWebhooks2Ikachan](https://metacpan.org/pod/App::GitHubWebhooks2Ikachan) are alternative
application that receive GitHub WebHooks.# COPYRIGHT AND LICENSE
Copyright Jakob Voss, 2014-
This library is free software; you can redistribute it and/or modify it under
the same terms as Perl itself.