Repository navigation
Set up dev container features repo with publish pipeline #1
Description
Goal
Create a reusable dev container features repository for the savvy-web org. Features are modular install scripts published as OCI artifacts to ghcr.io/savvy-web/devcontainers/<feature> and referenced in any repo's devcontainer.json without needing a custom Dockerfile.
Background
We currently duplicate devcontainer Dockerfile setup across repos. The dev container features spec (https://containers.dev/implementors/features/) lets us extract reusable pieces into independently versioned, option-configurable install scripts. This repo will hold org-specific tooling features; general-purpose features (bats-kcov, language runtimes) will live in a separate personal repo.
Repo structure
devcontainers/
src/
claude-code/
devcontainer-feature.json
install.sh
biome/
devcontainer-feature.json
install.sh
outbound-firewall/
devcontainer-feature.json
install.sh
init-firewall.sh
savvy-toolchain/
devcontainer-feature.json
install.sh
test/
claude-code/
test.sh
scenarios.json
biome/
test.sh
scenarios.json
outbound-firewall/
test.sh
scenarios.json
savvy-toolchain/
test.sh
scenarios.json
.github/
workflows/
publish.yml
test.yml
Planned features
claude-code
Installs Claude Code via Homebrew. Options: version (default: latest).
biome
Installs Biome as a pinned binary from GitHub releases. Options: version (required). Handles architecture detection (x64/arm64). Provides the LSP binary for the VS Code extension.
outbound-firewall
Installs an iptables-based outbound firewall that whitelists GitHub, npm, and Anthropic endpoints. Restricts AI agent internet access in dev containers. Options: extraDomains (additional domains to whitelist). Auto-skips in Codespaces (VS Code Server needs unrestricted outbound for relay communication).
savvy-toolchain
Installs the common savvy-web dev toolchain: commitlint config, lint-staged config, pnpm plugin. Options: commitlint (bool), lintStaged (bool). Sets up COREPACK_ENABLE_DOWNLOAD_PROMPT=0 and pnpm store directory.
Publish pipeline
Use devcontainers/action@v1 in GitHub Actions:
- Test job: Runs
test.shfor each feature against each scenario (different base images, option combinations) - Publish job: On push to main (after tests pass), packages each feature in
src/and pushes toghcr.io/savvy-web/devcontainers/<feature> - Features are independently versioned via
devcontainer-feature.jsonversion field
Consumer usage
In any repo's devcontainer.json:
{
"image": "mcr.microsoft.com/devcontainers/javascript-node:24",
"features": {
"ghcr.io/savvy-web/devcontainers/claude-code": {},
"ghcr.io/savvy-web/devcontainers/biome": { "version": "2.4.9" },
"ghcr.io/savvy-web/devcontainers/outbound-firewall": {},
"ghcr.io/savvy-web/devcontainers/savvy-toolchain": {}
},
"postCreateCommand": "pnpm install"
}No custom Dockerfile needed for most repos.
Tasks
- Scaffold repo structure (
src/,test/,.github/workflows/) - Implement claude-code feature
- Implement biome feature
- Implement outbound-firewall feature
- Implement savvy-toolchain feature
- Set up publish GitHub Action
- Set up test GitHub Action with scenarios
- Test features against
javascript-node:24andbase:ubuntuimages - Migrate vitest-bats devcontainer to use features
Activity