Skip to content

Split plugins/external.json into per-plugin files for CODEOWNERS support#1245

Open
tmeschter wants to merge 1 commit intogithub:stagedfrom
tmeschter:260331-SplitExternalJson
Open

Split plugins/external.json into per-plugin files for CODEOWNERS support#1245
tmeschter wants to merge 1 commit intogithub:stagedfrom
tmeschter:260331-SplitExternalJson

Conversation

@tmeschter
Copy link
Copy Markdown
Contributor

Split the monolithic plugins/external.json into individual files under plugins/external/ (one JSON file per external plugin) to enable per-file CODEOWNERS entries.

Changes

New files (8): Individual JSON files in plugins/external/:

  • azure.json, dataverse.json, dotnet.json, dotnet-diag.json, figma.json, microsoft-docs.json, modernize-dotnet.json, skills-for-copilot-studio.json

Deleted: plugins/external.json

Updated scripts (7) - all now read from the directory and exclude plugins/external/ from plugin directory scanning:

  • eng/generate-marketplace.mjs - reads individual files from directory instead of single array file
  • eng/generate-website-data.mjs - same directory-based reading
  • eng/update-readme.mjs - excludes external dir from plugin scanning
  • eng/clean-materialized-plugins.mjs - excludes external dir
  • eng/materialize-plugins.mjs - excludes external dir
  • eng/update-plugin-commands-to-skills.mjs - excludes external dir
  • eng/validate-plugins.mjs - excludes external dir

Updated docs (3):

  • CODEOWNERS - per-file ownership entries based on git history
  • CONTRIBUTING.md - updated external plugin instructions to reference new directory structure
  • AGENTS.md - same update

Validation

  • npm run build passes cleanly: 62 plugins (54 local + 8 external)
  • npm run plugin:validate passes: all 54 local plugins valid
  • marketplace.json output includes all 8 external plugins

Split the monolithic plugins/external.json into individual files under
plugins/external/ (one per external plugin) to support per-file CODEOWNERS
entries. Updated all scripts that scan the plugins directory to exclude
the new external/ subdirectory and read individual JSON files instead.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings March 31, 2026 16:29
@tmeschter tmeschter requested a review from aaronpowell as a code owner March 31, 2026 16:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Splits the external plugin registry from a single plugins/external.json file into per-plugin JSON files under plugins/external/ to enable granular CODEOWNERS ownership and updates build/validation scripts to load external plugins from the new directory.

Changes:

  • Added 8 per-plugin external manifests under plugins/external/ and removed plugins/external.json
  • Updated marketplace/website generation scripts to read external plugins from the new directory layout
  • Updated plugin-scanning scripts and docs/CODEOWNERS to account for the external/ directory structure

Reviewed changes

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

Show a summary per file
File Description
plugins/external/azure.json New per-plugin external manifest (Azure)
plugins/external/dataverse.json New per-plugin external manifest (Dataverse)
plugins/external/dotnet.json New per-plugin external manifest (.NET)
plugins/external/dotnet-diag.json New per-plugin external manifest (.NET diagnostics)
plugins/external/figma.json New per-plugin external manifest (Figma)
plugins/external/microsoft-docs.json New per-plugin external manifest (Microsoft Docs)
plugins/external/modernize-dotnet.json New per-plugin external manifest (Modernize .NET)
plugins/external/skills-for-copilot-studio.json New per-plugin external manifest (Copilot Studio skills)
plugins/external.json Removed monolithic external plugins array file
eng/generate-marketplace.mjs Read/validate external plugins from directory of per-plugin JSON files; exclude external/ from local scanning
eng/generate-website-data.mjs Read external plugins from plugins/external/ directory instead of external.json
eng/update-readme.mjs Exclude plugins/external/ from local plugin directory scanning
eng/validate-plugins.mjs Exclude plugins/external/ from local plugin directory scanning
eng/materialize-plugins.mjs Exclude plugins/external/ from local plugin directory scanning
eng/clean-materialized-plugins.mjs Exclude plugins/external/ from local plugin directory scanning
eng/update-plugin-commands-to-skills.mjs Exclude plugins/external/ from local plugin directory scanning
CONTRIBUTING.md Updated external plugin contribution instructions to per-file manifests
AGENTS.md Updated external plugin workflow instructions to per-file manifests
CODEOWNERS Added per-external-plugin ownership entries

Comment on lines +72 to +76
if (typeof plugin !== "object" || Array.isArray(plugin)) {
console.error(`Error: external/${file} must contain a single JSON object`);
hasErrors = true;
continue;
}
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

typeof null === "object", so a file containing null will pass this check and then validateExternalPlugin(plugin, file) will throw when accessing plugin.name. Update the guard to explicitly reject null (and ideally any non-plain-object values) before calling validation.

Copilot uses AI. Check for mistakes.
const pluginDirs = fs
.readdirSync(PLUGINS_DIR, { withFileTypes: true })
.filter((d) => d.isDirectory())
.filter((d) => d.isDirectory() && d.name !== "external")
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

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

The "external" directory exclusion is duplicated across multiple scripts in this PR. Consider centralizing the directory name (e.g., a shared constant in eng/constants.mjs) or a small helper (e.g., isPluginDirEntry(entry)) to avoid drift if the folder name or exclusion rules change again.

Copilot uses AI. Check for mistakes.
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