/ .github / workflows / real-e2e.yml
real-e2e.yml
  1  name: Real E2E Tests
  2  
  3  permissions:
  4    contents: read
  5  
  6  on:
  7    pull_request:
  8      branches: [ main ]
  9      paths:
 10        - 'server/opensandbox_server/**'
 11        - 'components/execd/**'
 12        - 'components/egress/**'
 13        - 'sdks/**'
 14        - 'tests/**'
 15    push:
 16      branches: [ main ]
 17  
 18  concurrency:
 19    group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
 20    cancel-in-progress: true
 21  
 22  jobs:
 23    python-e2e:
 24      name: Python E2E (docker bridge)
 25      runs-on: self-hosted
 26      env:
 27        UV_BIN: /home/admin/.local/bin
 28      steps:
 29        - name: Checkout code
 30          uses: actions/checkout@v6
 31  
 32        - name: Set up uv PATH and verify
 33          run: |
 34            echo "${UV_BIN}" >> "$GITHUB_PATH"
 35            export PATH="${UV_BIN}:${PATH}"
 36            uv --version
 37            uv run python --version
 38  
 39        - name: Clean up previous E2E resources
 40          run: |
 41            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
 42            # Remove root-owned files from previous sandbox runs by mounting parent dir
 43            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
 44            docker image prune -f || true
 45  
 46        - name: Build local egress image
 47          run: docker build -t opensandbox/egress:local -f components/egress/Dockerfile .
 48  
 49        - name: Run tests
 50          run: |
 51            set -e
 52  
 53            # Create config file
 54            cat <<EOF > ~/.sandbox.toml
 55            [server]
 56            host = "127.0.0.1"
 57            port = 8080
 58            api_key = ""
 59            [log]
 60            level = "INFO"
 61            [runtime]
 62            type = "docker"
 63            execd_image = "opensandbox/execd:local"
 64            [egress]
 65            image = "opensandbox/egress:local"
 66            mode = "dns"
 67            [docker]
 68            network_mode = "bridge"
 69            [storage]
 70            allowed_host_paths = ["/tmp/opensandbox-e2e"]
 71            [renew_intent]
 72            enabled = true
 73            min_interval_seconds = 60
 74            EOF
 75  
 76            ./scripts/python-e2e.sh
 77  
 78        - name: Eval server logs
 79          if: ${{ always() }}
 80          run: cat server/server.log
 81  
 82        - name: Upload execd logs
 83          if: always()
 84          uses: actions/upload-artifact@v7
 85          with:
 86            name: execd-log-for-python-e2e
 87            path: /tmp/opensandbox-e2e/logs/
 88            retention-days: 5
 89  
 90        - name: Clean up after E2E
 91          if: always()
 92          run: |
 93            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
 94            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
 95            pkill -f "python -m opensandbox_server.main" || true
 96  
 97    java-e2e:
 98      name: Java E2E (docker bridge)
 99      runs-on: self-hosted
100      env:
101        UV_BIN: /home/admin/.local/bin
102      steps:
103        - name: Checkout code
104          uses: actions/checkout@v6
105  
106        - name: Set up uv PATH and verify
107          run: |
108            echo "${UV_BIN}" >> "$GITHUB_PATH"
109            export PATH="${UV_BIN}:${PATH}"
110            uv --version
111            uv run python --version
112  
113        - name: Set up JDK 8
114          uses: actions/setup-java@v5
115          with:
116            distribution: temurin
117            java-version: "8"
118  
119        - name: Set up JDK 17
120          uses: actions/setup-java@v5
121          with:
122            distribution: temurin
123            java-version: "17"
124  
125        - name: Clean up previous E2E resources
126          run: |
127            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
128            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
129            docker image prune -f || true
130  
131        - name: Build local egress image
132          run: docker build -t opensandbox/egress:local -f components/egress/Dockerfile .
133  
134        - name: Run tests
135          env:
136            GRADLE_USER_HOME: ${{ github.workspace }}/.gradle-user-home
137            OPENSANDBOX_TEST_SECURE_ACCESS_VERIFIABLE: "false"
138          run: |
139            set -e
140            export GRADLE_OPTS="-Dorg.gradle.java.installations.auto-detect=true -Dorg.gradle.java.installations.auto-download=false -Dorg.gradle.java.installations.paths=${JAVA_HOME_8_X64},${JAVA_HOME_17_X64}"
141  
142            # Create config file
143            cat <<EOF > ~/.sandbox.toml
144            [server]
145            host = "127.0.0.1"
146            port = 8080
147            api_key = ""
148            [log]
149            level = "INFO"
150            [runtime]
151            type = "docker"
152            execd_image = "opensandbox/execd:local"
153            [egress]
154            image = "opensandbox/egress:local"
155            mode = "dns+nft"
156            [docker]
157            network_mode = "bridge"
158            [storage]
159            allowed_host_paths = ["/tmp/opensandbox-e2e"]
160            EOF
161  
162            bash ./scripts/java-e2e.sh
163  
164        - name: Eval server logs
165          if: ${{ always() }}
166          run: cat server/server.log
167  
168        - name: Upload Test Report
169          if: always()
170          uses: actions/upload-artifact@v7
171          with:
172            name: java-test-report
173            path: tests/java/build/reports/tests/test/
174            retention-days: 5
175  
176        - name: Upload execd logs
177          if: always()
178          uses: actions/upload-artifact@v7
179          with:
180            name: execd-log-for-java-e2e
181            path: /tmp/opensandbox-e2e/logs/
182            retention-days: 5
183  
184        - name: Clean up after E2E
185          if: always()
186          run: |
187            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
188            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
189            pkill -f "python -m opensandbox_server.main" || true
190  
191    javascript-e2e:
192      name: JavaScript E2E (docker bridge)
193      runs-on: self-hosted
194      env:
195        UV_BIN: /home/admin/.local/bin
196        NODE_VERSION: "20.19.0"
197      steps:
198        - name: Checkout code
199          uses: actions/checkout@v6
200  
201        - name: Set up uv PATH and verify
202          run: |
203            echo "${UV_BIN}" >> "$GITHUB_PATH"
204            export PATH="${UV_BIN}:${PATH}"
205            uv --version
206            uv run python --version
207  
208        - name: Set up Node.js
209          run: |
210            NODE_DIR="/home/admin/.local/node-v${NODE_VERSION}-linux-x64"
211            if [ -x "${NODE_DIR}/bin/node" ]; then
212              echo "Node.js ${NODE_VERSION} already cached"
213            else
214              echo "Downloading Node.js ${NODE_VERSION}..."
215              mkdir -p /home/admin/.local
216              curl -fsSL "https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.xz" \
217                | tar -xJ -C /home/admin/.local/
218            fi
219            echo "${NODE_DIR}/bin" >> "$GITHUB_PATH"
220            export PATH="${NODE_DIR}/bin:${PATH}"
221            node --version
222            npm --version
223  
224        - name: Clean up previous E2E resources
225          run: |
226            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
227            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
228            docker image prune -f || true
229  
230        - name: Build local egress image
231          run: docker build -t opensandbox/egress:local -f components/egress/Dockerfile .
232  
233        - name: Run tests
234          run: |
235            set -e
236  
237            # Create config file (match other E2E jobs)
238            cat <<EOF > ~/.sandbox.toml
239            [server]
240            host = "127.0.0.1"
241            port = 8080
242            api_key = ""
243            [log]
244            level = "INFO"
245            [runtime]
246            type = "docker"
247            execd_image = "opensandbox/execd:local"
248            [egress]
249            image = "opensandbox/egress:local"
250            [docker]
251            network_mode = "bridge"
252            [storage]
253            allowed_host_paths = ["/tmp/opensandbox-e2e"]
254            EOF
255  
256            bash ./scripts/javascript-e2e.sh
257  
258        - name: Eval server logs
259          if: ${{ always() }}
260          run: cat server/server.log
261  
262        - name: Upload Test Report
263          if: always()
264          uses: actions/upload-artifact@v7
265          with:
266            name: javascript-test-report
267            path: tests/javascript/build/test-results/junit.xml
268            retention-days: 5
269  
270        - name: Upload execd logs
271          if: always()
272          uses: actions/upload-artifact@v7
273          with:
274            name: execd-log-for-js-e2e
275            path: /tmp/opensandbox-e2e/logs/
276            retention-days: 5
277  
278        - name: Clean up after E2E
279          if: always()
280          run: |
281            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
282            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
283            pkill -f "python -m opensandbox_server.main" || true
284  
285    csharp-e2e:
286      name: C# E2E (docker bridge)
287      runs-on: self-hosted
288      env:
289        UV_BIN: /home/admin/.local/bin
290      steps:
291        - name: Checkout code
292          uses: actions/checkout@v6
293  
294        - name: Set up uv PATH and verify
295          run: |
296            echo "${UV_BIN}" >> "$GITHUB_PATH"
297            export PATH="${UV_BIN}:${PATH}"
298            uv --version
299            uv run python --version
300  
301        - name: Set up .NET SDK
302          uses: actions/setup-dotnet@v5
303          env:
304            DOTNET_INSTALL_DIR: /home/admin/.local/dotnet
305          with:
306            dotnet-version: "10.0.x"
307  
308        - name: Clean up previous E2E resources
309          run: |
310            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
311            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
312            docker image prune -f || true
313  
314        - name: Build local egress image
315          run: docker build -t opensandbox/egress:local -f components/egress/Dockerfile .
316  
317        - name: Run tests
318          run: |
319            set -e
320  
321            cat <<EOF > ~/.sandbox.toml
322            [server]
323            host = "127.0.0.1"
324            port = 8080
325            api_key = ""
326            [log]
327            level = "INFO"
328            [runtime]
329            type = "docker"
330            execd_image = "opensandbox/execd:local"
331            [egress]
332            image = "opensandbox/egress:local"
333            [docker]
334            network_mode = "bridge"
335            [storage]
336            allowed_host_paths = ["/tmp/opensandbox-e2e"]
337            EOF
338  
339            bash ./scripts/csharp-e2e.sh
340  
341        - name: Eval server logs
342          if: ${{ always() }}
343          run: cat server/server.log
344  
345        - name: Upload Test Report
346          if: always()
347          uses: actions/upload-artifact@v7
348          with:
349            name: csharp-test-report
350            path: tests/csharp/build/test-results/
351            retention-days: 5
352  
353        - name: Upload execd logs
354          if: always()
355          uses: actions/upload-artifact@v7
356          with:
357            name: execd-log-for-csharp-e2e
358            path: /tmp/opensandbox-e2e/logs/
359            retention-days: 5
360  
361        - name: Clean up after E2E
362          if: always()
363          run: |
364            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
365            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
366            pkill -f "python -m opensandbox_server.main" || true
367  
368    go-e2e:
369      name: Go E2E (docker bridge)
370      runs-on: self-hosted
371      env:
372        UV_BIN: /home/admin/.local/bin
373        HOME: /home/admin/actions-runner
374        GOCACHE: /home/admin/actions-runner/_temp/go-build
375        GOMODCACHE: /home/admin/actions-runner/_temp/go-mod-cache
376      steps:
377        - name: Checkout code
378          uses: actions/checkout@v6
379  
380        - name: Set up uv PATH and verify
381          run: |
382            echo "${UV_BIN}" >> "$GITHUB_PATH"
383            export PATH="${UV_BIN}:${PATH}"
384            uv --version
385            uv run python --version
386  
387        - name: Set up Go
388          uses: actions/setup-go@v6
389          with:
390            go-version: "1.24"
391            cache: false
392  
393        - name: Clean up previous E2E resources
394          run: |
395            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
396            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
397            docker image prune -f || true
398  
399        - name: Build local egress image
400          run: docker build -t opensandbox/egress:local -f components/egress/Dockerfile .
401  
402        - name: Run tests
403          run: |
404            set -e
405  
406            cat <<EOF > ~/.sandbox.toml
407            [server]
408            host = "127.0.0.1"
409            port = 8080
410            api_key = ""
411            [log]
412            level = "INFO"
413            [runtime]
414            type = "docker"
415            execd_image = "opensandbox/execd:local"
416            [egress]
417            image = "opensandbox/egress:local"
418            [docker]
419            network_mode = "bridge"
420            [storage]
421            allowed_host_paths = ["/tmp/opensandbox-e2e"]
422            EOF
423  
424            bash ./scripts/go-e2e.sh
425  
426        - name: Eval server logs
427          if: ${{ always() }}
428          run: cat server/server.log
429  
430        - name: Upload Test Report
431          if: always()
432          uses: actions/upload-artifact@v7
433          with:
434            name: go-test-report
435            path: tests/go/reports/
436            retention-days: 5
437  
438        - name: Upload execd logs
439          if: always()
440          uses: actions/upload-artifact@v7
441          with:
442            name: execd-log-for-go-e2e
443            path: /tmp/opensandbox-e2e/logs/
444            retention-days: 5
445  
446        - name: Clean up after E2E
447          if: always()
448          run: |
449            docker ps -aq --filter "label=opensandbox" | xargs -r docker rm -f || true
450            docker run --rm -v /tmp:/host_tmp alpine rm -rf /host_tmp/opensandbox-e2e || true
451            pkill -f "python -m opensandbox_server.main" || true