diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 000000000..11b050301 --- /dev/null +++ b/.github/copilot-instructions.md @@ -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//`). Each feature = metadata (`devcontainer-feature.json`) + install logic (`install.sh`) + optional helper scripts/docs. +- Tests live in `test//` 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//devcontainer-feature.json` and `src//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//test.sh` plus optional scenario JSON (`scenarios.json`) or additional scripts. + - Pattern: `source dev-container-features-test-lib`; then multiple `check "label" ` 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 ` (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 `: Limit to one feature (repeat flag for multiple). +- `--filter `: Only run scenario tests containing `` (works best together with `--skip-autogenerated --skip-duplicated` but cannot be used with `--skip-scenarios`). +- `-i ` / `--base-image `: Override base image for auto-generated test (not used for scenarios, see CI matrix in `test-all.yaml`). +- `--remote-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 ...; then check_packages ; 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 " version" --version || version` depending on tool semantics. +- For path expectations (common pattern): `check " path" bash -c "which | 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 ` 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.