Skip to content

Split Devcontainer and Workspace per Language and Drop Husky - #65

Merged
ptr727 merged 3 commits into
developfrom
per-language-devcontainers
May 4, 2026
Merged

Split Devcontainer and Workspace per Language and Drop Husky#65
ptr727 merged 3 commits into
developfrom
per-language-devcontainers

Conversation

@ptr727

@ptr727 ptr727 commented May 3, 2026

Copy link
Copy Markdown
Owner

Summary

  • Replace the single .devcontainer/ + ProjectTemplate.code-workspace with per-language pairs: .devcontainer/dotnet/ + DotNet.code-workspace and .devcontainer/python/ + Python.code-workspace. Each container ships only one toolchain so editor surface, recommended extensions, and postCreateCommand match the language being worked on.
  • Drop the Husky.Net hooks framework. Hooks are repo-global, so any framework forces its runtime (dotnet for Husky, Python for pre-commit) into the wrong-language container. CI already runs dotnet csharpier check, dotnet format --verify-no-changes, ruff check, ruff format --check, and pyright on every PR — that is the lint backstop.
  • Document opt-in hooks per language in README under "Optional: enable git hooks locally" so downstream forks can wire up Husky.Net (.NET) or pre-commit (Python) if they want pre-commit checks locally.

Notes

  • Windows host Python work is intentionally unsupported: the Python extension caches .venv/bin/python (Linux layout) against a venv whose actual Windows path is .venv\Scripts\python.exe, breaking Ruff. The python devcontainer is the supported path.
  • Git rename detection labels ProjectTemplate.code-workspace -> Python.code-workspace because Python.code-workspace happened to be the closer content match. Conceptually DotNet.code-workspace is the descendant; the actual file contents are correct in both.

Test plan

  • git diff main...HEAD review.
  • Open DotNet.code-workspace on Windows host -> dotnet build + dotnet test succeed without Husky.
  • Open DotNet.code-workspace -> Reopen in Container -> "dotnet" -> dotnet build succeeds; which uv returns nothing; ms-python.python not installed.
  • Open Python.code-workspace -> Reopen in Container -> "python" -> cd PyPiLibrary && uv sync && uv run pytest succeeds; which dotnet returns nothing; Ruff extension log shows interpreter at the container venv path.
  • Confirm CI green on this PR (csharpier check + dotnet format --verify-no-changes; ruff check + ruff format --check + pyright).
  • Push a deliberately mis-formatted .cs file on a throwaway branch -> .NET pipeline fails on csharpier; same with a .py file -> Python pipeline fails on ruff. (Verifies the lint backstop without hooks.)
  • Confirm .git/hooks/pre-commit does not exist after a fresh clone + devcontainer rebuild.

Replace the single `.devcontainer/` + `ProjectTemplate.code-workspace` with
per-language pairs: `.devcontainer/dotnet/` + `DotNet.code-workspace` and
`.devcontainer/python/` + `Python.code-workspace`. Each container only ships
the toolchain for one language so editor surface, recommended extensions,
and post-create steps reflect what the contributor is actually working on.

Drop the Husky.Net hooks framework. Git hooks are repo-global (one
`.git/hooks/pre-commit` shared by every environment that commits), so any
framework forces its runtime into the wrong-language container. CI already
runs `dotnet csharpier check`, `dotnet format --verify-no-changes`,
`ruff check`, `ruff format --check`, and `pyright` on every PR — those are
the lint backstop; hooks were redundant local-only enforcement.

Document opt-in hooks per language in README under "Optional: enable git
hooks locally" so downstream forks can wire up Husky.Net or pre-commit if
they want pre-commit checks locally.

Windows host Python work is intentionally not supported: the Python
extension caches the Linux-layout `.venv/bin/python` against a venv whose
actual Windows path is `.venv\Scripts\python.exe`, breaking Ruff. The
python devcontainer is the supported path for Python work.
Copilot AI review requested due to automatic review settings May 3, 2026 23:31

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR restructures the repository’s developer UX by splitting the VS Code devcontainer + workspace setup per language and removing Husky.Net as a repo-global git hooks framework (relying on CI formatting/linting instead).

Changes:

  • Split tooling into .devcontainer/dotnet/ + DotNet.code-workspace and .devcontainer/python/ + Python.code-workspace.
  • Remove Husky.Net hooks and related configuration from the template, and replace the Husky-based CI formatting step with direct csharpier/dotnet format invocations.
  • Update README to document the new per-language setup and provide opt-in hook instructions.

Reviewed changes

Copilot reviewed 11 out of 11 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
README.md Documents the per-language devcontainers/workspaces and opt-in hooks guidance.
Python.code-workspace Removes .NET-specific settings/extensions, keeping Python-focused editor settings.
DotNet.code-workspace Adds a .NET-focused workspace with C# tooling recommendations/settings.
.devcontainer/python/devcontainer.json Adds a Python-only devcontainer definition (Python + uv + gh).
.devcontainer/python/post-create.sh Removes .NET tool restore / Husky install; installs uv + runs uv sync.
.devcontainer/dotnet/devcontainer.json Updates .NET devcontainer to restore tools only (no uv/Husky).
.devcontainer/dotnet/post-create.sh Adds .NET-only post-create tool restore.
.github/workflows/test-release-task.yml Replaces dotnet husky run with dotnet csharpier check + dotnet format style.
.config/dotnet-tools.json Drops Husky from the local tool manifest.
.husky/task-runner.json Removed (Husky hook task configuration).
.husky/pre-commit Removed (Husky pre-commit hook entrypoint).
Comments suppressed due to low confidence (1)

.config/dotnet-tools.json:18

  • Husky is removed from the local tool manifest here, but there are still repo workflows/tasks that invoke dotnet husky … (for example the codegen PR workflows and the VS Code "Husky.Net Run" task). After this change those commands will fail because dotnet tool restore will no longer install Husky; either update those workflows/tasks to not depend on Husky, or keep Husky in the manifest (or install it explicitly where needed).
  "tools": {
    "csharpier": {
      "version": "1.2.6",
      "commands": [
        "csharpier"
      ],
      "rollForward": false
    },
    "dotnet-outdated-tool": {
      "version": "4.7.1",
      "commands": [
        "dotnet-outdated"
      ],
      "rollForward": false
    }

Comment thread README.md Outdated
Comment thread README.md Outdated
Comment thread README.md
Comment thread README.md Outdated
Comment thread README.md Outdated
Addresses Copilot review on PR #65 plus a low-confidence comment that
turned out to be a real workflow break.

Workflow fix (would have failed on next codegen run):
- run-codegen-pull-request-task.yml, run-codegen-app-pull-request-task.yml:
  drop `dotnet husky install` step. Husky was removed from the local tool
  manifest, so the call would fail after `dotnet tool restore`.

Stale doc cleanup following the Husky removal:
- AGENTS.md: rewrite the unified-container paragraph for the per-language
  split, fix project-structure list, drop husky from quick-start.
- CODESTYLE.md: replace Husky bullets with a CI-as-backstop note + pointer
  to the README opt-in section.
- PyPiLibrary/CODESTYLE.md: drop Husky-runs-ruff sentence; fix the
  delete-Python-side checklist to reference the new per-language paths.
- .vscode/tasks.json: remove the Husky.Net Run task.
- docs/devcontainer.md: full rewrite for the two per-language containers
  (workspace+image table, language-specific verify commands, no Husky in
  postCreateCommand).
- docs/host-setup.md: fix tail-link wording.

README review fixes:
- Pre-commit hook samples now run uv with --directory PyPiLibrary and
  scope `files` to PyPiLibrary so they execute in the uv project that
  actually owns ruff/pyright + their configs.
- Template TODO open-workspace step no longer hard-codes a single
  workspace name; reflects that derived projects may keep .NET, Python,
  or both workspace files.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 2 comments.

Comment thread README.md Outdated
Comment thread docs/host-setup.md
…aths

Addresses Copilot review on dc4ebc0:

- README.md Windows note: the Python tooling runs `uv sync` inside
  PyPiLibrary/, so the cached interpreter path is PyPiLibrary/.venv/...,
  not .venv/... at the repo root. Updates both the Linux-layout and
  Windows-layout examples accordingly.
- docs/host-setup.md "Supported hosts" Windows row: replace the stale
  reference to .devcontainer/devcontainer.json with the per-language
  paths .devcontainer/dotnet/devcontainer.json and
  .devcontainer/python/devcontainer.json.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 19 out of 19 changed files in this pull request and generated 1 comment.

Comment thread .github/workflows/test-release-task.yml
@ptr727
ptr727 merged commit bbc9ab2 into develop May 4, 2026
25 checks passed
@ptr727
ptr727 deleted the per-language-devcontainers branch May 4, 2026 02:32
ptr727 added a commit that referenced this pull request May 4, 2026
## Summary

- Replace the single `.devcontainer/` + `ProjectTemplate.code-workspace`
with per-language pairs: `.devcontainer/dotnet/` +
`DotNet.code-workspace` and `.devcontainer/python/` +
`Python.code-workspace`. Each container ships only one toolchain so
editor surface, recommended extensions, and `postCreateCommand` match
the language being worked on.
- Drop the Husky.Net hooks framework. Hooks are repo-global, so any
framework forces its runtime (`dotnet` for Husky, Python for pre-commit)
into the wrong-language container. CI already runs `dotnet csharpier
check`, `dotnet format --verify-no-changes`, `ruff check`, `ruff format
--check`, and `pyright` on every PR — that is the lint backstop.
- Document opt-in hooks per language in README under "Optional: enable
git hooks locally" so downstream forks can wire up Husky.Net (.NET) or
pre-commit (Python) if they want pre-commit checks locally.

## Notes

- Windows host Python work is intentionally unsupported: the Python
extension caches `.venv/bin/python` (Linux layout) against a venv whose
actual Windows path is `.venv\Scripts\python.exe`, breaking Ruff. The
python devcontainer is the supported path.
- Git rename detection labels `ProjectTemplate.code-workspace ->
Python.code-workspace` because `Python.code-workspace` happened to be
the closer content match. Conceptually `DotNet.code-workspace` is the
descendant; the actual file contents are correct in both.

## Test plan

- [ ] `git diff main...HEAD` review.
- [ ] Open `DotNet.code-workspace` on Windows host -> `dotnet build` +
`dotnet test` succeed without Husky.
- [ ] Open `DotNet.code-workspace` -> Reopen in Container -> "dotnet" ->
`dotnet build` succeeds; `which uv` returns nothing; `ms-python.python`
not installed.
- [ ] Open `Python.code-workspace` -> Reopen in Container -> "python" ->
`cd PyPiLibrary && uv sync && uv run pytest` succeeds; `which dotnet`
returns nothing; Ruff extension log shows interpreter at the container
venv path.
- [ ] Confirm CI green on this PR (csharpier check + dotnet format
--verify-no-changes; ruff check + ruff format --check + pyright).
- [ ] Push a deliberately mis-formatted `.cs` file on a throwaway branch
-> .NET pipeline fails on csharpier; same with a `.py` file -> Python
pipeline fails on ruff. (Verifies the lint backstop without hooks.)
- [ ] Confirm `.git/hooks/pre-commit` does not exist after a fresh clone
+ devcontainer rebuild.
ptr727 added a commit that referenced this pull request May 11, 2026
…me (#66)

Release merge: brings five squashed PRs from develop into main.

## Squashed PRs included

- **#61 — Pin release action SHA, target_commitish, agent conventions.**
`softprops/action-gh-release` pinned to a commit SHA with
`target_commitish: ${{ github.sha }}` so the release tag lands on the
artifact's commit, not the default branch. Updated `AGENTS.md` workflow
YAML conventions.
- **#62 — Rename Library project to NuGetLibrary.** Project + folder
renamed; `.slnx`, `.csproj`, build workflow, and references updated.
Disambiguates from the new Python sibling.
- **#63 — Add devcontainer + per-OS host and SSH signing docs.** New
`docs/host-setup.md`, `docs/ssh-signing.md`, `docs/devcontainer.md`.
Devcontainer bind-mounts SSH public key, allowed_signers, and `gh`
config so commits sign correctly inside the container.
- **#64 — Add PyPiLibrary Python sibling project.** New `PyPiLibrary/`
template under `src/`-layout: pyproject.toml + uv.lock +
ruff/pyright/pytest config + sample module + tests +
`build-pypilibrary-task.yml` workflow + `publish-pypi` job in
`publish-release.yml`.
- **#65 — Split Devcontainer and Workspace per Language and Drop
Husky.** `.devcontainer/dotnet/` + `DotNet.code-workspace` and
`.devcontainer/python/` + `Python.code-workspace`. Husky.Net removed (CI
is the lint backstop). Optional opt-in hooks documented in README. All
Husky references removed from workflows, AGENTS, CODESTYLE, and tasks.

## Notes

- Merge method: **merge-commit** (per [AGENTS.md branching
model](https://github.com/ptr727/ProjectTemplate/blob/develop/AGENTS.md#branching-model)).
Squash and rebase are blocked by the main ruleset.
- Main currently has 6 codegen-update commits that develop doesn't have
(#58, #59, #60 etc.). The merge-commit re-anchors develop on top of
those; the next develop cycle will start by merging main back into
develop to absorb them.

## Test plan

- [ ] CI passes on the merge commit (test-release-task workflow, all
build matrix legs).
- [ ] Confirm release tag lands on the merge commit (target_commitish
from #61).
- [ ] Spot-check the new `.devcontainer/dotnet/` and
`.devcontainer/python/` open and build cleanly.
- [ ] Spot-check `cd PyPiLibrary && uv sync && uv run pytest` passes.
- [ ] Confirm `.git/hooks/pre-commit` is absent in a fresh clone (Husky
removed).
ptr727 added a commit that referenced this pull request Jul 25, 2026
Slice 4 of the lint-only language type work. Applies the model to the
config repos and records the devcontainer convention.

## What

- **Reclassify `ESPHome-Config`** in the registry: `source-only` ->
`source-only + python(lint-only) + cpp(lint-only)`, with a `profiles`
map and a driftNote (lint-only python codegen + cpp headers;
clang-format not yet added). Now that the type model supports lint-only
languages, its codegen tooling draws **no** spurious codecov findings
(the `CODECOV_TOKEN` DEFECT and `codecov.yml` LETTER a naive `+python`
produced are gone - verified).
- **Devcontainer convention** in `section-model.md`: a devcontainer is
optional and not required by any type. An operational live-config repo
is edited/deployed live and its Devcontainer section states none; a repo
that keeps one (a toolchain, or an offline-debug aid) describes it.

## Not this PR

`HomeAssistant-Config` needs **no** reclassification - it is pure YAML
config (no python/cpp), correctly `source-only`. Its convergence is
downstream (a shared issue). ESPHome-Config's own AGENTS re-vendor debt
is likewise downstream (#65).

## Verification

`spec/validate.py` OK; a live audit of ESPHome-Config with the
reclassification shows zero codecov findings.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants