Initial commit
This commit is contained in:
52
skills/contract-test-validator/SKILL.md
Normal file
52
skills/contract-test-validator/SKILL.md
Normal file
@@ -0,0 +1,52 @@
|
||||
---
|
||||
name: validating-api-contracts
|
||||
description: |
|
||||
This skill validates API contracts using consumer-driven testing and OpenAPI validation. It leverages Pact for consumer-driven contract testing, ensuring that API providers adhere to the expectations of their consumers. It also validates APIs against OpenAPI specifications to guarantee compliance and identify breaking changes. Use this skill when the user asks to generate contract tests, validate API responses, check backward compatibility, or validate requests/responses using the terms "contract-test", "ct", "Pact", "OpenAPI validation", or "consumer-driven contract testing".
|
||||
allowed-tools: Read, Write, Edit, Grep, Glob, Bash
|
||||
version: 1.0.0
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
This skill enables Claude to generate and validate API contracts, ensuring compatibility between API providers and consumers. It uses Pact for consumer-driven contract testing and OpenAPI validation for specification compliance.
|
||||
|
||||
## How It Works
|
||||
|
||||
1. **Generating Contract Tests**: Claude creates Pact consumer tests based on API usage, generating provider verification tests and building OpenAPI contract validators.
|
||||
2. **Validating Contracts**: The skill verifies if API responses match the defined contracts.
|
||||
3. **Checking Compatibility**: It checks for backward compatibility to identify breaking changes in the API.
|
||||
|
||||
## When to Use This Skill
|
||||
|
||||
This skill activates when you need to:
|
||||
- Generate contract tests for an API.
|
||||
- Validate API responses against existing contracts.
|
||||
- Identify breaking changes in an API.
|
||||
|
||||
## Examples
|
||||
|
||||
### Example 1: Generating Pact Contracts
|
||||
|
||||
User request: "Generate contract tests for my API using Pact."
|
||||
|
||||
The skill will:
|
||||
1. Analyze the API and generate Pact consumer contracts.
|
||||
2. Create provider verification tests based on the contracts.
|
||||
|
||||
### Example 2: Validating an OpenAPI Specification
|
||||
|
||||
User request: "Validate my API against the OpenAPI specification."
|
||||
|
||||
The skill will:
|
||||
1. Validate the API against the provided OpenAPI specification.
|
||||
2. Report any discrepancies or violations of the specification.
|
||||
|
||||
## Best Practices
|
||||
|
||||
- **Clarity**: Be specific when requesting contract generation or validation, providing relevant API details.
|
||||
- **Completeness**: Ensure that your OpenAPI specifications are up-to-date for accurate validation.
|
||||
- **Context**: Provide context about the consumer and provider roles when using Pact.
|
||||
|
||||
## Integration
|
||||
|
||||
This skill can be integrated with other testing and deployment tools in the Claude Code ecosystem to automate contract verification as part of a CI/CD pipeline.
|
||||
8
skills/contract-test-validator/assets/README.md
Normal file
8
skills/contract-test-validator/assets/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Assets
|
||||
|
||||
Bundled resources for contract-test-validator skill
|
||||
|
||||
- [ ] pact_contract_template.json: A template for creating Pact consumer contracts.
|
||||
- [ ] openapi_example.yaml: An example OpenAPI specification file.
|
||||
- [ ] report_template.html: A template for generating HTML reports of contract validation results.
|
||||
- [ ] config_template.yaml: A configuration template for setting up the contract testing environment.
|
||||
80
skills/contract-test-validator/assets/config_template.yaml
Normal file
80
skills/contract-test-validator/assets/config_template.yaml
Normal file
@@ -0,0 +1,80 @@
|
||||
# Configuration for the Contract Test Validator plugin.
|
||||
|
||||
# General settings
|
||||
general:
|
||||
# Enable or disable the plugin
|
||||
enabled: true
|
||||
# Log level (debug, info, warning, error, critical)
|
||||
log_level: info
|
||||
# Directory to store temporary files and reports.
|
||||
temp_dir: ./tmp/contract_tests # REPLACE_ME: Choose a suitable temporary directory
|
||||
# Fail fast. Stop on first error?
|
||||
fail_fast: false
|
||||
|
||||
# Pact settings
|
||||
pact:
|
||||
# Enable Pact contract testing
|
||||
enabled: true
|
||||
# Directory to store Pact files
|
||||
pact_dir: ./pacts # REPLACE_ME: Choose a directory for pact files
|
||||
# URL of the Pact Broker (optional)
|
||||
broker_url: YOUR_VALUE_HERE # e.g., https://pact-broker.example.com
|
||||
# Username for Pact Broker authentication (optional)
|
||||
broker_username: YOUR_VALUE_HERE
|
||||
# Password for Pact Broker authentication (optional)
|
||||
broker_password: YOUR_VALUE_HERE
|
||||
# Publish verification results to the Pact Broker
|
||||
publish_verification_results: false
|
||||
# Consumer version tag to use when publishing to the broker
|
||||
consumer_version_tag: main # REPLACE_ME: Specify the consumer version tag
|
||||
# Provider version tag to use when verifying from the broker
|
||||
provider_version_tag: main # REPLACE_ME: Specify the provider version tag
|
||||
|
||||
# OpenAPI validation settings
|
||||
openapi:
|
||||
# Enable OpenAPI validation
|
||||
enabled: true
|
||||
# Directory containing OpenAPI specifications
|
||||
spec_dir: ./openapi_specs # REPLACE_ME: Choose a directory for OpenAPI specs
|
||||
# Base URL to use for validation
|
||||
base_url: http://localhost:8080 # REPLACE_ME: The base URL of your API
|
||||
|
||||
# Breaking change detection settings
|
||||
breaking_change:
|
||||
# Enable breaking change detection
|
||||
enabled: true
|
||||
# Previous API definition file (e.g., OpenAPI spec)
|
||||
previous_api_definition: ./openapi_specs/previous.yaml # REPLACE_ME: Path to previous API definition
|
||||
# Current API definition file (e.g., OpenAPI spec)
|
||||
current_api_definition: ./openapi_specs/current.yaml # REPLACE_ME: Path to current API definition
|
||||
# Report format (text, json)
|
||||
report_format: text
|
||||
# Output file for breaking change report
|
||||
report_file: ./reports/breaking_changes.txt # REPLACE_ME: Choose a location for report
|
||||
|
||||
# Custom scripts (e.g., for setup and teardown)
|
||||
scripts:
|
||||
# Script to run before contract tests
|
||||
before_all: ./scripts/before_all.sh # REPLACE_ME: Path to setup script (optional)
|
||||
# Script to run after contract tests
|
||||
after_all: ./scripts/after_all.sh # REPLACE_ME: Path to teardown script (optional)
|
||||
|
||||
# Notification settings (e.g., Slack, email)
|
||||
notifications:
|
||||
# Enable notifications
|
||||
enabled: false
|
||||
# Type of notification (slack, email)
|
||||
type: slack # or email
|
||||
# Slack webhook URL (if using Slack notifications)
|
||||
slack_webhook_url: YOUR_VALUE_HERE # REPLACE_ME: Your Slack webhook URL
|
||||
# Email configuration (if using email notifications)
|
||||
email:
|
||||
sender: YOUR_VALUE_HERE # REPLACE_ME: Sender email address
|
||||
recipients: # REPLACE_ME: List of recipient email addresses
|
||||
- recipient1@example.com
|
||||
- recipient2@example.com
|
||||
smtp_server: YOUR_VALUE_HERE # REPLACE_ME: SMTP server address
|
||||
smtp_port: 587
|
||||
smtp_username: YOUR_VALUE_HERE # REPLACE_ME: SMTP username
|
||||
smtp_password: YOUR_VALUE_HERE # REPLACE_ME: SMTP password
|
||||
use_tls: true
|
||||
237
skills/contract-test-validator/assets/openapi_example.yaml
Normal file
237
skills/contract-test-validator/assets/openapi_example.yaml
Normal file
@@ -0,0 +1,237 @@
|
||||
# OpenAPI Specification Example for Contract Test Validator Plugin
|
||||
# This file defines the structure of an example API for testing purposes.
|
||||
|
||||
openapi: 3.0.0
|
||||
info:
|
||||
title: Example API for Contract Testing
|
||||
version: 1.0.0
|
||||
description: A simple API to demonstrate contract testing with Pact and OpenAPI validation.
|
||||
contact:
|
||||
name: REPLACE_ME - Your Name
|
||||
email: REPLACE_ME - your.email@example.com
|
||||
|
||||
servers:
|
||||
- url: https://api.example.com/v1
|
||||
description: Production server
|
||||
|
||||
paths:
|
||||
/users:
|
||||
get:
|
||||
summary: Get all users
|
||||
description: Retrieves a list of all users.
|
||||
operationId: getUsers
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/User'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
post:
|
||||
summary: Create a new user
|
||||
description: Creates a new user with the provided information.
|
||||
operationId: createUser
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/CreateUserRequest'
|
||||
responses:
|
||||
'201':
|
||||
description: User created successfully
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
/users/{userId}:
|
||||
get:
|
||||
summary: Get user by ID
|
||||
description: Retrieves a specific user by their ID.
|
||||
operationId: getUserById
|
||||
parameters:
|
||||
- in: path
|
||||
name: userId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
description: The ID of the user to retrieve
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'404':
|
||||
description: User not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
put:
|
||||
summary: Update user by ID
|
||||
description: Updates a specific user by their ID.
|
||||
operationId: updateUserById
|
||||
parameters:
|
||||
- in: path
|
||||
name: userId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
description: The ID of the user to update
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UpdateUserRequest'
|
||||
responses:
|
||||
'200':
|
||||
description: Successful operation
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/User'
|
||||
'400':
|
||||
description: Bad request
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'404':
|
||||
description: User not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
delete:
|
||||
summary: Delete user by ID
|
||||
description: Deletes a specific user by their ID.
|
||||
operationId: deleteUserById
|
||||
parameters:
|
||||
- in: path
|
||||
name: userId
|
||||
schema:
|
||||
type: integer
|
||||
required: true
|
||||
description: The ID of the user to delete
|
||||
responses:
|
||||
'204':
|
||||
description: User deleted successfully
|
||||
'404':
|
||||
description: User not found
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
'500':
|
||||
description: Internal server error
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/Error'
|
||||
|
||||
components:
|
||||
schemas:
|
||||
User:
|
||||
type: object
|
||||
properties:
|
||||
id:
|
||||
type: integer
|
||||
description: The user ID.
|
||||
name:
|
||||
type: string
|
||||
description: The user's name.
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: The user's email address.
|
||||
created_at:
|
||||
type: string
|
||||
format: date-time
|
||||
description: The date and time the user was created.
|
||||
required:
|
||||
- id
|
||||
- name
|
||||
- email
|
||||
|
||||
CreateUserRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The user's name.
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: The user's email address.
|
||||
required:
|
||||
- name
|
||||
- email
|
||||
|
||||
UpdateUserRequest:
|
||||
type: object
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
description: The user's name.
|
||||
email:
|
||||
type: string
|
||||
format: email
|
||||
description: The user's email address.
|
||||
|
||||
Error:
|
||||
type: object
|
||||
properties:
|
||||
code:
|
||||
type: integer
|
||||
description: The error code.
|
||||
message:
|
||||
type: string
|
||||
description: The error message.
|
||||
required:
|
||||
- code
|
||||
- message
|
||||
|
||||
securitySchemes:
|
||||
bearerAuth: # arbitrary name for the security scheme
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: JWT # optional, for documentation purposes only
|
||||
|
||||
security:
|
||||
- bearerAuth: [] # applies the "bearerAuth" security scheme to all operations
|
||||
@@ -0,0 +1,93 @@
|
||||
{
|
||||
"_comment": "Pact Consumer Contract Template",
|
||||
"consumer": {
|
||||
"name": "MyConsumer"
|
||||
},
|
||||
"provider": {
|
||||
"name": "MyProvider"
|
||||
},
|
||||
"interactions": [
|
||||
{
|
||||
"_comment": "Example Interaction - GET request",
|
||||
"description": "a request to get a product",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"path": "/products/123",
|
||||
"headers": {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
"_comment": "Optional: Query parameters"
|
||||
"query": ""
|
||||
},
|
||||
"response": {
|
||||
"status": 200,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": {
|
||||
"id": 123,
|
||||
"name": "Example Product",
|
||||
"description": "A sample product for testing purposes",
|
||||
"price": 25.99,
|
||||
"inStock": true,
|
||||
"_comment": "Optional: Matchers for flexible validation"
|
||||
"_matchers": {
|
||||
"$.id": {
|
||||
"match": "type"
|
||||
},
|
||||
"$.price": {
|
||||
"match": "decimal"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"providerStates": [
|
||||
{
|
||||
"name": "Product 123 exists",
|
||||
"_comment": "Optional: Define state setup for provider"
|
||||
"params": {
|
||||
"productId": 123
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"_comment": "Example Interaction - POST request",
|
||||
"description": "a request to create a new product",
|
||||
"request": {
|
||||
"method": "POST",
|
||||
"path": "/products",
|
||||
"headers": {
|
||||
"Content-Type": "application/json"
|
||||
},
|
||||
"body": {
|
||||
"name": "New Product",
|
||||
"description": "A new product to be created",
|
||||
"price": 10.00
|
||||
}
|
||||
},
|
||||
"response": {
|
||||
"status": 201,
|
||||
"headers": {
|
||||
"Content-Type": "application/json; charset=utf-8"
|
||||
},
|
||||
"body": {
|
||||
"id": 456,
|
||||
"name": "New Product",
|
||||
"description": "A new product to be created",
|
||||
"price": 10.00
|
||||
}
|
||||
},
|
||||
"providerStates": [
|
||||
{
|
||||
"name": "The system is in a valid state to create products"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"pactSpecification": {
|
||||
"version": "3.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
161
skills/contract-test-validator/assets/report_template.html
Normal file
161
skills/contract-test-validator/assets/report_template.html
Normal file
@@ -0,0 +1,161 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Contract Validation Report</title>
|
||||
<style>
|
||||
/* Inline CSS for styling */
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #f4f4f4;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: #007bff;
|
||||
}
|
||||
|
||||
.report-container {
|
||||
max-width: 900px;
|
||||
margin: 0 auto;
|
||||
background-color: #fff;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.section {
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #eee;
|
||||
padding-bottom: 15px;
|
||||
}
|
||||
|
||||
.section h2 {
|
||||
color: #007bff;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.section p {
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.status-indicator {
|
||||
display: inline-block;
|
||||
padding: 5px 10px;
|
||||
border-radius: 5px;
|
||||
font-weight: bold;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.status-success {
|
||||
background-color: #28a745; /* Green */
|
||||
}
|
||||
|
||||
.status-failure {
|
||||
background-color: #dc3545; /* Red */
|
||||
}
|
||||
|
||||
.status-warning {
|
||||
background-color: #ffc107; /* Yellow */
|
||||
color: #212529;
|
||||
}
|
||||
|
||||
.status-unknown {
|
||||
background-color: #6c757d; /* Gray */
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
th, td {
|
||||
border: 1px solid #ddd;
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
background-color: #f2f2f2;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
pre {
|
||||
background-color: #f8f8f8;
|
||||
padding: 10px;
|
||||
border: 1px solid #ddd;
|
||||
overflow-x: auto;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
/* Responsive Design */
|
||||
@media (max-width: 600px) {
|
||||
.report-container {
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
table {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
th, td {
|
||||
padding: 6px;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="report-container">
|
||||
<h1>Contract Validation Report</h1>
|
||||
|
||||
<!-- Summary Section -->
|
||||
<div class="section">
|
||||
<h2>Summary</h2>
|
||||
<p>Report generated on: {{report_date}}</p>
|
||||
<p>Total tests: {{total_tests}}</p>
|
||||
<p>Passed: <span class="status-indicator status-success">{{passed_tests}}</span></p>
|
||||
<p>Failed: <span class="status-indicator status-failure">{{failed_tests}}</span></p>
|
||||
<p>Warnings: <span class="status-indicator status-warning">{{warning_tests}}</span></p>
|
||||
</div>
|
||||
|
||||
<!-- Pact Verification Results -->
|
||||
<div class="section">
|
||||
<h2>Pact Verification Results</h2>
|
||||
{{pact_results}}
|
||||
</div>
|
||||
|
||||
<!-- OpenAPI Validation Results -->
|
||||
<div class="section">
|
||||
<h2>OpenAPI Validation Results</h2>
|
||||
{{openapi_results}}
|
||||
</div>
|
||||
|
||||
<!-- Breaking Change Detection Results -->
|
||||
<div class="section">
|
||||
<h2>Breaking Change Detection Results</h2>
|
||||
{{breaking_change_results}}
|
||||
</div>
|
||||
|
||||
<!-- Raw Output Section -->
|
||||
<div class="section">
|
||||
<h2>Raw Output</h2>
|
||||
<pre>{{raw_output}}</pre>
|
||||
</div>
|
||||
|
||||
<!-- Additional Notes Section -->
|
||||
<div class="section">
|
||||
<h2>Additional Notes</h2>
|
||||
<p>{{additional_notes}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
9
skills/contract-test-validator/references/README.md
Normal file
9
skills/contract-test-validator/references/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# References
|
||||
|
||||
Bundled resources for contract-test-validator skill
|
||||
|
||||
- [ ] pact_best_practices.md: A guide to best practices for consumer-driven contract testing with Pact.
|
||||
- [ ] openapi_specification.md: Detailed documentation on the OpenAPI specification and how to use it for API validation.
|
||||
- [ ] consumer_driven_testing.md: An overview of consumer-driven contract testing principles and benefits.
|
||||
- [ ] api_contract_examples.md: Examples of API contracts for various protocols (REST, GraphQL, gRPC).
|
||||
- [ ] contract_evolution_strategies.md: Strategies for managing API contract evolution and versioning.
|
||||
9
skills/contract-test-validator/scripts/README.md
Normal file
9
skills/contract-test-validator/scripts/README.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# Scripts
|
||||
|
||||
Bundled resources for contract-test-validator skill
|
||||
|
||||
- [ ] generate_pact_tests.py: Generates Pact consumer contracts based on API specifications or example requests/responses.
|
||||
- [ ] validate_openapi.py: Validates API responses against OpenAPI specifications, reporting any discrepancies or errors.
|
||||
- [ ] detect_breaking_changes.py: Analyzes changes in API contracts or OpenAPI specifications to identify breaking changes that could affect consumers.
|
||||
- [ ] setup_pact_broker.sh: Sets up a Pact Broker instance for managing and sharing API contracts.
|
||||
- [ ] run_verification_tests.sh: Executes provider verification tests against the Pact Broker to ensure API providers adhere to consumer contracts.
|
||||
Reference in New Issue
Block a user