Skip to content

Add dev container config to Horizon #1181

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

Merged
merged 4 commits into from
Jun 4, 2025
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
84 changes: 84 additions & 0 deletions .devcontainer/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
FROM mcr.microsoft.com/devcontainers/base:debian

# Set non-interactive frontend for apt
ENV DEBIAN_FRONTEND=noninteractive

# Switch to root for installing packages
USER root

# Install additional dependencies
RUN apt update && apt install -y \
build-essential \
curl \
jq \
python3 \
python3-pip \
python3-venv \
pipx \
&& apt clean \
&& rm -rf /var/lib/apt/lists/*

# Install Node.js 20.x using NodeSource
RUN curl -fsSL https://deb.nodesource.com/setup_20.x | bash - && \
apt update && \
apt install -y nodejs && \
apt clean && \
rm -rf /var/lib/apt/lists/*

# Install Solidity compiler using pipx (isolated environment)
RUN pipx install solc-select && \
pipx ensurepath && \
/root/.local/bin/solc-select install 0.8.27 && \
/root/.local/bin/solc-select use 0.8.27 && \
# Copy binaries to /usr/local/bin with proper permissions (not symlinks)
cp /root/.local/bin/solc /usr/local/bin/solc && \
cp /root/.local/bin/solc-select /usr/local/bin/solc-select && \
chmod 755 /usr/local/bin/solc && \
chmod 755 /usr/local/bin/solc-select && \
# Make sure pipx directory is accessible
chmod -R a+rx /root/.local/pipx && \
# Set up for vscode user
mkdir -p /home/vscode/.solc-select && \
cp -r /root/.solc-select/* /home/vscode/.solc-select/ && \
chown -R vscode:vscode /home/vscode/.solc-select

RUN npm install -g ethers@6.13.4

# Install cloc for code analysis
RUN npm install -g cloc

# Install Foundry for Anvil (as root for global installation)
RUN curl -L https://foundry.paradigm.xyz | bash && \
/root/.foundry/bin/foundryup && \
# Copy binaries to /usr/local/bin with proper permissions
cp /root/.foundry/bin/anvil /usr/local/bin/anvil && \
cp /root/.foundry/bin/cast /usr/local/bin/cast && \
cp /root/.foundry/bin/forge /usr/local/bin/forge && \
cp /root/.foundry/bin/chisel /usr/local/bin/chisel && \
# Ensure proper permissions
chmod 755 /usr/local/bin/anvil && \
chmod 755 /usr/local/bin/cast && \
chmod 755 /usr/local/bin/forge && \
chmod 755 /usr/local/bin/chisel

# Set up pnpm
RUN corepack enable && \
corepack prepare pnpm@9.0.6 --activate

# Ensure all users have access to the tools
RUN chmod 755 /usr/local/bin/* && \
# Create a directory for vscode user's binaries
mkdir -p /home/vscode/.local/bin && \
chown -R vscode:vscode /home/vscode/.local/bin

# Switch back to vscode user
USER vscode

# Set environment variables
ENV PATH="/usr/local/bin:/home/vscode/.foundry/bin:/home/vscode/.local/bin:/root/.local/bin:$PATH"

# Create .bashrc additions for PATH
RUN echo 'export PATH="/usr/local/bin:$HOME/.local/bin:$PATH"' >> $HOME/.bashrc

# Set the default command
CMD ["sleep", "infinity"]
107 changes: 107 additions & 0 deletions .devcontainer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
# Graph Protocol Contracts Dev Container

This directory contains configuration files for the Graph Protocol contracts development container.

> **Note:** This dev container setup is a work in progress and will not be fully portable.

## Overview

The dev container provides a consistent development environment with caching to improve performance.

### Key Components

1. **Docker Compose Configuration**: Defines the container setup, volume mounts, and environment variables
2. **Dockerfile**: Specifies the container image and installed tools
3. **project-setup.sh**: Configures the environment after container creation
4. **host-setup.sh**: Sets up the host environment before starting the container
5. **setup-git-signing.sh**: Automatically configures Git to use SSH signing with forwarded SSH keys

## Cache System

The container uses a conservative caching approach to prevent cache corruption issues:

1. **Local Cache Directories**: Each container instance maintains its own cache directories

- `vscode-cache` → `/home/vscode/.cache` (VS Code cache)
- `vscode-config` → `/home/vscode/.config` (VS Code configuration)
- `vscode-data` → `/home/vscode/.local/share` (VS Code data)
- `vscode-bin` → `/home/vscode/.local/bin` (User binaries)

2. **Safe Caches Only**: Only caches that won't cause cross-branch issues are configured

- GitHub CLI: `/home/vscode/.cache/github`
- Python packages: `/home/vscode/.cache/pip`

3. **Intentionally Not Cached**: These tools use their default cache locations to avoid contamination
- NPM (different dependency versions per branch)
- Foundry, Solidity (different compilation artifacts per branch)
- Hardhat (different build artifacts per branch)

## Setup Instructions

### Start the Dev Container

To start the dev container:

1. Open VS Code
2. Use the "Remote-Containers: Open Folder in Container" command
3. Select the repository directory (for example `/git/graphprotocol/contracts`)

When the container starts, the `project-setup.sh` script will automatically run and:

- Install project dependencies using pnpm
- Configure Git to use SSH signing with your forwarded SSH key
- Source shell customizations if available in PATH

## Environment Variables

Environment variables are defined in two places:

1. **docker-compose.yml**: Contains most of the environment variables for tools and caching
2. **Environment File**: Personal settings are stored in `/opt/configs/graphprotocol/contracts.env` on the host

### Git Configuration

To enable Git commit signing, add the following settings to your environment file:

```env
# Git settings for commit signing
GIT_USER_NAME=Your Name
GIT_USER_EMAIL=your.email@example.com
```

These environment variables are needed for Git commit signing to work properly. If they are not defined, Git commit signing will not be configured, but the container will still work for other purposes.

## Troubleshooting

### Cache Issues

If you encounter build or compilation issues that seem related to cached artifacts:

1. **Rebuild the container**: This will start with fresh local caches
2. **Clean project caches**: Run `pnpm clean` to clear project-specific build artifacts
3. **Clear node modules**: Delete `node_modules` and run `pnpm install` again

### Git SSH Signing Issues

If you encounter issues with Git SSH signing:

1. **SSH Agent Forwarding**: Make sure SSH agent forwarding is properly set up in your VS Code settings
2. **GitHub Configuration**: Ensure your SSH key is added to GitHub as a signing key in your account settings
3. **Manual Setup**: If automatic setup fails, you can manually configure SSH signing:

```bash
# Check available SSH keys
ssh-add -l

# Configure Git to use SSH signing
git config --global gpg.format ssh
git config --global user.signingkey "key::ssh-ed25519 YOUR_KEY_CONTENT"
git config --global gpg.ssh.allowedSignersFile ~/.ssh/allowed_signers
git config --global commit.gpgsign true

# Create allowed signers file
echo "your.email@example.com ssh-ed25519 YOUR_KEY_CONTENT" > ~/.ssh/allowed_signers
```

For other issues, check the `project-setup.sh` and `setup-git-signing.sh` scripts for any errors.
42 changes: 42 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
{
"name": "graph contracts",
"dockerComposeFile": ["docker-compose.yml"],
"service": "dev-graph-contracts",
"features": {
"ghcr.io/devcontainers/features/git:1": {
"configureGitHubCLI": true,
"gitCredentialHelper": "cache"
},
"ghcr.io/devcontainers/features/github-cli:1": {},
"ghcr.io/devcontainers/features/common-utils:2.5.3": {},
"ghcr.io/devcontainers/features/node:1": {
"version": "20"
},
"ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}
},
"postCreateCommand": ".devcontainer/project-setup.sh",
"remoteUser": "vscode",
"workspaceFolder": "${localWorkspaceFolder}",
"customizations": {
"vscode": {
"extensions": [
"rust-lang.rust-analyzer",
"tamasfe.even-better-toml",
"usernamehw.errorlens",
"yzhang.markdown-all-in-one",
"DavidAnson.vscode-markdownlint",
"shd101wyy.markdown-preview-enhanced",
"bierner.markdown-preview-github-styles",
"Gruntfuggly.todo-tree",
"ms-azuretools.vscode-docker",
"donjayamanne.githistory",
"eamodio.gitlens",
"fill-labs.dependi",
"streetsidesoftware.code-spell-checker",
"Augment.vscode-augment",
"NomicFoundation.hardhat-solidity",
"foundry-rs.foundry-vscode"
]
}
}
}
53 changes: 53 additions & 0 deletions .devcontainer/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
services:
dev-graph-contracts:
build:
context: .
dockerfile: Dockerfile
env_file:
- /opt/configs/graphprotocol/contracts.env
environment:
# Essential for large builds
- NODE_OPTIONS=--max-old-space-size=4096

# Clean development environment
- PYTHONDONTWRITEBYTECODE=1

# Disable interactive prompts
- COREPACK_ENABLE_DOWNLOAD_PROMPT=0

# Standard user directories
- XDG_CACHE_HOME=/home/vscode/.cache
- XDG_CONFIG_HOME=/home/vscode/.config
- XDG_DATA_HOME=/home/vscode/.local/share

# Safe caches (won't cause cross-branch issues)
- GH_CONFIG_DIR=/home/vscode/.cache/github
- PIP_CACHE_DIR=/home/vscode/.cache/pip

# pnpm cache is safe to share due to content-addressable storage
- PNPM_HOME=/home/vscode/.local/share/pnpm
- PNPM_CACHE_DIR=/home/vscode/.cache/pnpm

# Note: NPM, Foundry, and Solidity caches are intentionally not set
# to avoid cross-branch contamination. Tools will use their default locations.
volumes:
# Git repo root
- /git:/git

# Local directories for user data (keep local to container)
- vscode-cache:/home/vscode/.cache
- vscode-config:/home/vscode/.config
- vscode-data:/home/vscode/.local/share
- vscode-bin:/home/vscode/.local/bin

# Shared pnpm cache (safe due to content-addressable storage)
- pnpm-store:/home/vscode/.local/share/pnpm
- pnpm-cache:/home/vscode/.cache/pnpm

volumes:
vscode-cache:
vscode-config:
vscode-data:
vscode-bin:
pnpm-store:
pnpm-cache:
48 changes: 48 additions & 0 deletions .devcontainer/host-setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
#!/usr/bin/env bash
# Host setup script for Graph Protocol Contracts dev container
# Run this script on the host before starting the dev container
# Usage: sudo .devcontainer/host-setup.sh

set -euo pipefail

echo "Setting up host environment for Graph Protocol Contracts dev container..."

# Check if running as root
if [ "$(id -u)" -ne 0 ]; then
echo "Error: This script must be run as root (sudo)" >&2
exit 1
fi

CACHE_DIRS=(
"/cache/vscode-cache"
"/cache/vscode-config"
"/cache/vscode-data"
"/cache/vscode-bin"
"/cache/hardhat"
"/cache/npm"
"/cache/yarn"
"/cache/pip"
"/cache/pycache"
"/cache/solidity"
"/cache/foundry"
"/cache/github"
"/cache/apt"
"/cache/apt-lib"
)

echo "Creating cache directories..."
for dir in "${CACHE_DIRS[@]}"; do
if [ ! -d "$dir" ]; then
echo "Creating $dir"
mkdir -p "$dir"
chmod 777 "$dir"
else
echo "$dir already exists"
fi
done

# Note: Package-specific directories will be created by the project-setup.sh script
# inside the container, as they are tied to the project structure

echo "Host setup completed successfully!"
echo "You can now start or rebuild your dev container."
Loading