Skip to content

Publish OpenClaw container image to GHCR #142

@bussyjd

Description

@bussyjd

Summary

The OpenClaw Helm chart references ghcr.io/obolnetwork/openclaw:<tag> but we don't publish this image yet. Currently, local development requires manually building from the upstream OpenClaw source and importing into k3d:

docker build -t ghcr.io/obolnetwork/openclaw:v2026.2.3 /path/to/openclaw/
k3d image import ghcr.io/obolnetwork/openclaw:v2026.2.3 -c <cluster>

We need a CI pipeline to build and publish the image so obol openclaw up works out of the box without manual image builds.

Proposed Approach

Model the workflow on charon-dkg-sidecar/.github/workflows/docker-publish.yml, which is our existing pattern for shipping container images.

Simplest implementation

Add a docker-publish-openclaw.yml workflow in this repo (obol-stack) that:

  1. Triggers on push to main (when internal/openclaw/** changes) and on v* tags
  2. Clones upstream OpenClaw at a pinned commit/tag (specified in internal/openclaw/OPENCLAW_VERSION)
  3. Builds the image using the upstream Dockerfile (Node.js 22 + pnpm, already non-root hardened)
  4. Publishes to ghcr.io/obolnetwork/openclaw with semver tags
  5. Scans with Trivy for vulnerabilities (same as charon-dkg-sidecar)

Renovate Integration

The version file uses Renovate's inline hint convention for automatic upstream tracking:

internal/openclaw/OPENCLAW_VERSION:

# renovate: datasource=github-releases depName=openclaw/openclaw
v2026.2.3

Automated flow:

  1. Upstream openclaw/openclaw cuts a new GitHub release (e.g. v2026.3.0)
  2. Renovate detects it, opens a PR bumping OPENCLAW_VERSION from v2026.2.3v2026.3.0
  3. PR merge triggers the docker-publish-openclaw.yml workflow (path filter matches internal/openclaw/**)
  4. New image published to ghcr.io/obolnetwork/openclaw:v2026.3.0

No custom regex manager config needed — the # renovate: comment is Renovate's standard inline datasource hint.

Key differences from charon-dkg-sidecar

Aspect charon-dkg-sidecar openclaw
Source Same repo Upstream openclaw/openclaw (pinned version)
Runtime Node.js (TypeScript) Node.js (TypeScript)
Platforms amd64 + arm64 amd64 + arm64
Registries GHCR + Docker Hub GHCR only (initially)
Build args BUILDTIME, GITCOMMIT, VERSION OPENCLAW_DOCKER_APT_PACKAGES (optional)

Tag strategy

tags:
  type=semver,pattern={{version}}           # v2026.2.3
  type=semver,pattern={{major}}.{{minor}}   # v2026.2
  type=sha,prefix=                         # abc1234
  type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

The chart values.yaml references a specific tag (currently v2026.2.3), so users get a deterministic deployment.

Acceptance Criteria

  • GitHub Actions workflow builds OpenClaw image from pinned upstream source
  • Image published to ghcr.io/obolnetwork/openclaw:<tag>
  • Multi-platform support (amd64 + arm64)
  • Trivy security scan on main branch pushes
  • Version pinning file (OPENCLAW_VERSION) with Renovate inline hint for automatic bumps
  • Renovate auto-opens PRs when upstream openclaw/openclaw cuts a new release
  • obol openclaw up works without manual docker build / k3d image import
  • Chart values.yaml tag matches published image tag

References

  • Existing pattern: charon-dkg-sidecar/docker-publish.yml
  • Upstream Dockerfile: openclaw/openclaw repo (Node 22 + pnpm + Bun build, non-root USER node)
  • Chart values: internal/openclaw/chart/values.yaml (image.tag: "v2026.2.3")

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions