mirror of
https://github.com/github/awesome-copilot.git
synced 2026-07-14 01:51:02 +00:00
Migrate extension metadata to plugin.json and enforce conventions (#2177)
* Remove pluginRoots property from marketplace.json The pluginRoots property is not used by install tooling and was only informational about the extension/plugin source directories. Removing it simplifies the marketplace.json structure while maintaining all functionality. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Migrate java-modernization-studio to plugin.json and update validation workflow - Create .github/plugin/plugin.json for java-modernization-studio extension - Remove legacy canvas.json from java-modernization-studio - Update validate-canvas-extensions.yml workflow to check for plugin.json instead of canvas.json - Update workflow to trigger on .schemas/plugin.schema.json changes (instead of canvas.schema.json) - Remove schema validation logic that relied on canvas.schema.json - All 12 extensions now use plugin.json for metadata Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Add extensions field to all extension plugin.json files Per https://github.com/github/copilot-agent-runtime/pull/9929, plugins that ship extensions need to include an extensions field specifying where the extension code is located. All 12 extensions now have extensions set to '.' to reference the current directory where extension.mjs is located. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Enforce convention-based extension metadata and remove x-awesome-copilot - Remove x-awesome-copilot.screenshots from all extension plugin.json files - Enforce logo=assets/preview.png convention for all extensions - Enforce extensions=. per copilot-agent-runtime#9929 - Update validate-plugins.mjs to enforce conventions - Update validate-canvas-extensions.yml workflow with convention checks - Update AGENTS.md and CONTRIBUTING.md documentation All 12 extensions validated successfully. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> * Use standard plugin validation for extensions Remove the custom extension schema and schema validation helper, and validate extension plugin.json files through the existing plugin validator instead. Update workflows to stop depending on the removed schema. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -6,7 +6,6 @@ on:
|
||||
types: [opened, synchronize, reopened]
|
||||
paths:
|
||||
- "extensions/**"
|
||||
- ".schemas/canvas.schema.json"
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@@ -29,110 +28,7 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: npm ci --ignore-scripts
|
||||
|
||||
- name: Validate changed canvas extensions
|
||||
- name: Validate changed extensions
|
||||
run: |
|
||||
set -euo pipefail
|
||||
|
||||
# Validate schema structure once, even for schema-only PRs.
|
||||
if ! node ./eng/validate-json-schema.mjs --schema .schemas/canvas.schema.json; then
|
||||
echo "❌ .schemas/canvas.schema.json failed schema compilation"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Collect changed extension directories.
|
||||
# Use null-terminated (-z) output from git diff so filenames containing newlines
|
||||
# or other special characters are read atomically (matches the pattern in skill-check.yml).
|
||||
# Each extracted name is then validated against a strict allowlist regex before use,
|
||||
# rejecting anything containing shell metacharacters ($, (, ), spaces, etc.).
|
||||
declare -A seen_dirs=()
|
||||
changed_extensions=()
|
||||
errors=()
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
case "$file" in
|
||||
extensions/*)
|
||||
ext_name="${file#extensions/}"
|
||||
ext_name="${ext_name%%/*}"
|
||||
|
||||
if [ "$ext_name" = "external-assets" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# Allowlist: extension directory names must be lowercase alphanumeric + hyphens only.
|
||||
# Fail for disallowed names so a PR cannot bypass validation by using a nonconforming folder.
|
||||
if [[ ! "$ext_name" =~ ^[a-z0-9][a-z0-9-]*$ ]]; then
|
||||
errors+=("\`extensions/$ext_name\`: invalid extension directory name (must match ^[a-z0-9][a-z0-9-]*$).")
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ -z "${seen_dirs[$ext_name]+x}" ]; then
|
||||
seen_dirs["$ext_name"]=1
|
||||
changed_extensions+=("extensions/$ext_name")
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
done < <(git diff --name-only -z "origin/${{ github.base_ref }}...HEAD")
|
||||
|
||||
if [ "${#changed_extensions[@]}" -eq 0 ]; then
|
||||
if [ "${#errors[@]}" -ne 0 ]; then
|
||||
echo "❌ Canvas extension validation failed:"
|
||||
for error in "${errors[@]}"; do
|
||||
echo "- $error"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
echo "No canvas extension directories changed — skipping validation."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Validating ${#changed_extensions[@]} extension(s): ${changed_extensions[*]}"
|
||||
|
||||
for ext_dir in "${changed_extensions[@]}"; do
|
||||
if [ ! -d "$ext_dir" ]; then
|
||||
echo "$ext_dir no longer exists (deleted?), skipping."
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -f "$ext_dir/extension.mjs" ]; then
|
||||
errors+=("\`$ext_dir\`: missing required \`extension.mjs\`.")
|
||||
fi
|
||||
|
||||
if [ ! -f "$ext_dir/canvas.json" ]; then
|
||||
errors+=("\`$ext_dir\`: missing required \`canvas.json\`.")
|
||||
continue
|
||||
fi
|
||||
|
||||
if [ ! -f "$ext_dir/assets/preview.png" ]; then
|
||||
errors+=("\`$ext_dir\`: missing required \`assets/preview.png\`.")
|
||||
fi
|
||||
|
||||
if ! schema_output="$(node ./eng/validate-json-schema.mjs --schema .schemas/canvas.schema.json --data "$ext_dir/canvas.json" 2>&1)"; then
|
||||
condensed_output="$(echo "$schema_output" | tr '\n' ' ' | sed 's/[[:space:]]\+/ /g')"
|
||||
errors+=("\`$ext_dir/canvas.json\`: schema validation failed against \`.schemas/canvas.schema.json\` ($condensed_output).")
|
||||
continue
|
||||
fi
|
||||
|
||||
mapfile -t screenshot_paths < <(
|
||||
node -e 'const fs = require("fs"); const manifest = JSON.parse(fs.readFileSync(process.argv[1], "utf8")); const paths = [manifest?.screenshots?.icon?.path, manifest?.screenshots?.gallery?.path].filter((value) => typeof value === "string" && value.trim().length > 0); for (const value of [...new Set(paths)]) { console.log(value); }' "$ext_dir/canvas.json"
|
||||
)
|
||||
|
||||
for screenshot_path in "${screenshot_paths[@]}"; do
|
||||
if [[ ! "$screenshot_path" =~ ^assets/([A-Za-z0-9_-]+/)*[A-Za-z0-9_-]+(\.[A-Za-z0-9_-]+)*\.(png|jpe?g|gif|webp|svg)$ ]]; then
|
||||
errors+=("\`$ext_dir/canvas.json\`: screenshot path \`$screenshot_path\` is not a valid assets path.")
|
||||
continue
|
||||
fi
|
||||
if [ ! -f "$ext_dir/$screenshot_path" ]; then
|
||||
errors+=("\`$ext_dir/canvas.json\`: screenshot path \`$screenshot_path\` does not exist in the extension directory.")
|
||||
fi
|
||||
done
|
||||
done
|
||||
|
||||
if [ "${#errors[@]}" -ne 0 ]; then
|
||||
echo "❌ Canvas extension validation failed:"
|
||||
for error in "${errors[@]}"; do
|
||||
echo "- $error"
|
||||
done
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "✅ All changed canvas extensions passed validation."
|
||||
npm run plugin:validate
|
||||
Reference in New Issue
Block a user