diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index ece080c..b050d88 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -8,12 +8,18 @@ "plugins": [ { "name": "sdlc", - "repository": "https://github.com/iamladi/cautious-computing-machine--sdlc-plugin", + "source": { + "source": "github", + "repo": "iamladi/cautious-computing-machine--sdlc-plugin" + }, "description": "Comprehensive SDLC plugin with specialized agents, commands, and integrations for enhanced software development workflow" }, { "name": "primitives", - "repository": "https://github.com/iamladi/cautious-computing-machine--primitives-plugin", + "source": { + "source": "github", + "repo": "iamladi/cautious-computing-machine--primitives-plugin" + }, "description": "Essential building blocks for Claude Code workflows - smart commits, debugging, PRs, and environment setup" } ] diff --git a/.github/workflows/validate-marketplace.yml b/.github/workflows/validate-marketplace.yml new file mode 100644 index 0000000..aae41a8 --- /dev/null +++ b/.github/workflows/validate-marketplace.yml @@ -0,0 +1,32 @@ +name: Validate Marketplace Schema + +on: + push: + branches: [main, master] + paths: + - '.claude-plugin/marketplace.json' + - '.github/workflows/validate-marketplace.yml' + pull_request: + branches: [main, master] + paths: + - '.claude-plugin/marketplace.json' + - '.github/workflows/validate-marketplace.yml' + +jobs: + validate: + runs-on: ubuntu-latest + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Setup Bun + uses: oven-sh/setup-bun@v1 + with: + bun-version: latest + + - name: Install dependencies + run: bun install + + - name: Validate marketplace.json schema + run: bun run validate diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1822831 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules/ +bun.lockb diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..b84b3c6 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,16 @@ +# Changelog + +## [1.0.1] - 2025-10-30 + +### Fixed +- Fixed marketplace.json schema validation errors by replacing `repository` fields with proper `source` objects following GitHub source format + +### Added +- GitHub Actions workflow for automated marketplace schema validation +- Validation script using Zod for schema enforcement +- CI/CD pipeline to validate marketplace.json on PRs and pushes + +## [1.0.0] - 2025-10-30 + +### Added +- Initial marketplace with sdlc and primitives plugins diff --git a/package.json b/package.json new file mode 100644 index 0000000..b179516 --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "name": "cautious-computing-machine", + "version": "1.0.0", + "description": "Claude Code plugins marketplace", + "private": true, + "type": "module", + "scripts": { + "validate": "bun run scripts/validate-marketplace.ts" + }, + "devDependencies": { + "@types/bun": "latest", + "zod": "^3.23.8" + } +} diff --git a/scripts/validate-marketplace.ts b/scripts/validate-marketplace.ts new file mode 100644 index 0000000..7efce88 --- /dev/null +++ b/scripts/validate-marketplace.ts @@ -0,0 +1,71 @@ +#!/usr/bin/env bun +import { z } from 'zod'; +import { readFile } from 'fs/promises'; +import { join } from 'path'; + +const GitHubSourceSchema = z.object({ + source: z.literal('github'), + repo: z.string().regex(/^[a-zA-Z0-9_-]+\/[a-zA-Z0-9_-]+$/, 'Invalid GitHub repo format (expected: owner/repo)'), +}); + +const UrlSourceSchema = z.object({ + source: z.literal('url'), + url: z.string().url(), +}); + +const RelativeSourceSchema = z.string().startsWith('./'); + +const SourceSchema = z.union([ + GitHubSourceSchema, + UrlSourceSchema, + RelativeSourceSchema, +]); + +const PluginSchema = z.object({ + name: z.string().regex(/^[a-z0-9-]+$/, 'Plugin name must be kebab-case'), + source: SourceSchema, + description: z.string().optional(), +}); + +const MarketplaceSchema = z.object({ + name: z.string(), + description: z.string().optional(), + owner: z.object({ + name: z.string(), + email: z.string().email().optional(), + url: z.string().url().optional(), + }), + plugins: z.array(PluginSchema), +}); + +async function validateMarketplace() { + const marketplacePath = join(process.cwd(), '.claude-plugin/marketplace.json'); + + try { + const content = await readFile(marketplacePath, 'utf-8'); + const json = JSON.parse(content); + + const result = MarketplaceSchema.safeParse(json); + + if (!result.success) { + console.error('❌ Marketplace validation failed:'); + console.error(JSON.stringify(result.error.format(), null, 2)); + process.exit(1); + } + + console.log('✅ Marketplace schema is valid'); + console.log(` Found ${result.data.plugins.length} plugins`); + + result.data.plugins.forEach(plugin => { + console.log(` - ${plugin.name}`); + }); + + } catch (error) { + if (error instanceof Error) { + console.error('❌ Error reading marketplace.json:', error.message); + } + process.exit(1); + } +} + +validateMarketplace();