mirror of
https://github.com/wshobson/agents.git
synced 2026-03-18 09:37:15 +00:00
style: format all files with prettier
This commit is contained in:
@@ -3,9 +3,11 @@
|
||||
You are a dependency management expert specializing in safe, incremental upgrades of project dependencies. Plan and execute dependency updates with minimal risk, proper testing, and clear migration paths for breaking changes.
|
||||
|
||||
## Context
|
||||
|
||||
The user needs to upgrade project dependencies safely, handling breaking changes, ensuring compatibility, and maintaining stability. Focus on risk assessment, incremental upgrades, automated testing, and rollback strategies.
|
||||
|
||||
## Requirements
|
||||
|
||||
$ARGUMENTS
|
||||
|
||||
## Instructions
|
||||
@@ -15,6 +17,7 @@ $ARGUMENTS
|
||||
Assess current dependency state and upgrade needs:
|
||||
|
||||
**Comprehensive Dependency Audit**
|
||||
|
||||
```python
|
||||
import json
|
||||
import subprocess
|
||||
@@ -32,13 +35,13 @@ class DependencyAnalyzer:
|
||||
'risk_assessment': self._assess_risks(),
|
||||
'priority_order': self._prioritize_updates()
|
||||
}
|
||||
|
||||
|
||||
return analysis
|
||||
|
||||
|
||||
def _analyze_dependencies(self):
|
||||
"""Analyze each dependency"""
|
||||
deps = {}
|
||||
|
||||
|
||||
# NPM analysis
|
||||
if self._has_npm():
|
||||
npm_output = subprocess.run(
|
||||
@@ -56,11 +59,11 @@ class DependencyAnalyzer:
|
||||
'type': info.get('type', 'dependencies'),
|
||||
'ecosystem': 'npm',
|
||||
'update_type': self._categorize_update(
|
||||
info['current'],
|
||||
info['current'],
|
||||
info['latest']
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
# Python analysis
|
||||
if self._has_python():
|
||||
pip_output = subprocess.run(
|
||||
@@ -80,15 +83,15 @@ class DependencyAnalyzer:
|
||||
pkg_info['latest_version']
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
return deps
|
||||
|
||||
|
||||
def _categorize_update(self, current_ver, latest_ver):
|
||||
"""Categorize update by semver"""
|
||||
try:
|
||||
current = version.parse(current_ver)
|
||||
latest = version.parse(latest_ver)
|
||||
|
||||
|
||||
if latest.major > current.major:
|
||||
return 'major'
|
||||
elif latest.minor > current.minor:
|
||||
@@ -106,6 +109,7 @@ class DependencyAnalyzer:
|
||||
Identify potential breaking changes:
|
||||
|
||||
**Breaking Change Scanner**
|
||||
|
||||
```python
|
||||
class BreakingChangeDetector:
|
||||
def detect_breaking_changes(self, package_name, current_version, target_version):
|
||||
@@ -119,10 +123,10 @@ class BreakingChangeDetector:
|
||||
'migration_required': False,
|
||||
'estimated_effort': 'low'
|
||||
}
|
||||
|
||||
|
||||
# Fetch changelog
|
||||
changelog = self._fetch_changelog(package_name, current_version, target_version)
|
||||
|
||||
|
||||
# Parse for breaking changes
|
||||
breaking_patterns = [
|
||||
r'BREAKING CHANGE:',
|
||||
@@ -134,13 +138,13 @@ class BreakingChangeDetector:
|
||||
r'moved to',
|
||||
r'replaced by'
|
||||
]
|
||||
|
||||
|
||||
for pattern in breaking_patterns:
|
||||
matches = re.finditer(pattern, changelog, re.IGNORECASE)
|
||||
for match in matches:
|
||||
context = self._extract_context(changelog, match.start())
|
||||
breaking_changes['api_changes'].append(context)
|
||||
|
||||
|
||||
# Check for specific patterns
|
||||
if package_name == 'react':
|
||||
breaking_changes.update(self._check_react_breaking_changes(
|
||||
@@ -150,19 +154,19 @@ class BreakingChangeDetector:
|
||||
breaking_changes.update(self._check_webpack_breaking_changes(
|
||||
current_version, target_version
|
||||
))
|
||||
|
||||
|
||||
# Estimate migration effort
|
||||
breaking_changes['estimated_effort'] = self._estimate_effort(breaking_changes)
|
||||
|
||||
|
||||
return breaking_changes
|
||||
|
||||
|
||||
def _check_react_breaking_changes(self, current, target):
|
||||
"""React-specific breaking changes"""
|
||||
changes = {
|
||||
'api_changes': [],
|
||||
'migration_required': False
|
||||
}
|
||||
|
||||
|
||||
# React 15 to 16
|
||||
if current.startswith('15') and target.startswith('16'):
|
||||
changes['api_changes'].extend([
|
||||
@@ -171,7 +175,7 @@ class BreakingChangeDetector:
|
||||
'String refs deprecated'
|
||||
])
|
||||
changes['migration_required'] = True
|
||||
|
||||
|
||||
# React 16 to 17
|
||||
elif current.startswith('16') and target.startswith('17'):
|
||||
changes['api_changes'].extend([
|
||||
@@ -179,7 +183,7 @@ class BreakingChangeDetector:
|
||||
'No event pooling',
|
||||
'useEffect cleanup timing changes'
|
||||
])
|
||||
|
||||
|
||||
# React 17 to 18
|
||||
elif current.startswith('17') and target.startswith('18'):
|
||||
changes['api_changes'].extend([
|
||||
@@ -189,7 +193,7 @@ class BreakingChangeDetector:
|
||||
'New root API'
|
||||
])
|
||||
changes['migration_required'] = True
|
||||
|
||||
|
||||
return changes
|
||||
```
|
||||
|
||||
@@ -198,7 +202,8 @@ class BreakingChangeDetector:
|
||||
Create detailed migration guides:
|
||||
|
||||
**Migration Guide Generator**
|
||||
```python
|
||||
|
||||
````python
|
||||
def generate_migration_guide(package_name, current_version, target_version, breaking_changes):
|
||||
"""
|
||||
Generate step-by-step migration guide
|
||||
@@ -233,7 +238,7 @@ npm install {package_name}@{target_version}
|
||||
|
||||
# Update peer dependencies if needed
|
||||
{generate_peer_deps_commands(package_name, target_version)}
|
||||
```
|
||||
````
|
||||
|
||||
### Step 2: Address Breaking Changes
|
||||
|
||||
@@ -290,11 +295,11 @@ git branch -D upgrade/{package_name}-{target_version}
|
||||
|
||||
- [Official Migration Guide]({get_official_guide_url(package_name, target_version)})
|
||||
- [Changelog]({get_changelog_url(package_name, target_version)})
|
||||
- [Community Discussions]({get_community_url(package_name)})
|
||||
"""
|
||||
|
||||
return guide
|
||||
```
|
||||
- [Community Discussions](<{get_community_url(package_name)}>)
|
||||
"""
|
||||
return guide
|
||||
|
||||
````
|
||||
|
||||
### 4. Incremental Upgrade Strategy
|
||||
|
||||
@@ -309,13 +314,13 @@ class IncrementalUpgrader:
|
||||
"""
|
||||
# Get all versions between current and target
|
||||
all_versions = self._get_versions_between(package_name, current, target)
|
||||
|
||||
|
||||
# Identify safe stopping points
|
||||
safe_versions = self._identify_safe_versions(all_versions)
|
||||
|
||||
|
||||
# Create upgrade path
|
||||
upgrade_path = self._create_upgrade_path(current, target, safe_versions)
|
||||
|
||||
|
||||
plan = f"""
|
||||
## Incremental Upgrade Plan: {package_name}
|
||||
|
||||
@@ -343,35 +348,37 @@ npm test -- --updateSnapshot
|
||||
|
||||
# Verification
|
||||
npm run integration-tests
|
||||
```
|
||||
````
|
||||
|
||||
**Key Changes**:
|
||||
{self._summarize_changes(step)}
|
||||
{self.\_summarize_changes(step)}
|
||||
|
||||
**Testing Focus**:
|
||||
{self._get_test_focus(step)}
|
||||
{self.\_get_test_focus(step)}
|
||||
|
||||
---
|
||||
|
||||
"""
|
||||
|
||||
|
||||
return plan
|
||||
|
||||
|
||||
def _identify_safe_versions(self, versions):
|
||||
"""Identify safe intermediate versions"""
|
||||
safe_versions = []
|
||||
|
||||
|
||||
for v in versions:
|
||||
# Safe versions are typically:
|
||||
# - Last patch of each minor version
|
||||
# - Versions with long stability period
|
||||
# - Versions before major API changes
|
||||
if (self._is_last_patch(v, versions) or
|
||||
if (self._is_last_patch(v, versions) or
|
||||
self._has_stability_period(v) or
|
||||
self._is_pre_breaking_change(v)):
|
||||
safe_versions.append(v)
|
||||
|
||||
|
||||
return safe_versions
|
||||
```
|
||||
|
||||
````
|
||||
|
||||
### 5. Automated Testing Strategy
|
||||
|
||||
@@ -393,10 +400,10 @@ async function testDependencyUpgrade(packageName, targetVersion) {
|
||||
performance: await capturePerformanceMetrics(),
|
||||
bundleSize: await measureBundleSize()
|
||||
};
|
||||
|
||||
|
||||
return baseline;
|
||||
},
|
||||
|
||||
|
||||
postUpgrade: async (baseline) => {
|
||||
// Run same tests after upgrade
|
||||
const results = {
|
||||
@@ -406,10 +413,10 @@ async function testDependencyUpgrade(packageName, targetVersion) {
|
||||
performance: await capturePerformanceMetrics(),
|
||||
bundleSize: await measureBundleSize()
|
||||
};
|
||||
|
||||
|
||||
// Compare results
|
||||
const comparison = compareResults(baseline, results);
|
||||
|
||||
|
||||
return {
|
||||
passed: comparison.passed,
|
||||
failures: comparison.failures,
|
||||
@@ -417,7 +424,7 @@ async function testDependencyUpgrade(packageName, targetVersion) {
|
||||
improvements: comparison.improvements
|
||||
};
|
||||
},
|
||||
|
||||
|
||||
smokeTests: [
|
||||
async () => {
|
||||
// Critical path testing
|
||||
@@ -433,23 +440,24 @@ async function testDependencyUpgrade(packageName, targetVersion) {
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
|
||||
return runUpgradeTests(testSuite);
|
||||
}
|
||||
```
|
||||
````
|
||||
|
||||
### 6. Compatibility Matrix
|
||||
|
||||
Check compatibility across dependencies:
|
||||
|
||||
**Compatibility Checker**
|
||||
|
||||
```python
|
||||
def generate_compatibility_matrix(dependencies):
|
||||
"""
|
||||
Generate compatibility matrix for dependencies
|
||||
"""
|
||||
matrix = {}
|
||||
|
||||
|
||||
for dep_name, dep_info in dependencies.items():
|
||||
matrix[dep_name] = {
|
||||
'current': dep_info['current'],
|
||||
@@ -458,7 +466,7 @@ def generate_compatibility_matrix(dependencies):
|
||||
'conflicts': find_conflicts(dep_name, dep_info['latest']),
|
||||
'peer_requirements': get_peer_requirements(dep_name, dep_info['latest'])
|
||||
}
|
||||
|
||||
|
||||
# Generate report
|
||||
report = """
|
||||
## Dependency Compatibility Matrix
|
||||
@@ -466,14 +474,14 @@ def generate_compatibility_matrix(dependencies):
|
||||
| Package | Current | Target | Compatible With | Conflicts | Action Required |
|
||||
|---------|---------|--------|-----------------|-----------|-----------------|
|
||||
"""
|
||||
|
||||
|
||||
for pkg, info in matrix.items():
|
||||
compatible = '✅' if not info['conflicts'] else '⚠️'
|
||||
conflicts = ', '.join(info['conflicts']) if info['conflicts'] else 'None'
|
||||
action = 'Safe to upgrade' if not info['conflicts'] else 'Resolve conflicts first'
|
||||
|
||||
|
||||
report += f"| {pkg} | {info['current']} | {info['target']} | {compatible} | {conflicts} | {action} |\n"
|
||||
|
||||
|
||||
return report
|
||||
|
||||
def check_compatibility(package_name, version):
|
||||
@@ -481,13 +489,13 @@ def check_compatibility(package_name, version):
|
||||
# Check package.json or requirements.txt
|
||||
peer_deps = get_peer_dependencies(package_name, version)
|
||||
compatible_packages = []
|
||||
|
||||
|
||||
for peer_pkg, peer_version_range in peer_deps.items():
|
||||
if is_installed(peer_pkg):
|
||||
current_peer_version = get_installed_version(peer_pkg)
|
||||
if satisfies_version_range(current_peer_version, peer_version_range):
|
||||
compatible_packages.append(f"{peer_pkg}@{current_peer_version}")
|
||||
|
||||
|
||||
return compatible_packages
|
||||
```
|
||||
|
||||
@@ -496,6 +504,7 @@ def check_compatibility(package_name, version):
|
||||
Implement safe rollback procedures:
|
||||
|
||||
**Rollback Manager**
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# rollback-dependencies.sh
|
||||
@@ -503,50 +512,50 @@ Implement safe rollback procedures:
|
||||
# Create rollback point
|
||||
create_rollback_point() {
|
||||
echo "📌 Creating rollback point..."
|
||||
|
||||
|
||||
# Save current state
|
||||
cp package.json package.json.backup
|
||||
cp package-lock.json package-lock.json.backup
|
||||
|
||||
|
||||
# Git tag
|
||||
git tag -a "pre-upgrade-$(date +%Y%m%d-%H%M%S)" -m "Pre-upgrade snapshot"
|
||||
|
||||
|
||||
# Database snapshot if needed
|
||||
if [ -f "database-backup.sh" ]; then
|
||||
./database-backup.sh
|
||||
fi
|
||||
|
||||
|
||||
echo "✅ Rollback point created"
|
||||
}
|
||||
|
||||
# Perform rollback
|
||||
rollback() {
|
||||
echo "🔄 Performing rollback..."
|
||||
|
||||
|
||||
# Restore package files
|
||||
mv package.json.backup package.json
|
||||
mv package-lock.json.backup package-lock.json
|
||||
|
||||
|
||||
# Reinstall dependencies
|
||||
rm -rf node_modules
|
||||
npm ci
|
||||
|
||||
|
||||
# Run post-rollback tests
|
||||
npm test
|
||||
|
||||
|
||||
echo "✅ Rollback complete"
|
||||
}
|
||||
|
||||
# Verify rollback
|
||||
verify_rollback() {
|
||||
echo "🔍 Verifying rollback..."
|
||||
|
||||
|
||||
# Check critical functionality
|
||||
npm run test:critical
|
||||
|
||||
|
||||
# Check service health
|
||||
curl -f http://localhost:3000/health || exit 1
|
||||
|
||||
|
||||
echo "✅ Rollback verified"
|
||||
}
|
||||
```
|
||||
@@ -556,6 +565,7 @@ verify_rollback() {
|
||||
Handle multiple updates efficiently:
|
||||
|
||||
**Batch Update Planner**
|
||||
|
||||
```python
|
||||
def plan_batch_updates(dependencies):
|
||||
"""
|
||||
@@ -568,16 +578,16 @@ def plan_batch_updates(dependencies):
|
||||
'major': [],
|
||||
'security': []
|
||||
}
|
||||
|
||||
|
||||
for dep, info in dependencies.items():
|
||||
if info.get('has_security_vulnerability'):
|
||||
groups['security'].append(dep)
|
||||
else:
|
||||
groups[info['update_type']].append(dep)
|
||||
|
||||
|
||||
# Create update batches
|
||||
batches = []
|
||||
|
||||
|
||||
# Batch 1: Security updates (immediate)
|
||||
if groups['security']:
|
||||
batches.append({
|
||||
@@ -587,7 +597,7 @@ def plan_batch_updates(dependencies):
|
||||
'strategy': 'immediate',
|
||||
'testing': 'full'
|
||||
})
|
||||
|
||||
|
||||
# Batch 2: Patch updates (safe)
|
||||
if groups['patch']:
|
||||
batches.append({
|
||||
@@ -597,7 +607,7 @@ def plan_batch_updates(dependencies):
|
||||
'strategy': 'grouped',
|
||||
'testing': 'smoke'
|
||||
})
|
||||
|
||||
|
||||
# Batch 3: Minor updates (careful)
|
||||
if groups['minor']:
|
||||
batches.append({
|
||||
@@ -607,7 +617,7 @@ def plan_batch_updates(dependencies):
|
||||
'strategy': 'incremental',
|
||||
'testing': 'regression'
|
||||
})
|
||||
|
||||
|
||||
# Batch 4: Major updates (planned)
|
||||
if groups['major']:
|
||||
batches.append({
|
||||
@@ -617,7 +627,7 @@ def plan_batch_updates(dependencies):
|
||||
'strategy': 'individual',
|
||||
'testing': 'comprehensive'
|
||||
})
|
||||
|
||||
|
||||
return generate_batch_plan(batches)
|
||||
```
|
||||
|
||||
@@ -626,6 +636,7 @@ def plan_batch_updates(dependencies):
|
||||
Handle framework upgrades:
|
||||
|
||||
**Framework Upgrade Guides**
|
||||
|
||||
```python
|
||||
framework_upgrades = {
|
||||
'angular': {
|
||||
@@ -680,60 +691,60 @@ Monitor application after upgrades:
|
||||
```javascript
|
||||
// post-upgrade-monitoring.js
|
||||
const monitoring = {
|
||||
metrics: {
|
||||
performance: {
|
||||
'page_load_time': { threshold: 3000, unit: 'ms' },
|
||||
'api_response_time': { threshold: 500, unit: 'ms' },
|
||||
'memory_usage': { threshold: 512, unit: 'MB' }
|
||||
},
|
||||
errors: {
|
||||
'error_rate': { threshold: 0.01, unit: '%' },
|
||||
'console_errors': { threshold: 0, unit: 'count' }
|
||||
},
|
||||
bundle: {
|
||||
'size': { threshold: 5, unit: 'MB' },
|
||||
'gzip_size': { threshold: 1.5, unit: 'MB' }
|
||||
}
|
||||
metrics: {
|
||||
performance: {
|
||||
page_load_time: { threshold: 3000, unit: "ms" },
|
||||
api_response_time: { threshold: 500, unit: "ms" },
|
||||
memory_usage: { threshold: 512, unit: "MB" },
|
||||
},
|
||||
|
||||
checkHealth: async function() {
|
||||
const results = {};
|
||||
|
||||
for (const [category, metrics] of Object.entries(this.metrics)) {
|
||||
results[category] = {};
|
||||
|
||||
for (const [metric, config] of Object.entries(metrics)) {
|
||||
const value = await this.measureMetric(metric);
|
||||
results[category][metric] = {
|
||||
value,
|
||||
threshold: config.threshold,
|
||||
unit: config.unit,
|
||||
status: value <= config.threshold ? 'PASS' : 'FAIL'
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
errors: {
|
||||
error_rate: { threshold: 0.01, unit: "%" },
|
||||
console_errors: { threshold: 0, unit: "count" },
|
||||
},
|
||||
|
||||
generateReport: function(results) {
|
||||
let report = '## Post-Upgrade Health Check\n\n';
|
||||
|
||||
for (const [category, metrics] of Object.entries(results)) {
|
||||
report += `### ${category}\n\n`;
|
||||
report += '| Metric | Value | Threshold | Status |\n';
|
||||
report += '|--------|-------|-----------|--------|\n';
|
||||
|
||||
for (const [metric, data] of Object.entries(metrics)) {
|
||||
const status = data.status === 'PASS' ? '✅' : '❌';
|
||||
report += `| ${metric} | ${data.value}${data.unit} | ${data.threshold}${data.unit} | ${status} |\n`;
|
||||
}
|
||||
|
||||
report += '\n';
|
||||
}
|
||||
|
||||
return report;
|
||||
bundle: {
|
||||
size: { threshold: 5, unit: "MB" },
|
||||
gzip_size: { threshold: 1.5, unit: "MB" },
|
||||
},
|
||||
},
|
||||
|
||||
checkHealth: async function () {
|
||||
const results = {};
|
||||
|
||||
for (const [category, metrics] of Object.entries(this.metrics)) {
|
||||
results[category] = {};
|
||||
|
||||
for (const [metric, config] of Object.entries(metrics)) {
|
||||
const value = await this.measureMetric(metric);
|
||||
results[category][metric] = {
|
||||
value,
|
||||
threshold: config.threshold,
|
||||
unit: config.unit,
|
||||
status: value <= config.threshold ? "PASS" : "FAIL",
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return results;
|
||||
},
|
||||
|
||||
generateReport: function (results) {
|
||||
let report = "## Post-Upgrade Health Check\n\n";
|
||||
|
||||
for (const [category, metrics] of Object.entries(results)) {
|
||||
report += `### ${category}\n\n`;
|
||||
report += "| Metric | Value | Threshold | Status |\n";
|
||||
report += "|--------|-------|-----------|--------|\n";
|
||||
|
||||
for (const [metric, data] of Object.entries(metrics)) {
|
||||
const status = data.status === "PASS" ? "✅" : "❌";
|
||||
report += `| ${metric} | ${data.value}${data.unit} | ${data.threshold}${data.unit} | ${status} |\n`;
|
||||
}
|
||||
|
||||
report += "\n";
|
||||
}
|
||||
|
||||
return report;
|
||||
},
|
||||
};
|
||||
```
|
||||
|
||||
@@ -748,4 +759,4 @@ const monitoring = {
|
||||
7. **Monitoring Dashboard**: Post-upgrade health metrics
|
||||
8. **Timeline**: Realistic schedule for implementing upgrades
|
||||
|
||||
Focus on safe, incremental upgrades that maintain system stability while keeping dependencies current and secure.
|
||||
Focus on safe, incremental upgrades that maintain system stability while keeping dependencies current and secure.
|
||||
|
||||
Reference in New Issue
Block a user