From cb51ba72bc02b71036f8c457b4f389f55f280891 Mon Sep 17 00:00:00 2001 From: pyr0ball Date: Fri, 3 Apr 2026 09:10:29 -0700 Subject: [PATCH] feat: cf-orch Docker image + Forgejo CI pipeline MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Dockerfile.orch — multi-mode image (coordinator | agent): - coordinator: runs cf-orch coordinator on $CF_ORCH_PORT (default 7700) - agent: connects to $CF_COORDINATOR_URL, serves $CF_AGENT_GPU_IDS .forgejo/workflows/docker.yml — publishes on every vN.N.N tag: - ghcr.io/circuit-forge/cf-orch:latest - ghcr.io/circuit-forge/cf-orch:vX.Y.Z - Layer cache via GHA cache backend Closes #19. Bumps to v0.6.0. --- .forgejo/workflows/docker.yml | 60 +++++++++++++++++++++++++++++++++++ Dockerfile.orch | 53 +++++++++++++++++++++++++++++++ docker/orch-entrypoint.sh | 25 +++++++++++++++ pyproject.toml | 2 +- 4 files changed, 139 insertions(+), 1 deletion(-) create mode 100644 .forgejo/workflows/docker.yml create mode 100644 Dockerfile.orch create mode 100644 docker/orch-entrypoint.sh diff --git a/.forgejo/workflows/docker.yml b/.forgejo/workflows/docker.yml new file mode 100644 index 0000000..3353cbf --- /dev/null +++ b/.forgejo/workflows/docker.yml @@ -0,0 +1,60 @@ +name: Build and publish cf-orch Docker image + +on: + push: + tags: + - "v*" + workflow_dispatch: + +env: + REGISTRY: ghcr.io + IMAGE_NAME: circuit-forge/cf-orch + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Extract version from tag + id: meta + run: | + TAG="${GITHUB_REF_NAME}" + echo "tag=${TAG}" >> "$GITHUB_OUTPUT" + echo "image=${REGISTRY}/${IMAGE_NAME}" >> "$GITHUB_OUTPUT" + + - name: Log in to GHCR + uses: docker/login-action@v3 + with: + registry: ${{ env.REGISTRY }} + username: ${{ github.actor }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Build and push + uses: docker/build-push-action@v5 + with: + context: . + file: Dockerfile.orch + push: true + tags: | + ${{ steps.meta.outputs.image }}:latest + ${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.tag }} + cache-from: type=gha + cache-to: type=gha,mode=max + labels: | + org.opencontainers.image.version=${{ steps.meta.outputs.tag }} + org.opencontainers.image.revision=${{ github.sha }} + + - name: Summary + run: | + echo "### Published" >> "$GITHUB_STEP_SUMMARY" + echo "- \`${{ steps.meta.outputs.image }}:latest\`" >> "$GITHUB_STEP_SUMMARY" + echo "- \`${{ steps.meta.outputs.image }}:${{ steps.meta.outputs.tag }}\`" >> "$GITHUB_STEP_SUMMARY" diff --git a/Dockerfile.orch b/Dockerfile.orch new file mode 100644 index 0000000..3665683 --- /dev/null +++ b/Dockerfile.orch @@ -0,0 +1,53 @@ +# cf-orch coordinator image +# Includes the coordinator + agent; designed for paid+ multi-node deployments. +# +# Usage (coordinator node): +# docker run -d \ +# -p 7700:7700 \ +# -e HEIMDALL_URL=https://license.circuitforge.tech \ +# -e HEIMDALL_MIN_TIER=paid \ +# -e CF_ORCH_AUTH_SECRET= \ +# ghcr.io/circuit-forge/cf-orch:latest coordinator +# +# Usage (GPU agent node — connects back to coordinator): +# docker run -d \ +# --gpus all \ +# -e CF_COORDINATOR_URL=http://:7700 \ +# ghcr.io/circuit-forge/cf-orch:latest agent +# +# Environment variables +# ───────────────────── +# CF_ORCH_PORT Coordinator listen port (default: 7700) +# HEIMDALL_URL Enable license auth (omit for LAN-only / self-hosted) +# HEIMDALL_MIN_TIER Minimum tier required (default: paid) +# CF_ORCH_AUTH_SECRET Shared secret with Heimdall /licenses/verify +# CF_COORDINATOR_URL Agent mode: coordinator URL to register with +# CF_AGENT_GPU_IDS Comma-separated GPU indices for agent (default: 0) + +FROM python:3.12-slim + +LABEL org.opencontainers.image.source="https://git.opensourcesolarpunk.com/Circuit-Forge/circuitforge-core" +LABEL org.opencontainers.image.description="cf-orch coordinator and agent for CircuitForge multi-node GPU orchestration" +LABEL org.opencontainers.image.licenses="BSL-1.1" + +WORKDIR /app + +# System deps — httpx needs curl for connection reuse; avoid full dev toolchain +RUN apt-get update && apt-get install -y --no-install-recommends \ + curl \ + && rm -rf /var/lib/apt/lists/* + +# Install cf-core with the resources extra (coordinator + agent deps) +COPY pyproject.toml README.md ./ +COPY circuitforge_core/ ./circuitforge_core/ + +RUN pip install --no-cache-dir ".[resources,manage]" + +ENV CF_ORCH_PORT=7700 +EXPOSE 7700 + +COPY docker/orch-entrypoint.sh /entrypoint.sh +RUN chmod +x /entrypoint.sh + +ENTRYPOINT ["/entrypoint.sh"] +CMD ["coordinator"] diff --git a/docker/orch-entrypoint.sh b/docker/orch-entrypoint.sh new file mode 100644 index 0000000..eeb9aac --- /dev/null +++ b/docker/orch-entrypoint.sh @@ -0,0 +1,25 @@ +#!/bin/bash +set -e + +MODE="${1:-coordinator}" +PORT="${CF_ORCH_PORT:-7700}" + +case "$MODE" in + coordinator) + echo "[cf-orch] Starting coordinator on port $PORT" + exec python -m circuitforge_core.resources.cli coordinator \ + --host 0.0.0.0 --port "$PORT" + ;; + agent) + COORDINATOR="${CF_COORDINATOR_URL:?CF_COORDINATOR_URL must be set for agent mode}" + GPU_IDS="${CF_AGENT_GPU_IDS:-0}" + echo "[cf-orch] Starting agent — coordinator=$COORDINATOR gpu_ids=$GPU_IDS" + exec python -m circuitforge_core.resources.cli agent \ + --coordinator "$COORDINATOR" \ + --gpu-ids "$GPU_IDS" + ;; + *) + echo "Usage: cf-orch [coordinator|agent]" + exit 1 + ;; +esac diff --git a/pyproject.toml b/pyproject.toml index 121ffda..197b66f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "circuitforge-core" -version = "0.5.0" +version = "0.6.0" description = "Shared scaffold for CircuitForge products" requires-python = ">=3.11" dependencies = [