diff --git a/.vscode/copilot-commit.md b/.vscode/copilot-commit.md deleted file mode 100644 index cef6c19..0000000 --- a/.vscode/copilot-commit.md +++ /dev/null @@ -1,48 +0,0 @@ - - - -Commit messages for the **devcontainer** repository must use Conventional Commits + gitmoji: - -`(): ` - -**Allowed scopes** (pick one, or omit the scope entirely): -- `angular-dev` -- `auto-header` -- `claude-dev` -- `deps` -- `deps-dev` -- `CI-CD` -- `deprecated` -- `dotfiles-sync` -- `essential-dev` -- `git-absorb` -- `github-dev` -- `package-auto-install` -- `peon-ping` -- `pnpm-store` -- `shell-history-per-project` -- `typescript-dev` -- `vite-plus` - -Never invent a scope that is not in the list above. - -**Type β†’ gitmoji** β€” pick the most specific emoji that fits the change: - -| Type | Primary | More specific alternatives | -|------|---------|---------------------------| -| `feat` | ✨ | 🚸 UX Β· ♿️ a11y Β· 🌐 i18n Β· πŸ’¬ text/literals | -| `fix` | πŸ› | πŸš‘οΈ hotfix Β· πŸ”’οΈ security Β· 🩹 trivial Β· πŸ₯… caught errors Β· 🚨 linter warnings Β· ✏️ typo | -| `docs` | πŸ“ | πŸ’‘ source comments Β· πŸ“„ license | -| `refactor` | ♻️ | 🎨 structure Β· πŸ”₯ remove code Β· ⚰️ dead code Β· 🚚 move/rename | -| `test` | βœ… | πŸ§ͺ add failing test Β· πŸ’š fix CI test | -| `chore` | πŸ”§ | πŸ”– tag/release Β· πŸ“Œ pin deps Β· 🩺 healthcheck Β· πŸ™ˆ gitignore | -| `perf` | ⚑️ | | -| `style` | πŸ’„ | 🎨 code style | -| `ci` | πŸ‘· | πŸ’š fix CI | -| `build` | πŸ“¦οΈ | βž• add dep Β· βž– remove dep Β· ⬆️ upgrade dep Β· ⬇️ downgrade dep | -| `revert` | βͺ️ | | - -**Rules:** -- Always include exactly **one** emoji, placed between `:` and the description -- Description: ≀72 chars Β· English Β· lowercase Β· imperative mood Β· no trailing period -- Multiple logical changes β†’ keep the dominant type in the subject line and use a bullet list in the body diff --git a/.vscode/settings.json b/.vscode/settings.json index 621e5e0..0967ef4 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,29 +1 @@ -{ - "conventionalCommits.scopes": [ - "angular-dev", - "auto-header", - "CI-CD", - "claude-dev", - "copilot-dev", - "deprecated", - "deps-dev", - "deps", - "dotfiles-sync", - "essential-dev", - "git-absorb", - "github-dev", - "helpers4-common", - "mistral-dev", - "package-auto-install", - "peon-ping", - "pnpm-store", - "shell-history-per-project", - "typescript-dev", - "vite-plus" - ], - "github.copilot.chat.commitMessageGeneration.instructions": [ - { - "file": ".vscode/copilot-commit.md" - } - ] -} +{} diff --git a/AGENTS.md b/AGENTS.md index e6b845f..406f43f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,189 +1,61 @@ -# AGENTS.md - DevContainer Features +# AGENTS.md β€” devcontainer -## β›” CRITICAL RESTRICTIONS - -- **NEVER execute `git push`** - The user will push manually after review -- **NEVER use GPT models** - Use Claude models only (claude-sonnet-4, Claude Opus 4.5) -- **Everything in English** - Code, comments, commits, documentation, logs, PR descriptions - -## Organization Context - -**helpers4** is a collection of open-source utilities across 5 repos: `typescript`, `devcontainer` (this repo), `action`, `website`, `.github`. All licensed LGPL-3.0. - -## Commit Messages - -Follow [Conventional Commits](https://www.conventionalcommits.org/) with a gitmoji between the scope and the description. - -**Format:** `(): ` - -**Scopes:** defined in `.vscode/settings.json` (`conventionalCommits.scopes`) β€” **add the new feature name here when creating a feature** (forgetting this breaks PR CI) - -| Type | Primary | Alternatives (gitmoji.dev) | When to use | -|------|---------|---------------------------|-------------| -| feat | ✨ | 🚸 UX, ♿️ a11y, 🌐 i18n, πŸ’¬ text/literals | New feature | -| fix | πŸ› | πŸš‘οΈ hotfix, πŸ”’οΈ security, 🩹 trivial, πŸ₯… errors, 🚨 warnings, ✏️ typo | Bug fix | -| docs | πŸ“ | πŸ’‘ source comments, πŸ“„ license | Documentation | -| refactor | ♻️ | 🎨 structure, πŸ”₯ remove code, ⚰️ dead code, 🚚 move/rename | Code refactoring | -| test | βœ… | πŸ§ͺ failing test, πŸ’š fix CI test | Tests | -| chore | πŸ”§ | πŸ™ˆ gitignore, πŸ”– tag/release, πŸ“Œ pin deps, 🩺 healthcheck | Maintenance | -| perf | ⚑️ | β€” | Performance | -| style | πŸ’„ | 🎨 code style | Code style / UI | -| ci | πŸ‘· | πŸ’š fix CI | CI/CD | -| build | πŸ“¦οΈ | βž• add dep, βž– remove dep, ⬆️ upgrade dep, ⬇️ downgrade dep | Build system | -| revert | βͺ️ | β€” | Revert | - -> Pick the **most specific** gitmoji that matches the change. The primary is the safe default; reach for an alternative when it adds real signal. Full list: https://gitmoji.dev - -**Examples:** -- `feat(git-absorb): ✨ add version selection option` -- `fix(dotfiles-sync): πŸ› fix symlink creation` -- `docs(typescript-dev): πŸ“ update README` -- `chore(CI-CD): πŸ”§ update dependencies` - ---- +β†’ [Org-wide rules](https://github.com/helpers4/.dev/blob/main/AGENTS.md): restrictions Β· commit format Β· license headers ## This Repository -**Purpose:** DevContainer Features published on GitHub Container Registry (`ghcr.io/helpers4/devcontainer/`). - -### Project Structure +**Purpose:** DevContainer Features published to `ghcr.io/helpers4/devcontainer/`. -``` -devcontainer/ -β”œβ”€β”€ src/ # Feature source code -β”‚ β”œβ”€β”€ helpers4-common/ # Bootstrap: jq + common.sh (all features depend on this) -β”‚ β”œβ”€β”€ essential-dev/ # Core dev environment (Git, Markdown, editor config) -β”‚ β”œβ”€β”€ typescript-dev/ # TypeScript/JS dev (dependsOn essential-dev) -β”‚ β”œβ”€β”€ angular-dev/ # Angular dev with port forwarding -β”‚ β”œβ”€β”€ vite-plus/ # Vite development setup -β”‚ β”œβ”€β”€ package-auto-install/ # Automatic package installation -β”‚ β”œβ”€β”€ pnpm-store/ # Shared pnpm store via Docker named volume -β”‚ β”œβ”€β”€ auto-header/ # Automatic LGPL-3.0 file headers -β”‚ β”œβ”€β”€ git-absorb/ # git-absorb tool installation -β”‚ β”œβ”€β”€ peon-ping/ # AI agent sound notifications -β”‚ └── shell-history-per-project/ # Persistent shell history per project -β”œβ”€β”€ test/ # One test.sh per feature -β”œβ”€β”€ .github/ -β”‚ β”œβ”€β”€ workflows/ # CI/CD (test matrix) -β”‚ β”œβ”€β”€ CONTRIBUTING.md -β”‚ └── DEVELOPMENT.md -β”œβ”€β”€ AGENTS.md # This file -β”œβ”€β”€ LICENSE # LGPL-3.0 +```text +src// +β”œβ”€β”€ devcontainer-feature.json # id, version, options, mounts, postStartCommand, customizations +β”œβ”€β”€ install.sh # runs as root at build time └── README.md +test//test.sh ``` -### Feature File Structure - -Each feature in `src//` contains: -- `devcontainer-feature.json` β€” Metadata, options, dependencies -- `install.sh` β€” Installation script -- `README.md` β€” Usage documentation - -### Installation Script Pattern - -All `install.sh` scripts follow: -1. Root privileges verification -2. Automatic non-root user detection -3. Dependencies installation via `apt` -4. Architecture detection (x86_64, aarch64) -5. Download from GitHub releases (when applicable) -6. Installation in `/usr/local/bin/` -7. Installation verification -8. Cleanup (`trap cleanup`) +**install.sh pattern:** `set -euo pipefail` Β· root check Β· `h4_detect_user` / `h4_resolve_home` from `helpers4-common` Β· apt deps Β· arch detection (x86_64/aarch64) Β· install to `/usr/local/bin/` Β· `trap cleanup EXIT` -**Requirements:** -- Bash with `set -e` -- Must support both x86_64 and aarch64 -- All features declare `installsAfter: ["ghcr.io/devcontainers/features/common-utils"]` - -### Testing +**Testing:** ```bash -devcontainer features test --features . # Test one feature -devcontainer features test . # Test all -``` - -**Base image requirements:** -- Shell features β†’ any base image (debian, ubuntu) -- Node.js features β†’ `mcr.microsoft.com/devcontainers/javascript-node:20`+ -- TypeScript features β†’ `mcr.microsoft.com/devcontainers/typescript-node:20`+ - -### Available Features - -| Feature | Version | Description | Dependencies | -|---------|---------|-------------|--------------| -| essential-dev | 1.0.2 | Git visualization, editor enhancements, Markdown | β€” | -| github-dev | 1.0.3 | GitHub CLI (gh), Copilot Chat, PR & Issues, GitHub Actions, RemoteHub, Remote Repositories, shared Copilot Chat instructions for commit messages and PR titles/descriptions (reads `conventionalCommits.scopes` per repo, follows the active repo's own PR template) | β€” | -| typescript-dev | 1.0.5 | TypeScript/JS dev with import management | essential-dev | -| angular-dev | 1.0.2 | Angular dev, port 4200 forwarding | β€” | -| vite-plus | 1.0.3 | Vite+ unified CLI (vp), Oxlint/Oxfmt, Vitest, optional system-wide symlink | β€” | -| package-auto-install | β€” | Auto-detect and install packages | β€” | -| helpers4-common | 1.0.0 | Bootstrap: installs jq + `/usr/local/share/helpers4/common.sh` (user detection, home resolution, apt helpers). All helpers4 features `dependsOn` this. | β€” | -| claude-dev | 1.0.1 | Claude Code IDE extension (`anthropic.claude-code`) for VS Code and Cursor | β€” | -| pnpm-store | 1.0.4 | Shared pnpm store via Docker named volume `helpers4-pnpm-store-${devcontainerId}` (no stray .pnpm-store) | helpers4-common | -| auto-header | β€” | LGPL-3.0 license headers | β€” | -| git-absorb | 1.0.2 | git-absorb from GitHub releases | β€” | -| dotfiles-sync | 1.0.2 | Sync local Git/SSH/GPG/npm/gh/cargo/pip/yarn/pnpm config β€” opt-in cloud creds (AWS, kube, Docker, gh OAuth) β€” macOS, Linux, WSL, Codespaces | β€” | -| peon-ping | β€” | Health check endpoint | β€” | -| shell-history-per-project | 1.0.2 | Persistent shell history (zsh/bash/fish) | β€” | - -### CI/CD Workflows - -| Workflow | Trigger | Jobs | -|----------|---------|------| -| `pr-validation.yml` | Pull request β†’ main | conventional-commits, test-features (matrix), shellcheck, pr-comment | -| `test.yml` | Push β†’ main | Feature tests matrix | -| `release.yml` | Published release | Publish features to GHCR | - -- **conventional-commits** β€” Validates PR commit messages against conventional commit format -- **test-features** β€” Matrix of 16 feature/baseImage combos (`devcontainer features test`) -- **shellcheck** β€” Lints all `install.sh` scripts with ShellCheck -- **pr-comment** β€” Posts/updates a status summary comment on the PR - -### Adding a New Feature - -1. Create `src//devcontainer-feature.json` -2. Create `src//install.sh` -3. Create `src//README.md` -4. Create `test//test.sh` -5. Update main `README.md` -6. **Update `.vscode/settings.json`** β€” Add feature name to `conventionalCommits.scopes` (required for PR CI to pass) -7. **Update `.github/workflows/pr-validation.yml`** β€” Add feature to test matrix with appropriate base image -8. **Update `.github/workflows/test.yml`** β€” Add feature to test matrix -9. Update this `AGENTS.md` (scopes + features table) - -### Usage - -```json -{ - "features": { - "ghcr.io/helpers4/devcontainer/essential-dev:1": {}, - "ghcr.io/helpers4/devcontainer/typescript-dev:1": {}, - "ghcr.io/helpers4/devcontainer/vite-plus:1": {}, - "ghcr.io/helpers4/devcontainer/package-auto-install:1": {}, - "ghcr.io/helpers4/devcontainer/git-absorb:1": {}, - "ghcr.io/helpers4/devcontainer/dotfiles-sync:1": {}, - "ghcr.io/helpers4/devcontainer/shell-history-per-project:1": {} - } -} +devcontainer features test --features . +devcontainer features test . ``` -### License Header (required on all scripts) +**Available features:** + +| Feature | Ver | Description | +| ------- | --- | ----------- | +| `helpers4-common` | 1.0.0 | Bootstrap: jq + `common.sh` (user detection, apt helpers) β€” all features depend on this | +| `essential-dev` | 1.0.2 | Git visualization, editor enhancements, Markdown | +| `github-dev` | 1.0.3 | gh CLI, Copilot Chat, PR/Issues/Actions extensions | +| `copilot-dev` | 1.0.1 | Copilot Chat + AI instructions (commits, PRs, code review) | +| `claude-dev` | 1.0.4 | Claude Code extension + `~/.claude` bind-mount (credentials + memory persist) | +| `mistral-dev` | 1.0.1 | Mistral Vibe extension + `~/.vibe` bind-mount | +| `typescript-dev` | 1.0.5 | TS/JS dev, import management (dependsOn essential-dev) | +| `angular-dev` | 1.0.2 | Angular dev, port 4200 | +| `vite-plus` | 1.0.3 | vp CLI, Oxlint/Oxfmt, Vitest | +| `package-auto-install` | β€” | Auto-detect and install packages | +| `pnpm-store` | 1.0.4 | Shared pnpm store via Docker named volume (dependsOn helpers4-common) | +| `auto-header` | β€” | LGPL-3.0 license headers | +| `git-absorb` | 1.0.2 | git-absorb from GitHub releases | +| `dotfiles-sync` | 1.0.2 | Sync Git/SSH/GPG/npm/gh config from host | +| `peon-ping` | 1.0.3 | AI agent sound notifications | +| `shell-history-per-project` | 1.0.2 | Persistent shell history (zsh/bash/fish) | + +**Adding a new feature β€” checklist:** + +1. `src//devcontainer-feature.json` + `install.sh` + `README.md` +2. `test//test.sh` +3. `scopes.json` β†’ add the feature name ← **PR CI fails without this** (action reads `scopes.json` automatically) +4. `.github/workflows/pr-validation.yml` + `test.yml` β†’ add to test matrix +5. This `AGENTS.md` features table + +**License header (all scripts):** ```bash # This file is part of helpers4. # Copyright (C) 2025 baxyz # SPDX-License-Identifier: LGPL-3.0-or-later ``` - -## Repository Links - -- TypeScript: https://github.com/helpers4/typescript -- DevContainer: https://github.com/helpers4/devcontainer -- Actions: https://github.com/helpers4/action -- Website: https://github.com/helpers4/website -- Organization: https://github.com/helpers4 - -## Questions? - -If you need clarification on any aspect, open an issue or comment on the PR. We're here to help! diff --git a/scopes.json b/scopes.json new file mode 100644 index 0000000..e12894b --- /dev/null +++ b/scopes.json @@ -0,0 +1,22 @@ +[ + "angular-dev", + "auto-header", + "CI-CD", + "claude-dev", + "copilot-dev", + "deprecated", + "deps-dev", + "deps", + "dotfiles-sync", + "essential-dev", + "git-absorb", + "github-dev", + "helpers4-common", + "mistral-dev", + "package-auto-install", + "peon-ping", + "pnpm-store", + "shell-history-per-project", + "typescript-dev", + "vite-plus" +] diff --git a/src/claude-dev/README.md b/src/claude-dev/README.md index 3053333..12deaec 100644 --- a/src/claude-dev/README.md +++ b/src/claude-dev/README.md @@ -1,8 +1,8 @@ # Claude Code Development Environment (claude-dev) Installs the [Claude Code](https://www.anthropic.com/claude-code) IDE extension -across supported editors so every devcontainer gets AI-assisted coding powered -by Claude out of the box. +across supported editors and persists `~/.claude` (credentials, config, memory) +across every devcontainer rebuild via a host bind-mount. ## Example Usage @@ -14,10 +14,22 @@ by Claude out of the box. } ``` +Add `initializeCommand` to your `devcontainer.json` so the host directory is +guaranteed to exist before Docker tries to bind-mount it: + +```jsonc +{ + "initializeCommand": "mkdir -p ~/.claude", + "features": { + "ghcr.io/helpers4/devcontainer/claude-dev:1": {} + } +} +``` + ## IDE support | Editor | Status | ID | -|--------|--------|----| +| ------ | ------ | -- | | VS Code | βœ… | `anthropic.claude-code` | | Cursor | βœ… | `anthropic.claude-code` (same registry as VS Code) | | JetBrains (IntelliJ, WebStorm…) | πŸ”œ | pending `xmlId` confirmation β€” marketplace page: [plugin/27310](https://plugins.jetbrains.com/plugin/27310) (vendor: Anthropic) | @@ -25,10 +37,16 @@ by Claude out of the box. ## How it works -The feature declares IDE extensions via the `customizations` field in -`devcontainer-feature.json`. The devcontainer runtime (VS Code Remote Containers, -Cursor, JetBrains Gateway…) reads this field and installs the listed extensions -automatically β€” no manual step required. +1. **Build time** (`install.sh`): generates `/usr/local/share/claude-dev/setup-credentials.sh` + with the target user's home path baked in. +2. **Mount** (`devcontainer-feature.json β†’ mounts`): bind-mounts `$HOME/.claude` from + the host to `/mnt/h4claude` inside the container. +3. **Every start** (`postStartCommand`): `setup-credentials.sh` replaces `~/.claude` + with a symlink to `/mnt/h4claude` β€” credentials, settings, and Claude Code memory + all survive rebuilds. + +If `/mnt/h4claude` is not mounted (e.g. missing `initializeCommand`, standalone test), +the script warns and exits cleanly β€” the container starts normally, just without persistence. ## OS and Architecture Support diff --git a/src/claude-dev/devcontainer-feature.json b/src/claude-dev/devcontainer-feature.json index d917f44..db2a10f 100644 --- a/src/claude-dev/devcontainer-feature.json +++ b/src/claude-dev/devcontainer-feature.json @@ -1,8 +1,8 @@ { "id": "claude-dev", - "version": "1.0.3", + "version": "1.0.4", "name": "Claude Code Development Environment", - "description": "Installs the Claude Code IDE extension (anthropic.claude-code) for VS Code and Cursor. Mounts ~/.claude from the host via a directory symlink β€” credentials and config persist across all rebuilds.", + "description": "Installs the Claude Code IDE extension (anthropic.claude-code) for VS Code and Cursor. Bind-mounts ~/.claude from the host and symlinks it at container start β€” credentials, config, and memory persist across all rebuilds.", "documentationURL": "https://github.com/helpers4/devcontainer/tree/main/src/claude-dev", "licenseURL": "https://github.com/helpers4/devcontainer/blob/main/LICENSE", "keywords": [ @@ -20,6 +20,14 @@ } }, + "mounts": [ + { + "source": "${localEnv:HOME}/.claude", + "target": "/mnt/h4claude", + "type": "bind" + } + ], + "postStartCommand": "/usr/local/share/claude-dev/setup-credentials.sh", "customizations": { "vscode": { "extensions": [ diff --git a/src/claude-dev/install.sh b/src/claude-dev/install.sh index 00e9570..dbc3dba 100755 --- a/src/claude-dev/install.sh +++ b/src/claude-dev/install.sh @@ -102,8 +102,8 @@ STAGED="/mnt/h4claude" TARGET="${TARGET_HOME}/.claude" if [ ! -d "${STAGED}" ]; then - echo "[claude-dev] ERROR: ${STAGED} is not mounted β€” cannot link ~/.claude" >&2 - exit 1 + echo "[claude-dev] WARN: ${STAGED} not mounted β€” ~/.claude not linked, no persistence across rebuilds" >&2 + exit 0 fi rm -rf "${TARGET}" diff --git a/src/copilot-dev/README.md b/src/copilot-dev/README.md index d808280..efd4bb6 100644 --- a/src/copilot-dev/README.md +++ b/src/copilot-dev/README.md @@ -51,7 +51,7 @@ corresponding type: | Setting | Trigger | What it enforces | | --- | --- | --- | -| `commitMessageGeneration.instructions` | Generate Commit Message | Conventional Commits + gitmoji, scopes from `conventionalCommits.scopes` workspace setting | +| `commitMessageGeneration.instructions` | Generate Commit Message | Conventional Commits + gitmoji, scopes from `scopes.json` at the repo root | | `pullRequestDescriptionGeneration.instructions` | Create Pull Request | Same title convention + repo PR template auto-detection with fallback | | `reviewSelection.instructions` | Review and Comment | Correctness bugs, security issues, simplification - no style feedback | diff --git a/src/copilot-dev/devcontainer-feature.json b/src/copilot-dev/devcontainer-feature.json index 04c4544..dc6241e 100644 --- a/src/copilot-dev/devcontainer-feature.json +++ b/src/copilot-dev/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "copilot-dev", - "version": "1.0.1", + "version": "1.0.3", "name": "GitHub Copilot Development Environment", "description": "GitHub Copilot Chat VS Code extension, gh copilot CLI extension, and shared instructions for commit messages, pull-request descriptions, and code reviews (Conventional Commits + gitmoji + active repo PR template).", "documentationURL": "https://github.com/helpers4/devcontainer/tree/main/src/copilot-dev", @@ -24,12 +24,12 @@ }, "github.copilot.chat.commitMessageGeneration.instructions": [ { - "text": "Generate commit messages in English only. Use Conventional Commits format with a gitmoji between the scope and the description: `(): `. The scope is optional; when used, it MUST be one of the values listed in the workspace setting `conventionalCommits.scopes` (defined in `.vscode/settings.json` for the active repository) β€” never invent a scope. Pick the most specific gitmoji from https://gitmoji.dev that matches the change. Common mapping (non-exhaustive): feat β†’ ✨ (new feature), 🚸 (UX), ♿️ (a11y), 🌐 (i18n), πŸ’¬ (text/literals); fix β†’ πŸ› (bug), πŸš‘οΈ (hotfix), πŸ”’οΈ (security), 🩹 (simple), πŸ₯… (errors), 🚨 (warnings), ✏️ (typo); docs β†’ πŸ“ (general), πŸ’‘ (source comments), πŸ“„ (license); refactor β†’ ♻️ (refactor), 🎨 (structure), πŸ”₯ (remove code), ⚰️ (dead code), 🚚 (move/rename); test β†’ βœ… (add/update), πŸ§ͺ (failing test), πŸ’š (fix CI); chore β†’ πŸ”§ (config), πŸ™ˆ (gitignore), πŸ”– (tag/release), πŸ“Œ (pin deps), 🩺 (healthcheck); perf β†’ ⚑️; style β†’ πŸ’„ (UI), 🎨 (code style); ci β†’ πŸ‘· (CI build), πŸ’š (fix CI); build β†’ πŸ“¦οΈ (artefacts), βž• (add dep), βž– (remove dep), ⬆️ (upgrade dep), ⬇️ (downgrade dep); revert β†’ βͺ️. Always include exactly ONE emoji. Keep the description short (≀72 chars), lowercase, imperative mood, no period at the end. If there are multiple logical changes, use a bullet list in the body. Generic shape examples (replace `` with a value from `conventionalCommits.scopes`): `feat(): ✨ add `, `fix(): πŸ› handle `, `docs(): πŸ“ update `, `refactor(): ♻️ simplify `, `chore(): ⬆️ bump `." + "text": "Generate commit messages in English only. Use Conventional Commits format with a gitmoji between the scope and the description: `(): `. The scope is optional; when used, it MUST be one of the values listed in `scopes.json` at the active repository root β€” never invent a scope. Pick the most specific gitmoji from https://gitmoji.dev that matches the change. Common mapping (non-exhaustive): feat β†’ ✨ (new feature), 🚸 (UX), ♿️ (a11y), 🌐 (i18n), πŸ’¬ (text/literals); fix β†’ πŸ› (bug), πŸš‘οΈ (hotfix), πŸ”’οΈ (security), 🩹 (simple), πŸ₯… (errors), 🚨 (warnings), ✏️ (typo); docs β†’ πŸ“ (general), πŸ’‘ (source comments), πŸ“„ (license); refactor β†’ ♻️ (refactor), 🎨 (structure), πŸ”₯ (remove code), ⚰️ (dead code), 🚚 (move/rename); test β†’ βœ… (add/update), πŸ§ͺ (failing test), πŸ’š (fix CI); chore β†’ πŸ”§ (config), πŸ™ˆ (gitignore), πŸ”– (tag/release), πŸ“Œ (pin deps), 🩺 (healthcheck); perf β†’ ⚑️; style β†’ πŸ’„ (UI), 🎨 (code style); ci β†’ πŸ‘· (CI build), πŸ’š (fix CI); build β†’ πŸ“¦οΈ (artefacts), βž• (add dep), βž– (remove dep), ⬆️ (upgrade dep), ⬇️ (downgrade dep); revert β†’ βͺ️. Always include exactly ONE emoji. Keep the description short (≀72 chars), lowercase, imperative mood, no period at the end. If there are multiple logical changes, use a bullet list in the body. Generic shape examples (replace `` with a value from `scopes.json`): `feat(): ✨ add `, `fix(): πŸ› handle `, `docs(): πŸ“ update `, `refactor(): ♻️ simplify `, `chore(): ⬆️ bump `." } ], "github.copilot.chat.pullRequestDescriptionGeneration.instructions": [ { - "text": "Generate pull-request titles and descriptions in English only.\n\n=== TITLE ===\nThe PR title MUST follow the same Conventional Commits + gitmoji format used for commit messages: `(): `. Reuse the same rules: scope optional; when used it MUST come from the workspace setting `conventionalCommits.scopes` defined in the active repo's `.vscode/settings.json` (never invent a scope; if that setting is empty or absent, omit the scope); exactly ONE gitmoji from https://gitmoji.dev (typeβ†’emoji mapping: featβ†’βœ¨, fixβ†’πŸ›, docsβ†’πŸ“, refactor→♻️, testβ†’βœ…, choreβ†’πŸ”§, perfβ†’βš‘οΈ, styleβ†’πŸ’„, ciβ†’πŸ‘·, buildβ†’πŸ“¦οΈ, revertβ†’βͺ️, with more specific variants when applicable); description ≀72 chars, lowercase, imperative mood, no trailing period. If the PR groups several conventional types, pick the dominant one for the title and list the others in the body.\n\n=== DESCRIPTION ===\nThe PR body MUST follow the active repository's own pull-request template, if one is available. Look for it in this order and use the first match found in the workspace:\n 1. `.github/PULL_REQUEST_TEMPLATE.md` (or `pull_request_template.md`)\n 2. `docs/PULL_REQUEST_TEMPLATE.md` or `PULL_REQUEST_TEMPLATE.md` at the repo root\n 3. Any file under `.github/PULL_REQUEST_TEMPLATE/` (multiple templates β€” pick the one whose name best matches the change, e.g. `bug.md` for fixes, `feature.md` for feats; otherwise pick the first one alphabetically)\n 4. If the workspace also bundles an organization-level `.github` repo as a sibling folder (e.g. `helpers4/.github`), use its `PULL_REQUEST_TEMPLATE.md` as a fallback.\n\nWhen a template is found, reproduce its sections in the exact order with the exact heading wording, preserve checkbox label text verbatim, and:\n - Fill text sections (e.g. *Description*, *How tested*, *Related issues*) with content derived from the diff and commits.\n - Tick (`[x]`) every checkbox item that applies based on the diff and commits; leave the others unchecked (`[ ]`). Never invent checklist items beyond what the template lists.\n - Use `Closes #N`, `Fixes #N`, or `Refs #N` for issue references; if no issue is linked, write `None.`\n - For optional/contextual sections (Screenshots, Additional Context, Migration notes…), write `N/A` when not applicable.\n - Never omit a section present in the template; never add sections beyond it.\n\nIf NO template is found anywhere, fall back to this minimal, repo-agnostic structure:\n\n## Description\n## Changes\n## How Has This Been Tested?\n## Related Issues\n\nWhere *Description* is 2–6 sentences, *Changes* is a concise bullet list of the most important diffs, *How Has This Been Tested?* lists the actual commands run (or states `Not tested.`), and *Related Issues* uses `Closes #N` lines or `None.`\n\nGeneral rules: English only; preserve heading wording and ordering verbatim when a template exists; preserve checkbox label text verbatim; no marketing tone." + "text": "Generate pull-request titles and descriptions in English only.\n\n=== TITLE ===\nThe PR title MUST follow the same Conventional Commits + gitmoji format used for commit messages: `(): `. Reuse the same rules: scope optional; when used it MUST come from `scopes.json` at the active repo root β€” never invent a scope; if absent, omit the scope; exactly ONE gitmoji from https://gitmoji.dev (typeβ†’emoji mapping: featβ†’βœ¨, fixβ†’πŸ›, docsβ†’πŸ“, refactor→♻️, testβ†’βœ…, choreβ†’πŸ”§, perfβ†’βš‘οΈ, styleβ†’πŸ’„, ciβ†’πŸ‘·, buildβ†’πŸ“¦οΈ, revertβ†’βͺ️, with more specific variants when applicable); description ≀72 chars, lowercase, imperative mood, no trailing period. If the PR groups several conventional types, pick the dominant one for the title and list the others in the body.\n\n=== DESCRIPTION ===\nThe PR body MUST follow the active repository's own pull-request template, if one is available. Look for it in this order and use the first match found in the workspace:\n 1. `.github/PULL_REQUEST_TEMPLATE.md` (or `pull_request_template.md`)\n 2. `docs/PULL_REQUEST_TEMPLATE.md` or `PULL_REQUEST_TEMPLATE.md` at the repo root\n 3. Any file under `.github/PULL_REQUEST_TEMPLATE/` (multiple templates β€” pick the one whose name best matches the change, e.g. `bug.md` for fixes, `feature.md` for feats; otherwise pick the first one alphabetically)\n 4. If the workspace also bundles an organization-level `.github` repo as a sibling folder (e.g. `helpers4/.github`), use its `PULL_REQUEST_TEMPLATE.md` as a fallback.\n\nWhen a template is found, reproduce its sections in the exact order with the exact heading wording, preserve checkbox label text verbatim, and:\n - Fill text sections (e.g. *Description*, *How tested*, *Related issues*) with content derived from the diff and commits.\n - Tick (`[x]`) every checkbox item that applies based on the diff and commits; leave the others unchecked (`[ ]`). Never invent checklist items beyond what the template lists.\n - Use `Closes #N`, `Fixes #N`, or `Refs #N` for issue references; if no issue is linked, write `None.`\n - For optional/contextual sections (Screenshots, Additional Context, Migration notes…), write `N/A` when not applicable.\n - Never omit a section present in the template; never add sections beyond it.\n\nIf NO template is found anywhere, fall back to this minimal, repo-agnostic structure:\n\n## Description\n## Changes\n## How Has This Been Tested?\n## Related Issues\n\nWhere *Description* is 2–6 sentences, *Changes* is a concise bullet list of the most important diffs, *How Has This Been Tested?* lists the actual commands run (or states `Not tested.`), and *Related Issues* uses `Closes #N` lines or `None.`\n\nGeneral rules: English only; preserve heading wording and ordering verbatim when a template exists; preserve checkbox label text verbatim; no marketing tone." } ], "github.copilot.chat.reviewSelection.instructions": [ diff --git a/src/copilot-dev/install.sh b/src/copilot-dev/install.sh index 805db70..d3b47cd 100755 --- a/src/copilot-dev/install.sh +++ b/src/copilot-dev/install.sh @@ -4,7 +4,7 @@ # SPDX-License-Identifier: LGPL-3.0-or-later # # Runs at BUILD TIME. -# Installs the gh-copilot CLI extension if gh is available. +# Installs the gh-copilot CLI extension. set -euo pipefail @@ -18,17 +18,13 @@ INSTALL_CLI="${_BUILD_ARG_INSTALLCLI:-${INSTALLCLI:-true}}" echo "πŸ”§ Configuring copilot-dev feature..." echo " Install CLI: ${INSTALL_CLI}" -# ============================================================================ -# Install gh copilot CLI extension -# ============================================================================ - +# ── Install gh copilot CLI extension ───────────────────────────────────────── if [ "${INSTALL_CLI}" = "true" ]; then if ! command -v gh >/dev/null 2>&1; then echo " ⚠️ gh CLI not found β€” skipping gh copilot extension install." echo " Add github-dev before copilot-dev, or install gh manually." else echo " Installing gh copilot extension..." - # --force re-installs if already present (idempotent). gh extension install github/gh-copilot --force echo " βœ… gh copilot extension installed: $(gh copilot --version 2>/dev/null || echo 'ok')" fi diff --git a/src/essential-dev/devcontainer-feature.json b/src/essential-dev/devcontainer-feature.json index ce274ab..df6cc08 100644 --- a/src/essential-dev/devcontainer-feature.json +++ b/src/essential-dev/devcontainer-feature.json @@ -1,6 +1,6 @@ { "id": "essential-dev", - "version": "1.0.7", + "version": "1.0.9", "name": "Essential Development Environment", "description": "Core development environment with Git visualization, Markdown support, and essential editor enhancements.", "documentationURL": "https://github.com/helpers4/devcontainer/tree/main/src/essential-dev", @@ -11,7 +11,6 @@ "extensions": [ "donjayamanne.githistory", "the0807.git-graph-plus", - "vivaxy.vscode-conventional-commits", "cardinal90.multi-cursor-case-preserve", "moshfeu.compare-folders", "xyz.local-history", @@ -69,5 +68,8 @@ } } } + }, + "dependsOn": { + "ghcr.io/helpers4/devcontainer/helpers4-common:1": {} } } diff --git a/src/essential-dev/install.sh b/src/essential-dev/install.sh index a8d6fd7..fd15130 100644 --- a/src/essential-dev/install.sh +++ b/src/essential-dev/install.sh @@ -1,12 +1,21 @@ #!/usr/bin/env bash - -# Essential Development Environment DevContainer Feature +# This file is part of helpers4. # Copyright (C) 2025 baxyz -# Licensed under LGPL-3.0 - see LICENSE file for details +# SPDX-License-Identifier: LGPL-3.0-or-later # -# Provides core development environment with Git, Copilot, and editor tools +# Provides core development environment with Git, Markdown, and editor tools. + +set -euo pipefail + +# shellcheck source=/dev/null +. /usr/local/share/helpers4/common.sh + +# Ensure git is available (ubuntu:latest is a minimal image with no git) +h4_ensure_packages git -set -e +# Git workflow aliases +git config --system alias.fixup 'commit --fixup' +git config --system alias.polish 'rebase -i --autosquash origin/HEAD' # Enable VS Code shell integration for all shells # This captures command execution and working directory changes in the terminal @@ -36,7 +45,7 @@ echo "" echo "βœ… essential-dev feature configured" echo "" echo "πŸ“¦ VS Code extensions installed:" -echo " - Git integration (history, graph, conventional commits)" +echo " - Git integration (history, graph)" echo " - Markdown support with preview and linting" echo " - Editor enhancements (multi-cursor, compare, local history)" echo " - File format support (YAML, JSON, CSV, XML, Makefile)" diff --git a/src/git-absorb/devcontainer-feature.json b/src/git-absorb/devcontainer-feature.json index 0bb3e47..95537ce 100644 --- a/src/git-absorb/devcontainer-feature.json +++ b/src/git-absorb/devcontainer-feature.json @@ -1,5 +1,5 @@ { - "version": "1.0.5", + "version": "1.0.6", "id": "git-absorb", "name": "git-absorb", "description": "Installs git-absorb, a tool to automatically absorb staged changes into their logical commits. Like 'git commit --fixup' but automatic.", diff --git a/src/git-absorb/install.sh b/src/git-absorb/install.sh index e0a9dfd..c1781d9 100755 --- a/src/git-absorb/install.sh +++ b/src/git-absorb/install.sh @@ -163,9 +163,14 @@ echo " βœ… git-absorb ${INSTALLED_VERSION} installed successfully" echo echo "πŸŽ‰ git-absorb installation complete!" echo + +# git absorb alias: whole-file matching, scoped to local (unpushed) commits +git config --system alias.absorb 'absorb --whole-file --base origin/HEAD' +echo " βœ… git absorb -> git absorb --whole-file --base origin/HEAD" + echo "πŸ“‹ Usage:" echo " git add # Stage your changes" -echo " git absorb # Automatically absorb into logical commits" +echo " git absorb # Absorb staged changes into local commits (whole-file, up to origin/HEAD)" echo " git absorb --dry-run # Preview what would be absorbed" echo echo "πŸš€ Ready to use:"