This is a small Elixir server with the purpose to configure and serve a light configuration to a real traffic light, like this one:
It is meant to be used with a corresponding client to read the light and do something awesome with it. An example is a client running on a Raspberry PI that fetches the light configuration of this app and displays it on a real traffic light.
The server features the following capabilities:
- LiveView-powered web UI to view a virtual traffic light.
- JSON API to connect a real traffic light client.
- Webhook API to receive status updates from CI services like CodeShip.
- Interactive “public” mode where you can control the traffic light with the web UI.
When in public
mode, the light configuration can be changed by clicking on the corresponding lights on the UI.
In ci
mode the web UI is read-only and only shows the current status.
Just change the heroku env variable like this heroku config:set LIGHT_MODE=public
, heroku will automatically restart your app and the new light mode is applied.
GET http://localhost:4000/lights
{
"green": true,
"mode": "public",
"red": false,
"yellow": false
}
For GitHub you can setup webhooks within your repository:
<Repository> -> Settings -> Webhooks
Make sure to only choose the following webhook events:
The traffic light will turn yellow
when a check run is started and will turn either red
or green
when a check suite was finished.
The reason why both events are needed is because repository-based webhooks only receive a call for check suites when they are finished, but not when they are started.
Additionally there is currently no way to retrieve the combined pull request status. This project should not get access to the GitHub data of a repo on its own. So right now we stay with webhooks even though they might jump between results when multiple actions are called.
Another option would be to leave out webhooks altogether and call the endpoints via curl
in your GH actions directly, but this solution has not been evaluated yet.
More information can be found here:
- Checks - GitHub Docs
- Creating CI tests with the Checks API - GitHub Docs
- Getting started with the Checks API - GitHub Docs
- Testing webhooks - GitHub Docs
POST http://localhost:4000/webhooks/github?token=MY-SECRET-CI-TOKEN
Content-Type: application/json
{
"action": "created",
"check_run": {
"status": "queued",
"conclusion": null,
}
}
POST http://localhost:4000/webhooks/codeship?token=MY-SECRET-CI-TOKEN
Content-Type: application/json
{
"build": {
"build_url":"https://www.codeship.com/projects/10213/builds/973711",
"commit_url":"https://github.com/codeship/docs/ commit/96943dc5269634c211b6fbb18896ecdcbd40a047",
"project_id":10213,
"build_id":973711,
"status":"success",
"project_full_name":"codeship/docs",
"project_name":"codeship/docs",
"commit_id":"96943dc5269634c211b6fbb18896ecdcbd40a047",
"short_commit_id":"96943",
"message":"Merge pull request #34 from codeship/feature/shallow-clone",
"committer":"beanieboi",
"branch":"master"
}
}
Start server with
iex -S mix phx.server
Install the Heroku Redis addon. This will also provide you with the REDIS_URL
environment variable.
Make sure all other required environment variables have been set by you using heroku config
.
heroku config:set CI_SECRET=YOURSECRET
heroku config:set LIGHT_MODE=public
heroku config:set DASHBOARD_AUTH_USERNAME=ADMIN
heroku config:set DASHBOARD_AUTH_PASSWORD=PASSWORD
Open a new iex console on Heroku.
heroku run iex -S mix
Setup some initial data for each mode:
ls = TrafficLight.LightSetting.build(mode: "ci")
TrafficLight.LightSetting.save(ls, "ci")
ls = TrafficLight.LightSetting.build(mode: "public")
TrafficLight.LightSetting.save(ls, "public")
This traffic light project exists since 2010. I use this side project as a form of recreational programming and joyful overengineering.
The software/hardware project has seen many stages:
- Connected to a Synology NAS with a self-soldered Velleman K8055 USB experimentation board.
- Connected to a Raspberry PI, running a Ruby script locally, node.js on the server side.
- Wiring mostly replaced by a custom etched circuit board - a Raspberry shield built only for the purpose of changing the traffic light (and debugging it at home without disassembling the whole traffic light).
- Replacement of the Raspbian/Ruby client with Elixir and Nerves.
- Replacement of the node.js server with Elixir and Phoenix.
The physical traffic light has been set up at two companies and four offices, motivating me and many others to keep your CI green and clean.
It also had its own dedicated blog, showing the appearances of the traffic light in different articles and videos as it was a welcome guest in German media.
🚥 ❤ 🚥