Skip to content

feat: generate README plugin docs with an MSBuild C# task - #38

Merged
jkdevito merged 7 commits into
git-config-updatesfrom
feature/msbuild-readme-docs
Oct 2, 2026
Merged

jkdevito merged 7 commits into
git-config-updatesfrom
feature/msbuild-readme-docs

Conversation

@jkdevito

@jkdevito jkdevito commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Moves README plugin-documentation generation (config example, supported types, join maps, base classes, interfaces, public methods, feedbacks) into the build. Previously it ran Python metadata.py plus a PowerShell script; now it is a C# MSBuild task, so it works on Windows and macOS with only the .NET SDK. It builds on the MSBuild badge generation already in git-config-updates.

What changed

  • build/ReadmeDocs.cs: C# port of metadata.py (workflow-templates 681f68e) plus the template's post-processing. RoslynCodeTaskFactory compiles it at build time; it sits outside src/, so it is never part of the plugin.
  • src/Directory.Build.targets:
    • UpdateReadmeDocs regenerates the docs. Run dotnet msbuild -t:UpdateReadmeDocs or the VS Code task "Update README docs", then review and commit.
    • CheckReadmeDocs: CI builds (CI=true) regenerate in memory and fail with PDREADME005 when README.md is stale.
    • Badge and docs targets now share one source list.
  • Brings in the docs commit from feature/local-readme-docs, copied rather than rebased, so that branch's history is untouched. That commit reorganizes the README, adds the update-readme-docs skill, and removes the robot-docs workflow caller.
  • Removes Update-ReadmeDocs.ps1, so Python and pwsh are no longer required anywhere.
  • Updates the README, the VS Code task and the skill.
  • Commits the copyright year (2026) and removes stray blank lines in MakeModelDevice.cs.

Why

  • Not every Windows machine has Python; some only have it inside VMs or containers. The .NET SDK is already required to build any repo created from this template.
  • The output is now deterministic. metadata.py used file-system order and an unordered set, so Supported Types could reorder between runs.
  • Renamed factories and join maps keep working. Detection is content-based, so a factory renamed to SonyBraviaDeviceFactory, or a join map whose file doesn't match its class name, is still found.

Differences from metadata.py output

The output matches metadata.py byte for byte, except for these intentional changes:

  • Minimum Essentials Framework Versions lists each distinct version once, instead of once per factory. The <!-- SKIP --> workaround that had frozen this section at 2.12.1 is removed.
  • Join maps are also found by class declaration, when the file isn't named <ClassName>.cs. metadata.py silently left the section empty in these cases.
  • Interfaces detection is case-sensitive. The old PowerShell post-processing classified IpTableObjectBase as an interface.
  • Base Classes come before Interfaces and are plain list items, not code-formatted.

Testing

  • Parity: the C# task and the reference pipeline (metadata.py with sorted directory traversal, plus the old post-processing) were run on 31 local plugin repos, including Essentials, epi-crestron-nvx and epi-qsc-qsysdsp.
    • 22 produce identical output.
    • The other 9 differ only in the intentional changes above.
    • Join maps were recovered in epi-1beyond-automate-vx (47 rows), epi-qsc-qsysdsp (68), epi-megapixel-helios (28), epi-crestron-iptable_editor (6) and epi-optisigns-graphql (3). No existing row changed.
  • Template, on macOS:
    • An added public method makes dotnet build -p:CI=true fail with PDREADME005; after UpdateReadmeDocs, it passes.
    • A normal build never runs the docs generator.
    • A README with CRLF line endings passes the check and keeps its line endings after an update.
    • Running from the solution or the repo root works.
  • Renames, tested on a scratch copy:
    • MakeModelDeviceFactory became SonyBraviaDeviceFactory.
    • A factory file became Factories.cs.
    • The join map moved to JoinMap.cs.
    • Badges, versions, join maps and base classes stayed correct.
  • Staged snapshot: built on its own with -p:CI=true, it passed.

Notes for reviewers

  • Not yet tested on Windows or Visual Studio. Please build there once. The inline tasks target netstandard2.0 / C# 7.3, so they should compile under VS's .NET Framework MSBuild, but that hasn't been confirmed.
  • Config Example type is the first TypeNames entry in the first file, sorted by name, that sets TypeNames. For a different type, edit the section and mark it <!-- SKIP -->.
  • Two implementations: metadata.py in workflow-templates is still used by the legacy update-readme.yml for other plugins. From now on, a fix in one won't reach the other automatically.
  • CI coverage: CI only runs the check in the release build, when getVersion reports a new version. Ordinary pushes aren't checked.

🤖 Generated with Claude Code

jkdevito and others added 5 commits October 1, 2026 17:03
Add Update-ReadmeDocs.ps1, a VS Code task and an update-readme-docs skill to generate plugin docs locally. Remove the robot-docs CI caller.
Replace the Python metadata.py + PowerShell pipeline with build/ReadmeDocs.cs,
compiled by RoslynCodeTaskFactory and run by the UpdateReadmeDocs target
(dotnet msbuild -t:UpdateReadmeDocs). Only the .NET SDK is required and it
runs offline. CI builds (CI=true) regenerate the sections in memory and fail
with PDREADME005 when README.md is stale.

The port matches metadata.py output except that it is deterministic, lists
each Minimum Essentials Framework Version once, finds factories and join maps
by content rather than file name (recovering join maps metadata.py skipped),
classifies IpTableObjectBase-style names correctly, and lists Base Classes
before Interfaces as plain items. Badges now read
MinimumEssentialsFrameworkVersion from any project C# file, so factories can
be renamed freely.

Remove Update-ReadmeDocs.ps1 and update the README, VS Code task and the
update-readme-docs skill.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Copyright: README heading 2026, LICENSE "2020-2026" (placeholder brackets
  removed); the csproj no longer overrides the props copyright
- csproj keeps only plugin-specific values; shared Version, Company, Authors
  and Copyright come from Directory.Build.props. PackageId uses "PepperDash"
  casing, PackageProjectUrl drops ".git", PackageTags are set once, and the
  duplicate hard-coded .cplz None Remove lines are removed
- Remove the uncompiled Properties/AssemblyInfo.cs and empty ControlSystem.cfg
  and .gitmodules
- Factory and class doc comments: rename examples use the current class
  names, valid MinimumEssentialsFrameworkVersion examples, per-category
  TypeNames examples, and correct BuildDevice summaries; fix ASCII,
  delimiter and TODO typos
- Docs: README, skill, generator header and commit-msg hook comment describe
  the generator's actual differences from metadata.py and CI behavior

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…axis

Placeholders:
- Replace the remaining EssentialsPluginTemplate names: the join map class is
  MakeModelBridgeJoinMap, Product/Description say "Make Model", and the
  repository URLs use the epi-make-model placeholder
- Namespace and RootNamespace are PepperDash.Essentials.Plugins.MakeModel;
  AssemblyTitle and PackageId are PepperDash.Essentials.Plugins.Make.Model
- Rename MakeModelConfigObject.cs to MakeModelPropertiesConfig.cs, with the
  classes MakeModelPropertiesConfig and MakeModelPropertiesConfigDictionary
- Drop "template" from PackageTags

README:
- Organize the hand-written sections as Tutorial, How-to guides, Reference
  and Explanation; the tutorial was verified end to end on a scratch clone
- Add reference tables for the repository layout, placeholder names, build
  outputs, targets, properties, PDREADME error codes, badges and generated
  sections
- Update the update-readme-docs skill for the renamed config class

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Copilot review overview

🟡 Changes recommended

The generator mishandles skipped sections, multiple minimum versions per file, and writable join capabilities.

Review effort: Balanced
Findings: 3 Medium severity

Open (3)
What changed in this PR

Moves README plugin-documentation generation into MSBuild while modernizing template naming and documentation.

Changes:

  • Adds the C# README generator and MSBuild update/check targets.
  • Reorganizes README guidance and removes the legacy workflow.
  • Normalizes namespaces, class names, and package metadata.
File Description
build/​ReadmeDocs.cs Implements documentation generation.
src/​Directory.Build.targets Adds README generation and validation targets.
src/​Directory.Build.props Updates shared package metadata.
README.md Adds comprehensive template and generated documentation.
.github/​skills/​update-readme-docs/​SKILL.md Adds README maintenance guidance.
.github/​workflows/​essentialsplugins-updatereadme-caller.yml Removes the legacy generation workflow.
.vscode/​tasks.json Adds the README update task.
.husky/​commit-msg Clarifies hook documentation.
src/​epi-make-model.4Series.csproj Updates namespace and package metadata.
src/​MakeModelPropertiesConfig.cs Renames and namespaces configuration types.
src/​MakeModelBridgeJoinMap.cs Renames and namespaces the join map.
src/​MakeModelDevice.cs Uses renamed configuration and join-map types.
src/​MakeModelDeviceFactory.cs Uses the renamed configuration type.
src/​MakeModelLogicDevice.cs Uses renamed template types.
src/​MakeModelLogicDeviceFactory.cs Uses the renamed configuration type.
src/​MakeModelCrestronDevice.cs Uses renamed template types.
src/​MakeModelCrestronDeviceFactory.cs Uses the renamed configuration type.
src/​Properties/​AssemblyInfo.cs Removes legacy manual assembly attributes.
LICENSE.md Updates the copyright range.
src/​Properties/​ControlSystem.cfg No substantive textual change shown.
.gitmodules No substantive textual change shown.

💡 Configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread build/ReadmeDocs.cs Outdated
Comment thread build/ReadmeDocs.cs Outdated
Comment thread build/ReadmeDocs.cs Outdated
jkdevito and others added 2 commits October 1, 2026 18:20
- Collect every MinimumEssentialsFrameworkVersion in a file (Matches), not just the first
- Render join access as R, W or R/W from JoinCapabilities instead of always R
- Document that SKIP still lets the Config Example's type and uid be updated

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Fill each property from the first <example><code> block containing its JSON name
- Default pollTimeMs, warningTimeoutMs and errorTimeoutMs to 30000, 180000 and 300000
- Use realistic key, name and group values
- Ignore <!-- SKIP --> in the Config Example so it always follows the code
- Fix the template config examples (pollTimeMs, control, DeviceDictionary)
- Document setting Config Example values in README and the update-readme-docs skill

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@jkdevito
jkdevito merged commit 784667e into git-config-updates Oct 2, 2026
2 checks passed
@jkdevito
jkdevito deleted the feature/msbuild-readme-docs branch October 2, 2026 00:37
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