From 064623717b3d9d9a1946feb4911b626c187abd38 Mon Sep 17 00:00:00 2001 From: Chris Alfano Date: Tue, 19 May 2026 19:03:40 -0400 Subject: [PATCH] ops(runbook): script + doc for fetching from the pod's data clone MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When investigating divergence between the sandbox and what's pushed to origin (or just chasing what the push daemon has in flight), it's useful to add the pod's PVC-backed clone as a git remote without exposing a network port. Git's ext:: transport lets you spawn an arbitrary command and speak git protocol over its stdio — here we shell into the pod and run git-upload-pack on /app/data. scripts/git-pod-uploadpack.sh resolves the pod by label selector each invocation (survives restarts) and reads kubeconfig / namespace / selector / data path from env with sensible defaults so a single line in the data repo's .git/config picks up the right pod for whoever has the kubeconfig. Runbook entry covers setup, env-var overrides, and the "read-only by design" carve-out — pushing to the pod would fight gitsheets and the push daemon. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/operations/runbook.md | 25 +++++++++++++++++++++++++ scripts/git-pod-uploadpack.sh | 29 +++++++++++++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100755 scripts/git-pod-uploadpack.sh diff --git a/docs/operations/runbook.md b/docs/operations/runbook.md index a9bba9e..1bda771 100644 --- a/docs/operations/runbook.md +++ b/docs/operations/runbook.md @@ -148,6 +148,31 @@ for the authoritative contract. Operationally: with the outcome + commits; failures log error. Search the pod logs for `hot-reload` to audit the most recent firings. +## Fetch from the pod's data clone + +The pod's working tree lives on a PVC at `/app/data` inside the container and may briefly hold commits the push daemon hasn't shipped to GitHub yet (or that got escape-hatched onto a `conflicts/*` branch — those *are* always pushed, see [`apps/api/src/store/reconcile.ts`](../../apps/api/src/store/reconcile.ts)). When you want to inspect the pod's view of the data repo without exposing any network ports, add it as a git remote via the `ext::` transport. + +```bash +cd /path/to/codeforphilly-data + +git config protocol.ext.allow always +git remote add pod 'ext::sh /path/to/codeforphilly-ng/scripts/git-pod-uploadpack.sh' + +git fetch pod +git log --oneline pod/published..pod/published # whatever you're chasing +``` + +The helper script resolves the current pod by label selector, so it survives restarts. Override via env if your setup differs: + +| Var | Default | +|---|---| +| `CFP_POD_KUBECONFIG` | `~/.kube/cfp-sandbox-cluster-kubeconfig.yaml` | +| `CFP_POD_NAMESPACE` | `codeforphilly-rewrite-sandbox` | +| `CFP_POD_SELECTOR` | `app.kubernetes.io/name=codeforphilly` | +| `CFP_POD_DATA_PATH` | `/app/data` | + +**Read-only by design** — `git upload-pack` only serves fetch; pushing back to the pod would bypass gitsheets + in-memory state and fight the push daemon. Pull what you need to your local clone, reason about it there, then push to `origin` if appropriate. + ## Helpful commands ```bash diff --git a/scripts/git-pod-uploadpack.sh b/scripts/git-pod-uploadpack.sh new file mode 100755 index 0000000..301e585 --- /dev/null +++ b/scripts/git-pod-uploadpack.sh @@ -0,0 +1,29 @@ +#!/usr/bin/env bash +# Spawn `git upload-pack` inside the running sandbox pod so you can fetch from +# the pod's PVC-backed data clone as a git remote. Designed to be plumbed into +# git's `ext::` transport — see docs/operations/runbook.md → "Fetch from the +# pod's data clone". +# +# Env (all optional, sensible defaults baked in): +# CFP_POD_KUBECONFIG — path to kubeconfig (default ~/.kube/cfp-sandbox-cluster-kubeconfig.yaml) +# CFP_POD_NAMESPACE — k8s namespace (default codeforphilly-rewrite-sandbox) +# CFP_POD_SELECTOR — label selector for the pod (default app.kubernetes.io/name=codeforphilly) +# CFP_POD_DATA_PATH — repo path inside the pod (default /app/data) +set -euo pipefail + +KUBECONFIG_PATH="${CFP_POD_KUBECONFIG:-$HOME/.kube/cfp-sandbox-cluster-kubeconfig.yaml}" +NAMESPACE="${CFP_POD_NAMESPACE:-codeforphilly-rewrite-sandbox}" +SELECTOR="${CFP_POD_SELECTOR:-app.kubernetes.io/name=codeforphilly}" +DATA_PATH="${CFP_POD_DATA_PATH:-/app/data}" + +POD=$(kubectl --kubeconfig="$KUBECONFIG_PATH" -n "$NAMESPACE" \ + get pod -l "$SELECTOR" --field-selector=status.phase=Running \ + -o jsonpath='{.items[0].metadata.name}') + +if [[ -z "$POD" ]]; then + echo "git-pod-uploadpack: no Running pod matched $SELECTOR in $NAMESPACE" >&2 + exit 1 +fi + +exec kubectl --kubeconfig="$KUBECONFIG_PATH" -n "$NAMESPACE" \ + exec -i "$POD" -- git upload-pack "$DATA_PATH"