forked from openchamber/openchamber
-
Notifications
You must be signed in to change notification settings - Fork 0
231 lines (199 loc) · 9.77 KB
/
opencode.yml
File metadata and controls
231 lines (199 loc) · 9.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
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