Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
version: 2
updates:
# Enable version updates for GitHub Actions
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
day: "monday"
time: "09:00"
open-pull-requests-limit: 10
labels:
- "dependencies"
- "github-actions"
commit-message:
prefix: "ci"
include: "scope"
reviewers:
- "3scale-labs/maintainers"
assignees:
- "3scale-labs/maintainers"
149 changes: 149 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
name: Tests

on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main, develop ]

jobs:
test:
name: Run Test Suite
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install dependencies
run: |
sudo apt-get install -y expect apparmor-profiles

- name: Get bubblewrap latest commit
id: bwrap-commit
run: |
COMMIT=$(git ls-remote https://github.com/containers/bubblewrap.git HEAD | cut -f1)
echo "commit=$COMMIT" >> $GITHUB_OUTPUT
echo "Bubblewrap latest commit: $COMMIT"

- name: Restore bubblewrap from cache
id: cache-bwrap
uses: actions/cache/restore@v4
with:
path: /tmp/bwrap-bin
key: bwrap-${{ runner.os }}-${{ steps.bwrap-commit.outputs.commit }}

- name: Install build dependencies
if: steps.cache-bwrap.outputs.cache-hit != 'true'
run: |
sudo apt-get install -y \
meson \
ninja-build \
libcap-dev \
gcc \
pkg-config

- name: Build latest bubblewrap
if: steps.cache-bwrap.outputs.cache-hit != 'true'
run: |
# Clone and build latest bubblewrap
cd /tmp
git clone https://github.com/containers/bubblewrap.git
cd bubblewrap
meson setup builddir --prefix=/usr
meson compile -C builddir

# Prepare binary for caching
mkdir -p /tmp/bwrap-bin
cp builddir/bwrap /tmp/bwrap-bin/

- name: Save bubblewrap to cache
if: steps.cache-bwrap.outputs.cache-hit != 'true'
uses: actions/cache/save@v4
with:
path: /tmp/bwrap-bin
key: bwrap-${{ runner.os }}-${{ steps.bwrap-commit.outputs.commit }}

- name: Install bubblewrap
run: |
sudo cp /tmp/bwrap-bin/bwrap /usr/bin/bwrap
sudo chmod +x /usr/bin/bwrap

# Verify version (should be 0.11.0 or later)
bwrap --version

- name: Setup user namespaces for bubblewrap
run: |
# Configure subuid and subgid for unprivileged user namespaces
USERNAME=$(whoami)

# Add subuid mapping (100000 UIDs starting from 100000)
# echo "$USERNAME:100000:65536" | sudo tee -a /etc/subuid

# Add subgid mapping (100000 GIDs starting from 100000)
# echo "$USERNAME:100000:65536" | sudo tee -a /etc/subgid

# Enable unprivileged user namespaces (should already be enabled on Ubuntu)
# echo "kernel.unprivileged_userns_clone=1" | sudo tee -a /etc/sysctl.conf
# sudo sysctl -p

# Setup AppArmor profile for bubblewrap user namespaces
sudo ln -s /usr/share/apparmor/extra-profiles/bwrap-userns-restrict /etc/apparmor.d/bwrap
sudo apparmor_parser /etc/apparmor.d/bwrap

# Verify setup
cat /etc/subuid
cat /etc/subgid

- name: Setup test environment
run: |
# Create isolated home for agent
mkdir -p ~/aihome

# Initialize git config (required for some tests)
git config --global user.email "ci@github.actions"
git config --global user.name "GitHub Actions"

- name: Run merge-overlay tests
run: |
cd ${{ github.workspace }}
./tests/test-merge-overlay.expect

- name: Setup for agent-dev tests
run: |
# Ensure we're in a git repo with proper setup
cd ${{ github.workspace }}
git status || git init

# Create .claude directory structure if needed
mkdir -p .claude
touch .claude/settings.local.json || true

- name: Run agent-dev integration tests
run: |
cd ${{ github.workspace }}
export PATH="$PWD:$PATH"
./tests/test-agent-dev.expect

- name: Test summary
if: always()
run: |
echo "Test execution completed"
echo "Check logs above for detailed results"

lint:
name: Shell Script Linting
runs-on: ubuntu-latest

steps:
- name: Checkout code
uses: actions/checkout@v4

- name: Install ShellCheck
run: sudo apt-get install -y shellcheck

- name: Lint shell scripts
run: |
echo "Linting bash scripts..."
shellcheck agent-dev merge-overlay || true
echo "Note: Some warnings may be acceptable for this use case"
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ build-iPhoneSimulator/

# unless supporting rvm < 1.11.0 or doing something fancy, ignore this:
.rvmrc
.tool-versions

# Used by RuboCop. Remote config files pulled in from inherit_from directive.
# .rubocop-https?--*
22 changes: 21 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Agent Dev Environment

[![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)

# Goal
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.

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

# Usage

* requires Bubblewrap 0.11+ for the overlayfs support
* add the script(s) to your PATH
* `mkdir -p ~/aihome`
* agent-dev bash
Expand All @@ -30,4 +35,19 @@ Now you can just call the script from within a git working tree and feel the fal
* 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
* note: *this means you need to install all necessary libraries from the host*

TODO: what is possibly unsafe - e.g. gitignored files, careful when merging (if I implement this)
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.

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.

## Running Tests

```bash
# Install expect if not already installed
sudo apt install expect # Debian/Ubuntu
# or
sudo dnf install expect # Fedora/RHEL

# Run all tests
./tests/test-merge-overlay.expect # Test the merge workflow
./tests/test-agent-dev.expect # Test isolation and sandbox behavior
```
Loading