Skip to content
Open
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
89 changes: 89 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
## AI Coding Agent Instructions for `devcontainers-features`

Purpose: Help an AI quickly make safe, correct changes to this repository of published Dev Container Features.

### 1. Big Picture
- This repo is a collection of reusable Dev Container Features (see `src/<feature>/`). Each feature = metadata (`devcontainer-feature.json`) + install logic (`install.sh`) + optional helper scripts/docs.
- Tests live in `test/<feature>/` mirroring `src/`. CI (see `.github/workflows/test-*.yaml`) runs `devcontainer features test` across multiple base images plus scenario tests.
- No monolithic build system: each feature is self-contained bash + JSON metadata. Consistency across features is critical (option naming, version bumping, cleanup patterns).
- Release/versioning: Each feature has its own semantic `version` field inside its `devcontainer-feature.json`. Bump only the changed feature(s) following semver (patch for fixes, minor for new non-breaking options, major for breaking changes).

### 2. Key Conventions & Patterns
- Mandatory files per feature: `src/<feature>/devcontainer-feature.json` and `src/<feature>/install.sh` (bash, root-only, `set -e`). Some have `README.md`, `NOTES.md`, `scripts/`, or helper binaries.
- Install script patterns:
- Always validate running as root early: `if [ "$(id -u)" -ne 0 ]; then ... exit 1`.
- Source `/etc/os-release` for distro branching logic.
- Use idempotent checks (e.g., skip install if tool already present with correct version substring).
- Environment customization via `containerEnv` in JSON rather than hard‑coding shell rc modifications unless required.
- Avoid interactive prompts: set `DEBIAN_FRONTEND=noninteractive` and pass non‑interactive flags.
- Metadata (`devcontainer-feature.json`):
- Fields: `id`, `version`, `name`, `description`, `documentationURL`, `options` (typed with `type`, `default`, descriptive `description`; may also use `proposals` or `enum`).
- Optional: `installsAfter`, `customizations.vscode.extensions` & Copilot chat instruction snippets, `containerEnv`, `entrypoint`, security flags (`privileged`, `capAdd`, `securityOpt`), `mounts`.
- Keep existing ordering/style; do not reorder unrelated keys in mechanical edits.
- Options naming: lower camel or kebab not used—this repo uses lower camelCase for multiword (e.g., `golangciLintVersion`, `azureDnsAutoDetection`). Stay consistent.
- Tests:
- Each feature has `test/<feature>/test.sh` plus optional scenario JSON (`scenarios.json`) or additional scripts.
- Pattern: `source dev-container-features-test-lib`; then multiple `check "label" <command>` calls; finish with `reportResults`.
- Prefer adding new `check` lines rather than introducing a different harness.
- Global scenarios in `test/_global/` exercise multi-feature interactions.

### 3. Typical Workflows
- Run all tests locally (needs Node + @devcontainers/cli):
- `npm install -g @devcontainers/cli`
- `devcontainer features test -f <feature>` (fast path while iterating)
- Add `--skip-scenarios` or `--skip-autogenerated` as CI workflows do for targeted subsets.
- Validate metadata schema: GitHub Action `.github/workflows/validate-metadata-files.yml` runs `devcontainers/action@v1` in validate-only mode. Keep JSON valid and semver strings correct.
- Adding a new check in tests: replicate existing style; ensure commands exist in PATH for all targeted base images or guard behind option-specific logic.

#### Common `devcontainer features test` Flags Used Here
- `-f <feature>`: Limit to one feature (repeat flag for multiple).
- `--filter <text>`: Only run scenario tests containing `<text>` (works best together with `--skip-autogenerated --skip-duplicated` but cannot be used with `--skip-scenarios`).
- `-i <image>` / `--base-image <image>`: Override base image for auto-generated test (not used for scenarios, see CI matrix in `test-all.yaml`).
- `--remote-user <user>`: Set container user for tests (default varies by base image; rarely needed here).
- `--skip-autogenerated`: Skip the default per-feature auto-generated test.
- `--skip-scenarios`: Skip scenario tests defined via `scenarios.json`.
- `--skip-duplicated`: Skip duplicate install mode (tests idempotent double install when `duplicate.sh` exists).
- `--global-scenarios-only`: Run only tests under `test/_global`.
- `--debug`: Verbose logging when diagnosing failing installs.
Use combinations (e.g. CI uses `--skip-scenarios` for the broad matrix, then a separate job without it to exercise scenarios).

### 4. Safe Change Guidelines
- Touch only the feature(s) you intend; avoid broad refactors across every feature.
- When altering install logic for a feature, update its `version` in `devcontainer-feature.json` (patch unless adding options or breaking behavior).
- Never downgrade existing tooling unless there is a security/compatibility reason—document rationale in a brief comment.
- Preserve distro branching logic; if adding a dependency ensure both Debian (`apt-get`) and RHEL (`dnf`/`microdnf`/`yum`) paths are handled.
- Ensure cleanup (`rm -rf /var/lib/apt/lists/*` or `rm -rf /var/cache/dnf/*`) is maintained so images stay slim.
- Keep scripts POSIX/Bash compatible with `#!/usr/bin/env bash` and `set -e`; prefer explicit `if ! type <tool> ...; then check_packages <pkg>; fi` pattern.

### 5. Adding / Updating Options
- Add new option under `options` with `type` (`string`, `boolean`, etc.), `default`, and clear `description`.
- If tool versions can be enumerated, use `proposals` (suggestions) or `enum` (strict) as existing features do.
- When an option changes behavior but is backward-compatible: bump minor. Breaking rename/removal: bump major.

### 6. Tests for New Behavior
- For new installed binaries: add `check "<tool> version" <tool> --version || <tool> version` depending on tool semantics.
- For path expectations (common pattern): `check "<tool> path" bash -c "which <tool> | grep /expected/path"`.
- Keep tests deterministic: avoid network-heavy operations beyond what existing patterns already do (the feature install covers that).

### 7. Copilot / Agent Usage Examples
- Modify feature version: edit only that feature's JSON `version` field and associated logic; do NOT bump unrelated features.
- Add a dependency: replicate `check_packages <pkg>` in correct distro branch rather than inline `apt-get install`.
- Add Copilot chat context for a feature: append an object under `customizations.vscode.settings.github.copilot.chat.codeGeneration.instructions` with a concise `text` value.

### 8. Common Pitfalls
- Forgetting to bump a feature version after changing `install.sh` or metadata (causes caching confusion for downstream users).
- Adding a test that only passes on Ubuntu but fails on Debian/RHEL variants—ensure packages exist across matrix.
- Reordering JSON keys causing noisy diffs—keep minimal diff.
- Leaving behind temporary GPG keys or package lists—ensure cleanup.

### 9. Quick Reference Files
- Example feature: `src/go/` shows version resolution + env vars.
- Complex options & privileged setup: `src/docker-in-docker/`.
- Test patterns: `test/go/test.sh`, `test/docker-in-docker/test.sh`, global multi-feature: `test/_global/*.sh`.
- CI workflows driving expectations: `.github/workflows/test-all.yaml`, `test-pr.yaml`, `validate-metadata-files.yml`.

### 10. When Unsure
- Mirror an existing feature with the closest complexity and adapt minimally.
- Favor explicit checks + comments over clever but opaque bash.

End of instructions – request clarification if a needed pattern is not covered here.