Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion agentic-marketplace/discover/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,58 @@ runs:
fi

echo "Discovering components..."
if ! OUTPUT=$(node "$SCRIPT_PATH" discover-all 2>&1); then
DISCOVER_STDERR=$(mktemp)
if ! OUTPUT=$(node "$SCRIPT_PATH" discover-all 2>"$DISCOVER_STDERR"); then
echo "ERROR: Discovery failed" >&2
cat "$DISCOVER_STDERR" >&2
echo "$OUTPUT" >&2
rm -f "$DISCOVER_STDERR"
exit 1
fi
# Show diagnostic messages in CI logs
if [ -s "$DISCOVER_STDERR" ]; then
cat "$DISCOVER_STDERR"
fi
rm -f "$DISCOVER_STDERR"

# Output for other steps
echo "components<<EOF" >> $GITHUB_OUTPUT
echo "$OUTPUT" >> $GITHUB_OUTPUT
echo "EOF" >> $GITHUB_OUTPUT

# Write job summary
if [ -n "$GITHUB_STEP_SUMMARY" ]; then
SKILLS=$(node -e "console.log(JSON.parse(process.argv[1]).skills.length)" "$OUTPUT")
COMMANDS=$(node -e "console.log(JSON.parse(process.argv[1]).commands.length)" "$OUTPUT")
AGENTS=$(node -e "console.log(JSON.parse(process.argv[1]).agents.length)" "$OUTPUT")
SKIPPED=$(node -e "console.log(JSON.parse(process.argv[1]).skipped?.length ?? 0)" "$OUTPUT")
SKIPPED_LIST=$(node -e "
const s = JSON.parse(process.argv[1]).skipped || [];
s.forEach(p => console.log('- \`' + p + '\`'));
" "$OUTPUT")

{
echo "### Discover"
echo ""
echo "| Component | Count |"
echo "|-----------|------:|"
echo "| Skills | $SKILLS |"
echo "| Commands | $COMMANDS |"
echo "| Agents | $AGENTS |"
if [ "$SKIPPED" -gt 0 ]; then
echo ""
echo "> [!WARNING]"
echo "> $SKIPPED file(s) skipped (no frontmatter)"
echo ""
echo "<details><summary>Skipped files</summary>"
echo ""
echo "$SKIPPED_LIST"
echo ""
echo "</details>"
fi
} >> "$GITHUB_STEP_SUMMARY"
fi

echo "✓ Discovery complete"

branding:
Expand Down
55 changes: 55 additions & 0 deletions agentic-marketplace/generate/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,64 @@ runs:
exit 1
fi

MARKETPLACE_FILE=".claude-plugin/marketplace.json"

# Save existing marketplace.json for comparison
if [ -f "$MARKETPLACE_FILE" ]; then
BEFORE=$(cat "$MARKETPLACE_FILE")
HAD_FILE=true
else
BEFORE=""
HAD_FILE=false
fi

echo "Generating marketplace files..."
node "$SCRIPT_PATH" generate

# Write job summary
if [ -n "$GITHUB_STEP_SUMMARY" ]; then
if [ -f "$MARKETPLACE_FILE" ]; then
AFTER=$(cat "$MARKETPLACE_FILE")
else
AFTER=""
fi

{
echo "### Generate"
echo ""

if [ "$HAD_FILE" = "false" ] && [ -n "$AFTER" ]; then
echo "📄 **New file** — \`$MARKETPLACE_FILE\`"
echo ""
echo "<details><summary>marketplace.json</summary>"
echo ""
echo '```json'
echo "$AFTER"
echo '```'
echo ""
echo "</details>"
elif [ "$BEFORE" = "$AFTER" ]; then
echo "No changes to \`$MARKETPLACE_FILE\`"
else
PLUGIN_LIST=$(node -e "
const m = JSON.parse(process.argv[1]);
m.plugins.forEach(p => console.log('- **' + p.name + '** (' + p.category + '): ' + p.description));
" "$AFTER")
echo "📦 **Updated** \`$MARKETPLACE_FILE\`"
echo ""
echo "$PLUGIN_LIST"
echo ""
echo "<details><summary>Full marketplace.json</summary>"
echo ""
echo '```json'
echo "$AFTER"
echo '```'
echo ""
echo "</details>"
fi
} >> "$GITHUB_STEP_SUMMARY"
fi

echo "✓ Generation complete"

branding:
Expand Down
37 changes: 32 additions & 5 deletions agentic-marketplace/validate/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,20 +42,47 @@ runs:

echo "Validating components..."

if node "$SCRIPT_PATH" validate; then
VALIDATE_OUTPUT=$(node "$SCRIPT_PATH" validate 2>&1) && VALID=true || VALID=false

# Echo output to logs as before
echo "$VALIDATE_OUTPUT"

if [ "$VALID" = "true" ]; then
echo "valid=true" >> $GITHUB_OUTPUT
echo "errors=[]" >> $GITHUB_OUTPUT
echo "✓ All components valid"
exit 0
else
echo "valid=false" >> $GITHUB_OUTPUT
echo "✗ Validation failed"
fi

if [ "$FAIL_ON_ERROR" = "true" ]; then
exit 1
# Write job summary
if [ -n "$GITHUB_STEP_SUMMARY" ]; then
if [ "$VALID" = "true" ]; then
ICON="✅"
STATUS="passed"
else
exit 0
ICON="❌"
STATUS="failed"
fi

{
echo "### Validate"
echo ""
echo "$ICON Validation **$STATUS**"
echo ""
echo "<details><summary>Full output</summary>"
echo ""
echo '```'
echo "$VALIDATE_OUTPUT"
echo '```'
echo ""
echo "</details>"
} >> "$GITHUB_STEP_SUMMARY"
fi

if [ "$VALID" = "false" ] && [ "$FAIL_ON_ERROR" = "true" ]; then
exit 1
fi

branding:
Expand Down
12 changes: 8 additions & 4 deletions scripts/dist/discover-components.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -7335,7 +7335,7 @@ function loadConfig() {
process.exit(1);
}
}
console.log("No generator.config.toml or .json found, using defaults");
console.error("No generator.config.toml or .json found, using defaults");
return defaults;
}
function validateAndMergeConfig(defaults, config) {
Expand Down Expand Up @@ -7417,6 +7417,7 @@ function discoverMarkdownComponents(rootDir, config) {
const commands = [];
const agents = [];
const errors = [];
const skipped = [];
const absoluteRoot = path.resolve(rootDir);
function shouldExcludePath(relPath) {
const pathParts = relPath.split(path.sep);
Expand Down Expand Up @@ -7467,15 +7468,17 @@ function discoverMarkdownComponents(rootDir, config) {
commands.push(classified.path);
} else if (classified.type === "agent") {
agents.push(classified.path);
} else if (!classified.skipped) {
} else if (classified.skipped) {
skipped.push(fullPath);
} else {
errors.push({ path: fullPath, error: classified.error });
}
}
}
}
}
walk(absoluteRoot, 0);
return { skills, commands, agents, errors };
return { skills, commands, agents, errors, skipped };
}
function discoverHooksFiles(rootDir, config) {
const { excludeDirs, excludePatterns, maxDepth } = config.discovery;
Expand Down Expand Up @@ -7833,7 +7836,8 @@ function discoverAllComponents(rootDir, config) {
mcpServers: mcpResult.servers,
hooksFiles,
mcpFiles,
errors: allErrors
errors: allErrors,
skipped: mdComponents.skipped
};
}
function getCategoryNames(config) {
Expand Down
12 changes: 8 additions & 4 deletions scripts/src/discover-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ function loadConfig() {
}

// No config file found - use defaults
console.log('No generator.config.toml or .json found, using defaults');
console.error('No generator.config.toml or .json found, using defaults');
return defaults;
}

Expand Down Expand Up @@ -293,6 +293,7 @@ function discoverMarkdownComponents(rootDir, config) {
const commands = [];
const agents = [];
const errors = [];
const skipped = [];
const absoluteRoot = path.resolve(rootDir);

function shouldExcludePath(relPath) {
Expand Down Expand Up @@ -354,7 +355,9 @@ function discoverMarkdownComponents(rootDir, config) {
commands.push(classified.path);
} else if (classified.type === 'agent') {
agents.push(classified.path);
} else if (!classified.skipped) {
} else if (classified.skipped) {
skipped.push(fullPath);
} else {
// Unclassified component with frontmatter - add to errors
errors.push({ path: fullPath, error: classified.error });
}
Expand All @@ -364,7 +367,7 @@ function discoverMarkdownComponents(rootDir, config) {
}

walk(absoluteRoot, 0);
return { skills, commands, agents, errors };
return { skills, commands, agents, errors, skipped };
}

/**
Expand Down Expand Up @@ -1031,7 +1034,8 @@ function discoverAllComponents(rootDir, config) {
mcpServers: mcpResult.servers,
hooksFiles,
mcpFiles,
errors: allErrors
errors: allErrors,
skipped: mdComponents.skipped
};
}

Expand Down
54 changes: 54 additions & 0 deletions scripts/test/discover-components.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const assert = require('assert');
const {
loadConfig,
classifyComponent,
discoverMarkdownComponents,
discoverAllComponents,
getCategoryNames,
groupIntoPlugins,
Expand Down Expand Up @@ -392,6 +393,59 @@ test('.md with explicit type in frontmatter takes priority', () => {
});
});

// --- skipped array ---

console.log('\nskipped array');

// Full config needed for discovery functions (defaultConfig lacks excludeDirs etc.)
const discoveryConfig = {
discovery: {
skillFilename: 'SKILL.md',
commandsDir: 'commands',
agentsDir: 'agents',
excludeDirs: ['.git', 'node_modules'],
excludePatterns: [],
maxDepth: 10
}
};

test('discoverMarkdownComponents returns skipped array for frontmatterless files', () => {
withTempDir((tmpDir) => {
// Create a .md file with no frontmatter (not in commands/agents/skills, not SKILL.md)
fs.writeFileSync(path.join(tmpDir, 'notes.md'), '# Just notes\n\nNo frontmatter.\n');
// Create a valid skill for contrast
fs.writeFileSync(path.join(tmpDir, 'SKILL.md'), '---\nname: test-skill\ndescription: A test\n---\nContent\n');

const result = discoverMarkdownComponents(tmpDir, discoveryConfig);
assert(Array.isArray(result.skipped), 'skipped should be an array');
assert.strictEqual(result.skipped.length, 1, 'should have 1 skipped file');
assert(result.skipped[0].endsWith('notes.md'), 'skipped file should be notes.md');
assert.strictEqual(result.skills.length, 1, 'should still find the skill');
});
});

test('discoverAllComponents propagates skipped array', () => {
withTempDir((tmpDir) => {
// Create a .md file with no frontmatter
fs.writeFileSync(path.join(tmpDir, 'planning.md'), '# Planning doc\n\nNo frontmatter.\n');

const result = discoverAllComponents(tmpDir, discoveryConfig);
assert(Array.isArray(result.skipped), 'skipped should be an array');
assert.strictEqual(result.skipped.length, 1, 'should have 1 skipped file');
assert(result.skipped[0].endsWith('planning.md'), 'skipped file should be planning.md');
});
});

test('discoverMarkdownComponents returns empty skipped array when all files have frontmatter', () => {
withTempDir((tmpDir) => {
fs.writeFileSync(path.join(tmpDir, 'SKILL.md'), '---\nname: test-skill\ndescription: A test\n---\nContent\n');

const result = discoverMarkdownComponents(tmpDir, discoveryConfig);
assert(Array.isArray(result.skipped), 'skipped should be an array');
assert.strictEqual(result.skipped.length, 0, 'should have no skipped files');
});
});

// --- Summary ---

console.log(`\n${passed + failed} tests: ${passed} passed, ${failed} failed`);
Expand Down