Skip to content

Development Deployment

Prerequisites

  • Docker and Docker Compose
  • AWS CLI configured with access to ECR (s3://parametric-sds-algol-app)
  • Access to the target device (SSH or serial)

Build and Deploy a Dev Image

# 1. Build the dev image
./scripts/build-image.sh

# 2. Prepare it for deployment
./scripts/manual-prepare-dev-image.sh

# 3. Push to device and reboot
./scripts/manual-deploy-dev-image.sh --remote-host <device-hostname> --reboot

Running Locally

Start a local NATS broker and individual modules for development:

# Start NATS
nats-server

# Run any module pointing at the local NATS
cd app/trigger
go run main.go --nats-url nats://localhost:4222 --id trigger

Running a Local Module Against a Device

A module built on the workstation can join a real device's bus over an SSH tunnel, which is useful for iterating on one app (say, the webui) against live data. The device's broker runs with --auth, so this takes three steps - an anonymous connection or an unknown module id is rejected with nats: Authorization Violation.

None of this applies to the algol CLI on the device itself: that is a docker exec wrapper into the running nats container, where the boot's root seed (/run/algol/nats/root.nkey, role keymaster) is presented automatically - so any host user who can run docker (e.g. torizon) already acts as the boot keymaster, no tunnel and no key setup needed (see Device Setup). The steps below are only for a module built on the workstation joining the bus from outside.

  1. Admit the dev module id on the device. Add a --module=<devname> line to the nats service in the device's docker-compose.yml and recreate the container (a restart of the old container keeps the old flag set). Pick a dev-only name (e.g. your initials): every module id binds to exactly one key on first connect, so reusing a deployed id like webui would collide with the key the device's own container already bound.

  2. Tunnel the broker. The compose file publishes NATS loopback-only on the device (127.0.0.1:4222), so forward it:

ssh -L 4222:localhost:4222 <device-hostname>
  1. Run the module with a key directory. Under --auth a connection must present an NKey; an empty --nats-key-dir means "connect without an identity" and is refused. Point it at any stable local directory - the key is generated on first start:
cd app/trigger
go run main.go --id lzadev --nats-key-dir ~/.algol/lzadev/.nats

The first successful connect binds the dev id to that key in the device's identity registry (bind-once, RFC-034). Keep the key directory: a fresh key under the same id is rejected until the old binding is removed - via the auth verbs as the boot keymaster, or by deleting the entry from /var/algol/nats/registry.json with the nats container stopped (see NATS broker and Device Setup).

The webui is the exception: it must run under its canonical id. Web login is anchored to the module name webui - the nats app's mirror admits web-user keys from webui.webuserinfo.* only, and the user lookup reads <id>.webuser.* - so a webui under a dev id has no users and its logins are rejected on the bus. Instead of steps 1 and 3: stop the webui container on the device, copy its key directory (/var/algol/webui/.nats) to the workstation, and run with --id webui and --nats-key-dir pointing at the copy. Keep the container stopped while the local instance runs - two instances fight over the webui.* statuses and re-key each other's web users.

Testing

# Run all tests
./scripts/test-all.sh

# Single module
cd app/trigger && go test -count=1 -timeout 10s ./...

# Single test
cd app/trigger && go test -run TestFooBar -v ./...

Format and Lint

# Format all modules
./scripts/fmt-all.sh

# Check (what CI runs)
cd app/<name> && gofmt -l . | diff -u /dev/null -

Integration Test (RET)

docker-compose -f targets/colibri-imx8x/docker-compose-test-ret.yml run test-ret

Dependency Management

./scripts/mod-tidy-all.sh   # tidy all modules
./scripts/bump-deps.sh      # bump dependencies across all modules

Local Documentation

The docs site is built with MkDocs Material. To preview it locally:

# Create and activate a virtualenv (one-time setup)
python3 -m venv .venv
.venv/bin/pip install -r app/docs/requirements.txt

# Live preview with hot-reload at http://127.0.0.1:8000
.venv/bin/mkdocs serve --config-file app/docs/mkdocs.yml

# Build static site to site/ (to inspect the output)
.venv/bin/mkdocs build --config-file app/docs/mkdocs.yml

The site/ directory is gitignored. The CI pipeline deploys the site to GitHub Pages automatically on every push to main (as latest) and on every tag push (as a versioned snapshot, e.g. v1.2.3).