Skip to content

Commit a5abbb4

Browse files
authored
Merge pull request #1 from 3scale-labs/test
use overlayfs and add tests
2 parents 905047f + 94f96af commit a5abbb4

8 files changed

Lines changed: 1929 additions & 1 deletion

File tree

.github/dependabot.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
version: 2
2+
updates:
3+
# Enable version updates for GitHub Actions
4+
- package-ecosystem: "github-actions"
5+
directory: "/"
6+
schedule:
7+
interval: "weekly"
8+
day: "monday"
9+
time: "09:00"
10+
open-pull-requests-limit: 10
11+
labels:
12+
- "dependencies"
13+
- "github-actions"
14+
commit-message:
15+
prefix: "ci"
16+
include: "scope"
17+
reviewers:
18+
- "3scale-labs/maintainers"
19+
assignees:
20+
- "3scale-labs/maintainers"

.github/workflows/tests.yml

Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
jobs:
10+
test:
11+
name: Run Test Suite
12+
runs-on: ubuntu-latest
13+
14+
steps:
15+
- name: Checkout code
16+
uses: actions/checkout@v4
17+
18+
- name: Install dependencies
19+
run: |
20+
sudo apt-get install -y expect apparmor-profiles
21+
22+
- name: Get bubblewrap latest commit
23+
id: bwrap-commit
24+
run: |
25+
COMMIT=$(git ls-remote https://github.com/containers/bubblewrap.git HEAD | cut -f1)
26+
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
27+
echo "Bubblewrap latest commit: $COMMIT"
28+
29+
- name: Restore bubblewrap from cache
30+
id: cache-bwrap
31+
uses: actions/cache/restore@v4
32+
with:
33+
path: /tmp/bwrap-bin
34+
key: bwrap-${{ runner.os }}-${{ steps.bwrap-commit.outputs.commit }}
35+
36+
- name: Install build dependencies
37+
if: steps.cache-bwrap.outputs.cache-hit != 'true'
38+
run: |
39+
sudo apt-get install -y \
40+
meson \
41+
ninja-build \
42+
libcap-dev \
43+
gcc \
44+
pkg-config
45+
46+
- name: Build latest bubblewrap
47+
if: steps.cache-bwrap.outputs.cache-hit != 'true'
48+
run: |
49+
# Clone and build latest bubblewrap
50+
cd /tmp
51+
git clone https://github.com/containers/bubblewrap.git
52+
cd bubblewrap
53+
meson setup builddir --prefix=/usr
54+
meson compile -C builddir
55+
56+
# Prepare binary for caching
57+
mkdir -p /tmp/bwrap-bin
58+
cp builddir/bwrap /tmp/bwrap-bin/
59+
60+
- name: Save bubblewrap to cache
61+
if: steps.cache-bwrap.outputs.cache-hit != 'true'
62+
uses: actions/cache/save@v4
63+
with:
64+
path: /tmp/bwrap-bin
65+
key: bwrap-${{ runner.os }}-${{ steps.bwrap-commit.outputs.commit }}
66+
67+
- name: Install bubblewrap
68+
run: |
69+
sudo cp /tmp/bwrap-bin/bwrap /usr/bin/bwrap
70+
sudo chmod +x /usr/bin/bwrap
71+
72+
# Verify version (should be 0.11.0 or later)
73+
bwrap --version
74+
75+
- name: Setup user namespaces for bubblewrap
76+
run: |
77+
# Configure subuid and subgid for unprivileged user namespaces
78+
USERNAME=$(whoami)
79+
80+
# Add subuid mapping (100000 UIDs starting from 100000)
81+
# echo "$USERNAME:100000:65536" | sudo tee -a /etc/subuid
82+
83+
# Add subgid mapping (100000 GIDs starting from 100000)
84+
# echo "$USERNAME:100000:65536" | sudo tee -a /etc/subgid
85+
86+
# Enable unprivileged user namespaces (should already be enabled on Ubuntu)
87+
# echo "kernel.unprivileged_userns_clone=1" | sudo tee -a /etc/sysctl.conf
88+
# sudo sysctl -p
89+
90+
# Setup AppArmor profile for bubblewrap user namespaces
91+
sudo ln -s /usr/share/apparmor/extra-profiles/bwrap-userns-restrict /etc/apparmor.d/bwrap
92+
sudo apparmor_parser /etc/apparmor.d/bwrap
93+
94+
# Verify setup
95+
cat /etc/subuid
96+
cat /etc/subgid
97+
98+
- name: Setup test environment
99+
run: |
100+
# Create isolated home for agent
101+
mkdir -p ~/aihome
102+
103+
# Initialize git config (required for some tests)
104+
git config --global user.email "ci@github.actions"
105+
git config --global user.name "GitHub Actions"
106+
107+
- name: Run merge-overlay tests
108+
run: |
109+
cd ${{ github.workspace }}
110+
./tests/test-merge-overlay.expect
111+
112+
- name: Setup for agent-dev tests
113+
run: |
114+
# Ensure we're in a git repo with proper setup
115+
cd ${{ github.workspace }}
116+
git status || git init
117+
118+
# Create .claude directory structure if needed
119+
mkdir -p .claude
120+
touch .claude/settings.local.json || true
121+
122+
- name: Run agent-dev integration tests
123+
run: |
124+
cd ${{ github.workspace }}
125+
export PATH="$PWD:$PATH"
126+
./tests/test-agent-dev.expect
127+
128+
- name: Test summary
129+
if: always()
130+
run: |
131+
echo "Test execution completed"
132+
echo "Check logs above for detailed results"
133+
134+
lint:
135+
name: Shell Script Linting
136+
runs-on: ubuntu-latest
137+
138+
steps:
139+
- name: Checkout code
140+
uses: actions/checkout@v4
141+
142+
- name: Install ShellCheck
143+
run: sudo apt-get install -y shellcheck
144+
145+
- name: Lint shell scripts
146+
run: |
147+
echo "Linting bash scripts..."
148+
shellcheck agent-dev merge-overlay || true
149+
echo "Note: Some warnings may be acceptable for this use case"

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ build-iPhoneSimulator/
5151

5252
# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
5353
.rvmrc
54+
.tool-versions
5455

5556
# Used by RuboCop. Remote config files pulled in from inherit_from directive.
5657
# .rubocop-https?--*

README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Agent Dev Environment
2+
3+
[![Tests](https://github.com/3scale-labs/agent-dev-env/actions/workflows/tests.yml/badge.svg)](https://github.com/3scale-labs/agent-dev-env/actions/workflows/tests.yml)
4+
15
# Goal
26
The goal is to easily start your coding agent within a secure sandbox environment that closely resembles your actual development environment and safely merge the results back.
37

@@ -13,6 +17,7 @@ There are existing attempts to sandbox agent processes, the most serious I find
1317

1418
# Usage
1519

20+
* requires Bubblewrap 0.11+ for the overlayfs support
1621
* add the script(s) to your PATH
1722
* `mkdir -p ~/aihome`
1823
* agent-dev bash
@@ -30,4 +35,19 @@ Now you can just call the script from within a git working tree and feel the fal
3035
* also `asdf`, `npm` and other directories from user's real home are monuted read-only inside the sandbox home so that you have access to these installations without ability to install, remove and modify them
3136
* note: *this means you need to install all necessary libraries from the host*
3237

33-
TODO: what is possibly unsafe - e.g. gitignored files, careful when merging (if I implement this)
38+
The biggest concern I see is merging the changes after exiting the agent. One has to be careful with merging files that are a potential treat outside the sanbox.
39+
40+
A lesser but potentially important in some environments is the cocern that a malware may set roots into the sandbox and use local resources or network access for malicious purposes. On signs of weird behavior, I'd suggest investigating and wiping the agent home dir to start over.
41+
42+
## Running Tests
43+
44+
```bash
45+
# Install expect if not already installed
46+
sudo apt install expect # Debian/Ubuntu
47+
# or
48+
sudo dnf install expect # Fedora/RHEL
49+
50+
# Run all tests
51+
./tests/test-merge-overlay.expect # Test the merge workflow
52+
./tests/test-agent-dev.expect # Test isolation and sandbox behavior
53+
```

0 commit comments

Comments
 (0)