|
| 1 | +--- |
| 2 | +mode: 'agent' |
| 3 | +description: 'Implement a new Dev Container Feature in this repository.' |
| 4 | +--- |
| 5 | + |
| 6 | +# New Devcontainer Feature Generator |
| 7 | + |
| 8 | +## Purpose |
| 9 | +Implement a new Dev Container Feature in this repository. |
| 10 | + |
| 11 | +## Invocation Pattern (Human Usage Examples) |
| 12 | +- `/new-feature just in @casey/just` |
| 13 | +- `/new-feature ripgrep in @BurntSushi/ripgrep` |
| 14 | +- `/new-feature mise in @jdx/mise version=2024.7.1` |
| 15 | +- `/new-feature protolint in @yoheimuta/protolint checksum=true` |
| 16 | + |
| 17 | +Copilot: Parse the user’s invocation to fill the Variables section below before generating changes. |
| 18 | + |
| 19 | +## Variables (to be derived or defaulted) |
| 20 | +Extract from user command or infer: |
| 21 | +- FEATURE_ID: Lowercase id (no spaces). Example: `just`, `ripgrep`, `mise`. |
| 22 | +- FEATURE_DISPLAY_NAME: Human-friendly (capitalize if appropriate). Example: `Just`, `Ripgrep`. |
| 23 | +- SOURCE_REPO: GitHub `owner/name` the binary/tool comes from. Example: `casey/just`. |
| 24 | +- BINARY_NAME: Name of the installed executable (often equals FEATURE_ID; override if different). |
| 25 | +- REQUESTED_VERSION: Explicit version if user supplied `version=...`; else "latest". |
| 26 | +- SUPPORT_CHECKSUM: Boolean if user included `checksum=true`; default false. |
| 27 | +- EXTRA_OPTIONS: Optional structured options (e.g. additional feature options) if user appended `opt:key=value` pairs. |
| 28 | +- INITIAL_FEATURE_VERSION: Always start at `1.0.0` (Feature’s internal semver, NOT the tool upstream version). |
| 29 | +- ARCH_LIST: Default `[x86_64, i686, aarch64, armv7]` (omit unsupported ones if known). |
| 30 | +- RELEASE_ASSET_PATTERN: Infer typical asset naming scheme once you inspect the SOURCE_REPO’s latest release assets (handle suffix variations like `linux-x86_64.tar.gz`, `.zip`, plain binary, etc.). |
| 31 | + |
| 32 | +If inference is ambiguous, favor adding commented fallback logic rather than guessing incorrectly. |
| 33 | + |
| 34 | +## High-Level Task |
| 35 | +Create a new Feature at `src/FEATURE_ID` that: |
| 36 | +1. Installs the tool from GitHub releases (or alternative upstream if tool uses another distribution method). |
| 37 | +2. Supports a `version` option (default `"latest"`) resolving to the latest stable release (exclude pre-releases unless user explicitly requests one). |
| 38 | +3. Implements multi-architecture support mapping `uname -m` to release asset names. |
| 39 | +4. Provides graceful fallback if GitHub API calls fail (e.g. rate limit / firewall) by: |
| 40 | + - Trying API first (`https://api.github.com/repos/SOURCE_REPO/releases/latest`) |
| 41 | + - Falling back to parsing HTML of `https://github.com/SOURCE_REPO/releases/latest` or using a lightweight strategy (document what you did). |
| 42 | +5. (Optional) Performs checksum verification if SUPPORT_CHECKSUM is true AND the upstream provides checksums (e.g. `SHA256SUMS` file). |
| 43 | +6. Adds tests: basic install + pinned version test; checksum test if applicable. |
| 44 | +7. Updates root README to list the feature with usage examples. |
| 45 | +8. Integrates tests into existing CI matrix (mirroring the just feature pattern). |
| 46 | +9. Uses consistent shell style and safety (`set -euo pipefail`, traps for cleanup). |
| 47 | +10. Leaves unrelated files untouched (NO incidental formatting changes, NO kyverno/zarf edits, NO drive-by refactors). |
| 48 | + |
| 49 | +## File/Directory Deliverables |
| 50 | +Create: |
| 51 | +- `src/FEATURE_ID/devcontainer-feature.json` |
| 52 | +- `src/FEATURE_ID/install.sh` |
| 53 | +- `test/FEATURE_ID/test.sh` |
| 54 | +- `test/_global/FEATURE_ID-specific-version.sh` |
| 55 | +update |
| 56 | +- `test/_global/all-tools.sh` |
| 57 | +- `test/_global/scenarios.json` |
| 58 | +- `.github/workflows/test.yaml` |
| 59 | + |
| 60 | +Modify minimally: |
| 61 | +- Root `README.md` (add new feature entry & examples) |
| 62 | + |
| 63 | +## devcontainer-feature.json Requirements |
| 64 | +- `id`: FEATURE_ID |
| 65 | +- `version`: INITIAL_FEATURE_VERSION |
| 66 | +- `name`: FEATURE_DISPLAY_NAME |
| 67 | +- `description`: Concise summary of what the tool does |
| 68 | +- `documentationURL`: Link to this feature’s README |
| 69 | +- `options.version`: string, default "latest" |
| 70 | +- Add any EXTRA_OPTIONS (preserve ordering) |
| 71 | +- `instantiationMode`: "onCreate" |
| 72 | + |
| 73 | +## install.sh Requirements |
| 74 | +1. `#!/usr/bin/env bash` |
| 75 | +2. `set -euo pipefail` |
| 76 | +3. Parse inputs: `VERSION=$VERSION` (from feature option) -> treat "latest" specially. |
| 77 | +4. Architecture map example (adjust names per RELEASE_ASSET_PATTERN): |
| 78 | + - `x86_64` or `amd64` -> `x86_64` |
| 79 | + - `aarch64` or `arm64` -> `aarch64` |
| 80 | + - `armv7l` -> `armv7` |
| 81 | + - `i386` or `i686` -> `i686` |
| 82 | +5. Resolve version: |
| 83 | + - If VERSION == "latest": |
| 84 | + - Try GitHub API → extract tag_name minus leading `v` if present |
| 85 | + - Fallback to scraping or light pattern detection from releases page HTML |
| 86 | + - Else trust user-supplied |
| 87 | +6. Construct download URL (document pattern). |
| 88 | +7. Download to temp dir. Use curl with retry/backoff flags similar to just feature style. |
| 89 | +8. Extract / move binary: |
| 90 | + - If archive: detect extension (.tar.gz, .zip), extract accordingly. |
| 91 | + - Ensure final binary path: `/usr/local/bin/BINARY_NAME` and `chmod 0755`. |
| 92 | +9. (Optional) Checksum: |
| 93 | + - Download checksums file, grep the asset, verify via `sha256sum -c -` |
| 94 | +10. Verification: |
| 95 | + - Run `${BINARY_NAME} --version` or fallback command; ensure it prints something containing resolved version if version != "latest". |
| 96 | +11. Output a success message. |
| 97 | + |
| 98 | + |
| 99 | +## CI Integration |
| 100 | +- Update workflow to include FEATURE_ID in matrix if that’s how others are integrated. |
| 101 | +- Keep ordering logical (append near similar tooling features). |
| 102 | +- Avoid reorganizing unrelated entries. |
| 103 | + |
| 104 | +## Commit / PR Conventions |
| 105 | +Suggested (may auto-squash): |
| 106 | +1. `chore: scaffold FEATURE_ID feature` |
| 107 | +2. `feat: implement FEATURE_ID install logic` |
| 108 | +3. `test: add tests for FEATURE_ID` |
| 109 | +4. `docs: add FEATURE_ID feature documentation` |
| 110 | + |
| 111 | +PR Title: |
| 112 | +`feat: add FEATURE_ID devcontainer feature` |
| 113 | + |
| 114 | +PR Body Should Include: |
| 115 | +- Summary |
| 116 | +- Version handling strategy |
| 117 | +- Architecture support |
| 118 | +- Checksum support (yes/no) |
| 119 | +- Usage examples |
| 120 | +- Tests added |
| 121 | +- Statement: “No unrelated changes; excludes kyverno/zarf fixes.” |
| 122 | + |
| 123 | +## Constraints & Non-Goals |
| 124 | +- Do NOT refactor global scripts. |
| 125 | +- Do NOT adjust unrelated workflow triggers. |
| 126 | +- Do NOT rename existing features. |
| 127 | +- Do NOT remove or reorder existing README content beyond adding new entry. |
| 128 | + |
| 129 | +## Acceptance Criteria |
| 130 | +- All new tests pass in CI. |
| 131 | +- Feature listed in root README. |
| 132 | +- `install.sh` resilient to GitHub API failure with fallback. |
| 133 | +- Pinning a version works. |
| 134 | +- Latest resolution works. |
| 135 | +- No unrelated file diffs (confirm with `git diff` scope). |
| 136 | +- If checksum requested and available upstream, verification implemented (skip gracefully if not). |
| 137 | + |
| 138 | +## Output Format Instruction for Copilot |
| 139 | +When generating the PR: |
| 140 | +1. Create new branch (named `feature/FEATURE_ID`). |
| 141 | +2. Add/modify files exactly as specified. |
| 142 | +3. Open a pull request with the defined title and body. |
| 143 | +4. Include only relevant changes. |
| 144 | + |
| 145 | +## Post-Generation Self-Check (Copilot) |
| 146 | +Before finalizing: |
| 147 | +- Re-open each new file; ensure placeholders replaced. |
| 148 | +- Ensure executable bits on `install.sh` and test scripts. |
| 149 | +- Ensure JSON is valid (no trailing commas). |
| 150 | +- Ensure shell uses POSIX-compatible constructs (or justify bash usage). |
| 151 | +- Verify version extraction logic with both “latest” and pinned flows (mentally or via test design). |
| 152 | +- Confirm absence of kyverno/zarf references / modifications. |
0 commit comments