ci: Commit node popularity data (#21992)

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Declan Carroll 2025-11-19 10:12:20 +00:00 committed by GitHub
parent 5d1c375fc6
commit 33bc272656
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 4084 additions and 50 deletions

3
.github/CODEOWNERS vendored
View File

@ -1 +1,4 @@
packages/@n8n/db/src/migrations/ @n8n-io/migrations-review
# Node popularity data updates
packages/frontend/editor-ui/data/node-popularity.json @n8n-io/catalysts

View File

@ -6,6 +6,9 @@ on:
- '**'
- '!release/*'
env:
COVERAGE_ENABLED: 'true' # Set globally for all jobs - ensures Turbo cache consistency
jobs:
install-and-build:
name: Install & Build
@ -16,7 +19,7 @@ jobs:
frontend_changed: ${{ steps.paths-filter.outputs.frontend == 'true' }}
non_python_changed: ${{ steps.paths-filter.outputs.non-python == 'true' }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge
@ -61,7 +64,7 @@ jobs:
if: needs.install-and-build.outputs.frontend_changed == 'true'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: refs/pull/${{ github.event.pull_request.number }}/merge

View File

@ -7,7 +7,7 @@ on:
description: GitHub ref to lint.
required: false
type: string
default: master
default: ''
nodeVersion:
description: Version of node to use.
required: false
@ -22,7 +22,7 @@ jobs:
name: Lint
runs-on: blacksmith-4vcpu-ubuntu-2204
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.ref }}

View File

@ -7,7 +7,7 @@ on:
description: GitHub ref to test.
required: false
type: string
default: master
default: ''
nodeVersion:
description: Version of node to use.
required: false
@ -30,7 +30,7 @@ jobs:
name: Backend Unit Tests
runs-on: blacksmith-4vcpu-ubuntu-2204
env:
COVERAGE_ENABLED: ${{ inputs.collectCoverage }} # Coverage collected when true
COVERAGE_ENABLED: ${{ inputs.collectCoverage }} # Coverage collected when true
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
@ -62,7 +62,7 @@ jobs:
name: Backend Integration Tests
runs-on: blacksmith-4vcpu-ubuntu-2204
env:
COVERAGE_ENABLED: ${{ inputs.collectCoverage }} # Coverage collected when true
COVERAGE_ENABLED: ${{ inputs.collectCoverage }} # Coverage collected when true
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:

View File

@ -0,0 +1,60 @@
name: Update Node Popularity Data
on:
schedule:
# Run every Monday at 00:00 UTC
- cron: '0 0 * * 1'
workflow_dispatch: # Allow manual trigger for testing
permissions:
contents: write
pull-requests: write
jobs:
update-popularity:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Setup Node.js and Dependencies
uses: ./.github/actions/setup-nodejs-github
with:
build-command: '' # Skip build, we only need to fetch data
- name: Fetch node popularity data
run: |
cd packages/frontend/editor-ui
node scripts/fetch-node-popularity.mjs
env:
N8N_FAIL_ON_POPULARITY_FETCH_ERROR: 'false' # Don't fail if API is down
- name: Check for changes
id: check-changes
run: |
if git diff --quiet packages/frontend/editor-ui/data/node-popularity.json; then
echo "No changes to popularity data"
echo "has_changes=false" >> "$GITHUB_OUTPUT"
else
echo "Popularity data has changed"
echo "has_changes=true" >> "$GITHUB_OUTPUT"
fi
- name: Create Pull Request
if: steps.check-changes.outputs.has_changes == 'true'
uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8
with:
branch-token: ${{ secrets.GITHUB_TOKEN }}
commit-message: 'chore: Update node popularity data'
title: 'chore: Update node popularity data'
body: |
This automated PR updates the node popularity data used for sorting nodes in the node creator panel.
The data is fetched weekly from the n8n telemetry endpoint to reflect current usage patterns.
_Generated by the weekly node popularity update workflow._
branch: update-node-popularity
base: master
delete-branch: true
author: n8n Bot <18347049+n8n-bot@users.noreply.github.com>
committer: n8n Bot <18347049+n8n-bot@users.noreply.github.com>

File diff suppressed because it is too large Load Diff

View File

@ -6,8 +6,6 @@
"type": "module",
"scripts": {
"clean": "rimraf dist .turbo .build",
"popularity-cache-marker": "node scripts/cache-marker.mjs",
"fetch-popularity": "node scripts/fetch-node-popularity.mjs",
"build": "cross-env VUE_APP_PUBLIC_PATH=\"/{{BASE_PATH}}/\" NODE_OPTIONS=\"--max-old-space-size=8192\" vite build",
"build:coverage": "cross-env VUE_APP_PUBLIC_PATH=\"/{{BASE_PATH}}/\" NODE_OPTIONS=\"--max-old-space-size=14000\" BUILD_WITH_COVERAGE=true vite build",
"typecheck": "vue-tsc --noEmit",

View File

@ -1,11 +0,0 @@
#!/usr/bin/env node
import { mkdirSync, writeFileSync } from 'fs';
const now = new Date();
const year = now.getFullYear();
const week = Math.ceil(
((now - new Date(year, 0, 1)) / 86400000 + new Date(year, 0, 1).getDay() + 1) / 7,
);
mkdirSync('.build', { recursive: true });
writeFileSync('.build/cache-marker', `${year}-W${week.toString().padStart(2, '0')}`);

View File

@ -8,12 +8,12 @@ const POPULARITY_ENDPOINT =
process.env.NODE_POPULARITY_ENDPOINT ||
'https://internal-production.app.n8n.cloud/webhook/nodes-popularity-scores';
const FAIL_ON_ERROR = process.env.N8N_FAIL_ON_POPULARITY_FETCH_ERROR === 'true';
const BUILD_DIR = path.join(__dirname, '..', '.build');
const OUTPUT_FILE = path.join(BUILD_DIR, 'node-popularity.json');
const DATA_DIR = path.join(__dirname, '..', 'data');
const OUTPUT_FILE = path.join(DATA_DIR, 'node-popularity.json');
async function ensureBuildDir() {
async function ensureDataDir() {
try {
await fs.mkdir(BUILD_DIR, { recursive: true });
await fs.mkdir(DATA_DIR, { recursive: true });
} catch (error) {
// Directory might already exist, that's fine
}
@ -50,7 +50,7 @@ async function getExistingData() {
}
async function savePopularityData(data) {
await ensureBuildDir();
await ensureDataDir();
await fs.writeFile(OUTPUT_FILE, JSON.stringify(data, null, 2));
console.log(`Saved popularity data to ${OUTPUT_FILE} with ${data.length} nodes`);
}

View File

@ -1,21 +0,0 @@
{
"extends": ["//"],
"tasks": {
"popularity-cache-marker": {
"cache": false,
"outputs": [".build/cache-marker"]
},
"fetch-popularity": {
"dependsOn": ["popularity-cache-marker"],
"cache": true,
"outputs": [".build/node-popularity.json"],
"inputs": ["scripts/fetch-node-popularity.mjs", ".build/cache-marker"],
"env": ["N8N_FAIL_ON_POPULARITY_FETCH_ERROR"]
},
"build": {
"dependsOn": ["^build", "fetch-popularity"],
"outputs": ["dist/**"],
"inputs": ["!.build/**"]
}
}
}

View File

@ -15,15 +15,15 @@ export function nodePopularityPlugin(): Plugin {
},
async load(id) {
if (id === RESOLVED_VIRTUAL_MODULE_ID) {
// Try to load the data from the build directory
const buildDataPath = path.join(process.cwd(), '.build', 'node-popularity.json');
// Try to load the data from the data directory
const dataPath = path.join(process.cwd(), 'data', 'node-popularity.json');
try {
const data = await fs.readFile(buildDataPath, 'utf-8');
const data = await fs.readFile(dataPath, 'utf-8');
return `export default ${data}`;
} catch (error) {
// If file doesn't exist, return empty array
console.warn('Node popularity data not found at', buildDataPath, '- using empty array');
console.warn('Node popularity data not found at', dataPath, '- using empty array');
return 'export default []';
}
}