Files
roboco/.github/workflows/release.yml
T
Renn FandRenzo F 3838d64eaa sandbox: kitchen-sink images, feature-aware selection (Phase 2)
Phase 1 made the provisioner able to activate allowlisted extensions
post-ready but kept the bare upstream images. Phase 2 ships the images that
actually carry the extension/module files, and selects them only when a
venture requests features — bare sandboxes stay on the light upstream image
(no heavier pull, honoring the 'existing opters stay bare' decision).

- _PostgresEngine / _RedisEngine gain kitchen_sink_image + image_for(features):
  bare (no features) -> the light image; features requested -> the kitchen-sink
  image. The provisioner runs engine.image_for(features), not engine.image, so
  the bare path is byte-for-byte unchanged. Mongo inherits the base image_for
  (returns its image regardless — no activatable features).
- docker/sandbox-pg.Dockerfile: pgvector/pgvector:pg16 (ships vector) + postgis
  apt install; contrib (pg_trgm/citext/uuid-ossp) inherited from the official
  postgres base. Built at deploy via the sandbox-pg-image compose one-shot
  (mirrors the agent-image builders); the provisioner's _ensure_image finds the
  local tag and never pulls. Published by release.yml; pulled in registry
  compose. The verify step fails loudly if an extension's files are missing.
- _RedisEngine kitchen-sink image: redis/redis-stack-server:latest (headless;
  ships search/json/bloom as loadable-but-unloaded modules — no custom build).
- Extended the sandbox image-tag ghost-tag guard (the mongo:8-alpine regression
  test) to also cover kitchen_sink_image: skips locally-built roboco-* images,
  uses the namespaced Docker Hub endpoint for redis/redis-stack-server.

Image-specific package names / module .so paths are verified at the CEO's NAS
deploy (the spec's NAS smoke); the unit tests with the fake runner remain the
CI bar, and the verify step is the fail-loud safety net for a wrong build.
2026-07-13 20:05:45 +02:00

139 lines
5.6 KiB
YAML

name: Release
on:
release:
types: [published]
workflow_dispatch:
jobs:
publish-images:
name: Build & push all RoboCo images to GHCR + Docker Hub
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
env:
GHCR: ghcr.io/rennf93 # GitHub Container Registry namespace
DOCKERHUB: docker.io/renzof93 # Docker Hub namespace (different username)
steps:
- name: Checkout code
uses: actions/checkout@v7
- name: Free up runner disk space
run: |
# Eleven images on one runner is disk-heavy; drop preinstalled tooling
# we don't use so the builds don't run out of space.
sudo rm -rf /usr/share/dotnet /opt/ghc /usr/local/lib/android /opt/hostedtoolcache/CodeQL || true
df -h /
- name: Log in to GitHub Container Registry
uses: docker/login-action@v4
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Log in to Docker Hub
uses: docker/login-action@v4
with:
username: renzof93
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Derive version tag
id: ver
run: |
# release → the tag (v0.1.0 → 0.1.0). Any manual dispatch runs against a
# branch whose name can contain "/" (e.g. feature/x) — not a valid image
# tag — so use the short SHA, which always is one.
if [ "${{ github.event_name }}" = "release" ]; then
RAW="${{ github.event.release.tag_name }}"
VERSION="${RAW#v}"
else
VERSION="$(git rev-parse --short HEAD)"
fi
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
echo "Release version: $VERSION"
- name: Build & push every RoboCo image
env:
VERSION: ${{ steps.ver.outputs.version }}
run: |
set -euo pipefail
# Tag one built image for both registries at :VERSION and :latest.
regtags() {
local name="$1"
echo "-t ${GHCR}/${name}:${VERSION} -t ${GHCR}/${name}:latest" \
"-t ${DOCKERHUB}/${name}:${VERSION} -t ${DOCKERHUB}/${name}:latest"
}
# Push one image's four tags (both registries, both labels).
pushall() {
local name="$1"
for ref in "${GHCR}/${name}" "${DOCKERHUB}/${name}"; do
docker push "${ref}:${VERSION}"
docker push "${ref}:latest"
done
}
# agent-base MUST build first: the agent images build
# `FROM roboco-agent-base` — a local tag that has to exist in the daemon
# before they build. Tag it locally (for the FROM) and for both registries.
echo "::group::build roboco-agent-base"
docker build -f docker/agent-base.Dockerfile \
-t roboco-agent-base $(regtags roboco-agent-base) .
echo "::endgroup::"
# roboco-agent-grok MUST build next, ahead of the loop: the two
# interactive Grok roles (prompter, secretary) build `FROM
# roboco-agent-grok` — a local tag that has to exist in the daemon
# before they build, and bash associative-array iteration order is
# unspecified, so it can't just be another entry in IMAGES below.
echo "::group::build roboco-agent-grok"
docker build -f docker/agent-grok.Dockerfile \
-t roboco-agent-grok $(regtags roboco-agent-grok) .
echo "::endgroup::"
# Every other image → its Dockerfile. Names mirror docker-compose's
# `image:` values exactly, so compose can later pull instead of build.
declare -A IMAGES=(
[roboco-orchestrator]=docker/orchestrator.Dockerfile
[roboco-panel]=docker/panel.Dockerfile
[roboco-video-renderer]=docker/video-renderer.Dockerfile
[roboco-sandbox-pg]=docker/sandbox-pg.Dockerfile
[roboco-agent-pm]=docker/agent-pm.Dockerfile
[roboco-agent-dev-be]=docker/agent-dev-be.Dockerfile
[roboco-agent-dev-fe]=docker/agent-dev-fe.Dockerfile
[roboco-agent-qa-be]=docker/agent-qa-be.Dockerfile
[roboco-agent-qa-fe]=docker/agent-qa-fe.Dockerfile
[roboco-agent-ux]=docker/agent-ux.Dockerfile
[roboco-agent-doc]=docker/agent-doc.Dockerfile
[roboco-agent-prompter]=docker/agent-prompter.Dockerfile
[roboco-agent-secretary]=docker/agent-secretary.Dockerfile
[roboco-agent-pr-reviewer]=docker/agent-pr-reviewer.Dockerfile
[roboco-agent-grok-prompter]=docker/agent-grok-prompter.Dockerfile
[roboco-agent-grok-secretary]=docker/agent-grok-secretary.Dockerfile
)
for name in "${!IMAGES[@]}"; do
echo "::group::build ${name}"
docker build -f "${IMAGES[$name]}" $(regtags "${name}") .
echo "::endgroup::"
done
# Push only after every build succeeds, so a failure never leaves a
# half-published release. Base first, then the rest.
echo "::group::push roboco-agent-base"
pushall roboco-agent-base
echo "::endgroup::"
echo "::group::push roboco-agent-grok"
pushall roboco-agent-grok
echo "::endgroup::"
for name in "${!IMAGES[@]}"; do
echo "::group::push ${name}"
pushall "${name}"
echo "::endgroup::"
done
echo "Published roboco-agent-base + roboco-agent-grok + ${#IMAGES[@]} more images to GHCR + Docker Hub at :${VERSION} and :latest"