{"id":16010011,"url":"https://github.com/nichtich/plack-app-github-webhook","last_synced_at":"2025-04-05T02:28:26.631Z","repository":{"id":9725112,"uuid":"11682523","full_name":"nichtich/Plack-App-GitHub-WebHook","owner":"nichtich","description":"GitHub WebHook receiver as Plack application","archived":false,"fork":false,"pushed_at":"2019-10-11T19:00:07.000Z","size":86,"stargazers_count":1,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-02-10T10:49:58.182Z","etag":null,"topics":["github-webhooks","perl"],"latest_commit_sha":null,"homepage":"https://metacpan.org/pod/Plack::App::GitHub::WebHook","language":"Perl","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":"icepy/Front-End-Develop-Guide","license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/nichtich.png","metadata":{"files":{"readme":"README.md","changelog":"Changes","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-07-26T09:33:28.000Z","updated_at":"2024-07-15T07:44:15.000Z","dependencies_parsed_at":"2022-08-29T05:01:00.406Z","dependency_job_id":null,"html_url":"https://github.com/nichtich/Plack-App-GitHub-WebHook","commit_stats":null,"previous_names":[],"tags_count":9,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichtich%2FPlack-App-GitHub-WebHook","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichtich%2FPlack-App-GitHub-WebHook/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichtich%2FPlack-App-GitHub-WebHook/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/nichtich%2FPlack-App-GitHub-WebHook/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/nichtich","download_url":"https://codeload.github.com/nichtich/Plack-App-GitHub-WebHook/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247278516,"owners_count":20912748,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["github-webhooks","perl"],"created_at":"2024-10-08T13:04:42.342Z","updated_at":"2025-04-05T02:28:26.616Z","avatar_url":"https://github.com/nichtich.png","language":"Perl","funding_links":[],"categories":[],"sub_categories":[],"readme":"# NAME\n\nPlack::App::GitHub::WebHook - GitHub WebHook receiver as Plack application\n\n# STATUS\n\n[![Build Status](https://travis-ci.org/nichtich/Plack-App-GitHub-WebHook.png)](https://travis-ci.org/nichtich/Plack-App-GitHub-WebHook)\n[![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)\n[![Kwalitee Score](http://cpants.cpanauthors.org/dist/Plack-App-GitHub-WebHook.png)](http://cpants.cpanauthors.org/dist/Plack-App-GitHub-WebHook)\n\n# SYNOPSIS\n\n    use Plack::App::GitHub::WebHook;\n\n    # Basic Usage\n    Plack::App::GitHub::WebHook-\u003enew(\n        hook =\u003e sub {\n            my $payload = shift;\n            ...\n        },\n        events =\u003e ['pull'],  # optional\n        secret =\u003e $secret,   # optional\n        access =\u003e 'github',  # default\n    )-\u003eto_app;\n\n    # Multiple hooks\n    use IPC::Run3;\n    Plack::App::GitHub::WebHook-\u003enew(\n        hook =\u003e [\n            sub { $_[0]-\u003e{repository}{name} eq 'foo' },\n            sub {\n                my ($payload, $event, $delivery, $logger) = @_;\n                run3 \\@cmd, undef, $logger-\u003e{info}, $logger-\u003e{error}; \n            },\n            sub { ...  }, # some more action\n        ]\n    )-\u003eto_app;\n\n# DESCRIPTION\n\nThis [PSGI](https://metacpan.org/pod/PSGI) application receives HTTP POST requests with body parameter\n`payload` set to a JSON object. The default use case is to receive \n[GitHub WebHooks](http://developer.github.com/webhooks/), for instance\n[PushEvents](http://developer.github.com/v3/activity/events/types/#pushevent).\n\nThe response of a HTTP request to this application is one of:\n\n- HTTP 403 Forbidden\n\n    If access was not granted (for instance because it did not origin from GitHub).\n\n- HTTP 405 Method Not Allowed\n\n    If the request was no HTTP POST.\n\n- HTTP 400 Bad Request\n\n    If the payload was no well-formed JSON or the `X-GitHub-Event` header did not\n    match configured events.\n\n- HTTP 200 OK\n\n    Otherwise, if the hook was called and returned a true value.\n\n- HTTP 202 Accepted\n\n    Otherwise, if the hook was called and returned a false value.\n\n- HTTP 500 Internal Server Error\n\n    If a hook died with an exception, the error is returned as content body. Use\n    configuration parameter `safe` to disable HTTP 500 errors. \n\nThis module requires at least Perl 5.10.\n\n# CONFIGURATION\n\n- hook\n\n    A hook can be any of a code reference, an object instance with method `code`,\n    a class name, or a class name mapped to parameters. You can also pass a list of\n    hooks as array reference. Class names are prepended by [GitHub::WebHook](https://metacpan.org/pod/GitHub::WebHook)\n    unless prepended by `+`.\n\n        hook =\u003e sub {\n            my ($payload, $event, $delivery, $logger) = @_;\n            ...\n        }\n\n        hook =\u003e 'Foo'\n        hook =\u003e '+GitHub::WebHook::Foo'\n        hook =\u003e GitHub::WebHook::Foo-\u003enew\n\n        hook =\u003e { Bar =\u003e [ doz =\u003e 'baz' ] }\n        hook =\u003e GitHub::WebHook::Bar-\u003enew( doz =\u003e 'baz' )\n        \n\n    Each hook gets passed the encoded payload, the type of webhook\n    [event](https://developer.github.com/webhooks/#events), a unique delivery ID,\n    and a [logger object](#logging).  If the hook returns a true value, the next\n    the hook is called or HTTP status code 200 is returned.  If a hook returns a\n    false value (or if no hook was given), HTTP status code 202 is returned\n    immediately.  Information can be passed from one hook to the next by modifying\n    the payload. \n\n- events\n\n    A list of [event types](http://developer.github.com/v3/activity/events/types/)\n    expected to be send with the `X-GitHub-Event` header (e.g. `['pull']`).\n\n- logger\n\n    Object or function reference to hande [logging events](#logging).  An object\n    must implement method `log` that is called with named arguments:\n\n        $logger-\u003elog( level =\u003e $level, message =\u003e $message );\n\n    For instance [Log::Dispatch](https://metacpan.org/pod/Log::Dispatch) can be used as logger this way.\n    A function reference is called with hash reference arguments:\n\n        $logger-\u003e({ level =\u003e $level, message =\u003e $message });\n\n    By default [PSGI::Extensions](https://metacpan.org/pod/psgix.logger) is used as logger (if set).\n\n- secret\n\n    Secret token set at GitHub Webhook setting to validate payload.  See\n    [https://developer.github.com/webhooks/securing/](https://developer.github.com/webhooks/securing/) for details. Requires\n    [Plack::Middleware::HubSignature](https://metacpan.org/pod/Plack::Middleware::HubSignature).\n\n- access\n\n    Access restrictions, as passed to [Plack::Middleware::Access](https://metacpan.org/pod/Plack::Middleware::Access). A recent list\n    of official GitHub WebHook IPs is vailable at [https://api.github.com/meta](https://api.github.com/meta).\n    The default value\n\n        access =\u003e 'github'\n\n    is a shortcut for these official IP ranges\n\n        access =\u003e [\n            allow =\u003e \"204.232.175.64/27\",\n            allow =\u003e \"192.30.252.0/22\",\n            deny  =\u003e 'all'\n        ]\n\n    and\n\n        access =\u003e [\n            allow =\u003e 'github',\n            ...\n        ]\n\n    is a shortcut for\n\n        access =\u003e [\n            allow =\u003e \"204.232.175.64/27\",\n            allow =\u003e \"192.30.252.0/22\",\n            ...\n        ]\n\n    To disable access control via IP ranges use any of\n\n        access =\u003e 'all'\n        access =\u003e []\n\n- safe\n\n    Wrap all hooks in `eval { ... }` blocks to catch exceptions.  Error\n    messages are send to the PSGI error stream `psgi.errors`.  A dying hook in\n    safe mode is equivalent to a hook that returns a false value, so it will result\n    in a HTTP 202 response.\n\n    If you want errors to result in a HTTP 500 response, don't use this option but\n    wrap the application in an eval block such as this:\n\n        sub {\n            eval { $app-\u003e(@_) } || do {\n                my $msg = $@ || 'Server Error';\n                [ 500, [ 'Content-Length' =\u003e length $msg ], [ $msg ] ];\n            };\n        };\n\n# LOGGING\n\nEach hook is passed a logger object to facilitate logging to\n[PSGI::Extensions](https://metacpan.org/pod/psgix.logger). The logger provides logging methods for each\nlog level and a general log method:\n\n    sub sample_hook {\n        my ($payload, $event, $delivery, $log) = @_;\n\n        $log-\u003edebug('message');  $log-\u003e{debug}-\u003e('message');\n        $log-\u003einfo('message');   $log-\u003e{info}-\u003e('message');\n        $log-\u003ewarn('message');   $log-\u003e{warn}-\u003e('message');\n        $log-\u003eerror('message');  $log-\u003e{error}-\u003e('message');\n        $log-\u003efatal('message');  $log-\u003e{fatal}-\u003e('message');\n\n        $log-\u003elog( warn =\u003e 'message' );\n\n        run3 \\@system_command, undef,\n            $log-\u003e{info},   # STDOUT to log level info\n            $log-\u003e{error};  # STDERR to log level error\n    }\n\nTrailing newlines on log messages are trimmed.\n\n# EXAMPLES\n\n## Synchronize with a GitHub repository\n\nThe following application automatically pulls the master branch of a GitHub\nrepository into a local working directory.\n\n    use Plack::App::GitHub::WebHook;\n    use IPC::Run3;\n\n    my $branch = \"master\";\n    my $work_tree = \"/some/path\";\n\n    Plack::App::GitHub::WebHook-\u003enew(\n        events =\u003e ['push','ping'],\n        hook =\u003e [\n            sub { \n                my ($payload, $event, $delivery, $log) = @_;\n                $log-\u003einfo(\"$event $delivery\");\n                $event eq 'ping' or $payload-\u003e{ref} eq \"refs/heads/$branch\";\n            },\n            sub {\n                my ($payload, $event, $delivery, $log) = @_;\n                my $origin = $payload-\u003e{repository}-\u003e{clone_url} \n                           or die \"missing clone_url\\n\";\n                my $cmd;\n                if ( -d \"$work_tree/.git\") {\n                    chdir $work_tree;\n                    $cmd = ['git','pull',$origin,$branch];\n                } else {\n                    $cmd = ['git','clone',$origin,'-b',$branch,$work_tree];\n                }\n                $log-\u003einfo(join ' ', '$', @$cmd);\n                run3 $cmd, undef, $log-\u003e{debug}, $log-\u003e{warn};\n                1;\n            },\n            # sub { ...optional action after each pull... } \n        ],\n    )-\u003eto_app;\n\nSee [GitHub::WebHook::Clone](https://metacpan.org/pod/GitHub::WebHook::Clone) for before copy and pasting this code.\n\n# DEPLOYMENT\n\nMany deployment methods exist. An easy option might be to use Apache webserver\nwith mod\\_cgi and [Plack::Handler::CGI](https://metacpan.org/pod/Plack::Handler::CGI). First install Apache, Plack and\nPlack::App::GitHub::WebHook:\n\n    sudo apt-get install apache2\n    sudo apt-get install cpanminus libplack-perl\n    sudo cpanm Plack::App::GitHub::WebHook\n\nThen add this section to `/etc/apache2/sites-enabled/default` (or another host\nconfiguration) and restart Apache.\n\n    \u003cDirectory /var/www/webhooks\u003e\n       Options +ExecCGI -Indexes +SymLinksIfOwnerMatch\n       AddHandler cgi-script .cgi\n    \u003c/Directory\u003e\n\nYou can now put webhook applications in directory `/var/www/webhooks` as long\nas they are executable, have file extension `.cgi` and shebang line\n`#!/usr/bin/env plackup`. You might further want to run webhooks scripts as\nanother user instead of `www-data` by using Apache module SuExec.\n\n# SEE ALSO\n\n- GitHub WebHooks are documented at [http://developer.github.com/webhooks/](http://developer.github.com/webhooks/).\n- See [GitHub::WebHook](https://metacpan.org/pod/GitHub::WebHook) for a collection of handlers for typical tasks.\n- [WWW::GitHub::PostReceiveHook](https://metacpan.org/pod/WWW::GitHub::PostReceiveHook) uses [Web::Simple](https://metacpan.org/pod/Web::Simple) to receive GitHub web\nhooks. A listener as exemplified by the module can also be created like this:\n\n        use Plack::App::GitHub::WebHook;\n        use Plack::Builder;\n        build {\n            mount '/myProject' =\u003e \n                Plack::App::GitHub::WebHook-\u003enew(\n                    hook =\u003e sub { my $payload = shift; }\n                );\n            mount '/myOtherProject' =\u003e \n                Plack::App::GitHub::WebHook-\u003enew(\n                    hook =\u003e sub { run3 \\@cmd ... }\n                );\n        };\n\n- [Net::GitHub](https://metacpan.org/pod/Net::GitHub) and [Pithub](https://metacpan.org/pod/Pithub) provide access to GitHub APIs.\n- [Github::Hooks::Receiver](https://metacpan.org/pod/Github::Hooks::Receiver) and [App::GitHubWebhooks2Ikachan](https://metacpan.org/pod/App::GitHubWebhooks2Ikachan) are alternative\napplication that receive GitHub WebHooks.\n\n# COPYRIGHT AND LICENSE\n\nCopyright Jakob Voss, 2014-\n\nThis library is free software; you can redistribute it and/or modify it under\nthe same terms as Perl itself.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichtich%2Fplack-app-github-webhook","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnichtich%2Fplack-app-github-webhook","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnichtich%2Fplack-app-github-webhook/lists"}