Files
openchamber/.github/workflows/opencode.yml
T

232 lines
9.8 KiB
YAML

name: OpenChamber for Actions
on:
workflow_dispatch:
inputs:
tunnel_provider:
description: 'Select Tunnel Provider'
required: true
default: 'cloudflare'
type: choice
options:
- ngrok
- cloudflare
timeout_minutes:
description: 'Auto-shutdown after (minutes)'
required: true
default: '300'
type: string
jobs:
serve:
runs-on: ubuntu-latest
env:
OPENCODE_SERVER_PASSWORD: ${{ secrets.OPENCODE_SERVER_PASSWORD }}
steps:
- name: Checkout repo
uses: actions/checkout@v4
# ============================================================
# PERSISTENCE: Restore previous session (OAuth, chats, config)
# ============================================================
- name: Restore Session Data (Artifact)
if: ${{ env.OPENCODE_SERVER_PASSWORD != '' }}
uses: dawidd6/action-download-artifact@v6
continue-on-error: true
with:
name: opencode-session
path: /tmp/opencode-restore
workflow: opencode.yml
workflow_conclusion: success
if_no_artifact_found: ignore
repo: ${{ github.repository }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Apply Restored Session Data
if: ${{ env.OPENCODE_SERVER_PASSWORD != '' }}
env:
OPENCODE_SERVER_PASSWORD: ${{ env.OPENCODE_SERVER_PASSWORD }}
run: |
chmod +x scripts/persistence-restore.sh
RESTORE_DIR=/tmp/opencode-restore ./scripts/persistence-restore.sh
# ============================================================
# CACHE: Speed up npm installations
# ============================================================
- name: Cache npm modules
uses: actions/cache@v4
with:
path: |
~/.npm
key: npm-cache-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-cache-${{ runner.os }}-
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: "20"
- name: Install Tools
run: |
npm install -g opencode-ai @openchamber/web
sudo apt update && sudo apt install jq lsof coreutils openssl -y
# Install ttyd for OpenCode TTY exposure
wget -q -O ttyd https://github.com/tsl0922/ttyd/releases/download/1.7.3/ttyd.x86_64
chmod +x ttyd
sudo mv ttyd /usr/local/bin/
# ============================================================
# CONFIGURATION: Setup OpenCode config (respects artifacts)
# ============================================================
- name: Configure OpenCode
run: |
chmod +x scripts/opencode-config.sh
RESTORE_DIR=/tmp/opencode-restore ./scripts/opencode-config.sh
# ============================================================
# STARTUP: Launch services and tunnel
# ============================================================
- name: Start Services
env:
OPENCODE_SERVER_PASSWORD: ${{ env.OPENCODE_SERVER_PASSWORD }}
run: |
# Setup Password Protection
TTYD_ARGS=""
if [[ -n "$OPENCODE_SERVER_PASSWORD" ]]; then
echo "Password protection enabled."
# Export for subsequent steps (Monitor script) and other services
echo "OPENCHAMBER_UI_PASSWORD=$OPENCODE_SERVER_PASSWORD" >> $GITHUB_ENV
echo "OPENCODE_UI_PASSWORD=$OPENCODE_SERVER_PASSWORD" >> $GITHUB_ENV
# Use for current step
export OPENCHAMBER_UI_PASSWORD="$OPENCODE_SERVER_PASSWORD"
export OPENCODE_UI_PASSWORD="$OPENCODE_SERVER_PASSWORD"
TTYD_ARGS="-c user:$OPENCODE_SERVER_PASSWORD"
else
echo "Password protection disabled (OPENCODE_SERVER_PASSWORD not set)."
fi
# Start OpenCode TTY (via ttyd)
echo "Starting OpenCode TTY..."
nohup stdbuf -oL ttyd $TTYD_ARGS -p 7681 opencode > opencode_tty.log 2>&1 &
# Start OpenChamber
echo "Starting OpenChamber..."
if [[ -n "$OPENCODE_SERVER_PASSWORD" ]]; then
nohup stdbuf -oL openchamber --port 9090 --ui-password "$OPENCODE_SERVER_PASSWORD" > openchamber.log 2>&1 &
else
nohup stdbuf -oL openchamber --port 9090 > openchamber.log 2>&1 &
fi
# Start OpenCode Web
echo "Starting OpenCode Web..."
if [[ -n "$OPENCODE_SERVER_PASSWORD" ]]; then
OPENCODE_SERVER_PASSWORD="$OPENCODE_SERVER_PASSWORD" nohup stdbuf -oL opencode web --port 8080 > opencode_web.log 2>&1 &
else
nohup stdbuf -oL opencode web --port 8080 > opencode_web.log 2>&1 &
fi
# Wait for services to initialize
sleep 20
echo "Services started. Checking status..."
lsof -i :7681 || echo "Warning: OpenCode TTY may not be running"
lsof -i :9090 || echo "Warning: OpenChamber may not be running"
lsof -i :8080 || echo "Warning: OpenCode Web may not be running"
- name: Setup Tunnel
run: |
if [[ "${{ github.event.inputs.tunnel_provider }}" == "ngrok" ]]; then
echo "Setting up ngrok tunnel..."
curl -s https://ngrok-agent.s3.amazonaws.com/ngrok.asc | sudo tee /etc/apt/trusted.gpg.d/ngrok.asc >/dev/null
echo "deb https://ngrok-agent.s3.amazonaws.com buster main" | sudo tee /etc/apt/sources.list.d/ngrok.list
sudo apt update && sudo apt install ngrok -y
ngrok config add-authtoken "${{ secrets.NGROK_AUTH_TOKEN }}"
# Note: Multiple ngrok tunnels on free plan might be limited or require config file
# Attempting to start tunnels blindly
nohup ngrok http 127.0.0.1:9090 --log=stdout > tunnel_chamber.log 2>&1 &
nohup ngrok http 127.0.0.1:8080 --log=stdout > tunnel_web.log 2>&1 &
nohup ngrok http 127.0.0.1:7681 --log=stdout > tunnel_tty.log 2>&1 &
sleep 10
# Extract URLs
URL_CHAMBER=$(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[] | select(.config.addr | contains("9090")) | .public_url' || true)
URL_WEB=$(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[] | select(.config.addr | contains("8080")) | .public_url' || true)
URL_TTY=$(curl -s http://localhost:4040/api/tunnels | jq -r '.tunnels[] | select(.config.addr | contains("7681")) | .public_url' || true)
echo "URL_CHAMBER=$URL_CHAMBER" >> $GITHUB_ENV
echo "URL_WEB=$URL_WEB" >> $GITHUB_ENV
echo "URL_TTY=$URL_TTY" >> $GITHUB_ENV
else
echo "Setting up Cloudflare tunnel..."
wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb
sudo dpkg -i cloudflared-linux-amd64.deb
# Start 3 separate tunnels
nohup cloudflared tunnel --url http://127.0.0.1:7681 > tunnel_tty.log 2>&1 &
nohup cloudflared tunnel --url http://127.0.0.1:9090 > tunnel_chamber.log 2>&1 &
nohup cloudflared tunnel --url http://127.0.0.1:8080 > tunnel_web.log 2>&1 &
echo "Waiting for Cloudflare Tunnel URLs..."
# Loop to wait for URLs
for i in {1..30}; do
URL_TTY=$(grep -o 'https://[-a-z0-9.]*trycloudflare.com' tunnel_tty.log 2>/dev/null | tail -n 1 || true)
URL_CHAMBER=$(grep -o 'https://[-a-z0-9.]*trycloudflare.com' tunnel_chamber.log 2>/dev/null | tail -n 1 || true)
URL_WEB=$(grep -o 'https://[-a-z0-9.]*trycloudflare.com' tunnel_web.log 2>/dev/null | tail -n 1 || true)
if [[ -n "$URL_TTY" && -n "$URL_CHAMBER" && -n "$URL_WEB" ]]; then
echo "All tunnels established!"
break
fi
echo "Waiting for tunnels... ($i/30)"
sleep 2
done
if [[ -z "$URL_TTY" ]]; then echo "Warning: TTY Tunnel URL missing"; fi
if [[ -z "$URL_CHAMBER" ]]; then echo "Warning: Chamber Tunnel URL missing"; fi
if [[ -z "$URL_WEB" ]]; then echo "Warning: Web Tunnel URL missing"; fi
echo "URL_TTY=$URL_TTY" >> $GITHUB_ENV
echo "URL_CHAMBER=$URL_CHAMBER" >> $GITHUB_ENV
echo "URL_WEB=$URL_WEB" >> $GITHUB_ENV
fi
# ============================================================
# MONITOR: Self-healing loop with status updates
# ============================================================
- name: Monitor & Self-Heal
env:
OPENCHAMBER_UI_PASSWORD: ${{ env.OPENCODE_SERVER_PASSWORD }}
run: |
chmod +x scripts/monitor.sh
# Pass all 3 URLs to monitor script
./scripts/monitor.sh "${{ github.event.inputs.tunnel_provider }}" "${{ github.event.inputs.timeout_minutes }}" "${{ env.URL_TTY }}" "${{ env.URL_CHAMBER }}" "${{ env.URL_WEB }}"
# ============================================================
# PERSISTENCE: Save all session data (always runs)
# ============================================================
- name: Prepare Session Data for Save
if: ${{ always() && env.OPENCODE_SERVER_PASSWORD != '' }}
env:
OPENCODE_SERVER_PASSWORD: ${{ env.OPENCODE_SERVER_PASSWORD }}
run: |
chmod +x scripts/persistence-save.sh
SAVE_DIR=/tmp/opencode-save ./scripts/persistence-save.sh
- name: Upload Session Data (Artifact)
if: ${{ always() && env.OPENCODE_SERVER_PASSWORD != '' }}
uses: actions/upload-artifact@v4
with:
name: opencode-session
path: /tmp/opencode-save/
retention-days: 90
overwrite: true
if-no-files-found: warn