AkurAI Build
Menu

AkurAI-Build

public

Latest change 9e7d102408551d0be9697ea986a66e2e7361ca5b - Isolate build caches and bootstrap pinned CI tools by Ólafur Búi Ólafsson

# AkurAI Build

A small Git-native CI/CD system: one Rust binary for repositories, pipelines, Docker/native jobs, build matrices, logs, artifacts, protected deployments, webhooks, CLI JSON, and a responsive MiniJinja dashboard.

It keeps the useful center of Jenkins, GitLab CI, GoCD, Concourse, and Woodpecker without their Git hosting, plugin markets, cluster control planes, or frontend frameworks.

## Foundation

AkurAI Build starts from [Bunfork](https://github.com/olibuijr/bunfork)'s proven shape:

- Rust single binary
- encrypted SQLCipher state and ordered migrations
- bounded Axum/Hyper HTTP serving
- MiniJinja templates and dependency-free Ponytail UI
- strict CSP, constant-time tokens, protected files, and hardened systemd
- digest-recorded artifacts and rollback-oriented deployment

Bunfork remains a supported artifact target; AkurAI Build replaces its unrelated vector/demo application surface with CI/CD.

## Production topology

```text
https://akurai-builds.olibuijr.com
        │ TLS
        ▼
EC2 Nginx / AkurAI-VPN
        │ private 100.88.0.0/16
        ▼
Titan 100.88.0.9:3210
  ├── akurai-build.service
  ├── Docker / BuildKit
  ├── encrypted SQLite
  └── workspaces, cache, artifacts
```

All mutations use the maintained entrypoint:

```sh
./deploy.sh bootstrap
./deploy.sh check
./deploy.sh deploy
./deploy.sh vhost
./deploy.sh status
```

Running it outside Titan forwards to Titan. `deploy` checks, release-builds, retains the prior binary, creates protected keys when absent, migrates transactionally, installs the Pi skill, and restarts the hardened system service under `olafurbui` with only the Docker supplementary group.

## Pipeline

Commit `.akurai.yml`:

```yaml
version: 1
jobs:
  - name: test
    image: oven/bun:1.3
    network: true
    run:
      - bun install --frozen-lockfile
      - bun test
    matrix:
      platform: [linux/amd64, linux/arm64]
    cache: [.bun]

  - name: package
    needs: [test]
    image: oven/bun:1.3
    run: bun build src/index.ts --compile --outfile dist/app
    artifacts: [dist/**]

  - name: deploy
    needs: [package]
    executor: native
    environment: production
    approval: true
    branches: [main]
    secrets: [DEPLOY_TOKEN]
    run: ./deploy.sh dist/app
```

Jobs default to depending on the previous job; set `needs: []` for an independent root. Caches are isolated by registered repository and shared by its jobs. Matrix axes expand to at most 32 variants and become `AKURAI_MATRIX_<AXIS>` variables. `platform` also selects Docker's `--platform`.

Docker jobs run with dropped capabilities, no-new-privileges, fixed CPU/memory/PID limits, a read-only root, writable workspace/tmp, host UID/GID, and no network unless `network: true`. Linux `amd64`/`arm64` variants use the local Titan Docker/BuildKit daemon (native or QEMU). Native jobs are disabled unless the repository is trusted and `AKURAI_ALLOW_NATIVE=1` is set.

Declared secrets resolve only from `AKURAI_SECRET_<NAME>`, are omitted from Docker arguments, and are exact-value-redacted from retained logs. Repository writers with secret-bearing jobs are privileged because build code can intentionally transform or exfiltrate a secret.

## CLI for people and agents

Every non-server command emits one JSON envelope.

```sh
./deploy.sh cli doctor
./deploy.sh cli repo add app https://github.com/org/app.git --branch main
./deploy.sh cli repo list
./deploy.sh cli run app --git-ref main
./deploy.sh cli runs --repo app --limit 20
./deploy.sh cli show 42
./deploy.sh cli wait 42 --timeout 3600
./deploy.sh cli logs 42 --failed
./deploy.sh cli retry 42
./deploy.sh cli promote 42 production
./deploy.sh cli artifact get 7 ./artifact.bin
```

The bundled `skills/akurai-build/SKILL.md` makes these the stable operating surface for BunFast and Pi agents. Agents must verify persisted `succeeded` states rather than infer success from process output.

## Git webhooks

Use:

```text
POST https://akurai-builds.olibuijr.com/api/hooks/<repository-name>
```

Supported authentication:

- GitHub `X-Hub-Signature-256`
- Gitea `X-Gitea-Signature`
- GitLab `X-Gitlab-Token`

The secret is the protected `webhook.token`; do not expose it in commands or documentation. Push payloads supply `ref` and the immutable commit. Manual/UI/API mutations require the separate bearer API token.

## State and recovery

- A run stores its resolved immutable commit before reading `.akurai.yml`.
- Jobs execute fail-fast in dependency order; all variants of a dependency must succeed.
- Artifacts are bounded, SHA-256 recorded, copied without symlinks/traversal, and served only after authorization.
- A protected deployment records the exact upstream artifact IDs and digests before execution.
- Restarted in-flight work becomes `interrupted`; it is never silently replayed. `retry` creates a new audited run.
- systemd restarts controller failures; `deploy.sh rollback` restores the prior binary.

Run evidence is the system's operational knowledge. It supports debugging and safe iteration without allowing unreviewed self-modifying code.

## Limits kept intentionally

The first release is one Titan scheduler with SQLite and sequential isolated jobs. Linux container matrices are complete; native Windows/macOS and remote Windows-container builds wait for a signed artifact-streaming agent protocol rather than pretending remote bind mounts are portable. Object storage, horizontal schedulers, provider commit-status adapters, and role-based multi-user accounts are deferred—not stubbed.

## Development

```sh
./deploy.sh lock       # only after reviewed dependency edits
./deploy.sh check
./deploy.sh docker-smoke
./deploy.sh publish "change summary"
./deploy.sh deploy
```

`check` runs formatting, Clippy with warnings denied, and all locked tests. Direct deployment or publication commands are outside the operating contract.