{"id":19197087,"url":"https://github.com/alexandru/github-webhook-listener","last_synced_at":"2025-06-22T13:08:33.119Z","repository":{"id":45016949,"uuid":"153904245","full_name":"alexandru/github-webhook-listener","owner":"alexandru","description":"Light server for reacting to GitHub's Webhooks","archived":false,"fork":false,"pushed_at":"2025-03-25T18:23:20.000Z","size":457,"stargazers_count":42,"open_issues_count":0,"forks_count":5,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-15T14:44:03.310Z","etag":null,"topics":["github","github-webhook","github-webhook-listener","graalvm-native-image","kotlin","ktor","ktor-server","server"],"latest_commit_sha":null,"homepage":"","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexandru.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null},"funding":{"patreon":"alexelcu"}},"created_at":"2018-10-20T12:39:36.000Z","updated_at":"2025-03-25T18:15:51.000Z","dependencies_parsed_at":"2023-10-02T08:24:44.624Z","dependency_job_id":"4ef4304f-c1e8-4ce8-a4da-9ed4ea36338f","html_url":"https://github.com/alexandru/github-webhook-listener","commit_stats":null,"previous_names":[],"tags_count":21,"template":false,"template_full_name":null,"purl":"pkg:github/alexandru/github-webhook-listener","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandru%2Fgithub-webhook-listener","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandru%2Fgithub-webhook-listener/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandru%2Fgithub-webhook-listener/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandru%2Fgithub-webhook-listener/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexandru","download_url":"https://codeload.github.com/alexandru/github-webhook-listener/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexandru%2Fgithub-webhook-listener/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261296968,"owners_count":23137221,"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","github-webhook","github-webhook-listener","graalvm-native-image","kotlin","ktor","ktor-server","server"],"created_at":"2024-11-09T12:15:30.718Z","updated_at":"2025-06-22T13:08:28.102Z","avatar_url":"https://github.com/alexandru.png","language":"Kotlin","readme":"# GitHub Webhook Listener (ver. 2)\n\n[![Build](https://github.com/alexandru/github-webhook-listener/workflows/build/badge.svg?branch=main)](https://github.com/alexandru/github-webhook-listener/actions?query=branch%3Amain+workflow%3Abuild) [![Deploy](https://github.com/alexandru/github-webhook-listener/workflows/deploy/badge.svg)](https://github.com/alexandru/github-webhook-listener/actions?query=workflow%3Adeploy)\n\nA simple web app that can be registered as a\n[GitHub Webhook](https://developer.github.com/webhooks/)\nand trigger shell commands in response to events.\n\nMain use-case is to trigger refreshes of websites hosted on your own\nserver via CI jobs (e.g., GitHub Actions), but in a secure way, without \nexposing server credentials or SSH keys.\n\nThe server process is also light in resource usage, not using more\nthan 10 MB of RAM, so it can be installed on under-powered servers.\n\n\u003e **NOTE**\n\u003e \n\u003e This used to be a Haskell project, that I switched to Kotlin. The code is still available on the [v1-haskell](https://github.com/alexandru/github-webhook-listener/tree/v1-haskell) branch. \n\n## Setup\n\nDocker images are published via [GitHub's Packages](https://github.com/alexandru/github-webhook-listener/pkgs/container/github-webhook-listener). You can quickly run a process like this:\n\n```sh\ndocker run \\\n  -p 8080:8080 \\\n  -ti ghcr.io/alexandru/github-webhook-listener:native-latest\n```\n\nThere are 2 versions of this project being published. The default is a binary compiled to a native executable via [GraalVM's Native Image](https://www.graalvm.org/22.1/reference-manual/native-image/). The other image is a JAR that runs with OpenJDK. You can choose between them via the tag used. To use the OpenJDK version, look for tags prefixed with `jvm-`:\n\n```sh\ndocker run \\\n  -p 8080:8080 \\\n  -ti ghcr.io/alexandru/github-webhook-listener:jvm-latest\n```\n\n### Which version to choose?\n\nThe native version (e.g., the `native-latest` tag) uses under 10 MB of RAM, and it's good for underpowered servers. The JVM version (e.g., `jvm-latest`) has at least a 50 MB penalty, so use it only if you bump into problems with the native version. The JVM's execution is optimized with the Shenandoah GC, though, releasing memory back to the OS, it's as optimal as a Java process can be, and if you have the RAM, you might prefer it.\n\n### Server Configuration\n\nOn its own this just starts the server, but doesn't know how to do anything. We'll need to specify a configuration file: Create your `./config.yaml`:\n\n```yaml\nhttp:\n  path: \"/\"\n  port: 8080\n\nprojects:\n  myproject:\n    ref: \"refs/heads/gh-pages\"\n    directory: \"/var/www/myproject\"\n    command: \"git pull\"\n    secret: \"xxxxxxxxxxxxxxxxxxxxxxxxxx\"\n```\n\nNotes:\n\n1. `myproject` in `project.myproject` is just a name of a project, it could be anything;\n2. `ref` says to only react on pushes to the `gh-pages` branch;\n3. `directory` is where the `command` should be executed;\n4. `command` is to be executed — note that `git` is not installed, see below;\n\nYou can then run the server:\n\n```sh\ndocker run \\\n  -p 8080:8080 \\\n  -v \"$(pwd)/config.yaml:/opt/app/config/config.yaml\" \\\n  -v \"/var/www:/var/www\" \\\n  -u \"$(id -u www-data):$(id -g www-data)\" \\\n  -ti ghcr.io/alexandru/github-webhook-listener:latest\n```\n\nNote that we are forcing the use of `www-data` as the user. This is because we need permissions for `/var/www` that's on the host operating system. Adjust accordingly. \n\nYou can also use a `docker-compose.yaml`:\n\n```yaml\nversion: '3.3'\n\nservices:\n  github-webhook-listener:\n    container_name: github-webhook-listener\n    image: ghcr.io/alexandru/github-webhook-listener:latest\n    restart: unless-stopped\n    ports:\n      - \"8080:8080\"\n    networks:\n      - main\n    volumes:\n      - /var/www:/var/www\n      - /etc/github-webhook-listener/config.yaml:/opt/app/config/config.yaml\n    user: \"${WWW_UID}:${WWW_GID}\"\n\nnetworks:\n  main:\n    external:\n      name: main\n```\n\nThen to expose this server via [Nginx](https://www.nginx.com/), it's just a matter of configuring a `proxy_pass`:\n\n```conf\nlocation / {\n  proxy_pass http://127.0.0.1:8080;\n  proxy_set_header    Host            $host;\n  proxy_set_header    X-Real-IP       $remote_addr;\n  proxy_set_header    X-Forwarded-for $remote_addr;\n  proxy_connect_timeout 300;\n}\n```\n\n### Configuring Your GitHub Project\n\nGo to the settings page of your project, the \"Webhooks\" section, link\nshould be like: `https://github.com/\u003cuser\u003e/\u003cproject\u003e/settings/hooks`\n\nSetup screen for adding a new Webhook should look like this:\n\n![Webhook setup screen](https://github.com/alexandru/github-webhook-listener/wiki/setup.png)\n\nNOTEs on those fields:\n\n1. the Payload URL contains a `some-id`, in the described path, that should be configured in your `config.yaml` file to identify your project\n2. the Secret is the passphrase you also configured in `config.yaml` — this is optional, but if the `config.yaml` mentions a passphrase which you're not mentioning in this setup, then requests will fail\n\n## Development\n\nThe project uses [Kotlin](https://kotlinlang.org/) as the programming language, with [Ktor](https://ktor.io/). And the setup is optimized for [GraalVM's Native Image](https://www.graalvm.org/22.2/reference-manual/native-image/).\n\nTo run the project in development mode:\n\n```sh\n./gradlew run -Pdevelopment --args=\"./config/application-dummy.conf\"\n```\n\nTo run after adding new dependencies:\n\n```sh\n./gradlew refreshVersionsMigrate  --mode=VersionCatalogOnly\n```\n\nTo update project dependencies:\n\n```sh\n./gradlew refreshVersions\n```\n\nTo build the Docker image for the JVM version from scratch:\n\n```sh \nmake build-jvm\n```\n\nOr the native version:\n\n```sh\nmake build-native\n```\n\n### Issues with native-image\n\n- [Kotlinx Serialization with GraalVM Native Images](https://github.com/Kotlin/kotlinx.serialization/issues/1125)\n\n## License\n\nCopyright © 2018-2022 Alexandru Nedelcu, some rights reserved.\n\nLicensed under the AGPL-3.0 license. See [LICENSE](./LICENSE).\n","funding_links":["https://patreon.com/alexelcu"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandru%2Fgithub-webhook-listener","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexandru%2Fgithub-webhook-listener","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexandru%2Fgithub-webhook-listener/lists"}