Skip to content

Add devcontainer definition for reproducible Linux dev environment - #236

Merged
jodavis merged 12 commits into
mainfrom
claude/devcontainer-setup-dv0qmu
Jun 26, 2026
Merged

Add devcontainer definition for reproducible Linux dev environment#236
jodavis merged 12 commits into
mainfrom
claude/devcontainer-setup-dv0qmu

Conversation

@jodavis-claude

Copy link
Copy Markdown
Collaborator

Provides a Docker-based devcontainer so Claude Code remote sessions and
local contributors get a consistent environment with all dependencies
pre-installed.

  • Base image: mcr.microsoft.com/devcontainers/base:ubuntu-24.04 (vscode
    user with passwordless sudo, git, curl pre-installed)
  • Baked into image: GitHub CLI, .NET 10 SDK, PowerShell, Node.js LTS,
    Claude Code CLI, Playwright OS-level Chromium deps, Python ML venv
    at /opt/ml-env with numpy/pandas/tensorflow/dvc
  • ~/.claude mounted as named volume (survives container rebuilds; first
    Claude Code login is interactive, subsequent starts reuse credentials)
  • GITHUB_TOKEN forwarded from host environment so gh works without
    interactive login
  • post-create.sh: dotnet restore → dotnet build → playwright.ps1 install
    chromium --with-deps (version-matched to Microsoft.Playwright NuGet pin)
  • ml/requirements.txt added alongside devcontainer so Dockerfile COPY
    works from the repo-root build context

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL

claude added 2 commits June 23, 2026 07:55
Provides a Docker-based devcontainer so Claude Code remote sessions and
local contributors get a consistent environment with all dependencies
pre-installed.

- Base image: mcr.microsoft.com/devcontainers/base:ubuntu-24.04 (vscode
  user with passwordless sudo, git, curl pre-installed)
- Baked into image: GitHub CLI, .NET 10 SDK, PowerShell, Node.js LTS,
  Claude Code CLI, Playwright OS-level Chromium deps, Python ML venv
  at /opt/ml-env with numpy/pandas/tensorflow/dvc
- ~/.claude mounted as named volume (survives container rebuilds; first
  Claude Code login is interactive, subsequent starts reuse credentials)
- GITHUB_TOKEN forwarded from host environment so gh works without
  interactive login
- post-create.sh: dotnet restore → dotnet build → playwright.ps1 install
  chromium --with-deps (version-matched to Microsoft.Playwright NuGet pin)
- ml/requirements.txt added alongside devcontainer so Dockerfile COPY
  works from the repo-root build context

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL
Builds the Docker image on every push/PR that touches devcontainer
files or ml/requirements.txt, then runs a smoke test inside the
built container to verify .NET, gh, Node.js, Python, and the ML
venv packages are all present and importable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown

Test Results

401 tests  ±0   401 ✅ ±0   2m 34s ⏱️ +29s
  5 suites ±0     0 💤 ±0 
  5 files   ±0     0 ❌ ±0 

Results for commit a246452. ± Comparison against base commit d2636b6.

This pull request removes 3 and adds 2 tests. Note that renamed tests count towards both.
,False)
AdaptiveRemote.Services.ProgrammaticSettings.PersistSettingsTests ‑ PersistSettings_Set_ValidatesKeyNameAsync (Hello
AdaptiveRemote.Services.ProgrammaticSettings.PersistSettingsTests ‑ PersistSettings_Set_ValidatesValueAsync (Invalid
AdaptiveRemote.Services.ProgrammaticSettings.PersistSettingsTests ‑ PersistSettings_Set_ValidatesKeyNameAsync (Hello
,False)
AdaptiveRemote.Services.ProgrammaticSettings.PersistSettingsTests ‑ PersistSettings_Set_ValidatesValueAsync (Invalid
,False)

♻️ This comment has been updated with latest results.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Docker-based devcontainer definition (plus CI validation) to provide a consistent Linux development environment for contributors/remote sessions, including preinstalled .NET/Node/Python tooling and a post-create bootstrap script.

Changes:

  • Added .devcontainer/ definition (Dockerfile + devcontainer.json) and a post-create.sh script to restore/build and install Playwright Chromium.
  • Added a GitHub Actions workflow to build the devcontainer image and run a basic smoke test for installed tooling.
  • Added ml/requirements.txt to support baking ML Python dependencies into the devcontainer image.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
ml/requirements.txt Introduces pip requirements used during devcontainer image build.
.github/workflows/devcontainer-build.yml Adds CI job to build the devcontainer image and smoke test key tools/packages.
.devcontainer/post-create.sh Adds post-create bootstrap steps (restore/build + Playwright browser install).
.devcontainer/Dockerfile Defines the devcontainer image and preinstalls developer dependencies.
.devcontainer/devcontainer.json Configures devcontainer build, mounts, env vars, and editor settings/extensions.

Comment thread .devcontainer/post-create.sh
Comment thread .devcontainer/post-create.sh Outdated
Comment thread ml/requirements.txt Outdated
On Debian/Ubuntu, python3-venv is a separate package from python3 and
must be explicitly installed before python3 -m venv will work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 5 out of 5 changed files in this pull request and generated 5 comments.

Comment thread .devcontainer/post-create.sh
Comment thread .devcontainer/post-create.sh Outdated
Comment thread .devcontainer/devcontainer.json
Comment thread ml/requirements.txt Outdated
Comment thread .devcontainer/Dockerfile
- Dockerfile: replace curl|bash NodeSource install with explicit GPG
  keyring + pinned node_24.x repo for auditability and reproducibility
- devcontainer.json: forward GH_TOKEN alongside GITHUB_TOKEN (gh CLI
  checks both env vars depending on how the host is configured)
- post-create.sh: export ~/.dotnet/tools to PATH in the fallback branch
  before calling playwright, since global tool installs land there and
  it is not on PATH by default; fix quality gate script names to
  include the .sh extension
- ml/requirements.txt: pin to versions validated by the CI build
  (numpy 2.5.0, pandas 3.0.3, tensorflow 2.21.0, dvc 3.67.1)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL
@jodavis
jodavis enabled auto-merge (squash) June 23, 2026 12:20
@jodavis
jodavis disabled auto-merge June 23, 2026 12:20
@jodavis
jodavis enabled auto-merge (rebase) June 23, 2026 12:20
@jodavis
jodavis disabled auto-merge June 23, 2026 12:20
claude and others added 8 commits June 23, 2026 14:57
…ials

Docker initialises a named volume from the image's directory at the
mount point. If the directory doesn't exist in the image, Docker creates
a root-owned entry and the vscode user cannot write to it — causing the
'login succeeds in browser but shows as not logged in' symptom.

Creating ~/.claude as the vscode user in the Dockerfile ensures the
volume is initialised with UID 1000 ownership on first use.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL
…racking, code style, and documentation standards.
…istry

github.repository expands to jodavis/AdaptiveRemote (uppercase A) which
Docker rejects — registry names must be all lowercase. Add a step that
pipes the repository name through tr to produce the lowercase image name,
then reference it via step output in imageName and cacheFrom.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019jmGA95hGTRu4aZ4yL45NL
Was pointing at /home/vscode/.claude/settings.json (the volume target,
same as CLAUDE_SETTINGS). Should point at /home/vscode/.claude-defaults/
settings.json where the Dockerfile bakes the template. In CI the named
volume is always fresh so the source never exists and cp fails. Locally
this is masked because returning developers already have settings in the
persistent volume and the if-block is skipped.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
validate.sh calls validate-build.sh and validate-tests.sh directly (no
bash prefix), so they must be executable. Without the execute bit the
devcontainer CI run fails with exit code 126 (permission denied) when
validate.sh reaches line 20.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@jodavis
jodavis merged commit 30d2cdb into main Jun 26, 2026
4 checks passed
@jodavis
jodavis deleted the claude/devcontainer-setup-dv0qmu branch June 26, 2026 22:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants