Commit 50d7d59

Eric Bower  ·  2026-08-15 21:00:22 -0400 EDT
parent 50e9dba
chore: rm proposal
1 files changed,  +0, -196
+0, -196
  1@@ -1,196 +0,0 @@
  2-# Proposal: Integrating Pici with GitHub Actions & `pipe.pico.sh` Remote Debugging
  3-
  4-## 1. Executive Summary
  5-
  6-Migrating existing projects away from GitHub Actions to a dedicated self-hosted CI system is difficult due to ecosystem inertia and configuration friction.
  7-
  8-This proposal outlines a strategy to provide an **official custom GitHub Action (`pico-sh/pici-action`)** powered by `pici run`. Developers write standard, parallel bash workflows (`pico.sh`) using `zmx`, execute them with 1:1 parity on both local workstations and GitHub Actions runners, and gain **live, interactive terminal debugging on failure** powered by native `pipe.pico.sh` bridging in Go.
  9-
 10----
 11-
 12-## 2. Core Design Goals
 13-
 14-1. **1-Step GitHub Action Experience**: A custom composite action (`pico-sh/pici-action@v1`) that installs `pici` + `zmx`, configures SSH keys, executes the workflow in-place, and uploads artifacts with zero boilerplate.
 15-2. **1:1 Local & Remote Parity**: `pici run` provides identical execution semantics across environments: metadata environment variable injection (`PICI_JOB`, `PICI_REPO`, `PICI_BRANCH`, `PICI_COMMIT`), `pico.sh` execution via `zmx`, live progress streaming, artifact rendering, and exit code propagation.
 16-3. **Explicit Workspace Semantics**: By default, `pici run` rsyncs to an isolated `/tmp` workspace to keep local working trees clean. In CI environments where the runner is already an ephemeral container/VM, an explicit `--in-place` flag instructs `pici run` to execute directly without rsyncing.
 17-4. **Native Docker Compatibility**: Mounts like `$(pwd):/app` work seamlessly in both local and CI environments.
 18-5. **Native Go Failure Hook (`pici debug`)**: When a job fails, `pici` directly opens a secure, authenticated PTY bridge to `pipe.pico.sh` in Go, avoiding brittle bash FIFOs or background SSH wrappers.
 19-6. **Security & Secret Scrubbing**: `pici` controls the debug shell environment and scrubs `GITHUB_TOKEN` and repository secrets before spawning interactive shells.
 20-
 21----
 22-
 23-## 3. The Custom GitHub Action: `pico-sh/pici-action`
 24-
 25-We are creating and publishing an official custom action—`pico-sh/pici-action`—that serves as the turnkey entrypoint for GitHub Actions users.
 26-
 27-### Standard Workflow (`.github/workflows/ci.yml`)
 28-
 29-With the custom action, adding Pici CI with remote debugging to any repo is a single step:
 30-
 31-```yaml
 32-name: CI
 33-on: [push, pull_request]
 34-
 35-jobs:
 36-  ci:
 37-    runs-on: ubuntu-latest
 38-    steps:
 39-      - uses: actions/checkout@v4
 40-
 41-      - name: Run CI with Pici
 42-        uses: picosh/pici-action@v1
 43-        with:
 44-          pico_ssh_key: ${{ secrets.PICO_SSH_KEY }}
 45-```
 46-
 47-### Action Configuration & Inputs
 48-
 49-| Input | Description | Default |
 50-| :--- | :--- | :--- |
 51-| `pico_ssh_key` | SSH private key registered with pico.sh for authenticated debug relay access. | `""` (optional, required for debug relay) |
 52-| `debug_on_fail` | Automatically open an interactive `pipe.pico.sh` debug bridge if a job fails. If omitted or `auto`, automatically enables when re-running with GitHub debug logging (`RUNNER_DEBUG=1`). | `"auto"` |
 53-
 54-### What `pico-sh/pici-action` Does Under the Hood
 55-1. **Tool Installation**: Installs the static `pici` and pinned `zmx` binaries (with SHA256 checksum verification) to `/usr/local/bin`.
 56-2. **Credential Setup**: Writes `pico_ssh_key` to a secure temp keyfile or SSH agent if provided.
 57-3. **Environment Propagation**: Passes GitHub Actions run metadata to `pici run`:
 58-   - `PICI_JOB="${GITHUB_RUN_ID}"`
 59-   - `PICI_EVENT="git.${GITHUB_EVENT_NAME}"`
 60-   - `PICI_BRANCH="${GITHUB_REF_NAME}"`
 61-   - `PICI_COMMIT="${GITHUB_SHA}"`
 62-4. **Execution (`pici run`)**: Invokes `pici run --in-place` (enabling `--debug-on-fail` if `debug_on_fail: true` or if GitHub's native debug re-run is active via `RUNNER_DEBUG=1`).
 63-5. **Job Summaries & Artifact Upload**:
 64-   - `pici` formats the run status table and failed logs into `$GITHUB_STEP_SUMMARY`.
 65-   - If `upload_artifacts` is enabled, the action uploads `/tmp/pici-artifacts/<repo>/<jobid>/` as a workflow artifact.
 66-
 67----
 68-
 69-## 4. Direct CLI Execution (Without the Action)
 70-
 71-For users who prefer manual step-by-step control or non-GitHub CI environments, `pici run` can be invoked directly:
 72-
 73-```yaml
 74-      - name: Run CI
 75-        run: |
 76-          pici run --in-place \
 77-            -e PICI_JOB="$GITHUB_RUN_ID" \
 78-            -e PICI_EVENT=git.push \
 79-            -e PICI_BRANCH="$GITHUB_REF_NAME" \
 80-            -e PICI_COMMIT="$GITHUB_SHA"
 81-```
 82-
 83----
 84-
 85-## 5. Native Go Debug Bridge (`pipe.pico.sh`)
 86-
 87-Rather than relying on bash scripts with named FIFOs (`mkfifo`) and background `ssh -N` commands, the relay bridge is implemented directly in Go inside `pici`:
 88-
 89-### How it works
 90-1. **Hook into Failure Path**: When `resolveJobExitCode()` detects a non-zero exit in `waitAndReport()` and debug mode is enabled (via `--debug-on-fail`, `-e PICI_DEBUG=1`, or GitHub Actions' standard `RUNNER_DEBUG=1`), `pici` initializes the debug session.
 91-2. **Native SSH Dialing**: `pici` dials `pipe.pico.sh` using the existing `-pk` / `-ck` SSH key infrastructure.
 92-3. **PTY Allocation (`creack/pty`)**: Spawns an interactive shell (`bash -i` or `$SHELL`) connected to the bidirectional SSH stream.
 93-4. **Attach Instructions & Notifications**: Prints the `ssh -t pipe.pico.sh pipe <topic>` command to stdout and appends it to `$GITHUB_STEP_SUMMARY`.
 94-5. **Idle Timeout & Clean Exit**: Waits for a connection with an idle timeout (e.g., 15 minutes). Once closed or timed out, `pici` terminates and exits with the original non-zero job exit code.
 95-6. **Standalone `pici debug`**: `pici debug <repo>/<jobid>` attaches to running or stalled jobs by targeting the deterministic session prefix (`ci.<repo>.<jobid>.`).
 96-
 97-### Security Advantages
 98-- **Environment Scrubbing**: Sensitive CI environment variables (`GITHUB_TOKEN`, `ACTIONS_RUNTIME_TOKEN`, injected secrets) are stripped from the debug shell process environment before launching.
 99-- **Host Key Pinning**: The `pipe.pico.sh` host key is verified natively in Go without passing `-o StrictHostKeyChecking=no`.
100-
101----
102-
103-## 6. Implementation & Verification Plan (Test Repository)
104-
105-To validate the complete flow end-to-end before public release, we will use a dedicated test repository (e.g., `picosh/pici-test`) to confirm local parity, GitHub Actions execution, and interactive failure recovery.
106-
107-### Step 1: Create the Test Repository Structure
108-
109-```
110-pici-test/
111-├── .github/
112-│   └── workflows/
113-│       ├── ci-action.yml    # Tests the custom picosh/pici-action
114-│       └── ci-direct.yml    # Tests direct pici binary execution
115-├── src/
116-│   └── main_test.go
117-├── pico.sh                  # Core CI script with configurable test modes
118-└── README.md
119-```
120-
121-### Step 2: Implement the Configurable `pico.sh`
122-
123-The test script supports environment variables to deterministically simulate success, failure, Docker steps, and hangs:
124-
125-```bash
126-#!/usr/bin/env bash
127-set -euo pipefail
128-
129-JOB_ID="${PICI_JOB:-local}"
130-REPO="${PICI_REPO:-pici-test}"
131-EVENT="${PICI_EVENT:-local}"
132-ZMX_SESSION_PREFIX="${ZMX_SESSION_PREFIX:-local.}"
133-
134-echo "==> Running CI for $REPO (job: $JOB_ID, event: $EVENT)"
135-
136-# 1. Parallel test steps
137-zmx run unit-tests -d bash -c 'echo "Running unit tests..."; sleep 2; echo "Tests passed!"'
138-zmx run lint -d bash -c 'echo "Running linter..."; sleep 1; echo "Lint clean!"'
139-
140-# 2. Simulated failure scenario (when TEST_FAILURE=1)
141-if [ "${TEST_FAILURE:-0}" = "1" ]; then
142-  zmx run failing-step -d bash -c 'echo "Simulating fatal compilation error..."; sleep 2; exit 42'
143-fi
144-
145-# 3. Simulated hang scenario (when TEST_HANG=1)
146-if [ "${TEST_HANG:-0}" = "1" ]; then
147-  zmx run hung-test -d bash -c 'echo "Simulating hung test process..."; sleep 3600'
148-fi
149-
150-# 4. Docker container step
151-zmx run docker-step -d docker run --rm alpine:latest sh -c "echo 'Docker step executed inside alpine container'"
152-
153-# 5. Wait for all steps
154-zmx wait "*"
155-
156-printf "\x1b[32mAll test steps succeeded!\x1b[0m\n"
157-```
158-
159-### Step 3: Configure GitHub Actions Workflows
160-
161-#### Test Workflow 1: Using `picosh/pici-action` (`.github/workflows/ci-action.yml`)
162-
163-```yaml
164-name: Pici Action Validation
165-on:
166-  push:
167-  workflow_dispatch:
168-    inputs:
169-      test_failure:
170-        description: "Simulate step failure (exit 42)"
171-        type: boolean
172-        default: false
173-
174-jobs:
175-  test-ci:
176-    runs-on: ubuntu-latest
177-    steps:
178-      - uses: actions/checkout@v4
179-
180-      - name: Run Pici CI
181-        uses: picosh/pici-action@main
182-        with:
183-          pico_ssh_key: ${{ secrets.PICO_SSH_KEY }}
184-          debug_on_fail: "true"
185-        env:
186-          TEST_FAILURE: ${{ github.event.inputs.test_failure && '1' || '0' }}
187-```
188-
189-### Step 4: Verification Matrix & Acceptance Criteria
190-
191-| Test Scenario | Trigger | Expected GHA Behavior | Acceptance Criteria |
192-| :--- | :--- | :--- | :--- |
193-| **1. Happy Path** | Push commit with `TEST_FAILURE=0` | All `zmx` sessions pass. | • Workflow exits with `0` (green).<br>• GHA Step Summary displays full table with durations.<br>• HTML report uploaded as workflow artifact. |
194-| **2. Failure & Remote Attach** | Dispatch workflow with `test_failure=true` | `failing-step` exits `42`. | • `waitAndReport` catches exit `42`.<br>• Relay bridge opens on `pipe.pico.sh`.<br>• `ssh -t pipe.pico.sh pipe <topic>` printed to logs and step summary.<br>• Connecting via terminal drops into interactive debug shell with active `zmx` sessions.<br>• Exiting debug shell ends GHA job with code `42` (red). |
195-| **3. Secret Scrubbing Audit** | During interactive debug session | Inspect environment variables inside attached shell. | • `GITHUB_TOKEN`, `ACTIONS_RUNTIME_TOKEN`, and `PICO_SSH_KEY` are absent from `env`. |
196-| **4. Docker Step Execution** | Standard run | Alpine container runs via `docker run --rm`. | • Docker mounts `$(pwd)` correctly in-place.<br>• Container logs captured in `zmx history docker-step`. |
197-| **5. Idle Timeout Cleanup** | Failure triggered without developer attaching | Wait for configured idle timeout (e.g. 15m). | • Bridge cleanly closes upon timeout.<br>• GHA runner exits with the original step failure code (does not hang indefinitely). |