Abstract
A small Python HTTP service that receives authenticated GitHub push webhooks, validates X-Hub-Signature-256 HMAC signatures, filters by branch, and dispatches repository-specific shell deployment scripts under systemd. The design keeps the listener generic while making all deployment routing explicit in configuration.
1. What This Is
A focused CI/CD building block, not a full pipeline platform. The listener exposes a single HTTP endpoint for GitHub push and ping events, authenticates each request via HMAC, and hands off to a pre-configured shell script for the matched repository. It runs as a long-lived systemd service on a Linux host, so there is no external CI runner or container orchestrator in the loop.
2. How It Works
| # | Stage | Input | Tool | Output |
|---|---|---|---|---|
| 01 | Receive webhook | GitHub push / ping event | Python HTTP service | Parsed request |
| 02 | Verify signature | X-Hub-Signature-256 header + shared secret | HMAC-SHA256 | Accept or reject |
| 03 | Filter event | Repository name, branch | Config mapping | Matched script path or ignore |
| 04 | Run deployment | Resolved shell script | Shell (background) | Deployment logs |
| 05 | Stay alive | systemd unit file | systemd | Persistent listener process |
3. Implementation Notes
3.1 HMAC gate
Every request is checked against the configured shared secret using X-Hub-Signature-256 before any event parsing or script resolution happens. Unsigned or mismatched requests are dropped immediately, which matters because the endpoint can trigger arbitrary server-side scripts.
3.2 Repository-to-script mapping
Deployment behavior lives in a configuration file that maps repository names and allowed branches to explicit shell script paths. The listener itself contains no deployment logic, so adding a new repo means adding one config entry and one script rather than touching the listener code.
3.3 systemd service
The listener ships with a systemd unit file so it runs as a supervised, auto-restarting process on the target host. Deployment work is dispatched in the background so the HTTP response returns quickly and the listener stays available for the next push.
4. Constraints
-
Single-host, single process
One systemd unit on one machine. No load balancing, no horizontal scale, no queue. A second push while the first script is still running will overlap.
-
Shell scripts as the deployment unit
No container orchestration, no rollback step, no built-in retry. If a script fails mid-run, the operator must intervene manually.
-
No rate limiting or concurrency guard
Rapid successive pushes to the same branch can spawn multiple background scripts simultaneously. There is no lock or queue to serialize them.
-
No health-check or metrics endpoint
Operational visibility is limited to log files. There is no /healthz probe or structured metrics for monitoring dashboards.
5. Next
- a. Add a file-based lock or in-process semaphore so concurrent pushes to the same repo are serialized.
- b. Expose a /healthz endpoint and structured JSON logs so the service can be monitored by systemd or an external probe.
- c. Wrap the shell scripts in a thin retry/rollback layer that snapshots state before deploy and reverts on non-zero exit.
— end of report —