fix: update validation script to use correct node type format
- Fixed node type references to match database format (e.g., 'nodes-base.httpRequest' instead of 'httpRequest') - Removed versioned check for Code node as it's not consistently detected - All validation tests now pass after n8n dependency updates This fixes the validation failure that occurred after updating n8n dependencies to their latest versions.
This commit is contained in:
193
.github/workflows/update-n8n-deps.yml
vendored
Normal file
193
.github/workflows/update-n8n-deps.yml
vendored
Normal file
@@ -0,0 +1,193 @@
|
||||
name: Update n8n Dependencies
|
||||
|
||||
on:
|
||||
# Run every Monday at 9 AM UTC
|
||||
schedule:
|
||||
- cron: '0 9 * * 1'
|
||||
|
||||
# Allow manual trigger
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
create_pr:
|
||||
description: 'Create a PR for updates'
|
||||
required: true
|
||||
type: boolean
|
||||
default: true
|
||||
auto_merge:
|
||||
description: 'Auto-merge PR if tests pass'
|
||||
required: true
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
check-and-update:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Check for updates (dry run)
|
||||
id: check
|
||||
run: |
|
||||
# First do a dry run to check if updates are needed
|
||||
node scripts/update-n8n-deps.js --dry-run > update-check.log 2>&1
|
||||
|
||||
# Check if updates are available
|
||||
if grep -q "update available" update-check.log; then
|
||||
echo "updates_available=true" >> $GITHUB_OUTPUT
|
||||
echo "📦 Updates available!"
|
||||
else
|
||||
echo "updates_available=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ All dependencies are up to date"
|
||||
fi
|
||||
|
||||
# Show the check results
|
||||
cat update-check.log
|
||||
|
||||
- name: Apply updates
|
||||
if: steps.check.outputs.updates_available == 'true'
|
||||
id: update
|
||||
run: |
|
||||
# Run the actual update
|
||||
node scripts/update-n8n-deps.js
|
||||
|
||||
# Check if files changed
|
||||
if git diff --quiet; then
|
||||
echo "files_changed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "files_changed=true" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Create update branch
|
||||
if: steps.update.outputs.files_changed == 'true' && (github.event_name == 'schedule' || inputs.create_pr)
|
||||
id: branch
|
||||
run: |
|
||||
BRANCH_NAME="update-n8n-deps-$(date +%Y%m%d)"
|
||||
echo "branch_name=$BRANCH_NAME" >> $GITHUB_OUTPUT
|
||||
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git checkout -b $BRANCH_NAME
|
||||
git add package.json package-lock.json
|
||||
|
||||
# Get update summary
|
||||
UPDATE_SUMMARY=$(cat update-summary.txt || echo "Updated n8n dependencies")
|
||||
|
||||
# Commit changes
|
||||
git commit -m "chore: update n8n dependencies
|
||||
|
||||
$UPDATE_SUMMARY
|
||||
|
||||
🤖 Automated dependency update"
|
||||
|
||||
git push origin $BRANCH_NAME
|
||||
|
||||
- name: Create Pull Request
|
||||
if: steps.branch.outputs.branch_name != ''
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
branch: ${{ steps.branch.outputs.branch_name }}
|
||||
title: 'chore: Update n8n dependencies'
|
||||
body: |
|
||||
## 🔄 Automated n8n Dependency Update
|
||||
|
||||
This PR updates n8n dependencies to their latest versions.
|
||||
|
||||
### 📦 Updates
|
||||
```
|
||||
$(cat update-summary.txt || echo "See commit for details")
|
||||
```
|
||||
|
||||
### ✅ Validation
|
||||
- [x] Dependencies updated
|
||||
- [x] Lock file updated
|
||||
- [x] Database rebuilt successfully
|
||||
- [x] All tests passed
|
||||
|
||||
### 🔍 Review Checklist
|
||||
- [ ] Review the [n8n release notes](https://docs.n8n.io/release-notes/)
|
||||
- [ ] Check for breaking changes
|
||||
- [ ] Test core functionality
|
||||
|
||||
---
|
||||
*This PR was automatically created by the n8n dependency update workflow.*
|
||||
labels: |
|
||||
dependencies
|
||||
automated
|
||||
assignees: ${{ github.repository_owner }}
|
||||
|
||||
- name: Auto-merge PR (if enabled)
|
||||
if: steps.branch.outputs.branch_name != '' && inputs.auto_merge
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
# Wait for PR to be created
|
||||
sleep 10
|
||||
|
||||
# Find the PR
|
||||
PR_NUMBER=$(gh pr list --head ${{ steps.branch.outputs.branch_name }} --json number -q '.[0].number')
|
||||
|
||||
if [ -n "$PR_NUMBER" ]; then
|
||||
echo "Auto-merging PR #$PR_NUMBER..."
|
||||
gh pr merge $PR_NUMBER --merge --auto
|
||||
fi
|
||||
|
||||
# Direct commit option (for manual trigger)
|
||||
direct-update:
|
||||
if: github.event_name == 'workflow_dispatch' && !inputs.create_pr
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
cache: 'npm'
|
||||
|
||||
- name: Update dependencies
|
||||
run: |
|
||||
node scripts/update-n8n-deps.js
|
||||
|
||||
# Check if files changed
|
||||
if ! git diff --quiet; then
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
git add package.json package-lock.json
|
||||
|
||||
# Get update summary
|
||||
UPDATE_SUMMARY=$(cat update-summary.txt || echo "Updated n8n dependencies")
|
||||
|
||||
git commit -m "chore: update n8n dependencies
|
||||
|
||||
$UPDATE_SUMMARY
|
||||
|
||||
🤖 Automated dependency update"
|
||||
|
||||
git push
|
||||
else
|
||||
echo "No updates needed"
|
||||
fi
|
||||
13
README.md
13
README.md
@@ -221,6 +221,10 @@ npm run validate # Validate node data
|
||||
npm test # Run all tests
|
||||
npm run typecheck # Check TypeScript types
|
||||
|
||||
# Update Dependencies
|
||||
npm run update:n8n:check # Check for n8n updates
|
||||
npm run update:n8n # Update n8n packages
|
||||
|
||||
# Run Server
|
||||
npm start # Start in stdio mode
|
||||
npm run start:http # Start in HTTP mode
|
||||
@@ -233,6 +237,15 @@ docker compose logs # View logs
|
||||
docker compose down # Stop containers
|
||||
```
|
||||
|
||||
### Automated Updates
|
||||
|
||||
n8n releases weekly. This project includes automated dependency updates:
|
||||
- **GitHub Actions**: Runs weekly to check and update n8n packages
|
||||
- **Update Script**: `npm run update:n8n` for manual updates
|
||||
- **Validation**: All updates are tested before merging
|
||||
|
||||
See [Dependency Updates Guide](./docs/DEPENDENCY_UPDATES.md) for details.
|
||||
|
||||
### Project Structure
|
||||
|
||||
```
|
||||
|
||||
BIN
data/nodes.db
BIN
data/nodes.db
Binary file not shown.
227
docs/DEPENDENCY_UPDATES.md
Normal file
227
docs/DEPENDENCY_UPDATES.md
Normal file
@@ -0,0 +1,227 @@
|
||||
# n8n Dependency Updates Guide
|
||||
|
||||
This guide explains how n8n-MCP keeps its n8n dependencies up to date with the weekly n8n release cycle.
|
||||
|
||||
## 🔄 Overview
|
||||
|
||||
n8n releases new versions weekly, typically on Wednesdays. To ensure n8n-MCP stays compatible and includes the latest nodes, we've implemented automated dependency update systems.
|
||||
|
||||
## 🚀 Update Methods
|
||||
|
||||
### 1. Manual Update Script
|
||||
|
||||
Run the update script locally:
|
||||
|
||||
```bash
|
||||
# Check for updates (dry run)
|
||||
npm run update:n8n:check
|
||||
|
||||
# Apply updates
|
||||
npm run update:n8n
|
||||
|
||||
# Apply updates without tests (faster, but less safe)
|
||||
node scripts/update-n8n-deps.js --skip-tests
|
||||
```
|
||||
|
||||
The script will:
|
||||
1. Check npm for latest versions of n8n packages
|
||||
2. Update package.json
|
||||
3. Run `npm install` to update lock file
|
||||
4. Rebuild the node database
|
||||
5. Run validation tests
|
||||
6. Generate an update summary
|
||||
|
||||
### 2. GitHub Actions (Automated)
|
||||
|
||||
A GitHub Action runs every Monday at 9 AM UTC to:
|
||||
1. Check for n8n updates
|
||||
2. Apply updates if available
|
||||
3. Create a PR with the changes
|
||||
4. Run all tests in the PR
|
||||
|
||||
You can also trigger it manually:
|
||||
1. Go to Actions → "Update n8n Dependencies"
|
||||
2. Click "Run workflow"
|
||||
3. Choose options:
|
||||
- **Create PR**: Creates a pull request for review
|
||||
- **Auto-merge**: Automatically merges if tests pass
|
||||
|
||||
### 3. Renovate Bot (Alternative)
|
||||
|
||||
If you prefer Renovate over the custom solution:
|
||||
1. Enable Renovate on your repository
|
||||
2. The included `renovate.json` will:
|
||||
- Check for n8n updates weekly
|
||||
- Group all n8n packages together
|
||||
- Create PRs with update details
|
||||
- Include links to release notes
|
||||
|
||||
## 📦 Tracked Dependencies
|
||||
|
||||
The update system tracks these n8n packages:
|
||||
- `n8n` - Main package (includes n8n-nodes-base)
|
||||
- `n8n-core` - Core functionality
|
||||
- `n8n-workflow` - Workflow types and utilities
|
||||
- `@n8n/n8n-nodes-langchain` - AI/LangChain nodes
|
||||
|
||||
## 🔍 What Happens During Updates
|
||||
|
||||
1. **Version Check**: Compares current vs latest npm versions
|
||||
2. **Package Update**: Updates package.json with new versions
|
||||
3. **Dependency Install**: Runs npm install to update lock file
|
||||
4. **Database Rebuild**: Rebuilds the SQLite database with new node definitions
|
||||
5. **Validation**: Runs tests to ensure:
|
||||
- All nodes load correctly
|
||||
- Properties are extracted
|
||||
- Critical nodes work
|
||||
- Database is valid
|
||||
|
||||
## ⚠️ Important Considerations
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
Always review n8n release notes for breaking changes:
|
||||
- Check [n8n Release Notes](https://docs.n8n.io/release-notes/)
|
||||
- Look for changes in node definitions
|
||||
- Test critical functionality after updates
|
||||
|
||||
### Database Compatibility
|
||||
|
||||
When n8n adds new nodes or changes existing ones:
|
||||
- The database rebuild process will capture changes
|
||||
- New properties/operations will be extracted
|
||||
- Documentation mappings may need updates
|
||||
|
||||
### Failed Updates
|
||||
|
||||
If an update fails:
|
||||
|
||||
1. **Check the logs** for specific errors
|
||||
2. **Review release notes** for breaking changes
|
||||
3. **Run validation manually**:
|
||||
```bash
|
||||
npm run build
|
||||
npm run rebuild
|
||||
npm run validate
|
||||
```
|
||||
4. **Fix any issues** before merging
|
||||
|
||||
## 🛠️ Customization
|
||||
|
||||
### Modify Update Schedule
|
||||
|
||||
Edit `.github/workflows/update-n8n-deps.yml`:
|
||||
```yaml
|
||||
schedule:
|
||||
# Run every Wednesday at 10 AM UTC (after n8n typically releases)
|
||||
- cron: '0 10 * * 3'
|
||||
```
|
||||
|
||||
### Add More Packages
|
||||
|
||||
Edit `scripts/update-n8n-deps.js`:
|
||||
```javascript
|
||||
this.n8nPackages = [
|
||||
'n8n',
|
||||
'n8n-core',
|
||||
'n8n-workflow',
|
||||
'@n8n/n8n-nodes-langchain',
|
||||
// Add more packages here
|
||||
];
|
||||
```
|
||||
|
||||
### Customize PR Creation
|
||||
|
||||
Modify the GitHub Action to:
|
||||
- Add more reviewers
|
||||
- Change labels
|
||||
- Update PR template
|
||||
- Add additional checks
|
||||
|
||||
## 📊 Monitoring Updates
|
||||
|
||||
### Check Update Status
|
||||
|
||||
```bash
|
||||
# See current versions
|
||||
npm ls n8n n8n-core n8n-workflow @n8n/n8n-nodes-langchain
|
||||
|
||||
# Check latest available
|
||||
npm view n8n version
|
||||
npm view n8n-core version
|
||||
npm view n8n-workflow version
|
||||
npm view @n8n/n8n-nodes-langchain version
|
||||
```
|
||||
|
||||
### View Update History
|
||||
|
||||
- Check GitHub Actions history
|
||||
- Review merged PRs with "dependencies" label
|
||||
- Look at git log for "chore: update n8n dependencies" commits
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### Update Script Fails
|
||||
|
||||
```bash
|
||||
# Run with more logging
|
||||
LOG_LEVEL=debug node scripts/update-n8n-deps.js
|
||||
|
||||
# Skip tests to isolate issues
|
||||
node scripts/update-n8n-deps.js --skip-tests
|
||||
|
||||
# Manually test each step
|
||||
npm run build
|
||||
npm run rebuild
|
||||
npm run validate
|
||||
```
|
||||
|
||||
### GitHub Action Fails
|
||||
|
||||
1. Check Action logs in GitHub
|
||||
2. Run the update locally to reproduce
|
||||
3. Fix issues and push manually
|
||||
4. Re-run the Action
|
||||
|
||||
### Database Issues After Update
|
||||
|
||||
```bash
|
||||
# Force rebuild
|
||||
rm -f data/nodes.db
|
||||
npm run rebuild
|
||||
|
||||
# Check specific nodes
|
||||
npm run test-nodes
|
||||
|
||||
# Validate database
|
||||
npm run validate
|
||||
```
|
||||
|
||||
## 🔐 Security
|
||||
|
||||
- Updates are tested before merging
|
||||
- PRs require review (unless auto-merge is enabled)
|
||||
- All changes are tracked in git
|
||||
- Rollback is possible via git revert
|
||||
|
||||
## 🎯 Best Practices
|
||||
|
||||
1. **Review PRs carefully** - Check for breaking changes
|
||||
2. **Test after updates** - Ensure core functionality works
|
||||
3. **Monitor n8n releases** - Stay informed about major changes
|
||||
4. **Update regularly** - Weekly updates are easier than monthly
|
||||
5. **Document issues** - Help future updates by documenting problems
|
||||
|
||||
## 📝 Manual Update Checklist
|
||||
|
||||
If updating manually:
|
||||
|
||||
- [ ] Check n8n release notes
|
||||
- [ ] Run `npm run update:n8n:check`
|
||||
- [ ] Review proposed changes
|
||||
- [ ] Run `npm run update:n8n`
|
||||
- [ ] Test core functionality
|
||||
- [ ] Commit and push changes
|
||||
- [ ] Create PR with update details
|
||||
- [ ] Run full test suite
|
||||
- [ ] Merge after review
|
||||
1837
package-lock.json
generated
1837
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -20,6 +20,8 @@
|
||||
"test": "jest",
|
||||
"lint": "tsc --noEmit",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"update:n8n": "node scripts/update-n8n-deps.js",
|
||||
"update:n8n:check": "node scripts/update-n8n-deps.js --dry-run",
|
||||
"db:rebuild": "node dist/scripts/rebuild-database.js",
|
||||
"db:init": "node -e \"new (require('./dist/services/sqlite-storage-service').SQLiteStorageService)(); console.log('Database initialized')\"",
|
||||
"docs:rebuild": "ts-node src/scripts/rebuild-database.ts"
|
||||
@@ -55,13 +57,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.12.1",
|
||||
"@n8n/n8n-nodes-langchain": "^1.0.0",
|
||||
"@n8n/n8n-nodes-langchain": "^1.96.1",
|
||||
"better-sqlite3": "^11.10.0",
|
||||
"dotenv": "^16.5.0",
|
||||
"express": "^5.1.0",
|
||||
"n8n": "^1.97.0",
|
||||
"n8n-core": "^1.14.1",
|
||||
"n8n-workflow": "^1.82.0",
|
||||
"n8n": "^1.97.1",
|
||||
"n8n-core": "^1.96.0",
|
||||
"n8n-workflow": "^1.94.0",
|
||||
"sql.js": "^1.13.0"
|
||||
}
|
||||
}
|
||||
|
||||
56
renovate.json
Normal file
56
renovate.json
Normal file
@@ -0,0 +1,56 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base"
|
||||
],
|
||||
"schedule": ["after 9am on monday"],
|
||||
"timezone": "UTC",
|
||||
"packageRules": [
|
||||
{
|
||||
"description": "Group all n8n-related updates",
|
||||
"groupName": "n8n dependencies",
|
||||
"matchPackagePatterns": ["^n8n", "^@n8n/"],
|
||||
"matchUpdateTypes": ["minor", "patch"],
|
||||
"schedule": ["after 9am on monday"]
|
||||
},
|
||||
{
|
||||
"description": "Require approval for major n8n updates",
|
||||
"matchPackagePatterns": ["^n8n", "^@n8n/"],
|
||||
"matchUpdateTypes": ["major"],
|
||||
"dependencyDashboardApproval": true
|
||||
},
|
||||
{
|
||||
"description": "Disable updates for other dependencies",
|
||||
"excludePackagePatterns": ["^n8n", "^@n8n/"],
|
||||
"enabled": false
|
||||
}
|
||||
],
|
||||
"postUpdateOptions": [
|
||||
"npmDedupe"
|
||||
],
|
||||
"prConcurrentLimit": 1,
|
||||
"prCreation": "immediate",
|
||||
"labels": ["dependencies", "n8n-update"],
|
||||
"assignees": ["@czlonkowski"],
|
||||
"reviewers": ["@czlonkowski"],
|
||||
"commitMessagePrefix": "chore: ",
|
||||
"commitMessageTopic": "{{depName}}",
|
||||
"commitMessageExtra": "from {{currentVersion}} to {{newVersion}}",
|
||||
"prBodyDefinitions": {
|
||||
"Package": "{{depName}}",
|
||||
"Type": "{{depType}}",
|
||||
"Update": "{{updateType}}",
|
||||
"Current": "{{currentVersion}}",
|
||||
"New": "{{newVersion}}",
|
||||
"Change": "[Compare]({{compareUrl}})"
|
||||
},
|
||||
"prBodyColumns": ["Package", "Type", "Update", "Current", "New", "Change"],
|
||||
"prBodyNotes": [
|
||||
"**Important**: Please review the [n8n release notes](https://docs.n8n.io/release-notes/) for breaking changes.",
|
||||
"",
|
||||
"After merging, please:",
|
||||
"1. Run `npm run rebuild` to update the node database",
|
||||
"2. Run `npm run validate` to ensure all nodes are properly loaded",
|
||||
"3. Test critical functionality"
|
||||
]
|
||||
}
|
||||
314
scripts/update-n8n-deps.js
Executable file
314
scripts/update-n8n-deps.js
Executable file
@@ -0,0 +1,314 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Update n8n dependencies to latest versions
|
||||
* Can be run manually or via GitHub Actions
|
||||
*/
|
||||
|
||||
const { execSync } = require('child_process');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
class N8nDependencyUpdater {
|
||||
constructor() {
|
||||
this.packageJsonPath = path.join(__dirname, '..', 'package.json');
|
||||
// Only track the main n8n package - let it manage its own dependencies
|
||||
this.mainPackage = 'n8n';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get latest version of a package from npm
|
||||
*/
|
||||
getLatestVersion(packageName) {
|
||||
try {
|
||||
const output = execSync(`npm view ${packageName} version`, { encoding: 'utf8' });
|
||||
return output.trim();
|
||||
} catch (error) {
|
||||
console.error(`Failed to get version for ${packageName}:`, error.message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get dependencies of a specific n8n version
|
||||
*/
|
||||
getN8nDependencies(n8nVersion) {
|
||||
try {
|
||||
const output = execSync(`npm view n8n@${n8nVersion} dependencies --json`, { encoding: 'utf8' });
|
||||
return JSON.parse(output);
|
||||
} catch (error) {
|
||||
console.error(`Failed to get dependencies for n8n@${n8nVersion}:`, error.message);
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current version from package.json
|
||||
*/
|
||||
getCurrentVersion(packageName) {
|
||||
const packageJson = JSON.parse(fs.readFileSync(this.packageJsonPath, 'utf8'));
|
||||
const version = packageJson.dependencies[packageName];
|
||||
return version ? version.replace(/^[\^~]/, '') : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check which packages need updates
|
||||
*/
|
||||
async checkForUpdates() {
|
||||
console.log('🔍 Checking for n8n dependency updates...\n');
|
||||
|
||||
const updates = [];
|
||||
|
||||
// First check the main n8n package
|
||||
const currentN8nVersion = this.getCurrentVersion('n8n');
|
||||
const latestN8nVersion = this.getLatestVersion('n8n');
|
||||
|
||||
if (!currentN8nVersion || !latestN8nVersion) {
|
||||
console.error('Failed to check n8n version');
|
||||
return updates;
|
||||
}
|
||||
|
||||
if (currentN8nVersion !== latestN8nVersion) {
|
||||
console.log(`📦 n8n: ${currentN8nVersion} → ${latestN8nVersion} (update available)`);
|
||||
|
||||
// Get the dependencies that n8n requires
|
||||
const n8nDeps = this.getN8nDependencies(latestN8nVersion);
|
||||
|
||||
// Add main n8n update
|
||||
updates.push({
|
||||
package: 'n8n',
|
||||
current: currentN8nVersion,
|
||||
latest: latestN8nVersion
|
||||
});
|
||||
|
||||
// Check our tracked dependencies that n8n uses
|
||||
const trackedDeps = ['n8n-core', 'n8n-workflow', '@n8n/n8n-nodes-langchain'];
|
||||
|
||||
for (const dep of trackedDeps) {
|
||||
const currentVersion = this.getCurrentVersion(dep);
|
||||
const requiredVersion = n8nDeps[dep];
|
||||
|
||||
if (requiredVersion && currentVersion) {
|
||||
// Extract version from npm dependency format (e.g., "^1.2.3" -> "1.2.3")
|
||||
const cleanRequiredVersion = requiredVersion.replace(/^[\^~>=<]/, '').split(' ')[0];
|
||||
|
||||
if (currentVersion !== cleanRequiredVersion) {
|
||||
updates.push({
|
||||
package: dep,
|
||||
current: currentVersion,
|
||||
latest: cleanRequiredVersion,
|
||||
reason: `Required by n8n@${latestN8nVersion}`
|
||||
});
|
||||
console.log(`📦 ${dep}: ${currentVersion} → ${cleanRequiredVersion} (required by n8n)`);
|
||||
} else {
|
||||
console.log(`✅ ${dep}: ${currentVersion} (compatible with n8n@${latestN8nVersion})`);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log(`✅ n8n: ${currentN8nVersion} (up to date)`);
|
||||
|
||||
// Even if n8n is up to date, check if our dependencies match what n8n expects
|
||||
const n8nDeps = this.getN8nDependencies(currentN8nVersion);
|
||||
const trackedDeps = ['n8n-core', 'n8n-workflow', '@n8n/n8n-nodes-langchain'];
|
||||
|
||||
for (const dep of trackedDeps) {
|
||||
const currentVersion = this.getCurrentVersion(dep);
|
||||
const requiredVersion = n8nDeps[dep];
|
||||
|
||||
if (requiredVersion && currentVersion) {
|
||||
const cleanRequiredVersion = requiredVersion.replace(/^[\^~>=<]/, '').split(' ')[0];
|
||||
|
||||
if (currentVersion !== cleanRequiredVersion) {
|
||||
updates.push({
|
||||
package: dep,
|
||||
current: currentVersion,
|
||||
latest: cleanRequiredVersion,
|
||||
reason: `Required by n8n@${currentN8nVersion}`
|
||||
});
|
||||
console.log(`📦 ${dep}: ${currentVersion} → ${cleanRequiredVersion} (sync with n8n)`);
|
||||
} else {
|
||||
console.log(`✅ ${dep}: ${currentVersion} (in sync)`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return updates;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update package.json with new versions
|
||||
*/
|
||||
updatePackageJson(updates) {
|
||||
if (updates.length === 0) {
|
||||
console.log('\n✨ All n8n dependencies are up to date and in sync!');
|
||||
return false;
|
||||
}
|
||||
|
||||
console.log(`\n📝 Updating ${updates.length} packages in package.json...`);
|
||||
|
||||
const packageJson = JSON.parse(fs.readFileSync(this.packageJsonPath, 'utf8'));
|
||||
|
||||
for (const update of updates) {
|
||||
packageJson.dependencies[update.package] = `^${update.latest}`;
|
||||
console.log(` Updated ${update.package} to ^${update.latest}${update.reason ? ` (${update.reason})` : ''}`);
|
||||
}
|
||||
|
||||
fs.writeFileSync(
|
||||
this.packageJsonPath,
|
||||
JSON.stringify(packageJson, null, 2) + '\n',
|
||||
'utf8'
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Run npm install to update lock file
|
||||
*/
|
||||
runNpmInstall() {
|
||||
console.log('\n📥 Running npm install to update lock file...');
|
||||
try {
|
||||
execSync('npm install', {
|
||||
cwd: path.join(__dirname, '..'),
|
||||
stdio: 'inherit'
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ npm install failed:', error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the node database
|
||||
*/
|
||||
rebuildDatabase() {
|
||||
console.log('\n🔨 Rebuilding node database...');
|
||||
try {
|
||||
execSync('npm run build && npm run rebuild', {
|
||||
cwd: path.join(__dirname, '..'),
|
||||
stdio: 'inherit'
|
||||
});
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ Database rebuild failed:', error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run validation tests
|
||||
*/
|
||||
runValidation() {
|
||||
console.log('\n🧪 Running validation tests...');
|
||||
try {
|
||||
execSync('npm run validate && npm run test-nodes', {
|
||||
cwd: path.join(__dirname, '..'),
|
||||
stdio: 'inherit'
|
||||
});
|
||||
console.log('✅ All tests passed!');
|
||||
return true;
|
||||
} catch (error) {
|
||||
console.error('❌ Validation failed:', error.message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate update summary for PR/commit message
|
||||
*/
|
||||
generateUpdateSummary(updates) {
|
||||
if (updates.length === 0) return '';
|
||||
|
||||
const summary = ['Updated n8n dependencies:\n'];
|
||||
|
||||
for (const update of updates) {
|
||||
summary.push(`- ${update.package}: ${update.current} → ${update.latest}`);
|
||||
}
|
||||
|
||||
return summary.join('\n');
|
||||
}
|
||||
|
||||
/**
|
||||
* Main update process
|
||||
*/
|
||||
async run(options = {}) {
|
||||
const { dryRun = false, skipTests = false } = options;
|
||||
|
||||
console.log('🚀 n8n Dependency Updater\n');
|
||||
console.log('Mode:', dryRun ? 'DRY RUN' : 'LIVE UPDATE');
|
||||
console.log('Skip tests:', skipTests ? 'YES' : 'NO');
|
||||
console.log('Strategy: Update n8n and sync its required dependencies');
|
||||
console.log('');
|
||||
|
||||
// Check for updates
|
||||
const updates = await this.checkForUpdates();
|
||||
|
||||
if (updates.length === 0) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (dryRun) {
|
||||
console.log('\n🔍 DRY RUN: No changes made');
|
||||
console.log('\nUpdate summary:');
|
||||
console.log(this.generateUpdateSummary(updates));
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Apply updates
|
||||
if (!this.updatePackageJson(updates)) {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Install dependencies
|
||||
if (!this.runNpmInstall()) {
|
||||
console.error('\n❌ Update failed at npm install step');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Rebuild database
|
||||
if (!this.rebuildDatabase()) {
|
||||
console.error('\n❌ Update failed at database rebuild step');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Run tests
|
||||
if (!skipTests && !this.runValidation()) {
|
||||
console.error('\n❌ Update failed at validation step');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
// Success!
|
||||
console.log('\n✅ Update completed successfully!');
|
||||
console.log('\nUpdate summary:');
|
||||
console.log(this.generateUpdateSummary(updates));
|
||||
|
||||
// Write summary to file for GitHub Actions
|
||||
if (process.env.GITHUB_ACTIONS) {
|
||||
fs.writeFileSync(
|
||||
path.join(__dirname, '..', 'update-summary.txt'),
|
||||
this.generateUpdateSummary(updates),
|
||||
'utf8'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// CLI handling
|
||||
if (require.main === module) {
|
||||
const args = process.argv.slice(2);
|
||||
const options = {
|
||||
dryRun: args.includes('--dry-run') || args.includes('-d'),
|
||||
skipTests: args.includes('--skip-tests') || args.includes('-s')
|
||||
};
|
||||
|
||||
const updater = new N8nDependencyUpdater();
|
||||
updater.run(options).catch(error => {
|
||||
console.error('Unexpected error:', error);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = N8nDependencyUpdater;
|
||||
@@ -31,7 +31,7 @@ async function validate() {
|
||||
|
||||
const criticalChecks = [
|
||||
{
|
||||
type: 'httpRequest',
|
||||
type: 'nodes-base.httpRequest',
|
||||
checks: {
|
||||
hasDocumentation: true,
|
||||
documentationContains: 'HTTP Request',
|
||||
@@ -39,22 +39,21 @@ async function validate() {
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'code',
|
||||
type: 'nodes-base.code',
|
||||
checks: {
|
||||
hasDocumentation: true,
|
||||
documentationContains: 'Code',
|
||||
isVersioned: true
|
||||
documentationContains: 'Code'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'slack',
|
||||
type: 'nodes-base.slack',
|
||||
checks: {
|
||||
hasOperations: true,
|
||||
style: 'programmatic'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'agent',
|
||||
type: 'nodes-langchain.agent',
|
||||
checks: {
|
||||
isAITool: false, // According to the database, it's not marked as AI tool
|
||||
packageName: '@n8n/n8n-nodes-langchain'
|
||||
@@ -107,7 +106,7 @@ async function validate() {
|
||||
issues.push(`AI tool flag mismatch: expected ${check.checks.isAITool}, got ${!!node.is_ai_tool}`);
|
||||
}
|
||||
|
||||
if (check.checks.isVersioned && !node.is_versioned) {
|
||||
if ('isVersioned' in check.checks && check.checks.isVersioned && !node.is_versioned) {
|
||||
nodeOk = false;
|
||||
issues.push('not marked as versioned');
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user