From daa711f9dd035abe67846183fa727962ddddecb1 Mon Sep 17 00:00:00 2001 From: Rihards Gailums Date: Sat, 23 May 2026 17:29:45 +0000 Subject: [PATCH] deploy: wire the processgit-updater sidecar into docker-compose Updates `deploy/docker-compose.yml` and adds `deploy/.env.example` to support the in-product self-update story. Three changes to the compose file: 1. The processgit / processgit-init-perms / processgit-bootstrap services now use `image: ghcr.io/algomation-ai/processgit:${PROCESSGIT_VERSION:-latest}` instead of the hard-coded local `processgit:0.1` tag. `build:` is preserved, so `docker compose up --build` still works for source builds; production deployments use `docker compose pull` + up. 2. Adds the `processgit-updater` service (image ghcr.io/algomation-ai/processgit-updater:${PROCESSGIT_VERSION:-latest}), with /var/run/docker.sock bind-mounted plus a state volume for the job log. Bind-mounts the deploy/ directory RW so the updater can drive `docker compose up --no-deps processgit` and persist the new PROCESSGIT_VERSION value in .env after a successful update. 3. PROCESSGIT_UPDATER_TOKEN is now a required interpolation variable on both processgit and processgit-updater services (`${PROCESSGIT_UPDATER_TOKEN:?...}`). Compose will fail fast at `up` time if it's unset. `deploy/.env.example` is the new template documenting: - PROCESSGIT_UPDATER_TOKEN (required; generate with `openssl rand -hex 32`) - PROCESSGIT_VERSION (defaults to "latest"; the updater rewrites this on commit so the new version persists across host restarts) - PROCESSGIT_UPDATER_REPO (optional; defaults to Algomation-AI/ProcessGit) - PROCESSGIT_UPDATER_STUB (Slice 3A default = "true" until 3B real docker calls ship; this PR's docker-compose threads the value through so operators can flip without redeploying) The new env file convention: - deploy/.env is created by the operator (copied from .env.example) and managed by the updater. Contains PROCESSGIT_UPDATER_TOKEN and PROCESSGIT_VERSION. - ../.env (project root) is the operator's app-config file (existing env_file mount), unchanged. Co-authored-by: Claude --- deploy/.env.example | 60 +++++++++++++++++++++++++++++++++++++++ deploy/docker-compose.yml | 60 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 deploy/.env.example diff --git a/deploy/.env.example b/deploy/.env.example new file mode 100644 index 0000000..8ffc398 --- /dev/null +++ b/deploy/.env.example @@ -0,0 +1,60 @@ +# ProcessGit deployment environment. +# +# Copy this file to ../.env (one level above deploy/) and fill in the values. +# All variables marked `(required)` MUST be set; the others can be left blank +# to accept defaults. +# +# Generate the bearer token once: +# openssl rand -hex 32 +# +# Then either: +# - Paste it into PROCESSGIT_UPDATER_TOKEN= below, or +# - Run: echo "PROCESSGIT_UPDATER_TOKEN=$(openssl rand -hex 32)" >> ../.env + +# ----------------------------------------------------------------------------- +# REQUIRED +# ----------------------------------------------------------------------------- + +# Shared bearer token between the main ProcessGit app and the updater sidecar. +# 64 hex chars = 32 bytes of entropy. Both containers read this from .env. +# (required) +PROCESSGIT_UPDATER_TOKEN= + +# ----------------------------------------------------------------------------- +# VERSION CONTROL +# ----------------------------------------------------------------------------- + +# Pin the ProcessGit image version. The updater rewrites this line when a +# release is committed via the in-product UI, so the next `docker compose up` +# reuses the same version after a host restart. +# Defaults to `latest` if unset, which moves on every stable release — +# acceptable for evaluation but not recommended for production. +PROCESSGIT_VERSION=latest + +# ----------------------------------------------------------------------------- +# UPDATER CONFIG (optional) +# ----------------------------------------------------------------------------- + +# GitHub repository the updater polls for releases. +PROCESSGIT_UPDATER_REPO=Algomation-AI/ProcessGit + +# Slice 3A stub mode. The updater simulates the docker operations rather +# than actually pulling/swapping containers. Default true while the docker +# operations harden in Slice 3B. +# Flip to `false` once Slice 3B (real docker calls) is merged AND you've +# tested a stub-mode update flow end-to-end. +PROCESSGIT_UPDATER_STUB=true + +# ----------------------------------------------------------------------------- +# PROCESSGIT APP CONFIG (passed through env_file to the main container) +# ----------------------------------------------------------------------------- + +# Add any APP_* / GITEA_* / PROCESSGIT_* settings you want passed to the +# main app container here. See: +# https://docs.gitea.com/installation/install-with-docker +# for the available config keys (ProcessGit inherits Gitea's config surface). + +# Example: +# APP_NAME=ProcessGit +# DOMAIN=processgit.example.com +# SSH_PORT=12222 diff --git a/deploy/docker-compose.yml b/deploy/docker-compose.yml index 83e8120..de3c9e1 100644 --- a/deploy/docker-compose.yml +++ b/deploy/docker-compose.yml @@ -1,11 +1,33 @@ +# ProcessGit production-capable deployment. +# +# Two ways to run this: +# +# 1. Build locally from source (dev / first install): +# docker compose -f deploy/docker-compose.yml up --build -d +# +# 2. Pull from GHCR (production / after first install): +# docker compose -f deploy/docker-compose.yml pull +# docker compose -f deploy/docker-compose.yml up -d +# +# The `processgit-updater` service drives in-product updates from the +# admin UI. It requires: +# +# - $PROCESSGIT_UPDATER_TOKEN in .env (generate once via: +# openssl rand -hex 32 >> /tmp/x && sed -i "s/^/PROCESSGIT_UPDATER_TOKEN=/" /tmp/x +# then append /tmp/x to your .env). See deploy/.env.example. +# - /var/run/docker.sock bind-mounted (it needs to drive `docker pull` etc). +# - deploy/ directory bind-mounted, so the updater can find this file and +# persist the new PROCESSGIT_VERSION to .env on commit. + services: processgit: container_name: processgit restart: unless-stopped + # Build OR pull, depending on whether the local tag exists. build: context: .. dockerfile: deploy/Dockerfile.processgit - image: processgit:0.1 + image: ghcr.io/algomation-ai/processgit:${PROCESSGIT_VERSION:-latest} depends_on: processgit-init-perms: condition: service_completed_successfully @@ -21,6 +43,9 @@ services: USER_GID: "1000" APP_NAME: "ProcessGit: Git for Processes" PROCESSGIT_SEED_STRICT: "false" + # So the main app knows how to reach the updater + PROCESSGIT_UPDATER_URL: "http://processgit-updater:9000" + PROCESSGIT_UPDATER_TOKEN: ${PROCESSGIT_UPDATER_TOKEN:?PROCESSGIT_UPDATER_TOKEN is required - see deploy/.env.example} healthcheck: test: ["CMD-SHELL", "wget -qO- http://localhost:3000/api/v1/version >/dev/null 2>&1 || exit 1"] interval: 5s @@ -28,7 +53,7 @@ services: retries: 30 processgit-init-perms: - image: processgit:0.1 + image: ghcr.io/algomation-ai/processgit:${PROCESSGIT_VERSION:-latest} user: "0:0" volumes: - processgit-data:/data @@ -37,7 +62,7 @@ services: restart: "no" processgit-bootstrap: - image: processgit:0.1 + image: ghcr.io/algomation-ai/processgit:${PROCESSGIT_VERSION:-latest} restart: "no" depends_on: processgit: @@ -51,5 +76,34 @@ services: entrypoint: ["/bin/sh", "-c"] command: ["/opt/processgit/bootstrap/bootstrap-templates.sh"] + # --------------------------------------------------------------------------- + # Self-update sidecar. See updater/README.md. + # Drives `docker compose up --no-deps processgit` with a new version variable + # when the admin clicks "Install update" in the UI. + # --------------------------------------------------------------------------- + processgit-updater: + container_name: processgit-updater + restart: unless-stopped + image: ghcr.io/algomation-ai/processgit-updater:${PROCESSGIT_VERSION:-latest} + environment: + PROCESSGIT_UPDATER_TOKEN: ${PROCESSGIT_UPDATER_TOKEN:?PROCESSGIT_UPDATER_TOKEN is required - see deploy/.env.example} + PROCESSGIT_UPDATER_REPO: ${PROCESSGIT_UPDATER_REPO:-Algomation-AI/ProcessGit} + PROCESSGIT_UPDATER_APP_CONTAINER: processgit + PROCESSGIT_UPDATER_COMPOSE_FILE: /deploy/docker-compose.yml + PROCESSGIT_UPDATER_ENV_FILE: /deploy/.env + # Slice 3A landed with stubs as the default; flip to "false" once Slice 3B is merged. + # Override here per deployment if you want to opt into real updates early. + PROCESSGIT_UPDATER_STUB: ${PROCESSGIT_UPDATER_STUB:-true} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - processgit-updater-state:/var/lib/processgit-updater + # The deploy/ directory is mounted RW so the updater can: + # - read docker-compose.yml to drive `docker compose up --no-deps` + # - persist the new PROCESSGIT_VERSION to .env on commit + - .:/deploy + # Parent dir (project root) RO for .env access via ../.env path + - ..:/host-root:ro + volumes: processgit-data: + processgit-updater-state: