This is a working example of a lightweight service that's used as part of Sematext's Synthetics CI/CD. You can use it as an example for how to convert your GitHub workflows to self-hosted applications which you can run on your existing environments and circumvent GitHub Actions Minutes limitations, since it also showcases how to interact with GitHub from external services.
At Sematext we actually use this internally for reasons described here: https://sematext.com/docs/synthetics/ci-cd/ci-cd-self-hosting/
This self-hosted Github Runner is designed to run persistently as a server on one of our kubernetes clusters and listen for requests. These requests are sent from ArgoCD when an environment deployment is complete. This service then collects the latest commit hash for the deployed environment from its config on the deployment
repo so that it can be linked with the appropriate commit on the sematext-cloud
repo. This information is then sent to the sematext-cloud
repo as a repository_dispatch
event.
There are two ways to run the self-hosted runner locally for testing. Running the Go program is easier when making changes to the code, but once those are done you should also run the Dockerized setup to confirm everything works that way, since we'll be using it as a Docker container in production.
go build main.go
go run main.go
The base image we're using is very light, so the building process shouldn't take longer than a couple of seconds.
docker build -t gh-runner .
docker run --name gh-runner -p 9555:9555 gh-runner
A GitHub token with appropriate permissions to access both the deployment
repo and the sematext-cloud
repo is required. It will be automatically picked up by the service if it's set as an environment variable called GITHUB_TOKEN
, but it can also be passed within a request to the /dispatch
endpoint for testing purposes.
Note: We can use the PAT for build@sematext.com
here, since it has access to both of the repos.
Variable name | Default value |
---|---|
PORT | 9555 |
GITHUB_API_URL | https://api.github.com |
TARGET_REPO | sematext/sematext-cloud |
DEPLOYMENT_REPO | sematext/deployment |
GITHUB_TOKEN | (empty) |
Processes deployment notifications and triggers repository dispatch events.
Request:
{
"application": "pr-1234",
"github_token": "ghp_xxxxxxxxxxxx"
}
Request Fields:
Field Name | Type | Required | Description |
---|---|---|---|
application |
string | Yes | Application name. Must start with pr- to be processed. |
github_token |
string | No | GitHub token for authentication. If not provided, the service will use the GITHUB_TOKEN environment variable. |
Success - 200
{
"status": "success",
"commitHash": "abc123def456",
"sourceName": "pr-example-app"
}
Skipped (Invalid Application Name) - 200
{
"status": "skipped",
"reason": "application name doesn't start with 'pr-'"
}
400 Bad Request
- Invalid JSON payload or missing GitHub token404 Not Found
- Could not findvalues.yaml
for the specified application405 Method Not Allowed
- Non-POST request500 Internal Server Error
- Error extracting deployment tag or sending dispatch
- Validates that the application name starts with
pr-
- Searches for
values.yaml
indeployment
repository paths:configs/pr/light/{application}/values.yaml
configs/pr/heavy/{application}/values.yaml
- Extracts the
DEPLOYMENT_TAG
from thevalues.yaml
file - Sends a
repository_dispatch
event with typeenvironment_ready
to the target repository (sematext-cloud
)
Health check endpoint for monitoring service availability.
Success - 200
{
"status": "healthy"
}