Files
horus/docker/Readme.md
peternashaat aa30c54742
Some checks failed
CI / Build & Test (push) Failing after 1m41s
CI / Build & Test (pull_request) Failing after 1m42s
docs: document hero-git image and installer-based release pipeline
- add README for hero-git Docker image usage (local + CI)
- explain Dockerfile/entrypoint behavior and horus_full_install workflow
- describe new release process using hero-git image and horus_full_install.vsh
2025-11-20 12:06:41 +00:00

7.7 KiB
Raw Blame History

hero-git Docker Image

This directory contains a reusable Docker image and entrypoint script used to build Hero / Horus binaries via the V-based herolib installers.

It is designed for two main use cases:

  1. Local development / testing run the herolib CLI (hero) and Horus installers in a clean, reproducible environment.
  2. CI / Release builds build Horus binaries inside this image (using horus_full_install.vsh) and export them as release artifacts.

Files

Dockerfile

The Dockerfile builds an Ubuntu-based image with all dependencies needed for herolib and its installers.

Key points:

  • Base: ubuntu:24.04

  • Installs system tooling:

    • ssh, wget, curl, unzip, build-essential, git, git-lfs
    • redis-server, libsqlite3-dev, libpq-dev, autoconf, libtool, net-tools, iputils-ping, rsync, mc, tmux, ufw, xz-utils
  • Installs V compiler:

    • Downloads v_linux.zip from the official V GitHub releases
    • Unzips it and runs ./v symlink so v is on the PATH
  • Installs Bun (used for the docusaurus docs template):

    • curl -fsSL https://bun.sh/install | bash
  • Clones:

    • https://github.com/Incubaid/herolib into /opt/herolib
    • https://github.com/incubaid/docusaurus_template into /root/code/github/incubaid/docusaurus_template
  • Warms Bun dependencies for the docusaurus template (for faster re-use):

    • cd /root/code/github/incubaid/docusaurus_template/template && bun install
  • Prepares directories:

    • /root/.vmodules/incubaid used by V module resolution
    • /root/ssh optional mount point for SSH keys
  • Copies entrypoint.sh into the image and marks it executable.

The containers entrypoint is set to the custom script /bin/entrypoint.sh.


entrypoint.sh

The entrypoint script is responsible for:

  1. Starting Redis in the background.
  2. Optionally configuring SSH (if keys are provided).
  3. Selecting the correct herolib source (mounted or cloned).
  4. Checking out the desired herolib branch.
  5. Building the hero CLI with V and making it available as /bin/hero.
  6. Finally, executing any command passed to docker run.

Behavior in detail

#!/bin/bash
set -euo pipefail

# Start Redis in the background
redis-server --daemonize yes

# Optional SSH setup: only if /root/ssh has keys
if [ -d /root/ssh ] && compgen -G "/root/ssh/*" > /dev/null; then
    mkdir -p /root/.ssh
    cp -r /root/ssh/* /root/.ssh/
    chmod 600 /root/.ssh/*
    eval "$(ssh-agent)"
    ssh-add /root/.ssh/*
fi

# Support optionally bind-mounting a local herolib into the container.
# If /opt/herolib_mount exists, we use that; otherwise we use the cloned /opt/herolib
rm -f /root/.vmodules/freeflowuniverse/herolib
if [ -d "/opt/herolib_mount" ]; then
    ln -s /opt/herolib_mount/lib /root/.vmodules/incubaid/herolib
    cd /opt/herolib_mount
else
    ln -s /opt/herolib/lib /root/.vmodules/incubaid/herolib
    cd /opt/herolib
    git fetch
    git checkout "${HEROLIB_REF:-development}"
    git pull
fi

cd cli
echo "Building hero..."
v -enable-globals hero.v > build.log 2>&1 || (cat build.log && exit 1)
ln -s "$(realpath hero)" /bin/hero

cd /root

# If a command was provided to `docker run`, execute it as-is.
# Example: docker run hero-git:latest bash -lc 'cd /opt/herolib && ./examples/installers/horus/horus_full_install.vsh'
if [ "$#" -gt 0 ]; then
    exec "$@"
else
    # No command passed → give an interactive shell
    exec bash
fi

Important environment variables

  • HEROLIB_REF

    • Git ref (branch, tag, or commit) used when checking out /opt/herolib.
    • Default: development.
    • Example for CI: HEROLIB_REF=development_nile_installers.

Optional mounts

  • /opt/herolib_mount

    • If you bind-mount your local herolib repo here, the container will use it instead of the cloned /opt/herolib.
    • Useful for local development when you want to test uncommitted changes.
  • /root/ssh

    • Optional directory containing SSH keys (e.g. id_ed25519) if you need to access private repositories.
    • If present and non-empty, keys are copied to /root/.ssh and added to an SSH agent.

What this image is used for

1. Local development / experimentation

You can drop into the container and manually run installers or commands against herolib:

# Interactive shell with default branch
docker run -it --rm hero-git:latest

# Use a specific herolib ref
docker run -it --rm -e HEROLIB_REF=development_nile_installers hero-git:latest

# Mount a local herolib repo and use that instead of the cloned one
docker run -it --rm \
  -v "$PWD/herolib:/opt/herolib_mount" \
  hero-git:latest

Inside the container you can then run:

cd /opt/herolib
./examples/installers/horus/horus_full_install.vsh

2. CI / Release builds for Horus

In CI (e.g. the release.yml workflow), this image is used to build Horus binaries via the V-based installer script:

  • The workflow:

    1. Ensures hero-git:latest is available on the self-hosted runner.
    2. Creates a local directory (e.g. hero-bin/) on the runner.
    3. Runs the container, mounting hero-bin/ into /root/hero/bin.
    4. Inside the container, executes ./examples/installers/horus/horus_full_install.vsh from /opt/herolib.
    5. The installer writes the compiled Horus binaries into /root/hero/bin, which appear on the host inside hero-bin/.
    6. The workflow then packages those binaries into .tar.gz archives and uploads them as release artifacts.

Example CI step:

- name: Run horus_full_install installer in container
  run: |
    set -euxo pipefail

    docker run --rm \
      -v "$PWD/hero-bin:/root/hero/bin" \
      -e HEROLIB_REF=development_nile_installers \
      hero-git:latest \
      bash -lc '
        set -euxo pipefail
        cd /opt/herolib
        ./examples/installers/horus/horus_full_install.vsh
        echo "===== AFTER INSTALL, ls -R /root/hero ====="
        ls -R /root/hero || true
      '

After this step, hero-bin/ on the host should contain binaries like:

  • supervisor
  • coordinator
  • horus
  • osiris
  • herorunner
  • runner_osiris
  • runner_sal

These are then packaged and attached to the Gitea release.


How to build the image

From the directory containing the Dockerfile and entrypoint.sh:

# Build the image (force a clean rebuild)
docker build --no-cache -t hero-git:latest .

# Verify entrypoint contents
docker run --rm --entrypoint cat hero-git:latest /bin/entrypoint.sh | tail -n 20

You should see the exec "$@" block at the end of the script, which ensures that commands passed to docker run are executed as-is inside the container.


How to run the image (examples)

Basic interactive usage

# Default branch (HEROLIB_REF=development)
docker run -it --rm hero-git:latest

# Specific herolib ref
export HEROLIB_REF=development_nile_installers

docker run -it --rm \
  -e HEROLIB_REF=$HEROLIB_REF \
  hero-git:latest

Build Horus binaries into a host directory

mkdir -p hero-bin

docker run --rm \
  -v "$PWD/hero-bin:/root/hero/bin" \
  -e HEROLIB_REF=development_nile_installers \
  hero-git:latest \
  bash -lc '
    set -euxo pipefail
    cd /opt/herolib
    ./examples/installers/horus/horus_full_install.vsh
    ls -al /root/hero/bin
  '

ls -al hero-bin

You should now see the built Horus binaries on the host in hero-bin/.


Summary

  • The hero-git:latest image encapsulates all dependencies required to build Horus via herolib.

  • entrypoint.sh:

    • Starts Redis
    • Optionally configures SSH
    • Selects and updates the herolib checkout
    • Builds the hero CLI once
    • Runs any command passed to the container (e.g. Horus installers)
  • CI uses this image to run horus_full_install.vsh and collect Horus binaries from /root/hero/bin for releases.