Skip to content
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
85 changes: 85 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# Copilot Instructions — devcontainer-features

> Community-maintained collection of [Dev Container Features](https://containers.dev/implementors/features/) that install CLI tools into development containers.

## Quick Reference

- **Build/test a feature**: `devcontainer features test --skip-scenarios -f <FEATURE_ID> -i debian:latest .`
- **Release**: Manual workflow dispatch via `.github/workflows/release.yaml` (main branch only)
- **Feature count**: ~51 features across 7 install methods

## Repository Layout

```
src/<FEATURE_ID>/ # One directory per feature
├── devcontainer-feature.json # Metadata, version, options (source of truth)
├── install.sh # Installation script (must be executable)
├── NOTES.md # Human-written docs: project link, description, install method
└── README.md # AUTO-GENERATED by release workflow — never edit manually
test/<FEATURE_ID>/
└── test.sh # Feature tests using dev-container-features-test-lib
.github/
├── skills/ # AI skill files for creating/changing features
├── workflows/test.yaml # CI: tests changed features on PR, all on push to main
└── workflows/release.yaml # Publishes features to GHCR, auto-generates README.md
README.md # Root: feature table (name, description, method, version)
```

**Critical invariant**: The directory name under `src/` must exactly match the `"id"` field in `devcontainer-feature.json`.

## Feature Naming Conventions

| Priority | Style | When | Examples |
|----------|-------|------|---------|
| 1 | Domain-style | Project has a well-known website | `starship.rs`, `chezmoi.io`, `atuin.sh` |
| 2 | Owner-project | Project name alone is ambiguous | `charmbracelet-gum`, `schpet-linear-cli` |
| 3 | Plain name | Widely recognized, unambiguous tools | `bat`, `jq`, `fzf`, `fd` |

Use hyphens (not slashes) for owner-project names.

## Install Methods (in priority order)

1. **gh release** (~69%) — pre-built binaries from GitHub Releases. Canonical template: `src/fzf/install.sh`
2. **curl** (~20%) — official install script. Reference: `src/bun.sh/install.sh`
3. **apt** (~6%) — Debian/Ubuntu packages. Reference: `src/jq/install.sh`
4. **cargo / bun / npm / nix** — last resort. References: `src/jnsahaj-lumen/install.sh`, `src/critique.work/install.sh`, `src/devenv.sh/install.sh`

## install.sh Conventions

Every `install.sh` must have:
- **Shebang**: `#!/bin/bash`
- **Strict flags**: `set -o errexit`, `pipefail`, `noclobber`, `nounset`, `allexport`
- **Footer**: `echo_banner "devcontainer.community"` → `install "$@"` → `echo "(*) Done!"`
- **Executable bit**: `chmod +x` AND `git update-index --chmod=+x`

Helper functions (e.g., `apt_get_update`, `github_get_latest_release`, `debian_get_target_arch`) come from [shell-snippets](https://github.com/devcontainer-community/shell-snippets) and must be copied verbatim — only customize feature-specific parts.

## Version Management

- New features start at `1.0.0`
- **Every change requires a version bump** — patch by default, minor for new options, major for breaking changes
- Version must be updated in **both** `src/<ID>/devcontainer-feature.json` AND the root `README.md` table
- Both must match exactly

## Testing

CI runs on 3 base images for each changed feature:
- `debian:latest`
- `ubuntu:latest`
- `mcr.microsoft.com/devcontainers/base:ubuntu`

Test files must source `dev-container-features-test-lib` and call `reportResults`.

## Skills (Detailed Workflows)

For step-by-step instructions, read these files:
- **New feature**: [.github/skills/create-devcontainer-feature/SKILL.md](.github/skills/create-devcontainer-feature/SKILL.md)
- **Change feature**: [.github/skills/change-devcontainer-feature/SKILL.md](.github/skills/change-devcontainer-feature/SKILL.md)

## Common Pitfalls

- **Never manually edit** `src/<ID>/README.md` — it's auto-generated by the release workflow
- **Architecture mapping varies per project** — always verify asset names (Go: `amd64`/`arm64`; Rust: `x86_64-unknown-linux-musl`/`aarch64-unknown-linux-musl`)
- **Root README table must stay alphabetically sorted** when adding new features
- **`installsAfter`** is rare — only add when there's a real dependency (e.g., aws-cli depends on common-utils)
- **`options.version.default`** is always `"latest"` unless versioning isn't supported
95 changes: 95 additions & 0 deletions .github/skills/change-devcontainer-feature/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# change-devcontainer-feature

Modify an existing devcontainer feature: update install logic, fix bugs, change metadata — and bump the version.

## When to Use

Use this skill when an issue or request involves changing an existing feature (bug fix, install method update, description change, dependency update, etc.). Do **not** use this for creating a new feature from scratch — use `create-devcontainer-feature` for that.

## Critical Rule: Always Bump the Version

**Every change to a feature MUST include a version bump.** No exceptions.

- **Patch bump** (default): `1.0.0` → `1.0.1` — for bug fixes, minor install script changes, documentation fixes, dependency updates
- **Minor bump**: `1.0.0` → `1.1.0` — for new options, significant behavior changes, new capabilities
- **Major bump**: `1.0.0` → `2.0.0` — for breaking changes (e.g., different binary name, removed options, changed default behavior)

Use a **patch bump** unless the issue explicitly requests or the change clearly warrants a minor or major bump.

## Step 1 — Identify the Feature

Determine which feature to modify from the issue description. The feature `id` matches the directory name under `src/`.

Read the existing files to understand the current state:
- `src/<FEATURE_ID>/devcontainer-feature.json` — current version, options, metadata
- `src/<FEATURE_ID>/install.sh` — current install logic
- `src/<FEATURE_ID>/NOTES.md` — current documentation
- `test/<FEATURE_ID>/test.sh` — current tests

## Step 2 — Make the Requested Changes

Apply the changes described in the issue. Common change types:

- **Bug fix in install.sh** — fix download URL, architecture mapping, error handling, etc.
- **Update install method** — e.g., switch from curl to gh release
- **Update metadata** — description, name, options in `devcontainer-feature.json`
- **Update documentation** — `NOTES.md` content
- **Update tests** — fix or improve `test.sh` assertions
- **Update helper functions** — copy latest versions from https://github.com/devcontainer-community/shell-snippets

When modifying `install.sh`:
- Keep helper functions verbatim from the shell-snippets repo
- Only customize the feature-specific parts (repository, binary name, URL template, architecture mappings)
- Preserve the required header (`set -o` flags) and footer (`echo_banner` + install call)
- Ensure the executable bit is preserved: run `chmod +x` and `git update-index --chmod=+x` if the file is recreated

## Step 3 — Bump the Version

Update the version in **both** locations:

### 3a. `src/<FEATURE_ID>/devcontainer-feature.json`

Increment the `"version"` field:

```json
{
"version": "1.0.1"
}
```

### 3b. Root `README.md`

Find the feature's row in the table and update the version in the last column:

```
| [feature-name](...) | `binary` — description | install-method | 1.0.1 |
```

**Both files must have the same version.** If they are out of sync before your change, align them to the new bumped version.

## Step 4 — Update Tests if Needed

If the change affects the binary name, version output format, or install location, update `test/<FEATURE_ID>/test.sh` accordingly.

If the change is purely a bug fix in install logic and the test already verifies the binary works, the test likely needs no changes.

## Step 5 — Validate

1. Verify `devcontainer-feature.json` is valid JSON and the version was bumped
2. Verify the version in `README.md` matches the version in `devcontainer-feature.json`
3. Verify `install.sh` still has correct shebang, `set -o` flags, and the executable bit
4. Verify `test.sh` still sources `dev-container-features-test-lib` and calls `reportResults`
5. Run CI tests via GitHub Actions — the test workflow automatically picks up changed features on a PR:
- `devcontainer features test --skip-scenarios -f <FEATURE_ID> -i debian:latest .`
- `devcontainer features test --skip-scenarios -f <FEATURE_ID> -i ubuntu:latest .`
- `devcontainer features test --skip-scenarios -f <FEATURE_ID> -i mcr.microsoft.com/devcontainers/base:ubuntu .`

## Checklist

- [ ] Changes applied as described in the issue
- [ ] Version bumped in `src/<ID>/devcontainer-feature.json` (patch unless stated otherwise)
- [ ] Version bumped in root `README.md` (same version, correct row)
- [ ] Both versions match
- [ ] `install.sh` executable bit preserved (if file was modified)
- [ ] Tests updated if affected by the change
- [ ] CI tests pass on all three base images
Loading
Loading