- Elixir 99.3%
- Shell 0.3%
- Dockerfile 0.3%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
|
|
||
| apps | ||
| config | ||
| docs | ||
| manifests | ||
| tests | ||
| .dockerignore | ||
| .formatter.exs | ||
| .gitignore | ||
| AGENTS.md | ||
| ci.Dockerfile | ||
| Dockerfile | ||
| Makefile | ||
| mix.exs | ||
| mix.lock | ||
| README.md | ||
binjovi
Binjovi is a portable Elixir and OTP CI/CD control plane. Kubernetes is its first deployment target. Kubernetes is not its durable state model or its only execution engine.
The first pass uses sean/bytey to measure the minimum control-plane cost.
Bytey has almost no product work, so it exposes coordination overhead.
Current slice
The current slice contains:
- pure Build, Release, and Deployment models with immutable source identity;
- a typed, shell-free Bytey execution plan;
- a PostgreSQL authority with automatic migrations, provider-delivery deduplication, source deduplication, and compare-and-set transitions;
- one short-lived
:gen_statemcoordinator for each active Build; - pod-scoped lease owners and fencing epochs for safe controller takeover;
- signed Forgejo webhook wakeups for Bytey and for Binjovi, with a bounded five-minute recovery scan for missed deliveries;
- canonical Forgejo pull-request Changes with frozen plan digests and the
binjovi/cicommit status; - restricted Kubernetes Jobs that run Bytey through an AlmaLinux 10
buildctlclient with no shell, token, or credential mount; - durable status delivery, pull-request head supersession, Job cancellation, and Job log folds;
- an in-memory Bytey floor probe that measures the control contract without creating project Build records;
- authenticated, idempotent release commands with durable stage, lease, fencing, retry, and external-effect evidence;
- exact-head fast-forward integration, main promotion, stable patch tags, Forgejo Releases, and immutable artifact identity;
- independent deploy commands with exact-revision target verification;
- an operator dashboard with only Builds, Releases, and Deploys; Build folds contain Change evidence, execution attempts, logs, and release actions;
- an OTP release and AlmaLinux 10 container image;
- a self-hosted Shipwright image executor with deterministic BuildRun identity;
- a machine-owned Forgejo deploy branch and exact-digest Argo CD delivery;
- an isolated, read-only staging instance and a 60-second dual-stack availability gate before automatic production promotion;
- three control-plane replicas on separate nodes, with a two-copy disruption floor during planned node rolls.
The Bytey floor probe stays in memory and does not create project activity.
Bytey and Binjovi pull requests run the real CI path. An authenticated user can
release an exact successful Build from the dashboard. Binjovi fails the
command if its Change head or base became stale. For an exact current Bytey
Build, it fast-forwards trunk and main, creates the next stable patch tag,
and records the exact Forgejo Release URL. A separate deploy command updates
the bytey-floorplan ConfigMap with resource-version compare-and-set. Binjovi
records a Deploy only after exact readback.
Binjovi pull requests use Shipwright to isolate the image build. The first new
release is v0.1.0; later releases increase the stable patch version. Each
Release records the exact OCI digest. A separate deploy command first copies
the exact revision and digest to deploy-staging. Argo CD applies the
read-only instance at staging.binjovi.sean.farm. A restricted host-network
Job then verifies the Service, the internal Gateway, public IPv4 reachability,
public A and AAAA records, the UI, and the CI service spine. The gate needs
five consecutive preflight passes and then zero failures for 60 seconds.
The probe writes the exact summary to stdout and the Pod termination message,
so a node replacement cannot remove the promotion evidence. Binjovi stores
the result with the staging Deploy. Only then does policy copy the same
Release to deploy for production. Production succeeds only after all three
replicas report the exact source revision and image digest.
A failed staging Deploy has an authenticated retry action in its dashboard
fold. A retry deletes the old deterministic probe Job and repeats the same
Release verification. The API rejects direct production retries.
Each self-hosted revision records its complete accepted-to-verified duration, with separate Build, Release, and Deploy timings in the dashboard.
Run
Install Elixir 1.20 with Erlang/OTP 29, then run:
mix deps.get
make check
make floor
Start the HTTP service:
mix run --no-halt
open http://127.0.0.1:4000/
curl http://127.0.0.1:4000/health/ready
curl http://127.0.0.1:4000/api/v1/floor
curl http://127.0.0.1:4000/api/v1/projects/bytey/activity
curl http://127.0.0.1:4000/api/v1/projects/binjovi/activity
The Kubernetes dashboard is https://binjovi.sean.farm. Select bytey to see
real pull-request Builds with folded Forgejo Change evidence, Releases, and
marker Deploys.
Select binjovi to see each self-hosted image Build, OCI Release, and Argo CD
Deploy. The dashboard refreshes
durable PostgreSQL activity every five seconds.
Forgejo calls /hooks/forgejo through the cluster-local Service. The endpoint
verifies the payload HMAC before it wakes a reconciler. The payload is only a
hint. The reconciler reads canonical source state from Forgejo and durable
phase state from PostgreSQL. A five-minute scan repairs a lost webhook.
Normal source discovery therefore takes one signed delivery round trip, not a
fixed polling interval.
Configure the Forgejo hook with the pull_request event. A push event alone
supports only the temporary self-host bootstrap path.
Each phase has a durable wall-clock boundary. Build time is acceptance through terminal Build state. Release time is release-command acceptance through immutable artifact observation. Deploy time is deploy-command acceptance through independent target verification. The accepted-to-verified total runs from Build acceptance through Deploy verification. It can include policy wait time between the independent phases. A controller restart does not reset a phase timer.
Build logs stream while containers run. At terminal state, Binjovi also
captures any container log that does not yet have a durable MinIO chunk.
A replacement controller adopts the same deterministic BuildRun after a
lease expires.
Fence epochs stop an expired controller from changing the recovered run.
The self-host image gate runs the complete make check suite before it can
publish an image.
BuildRun submission observes that deterministic identity before each bounded
transport retry.
Floor scope
mix binjovi.floor and /api/v1/floor measure this path:
validated Forgejo-shaped event
-> atomic delivery and Build acceptance
-> OTP coordinator start
-> immutable Bytey plan creation
-> fake executor start and completion events
-> terminal Build state
The floor measurement does not include Forgejo synchronization, PostgreSQL, worker network time, repository checkout, BuildKit, or Bytey compilation. It remains a stable lower bound while the dashboard shows the durable production observation path.
See docs/architecture.md for the design boundaries and docs/pipeline-lifecycles.md for the three-section project model and the Build and Release state machines.