-
Couldn't load subscription status.
- Fork 45
Add dev container #179
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Add dev container #179
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,52 @@ | ||
| FROM mcr.microsoft.com/devcontainers/base:ubuntu | ||
|
|
||
| # Set environment variables | ||
| ENV DEBIAN_FRONTEND=noninteractive | ||
| ENV JAVA_HOME=/usr/lib/jvm/java-21-openjdk-amd64 | ||
| ENV GHIDRA_INSTALL_DIR=/opt/ghidra | ||
| ENV GRADLE_VERSION=9.0 | ||
| ENV PATH=$PATH:/opt/ghidra:/opt/gradle/bin | ||
|
|
||
| # Install basic dependencies including build tools for Ghidra | ||
| RUN apt-get update && apt-get install -y \ | ||
| curl \ | ||
| wget \ | ||
| unzip \ | ||
| git \ | ||
| build-essential \ | ||
| python3 \ | ||
| python3-pip \ | ||
| python3-venv \ | ||
| openjdk-21-jdk \ | ||
| bison \ | ||
| flex \ | ||
| && rm -rf /var/lib/apt/lists/* | ||
|
|
||
| # Install Gradle | ||
| RUN wget -q https://services.gradle.org/distributions/gradle-${GRADLE_VERSION}-bin.zip -O /tmp/gradle.zip && \ | ||
| unzip -q /tmp/gradle.zip -d /opt && \ | ||
| mv /opt/gradle-${GRADLE_VERSION} /opt/gradle && \ | ||
| rm /tmp/gradle.zip | ||
|
|
||
| # Create ghidra directories | ||
| RUN mkdir -p /opt/ghidra /opt/ghidra-src | ||
|
|
||
| # Create a Python virtual environment and install MCP SDK | ||
| RUN python3 -m venv /opt/venv && \ | ||
| . /opt/venv/bin/activate && \ | ||
| pip install --upgrade pip setuptools wheel && \ | ||
| pip install mcp pytest requests | ||
|
|
||
| # Set up vscode user permissions | ||
| RUN chown -R vscode:vscode /opt/ghidra /opt/ghidra-src /opt/gradle /opt/venv | ||
|
|
||
| # Switch to vscode user | ||
| USER vscode | ||
|
|
||
| # Add virtual environment to PATH for vscode user | ||
| ENV PATH="/opt/venv/bin:${PATH}" | ||
|
|
||
| # Verify installations | ||
| RUN java -version && gradle --version && python3 --version | ||
|
|
||
| WORKDIR /workspaces/reverse-engineering-assistant |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,51 @@ | ||
| { | ||
| "name": "ReVa Development Environment", | ||
| "dockerFile": "Dockerfile", | ||
| "runArgs": [ | ||
| "--init" | ||
| ], | ||
| "mounts": [ | ||
| "source=/var/run/docker.sock,target=/var/run/docker.sock,type=bind" | ||
| ], | ||
| "forwardPorts": [8080], | ||
| "portsAttributes": { | ||
| "8080": { | ||
| "label": "ReVa MCP Server", | ||
| "onAutoForward": "notify" | ||
| } | ||
| }, | ||
| "customizations": { | ||
| "vscode": { | ||
| "extensions": [ | ||
| "vscjava.vscode-java-pack", | ||
| "redhat.java", | ||
| "vscjava.vscode-gradle", | ||
| "ms-python.python", | ||
| "ms-python.pylint", | ||
| "ms-python.black-formatter", | ||
| "ms-vscode.hexeditor", | ||
| "charliermarsh.ruff", | ||
| "github.copilot" | ||
| ], | ||
| "settings": { | ||
| "java.jdt.ls.java.home": "/usr/lib/jvm/java-21-openjdk-amd64", | ||
| "java.configuration.runtimes": [ | ||
| { | ||
| "name": "JavaSE-21", | ||
| "path": "/usr/lib/jvm/java-21-openjdk-amd64" | ||
| } | ||
| ], | ||
| "java.compile.nullAnalysis.mode": "automatic", | ||
| "java.gradle.java.home": "/usr/lib/jvm/java-21-openjdk-amd64" | ||
| } | ||
| } | ||
| }, | ||
| "containerEnv": { | ||
| "GHIDRA_INSTALL_DIR": "/opt/ghidra", | ||
| "GHIDRA_SRC_DIR": "/opt/ghidra-src", | ||
| "JAVA_HOME": "/usr/lib/jvm/java-21-openjdk-amd64", | ||
| "PATH": "${containerEnv:PATH}:/opt/ghidra:/opt/gradle/bin" | ||
| }, | ||
| "postCreateCommand": ".devcontainer/postCreateCommand.sh", | ||
| "remoteUser": "vscode" | ||
| } |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,101 @@ | ||||||||||||||||||||||||||||||||||
| #!/bin/bash | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Post-create command script for ReVa devcontainer | ||||||||||||||||||||||||||||||||||
| set -e | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| echo "🚀 Setting up ReVa development environment..." | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Ensure we're in the correct directory | ||||||||||||||||||||||||||||||||||
| cd /workspaces/reverse-engineering-assistant | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Verify installations | ||||||||||||||||||||||||||||||||||
| echo "📋 Verifying installations..." | ||||||||||||||||||||||||||||||||||
| echo "Java version:" | ||||||||||||||||||||||||||||||||||
| java -version | ||||||||||||||||||||||||||||||||||
| echo "Gradle version:" | ||||||||||||||||||||||||||||||||||
| gradle --version | ||||||||||||||||||||||||||||||||||
| echo "Python version:" | ||||||||||||||||||||||||||||||||||
| python3 --version | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Clone and build Ghidra from source if not already done | ||||||||||||||||||||||||||||||||||
| if [ ! -d "/opt/ghidra-src/.git" ]; then | ||||||||||||||||||||||||||||||||||
| echo "📦 Cloning Ghidra source code..." | ||||||||||||||||||||||||||||||||||
| git clone https://github.com/NationalSecurityAgency/ghidra.git /opt/ghidra-src | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [ ! -f "/opt/ghidra/ghidraRun" ]; then | ||||||||||||||||||||||||||||||||||
| echo "🔨 Building Ghidra from source (this may take a while)..." | ||||||||||||||||||||||||||||||||||
| cd /opt/ghidra-src | ||||||||||||||||||||||||||||||||||
| gradle --no-daemon -I gradle/support/fetchDependencies.gradle init | ||||||||||||||||||||||||||||||||||
| gradle --no-daemon buildGhidra | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| echo "📦 Extracting Ghidra build..." | ||||||||||||||||||||||||||||||||||
| unzip -q build/dist/ghidra_*_DEV_*.zip -d /opt | ||||||||||||||||||||||||||||||||||
| mv /opt/ghidra_*_DEV* /opt/ghidra | ||||||||||||||||||||||||||||||||||
| chmod +x /opt/ghidra/ghidraRun | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| cd /workspaces/reverse-engineering-assistant | ||||||||||||||||||||||||||||||||||
| echo "✅ Ghidra build complete!" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| echo "✅ Ghidra is already built and available" | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Check if GHIDRA_INSTALL_DIR is properly set | ||||||||||||||||||||||||||||||||||
| if [ -z "$GHIDRA_INSTALL_DIR" ]; then | ||||||||||||||||||||||||||||||||||
| echo "❌ GHIDRA_INSTALL_DIR is not set!" | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [ ! -d "$GHIDRA_INSTALL_DIR" ]; then | ||||||||||||||||||||||||||||||||||
| echo "❌ Ghidra directory does not exist at $GHIDRA_INSTALL_DIR" | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| echo "✅ GHIDRA_INSTALL_DIR is properly set to: $GHIDRA_INSTALL_DIR" | ||||||||||||||||||||||||||||||||||
| echo "📂 Ghidra source is available at: /opt/ghidra-src" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Activate Python virtual environment | ||||||||||||||||||||||||||||||||||
| echo "🐍 Activating Python virtual environment..." | ||||||||||||||||||||||||||||||||||
| source /opt/venv/bin/activate | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Install any additional Python dependencies if requirements files exist | ||||||||||||||||||||||||||||||||||
| if [ -f "cli/requirements.txt" ]; then | ||||||||||||||||||||||||||||||||||
| echo "📦 Installing Python dependencies from cli/requirements.txt..." | ||||||||||||||||||||||||||||||||||
| pip install -r cli/requirements.txt | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| if [ -f "requirements.txt" ]; then | ||||||||||||||||||||||||||||||||||
| echo "📦 Installing Python dependencies from requirements.txt..." | ||||||||||||||||||||||||||||||||||
| pip install -r requirements.txt | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Verify MCP SDK is installed | ||||||||||||||||||||||||||||||||||
| echo "🔧 Verifying MCP SDK installation..." | ||||||||||||||||||||||||||||||||||
| python3 -c "import mcp; print('✅ MCP SDK is installed')" || echo "❌ MCP SDK installation failed" | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Build the project | ||||||||||||||||||||||||||||||||||
| echo "🔨 Building ReVa extension..." | ||||||||||||||||||||||||||||||||||
| if gradle clean build; then | ||||||||||||||||||||||||||||||||||
| echo "✅ Build successful!" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| echo "❌ Build failed!" | ||||||||||||||||||||||||||||||||||
| exit 1 | ||||||||||||||||||||||||||||||||||
| fi | ||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||
| # Run tests to verify everything is working | ||||||||||||||||||||||||||||||||||
| echo "🧪 Running unit tests..." | ||||||||||||||||||||||||||||||||||
| if gradle test --info; then | ||||||||||||||||||||||||||||||||||
| echo "✅ Unit tests passed!" | ||||||||||||||||||||||||||||||||||
| else | ||||||||||||||||||||||||||||||||||
| echo "⚠️ Unit tests failed - this might be expected in some environments" | ||||||||||||||||||||||||||||||||||
|
Comment on lines
+86
to
+90
|
||||||||||||||||||||||||||||||||||
| echo "🧪 Running unit tests..." | |
| if gradle test --info; then | |
| echo "✅ Unit tests passed!" | |
| else | |
| echo "⚠️ Unit tests failed - this might be expected in some environments" | |
| # In headless environments (e.g., CI, devcontainers without GUI), some tests may fail due to missing GUI dependencies. | |
| # We skip running tests if DISPLAY is not set (Linux) or if running in a known headless environment. | |
| echo "🧪 Running unit tests..." | |
| if [ -z "$DISPLAY" ]; then | |
| echo "⚠️ Skipping unit tests: headless environment detected (no DISPLAY variable set)." | |
| else | |
| if gradle test --info; then | |
| echo "✅ Unit tests passed!" | |
| else | |
| echo "⚠️ Unit tests failed - this might be expected in headless environments or if GUI dependencies are missing." | |
| fi |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,28 @@ | ||
| - When writing integration tests, make sure to set up the program, call the tool and then validate the output. If the tool modifies the program, validate the modification. | ||
| - Don't write useless tests, make sure they have a purpose. | ||
| - **CRITICAL**: Integration tests should validate actual Ghidra program state changes, not just MCP tool responses | ||
| # Integration Test Development Guidelines | ||
|
|
||
| ## Test Design Philosophy | ||
|
|
||
| - **State Validation**: Always validate actual Ghidra program state changes, not just MCP tool responses | ||
| - **Purpose-Driven Testing**: Only write tests that verify meaningful functionality | ||
| - **End-to-End Validation**: Set up program state, execute tools, validate both response and program modifications | ||
|
|
||
| ## Critical Testing Requirements | ||
|
|
||
| 1. **Program State Validation**: | ||
| - Use `Function.getParameters()` and `Function.getAllVariables()` to validate variable changes | ||
| - Use `DataType.isEquivalent()` to compare datatypes before/after changes | ||
| - Check actual symbol table entries, not just tool responses | ||
|
|
||
| 2. **Shared Test Environment**: | ||
| - Tests use shared Ghidra environment for faster execution | ||
| - Each test gets a fresh program via `createDefaultProgram()` | ||
| - MCP server persists across tests within the same class | ||
|
|
||
| 3. **Test Isolation**: | ||
| - Fork every test to prevent configuration conflicts | ||
| - Programs are automatically registered/unregistered with MCP server | ||
| - Always wrap program modifications in transactions | ||
|
|
||
| ## Test Requirements | ||
| - Tests run with `java.awt.headless=false` (GUI environment required) | ||
| - **You are not finished until all tests pass!** |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The script checks if
$GHIDRA_INSTALL_DIRdirectory exists before Ghidra is actually built and installed. Since Ghidra is built in the previous section (lines 26-41), this check should come after the Ghidra build completion, not before.