fix(scripts): stop check-manifests passing on entries it cannot parse
A marketplace entry missing its source key disabled both directions of the check at once. The helper required source to be a string, so a source-less entry was skipped and its plugin.json existence check never ran; the name axis selected on (.source | type) != "string", and null != "string" is true, so the same entry also marked its on-disk directory as listed. Delete source from an entry and delete its plugin.json and the script exited 0. Because sync-plugin-content.sh --all derives its work list from the same helper, that plugin silently dropped out of the content-mirror gate too. Also in this pass: - a wrongly typed skills value crashed the script mid-loop with a raw jq error and no "Manifest check failed:" line, leaving every later plugin unchecked. Note skills is legally string|string[] per both host schemas, so a string now resolves as a single path rather than erroring - array- and object-valued pointer fields were reported missing even when they resolved, because the whole JSON value was pretty-printed into a path test - an unparseable marketplace.json died inside a process substitution, so the run reported six "no entry in marketplace.json" errors that sent the reader to edit apm.yml when the real fault was a corrupt manifest - a missing marketplace.json exited 0 even with plugin directories present Tests: 14 -> 23 assertions. Every failure case asserts on message text, not exit code alone, since exit 1 here is reachable by several causes that call for opposite fixes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X7GvKuJfy2WrdBmUttV4DT
This commit is contained in:
@@ -7,6 +7,44 @@
|
||||
#
|
||||
# Requires jq. Not meant to be executed directly -- source it.
|
||||
|
||||
# assert_marketplace_manifest_usable <marketplace_json_path>
|
||||
#
|
||||
# Checks the preconditions list_marketplace_local_plugins depends on but cannot
|
||||
# report on. Both callers run the walk inside a process substitution
|
||||
# (`done < <(list_marketplace_local_plugins ...)`), which is its own subshell: a
|
||||
# jq abort in there kills only that subshell, so an unparseable manifest yields
|
||||
# zero lines and reads exactly like "this marketplace declares no local plugins".
|
||||
# The caller then blames whatever its empty-set branch blames -- for
|
||||
# check-manifests.sh, every plugin directory on disk being unlisted.
|
||||
#
|
||||
# It also rejects an entry with no `source` at all. Such an entry is not a local
|
||||
# plugin (the walk below requires a string `source`) and not a remote one either,
|
||||
# so it silently drops out of every marketplace-derived work list -- this walk's
|
||||
# and, through it, sync-plugin-content.sh --all's.
|
||||
#
|
||||
# Exits 1 with a specific message on any violation, so call it from the caller's
|
||||
# own shell -- never inside `< <(...)`, which is the exact swallowing this guards.
|
||||
assert_marketplace_manifest_usable() {
|
||||
local marketplace="$1" plugins_type sourceless
|
||||
|
||||
if ! jq empty "$marketplace" >/dev/null 2>&1; then
|
||||
echo "Error: $marketplace is not valid JSON -- every marketplace-derived check reads as \"no plugins declared\" until it parses. Fix it, or recompile it with \`apm pack\`." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
plugins_type="$(jq -r '.plugins | type' "$marketplace")"
|
||||
if [[ "$plugins_type" != "array" && "$plugins_type" != "null" ]]; then
|
||||
echo "Error: $marketplace has a \`plugins\` field of type $plugins_type; expected an array of plugin entries." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sourceless="$(jq -r '[.plugins[]? | select(.source == null) | .name // "<unnamed>"] | join(", ")' "$marketplace")"
|
||||
if [[ -n "$sourceless" ]]; then
|
||||
echo "Error: $marketplace has entries with no \`source\` field: $sourceless. An entry without a \`source\` is neither local nor remote, so it is skipped by every marketplace-derived check while still claiming its name. Give it a \`source\` in root apm.yml's marketplace.packages[] and recompile." >&2
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# list_marketplace_local_plugins <repo_root> <marketplace_json_path>
|
||||
#
|
||||
# Prints one "<name>\t<absolute_plugin_dir>" line per local (string `source:`)
|
||||
|
||||
Reference in New Issue
Block a user