Add lair/containers image-build repo; hermes as first image
Some checks failed
images / hermes (push) Has been cancelled

Builds container images for lair infra and publishes to git.lair.cafe.
Hermes Agent (NousResearch) is built directly from its upstream Dockerfile
at the latest release tag, published as git.lair.cafe/lair/hermes; the build
is release-triggered (daily API poll) and self-healing (gated on registry
presence, not a committable pin). Includes a draft rootful quadlet for bob
matching the agent-zero/open-webui convention. Convention follows gongfoo.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011D3YeWKpjg5bT488fVanCH
This commit is contained in:
grenade
2026-06-23 12:17:10 +03:00
commit 214850dae4
6 changed files with 263 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
name: images
# Build container images required by lair infra and publish them to the Gitea
# registry at git.lair.cafe. Convention mirrors gongfoo/.gitea/workflows/images.yml.
#
# Hermes is the first image: built directly from NousResearch/hermes-agent's own
# Dockerfile at the latest upstream release tag, and published as
# git.lair.cafe/lair/hermes:{<version>,latest}. bob then pulls it via a normal
# AutoUpdate=registry quadlet.
on:
push:
branches: [main]
paths:
- "images/**"
- ".gitea/workflows/images.yml"
schedule:
# Daily poll for new upstream releases (Gitea can't subscribe to GitHub
# release webhooks, so we poll). Release-triggered in effect: a build only
# runs when the resolved upstream version isn't already in our registry.
- cron: "0 7 * * *"
workflow_dispatch:
inputs:
force:
description: "Rebuild even if the version is already published"
type: boolean
default: false
jobs:
hermes:
runs-on:
- metal
- podman
steps:
- uses: actions/checkout@v4
- name: resolve latest upstream release
id: rel
run: |
# Prefer a published release; fall back to the newest tag.
tag=$(curl -fsS 'https://api.github.com/repos/NousResearch/hermes-agent/releases/latest' | jq -r '.tag_name // empty')
if [ -z "$tag" ]; then
tag=$(curl -fsS 'https://api.github.com/repos/NousResearch/hermes-agent/tags' | jq -r '.[0].name // empty')
fi
if [ -z "$tag" ] || [ "$tag" = "null" ]; then
echo "ERROR: could not resolve an upstream hermes release/tag"; exit 1
fi
echo "upstream latest: $tag"
echo "tag=$tag" >> "$GITHUB_OUTPUT"
echo "version=${tag#v}" >> "$GITHUB_OUTPUT"
- name: login to registry
run: podman login -u ${{ gitea.actor }} -p ${{ secrets.REGISTRY_TOKEN }} git.lair.cafe
- name: build & push (release-triggered, self-healing)
env:
TAG: ${{ steps.rel.outputs.tag }}
VERSION: ${{ steps.rel.outputs.version }}
FORCE: ${{ github.event.inputs.force }}
run: |
IMAGE=git.lair.cafe/lair/hermes
# Self-healing: the source of truth is "is this version in the registry?"
# — not a committed pin that can desync if a prior build failed.
if [ "$FORCE" != "true" ] && skopeo inspect "docker://${IMAGE}:${VERSION}" >/dev/null 2>&1; then
echo "${IMAGE}:${VERSION} already published — nothing to build"
exit 0
fi
echo "building ${IMAGE}:${VERSION} from NousResearch/hermes-agent#${TAG}"
podman build --pull=newer \
-t "${IMAGE}:${VERSION}" \
-t "${IMAGE}:latest" \
"https://github.com/NousResearch/hermes-agent.git#${TAG}"
podman push "${IMAGE}:${VERSION}"
podman push "${IMAGE}:latest"
echo "published ${IMAGE}:${VERSION} (and :latest)"