Compare commits

...

2469 commits

Author SHA1 Message Date
Iván Ovejero
10dbf32596
feat(core): Scale expression isolate pool to 0 after inactivity (#28472)
Some checks are pending
Build: Benchmark Image / build (push) Waiting to run
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Util: Sync API Docs / sync-public-api (push) Waiting to run
Co-authored-by: Danny Martini <danny@n8n.io>
2026-04-21 15:20:01 +00:00
RomanDavydchuk
4869e0a463
fix(editor): HTTP request node showing warning about credentials not set when they are set (#28270) 2026-04-21 15:16:08 +00:00
Irénée
3bd7a2847c
feat(core): Make SSO connection settings configurable via env vars (#28714)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-21 15:14:00 +00:00
Dimitri Lavrenük
9494f41c34
feat: Track computer use connect events (no-changelog) (#28815) 2026-04-21 14:49:48 +00:00
RomanDavydchuk
713c4981b7
fix(editor): Move tooltip for required RMC fields to the right (#28803) 2026-04-21 14:44:45 +00:00
Albert Alises
6db02fe928
fix(MCP Server Trigger Node): Only return error name and message in tool error responses (#28791)
Co-authored-by: Anand Reddy Jonnalagadda <15153801+joan1011@users.noreply.github.com>
2026-04-21 13:43:20 +00:00
Alex Grozav
a88f847708
refactor(editor): Migrate nodeMetadata to workflowDocumentStore (no-changelog) (#28788) 2026-04-21 13:22:52 +00:00
Svetoslav Dekov
7d74c1f04b
fix(editor): Resolve node parameter defaults in Instance AI setup wizard (no-changelog) (#28800)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-21 13:04:15 +00:00
Daria
b1ca129496
feat(core): Broadcast workflow updates from MCP tools to open editors (#28709) 2026-04-21 12:26:56 +00:00
Michael Kret
8e49800421
fix: Additional keys in routing nodes (#28758) 2026-04-21 12:24:43 +00:00
Albert Alises
782b2d18b2
fix(ai-builder): Prevent duplicate workflow creation on parallel submits in instance AI (#28793) 2026-04-21 12:21:48 +00:00
Milorad FIlipović
76358a60be
fix(editor): Allow name parameters to be defined by AI (#28763) 2026-04-21 11:52:25 +00:00
Jaakko Husso
86ceb68a05
feat(core): Include workflow names on instance AI confirmations (no-changelog) (#28719)
Co-authored-by: Albert Alises <albert.alises@gmail.com>
2026-04-21 11:24:16 +00:00
Jaakko Husso
2d624a521e
fix(core): Generate title once there's enough user context (#28721) 2026-04-21 10:28:19 +00:00
Matsuuu
ba2c5488c7
Merge tag 'n8n@2.18.0' 2026-04-21 13:32:15 +03:00
Daria
d1c7b31237
fix: Stop persisting client id in session storage to fix duplicate tab problem (no-changelog) (#28769) 2026-04-21 10:02:43 +00:00
Ricardo Espinoza
26ecadcf94
fix(core): Use upsert for MCP OAuth consent to allow re-authorization (#28703) 2026-04-21 09:58:01 +00:00
Svetoslav Dekov
45b5b9e383
fix(editor): Fix instance-ai setup parameter issues not resetting on input (no-changelog) (#28689) 2026-04-21 09:55:29 +00:00
Matsu
cb9882ce9c
ci: Run ci-pr-quality only on n8n team PRs (#28773) 2026-04-21 09:50:16 +00:00
Jaakko Husso
6592ed8047
refactor(core): Move instance AI user settings under actual user settings (no-changelog) (#28706) 2026-04-21 09:47:36 +00:00
Michael Kret
92f1dac835
chore(Microsoft Agent 365 Trigger Node): Change label on toggle to enable Microsoft MCP Servers (#28766) 2026-04-21 09:38:33 +00:00
Vitalii Borovyk
a88ee76553
fix(MongoDB Chat Memory Node): Add connection pool limit (#28042)
Co-authored-by: Eugene <eugene@n8n.io>
2026-04-21 09:21:40 +00:00
Suguru Inoue
b444a95e11
refactor(editor): Migrate workflow object usages (#28534) 2026-04-21 09:17:45 +00:00
Declan Carroll
5e8002ab28
test: Refactor test workflow initialization (#28772) 2026-04-21 09:15:26 +00:00
Guillaume Jacquart
c012b52ac2
feat(core): Bootstrap encryption key set from environment (#28716)
Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-21 09:13:11 +00:00
Garrit Franke
fc5424477d
feat(core): Add require-node-api-error ESLint rule for community nodes (no-changelog) (#28454) 2026-04-21 09:12:51 +00:00
Jaakko Husso
cb1244c041
refactor: Use napi-rs/image instead of sharp for screenshots (#28586) 2026-04-21 09:12:14 +00:00
n8n-assistant[bot]
6336f0a447
🚀 Release 2.18.0 (#28768)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-04-21 08:58:38 +00:00
Albert Alises
9ea2ef1840
fix(core): Hide pre-resolved setup requests from Instance AI wizard (#28731) 2026-04-21 08:34:59 +00:00
Milorad FIlipović
5e111975d4
fix(editor): Reset remote values on credentials change (#26282)
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-21 08:21:06 +00:00
José Braulio González Valido
87163163e6
fix(core): Add required field validation to MCP OAuth client registration (#28490)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-21 08:04:54 +00:00
Matsu
95c155859e
ci: Ensure stable npm packages are tagged as latest after release (#28755) 2026-04-21 08:04:21 +00:00
Ricardo Espinoza
575c34eae1
feat(core): Track workflow action source for external API and MCP requests (#28483) 2026-04-21 08:00:04 +00:00
Matsu
0d98d29ae4
ci: Only post QA metrics on n8n-io/n8n monorepo (#28692)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
2026-04-21 04:59:06 +00:00
Ali Elkhateeb
9a65549575
feat(API): Add missing credential endpoints (GET by ID and test) (#28519)
Some checks are pending
Build: Benchmark Image / build (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
Util: Sync API Docs / sync-public-api (push) Waiting to run
2026-04-20 20:56:51 +00:00
Dawid Myslak
dd6c28c6d1
fix(Alibaba Cloud Chat Model Node): Add credential-level url field for AI gateway compatibility (#28697) 2026-04-20 19:40:12 +00:00
Joco-95
d14f2546a1
feat: Removes computer use setup logic on Assistant AI opt-in flow and minor UX changes (no-changelog) (#28679) 2026-04-20 18:25:09 +00:00
RomanDavydchuk
d179f667c0
fix(HubSpot Trigger Node): Add missing property selectors (#28595) 2026-04-20 18:05:37 +00:00
Mutasem Aldmour
5b376cb12d
feat(editor): Enable workflow execution from instance AI preview canvas (#28412)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 17:57:03 +00:00
Jaakko Husso
6cfa0ed559
feat(core): Rename instance AI to AI Assistant in the UI texts (no-changelog) (#28732) 2026-04-20 17:49:04 +00:00
Luca Mattiazzi
107c48f65c
fix(core): Ensure single zod instance across workspace packages (#28604) 2026-04-20 17:02:24 +00:00
Svetoslav Dekov
1b13d325f1
fix(editor): Show auth type selector in Instance AI workflow setup (#28707)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-20 16:50:21 +00:00
Albert Alises
db83a95522
fix(editor): Gate Instance AI input while setup wizard is open (#28685) 2026-04-20 16:32:14 +00:00
Joco-95
b42c890c5e
chore(core): Switch PostHog environment variables to EU region (#27115) 2026-04-20 16:21:37 +00:00
Albert Alises
3b15e470b5
fix(editor): Advance wizard step on Continue instead of applying setup (#28698) 2026-04-20 16:11:50 +00:00
Marc Littlemore
bef528cb21
fix: Restore OpenAPI schema version (no-changelog) (#28713) 2026-04-20 15:51:44 +00:00
Matsu
0b8fae6c5a
ci: Only run visual storybook on public monorepo (#28699)
Some checks are pending
Build: Benchmark Image / build (push) Waiting to run
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Util: Sync API Docs / sync-public-api (push) Waiting to run
2026-04-20 14:25:42 +00:00
José Braulio González Valido
560f300716
test: Add Instance AI workflow evals CI pipeline (no-changelog) (#28366)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-20 14:15:41 +00:00
Jaakko Husso
73d93d4edf
fix(core): Better titles on instance AI, use common title logic on n8n agents sdk (no-changelog) (#28686) 2026-04-20 13:27:33 +00:00
Matsu
9f71e12e5f
chore: Migrate @n8n/json-schema-to-zod from Jest to Vitest (#28411)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-20 13:07:50 +00:00
Stephen Wright
9dd3e59acb
feat(core): Add KeyManagerService for encryption key lifecycle management (#28533) 2026-04-20 12:39:46 +00:00
Albert Alises
657bdf136f
fix(core): Filter stale credentials from setup wizard requests (#28478) 2026-04-20 12:37:51 +00:00
Bernhard Wittmann
2d0b231e31
fix(IMAP Node): Fix out-of-memory crash after ECONNRESET on reconnect (#28290) 2026-04-20 12:27:24 +00:00
Raúl Gómez Morales
c17f5b61fe
fix(editor): Prevent chat window jump when hovering prompt suggestions (no-changelog) (#28683) 2026-04-20 12:19:13 +00:00
Alex Grozav
db1eb91940
refactor(editor): Migrate workflow name consumers to workflowDocumentStore (#28682) 2026-04-20 12:17:08 +00:00
Matsu
a3292b738a
chore: Migrate @n8n/permissions to Vitest (#28408) 2026-04-20 12:14:53 +00:00
Declan Carroll
82ee4a9fce
ci: Strengthen Playwright test resilience (#28687) 2026-04-20 12:06:41 +00:00
Matsu
d608889e88
ci: Allow only bundles to 1.x (#28401) 2026-04-20 11:55:35 +00:00
Matsu
a39618a889
chore: Migrate @n8n/client-oauth2 to vitest (#28404) 2026-04-20 11:54:51 +00:00
oleg
bfee79dc21
fix(core): Fix instance-ai planner and prompts after tool consolidation (no-changelog) (#28684) 2026-04-20 11:29:49 +00:00
Jaakko Husso
3e724303c5
fix(core): Prevent nodes tool crash on flattened required fields (#28670) 2026-04-20 10:48:39 +00:00
RomanDavydchuk
19aadf19f7
fix(ClickUp Node): Unclear error message when using OAuth credentials (#28584)
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
2026-04-20 10:33:23 +00:00
Albert Alises
7b3696f3f7
fix(ai-builder): Scope artifacts panel to resources produced in-thread (#28678) 2026-04-20 10:11:46 +00:00
Albert Alises
35f9bed4de
fix(core): Cascade-cancel dependent planned tasks when a parent task fails (#28656) 2026-04-20 09:50:33 +00:00
Garrit Franke
b1c52dad58
test(core): Add credential isolation tests for same-type credentials (no-changelog) (#28308)
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
2026-04-20 09:04:06 +00:00
Alex Grozav
d037fd4647
refactor(editor): Normalize sharedWithProjects field in workflow document store (no-changelog) (#28078) 2026-04-20 08:50:56 +00:00
Milorad FIlipović
0fc2d90b52
fix(core): Report success from mcp tool if workflow is created in DB (no-changelog) (#28529) 2026-04-20 08:48:32 +00:00
Matsu
b2fdcf16c0
ci: Update minor and patch release schedules (#28511) 2026-04-20 08:47:34 +00:00
RomanDavydchuk
73659cb3e7
fix(Google Gemini Node): Determine the file extention from MIME type for image and video operations (#28616) 2026-04-20 08:16:51 +00:00
Michael Kret
4070930e4c
fix(OpenAI Node): Replace hardcoded models with RLC (#28226) 2026-04-20 08:13:47 +00:00
Rob Hough
e848230947
fix(editor): Improve disabled Google sign-in button styling and tooltip alignment (#28536) 2026-04-20 07:31:15 +00:00
James Campbell
7094395cef
fix(Google Cloud Firestore Node): Fix empty array serialization in jsonToDocument (#28213)
Some checks failed
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Has been cancelled
CI: Master (Build, Test, Lint) / Unit tests (push) Has been cancelled
CI: Master (Build, Test, Lint) / Lint (push) Has been cancelled
CI: Master (Build, Test, Lint) / Performance (push) Has been cancelled
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Has been cancelled
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-04-18 13:48:45 +00:00
Jon
f1dab3e295
feat(Slack Node): Add app_home_opened as a dedicated trigger event (#28626)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Roman Davydchuk <roman.davydchuk@n8n.io>
2026-04-17 19:13:53 +00:00
RomanDavydchuk
ff950e5840
fix: Link to n8n website broken in n8n forms (#28627) 2026-04-17 17:09:14 +00:00
Jon
77d27bc826
fix(core): Guard against undefined config properties in credential overwrites (#28573)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-17 16:42:34 +00:00
R🂡hul
25e07cab5a
fix(LinkedIn Node): Update LinkedIn API version in request headers (#28564)
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
2026-04-17 14:33:10 +00:00
robrown-hubspot
8c3e692174
fix(HubSpot Node): Rename HubSpot "App Token" auth to "Service Key" (#28479)
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
2026-04-17 14:20:54 +00:00
Declan Carroll
ef4bfbfe94
ci: Skip non isolated tests (#28615)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
2026-04-17 13:03:10 +00:00
Jon
51bc71e897
fix(editor): Restore WASM file paths for cURL import in HTTP Request node (#28610)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Matsuuu <huhta.matias@gmail.com>
2026-04-17 12:41:56 +00:00
Eugene
3b248eedc2
feat(Linear Trigger Node): Add signing secret validation (#28522)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-17 12:33:01 +00:00
Csaba Tuncsik
21317b8945
fix(editor): Re-initialize SSO store after login to populate OIDC redirect URL (#28386) 2026-04-17 12:05:48 +00:00
Jaakko Husso
46aa46d996
fix(editor): Handle plan confirmation correctly at the UI (no-changelog) (#28613) 2026-04-17 12:05:33 +00:00
Jaakko Husso
5c9a732af4
fix(core): Rework Instance ai settings (no-changelog) (#28495) 2026-04-17 11:36:49 +00:00
Mutasem Aldmour
cff2852332
fix(core): Preserve submitted workflow outcome when builder errors after submit (no-changelog) (#28606)
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-17 10:19:42 +00:00
Raúl Gómez Morales
465478a829
feat(editor): Add collapsible sidebar and deferred thread creation to Instance AI (no-changelog) (#28459) 2026-04-17 10:00:37 +00:00
Albert Alises
d17211342e
fix(editor): Improve setup wizard placeholder detection and card completion scoping (#28474) 2026-04-17 08:47:54 +00:00
Stephen Wright
bb96d2e50a
feat(core): Persist deployment_key entries for stability across restarts and key rotation (#28518)
Some checks are pending
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
2026-04-16 19:49:11 +00:00
Mutasem Aldmour
c97c3b4d12
fix(editor): Resolve nodes stuck on loading after execution in instance-ai preview (#28450)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-16 19:07:19 +00:00
Garrit Franke
fb2bc1ca5f
feat: Add require-community-node-keyword ESLint rule (no-changelog) (#28395) 2026-04-16 17:26:11 +00:00
Rob Hough
04860d5cd7
fix(editor): Fix styles on disabled Publish button (no-changelog) (#28531) 2026-04-16 16:15:11 +00:00
Stephen Wright
c6534fa0b3
feat: Add Prometheus counters for token exchange (#28453)
Some checks are pending
CI: Master (Build, Test, Lint) / Unit tests (push) Waiting to run
CI: Master (Build, Test, Lint) / Build for Github Cache (push) Waiting to run
CI: Master (Build, Test, Lint) / Lint (push) Waiting to run
CI: Master (Build, Test, Lint) / Performance (push) Waiting to run
CI: Master (Build, Test, Lint) / Notify Slack on failure (push) Blocked by required conditions
2026-04-16 12:20:38 +00:00
Declan Carroll
bb9bec3ba4
revert: Make Wait node fully durable by removing in-memory execution path (#28538) 2026-04-16 11:42:22 +00:00
Stephen Wright
56f36a6d19
fix: Disable axios built-in proxy for OAuth2 token requests (#28513) 2026-04-16 09:35:15 +00:00
Luca Mattiazzi
e4fc753967
fix(core): Fix dev:ai script in package.json (no-changelog) (#28402) 2026-04-15 17:11:51 +00:00
Milorad FIlipović
1ecc290107
fix(core): Add strict input validation for workflow() (no-changelog) (#28517) 2026-04-15 14:57:43 +00:00
Jaakko Husso
6bb271d83c
fix(core): Position workflow correctly if opened while on a background tab (no-changelog) (#28421) 2026-04-15 13:26:07 +00:00
Michael Kret
d012346c77
feat: AI Gateway credentials endpoint instance url (#28520) 2026-04-15 12:12:19 +00:00
Tuukka Kantola
6739856aa3
fix(editor): Center sub-node icons and refresh triggers panel icons (#28515)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-15 10:35:12 +00:00
Suguru Inoue
b3e56437c8
refactor(editor): Migrate usages of workflowObject in canvas operations (#28128) 2026-04-15 10:34:00 +00:00
Milorad FIlipović
e5aaeb53a9
fix(core): Implement data tables name collision detection on pull (#26416)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
2026-04-15 09:38:08 +00:00
Marcus
8b105cc0cf
feat(core): Support npm registry token authentication to install private community node packages (#28228)
Co-authored-by: Sandra Zollner <sandra.zollner@n8n.io>
2026-04-15 09:28:55 +00:00
Sandra Zollner
34430aedb1
fix(core): Fix public API package update process (#28475) 2026-04-15 09:04:39 +00:00
RomanDavydchuk
30128c9254
fix(Google Drive Node): Continue on error support for download file operation (#28276)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-04-15 08:41:15 +00:00
Albert Alises
e20f8e91ce
feat(editor): Add admin toggle for computer use in AI settings (no-changelog) (#28452) 2026-04-15 08:08:39 +00:00
Charlie Kolb
f216fda511
fix(editor): Refine resource dependency badge (#28087) 2026-04-15 07:54:26 +00:00
Suguru Inoue
5368851506
refactor(editor): Migrate Workflow class usages in Vue props and function arguments (#28393) 2026-04-15 07:30:49 +00:00
Matsu
80de266be4
ci: Account for pnpm-workspace changes in bump-versions.mjs (#28503) 2026-04-15 07:02:10 +00:00
Matsu
57af37fc61
chore: Migrate @n8n/stylelint-config to Vitest (#28405) 2026-04-15 06:06:03 +00:00
Matsu
229256ee7c
chore: Migrate @n8n/api-types to Vitest (#28394) 2026-04-15 06:05:11 +00:00
Albert Alises
bb7d137cf7
fix(editor): Display placeholder sentinels as hint text in setup wizard (#28482) 2026-04-14 16:36:28 +00:00
Milorad FIlipović
62dc073b3d
fix(core): Fix workflow-sdk validation for plain workflow objects (#28416) 2026-04-14 16:29:20 +00:00
Dawid Myslak
3f57f1cc19
refactor(core): Rename AI Gateway credits to wallet with USD amounts (#28436) 2026-04-14 15:29:13 +00:00
Dimitri Lavrenük
819e707a61
feat: Simplify user consent flow for computer-use (no-changelog) (#28266) 2026-04-14 15:13:08 +00:00
Albert Alises
04d57c5fd6
fix(editor): Prevent setup wizard disappearing on requestId-driven remount (#28473) 2026-04-14 14:58:39 +00:00
Dawid Myslak
bd927d9350
feat(MiniMax Chat Model Node): Add MiniMax Chat Model sub-node (#28305) 2026-04-14 14:29:50 +00:00
Csaba Tuncsik
1042350f4e
fix(editor): Reset OIDC form dirty state after saving IdP settings (#28388) 2026-04-14 14:21:49 +00:00
Albert Alises
f54608e6e4
refactor(ai-builder): Consolidate native tools into 10 action families (no-changelog) (#28140) 2026-04-14 14:00:41 +00:00
Csaba Tuncsik
9c97931ca0
fix(editor): Only show role assignment warning modal when value actually changed (#28387) 2026-04-14 13:32:44 +00:00
Stephen Wright
ac41112731
fix(core): Enforce credential access checks in dynamic node parameter requests (#28446) 2026-04-14 13:23:41 +00:00
Bernhard Wittmann
2959b4dc2a
fix(core): Skip npm outdated check for verified-only community packages (#28335) 2026-04-14 13:09:13 +00:00
James Gee
36261fbe7a
feat(core): Configure OIDC settings via env vars (#28185)
Signed-off-by: James Gee <1285296+geemanjs@users.noreply.github.com>
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
Co-authored-by: Ali Elkhateeb <ali.elkhateeb@n8n.io>
2026-04-14 13:06:22 +00:00
Jaakko Husso
e849041c11
fix(core): Make workflow preview refresh after setup completes (no-changelog) (#28468) 2026-04-14 12:41:20 +00:00
Ali Elkhateeb
fa3299d042
fix(core): Handle git fetch failure during source control startup (#28422)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 12:40:06 +00:00
Sandra Zollner
24015b3449
feat(core): Project based data table creation and transfer (#28323) 2026-04-14 12:38:44 +00:00
Stephen Wright
59edd6ae54
feat: Add deployment_key table, entity, repository, and migration (#28329) 2026-04-14 12:20:22 +00:00
krisn0x
ca871cc10a
feat(core): Support npm dist-tags in community node installation (#28067)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-14 12:18:28 +00:00
yehorkardash
39189c3985
fix: Update working memory using tools (#28467) 2026-04-14 11:45:57 +00:00
Jaakko Husso
9ef55ca4f9
feat(core): Instance AI preview tags and command bar improvements (no-changelog) (#28383) 2026-04-14 11:38:00 +00:00
Charlie Kolb
90a3f460f1
feat(editor): Support showing full label in tooltip on hover of dropdown menu items (no-changelog) (#28231)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-14 11:33:13 +00:00
Svetoslav Dekov
00b0558c2b
fix(editor): Hide setup parameter issue icons until user interacts with input (#28010)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 11:14:37 +00:00
Jaakko Husso
094a5b403e
fix(core): Switch to latest artifact when it updates / new one is created (no-changelog) (#28461) 2026-04-14 11:04:02 +00:00
Elias Meire
c9cab112f9
fix(editor): Show relevant node in workflow activation errors (#26691) 2026-04-14 11:03:50 +00:00
Matsu
dcbc3f14bd
chore: Bump axios to 1.15.0 (#28460) 2026-04-14 10:49:05 +00:00
Charlie Kolb
69a62e0906
docs: Add migration timestamp guidance to @n8n/db AGENTS.md (no-changelog) (#28444)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-14 10:40:42 +00:00
RomanDavydchuk
357fb7210a
fix(GraphQL Node): Improve error response handling (#28209) 2026-04-14 10:12:48 +00:00
Danny Martini
98b833a07d
fix(core): Resolve additional keys lazily in VM expression engine (#28430)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
2026-04-14 09:10:20 +00:00
Charlie Kolb
b1a075f760
feat(editor): Add favoriting for projects, folders, workflows and data tables (#26228)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: aikido-pr-checks[bot] <169896070+aikido-pr-checks[bot]@users.noreply.github.com>
2026-04-14 09:09:00 +00:00
Matsu
d6fbe5f847
ci: Run lint:styles as a part of reusable linting workflow (#28449) 2026-04-14 08:44:48 +00:00
Matsu
d496f6f1bd
ci: Replace docker/login-action with retry-wrapped docker login for DockerHub (#28442)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-14 08:44:12 +00:00
oleg
bd9713bd67
feat(instance-ai): Add Brave Search and Daytona credential types (no-changelog) (#28420)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-14 08:15:36 +00:00
Luca Mattiazzi
9078bb2306
feat(ai-builder): Add a binary check to avoid code import in code blocks (no-changelog) (#28382)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-14 08:02:41 +00:00
Mutasem Aldmour
433370dc2f
test: Add isolated local Playwright runner (#28427)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-14 07:57:24 +00:00
Jaakko Husso
bbc3230dcf
chore: Suppress warning from style lint (#28426) 2026-04-14 07:54:05 +00:00
Albert Alises
3c850f2711
fix(ai-builder): Increase orchestrator max steps from default 5 to 60 (#28429) 2026-04-14 07:51:51 +00:00
Dimitri Lavrenük
b48aeef1f2
fix: Block concurring connection requests in computer use (no-changelog) (#28312) 2026-04-14 07:29:25 +00:00
Andreas Fitzek
e8360a497d
feat(core): Add instance registry service (no-changelog) (#27731) 2026-04-14 06:57:35 +00:00
Bernhard Wittmann
5f8ab01f9b
fix(Schedule Node): Use elapsed-time check to self-heal after missed triggers (#28423) 2026-04-13 15:44:42 +00:00
James Gee
9a22fe5a25
feat(core): Workflow tracing - add workflow version id (#28424) 2026-04-13 15:25:44 +00:00
Jon
ca71d89d88
fix(core): Handle invalid percent sequences and equals signs in HTTP response headers (#27691)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-13 15:17:33 +00:00
Garrit Franke
550409923a
feat(core): Add require-node-description-fields ESLint rule for icon and subtitle (#28400) 2026-04-13 14:55:17 +00:00
n8n-release-tag-merge[bot]
60503b60b1 Merge tag 'n8n@2.17.0' 2026-04-13 15:10:41 +00:00
Mutasem Aldmour
df5855d4c6
test(editor): Add comprehensive instance AI e2e tests (#28326)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 14:40:15 +00:00
Irénée
1108467f44
feat: Enable security policy settings via env vars (#28321) 2026-04-13 14:09:06 +00:00
n8n-assistant[bot]
56d336b877
🚀 Release 2.17.0 (#28418)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-04-13 13:53:22 +00:00
Albert Alises
39c6217109
fix(ai-builder): Use placeholders for user-provided values instead of hardcoding fake addresses (#28407) 2026-04-13 13:29:31 +00:00
Ali Elkhateeb
6217d08ce9
fix(core): Skip disabled Azure Key Vault secrets and handle partial fetch failures (#28325) 2026-04-13 13:23:38 +00:00
Declan Carroll
837652d14a
ci: Increase stale image limit (#28413) 2026-04-13 12:57:08 +00:00
Sandra Zollner
8cd75d2f2d
feat(core): Enable credential creation per project in public API (#28240) 2026-04-13 12:22:52 +00:00
oleg
a9950c182a
refactor(instance-ai): Harmonize prompting between builders (no-changelog) (#28338)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-13 11:59:50 +00:00
Jaakko Husso
4a14840d54
fix(core): Refresh the ai assistant token if it's about to expire (no-changelog) (#28340) 2026-04-13 11:59:28 +00:00
Danny Martini
3d8da49ee4
fix(core): Use closure-scoped evaluation contexts in VM expression bridge (#28337)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 11:53:44 +00:00
Guillaume Jacquart
21c0bf3048
feat(core): Add telemetry for data redaction settings and reveal data (#28396)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:48:13 +00:00
Claire
ebd279f88c
fix(core): Add projectId and projectName to log streaming events (#28310)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 11:43:14 +00:00
Andreas Fitzek
05554abf16
feat(core): Make token exchange rate limits configurable via env vars (no-changelog) (#28328) 2026-04-13 11:40:17 +00:00
Jaakko Husso
3033d9e0eb
fix(core): Make it possible to run workflows with event based triggers on instance AI (no-changelog) (#28398) 2026-04-13 11:20:53 +00:00
Jaakko Husso
5f3dc64cb6
fix(core): More accurate definition of form triggers on system prompt (no-changelog) (#28252) 2026-04-13 11:20:17 +00:00
Declan Carroll
738d42cb54
test: Fix flaky unit tests across three packages (no-changelog) (#28336)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 10:58:24 +00:00
phyllis-noester
06a666aaa0
chore: Add scoped JWT strategy for public API (no-changelog) (#28333) 2026-04-13 10:54:27 +00:00
Romeo Balta
22afd80759
feat(editor): Add Instance AI prompt suggestions (#27984) 2026-04-13 10:50:43 +00:00
Albert Alises
e78f144e8e
feat(ai-builder): Improve sub-agent context passing with structured briefings and debriefings (#28317) 2026-04-13 10:11:27 +00:00
Guillaume Jacquart
0ce81461ab
feat(core): Add audit logging for expression-based role assignments (#28018)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-13 10:11:17 +00:00
Elias Meire
dab714f961
fix: Prohibit tool access to gateway settings directory (#28320) 2026-04-13 09:31:11 +00:00
Irénée
346d4f1597
feat(core): Add userRole and feature-enabled telemetry for external secrets (#27431) 2026-04-13 09:17:17 +00:00
Jaakko Husso
bb310661ce
fix(core): Show data table artifact after row mutations (no-changelog) (#28314) 2026-04-13 09:10:40 +00:00
Raúl Gómez Morales
316d5bda80
feat(editor): Add response grouping and thinking UI for instance AI (no-changelog) (#28236)
Co-authored-by: Tuukka Kantola <tuukka@n8n.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 08:47:06 +00:00
Matsu
a12d368482
chore: Remove dependency to yamljs in favor of yaml (#28307) 2026-04-13 08:06:36 +00:00
Joco-95
98be0ad452
feat: Implement opt-in flow for n8n Agent enrolment (#28006) 2026-04-13 08:00:32 +00:00
Garrit Franke
882dd9ce53
fix(core): Drain webhook close functions to prevent MCP connection leaks (#28384) 2026-04-13 07:48:52 +00:00
krisn0x
72d0f9b98c
fix(Gitlab Node): Handle binary data in all storage modes (#28363)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 06:21:04 +00:00
Albert Alises
ff99c84b88
feat(core): Add parse-file tool for structured attachments (no-changelog) (#28251) 2026-04-10 19:11:50 +00:00
Albert Alises
153fae251c
fix(ai-builder): Prevent orchestrator and planner from assuming resource identifiers (no-changelog) (#28342) 2026-04-10 19:11:30 +00:00
Michael Kret
2c4b9749c7
feat: AI Gateway Top Up Flow (#28113)
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
2026-04-10 16:13:06 +00:00
Marc Littlemore
9ab974b7b0
fix(core): Improve audit queries to avoid PostgreSQL bind parameter limits (#27985)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 16:07:52 +00:00
José Braulio González Valido
9072365bdb
fix(ai-builder): Handle data table name conflict gracefully instead of looping (no-changelog) (#28279)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 15:19:21 +00:00
Marc Littlemore
dbe3f022f1
fix(core): Improve audit queries to avoid PostgreSQL bind parameter limits (#27985)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 15:12:16 +00:00
Matsu
aaa2599378
chore: Bump version and remove unnecessary js-base64 patch (#28324) 2026-04-10 15:04:49 +00:00
Dawid Myslak
e30d2eee60
feat(Moonshot Kimi Node): Add new node (#28189) 2026-04-10 14:48:12 +00:00
Csaba Tuncsik
4c3a1501fe
feat(editor): Refactor role provisioning to two-dropdown layout (#28024) 2026-04-10 14:27:44 +00:00
José Braulio González Valido
ac922fa38c
feat(ai-builder): Improve eval verifier and mock handler reliability (no-changelog) (#28255)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 13:57:32 +00:00
Jean Ibarz
2d22c65e50
fix(core): Propagate formidable parse errors in Form Trigger (#28217) 2026-04-10 13:23:47 +00:00
Declan Carroll
095bfc00f6
ci: Fix flaky e2e tests (#28306) 2026-04-10 12:54:25 +00:00
Dimitri Lavrenük
25e90ffde3
feat: Limit computer use connections to only cloud instances (#28304)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-10 12:52:59 +00:00
Andreas Fitzek
8810097604
feat(core): Wire up embed login end-to-end with cookie overrides and audit events (no-changelog) (#28303) 2026-04-10 12:52:46 +00:00
Charlie Kolb
b353143543
fix(core): Increase timing delays in workflow publish history tests (#28301)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 12:17:16 +00:00
Andreas Fitzek
87e3f1877e
feat(core): Wire TokenExchangeService.exchange() end-to-end (no-changelog) (#28293) 2026-04-10 11:49:17 +00:00
Matsu
872fc671bb
ci: Add exclude patterns for test files in PR size check (#28316) 2026-04-10 11:46:07 +00:00
Jon
4b0519167f
fix(Box Node): Fix issue where Box trigger node was not paginating correctly (#27415) 2026-04-10 11:32:18 +00:00
Andreas Fitzek
f913ec7a59
feat(core): Add JWKS resolver for fetching and parsing JWK Set URLs (no-changelog) (#28027) 2026-04-10 11:27:22 +00:00
phyllis-noester
99e5f1578d
chore: Add tokengrant for JWT permission context (no-changelog) (#28295) 2026-04-10 10:40:06 +00:00
Jake Ranallo
9a8631da38
fix(editor): Move save button to credential modal header (#28287)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-04-10 10:37:55 +00:00
Chris Z
4c2f90539a
docs: Fix design system path in contributing guide (#27998)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-10 10:25:30 +00:00
Albert Alises
7614712a15
fix(core): Remove LocalFilesystemProvider, require computer use for filesystem access (no-changelog) (#28297) 2026-04-10 10:14:20 +00:00
Jon
d7d18a04c8
fix(HubSpot Trigger Node): Add missing tickets scope to OAuth credentials (#27599)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 10:07:47 +00:00
Albert Alises
483b41221a
fix(editor): Address high-severity issues in parity of Instance AI setup wizard (no-changelog) (#28239) 2026-04-10 10:06:43 +00:00
Matsu
54881e189d
chore: Update create-pr skill and PR template (no-changelog) (#28302) 2026-04-10 09:58:59 +00:00
Tim Berndt
290005e0e8
fix(Facebook Lead Ads Node): Add missing pages_read_engagement scope (#27379)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-10 09:57:25 +00:00
Alon Kolyakov
be45c085fb
fix(AWS ELB Node): Fix spelling typo 'sucess' → 'success' in RemoveListenerCertificates (#27703)
Co-authored-by: BloodShop <bloodshop@users.noreply.github.com>
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-10 09:46:29 +00:00
Iván Ovejero
69cb927761
ci: Upgrade to turbo 2.9 (#28292) 2026-04-10 09:44:24 +00:00
oleg
ab8e9a6764
fix(core): Reduce planner workflow bias and fix data-table task routing (no-changelog) (#28299) 2026-04-10 09:42:43 +00:00
oleg
320a4b244d
fix(core): Release LS trace clients on run finalization (no-changelog) (#28254)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-10 09:42:00 +00:00
Declan Carroll
98534c6db9
ci: Fix Node 25 build failure and benchmark OOM on master (no-changelog) (#28262)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 09:05:14 +00:00
Tuukka Kantola
ea5b874a8c
feat(editor): Update built-in node icons to custom SVGs (#28104)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-10 08:53:41 +00:00
Charlie Kolb
8cc0c77775
fix(editor): Fix dependency pill alignment in data table details header (no-changelog) (#27903)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 08:50:35 +00:00
Charlie Kolb
8509074cb6
fix(core): Migrate workflow publish history version id foreign key to set null instead (no-changelog) (#27434) 2026-04-10 08:24:11 +00:00
Albert Alises
8f8b70a301
fix(ai-builder): Unify post-build credential setup into single setup-workflow flow (#28273) 2026-04-10 08:06:09 +00:00
Matsu
733812b1a1
ci: Add PR ownership and size guardrails (#28103)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-10 06:53:18 +00:00
Bernhard Wittmann
4b06720c8b
fix(AWS DynamoDB Node): Add option to disable auto-parsing of numeric strings (#28093)
Co-authored-by: umut-polat <52835619+umut-polat@users.noreply.github.com>
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-04-10 06:29:36 +00:00
Sandra Zollner
dfdc6d2c75
feat(core): Add 'verify' option to installPackage handler and update … (#28257) 2026-04-09 16:39:07 +00:00
krisn0x
769c21946c
chore: Enable n8n plugin in Claude GitHub Actions workflows (no-changelog) (#28258)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-09 15:21:27 +00:00
Bernhard Wittmann
b964ec9588
fix(Google Drive Node): Fix infinite pagination loop in v1 API request (#28244) 2026-04-09 15:03:04 +00:00
Bernhard Wittmann
5fb777e14e
fix(HTTP Request Node): Fix multipart/form-data file upload with binary streams (#28233) 2026-04-09 15:02:34 +00:00
Bernhard Wittmann
c1b5c96f62
fix: Add credential auth and test for PostHog, NASA, Peekalink, Clearbit, Uptime Robot (#27957) 2026-04-09 15:02:17 +00:00
Declan Carroll
09c9b11fff
fix: Update lodash, lodash-es, and xmldom to latest stable versions (#28121)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 14:52:23 +00:00
Declan Carroll
bf25fad7df
test: Resolve 43 janitor violations and update baseline (no-changelog) (#28173)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 14:34:18 +00:00
Andreas Fitzek
12e660a1a8
feat(core): Add DB-backed TrustedKeyService with leader refresh and crypto cache (no-changelog) (#28136) 2026-04-09 14:24:50 +00:00
Rob Hough
5a01bb308e
fix(editor): Improve popover positioning defaults and animations (#27919) 2026-04-09 14:23:45 +00:00
Garrit Franke
af90581c45
test: Harden polling trigger test helper against flaky OAuth2 failures (no-changelog) (#28247) 2026-04-09 14:10:23 +00:00
Arvin A
df8e795c3f
fix(core): Sanitize request data sent to LLM in eval mock handler (no-changelog) (#28200)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 13:16:35 +00:00
Jaakko Husso
42fde1e369
fix(core): Run snapshot pruning correctly and adjust logs (no-changelog) (#28250) 2026-04-09 13:12:12 +00:00
Albert Alises
a407c70841
fix(ai-builder): Allow non-admin users to access Instance AI preferences (no-changelog) (#28243) 2026-04-09 13:11:26 +00:00
Hyuncheol Park
752a4e47d4
fix(MCP Client Node): Ensure MCP connections close when MCP Client node execution ends (#25742)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 12:51:28 +00:00
Csaba Tuncsik
0f4d558b36
chore: Bump n8n Claude Code plugin version to 0.2.0 (no-changelog) (#28249) 2026-04-09 12:49:20 +00:00
oleg
8793ca6386
fix(API): Disable response compression on instance-ai SSE connections (no-changelog) (#28246) 2026-04-09 12:22:30 +00:00
Stephen Wright
8f2da63871
fix: Handle normalization of JSON for SQLite / postgres (#28242) 2026-04-09 12:02:54 +00:00
Dawid Myslak
5cbc9734a4
feat(Moonshot Kimi Chat Model Node): Add Moonshot Kimi Chat Model sub-node (#28156) 2026-04-09 11:59:45 +00:00
oleg
7d834835f3
chore(instance-ai): Disable working memory and remove related code (no-changelog) (#28234)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-09 11:55:11 +00:00
Dimitri Lavrenük
d3e6519730
feat: Implement session based permission modes in Computer Use (#28184) 2026-04-09 11:54:54 +00:00
Dimitri Lavrenük
6f722efef3
fix: Update computer use branding and readme (no-changelog) (#28241) 2026-04-09 10:35:38 +00:00
Dawid Myslak
1148d27725
feat(Alibaba Cloud Model Studio Node): Add new node (#27928)
Co-authored-by: Daniel Molenaars <daniel.molenaars@alibaba-inc.com>
Co-authored-by: Roman Davydchuk <roman.davydchuk@n8n.io>
2026-04-09 10:32:59 +00:00
Declan Carroll
7399af34c9
ci: Defer Chromatic visual regression tests (#28235) 2026-04-09 09:53:20 +00:00
Iván Ovejero
569ad497b7
fix(core): Align VM expression engine error handler with legacy engine (#28166)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 09:14:57 +00:00
Eugene
126983283e
chore: Add skill usage tracking hook (no-changelog) (#28183) 2026-04-09 09:14:56 +00:00
Declan Carroll
85144aa6bc
test: Add simple baseline instance AI memory test (#28170) 2026-04-09 08:47:25 +00:00
Iván Ovejero
4ccd72716e
feat(core): Emit audit events for workflow activation on bootup (#28126) 2026-04-09 08:41:54 +00:00
Rob Hough
72ebb430f4
fix(editor): Keep Back before Continue in MFA login footer (#27911) 2026-04-09 08:33:13 +00:00
Stephen Wright
3db52dca22
fix(core): Omit empty scope from OAuth2 client credentials token request and improve error messaging (#28159) 2026-04-09 08:11:25 +00:00
Raúl Gómez Morales
aa6c322059
fix(editor): UI tweaks for instance AI components (#28155) 2026-04-09 07:48:39 +00:00
Nikhil Kuriakose
5e60272632
fix(editor): Remove default for api params (#27914) 2026-04-09 07:39:39 +00:00
Declan Carroll
b7d6b6ea17
ci: Make PR metrics comment non-blocking (no-changelog) (#28232)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-09 07:49:32 +00:00
Stephen Wright
26d578dfc8
feat: Disable manual role management when expression-based mapping is enabled (#28105) 2026-04-09 07:29:32 +00:00
Tuukka Kantola
cc32c507c5
refactor(editor): Centralize instance AI confirmation dialog styling (#28195)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-09 07:25:22 +00:00
Andreas Fitzek
a95cbfb429
feat(core): Add DB infrastructure for trusted keys and key sources (no-changelog) (#28097) 2026-04-09 02:26:53 +00:00
Arvin A
09bb743bdb
fix(core): Preserve config credential properties in eval mock layer (no-changelog) (#28198)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 21:34:09 +00:00
Albert Alises
4b3b40e238
fix(ai-builder): Improve post-build flow: setup, test, then publish (#28125) 2026-04-08 16:45:56 +00:00
Jaakko Husso
eb5e89055a
feat(core): Persist open artifact preview on instance AI threads (no-changelog) (#28202) 2026-04-08 16:40:33 +00:00
Luca Mattiazzi
1e22e0ad51
fix(If Node): Patches IF node when fields are missing (#28014) 2026-04-08 16:35:57 +00:00
Muhammad Osama
1899a4e284
fix(Http Request Node): Handle empty JSON responses (#27793)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-04-08 16:35:53 +00:00
Jaakko Husso
f1bb47e6a2
fix(core): Mark tool calls cancelled when cancelling main agent on instance AI (no-changelog) (#28192) 2026-04-08 16:17:06 +00:00
Albert Alises
d1a4fa99cc
fix(core): Unblock builder agent when correction arrives during HITL confirmation (no-changelog) (#28203) 2026-04-08 16:16:48 +00:00
phyllis-noester
f23d4ced40
fix(core): Resolver settings page is only visible to authorized users (no-changelog) (#28201) 2026-04-08 16:11:34 +00:00
Iván Ovejero
f8c21276cb
feat(core): Make VM expression bridge timeout and memory limit configurable (#27962)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-04-08 16:07:16 +00:00
md
bd5a70215d
fix(Oracle Node): Resolve 'Maximum call stack size exceeded' on large datasets (#27037)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-08 15:17:02 +00:00
Rayan Salhab
294868de5a
fix(ICalendar Node): Fix Convert to ICS failing when File Name option is set (#27712)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-08 15:15:17 +00:00
Jaakko Husso
7e1bebdae6
feat(core): Make instance AI aware of read-only environments (no-changelog) (#28120) 2026-04-08 15:10:31 +00:00
Ian Gallagher
a93ae81fa4
fix(MQTT Trigger Node): Fix typo (no-changelog) (#9304)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-08 15:09:53 +00:00
Dimitri Lavrenük
468c9c4f8f
fix: Increase timeout for computer use tool calls to 60 seconds (no-changelog) (#28196) 2026-04-08 15:08:47 +00:00
AndyHazz
c0c0f8397c
fix(Pushover Node): Replace duplicate Pushover Timestamp field with the missing TTL field (#11287)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-08 14:56:35 +00:00
Jaakko Husso
59a9f016cb
fix(core): Save cancellation status on cancelled background sub-agent snapshots (no-changelog) (#28175) 2026-04-08 14:56:28 +00:00
oleg
5014d205f1
feat(instance-ai): Add planner sub-agent with progressive plan rendering (no-changelog) (#27889)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-08 14:56:09 +00:00
Stephen Wright
0d078c75f0
fix: Truncate long custom role names and add hover tooltip (#28191) 2026-04-08 14:49:14 +00:00
Bernhard Wittmann
853a74044f
fix(Microsoft Outlook Node): Prevent poll from skipping messages after API errors (#28157) 2026-04-08 14:47:27 +00:00
José Braulio González Valido
91b01d27b9
feat(ai-builder): Fix IF/Switch/Filter node misconfiguration in builder (no-changelog) (#28172)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:35:43 +00:00
RomanDavydchuk
4fab655cc5
fix(Microsoft Teams Node): Block requests from Microsoft Preview Service to prevent accidental approvals for "Send and Wait" (#28085) 2026-04-08 14:25:54 +00:00
Nikhil Kuriakose
33282dbeb9
fix(editor): Removing redundant stop of key propogation (#23464)
Co-authored-by: Garrit Franke <32395585+garritfra@users.noreply.github.com>
2026-04-08 14:03:26 +00:00
Garrit Franke
4f725dab1b
feat(core): Add no-forbidden-lifecycle-scripts lint rule for community nodes (#28176)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 14:00:47 +00:00
Albert Alises
c2fbf9d643
fix(ai-builder): Expose credential account context to prevent prompt/credential mismatch (#28100) 2026-04-08 13:22:10 +00:00
Garrit Franke
b39fc5d612
test: Fix flaky e2e tests in CI shards 2, 5, and 7 (no-changelog) (#28182)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:12:27 +00:00
Irénée
1b995cde18
feat(core): Enable instance owner setup via environment variables (#27859)
Co-authored-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2026-04-08 13:03:50 +00:00
Elias Meire
6bb90d43b6
feat: Rename extension to "Browser Use" and prepare for publishing (#27898)
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-04-08 12:58:31 +00:00
Garrit Franke
6d110fa29b
feat: Add require-continue-on-fail ESLint rule for community nodes (no-changelog) (#28163)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:14:22 +00:00
krisn0x
8c52c5177a
chore: Refine linear-issue skill (no-changelog) (#28074)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-08 12:06:09 +00:00
Iván Ovejero
94b463e2a0
fix(core): Avoid permanent deactivation on transient isolate errors (#28117) 2026-04-08 12:00:02 +00:00
Csaba Tuncsik
91fec345b1
feat(editor): Add project rules, fallback role, remove mapping, save flow (#27689) 2026-04-08 11:23:00 +00:00
Mutasem Aldmour
8cdcab3cc8
feat(core): Add telemetry events for AI builder journey (#28116)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 11:10:42 +00:00
Garrit Franke
e282fcdf0f
feat(core): Add missing-paired-item lint rule for community nodes (#28118)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:54:35 +00:00
Declan Carroll
65b878221a
test: Resolve 45 janitor violations and update baseline (no-changelog) (#28161)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 10:34:00 +00:00
Ali Elkhateeb
1253888174
chore(n8n Node): Add insights summary endpoint to API coverage manifest (no-changelog) (#28160) 2026-04-08 10:32:13 +00:00
krisn0x
7983a41132
chore: Add new entries to .gitignore (no-changelog) (#28168) 2026-04-08 10:21:22 +00:00
Garrit Franke
8f25ce57f2
chore(core): Add skill for creating community node lint rules (no-changelog) (#28165)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 10:17:35 +00:00
Jaakko Husso
1506afba91
fix(core): Avoid markdown in instance AI titles (no-changelog) (#28167) 2026-04-08 10:05:46 +00:00
Jaakko Husso
b68f843f31
refactor(core): Miscellaneous instance AI cleanup (#28162) 2026-04-08 10:05:26 +00:00
Matsu
2597669a5d
chore: Improve linear-issue claude skills (no-changelog) (#27970) 2026-04-08 09:53:12 +00:00
Matsu
69526c6795
ci: Run test:local on community PR's (#28164) 2026-04-08 09:40:56 +00:00
Jaakko Husso
4c3dc92c52
fix(core): Ensure SSE is connected on initial instance AI message (no-changelog) (#28131) 2026-04-08 08:54:54 +00:00
Daria
d6e7923ca6
fix: Validate workflow size for workflows with pinned data on backend (no-changelog) (#27356) 2026-04-08 08:33:01 +00:00
Declan Carroll
b13495227e
test: Resolve 68 janitor scope-lockdown violations in NodeDetailsViewPage (#27993)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-08 08:27:19 +00:00
Elias Meire
94f0a4db5d
fix: Improve browser use Chrome extension connection stability (#27846)
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-04-08 08:16:45 +00:00
Csaba Tuncsik
a00dd19c43
chore: Move Claude Code skills, agents and commands under n8n plugin (no-changelog) (#28020) 2026-04-08 07:57:39 +00:00
yehorkardash
8d4e355241
feat: Add agent schema introspection (no-changelog) (#28015)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-08 07:53:51 +00:00
Andreas Fitzek
4eb99b9c88
feat(core): Add in-process mutex for SQLite advisory lock parity (#28135) 2026-04-08 07:24:36 +00:00
Bernhard Wittmann
f5402dd7f7
feat(MCP Client Tool Node): Prefix MCP tool names with server name (#28094) 2026-04-08 07:23:40 +00:00
Declan Carroll
a23fc0a867
ci: Tag Docker images (#28088) 2026-04-08 06:12:02 +00:00
José Braulio González Valido
fef91c97dd
feat(ai-builder): Add --keep-workflows flag and fix eval execution errors (no-changelog) (#28129)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 17:35:04 +00:00
Csaba Tuncsik
a6b051bfe3
feat(editor): Add instance rules editor with drag-to-reorder (#27688) 2026-04-07 16:55:50 +00:00
Iván Ovejero
2ed3f9c336
fix(core): Fix retry activation in multi-main bypassing exponential backoff (#28110) 2026-04-07 16:40:37 +00:00
Alex Grozav
205ae77c9e
refactor(editor): Migrate description field to workflowDocument store (no-changelog) (#28064) 2026-04-07 15:28:52 +00:00
Ali Elkhateeb
13d153ef1e
feat(API): Add insights summary endpoint to public API (#28099)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-07 15:24:02 +00:00
Dimitri Lavrenük
b841c736df
feat: Update naming of local gateway to computer use (#28111) 2026-04-07 15:22:32 +00:00
James Gee
309a739271
fix(core): Improve performance of the push/pull modal getStatus (#27188)
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
Co-authored-by: Ali Elkhateeb <ali.elkhateeb@n8n.io>
2026-04-07 15:19:50 +00:00
Suguru Inoue
c5969b1952
refactor(editor): Migrate workflowObject usages in NDV components (#27982)
Co-authored-by: r00gm <raul00gm@gmail.com>
2026-04-07 15:09:52 +00:00
Suguru Inoue
2aec493852
refactor(editor): Migrate workflowObject usages in NDV store (#28115) 2026-04-07 15:09:33 +00:00
yehorkardash
5b2c221ffe
fix: Ensure monotonic message timestamps for agent (no-changelog) (#27624) 2026-04-07 14:14:28 +00:00
Luka Zivkovic
2e56ba137d
fix(core): MCP tools called after workflow execution failure (#28021) 2026-04-07 13:37:36 +00:00
José Braulio González Valido
2383749980
feat(ai-builder): Workflow evaluation framework with LLM mock execution (#27818)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Arvin A <51036481+DeveloperTheExplorer@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-07 13:31:16 +00:00
Declan Carroll
7ed34d7f85
ci: Add automated QA metrics reporting to PRs (#28003) 2026-04-07 13:17:01 +00:00
Alex Grozav
14e0c10f4d
refactor(editor): Migrate versionId to workflowDocument store (no-changelog) (#28063) 2026-04-07 13:08:46 +00:00
Albert Alises
91a1282db6
fix(editor): Skip only current step when clicking Later in workflow setup (#27929) 2026-04-07 12:58:16 +00:00
Matsu
b646105028
ci: Install script dependencies before detecting new packages (#28112) 2026-04-07 12:56:28 +00:00
Albert Alises
4a3fc7d27c
fix(ai-builder): Paginate list-credentials tool and drop unused fields (#28108) 2026-04-07 12:52:49 +00:00
Arvin A
b0484a1555
fix(core): Add streaming keepalive to prevent proxy timeout during long agent executions (#27853)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 12:42:06 +00:00
Sandra Zollner
524166e0f1
feat(core): Support projectId when creating workflow via public API (#27884) 2026-04-07 12:14:24 +00:00
Csaba Tuncsik
4e6b4fc3be
feat(editor): Add expression-based role mapping plumbing (#27686) 2026-04-07 11:52:46 +00:00
Andreas Fitzek
d9a5defe88
feat(core): Add identity resolution for token exchange (no-changelog) (#28009) 2026-04-07 11:28:41 +00:00
Charlie Kolb
a82de1dd8f
feat(core): Track instance version history (no-changelog) (#27428) 2026-04-07 11:20:31 +00:00
Guillaume Jacquart
7c156062d1
refactor(core): Extract API key auth into AuthStrategy pattern (no-changelog) (#28008)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Phyllis Noester <phyllis.noester@n8n.io>
2026-04-07 11:00:38 +00:00
Raúl Gómez Morales
91ce8ea93c
fix(editor): UI tweaks for instance AI components (#27917)
Co-authored-by: Tuukka Kantola <tuukka@n8n.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 10:52:24 +00:00
Romeo Balta
a9bc92f83d
fix(core): Scope deferred tool processors per run (#28068) 2026-04-07 10:36:54 +00:00
Raúl Gómez Morales
29e4248cc3
refactor(editor): Add workflowObject facade methods + ESLint guards (no-changelog) (#27556)
Co-authored-by: Suguru Inoue <suguru@n8n.io>
2026-04-07 09:16:36 +00:00
Michael Kret
6e2d35644f
feat: Add AI Gateway support for AI nodes (#27593)
Co-authored-by: Alexander Gekov <40495748+alexander-gekov@users.noreply.github.com>
2026-04-07 09:11:24 +00:00
Albert Alises
9b94862dc7
feat: N8n Agent admin settings page with enable toggle and permissions (#27913) 2026-04-07 08:56:50 +00:00
Matsu
e64408a0d2
ci: Migrate from codecov/test-results-action to codecov-action (#28086) 2026-04-07 08:48:24 +00:00
oleg
dc249ad5ee
fix(instance-ai): reduce memory footprint (no-changelog) (#27967)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-04-07 07:50:30 +00:00
yehorkardash
2ec98687d4
chore: Make scripts in local-gateway platform-agnostic (#28019) 2026-04-07 07:45:35 +00:00
Charlie Kolb
ccd4fd0fc8
fix(core): Decrease workflow history compaction retention periods (#27763) 2026-04-07 07:21:46 +00:00
Svetoslav Dekov
aca249e856
fix(editor): AI builder setup wizard positioning and popover collision (#27821)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 07:20:49 +00:00
Charlie Kolb
c6a98b036e
feat(editor): Track telemetry when user clicks dependency pill item (no-changelog) (#27902)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-07 06:31:12 +00:00
n8n-assistant[bot]
6eb2d75670
🚀 Release 2.16.0 (#28080)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-04-07 04:26:54 +00:00
Alex Grozav
4aba06d78e
refactor(editor): Migrate workflow name to workflowDocument store (#27343) 2026-04-07 00:37:52 +00:00
Albert Alises
9120283009
fix(editor): Skip unsaved-changes confirmation when closing new credential modal (#27975) 2026-04-06 13:55:02 +00:00
Michael Kret
e016b55210
fix(Microsoft Agent 365 Trigger Node): Welcome message fix (#28000)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-04-06 09:45:58 +00:00
krisn0x
de60c85581
fix(Pipedrive Node): Add v2 node with API v2 migration (#27905) 2026-04-06 08:26:53 +00:00
n8n-assistant[bot]
11dcb11565
chore: Update node popularity data (#28052)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-04-06 00:59:21 +00:00
Raúl Gómez Morales
fb4c2631b2
refactor(editor): Migrate AI assistant to workflowDocumentStore connections (no-changelog) (#27422)
Co-authored-by: Alex Grozav <alex@grozav.com>
2026-04-03 15:16:28 +00:00
Guillaume Jacquart
a1f68f03a7
feat(core): Make data redaction available without feature flag (#27981)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 13:33:03 +00:00
Dawid Myslak
864f869d9b
feat(core): Add input/output token tracking to node graph telemetry (#27992) 2026-04-03 13:18:08 +00:00
Dawid Myslak
5a11c5817e
feat(Alibaba Cloud Chat Model Node): Add new node (#27882) 2026-04-03 13:10:26 +00:00
Andreas Fitzek
9a8ea27e6c
feat(core): Add JTI store with atomic consume and cleanup job for token exchange (#27944) 2026-04-03 12:34:10 +00:00
Guillaume Jacquart
1e55b0854b
feat(editor): Put data redaction settings behind enterprise license (#28001)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-03 12:16:38 +00:00
Guillaume Jacquart
cdad6db530
fix(editor): Update JsonEditor content when modelValue changes to same-length string (#27933)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 11:38:47 +00:00
Elias Meire
4fb1f7d6f7
feat(Chat Trigger Node): Auto-add highlighted execution data (#18778)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-04-03 08:51:10 +00:00
Garrit Franke
2c56dbf16e
feat(core): Add options-sorted-alphabetically lint rule for community nodes (#27886)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-03 08:12:59 +00:00
Andreas Fitzek
34931a7412
feat(core): Add static key loading and startup validation for TrustedKeyService (no-changelog) (#27969) 2026-04-03 07:40:59 +00:00
Declan Carroll
f96cdb17db
test: Resolve 20 janitor scope-lockdown and dead-code violations (#27948)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 17:32:27 +00:00
Dimitri Lavrenük
74e6df3b2e
feat: Computer use HITL confirmations in Instance AI (#27910) 2026-04-02 16:49:01 +00:00
Eugene
00014420b1
refactor(core): Remove multi-agent architecture entry point from AI workflow builder (no-changelog) (#27925)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 16:32:19 +00:00
Mutasem Aldmour
77db1bb492
fix(core): Fixing issues across instance ai (no-changelog) (#27939)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 16:31:40 +00:00
Iván Ovejero
aabfdc10f2
ci: Add nightly E2E run with VM expression engine (#27964) 2026-04-02 16:30:57 +00:00
Jaakko Husso
c754724caf
fix(core): Fix daytona proxy bug (#27974)
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
2026-04-02 14:55:53 +00:00
Albert Alises
663f2c5086
fix(core): Set trigger start node for executions without input data (#27968) 2026-04-02 14:53:28 +00:00
Charlie Kolb
eaacd7599e
feat(core): Add data table MCP tool (#27811)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-02 14:07:26 +00:00
Guillaume Jacquart
551960053a
fix(Anthropic Node): Use models endpoint for credential test (#27951)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-02 14:05:38 +00:00
Albert Alises
c909730d49
fix(editor): Truncate large JSON in Instance AI tool results to prevent browser crash (no-changelog) (#27966) 2026-04-02 13:45:13 +00:00
phyllis-noester
0769dbd84f
feat(core): Add AuthStrategyRegistry for pluggable public API auth (no-changelog) (#27956) 2026-04-02 13:30:03 +00:00
Milorad FIlipović
054a2d725a
fix(core): Make MCP executions asynchronous (#27762)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-04-02 12:32:17 +00:00
Jon
59cec2c9e2
feat(Notion Node): Add support for OAuth (#27419)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-04-02 12:11:42 +00:00
Albert Alises
184d521d76
fix(editor): Await confirmAction in handleLater to prevent stuck sub-agents (no-changelog) (#27959) 2026-04-02 12:11:08 +00:00
Garrit Franke
1140c83565
feat(core): Add lint rule to flag string literals in node inputs/outputs (#27890)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 12:08:57 +00:00
krisn0x
70be3f5990
fix(Chat Trigger Node): Fix webhook not registered error when using pinned data (#27697) 2026-04-02 11:54:00 +00:00
Albert Alises
9dd857824f
fix: Auto-authorize task-family tools after plan approval (#27896) 2026-04-02 11:32:30 +00:00
Bernhard Wittmann
763dd7e0b0
fix(Read/Write Files from Disk Node): Add search aliases for binary file nodes (#27760) 2026-04-02 11:32:09 +00:00
Ali Elkhateeb
e2410f05a1
feat(core): Add insights:read scope to API key roles (#27868)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 11:21:09 +00:00
Declan Carroll
a5a9f6d211
fix: Bump dependencies (#27880)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 10:46:49 +00:00
Declan Carroll
4de4053a18
ci: Skip E2E tests for merge group events (#27963) 2026-04-02 11:11:35 +00:00
Milorad FIlipović
573bcdeee0
fix(core): Support descriptions when updating workflows via public API (#27679) 2026-04-02 09:40:27 +00:00
Danny Martini
ae5693beb4
refactor(core): Add structured logging to expression runtime (no-changelog) (#27921)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-02 09:26:12 +00:00
Iván Ovejero
e5208484aa
fix(core): Fix missing isolate acquisition and VM globals in expression engine (#27895) 2026-04-02 09:22:14 +00:00
Declan Carroll
f025a786e7
perf(core): Make Wait node fully durable by removing in-memory execution path (#27066)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 09:15:44 +00:00
Albert Alises
6dd2980e6c
feat(editor): Add missing agent permissions for workflow and data table actions (#27927) 2026-04-02 08:39:30 +00:00
Jaakko Husso
d9c9ffc6c5
refactor(core): Instance AI tweaks (no-changelog) (#27940) 2026-04-02 08:24:55 +00:00
James Gee
cbe109a4cc
feat(core): OTEL - workflow node tracing (#27789) 2026-04-02 07:59:19 +00:00
Stephen Wright
5ad1c54514
feat: Add expression-based role mapping strategy (#27745) 2026-04-02 07:57:32 +00:00
bjorger
618546440b
fix(core): Increase Concurrency for watch mode from 32 to 64 (#27907) 2026-04-02 07:29:51 +00:00
Matsu
efc474cc01
chore: Vite 8 upgrade (#27680) 2026-04-02 09:27:10 +03:00
Garrit Franke
34894af3fa
feat: Add --init-workflow flag to scaffold publish.yml (#27292)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-02 05:45:37 +00:00
phyllis-noester
9ed9b9622e
fix: NodeCredentials use correct credential type rather than first (#27671) 2026-04-02 05:45:35 +00:00
oleg
629826ca1d
feat: Instance AI and local gateway modules (no-changelog) (#27206)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Albert Alises <albert.alises@gmail.com>
Co-authored-by: Jaakko Husso <jaakko@n8n.io>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Tuukka Kantola <Tuukkaa@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
Co-authored-by: Raúl Gómez Morales <raul00gm@gmail.com>
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
Co-authored-by: Mutasem Aldmour <mutasem@n8n.io>
2026-04-01 21:33:38 +03:00
Stephen Wright
94dae154da
feat(core): Implement JWT issuance in token exchange service (#27887) 2026-04-01 17:33:31 +00:00
Iván Ovejero
0fd9fd7155
fix(core): Debounce per event type in pubsub (#27877) 2026-04-01 14:57:02 +00:00
Sandra Zollner
1fa28054a6
feat(core): Enable community package management via Public API (#27637) 2026-04-01 14:51:33 +00:00
Nikhil Kuriakose
baa503de42
feat(editor): Add topic descriptions to CLI help output (no-changelog) (#27851)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 14:50:45 +00:00
Dawid Myslak
9851478faf
fix(core): Add @n8n/ai-node-sdk as CLI dependency for community nodes (#27749) 2026-04-01 13:26:31 +00:00
Danny Martini
644dd00046
test(core): Replace mock-based VM error tests with end-to-end integration tests (#27816)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 12:27:33 +00:00
Guillaume Jacquart
d36cfa1624
feat(core): Improve custom auth JSON masking, preserve shape, redact leaf values (#27675)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-01 12:24:21 +00:00
Andreas Fitzek
72b41a9a76
feat(core): Add embed auth controller and token exchange service skeleton (no-changelog) (#27881) 2026-04-01 12:12:16 +00:00
Andreas Fitzek
285f39b134
feat(core): Add OIDC test login endpoint with frontend Test button (#27824) 2026-04-01 12:08:43 +00:00
Declan Carroll
b82de23cc4
chore: Bump Node.js from 24.13.1 to 24.14.1 (#27894)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 11:54:03 +00:00
Iván Ovejero
df6ee78638
refactor: Upgrade to TypeScript 6.0.2 (#27673) 2026-04-01 11:03:37 +00:00
Jon
5fdb18b5f9
fix(X (Twitter) Node): Surface API error message for insufficient access level (#27603)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-04-01 10:53:17 +00:00
Declan Carroll
daf233f24e
test: Clean up janitor violations and update baseline (#27823)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 10:36:58 +00:00
Charlie Kolb
a061bc6c65
fix(Data Table Node): Change copy for Limit to indicate it applies per input row (#27813) 2026-04-01 10:05:04 +00:00
Declan Carroll
dc7e493fd0
test: Adopt rules engine in playwright janitor (no-changelog) (#27840) 2026-04-01 09:27:13 +00:00
Stephen Wright
b81870afe9
feat(core): Add POST /auth/oauth/token controller and audit event types for token exchange (#27844) 2026-04-01 09:02:46 +00:00
Guillaume Jacquart
29fa8488b5
feat(core): Add redactExecutionData query param to public API executions (#27743)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-01 08:52:12 +00:00
Andreas Fitzek
6ef553cd62
fix(Schedule Node): Skip recurrence check during manual execution (#27830) 2026-04-01 08:13:25 +00:00
Iván Ovejero
5ee0e842b8
feat(core): Add isolate pooling for VM expression engine (#27573) 2026-03-31 14:54:11 +00:00
Sandra Zollner
ccd04b0edf
feat(core): Improve public API middleware to handle different error types (#27562) 2026-03-31 14:06:23 +00:00
Stephen Wright
4471ee87e7
feat(core): Add Zod validation schemas for token-exchange external input (#27825)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:22:32 +00:00
Andreas Fitzek
e0eb8413b5
feat(core): Add Redis storage backend for instance registry (no-changelog) (#27527) 2026-03-31 12:04:23 +00:00
Declan Carroll
3922984b74
ci: Add rules engine and code health packages (no-changelog) (#27815)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-31 11:20:11 +00:00
Declan Carroll
3dde7e16f8
test: Fix flaky unit tests (#27750)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-31 08:49:38 +00:00
Charlie Kolb
ada24f13fe
feat(core): Add instance version history table (#27740) 2026-03-31 08:44:54 +00:00
Eugene
6294b0e56f
feat(ai-builder): Add agent text response evaluation and workflow changes binary check (no-changelog) (#27755)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 07:49:10 +00:00
Declan Carroll
e947000d97
ci: Improve coverage reports (#27756) 2026-03-31 05:42:44 +00:00
n8n-assistant[bot]
d300568ee1
🚀 Release 2.15.0 (#27787)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-03-30 20:55:37 +03:00
Matsu
f2ac7b5cce
ci: Pin provenance to version, not SHA (#27785) 2026-03-30 20:53:11 +03:00
Danny Martini
769e28cb36
fix(core): Remaining VM test fixes — error propagation, proxy traps, and cross-realm assertions (#27541)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 16:13:12 +00:00
Matsu
189c1047bc
ci: Prevent buffer overflow in other helper scripts (#27774) 2026-03-30 15:24:42 +00:00
Matsu
fdf9857344
ci: Parse pnpm ls with jq to prevent buffer overload (#27770) 2026-03-30 14:40:36 +00:00
Irénée
d9f8f04772
fix(core): Rename data table columns during source control pull (#27746)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 13:10:04 +00:00
Milorad FIlipović
4436e4b71c
fix(core): Fix /healthz endpoint when using N8N_PATH (#27665) 2026-03-30 13:05:07 +00:00
Svetoslav Dekov
de02036f47
fix(core): Treat sub-node connections as non-blocking for partial execution root detection (#27759)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:50:36 +00:00
Milorad FIlipović
cf56b9a530
fix(editor): Update mcp eligibility requirements in workflow settings (no-changelog) (#27502) 2026-03-30 12:33:07 +00:00
Svetoslav Dekov
dbe8cd10fc
fix(editor): Use execution data instead of stale NDV state for chat trigger check (#27752)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 12:29:28 +00:00
Eugene
f54453a419
refactor: Remove persistBuilderSessions feature flag (#27481)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 12:16:07 +00:00
Matsu
1963d9775d
ci: Disable chromatic, if not in main repo (#27747) 2026-03-30 11:08:16 +00:00
Svetoslav Dekov
21faa2e187
fix(editor): Handle chat trigger waiting state in setup cards (#27682)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 10:56:47 +00:00
Stephen Wright
af2af60a0f
feat(core): Add POST /role-mapping-rule/:id/move endpoint for reordering rules (#27677)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 10:46:05 +00:00
Charlie Kolb
91d56d2f61
fix(editor): Show tooltip on dependency pill (#27545) 2026-03-30 10:36:23 +00:00
Paul Issert
6d6a10c55e
fix(editor): Restore templates sidebar click tracking (#27623)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 10:23:00 +00:00
Charlie Kolb
706fc4360e
fix(editor): Avoid resource locator cache pollution (#27493) 2026-03-30 10:16:38 +00:00
Svetoslav Dekov
98d685111c
feat(editor): Group agent subnodes into multi-node setup cards (#27570)
Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 10:08:34 +00:00
Declan Carroll
a259295e62
feat(core): Add configurable minimum password length via N8N_PASSWORD_MIN_LENGTH (#26953)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-30 09:40:26 +00:00
Guillaume Jacquart
8ab168f787
chore(core): Query executions using a single query intead of two (#27081)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-30 08:19:32 +00:00
Eugene
6314cd4842
feat(ai-builder): Support dataset context and conversation history in evaluations (no-changelog) (#27618)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-30 08:14:01 +00:00
Iván Ovejero
bd0bc0cbd6
fix: Track workflow archive/unarchive endpoints in API coverage manifest (#27738) 2026-03-30 08:12:13 +00:00
José Braulio González Valido
6f1e0c2f69
feat(editor): Make AI builder test data opt-in via follow-up actions (no-changelog) (#27425)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-30 08:11:21 +00:00
Sandra Zollner
dd599225ab
refactor(core): Extract CommunityPackagesLifecycleService from controller (#27636) 2026-03-30 07:54:34 +00:00
Charlie Kolb
5b989031c1
feat(editor): Support error workflows in workflow dependency (#27542) 2026-03-30 07:29:09 +00:00
Denisf88
a77aa6ad37
fix(core): Use toString() instead of type cast for password field check (#27662) 2026-03-30 06:42:23 +00:00
n8n-assistant[bot]
4270819367
chore: Update node popularity data (#27400)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-30 00:59:31 +00:00
Stephen Wright
54deffcd6a
feat: Add normalization after create, update, delete (#27669) 2026-03-27 17:49:56 +00:00
Sandra Zollner
d33334c5a2
feat(core): Add public API endpoints for workflow archive and unarchive (#27513) 2026-03-27 16:48:08 +00:00
phyllis-noester
b173e3b26a
feat(core): Add Slack credential resolver for dynamic credentials (no-changelog) (#27486)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-27 15:01:06 +00:00
Arvin A
948f458776
feat(editor): Replace restore/changes UI with inline version cards (#27522) 2026-03-27 13:31:48 +00:00
Svetoslav Dekov
f751500472
chore: Update n8n-plan skill to save plans and link them in PRs (no-changelog) (#27495)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Csaba Tuncsik <csaba.tuncsik@gmail.com>
2026-03-27 12:32:00 +00:00
Jon
451d772888
fix: Fix issue preventing community nodes re-installing when using a custom registry (#26599) 2026-03-27 11:51:10 +00:00
Stephen Wright
3d04c50342
feat: DELETE /role-mapping-rule endpoint (#27608) 2026-03-27 11:38:43 +00:00
phyllis-noester
f36f6ae1d7
feat(core): Move id extraction logic into resolver (no-changelog) (#27655) 2026-03-27 11:36:02 +00:00
Michael Kret
4d356c36d6
feat: Environment var to disable forms pages sandboxing (#27409) 2026-03-27 10:52:22 +00:00
Marc Littlemore
4f98ce4336
fix(editor): Truncate long workflow names in insights table (#27631)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-27 10:39:44 +00:00
Svetoslav Dekov
b4f0965c9c
fix(editor): Remove unused options from NDV settings for agent model nodes (#27364) 2026-03-27 09:49:07 +00:00
Milorad FIlipović
dccc39163a
feat(editor): Implement preview tag for MCP (no-changelog) (#27630) 2026-03-27 09:12:22 +00:00
Stephen Wright
1064f04b79
feat: GET /role-mapping-rule endpoint (#27609) 2026-03-27 09:04:57 +00:00
Milorad FIlipović
0fd427de9f
fix(editor): Fix empty project ID when creating resources using RLC (#27544) 2026-03-27 07:50:37 +00:00
Milorad FIlipović
8b9de31d69
feat(core): Implement Test workflow MCP tool (#27348) 2026-03-27 07:47:48 +00:00
Matsu
6de46623a9
ci: Set initial npm publish to function with it's own token (#27620) 2026-03-27 07:23:06 +00:00
Matsu
ba59ff14ae
ci: Allow manual execution of release-schedule-patch-prs (#27653) 2026-03-27 07:18:02 +00:00
Matsu
10d4a7dd2b
ci: Pin action to commit SHA and pass secrets via env vars (#27622)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-27 07:17:14 +00:00
Ria Scholz
1113cee1a4
feat(Zammad Node): Add support for updating tickets (#16800)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
2026-03-27 06:59:12 +00:00
Ali Elkhateeb
d8fc058326
feat(core): Add OTEL unhappy path handling and safe trace exporter (#27568)
Co-authored-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2026-03-26 20:45:10 +00:00
Iván Ovejero
65a5495cc9
perf(core): Optimize execution deletions for throughput (#27336) 2026-03-26 18:15:29 +00:00
Csaba Tuncsik
174aece228
chore: Add n8n Claude Code plugin with setup-mcps skill (#27589) 2026-03-26 15:11:30 +00:00
Jon
ef506be259
fix: Fix issue with multi line string handling (#27176) 2026-03-26 14:36:24 +00:00
Jon
57179e3326
fix(Microsoft Outlook Trigger Node): Wrap folder filter in parentheses to ensure correct OData operator precedence (#27605)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 14:35:44 +00:00
Stephen Wright
150067fbbb
feat: POST / PATCH /role-mapping-rule endpoints (#27569) 2026-03-26 13:39:06 +00:00
Milorad FIlipović
197a4314b3
fix(editor): Fix /diff route loading in demo mode (#27610) 2026-03-26 12:45:14 +00:00
Matsu
d1fd399ca2
ci: Detect new unpublished packages after merge and add manual publish workflow (#27611)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 12:06:10 +00:00
Matsu
44af2a1bbd
ci: Add security publish fix workflow for 1.x branch (#27604)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 12:06:02 +00:00
Matsu
fdd2be44b6
ci: Use track-specific npm dist-tags on publish (#27598)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 12:03:18 +00:00
Matsu
93e2998153
ci: Don't error on release candidate cleanup when branch is missing (#27602) 2026-03-26 12:02:35 +00:00
yehorkardash
58fbaf4a88
feat: Add @n8n/agents package (#27560) 2026-03-26 11:32:46 +00:00
Raúl Gómez Morales
d3e45bc126
fix(core): Resolve $().item expressions in partial executions (#27338) 2026-03-26 10:38:06 +00:00
phyllis-noester
c114e7ea59
feat(core): Add Slack signature extractor hook for dynamic credentials (no-changelog) (#27485)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 10:36:04 +00:00
Stephen Wright
4cc9019cb6
feat: Type and order uniqueness (#27600) 2026-03-26 09:22:37 +00:00
Matsu
704d5b4a3d
ci: Add 1.x sync and bundle branch automation for n8n-private (#27594)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 08:32:11 +00:00
Jon
23f7ed8ef8
feat(Wordpress Node): Add support for OAuth2 (#27113) 2026-03-26 08:24:16 +00:00
Jon
097567fbb3
chore: Add node-add-oauth skill (no-changelog) (#27447)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-26 07:58:13 +00:00
Iván Ovejero
d3f40cd31d
fix(core): Fix race condition when stopping jobs in queue mode (#27211) 2026-03-26 07:33:14 +00:00
Matsu
468269af04
ci: Run pnpm pack --dry-run on CI to catch workspace errors (#27480) 2026-03-26 06:55:57 +00:00
Elias Meire
88f170b95e
fix(core): Refresh OAuth2 tokens on 401 during MCP tool calls (#26463)
Co-authored-by: aikido-pr-checks[bot] <169896070+aikido-pr-checks[bot]@users.noreply.github.com>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-25 17:58:15 +00:00
Jon
53f65ab034
fix(Salesforce Node): Fix private key field stripping newlines in JWT credential (#27517)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 17:37:47 +00:00
Dimitri Lavrenük
5229fa0887
fix: Implement raw query parameters field for Microsoft SQL node (#26355) 2026-03-25 16:44:37 +00:00
Benjamin Schroth
87a9973390
fix(editor): Correct navigation to evaluation tab (#27509) 2026-03-25 16:01:06 +00:00
Iván Ovejero
b55729280e
feat(core): Replace unbounded expression code cache with LRU (#27477)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 15:39:01 +00:00
Guillaume Jacquart
5b4d5ce64e
fix(API): Skip sharing license check when isGlobal value is unchanged (#27567)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-25 15:28:55 +00:00
Andreas Fitzek
09d736ede3
feat(core): Implement MemoryInstanceStorage for single-instance deployments (no-changelog) (#27460) 2026-03-25 15:00:26 +00:00
phyllis-noester
884c34e49e
feat(core): Add Slack signature identifier for dynamic credentials (no-changelog) (#27484)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 14:36:13 +00:00
James Gee
42843d6c72
feat(core): Workflow level otel (#27528) 2026-03-25 14:27:51 +00:00
Joco-95
e79d8af1bb
feat: PostHog feature flags resolution caching & group support (#27525) 2026-03-25 13:39:37 +00:00
Milorad FIlipović
ca3a957c8e
fix(core): Fix hard-coded path style in external storage configuration (#27553) 2026-03-25 13:39:04 +00:00
Raúl Gómez Morales
9736ce7846
fix(editor): Use direct store reference for connections in initializeWorkspace (#27552) 2026-03-25 12:15:52 +00:00
Stephen Wright
e0749a8dc2
feat(core): Add RoleMappingRule entity and database tables (#27440) 2026-03-25 11:19:59 +00:00
Dawid Myslak
ad0a551326
fix(core): Fix execution history when flow includes wait node (#27357) 2026-03-25 11:10:04 +00:00
Elias Meire
cfe1409ede
fix(editor): Clean up quick connect feature flag and fix first load (#27286) 2026-03-25 10:44:15 +00:00
Raúl Gómez Morales
fe253d543b
refactor(editor): Migrate shared editors and setup panel connections to workflowDocumentStore (no-changelog) (#27423) 2026-03-25 10:36:31 +00:00
Benjamin Schroth
c683b6510c
fix(Basic LLM Chain Node): Fix abort signal handling (#27520) 2026-03-25 10:29:49 +00:00
Raúl Gómez Morales
bf7379d6e0
fix(editor): Populate workflowDocumentStore in execution preview iframe (#27540) 2026-03-25 09:45:20 +00:00
Ali Elkhateeb
c12ced7f41
fix(editor): Improve workflow diff design feedback (#27494) 2026-03-25 08:49:36 +00:00
Matsu
92e5684a40
ci: Replace vars context with runner.name in composite action (#27535)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 11:02:40 +02:00
jeanpaul
158e3bb042
fix(Structured Output Parser Node): Show descriptive error when structured output parser receives empty response (#27443)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-25 08:38:01 +00:00
Jaakko Husso
f165f6c5cc
fix(core): Include custom headers when loading OpenAI models (#27534) 2026-03-25 08:37:09 +00:00
Alex Grozav
9ce9372c6b
refactor(editor): Migrate workflow composables to use workflowDocumentStore (no-changelog) (#27265) 2026-03-25 08:00:47 +00:00
Krystian Slowik
fb7788d6c2
fix(core): Add format validation to source control branch name (#27518) 2026-03-25 07:54:09 +00:00
n8n-assistant[bot]
2d9a2ec76e
chore: Bundle 2026-W9 (#27532)
Co-authored-by: Matsu <matias.huhta@n8n.io>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
Co-authored-by: Jaakko Husso <jaakko@n8n.io>
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Guillaume Jacquart <jacquart.guillaume@gmail.com>
Co-authored-by: Sandra Zollner <sandra.zollner@n8n.io>
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-03-25 07:51:06 +00:00
Matsu
732f2a3d3d
ci: Create stable release on GitHub promotion (#27492)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-25 07:26:06 +00:00
manusjs
fc0f0712d8
fix(core): Correct process.version in expression sandbox (#26550)
Co-authored-by: manusjs <manusjs@users.noreply.github.com>
2026-03-24 16:00:31 +00:00
Ricardo Espinoza
9775f96f15
docs: Add README for @n8n/cli package (#27510) 2026-03-24 15:05:15 +00:00
Alexander Gekov
f454b6e7d2
chore: Add create-skill agent skill (#27448) 2026-03-24 15:04:13 +00:00
Benjamin Schroth
8f490b5000
chore: Remove unneeded peer dependency (#27501) 2026-03-24 14:31:24 +00:00
Ricardo Espinoza
8fdb86db4d
chore: Mark @n8n/cli as beta in package description (#27500)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-24 12:56:37 +00:00
Ricardo Espinoza
e638b3ab74
fix(core): Add ownership check to MCP OAuth client deletion (#27446) 2026-03-24 12:55:17 +00:00
Milorad FIlipović
ac65eb9077
fix(editor): Fix callout dismiss action in NDV (#27496) 2026-03-24 12:16:36 +00:00
Ricardo Espinoza
f3b4069a09
feat(editor): Add canvas-only mode (#27184)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: nik8n <niklas@n8n.io>
2026-03-24 10:59:24 +00:00
Stephen Wright
6cf30f30ca
feat: Add role mapping rule scopes (#27476) 2026-03-24 10:34:51 +00:00
Matsu
1efdb2ccd5
ci: Remove prerelease tag when promoting previous beta to latest (#27490) 2026-03-24 09:51:32 +00:00
Matsu
806eeea422
ci: Ensure release candidates in release pipeline using the app token (#27489) 2026-03-24 09:30:02 +00:00
n8n-assistant[bot]
2374f40ec3
🚀 Release 2.14.0 (#27479)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-03-24 08:55:14 +00:00
Matsu
3040d0f05b
chore: Lock @types/node to a version in @n8n/cli (#27473) 2026-03-24 10:26:49 +02:00
Tomi Turtiainen
98d478cba4
refactor(core): Extract axios utility helpers into axios-utils (#27022) 2026-03-24 08:08:10 +00:00
Charlie Kolb
0eb9b1b1b3
fix(editor): Use new move-to-folder modal in canvas header (#27091) 2026-03-24 07:52:17 +00:00
Tomi Turtiainen
42bfb43493
chore: Remove mariadb specific code paths (#26996) 2026-03-24 07:39:40 +00:00
Raúl Gómez Morales
673b40ec42
refactor(editor): Migrate node composables to workflowDocumentStore (connections) (no-changelog) (#27318) 2026-03-24 07:12:10 +00:00
Iván Ovejero
a21e9e6619
build: Add import-x/no-extraneous-dependencies lint rule to n8n-workflow (#27155) 2026-03-24 07:11:00 +00:00
Matsu
bf856cd442
ci: Modify immutable commit subject via spreading (#27467) 2026-03-24 06:37:24 +00:00
Csaba Tuncsik
61a526133d
fix(core): Clean up resolver references on deletion (#26524) 2026-03-23 18:08:20 +00:00
Csaba Tuncsik
28f50f50bc
feat(editor): Show redacted state in execution viewer with reveal flow (#26543)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 18:08:14 +00:00
Garrit Franke
76c10d53da
fix(editor): Prevent toggle animation on Security & Policies page load (#27350)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 17:55:00 +00:00
Danny Martini
1acdafe6ac
fix(core): VM test Group G — RCE prevention & expression fixture fixes (#27178)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 17:20:20 +00:00
Pinar Kaya
09e2c2b554
fix(core): Disable dynamic banners when diagnostics are disabled (#26741) 2026-03-23 17:19:19 +00:00
Rob Hough
ee2e928a51
fix(editor): Add inner content padding to Popover stories (no-changelog) (#27430) 2026-03-23 16:23:16 +00:00
RomanDavydchuk
eafd32e78d
fix(editor): Node references in expressions not updated when the renamed node has quotes (#27371) 2026-03-23 15:46:36 +00:00
Raúl Gómez Morales
e821053087
refactor(editor): Migrate AI assistant stores to workflowDocumentStore (no-changelog) (#26713) 2026-03-23 15:14:51 +00:00
Dawid Myslak
604b291236
docs: Add security fix hygiene guidelines for public artifacts (#27441) 2026-03-23 15:04:17 +00:00
Ali Elkhateeb
835094c34e
feat(core): Introduce CredentialDependency entity to track credential dependencies (#27151)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
2026-03-23 14:37:09 +00:00
Guillaume Jacquart
d2da928429
fix(core): Confirm messages immediately when no destination is listening (#27334)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-23 14:32:43 +00:00
krisn0x
050aef73db
fix(Gmail Node): Update draft resource hint (#27435) 2026-03-23 14:29:50 +00:00
Garrit Franke
2742741316
feat(core): Add lint rules for missing node and credential icons (#27340)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 13:44:06 +00:00
Eugene
a009988336
fix(core): Send client_id and client_secret in body for OAuth2 PKCE flow (#27366)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-23 13:23:58 +00:00
Benjamin Schroth
46a0aa5093
fix(AI Agent Node): Extract tool name correctly for MCP tool calls (#27345) 2026-03-23 13:21:20 +00:00
Benjamin Schroth
60d6823877
fix(ai-builder): Include langsmith threadId on traces in code-builder (no-changelog) (#27424) 2026-03-23 12:26:29 +00:00
Svetoslav Dekov
efa5d02979
fix(editor): Sort loop node outputs by execution order in setup panel (#27418)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:11:03 +00:00
Ricardo Espinoza
e04dddcbcc
feat(core): Remove license check for API key scopes (#27306)
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 12:10:43 +00:00
Elias Meire
5b6ee17c81
feat(core): Add signature validation for waiting webhooks and forms (#24159)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-03-23 11:48:52 +00:00
Iván Ovejero
88f9f2ed65
fix(core): Assign webhook ID to API-created webhook nodes (#27161) 2026-03-23 11:48:29 +00:00
Andreas Fitzek
b484e895aa
feat(core): Add signing key and certificate fields to SAML preferences with encryption and validation (#27316) 2026-03-23 11:25:50 +00:00
Raúl Gómez Morales
f6893858f3
refactor(editor): Migrate workflow composables to workflowDocumentStore (connections) (no-changelog) (#27263) 2026-03-23 10:57:04 +00:00
Guillaume Jacquart
95ac4a46bd
fix(core): Fix IDOR in test-runs endpoint by consolidating access checks (#27305) 2026-03-23 10:56:36 +00:00
Raúl Gómez Morales
e6071004b5
refactor(editor): Migrate NDV stores and views to workflowDocumentStore (no-changelog) (#27281) 2026-03-23 10:03:14 +00:00
Raúl Gómez Morales
34c4f00a63
refactor(editor): Migrate NDV settings to workflowDocumentStore connections (no-changelog) (#27261) 2026-03-23 10:02:03 +00:00
Raúl Gómez Morales
46bea6ce80
refactor(editor): Migrate canvas operations to workflowDocumentStore connections (no-changelog) (#27280) 2026-03-23 10:01:21 +00:00
Benjamin Schroth
4901814268
fix(AWS Bedrock Chat Model Node): Extract region from modelName ARNs (#26972) 2026-03-23 10:00:05 +00:00
Jon
81142c45a6
chore: Update ssh2-sftp-client to 12.1.0 (#27210) 2026-03-23 09:58:32 +00:00
Arvin A
87afcd8db4
fix(core): Force full execution data fetching for evaluation test runs (#27335) 2026-03-23 09:56:05 +00:00
Albert Alises
3ad5926a5e
chore: Add create-issue skill for Linear tickets and GitHub issues (#27285) 2026-03-23 09:53:07 +00:00
Rob Hough
fee5f2ea94
fix(editor): Restore animation duration units for design system dialogs (#27320) 2026-03-23 09:36:33 +00:00
Garrit Franke
0e1ef918f4
fix(editor): Fix stop button size mismatch in split-trigger mode (#27328)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 09:16:09 +00:00
Rob Hough
5d783620a0
fix(editor): Support per-corner border radius in N8nInput (#27321)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-23 09:07:48 +00:00
Raúl Gómez Morales
e254fd0de3
fix(editor): Fix type mismatch (#27324) 2026-03-23 09:05:49 +00:00
Guillaume Jacquart
1bf602e3ed
fix(core): Allow expressions in OAuth credential URL fields (#27354)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-23 08:46:06 +00:00
Michael Kret
b67863b854
feat(Microsoft Agent 365 Trigger Node): Mcp tools logs (#27215) 2026-03-23 08:26:48 +00:00
Garrit Franke
76af1e6fd9
feat(databricks Node): Add basic databricks node (#27004)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-23 08:16:41 +00:00
Elias Meire
9be76c5372
fix(Extract from File Node): Skip empty lines in CSV parsing to prevent errors (#26511)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-03-23 08:16:36 +00:00
Svetoslav Dekov
b3ced35850
fix(core): Fix an issue with workflow execution status (#27349)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 07:43:16 +00:00
Svetoslav Dekov
e05697835f
feat(editor): Pass telemetry source for ai workflow builder executions from setup (no-changelog) (#27358)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-23 07:43:01 +00:00
Iván Ovejero
682aa4ac94
perf(core): Make webhook cache writes non-blocking (#27360) 2026-03-21 12:19:20 +00:00
Alexander Gekov
c47176e841
fix(HTTP Request Node): Fail on non-2xx status codes during pagination with "other" completion (#27352) 2026-03-20 15:29:24 +00:00
José Braulio González Valido
01c623fdae
fix(editor): Fix workflow tag filtering excluding workflows inside folders (#27333)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-20 15:14:07 +00:00
Sandra Zollner
fc526529d6
fix(editor): Improve colorings update logic in resolvableHighlighter … (#27331) 2026-03-20 14:20:22 +00:00
Albert Alises
20f1092815
feat: Add @n8n/cli: a client CLI to manage n8n from the terminal (#26943)
Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
2026-03-20 14:11:35 +00:00
Charlie Kolb
45023afa9f
fix(editor): Properly align line after bullet point in Sticky markdown (#27231) 2026-03-20 14:07:38 +00:00
Jacob Lee
05c6d87163
chore: Bump @langchain/core to latest (#27252) 2026-03-20 13:18:28 +00:00
Charlie Kolb
03584b4683
fix(editor): Properly align line after bullet point in Sticky markdown (#27231) 2026-03-20 13:16:10 +00:00
Matsu
24dcf7510a
ci: Prevent new version patches, if only content is ci changes (#27329) 2026-03-20 11:44:57 +00:00
Declan Carroll
bab42216c0
test: fix scope-lockdown violations in page objects (#27326) 2026-03-20 11:43:14 +00:00
Garrit Franke
b13b280443
feat: Add publish workflow to node-cli (#27288) 2026-03-20 10:47:21 +00:00
Kesku
483250d539
feat(Perplexity Node): Update Perplexity node for full API coverage (#26970)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-03-20 10:18:29 +00:00
Svetoslav Dekov
2ff73d5440
feat(editor): AI workflow builder setup wizard (#26832)
Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 10:18:25 +00:00
Iván Ovejero
6fcc86037d
fix(core): Fix unhandled rejection in task broker on runner disconnect (#27278) 2026-03-20 09:19:41 +00:00
Eugene
e60d9e7f39
fix(editor): Fix tooltip on credits counter info icon (#27244)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 09:01:36 +00:00
Declan Carroll
9b6888ff65
feat(API): Add GET /api/v1/discover endpoint for capability discovery (#27014)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-20 08:31:55 +00:00
José Braulio González Valido
beb34ebefa
docs: Add .env.local.example template and dotenvx for local dev setup (no-changelog) (#27241) 2026-03-19 15:53:14 +00:00
Milorad FIlipović
deb4ef7009
feat(core): Always expose mcp sdk reference as a tool (no-changelog) (#27271) 2026-03-19 15:26:12 +00:00
Rob Hough
e4c4be99bf
fix(editor): Unify input component background surfaces (#27237) 2026-03-19 15:25:40 +00:00
phyllis-noester
acaa0db33a
feat(core): Add node that allows checking dynamic credentials inside node (#27165)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 15:21:42 +00:00
Andreas Fitzek
844b5b92c5
fix(core): Move OIDC SSO provisioning outside user creation transaction (#27279) 2026-03-19 15:02:54 +00:00
Elias Meire
95f70b0e1c
fix: Fix credential displayNames with missing spaces (#27259) 2026-03-19 14:48:09 +00:00
Alex Grozav
e4e929229b
refactor(editor): Migrate integrations, evaluation, and experiments to workflowDocumentStore (no-changelog) (#27163) 2026-03-19 13:18:22 +00:00
Andreas Fitzek
d9bdd040f5
feat(core): Introduce expression-based role resolver for SSO claim mapping (no-changelog) (#27240) 2026-03-19 12:58:35 +00:00
Claire
b6e8074f8a
feat(core): Add project context to execution log metadata (#27169)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-19 12:33:58 +00:00
Eugene
c2731df00d
fix(Anthropic Node): Update credential test to use available model (#27234) 2026-03-19 11:42:27 +00:00
Daria
556b4d3fa4
feat: Add new execution filter by workflow version (#26904) 2026-03-19 11:31:27 +00:00
Alex Grozav
5c292896d6
refactor(editor): Migrate NDV stores and views to workflowDocumentStore (no-changelog) (#27138) 2026-03-19 11:19:02 +00:00
Alex Grozav
8fa0b13a7e
refactor(editor): Migrate canvas operations to workflowDocumentStore (no-changelog) (#26947) 2026-03-19 10:58:13 +00:00
Matsu
8b2903b4e9
ci: Propagate dependency bumps transitively (#27270) 2026-03-19 10:38:56 +00:00
Svetoslav Dekov
51a65d9bda
fix(editor): Remove toast bottom offset when AI chat panel is open (#27132)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 10:18:16 +00:00
Jaakko Husso
90b2b9c516
fix(core): Allow expressions in tool default values on chat hub tools (#27167) 2026-03-19 10:08:07 +00:00
Daria
036a0db0b3
feat(editor): Add history version info to execution page (#26768) 2026-03-19 09:53:35 +00:00
Charlie Kolb
f79b4d7a71
feat(editor): Display workflow, credential and data table dependencies (#26912)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-19 09:53:21 +00:00
Alex Grozav
8b9c63a58b
refactor(editor): Migrate execution and logs composables to workflowDocumentStore (no-changelog) (#27162) 2026-03-19 09:31:47 +00:00
Alexander Gekov
588308e3c1
fix(Jira Node): Add continueOnFail support for all operations (#27108) 2026-03-19 09:29:40 +00:00
Milorad FIlipović
5af2a8a4b8
fix(core): Stop auto applying credentials for updated MCP workflows (#27258) 2026-03-19 09:19:59 +00:00
Ricardo Espinoza
dce55d2e19
feat(core): Add search_projects, search_folders MCP tools and folderId to create_workflow (#27248)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-19 09:08:42 +00:00
Rob Hough
32ec3d390f
fix(editor): Fix markdown list item wrapping in chat messages (no-changelog) (#27082) 2026-03-19 08:54:17 +00:00
Ricardo Espinoza
322aac1da0
feat(core): Add filtering parameters to get_execution MCP tool (#27192) 2026-03-19 08:35:16 +00:00
Alex Grozav
cfcaa97d63
refactor(editor): Extract workflow document connections facade composable (no-changelog) (#27221)
Co-authored-by: r00gm <raul00gm@gmail.com>
2026-03-19 08:03:02 +00:00
Alex Grozav
91a3a3d223
feat(editor): Migrate node composables to use workflowDocumentStore directly (no-changelog) (#27159) 2026-03-19 07:49:18 +00:00
Charlie Kolb
20b50372df
fix(Execute Workflow Node): Fallback to latest draft if there no active sub-workflow version (#27134) 2026-03-19 07:49:13 +00:00
Svetoslav Dekov
d8f8ff0980
fix(editor): Clear resource locator cache after URL redirect creation (#27175)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-19 07:07:44 +00:00
Ricardo Espinoza
6ede5e1ec7
feat(core): Batch public API telemetry events on pulse cycle (#27226)
Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
2026-03-18 21:14:02 +00:00
Rob Hough
a830652504
refactor(editor): Re-organise and label design-system stories (no-changelog) (#27179)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-18 16:09:51 +00:00
Raúl Gómez Morales
ec0831f95f
feat(editor): Use server-side search for project sharing dropdowns (#27093) 2026-03-18 15:13:48 +00:00
Andreas Fitzek
72bdad9d40
feat(core): Add structured error responses for authorization failures (#27170) 2026-03-18 13:46:00 +00:00
Albert Alises
30b8dc4f33
feat: Add design principles section to AGENTS.md with the security guidelines (#25997) 2026-03-18 13:42:05 +00:00
Matsu
e5dd89022b
ci: Strip backport information from commit labels on changelog (#27203) 2026-03-18 13:41:20 +00:00
Milorad FIlipović
4d40db2c39
perf(core): Fix slow user mock in cli tests (no-changelog) (#27205) 2026-03-18 13:41:10 +00:00
Daria
d0e7ce08fb
feat(core): Send user agent for public api events (no-changelog) (#27217) 2026-03-18 13:03:24 +00:00
Andreas Fitzek
87595474e7
feat(core): Apply execution redaction to real-time push events (no-changelog) (#27102) 2026-03-18 12:59:53 +00:00
Ricardo Espinoza
95fca83fa0
fix(core): Use published version for error workflow execution (#27196)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 12:56:39 +00:00
Raúl Gómez Morales
277a45d8ef
refactor(editor): Migrate shared editors and context menu to injectWorkflowDocumentStore (no-changelog) (#27207) 2026-03-18 12:05:30 +00:00
Guillaume Jacquart
eddb26d05c
fix(core): Add plain text body to password reset and notification emails (#27125)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-18 11:53:04 +00:00
Alex Grozav
f2d5497d35
refactor(editor): Migrate NDV settings and runData to workflowDocumentStore (no-changelog) (#27140) 2026-03-18 11:23:56 +00:00
Alex Grozav
7f262fb92f
refactor(editor): Migrate NDV panel components to workflowDocumentStore (no-changelog) (#27158) 2026-03-18 11:19:20 +00:00
Benjamin Schroth
3f1d60f807
fix(ai-builder): Show feedback buttons in variant (no-changelog) (#27201) 2026-03-18 10:32:47 +00:00
Matsu
927b7bc818
ci: Create github releases from mjs scripts (#27121) 2026-03-18 09:19:31 +00:00
Matsu
8995c25512
ci: Schedule creation of minor and patch PRs (#27199) 2026-03-18 08:31:18 +00:00
RomanDavydchuk
827e8680e3
fix(Postgres Node): Expressions are not resolved in v1 (#26496)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-03-18 08:05:05 +00:00
Jon
91d4c1bdbd
fix: Fix issue with hideOnCloud not working for node display options (#27124)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-03-18 07:42:05 +00:00
Nikhil Kuriakose
5fa8855a1f
fix(editor): Add data to a data table by csv upload (#26495)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 19:26:57 +00:00
Daria
4eb815c4ee
fix(core): Add missing fields to public API workflow schema (#27157) 2026-03-17 17:57:32 +00:00
Stephen Wright
a8f5ee3aeb
feat: Enable secure invite links (#27107) 2026-03-17 15:58:47 +00:00
Jaakko Husso
ebf219f690
chore(editor): Differentiate canvas and chat hub events (#27100) 2026-03-17 14:31:13 +00:00
Rob Hough
98544506a2
fix(editor): Adjust external secrets input styling (#27110) 2026-03-17 13:56:48 +00:00
Rob Hough
13a0a72159
docs(editor): Add shared design-system AI style review rules (no-changelog) (#27008) 2026-03-17 13:54:43 +00:00
Iván Ovejero
90aca62efe
build: Pin uuid in n8n-workflow to catalog version (#27129) 2026-03-17 13:51:40 +00:00
Tomi Turtiainen
dd419ae567
fix(core): Handle external hook file paths on Windows (#26983)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-03-17 13:13:51 +00:00
Tomi Turtiainen
61a40684d6
refactor(core): Extract global axios config into axios-config.ts (no-changelog) (#26852) 2026-03-17 13:09:36 +00:00
Matsu
6dd462e3ef
chore: Add 1.x branch compatibility to workflow scripts (#27153) 2026-03-17 13:06:26 +00:00
Iván Ovejero
04bf206acf
fix(core): Emit leader-takeover on leadership mismatch in checkLeader (#27126) 2026-03-17 11:37:22 +00:00
Charlie Kolb
bc76e620fb
fix(editor): Remove inconsistent scrim on node creator open (#27086) 2026-03-17 11:03:41 +00:00
Paul Issert
608c6497ae
chore(editor): Add A/A exp to validate experimentation system (no-changelog) (#26387)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Romeo Balta <7095569+romeobalta@users.noreply.github.com>
2026-03-17 10:24:58 +00:00
Svetoslav Dekov
b2d7bdebe7
fix(editor): Command bar wasn't finding any workflows (#26788) 2026-03-17 10:11:31 +00:00
Guillaume Jacquart
2f7db771c8
fix(core): Preserve nested proxy/redirect shape in log streaming webhook (#27109)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 09:50:29 +00:00
Guillaume Jacquart
d1d56c8f60
chore(core): Add additional validation on resolver config and better error specs (#27013)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-17 09:37:27 +00:00
Tomi Turtiainen
5800ab8c9a
fix(core): Retry multi-main follower license check during startup (#26990) 2026-03-17 09:19:44 +00:00
Milorad FIlipović
7e9f14c9b4
fix(editor): Prevent clicks on pinned rows in data tables (#26347) 2026-03-17 09:18:32 +00:00
Danny Martini
5ffe546a7e
feat(core): Wire builtin globals onto __data in VM expression isolate (#26954)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 08:53:18 +00:00
Matsu
104bab450c
chore: Update PR template with new backport labels (#27123)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-17 08:18:18 +00:00
Svetoslav Dekov
969c32f5a5
fix(editor): Show warning toast when executed node was not reached (#27094)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-17 07:42:33 +00:00
Charlie Kolb
eea5fffa40
fix(editor): Update StopManyExecs modal formatting, (#26994) 2026-03-17 07:33:04 +00:00
Michael Kret
a7b9e00be6
fix: Partial execution of Chat node and Chat tool (#26334) 2026-03-17 07:26:39 +00:00
Jaakko Husso
5c0e0bcec2
feat(core): Add chat hub settings to disable Responses API and change memory context window (#26525) 2026-03-17 07:17:16 +00:00
Declan Carroll
7c7c70f142
ci: Unify QA metrics pipeline to single webhook, format, and BigQuery table (no-changelog) (#27111)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-17 05:50:10 +00:00
Alex Grozav
dcd306bc5c
fix(editor): Prevent unwanted UI elements appearing when execute button is loading (#27003) 2026-03-16 18:27:20 +00:00
Declan Carroll
fbccfbc7f5
test(benchmark): Add Kafka and webhook benchmark framework (no-changelog) (#26761)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 15:29:50 +00:00
Arvin A
100bf967f6
feat(editor): Redesign builder Q&A wizard with number badges and keyboard navigation (#26952) 2026-03-16 15:19:57 +00:00
Andreas Fitzek
94f4ff8466
fix(core): Handle invalid JSON responses from OAuth2 token endpoints (#27089) 2026-03-16 15:15:06 +00:00
Benjamin Schroth
efb3f38217
fix(editor): Fix double execution of afterMessageSent hook (#26103) 2026-03-16 14:57:35 +00:00
n8n-release-tag-merge[bot]
9a22a273b8 Merge tag 'n8n@2.13.0' 2026-03-16 14:17:57 +00:00
n8n-assistant[bot]
24272b6592
🚀 Release 2.13.0 (#27098)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-03-16 13:48:51 +00:00
Marc Littlemore
ceb17e7fd4
feat(core): Allow manual configuration of HashiCorp Vault KV mount path and version (#26798)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-16 13:25:10 +00:00
Danny Martini
d109822050
feat(core): Serialize Luxon types at V8 isolate boundary (#26993)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 12:55:38 +00:00
Jaakko Husso
dd43e4878e
feat(core): Support Chat hub on workflow canvas (#26137) 2026-03-16 12:55:17 +00:00
Arvin A
8934bf5508
feat: Conditional credit usage banner (#26891) 2026-03-16 12:21:59 +00:00
Declan Carroll
0ba453093f
ci: Skip Chromatic in merge queue to avoid stale baseline failures (#27092)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 12:08:43 +00:00
Irénée
463c3d56e5
feat(core): Enable role-based access for external secrets by default (#27084)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 11:56:33 +00:00
Danny Martini
82dfa760b7
fix(core): Simplify $items global type declaration in expression runtime (#27087)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-16 11:39:52 +00:00
Ali Elkhateeb
7827ae0e74
feat(core): Delete secrets provider connections on project deletion (#26706) 2026-03-16 11:08:49 +00:00
Daria
6023d46fd1
chore: Enable MCP builder (#27079)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2026-03-16 10:22:08 +00:00
Matsu
9d975450e3
chore: Audit and secure .github/scripts shadow dependencies (#27083) 2026-03-16 10:06:27 +00:00
Declan Carroll
2d6a0e1041
fix: Lazy load heavy imports and add future guidance (#26903)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 09:51:25 +00:00
Irénée
af0ac3ff3a
feat: External secrets access based on system roles (no-changelog) (#26646)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ali Elkhateeb <ali.elkhateeb@n8n.io>
2026-03-16 09:43:06 +00:00
Danny Martini
15f533dc0b
feat(core): Add $now/$today to V8 isolate (#27015)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 09:42:17 +00:00
Stephen Wright
82a685a540
feat: Add saml feature flag (#27009) 2026-03-16 09:09:06 +00:00
Konstantin Tieber
e843b67906
fix(core): Support all known execution statuses on public API (#27080) 2026-03-16 09:08:23 +00:00
Danny Martini
731c96d322
test(core): Wrap bare assertion in test block in expression-extension.test.ts (no-changelog) (#26909)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-16 09:00:54 +00:00
Ali Elkhateeb
6776b66907
feat(editor): Show folder tree view in source control push/pull modals (#26758) 2026-03-16 08:43:23 +00:00
Raúl Gómez Morales
3b00e1bafe
feat(core): Add server-side search, pagination, and filtering to GET /projects (#27036) 2026-03-16 08:23:27 +00:00
Alex Grozav
1e9d6c1ea7
refactor(editor): Migrate AI assistant components to useWorkflowDocumentStore (no-changelog) (#26908) 2026-03-16 08:15:07 +00:00
Alex Grozav
7ad6020e0d
refactor(editor): Refactor app stores and utils to use workflowDocumentStore (no-changelog) (#26941) 2026-03-16 07:56:11 +00:00
Alex Grozav
32f437bcaa
refactor(editor): Migrate AI assistant composables to workflowDocumentStore (no-changelog) (#26910) 2026-03-16 07:55:57 +00:00
Suguru Inoue
b2c8edd98b
feat(editor): ChatHub file knowledge UX improvements (no-changelog) (#26781) 2026-03-16 07:52:50 +00:00
Raúl Gómez Morales
cd2c22c0ae
fix(editor): Fix toogle share action based on scopes (#26902) 2026-03-16 07:38:20 +00:00
n8n-assistant[bot]
b086e74a91
chore: Update node popularity data (#27076)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-16 04:01:57 +00:00
jabbson
b7e3e630c8
fix(Notion Node): Allow underscores in page URL slug validation (#27051)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-14 21:55:49 +00:00
krisn0x
19786609d9
fix(Airtable Node): Revert flattening output from search and get operations (#26697) 2026-03-13 17:13:33 +00:00
Sandra Zollner
f7a787aca8
feat(editor): Enable project editors to view external secret vaults (#27007) 2026-03-13 16:51:29 +00:00
Sandra Zollner
1679474042
feat(editor): Add telemetry events for workflow diff in version history (#26778) 2026-03-13 15:44:14 +00:00
Jaakko Husso
75edc5837f
feat(core): Add type field to chat hub sessions (#26905) 2026-03-13 15:09:38 +00:00
Stephen Wright
5ca96b10e7
chore(editor): Change custom auth JSON (#27010) 2026-03-13 14:28:49 +00:00
Stephen Wright
39e8f95ba7
fix: Bug with odd error message on project limit cloud (#26911) 2026-03-13 14:16:49 +00:00
Matsu
e334678440
ci: Use n8n assistant for releases (#26998) 2026-03-13 13:53:30 +00:00
Alex Grozav
107f16cc0c
fix(editor): Prevent reference sharing connections in workflow save data (no-changelog) (#26991) 2026-03-13 12:41:35 +00:00
Declan Carroll
3c2b6c7ee3
feat(core): Add workflow execution duration histogram metric (#26889)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 11:58:22 +00:00
Declan Carroll
060675aa3f
test: Fix no-direct-page-instantiation violations and improve impact analysis (#26914)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 10:49:29 +00:00
Tony Bigby
f0aca64006
fix(core): Ignore parameter name when renaming binary file (#26647) 2026-03-13 10:16:04 +00:00
Matsu
945e1a435f
ci: Prevent forks from targeting release/** (#26975) 2026-03-13 09:29:41 +00:00
Matsu
4fcbad8251
ci: Add track name to run-name in patch release workflow (#26979) 2026-03-13 09:16:39 +00:00
Rob Hough
8c3c0dc747
fix(editor): Use text shade token in N8nInput (#26934) 2026-03-13 09:01:29 +00:00
Tomi Turtiainen
f5baa1bbf5
fix(core): Skip task runner startup on main in offload mode (#26876) 2026-03-13 08:33:26 +00:00
Tuukka Kantola
3d8273917e
fix(editor): Update Add node context menu shortcut hint from Tab to N (no-changelog) (#26955)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 08:28:43 +00:00
mfsiega
4e5c3cc666
feat(core): Make workflow index batch size configurable via env var (#26893)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-13 07:35:48 +00:00
Danny Martini
e9bdf8779b
feat(core): Propagate workflow timezone into V8 isolate (#26562)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 14:26:58 +00:00
Declan Carroll
e4dbe0db6b
ci: Update GitHub Actions to latest versions for Node.js 24 compatibility (#26949)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 14:01:53 +00:00
Daria
d849487e6d
fix(core): Fix MCP validate_workflow tool output schema warnings (#26938) 2026-03-12 13:46:35 +00:00
Matsu
b97e864f93
chore: Update CODEOWNERS with ci-admins (#26946) 2026-03-12 13:40:51 +00:00
Andreas Fitzek
731d029a4d
feat(core): Port function extensions to VM isolate and add URL and Intl polyfills (#26689)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 12:44:28 +00:00
Stephen Wright
abf20f44ca
feat: Custom auth redacts values correctly (#26895) 2026-03-12 11:39:32 +00:00
Declan Carroll
88ff772ceb
ci: Reduce noisy Codecov PR comments and fix double bundle upload (#26939)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:07:51 +00:00
Charlie Kolb
155b35d39c
feat(editor): Expose required parameters in setup panel (no-changelog) (#26205)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 11:01:30 +00:00
Tuukka Kantola
97fc970b89
chore(editor): Improve workflow builder enter/exit animation (#26171)
Co-authored-by: Claude <noreply@anthropic.com>
2026-03-12 10:06:17 +00:00
Benjamin Schroth
da61e72f22
chore: Upgrade langchain packages (#26892) 2026-03-12 09:30:19 +00:00
Guillaume Jacquart
b424d2fdbc
fix(editor): Hide redaction policy when the feature env variable is not there (#26933) 2026-03-12 09:22:13 +00:00
Csaba Tuncsik
f7d9f74a17
feat(core): Add workflow:unpublish project scope (#26625)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 08:38:42 +00:00
Svetoslav Dekov
7e86a53893
test(editor): Fix flaky resource mapper E2E test (#26927)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-12 07:56:42 +00:00
jabbson
69d05813ca
fix(editor): Remove stray closing brace in bug report URL generation (#26916)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 19:31:01 +00:00
Declan Carroll
ae7d19ca75
chore: Dependency bumps in runner image (zlib, pip) (#26888)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:40:45 +00:00
Declan Carroll
8ed162d274
chore: Update dependencies to latest stable versions (#26878)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 17:03:31 +00:00
Declan Carroll
3612e4b1ce
fix(core): Preserve NODE_PATH for globally installed npm packages in Docker (#26898)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 16:41:07 +00:00
Matsu
4e1e0cd1c0
ci: Add version release notification workflow (#26897)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-11 16:30:19 +00:00
Charlie Kolb
5ab71b4ba6
fix(editor): Repair fromAI override and button styling (#26682)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-11 15:51:32 +00:00
Albert Alises
33391e6e15
fix(MongoDBVectorStore Node): Replace MongoDB Atlas Vector Store singleton with per-execution client (#26906) 2026-03-11 15:35:12 +00:00
Alex Grozav
f6c4f28e4a
refactor(editor): Migrate app components to workflowDocumentStore (no-changelog) (#26839) 2026-03-11 14:08:14 +00:00
Andreas Fitzek
4a9f66640f
chore(core): Polyfill crypto and URLSearchParams in VM expression engine isolate (#26626)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-03-11 13:47:57 +00:00
Danny Martini
648962eefb
feat(benchmark): Add expression engine benchmark suite with production patterns (#26451)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 13:24:40 +00:00
mfsiega
982922b1e5
fix(core): Use correct published nodes for workflow indexing (#26767)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 12:09:25 +00:00
mfsiega
e0cd513661
feat(core): Populate workflow published version mapping (#25242)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 11:08:04 +00:00
Suguru Inoue
89e03680ac
fix(core): Make ChatHub work with LM Studio's OpenAI compatible endpoint (#26887) 2026-03-11 11:04:25 +00:00
Suguru Inoue
75f2f3be68
fix(editor): Fix ChatHub chat UI layout (no-changelog) (#26875) 2026-03-11 10:49:35 +00:00
ByteEVM
5993309e54
fix(editor): I18n for sign out label in bottom menu (#26885) 2026-03-11 10:42:58 +00:00
Dawid Myslak
fb1f76baf2
chore: Add spec-driven-development agent skill (#26881) 2026-03-11 10:33:49 +00:00
Michael Kret
b039bd7622
fix(Microsoft Agent 365 Trigger Node): Fix memory, update MCP tool listing, replace deprecated MS library functions (#26422) 2026-03-11 10:20:58 +00:00
Ahsan Virani
95723753d2
feat: Allow skipping foreignkey constraint disablement for imports (#25734) 2026-03-11 09:53:42 +00:00
Alex Grozav
748b0aa6a7
refactor(editor): Migrate credentials and setup panel to workflowDocumentStore (no-changelog) (#26769) 2026-03-11 09:53:24 +00:00
Tomi Turtiainen
28d63fa081
fix(core): Fix task runner hanging when connection attempt fails (#26848) 2026-03-11 09:06:07 +00:00
Matsu
fd4e013bd5
ci: Set auto-merge to squash (#26867) 2026-03-11 08:55:52 +00:00
Declan Carroll
f79dd7fac1
test: Fix selector-purity violations in Playwright tests (no-changelog) (#26856)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-11 08:29:35 +00:00
Daria
86f1c24eb7
fix: MCP - Resolve webhook id during workflow creation and update (#26838) 2026-03-11 08:25:57 +00:00
Tomi Turtiainen
edd74ec065
fix: Improve SSRF blocked IP error message (#26837) 2026-03-11 08:06:46 +00:00
Stephen Wright
694d4fe768
feat: Add redaction reveal failure audit logs (#26826) 2026-03-10 15:34:58 +00:00
Declan Carroll
0b1920f03d
test: Fix deduplication violations and update janitor baseline (no-changelog) (#26847)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 15:34:16 +00:00
Tomi Turtiainen
d18ebb0c57
ci: Retry SafeChain install download in setup action (#26845) 2026-03-10 15:02:20 +00:00
Svetoslav Dekov
33ba2d5e4d
fix(editor): Preserve resource mapper values during floating node navigation (#26789)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:58:50 +00:00
Declan Carroll
1d8485c987
test: Move raw locators from spec files into page objects (no-changelog) (#26835)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 14:31:49 +00:00
Suguru Inoue
05426be8b4
feat: Add connection tests to ChatHub vector store nodes (no-changelog) (#26830) 2026-03-10 14:15:58 +00:00
Ijas
bf5344768d
fix(core): Prevent OAuth token wipe during source control pull (#26566) 2026-03-10 14:05:25 +00:00
Rob Hough
fab08c4bc2
fix(editor): Remove migrate-button-v2 script (#26779) 2026-03-10 13:56:02 +00:00
Irénée
0bc948be66
fix(core): Exclude disabled secret connections from autocomplete, resolution, and registry (#26783)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:34:08 +00:00
Declan Carroll
3930cb012c
test: Move hovering-item selector to RunDataPanel page object (no-changelog) (#26793)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:29:55 +00:00
Matsu
3b2beebc5f
ci: Bump korthout/backport-action to enable add_author_as_reviewer (#26829) 2026-03-10 13:26:44 +00:00
Matsu
adb9b26cb1
ci: Call Cloud DB populate workflow from actions (#26808) 2026-03-10 15:24:06 +02:00
Declan Carroll
9a1b434f7a
ci: Add nightly schedule to Docker build smoke test (no-changelog) (#26794)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 13:05:25 +00:00
Matsu
633f1a4b48
ci: Add release environment to post release jobs (#26756) 2026-03-10 13:00:18 +00:00
Matsu
42a8bb1bf8
ci: Wait for git tag updates before ensuring RC branches (#26806) 2026-03-10 12:59:15 +00:00
Matsu
b27a28de4f
ci: Workflow to create Patch release for track (#26824) 2026-03-10 12:59:03 +00:00
Eugene
a99cf3d0e4
feat(ai-builder): Add web-fetch tool for fetching external documentation (#26630)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-10 12:49:15 +00:00
Suguru Inoue
a714131ad9
chore(editor): ChatHub file knowledge telemetry events (#26816) 2026-03-10 12:31:47 +00:00
Marc Littlemore
ec909ec994
fix(core): Prefix external secrets retry logs (#26802)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 12:29:43 +00:00
Matsu
524b6bab0e
ci: Add Workflow script test runner to CI (#26538) 2026-03-10 12:12:36 +00:00
Tomi Turtiainen
03b6e2d74e
fix(HTTP Request Node): Improve invalid JSON field error messages (#26817) 2026-03-10 12:05:41 +00:00
Declan Carroll
e7545ba549
fix: Gate /healthz/readiness behind fullyReady flag (#26742)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:55:12 +00:00
mjain
236e9e589a
feat(Agent): Add custom tracing metadata support in Agent Node (#25810)
Co-authored-by: Arvin Ansari <arvin.ansari@n8n.io>
2026-03-10 11:52:28 +00:00
Ahsan Virani
319e400178
fix(core): Fix entity import failing in Kubernetes due to ZIP self-inclusion and local header size placeholders (#26628) 2026-03-10 11:36:07 +00:00
Declan Carroll
8005cae5e6
test: Add contract test for n8n node vs public API coverage (#26490)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 11:35:14 +00:00
Alex Grozav
a268e07464
refactor(editor): Add useProvideWorkflowId and useInjectWorkflowId composables (no-changelog) (#26657) 2026-03-10 10:53:04 +00:00
Declan Carroll
60f4569fbe
ci: Add reusable retry script for CI commands (#26815)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-10 10:52:57 +00:00
Sandra Zollner
56176bf6b5
feat(editor): Allow instance admin to re-enable disabled secret provider connections (#26760) 2026-03-10 10:25:02 +00:00
Tomi Turtiainen
18db53c966
build: Install build tools for isolated-vm rebuild in n8n Docker image (#26809) 2026-03-10 09:22:45 +00:00
Bram
7deebe9ace
feat(Baserow Node): Add batch operations, more filters, add DB token credential (#19758)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-03-10 08:44:07 +00:00
Tomi Turtiainen
6c5c99f83f
test: Add end-to-end SSRF integration coverage (#26771) 2026-03-10 08:42:23 +00:00
Ali Elkhateeb
1d24edb68d
fix(editor): Show version name instead of current changes label for named versions (#26785) 2026-03-10 08:38:22 +00:00
Alex Grozav
41addadb44
fix: Replace setTimeout with deterministic waits in MessagePort transport tests (no-changelog) (#26774) 2026-03-10 07:50:25 +00:00
Tomi Turtiainen
844c5e22a4
fix: Fix segfault in arm64 image due to missing native addon (#26765) 2026-03-10 07:07:58 +00:00
n8n-assistant[bot]
75a2641925
chore: Update node popularity data (#26613)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-03-10 06:52:57 +00:00
Declan Carroll
9fdfaafc1b
test: Fix selector-purity violations and enable method-level impact analysis (no-changelog) (#26775)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 19:27:29 +00:00
Irénée
5740de50df
feat(editor): Add opt-in toggle for external secrets system roles (#26684) 2026-03-09 17:43:46 +00:00
Charlie Kolb
68cfa2368e
feat(core): Support data tables in workflow indexer (no-changelog) (#26470) 2026-03-09 16:13:02 +00:00
n8n-assistant[bot]
0d4719cebc
🚀 Release 2.12.0 (#26780)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-03-09 17:46:27 +02:00
Joco-95
83879018f2
feat(core): Implements telemetry group identify calls (#26634) 2026-03-09 14:31:21 +00:00
Tomi Turtiainen
0345d5e053
test(Discord Node): Fix flaky roleRemove test with proper nock setup (no-changelog) (#26770) 2026-03-09 13:41:14 +00:00
Declan Carroll
af7dfb7d35
ci: Normalize input paths for impact analysis orchestration (no-changelog) (#26602)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:28:40 +00:00
Irénée
ecbd3facf3
feat: Allow users with custom project scope to access secrets completions (no-changelog) (#26574)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 13:18:28 +00:00
Guillaume Jacquart
80ae158121
refactor(core): Implement decorator-based auto-discovery for breaking change rules (#26270)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:53:13 +00:00
Tomi Turtiainen
1e8e7ee018
refactor(core): Unify SSRF bridge result contract (#26660) 2026-03-09 12:39:32 +00:00
Alex Grozav
f2a65da361
refactor(editor): Use workflowDocumentStore for node access in context menus and completions (no-changelog) (#26763) 2026-03-09 12:39:29 +00:00
Matsu
f052079bd5
ci: Extract merge-tag-to-branch into reusable workflow and support patch release merges to RC branch (#26764) 2026-03-09 11:56:19 +00:00
Suguru Inoue
fc1bd21858
fix(editor): Adjust chat input styling after design system update (no-changelog) (#26759) 2026-03-09 11:23:06 +00:00
Suguru Inoue
da0cd96537
feat(core): Agent file knowledge in ChatHub (no-changelog) (#26516) 2026-03-09 10:49:07 +00:00
Irénée
6fa907c233
fix(core): Support project-scoped externalSecret:list in credential validation (no-changelog) (#26644) 2026-03-09 10:45:49 +00:00
Rob Hough
396fa210f6
fix(editor): Reduce fixed collection add button sizes (#26411) 2026-03-09 10:31:21 +00:00
RomanDavydchuk
ce11638ace
feat: Add AGENTS.md for community node templates (no-changelog) (#26693)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-09 09:42:22 +00:00
Marc Littlemore
a567244cbc
fix(core): Handle null KV mount options in Vault provider (#26695) 2026-03-09 09:16:15 +00:00
Matsu
755b970f18
ci: Clarify messaging around backporting (#26753)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-03-09 08:56:08 +00:00
RomanDavydchuk
95f7ce8808
fix(editor): Add new collection parameter button incorrectly displayed in old collections UI (#26631) 2026-03-09 08:53:13 +00:00
Guillaume Jacquart
39ca047079
fix(core): Return resolver_missing status when dynamic credentials lack resolver (#26673)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:49:32 +00:00
Declan Carroll
908a810e07
fix: Remove isolated-vm from Dockerfile npm rebuild (#26745)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 08:40:40 +00:00
Matsu
5fbcaeee05
ci: Automatically approve release PR after creation (#26755) 2026-03-09 08:11:23 +00:00
Matsu
553f862e10
ci: Add label on node popularity automation (#26754) 2026-03-09 08:11:15 +00:00
Tomi Turtiainen
809ea48d08
feat(core): Integrate SSRF protection into request helpers (#26581) 2026-03-09 07:59:03 +00:00
RomanDavydchuk
34af844c95
fix(editor): Do not show "Set up error notifications" suggestion when activating an error workflow (#26419)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-06 21:21:00 +00:00
Jon
7bc9cac72e
chore: NODE-4536 - Generate Schema Files (no-changelog) (#26379)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-06 21:18:04 +00:00
Jon
ab26070d14
fix: Fix compliance with RFC 9727 and 8414 for MCP DCR (#26290)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-06 21:14:27 +00:00
Krystian Slowik
565afb5ad9
docs(Microsoft Teams Node): Remove non-existent Subscription.ReadWrite.All from description (no-changelog) (#25306) 2026-03-06 17:28:05 +00:00
jeanpaul
23d29bcdc7
fix(editor): Hide AI context menu option when AI builder is not licensed (#26627)
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-06 16:29:20 +00:00
Daria
9e2aa8e780
feat(core): Add a separate MCP tool for full execution data (#26674) 2026-03-06 15:53:05 +00:00
Guillaume Jacquart
9dc8b4462a
feat(core): Add configurable HTTP status code for OAuth2 token refresh (#26641)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 15:41:36 +00:00
Tuukka Kantola
136a678b1f
fix(editor): Replace wrong button variant in AIWB mode selector (no-changelog) (#26670)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-06 15:26:24 +00:00
Garrit Franke
ec0cf13141
feat: Add optional --publish flag to n8n-node release command (#26688) 2026-03-06 14:43:51 +00:00
Tomi Turtiainen
43222940bc
chore: Rename migration transaction flag (#26683) 2026-03-06 14:31:53 +00:00
Daria
724f361cb8
feat(core): Add (un)publish workflow tools to MCP (#26681) 2026-03-06 14:15:23 +00:00
Danny Martini
2614154b71
feat(core): Wire expression-runtime behind N8N_EXPRESSION_ENGINE=vm flag (no-changelog) (#26528)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-06 13:55:04 +00:00
Irénée
6fa0d2e0a7
feat(core): Expose isEnabled on Secrets Provider Connection (#26680) 2026-03-06 13:49:58 +00:00
Dimitri Lavrenük
fcf2d31774
feat: Implement additional checkbox confirmation for quick connect flow (#26472) 2026-03-06 13:10:06 +00:00
Suguru Inoue
854835dcf0
fix: Rebuild isolated-vm in Dockerfile (#26672) 2026-03-06 13:04:21 +00:00
Nikhil Kuriakose
00ccef8915
fix(editor): Fix parameter label hover glitch with Fixed/Expression toggle (#26676) 2026-03-06 12:59:41 +00:00
Andreas Fitzek
8d8ca2fd67
chore(core): Redact sensitive node output fields via configurable strategy pipeline (#26546)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 12:59:03 +00:00
Ali Elkhateeb
26de9dc353
feat(editor): Allow switching versions in workflow history diff view (#26418)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-06 12:51:45 +00:00
Raúl Gómez Morales
095e37b2e7
refactor(editor): Create useWorkflowDocumentNodes facade and ESLint migration guards (no-changelog) (#26620) 2026-03-06 12:36:35 +00:00
Jon
78b7f88846
feat: Add option to hide credential overwrites (#26489) 2026-03-06 12:06:20 +00:00
Matsu
38534ae3d8
ci: Ensure PNPM cache directory to avoid cache failure (#26671) 2026-03-06 11:55:55 +00:00
Milorad FIlipović
9f7ea5ab6c
fix(editor): Fix MCP connection popover UI bugs (no-changelog) (#26560) 2026-03-06 11:38:53 +00:00
Alex Grozav
725567d087
refactor: Remove KeepAlive for NodeView (no-changelog) (#26583) 2026-03-06 11:26:01 +00:00
Milorad FIlipović
06ebc96464
feat(editor): Add AI workflow builder capabilities to MCP server (no-changelog) (#26532)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
2026-03-06 10:54:52 +00:00
Matsu
b134e10325
ci: Ignore bundle commits on sync action (#26662) 2026-03-06 10:45:16 +00:00
Dawid Myslak
6f2f384f39
fix(Form Node): Improve custom CSS sanitization (#26623) 2026-03-06 10:43:17 +00:00
Dawid Myslak
dfd41f4351
fix(Facebook Trigger Node): Include appsecret_proof in Graph API calls (#26497) 2026-03-06 10:03:00 +00:00
Garrit Franke
0057bf38fc
feat: Add support for publishing community nodes through GitHub Actions (#26597)
Co-authored-by: aikido-pr-checks[bot] <169896070+aikido-pr-checks[bot]@users.noreply.github.com>
2026-03-06 09:20:51 +00:00
Garrit Franke
82eae73d8a
feat: Add lint rule to disallow httpRequest with manual authentication (#26624) 2026-03-06 09:02:27 +00:00
Alex Grozav
faf2267ab7
fix(editor): Fix expression autocomplete for optional chaining (#26598) 2026-03-06 08:59:07 +00:00
github-actions[bot]
46bfc0cff2
fix(Customer.io Node): Migrate Customer.io nodes from deprecated beta API to App API (#26049)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-06 08:52:43 +00:00
Alexander Menk
8a866d040f
fix(Filter Node): Fix inverse logic description (#19634)
Co-authored-by: krisn0x <10799186+krisn0x@users.noreply.github.com>
2026-03-06 08:49:12 +00:00
Irénée
7a6b78ccd1
chore: Add role column to project_secrets_provider_access (#26523)
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
2026-03-06 08:21:43 +00:00
RomanDavydchuk
14b91ab696
fix(Slack Trigger Node): Users or bots to ignore are not actually ignored for message_changed event subtype (#26414) 2026-03-06 08:16:57 +00:00
Matsu
819d0990ad
ci: Checkout backport code with generated token (#26655) 2026-03-06 07:56:23 +00:00
Matsu
58e8af5c0d
ci: Change backporting to n8n assistant app (#26651) 2026-03-06 06:51:29 +00:00
Tomi Turtiainen
11934c02ee
chore: Include request details into reported response errors (#26517) 2026-03-06 06:42:17 +00:00
Matsu
d895c64e4d
ci: Use n8n release helper in backporting (#26649) 2026-03-06 06:38:37 +00:00
Michael Kret
cc22c31490
feat(Chat Node): Return chat message instead of input data if Chat is not waiting for user input (#26167)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-03-05 20:22:58 +00:00
Romeo Balta
8c12032941
fix(Notion Node): Skip fetching children of unsupported block types (#26188)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 20:13:05 +00:00
Konstantin Tieber
4fe6b4fb73
feat(core): Improve secret proxy (#26522) 2026-03-05 20:01:37 +00:00
Andreas Fitzek
a441e83f3a
chore(core): Integrate ExecutionRedactionService into all execution data endpoints (#26488) 2026-03-05 15:49:22 +00:00
Tomi Turtiainen
ecf479cf1e
feat(core): Move enum check constraints to Column class (no-changelog) (#26588) 2026-03-05 15:25:31 +00:00
Tomi Turtiainen
8a8cf718bb
feat(core): Add in-memory DNS cache with TTL validation (no-changelog) (#26482) 2026-03-05 15:19:52 +00:00
Marc Littlemore
1f1021e707
feat(core): Add 1Password external secrets provider (#26307)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-03-05 15:08:13 +00:00
Ali Elkhateeb
2e35bb322e
fix(core): Apply empty-hash placeholder fix to getHash cache method (#26593) 2026-03-05 14:06:23 +00:00
phyllis-noester
6b171fc025
fix: Fix credential resolver RBAC for member users (#26552) 2026-03-05 13:42:13 +00:00
Dawid Myslak
f1a074f946
fix(Form Node): Improve form rendering consistency (#26540) 2026-03-05 13:26:48 +00:00
Matsu
c44f7f278a
ci: Automatically approve and auto-merge node popularity (#26607) 2026-03-05 13:23:07 +00:00
Alex Grozav
30c08cf56f
fix(editor): Fix canvas loading state indicator position and style (no-changelog) (#26596) 2026-03-05 13:03:17 +00:00
Declan Carroll
59d2b55cde
ci: Consolidate trivy scan Slack notifications to #updates-security (#26601)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 12:27:33 +00:00
Raúl Gómez Morales
c32e724871
refactor(editor): Migrate parentFolder field to workflowDocument (#26515) 2026-03-05 12:01:50 +00:00
Andreas Fitzek
01f912cab7
feat(core): Emit audit event when execution data is revealed (#26425) 2026-03-05 11:42:39 +00:00
Declan Carroll
66087e2dd5
chore: Apply biome formatting to playwright package (no-changelog) (#26586)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 10:47:20 +00:00
Tomi Turtiainen
efa01c32d2
fix: Cache node initialization in test harness (no-changelog) (#26584) 2026-03-05 10:30:45 +00:00
Michael Drury
a04ff92a4f
fix(ai-builder): Don't use autoGenerate for UUID columns for WFB persistence migration (#26558)
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
2026-03-05 10:00:28 +00:00
Declan Carroll
1abcd3f425
ci: Unify impact analysis into single ImpactAnalyzer (no-changelog) (#26556)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 09:26:28 +00:00
Matsu
0acf7f73d1
ci: Add GITHUB_TOKEN to backport workflow (#26582) 2026-03-05 09:17:50 +00:00
Guillaume Jacquart
9e500cc9d8
feat(core): Explicit fail on production executions with failing dynamic (#26500) 2026-03-05 09:17:21 +00:00
Matsu
93a36c5b74
chore: Give backport action a name (#26580) 2026-03-05 09:16:21 +00:00
Andreas Fitzek
212623329d
chore(core): Redact error messages in execution data to prevent PII leakage (#26479) 2026-03-05 08:53:26 +00:00
Matsu
7df0125b6d
ci: Allow manual execution of backport workflow (#26576) 2026-03-05 08:23:18 +00:00
Brian Kasper
b0a4d3db26
fix: Task Runner Initialize NODE_PATH for external npm packages (#24517)
Co-authored-by: Declan Carroll <declan@n8n.io>
2026-03-05 08:10:47 +00:00
Tomi Turtiainen
f2a6b3efef
feat(core): Add SSRF protection config (#26424) 2026-03-05 07:19:14 +00:00
Declan Carroll
e18564773a
test: Remove dead code NodeDetailsViewPage.getParameterInputContainer (no-changelog) (#26548) 2026-03-04 19:37:19 +00:00
Raúl Gómez Morales
cce853eeec
refactor(editor): Normalize usedCredentials in workflow document state (no-changelog) (#26535) 2026-03-04 16:13:34 +00:00
Sandra Zollner
ac017457af
test: Add external secrets provider connection tests (#26493) 2026-03-04 15:52:15 +00:00
Ali Elkhateeb
cf90a202ae
fix(core): Fix cache get for Redis missing key placeholders and set for falsy values (#26502)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-04 15:51:32 +00:00
Guillaume Jacquart
71cec8bffe
feat(core): Add validation on workflow with dynamic credentials (#26423)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 15:04:55 +00:00
Declan Carroll
59f054ad38
fix: Devcontainer build failures from hardened base image (no-changelog) (#26477)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:37:23 +00:00
Declan Carroll
bcd18a6bfe
test: Janitor cleanup — scope-lockdown, additive-only impact narrowing, metrics refresh (no-changelog) (#26476)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 14:37:19 +00:00
Rob Hough
72081560e3
fix(editor): Improve NDV panel drag handle contrast in dark mode (#26533) 2026-03-04 14:24:48 +00:00
Daria
e0ba687ca4
refactor(core): Move workflow creation logic to the service (#26521) 2026-03-04 14:17:49 +00:00
Nikhil Kuriakose
d3af5e44d8
fix(editor): Store statistics only when wf succeeded or failed (#25988) 2026-03-04 13:42:12 +00:00
Nikhil Kuriakose
a6e5d9b4bf
fix(editor): Fix alignment in trigger panel (#26475) 2026-03-04 13:42:02 +00:00
Nikhil Kuriakose
9a5c460f65
fix(editor): Change button variant to ghost (#26542) 2026-03-04 13:41:24 +00:00
Csaba Tuncsik
e1221d6dfb
feat(editor): Add 'New' badge to project roles and upgrade landing page (#26348) 2026-03-04 12:16:13 +00:00
Matsu
0a17291939
ci: Introduce backport workflow and compute-backport-targets script (#26518) 2026-03-04 11:15:09 +00:00
Rob Hough
d48b7986a5
fix(editor): Remove light-dark and use mixin (no-changelog) (#26527) 2026-03-04 11:11:29 +00:00
Guillaume Jacquart
f72dfc7a28
feat(core): Static fallback on dynamic credentials for manual executions (#26406) 2026-03-04 10:14:39 +00:00
Sandra Zollner
4ffe54ba3b
feat(editor): Implement read-only mode for external secrets connections (#26432) 2026-03-04 10:12:52 +00:00
Declan Carroll
114b450aa1
ci: Update claude-code-action to latest v1 and suppress output (#26520)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 10:03:09 +00:00
Alex Grozav
7c498d7d0a
feat(editor): Normalize isArchived field in workflow document state (no-changelog) (#26510) 2026-03-04 09:57:01 +00:00
RomanDavydchuk
64bd34b4ee
feat: Add ai_model field to node graph item (no-changelog) (#26429) 2026-03-04 09:56:13 +00:00
Tomi Turtiainen
d832ffe763
refactor(core): Remove TaskRunnersConfig.enabled since runners are always on (#25834)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Danny Martini <danny@n8n.io>
2026-03-04 09:55:08 +00:00
Rob Hough
1e1c3a75bc
refactor(editor): Update DS Input with new styles (no-changelog) (#26134)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-03-04 09:09:16 +00:00
oleg
834966e145
feat(ai-builder): Add binary-checks evaluation suite (no-changelog) (#26415)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-03-04 08:42:05 +00:00
phyllis-noester
c275f802bb
fix: Log streaming config works with proxy (#26492) 2026-03-04 08:06:21 +00:00
Jaakko Husso
d00cded5ac
feat(core): Add suggested prompts to Personal Agents on Chat hub (#26444) 2026-03-04 08:06:11 +00:00
Declan Carroll
d8d839a6af
ci: Change default value of suppress_output to true (#26513) 2026-03-04 08:05:37 +00:00
Raúl Gómez Morales
ebca21f58d
refactor(editor): Normalize scopes field in workflow document state (no-changelog) (#26331)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-04 08:00:20 +00:00
Garrit Franke
19147d7e44
chore(core): Increase turbo watch concurrency (#26461) 2026-03-04 07:38:02 +00:00
Daria
9a84403d2f
fix(editor): Do not send health checks in preview (no-changelog) (#26484) 2026-03-03 19:39:09 +00:00
Andreas Fitzek
edd0c9f0d1
chore(editor): Fix node click keeping adding to context (#26494) 2026-03-03 17:11:46 +00:00
Declan Carroll
6f05974ff1
ci: Parallelize NPM publish and Docker builds in release pipeline (#26480)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 17:08:10 +00:00
Jon
3bc267953a
docs: Update error message when community nodes fail to install (#26486) 2026-03-03 16:08:45 +00:00
Declan Carroll
c4ab0fff99
ci: Add performance benchmark regression detection to CI (#26156)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:52:04 +00:00
Declan Carroll
2b355546b6
fix(core): Fix Python and JS task runners for Windows platform (#26288)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 15:26:15 +00:00
Irénée
db5f40a6ab
refactor(core): Align external secrets RBAC scopes with endpoint semantics (no-changelog) (#26293) 2026-03-03 15:16:19 +00:00
Arvin A
990298238d
fix: Clicking a node keeps adding to context (#26469) 2026-03-03 14:51:31 +00:00
Charlie Kolb
cc1e378c51
fix(editor): Remember data table sort selection (#26462) 2026-03-03 14:42:11 +00:00
Michael Kret
62d7769000
fix(Todoist Node): Filter tasks endpoint (#26396)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-03-03 14:33:47 +00:00
Daria
a1f3515cc0
fix: Handle collaboration push old format (#26467) 2026-03-03 14:18:52 +00:00
Declan Carroll
9b350264fb
test: Refine unit test descriptions for clarity and determinism (#26478) 2026-03-03 14:08:44 +00:00
Declan Carroll
f8455f81be
ci: Add E2E coverage gap analysis (#26440) 2026-03-03 13:41:20 +00:00
Suguru Inoue
1e8dafeb18
chore(core): Update ChatHub agents table schema for file knowledge (#26465) 2026-03-03 13:13:19 +00:00
Declan Carroll
02e094c0cd
ci: Improve Helm stack for local dev and CI usage (no-changelog) (#26471) 2026-03-03 13:07:57 +00:00
Alex Grozav
cf839dd544
fix: Initialize Demo layout (no-changelog) (#26468) 2026-03-03 12:40:35 +00:00
Declan Carroll
e3ff66bb1f
test: Fix janitor dead-code false positives and CI impact analysis path resolution (no-changelog) (#26449)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 12:32:28 +00:00
Matsu
15ce65d6f0
ci: Use inputs. vs github.event.inputs for workflow_call compatibility (#26454) 2026-03-03 12:13:58 +00:00
Matsu
17b85ab4fa
ci: Migrate from deprecated codecov test-results-action (#26457) 2026-03-03 12:13:53 +00:00
Matsu
01d7903958
ci: Pass secrets to post-release actions (#26458) 2026-03-03 12:13:48 +00:00
Raúl Gómez Morales
d614954034
fix(editor): Fix race condition in credentialResolverId test (#26464) 2026-03-03 11:29:42 +00:00
Jaakko Husso
1cc7e8dfe3
fix(editor): Position chat welcome message to center with base LLM models (#26442) 2026-03-03 09:18:58 +00:00
Jaakko Husso
45fa6419ae
feat(editor): Make it possible to pick Chat hub model by ID even if no models are loaded (#26435) 2026-03-03 09:18:43 +00:00
Jaakko Husso
672bfc3a25
fix(core): Don't include last human message twice on Chat hub message regeneration (#26430) 2026-03-03 09:18:20 +00:00
Matsu
e1a86eca2f
ci: Add automation for creating Release candidate branches (#26327) 2026-03-03 09:04:12 +00:00
Elias Meire
8ac25b8270
fix(editor): Always show auth mode dropdown in credential modal (#26280) 2026-03-03 08:48:19 +00:00
Alex Grozav
863aa1991f
chore: Add cubic rule for workflowDocumentStore migration (no-changelog) (#26459) 2026-03-03 08:30:45 +00:00
Michael Kret
6a2127c9ad
fix: Merge by sql update (#26364) 2026-03-03 08:29:41 +00:00
Alex Grozav
2da3eee8d4
refactor(editor): Migrate settings to normalized workflow document state (no-changelog) (#26407)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-03 07:07:31 +00:00
n8n-assistant[bot]
d478552a23
🚀 Release 2.11.0 (#26456)
Co-authored-by: Matsuuu <16068444+Matsuuu@users.noreply.github.com>
2026-03-03 08:18:52 +02:00
Danny Martini
5d0152c373
feat(core): Add ExpressionEvaluator and integration tests (no-changelog) (#26230)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 22:47:56 +00:00
Declan Carroll
19cca66502
ci: Pin Trivy binary version to fix yanked release (#26431)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 19:01:38 +00:00
Tomi Turtiainen
c6762eb8dd
chore: Ignore 'SET search_path TO' spans (#26434) 2026-03-02 18:17:03 +00:00
Charlie Kolb
049af4363e
fix(editor): Fix project assignment when duplicating workflow from overview (#26341) 2026-03-02 15:54:12 +00:00
Declan Carroll
7be48a4114
fix: Fix selector-purity violation and E2E impact analysis in CI (#26410)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 14:56:48 +00:00
Matsu
602f858149
ci: Pass secrets to release-create-pr on workflow_call (#26427) 2026-03-02 14:37:25 +00:00
Daria
f020caa6a7
feat: Update existing MCP tools (#26248) 2026-03-02 14:07:16 +00:00
Andreas Fitzek
eb19e00b0c
feat(editor): Expose workflow:execute scope checkbox in custom role UI (#26405) 2026-03-02 13:40:58 +00:00
Declan Carroll
b935dc1f64
test: Add Helm chart E2E testing via K3s + testcontainers (#26155)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 13:32:37 +00:00
Dawid Myslak
3ed72a1753
chore(core): Add n8n-workflow to devDependencies in ai-utilities (#26421) 2026-03-02 13:26:39 +00:00
Daria
c544e94e39
feat: Hide workflow edit conflict error in Sentry (no-changelog) (#26412) 2026-03-02 13:20:41 +00:00
Dawid Myslak
b62d857646
fix(core): Make n8n-workflow a peer dependency in ai-utilities (#26404) 2026-03-02 12:02:34 +00:00
Matsu
e14b9680ff
ci: Clean up abandoned release branches on PR dismiss (#26342) 2026-03-02 11:58:48 +00:00
Sandra Zollner
4dcc2d8806
feat(core): Enable external secrets for projects (#26329) 2026-03-02 11:57:55 +00:00
Sandra Zollner
b883b3c41c
feat(editor): Disable scope selection when opened from project settings page (#26403)
Co-authored-by: konstantintieber <konstantin.tieber@n8n.io>
2026-03-02 11:27:36 +00:00
Milorad FIlipović
bfa4550200
fix(editor): Prevent scrollbar flashing when toasts are shown (#26338) 2026-03-02 11:17:25 +00:00
Charlie Kolb
1bacba3d8b
feat(editor): Add searching and sorting to data table overviews (#25623)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-02 10:48:53 +00:00
Rob Hough
aee2f8687a
refactor(editor): Consolidate design system tokens (no-changelog) (#25823) 2026-03-02 10:36:52 +00:00
Declan Carroll
4e0cd02d5c
fix(editor): Replace jsonpath with jsonpath-plus to resolve CVE (#26399)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 10:15:16 +00:00
Andreas Fitzek
fc74592515
chore(core): Introduce instance registry module (#26310) 2026-03-02 10:06:43 +00:00
Declan Carroll
d05123d723
test: Move test discovery and orchestration into janitor (#26366)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-02 09:51:05 +00:00
Andreas Fitzek
634041c5c8
feat(core): Track dynamic credential resolution per node execution in ITaskData (#26354) 2026-03-02 09:13:55 +00:00
Michael Kret
d00a55f869
chore: Move createVectoreStore factory to ai-utilities (#25968)
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
2026-03-02 09:10:31 +00:00
Andreas Fitzek
4f4b85cc0c
chore(core): Add redactionInfo object to execution data responses (#26326) 2026-03-02 09:08:55 +00:00
Declan Carroll
241ad231a4
ci: Refine Trivy scans, centralizes security config (#26384) 2026-03-02 07:43:29 +00:00
aikido-autofix[bot]
0b84e1079d
fix: Fix 11 security issues in jsonpath, mailparser, mysql2 and 6 more (#26362)
Co-authored-by: aikido-autofix[bot] <119856028+aikido-autofix[bot]@users.noreply.github.com>
2026-03-01 15:17:14 +00:00
Dimitri Lavrenük
e01ce10f20
fix: Admin should be able to install community nodes (#26296)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-02-27 22:52:12 +00:00
Declan Carroll
7af85fc297
fix(core): Increase timeout for workflow execution tests (#26150)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 17:34:55 +00:00
Kartik Balasubramanian
5ec61a6a17
refactor(core): Enhance configuration comments for clarity and consistency (#25677)
Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com>
2026-02-27 16:42:05 +00:00
Michael Kret
ba687dad5e
fix(XML Node): Invalid attributes (#26353) 2026-02-27 16:21:15 +00:00
Benjamin Schroth
f7c36840fb
feat(ai-builder): Implement changes list for builder and on canvas diff (#26062) 2026-02-27 16:02:21 +00:00
Csaba Tuncsik
c320383f88
fix(editor): Hide client secret field in resolver when user info endpoint is selected (#26340)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-27 15:05:48 +00:00
Andreas Fitzek
6051fc74ea
chore(core): Introduce redaction marker for items (#26308) 2026-02-27 14:59:15 +00:00
Csaba Tuncsik
c2e31e9fe6
fix(editor): Allow clearing credential resolver in workflow settings (#26343)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-27 14:58:55 +00:00
Milorad FIlipović
dde639664a
fix(editor): Fix Add column button spacing in data table (no-changelog) (#26345) 2026-02-27 14:26:50 +00:00
Milorad FIlipović
470fc503a0
fix(editor): Fix CSV export for data tables downloading wrong table (#26325) 2026-02-27 13:28:34 +00:00
Charlie Kolb
0ec749e8dd
feat(editor): Add project badge in data table overview (#26289)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-27 13:13:46 +00:00
Milorad FIlipović
363d7ec493
fix(editor): Fix What's new callout position (no-changelog) (#26236) 2026-02-27 13:11:37 +00:00
Milorad FIlipović
6d15d0ee03
fix(editor): Fix trigger listening state tooltip layout (no-changelog) (#26295) 2026-02-27 13:11:17 +00:00
Milorad FIlipović
d7a5b04b9f
fix(editor): Fix filters popover layout (no-changelog) (#26339) 2026-02-27 13:10:38 +00:00
Raúl Gómez Morales
1b938f4c93
refactor(editor): Normalize meta field in workflow document state (#26223) 2026-02-27 12:11:37 +00:00
Matsu
69458c29dc
ci: Re-introduce RELEASE env variable to vite builds in release (#26335) 2026-02-27 11:31:38 +00:00
Andreas Fitzek
a94c8b728c
chore(core): Allow changing redaction settings in the workflow settings (#26298) 2026-02-27 10:51:04 +00:00
Csaba Tuncsik
c93e4380bc
feat: Add assignments tab for custom roles with project visibility (#25992)
Co-authored-by: Declan Carroll <declan@n8n.io>
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: Mutasem Aldmour <4711238+mutdmour@users.noreply.github.com>
Co-authored-by: Ali Elkhateeb <ali.elkhateeb@n8n.io>
Co-authored-by: Matsu <huhta.matias@gmail.com>
Co-authored-by: Guillaume Jacquart <jacquart.guillaume@gmail.com>
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: Rob Hough <robhough180@gmail.com>
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
Co-authored-by: James Gee <1285296+geemanjs@users.noreply.github.com>
Co-authored-by: Alex Grozav <alex@grozav.com>
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
Co-authored-by: Stephen Wright <sjw948@gmail.com>
Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
Co-authored-by: Albert Alises <albert.alises@gmail.com>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Daria <daria.staferova@n8n.io>
Co-authored-by: peteawood <pete.a.wood@gmail.com>
Co-authored-by: Roman Davydchuk <roman.davydchuk@n8n.io>
Co-authored-by: Jaakko Husso <jaakko@n8n.io>
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Eugene <eugene@n8n.io>
Co-authored-by: Benjamin Schroth <benjamin@n8n.io>
Co-authored-by: Sandra Zollner <sandra.zollner@n8n.io>
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
Co-authored-by: Benjamin Schroth <68321970+schrothbn@users.noreply.github.com>
Co-authored-by: oleg <me@olegivaniv.com>
Co-authored-by: Konstantin Tieber <46342664+konstantintieber@users.noreply.github.com>
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
Co-authored-by: Romeo Balta <7095569+romeobalta@users.noreply.github.com>
Co-authored-by: Tuukka Kantola <Tuukkaa@users.noreply.github.com>
Co-authored-by: Kaito Horiuchi <horiyee.ka@gmail.com>
Co-authored-by: Michael Drury <me@michaeldrury.co.uk>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-27 10:33:41 +00:00
Alex Grozav
520ff6c1c9
refactor(editor): Migrate workflow timestamps to document store (no-changelog) (#26292)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-27 10:29:51 +00:00
Raúl Gómez Morales
b17960d2f9
refactor(editor): Normalize homeProject field in workflow document state (#26224) 2026-02-27 08:52:46 +00:00
Raúl Gómez Morales
43ce065ddc
refactor(editor): Stop writing sharedWithProjects to workflowsStore.workflow (no-changelog) (#26246) 2026-02-27 08:52:21 +00:00
Ali Elkhateeb
d3afac8d99
feat(editor): Allow comparing workflow history versions (#26060) 2026-02-27 08:02:05 +00:00
Csaba Tuncsik
26b36e0f04
feat(editor): Add dynamic credentials UI for ChatHub (#25685)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-27 07:16:20 +00:00
Jaakko Husso
218569c70a
fix(core): Disallow file uploads on Chat hub when chat trigger doesn't permit them (#25714) 2026-02-27 07:13:29 +00:00
Ricardo Espinoza
b298a5d018
fix(editor): Custom sticky text color (#25961) 2026-02-26 21:32:31 +00:00
Andreas Fitzek
a741f15792
chore(core): Implement redaction logic in redaction module (#26268) 2026-02-26 17:32:40 +00:00
Andreas Fitzek
3739998915
chore(core): Integrate execution redaction service in execution service (#26255) 2026-02-26 16:20:36 +00:00
Andreas Fitzek
add88df9b4
chore(core): Decouple workflow execution from edit permission (#25737) 2026-02-26 15:48:41 +00:00
Guillaume Jacquart
7459abced4
chore(core): Add e2e tests for dynamic credentials setup, status and workflow calling (#26209) 2026-02-26 15:35:11 +00:00
Danny Martini
0ed9f35ddc
feat(core): Add IsolatedVmBridge (no-changelog) (#26142)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 14:20:33 +00:00
Raúl Gómez Morales
e97b6b82ee
fix(editor): Fix input panel error output (#23116)
Co-authored-by: Eugene <eugene@n8n.io>
2026-02-26 14:11:08 +00:00
Matsu
8e952871e2
ci: Automatically mark releases at latest or pre-release (#26294) 2026-02-26 13:23:17 +00:00
Declan Carroll
216ef96e3a
ci: Add suppress_output option to Claude task runner (no-changelog) (#26287)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 12:13:23 +00:00
Declan Carroll
a80bd41f57
ci: Enforce Chromatic as required check for design system changes (no-changelog) (#26126)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 11:09:27 +00:00
Alex Grozav
22e0b8aa96
refactor(editor): Migrate workflow checksum to document store (no-changelog) (#26227)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 10:37:12 +00:00
Mutasem Aldmour
a0664a1add
feat(core): Expand workflow-sdk test fixtures from 500 to 2000 workflows and fix codegen bugs (#26041)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 10:09:16 +00:00
Guillaume Jacquart
e9627a640e
fix(core): Skip onboarding screen for SAML users with IdP-provided names (#26245)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-26 09:57:28 +00:00
Rob Hough
cae80a2a56
fix(editor): Remove white separator from Button (no-changelog) (#26266) 2026-02-26 09:52:18 +00:00
Matsu
c38291a2a5
ci: Automate calls to release-push-to-channel (#26281) 2026-02-26 09:35:41 +00:00
Jaakko Husso
a006e02759
feat(Chat Trigger Node): Add Suggested prompts, shown on Chat hub (#26217) 2026-02-26 09:10:43 +00:00
Declan Carroll
b4465c86af
ci: Enhance Claude task runner workflow (#26267) 2026-02-26 08:30:33 +00:00
Michael Kret
27949dd87e
feat: Update Replace Me placeholder in Loop Over Items (#23756)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-02-26 08:07:15 +00:00
Dimitri Lavrenük
4b9e7e3739
fix: Improve chat message button handling (#26249) 2026-02-26 08:04:38 +00:00
Matsu
96e446fc61
ci: Clarify and automate release process (#26181) 2026-02-26 07:45:31 +00:00
Rob Hough
6ec3255397
fix(editor): Custom style for date picker btns (no-changelog) (#26263) 2026-02-25 17:27:48 +00:00
Irénée
b468a72d26
feat: Enable project-scope external secrets permissions (no-changelog) (#26143)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 16:11:49 +00:00
Sandra Zollner
82db0b923d
fix(editor): Fix workflow diff navigation left arrow hover state (#26253) 2026-02-25 15:55:47 +00:00
Andreas Fitzek
81ab10d45b
feat(core): Add execution:reveal scope (#26252)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 14:51:13 +00:00
Svetoslav Dekov
c1d4d1241c
chore(core): Update linear-issue skill to properly interpret node popularity (no-changelog) (#26241) 2026-02-25 14:49:46 +00:00
Michael Drury
c30870ca34
fix(ai-builder): Fix chat fade, keyboard shortcuts, node tidy-up, and feedback styling (#26200)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:53:41 +00:00
Guillaume Jacquart
4aacc574f6
feat(editor): Disable v2 migration report via shared target version constant (#26244) 2026-02-25 13:47:20 +00:00
Andreas Fitzek
3994d38eca
chore(core): Add redaction policy to workflow setting (#26239) 2026-02-25 13:44:47 +00:00
Michael Kret
c3ddc49d85
fix: Add missing chat tool input logs (#26229) 2026-02-25 13:35:58 +00:00
github-actions[bot]
241ee1eefc
chore: Update node popularity data (#25806)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2026-02-25 11:40:28 +00:00
yehorkardash
36bde68ecc
fix(core): Don't show setup in demo mode (#26233) 2026-02-25 10:55:58 +00:00
Milorad FIlipović
45106e3fa1
fix(editor): Fix spacing between workflow history (no-changelog) (#26225) 2026-02-25 10:55:44 +00:00
Milorad FIlipović
4fd3fd7594
fix(editor): Stop hijacking search shortcut for layouts without search (#26222) 2026-02-25 10:55:31 +00:00
Rob Hough
4e489a6884
fix(editor): Fix grid alignment on Safari 18.6 (#26234) 2026-02-25 10:43:29 +00:00
Albert Alises
ec4496d12c
feat(editor): Forward rich message types from SDK instead of flattening to text (#26177) 2026-02-25 09:46:17 +00:00
ByteEVM
fa46fc46be
fix(editor): Compact i18n secrets count (#25883) 2026-02-25 09:23:22 +00:00
Milorad FIlipović
8803226f72
fix(editor): Fix shift+space key combo in canvas (#26169) 2026-02-25 09:02:13 +00:00
Irénée
cc10bce371
feat: Add secrets management scopes via custom roles (no-changelog) (#26219) 2026-02-25 08:46:38 +00:00
Michael Kret
4655a6273b
fix(Microsoft Teams Node): Block Teams link preview service from triggering sendAndWait approvals (#26125) 2026-02-25 08:45:13 +00:00
Michael Kret
265aea30d4
fix: Assignments control buttons top padding fix (#26165) 2026-02-25 08:44:26 +00:00
Sandra Zollner
e0ef26bf1d
fix(editor): Resolve credential modal expressions without workflow co… (#26191) 2026-02-25 08:26:52 +00:00
Declan Carroll
c92becbc34
ci: Adds Docker stats telemetry (#26196) 2026-02-25 08:18:23 +00:00
n8n-assistant[bot]
562d867483
chore: Bundle 2026-W7 (#26214)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: James Gee <1285296+geemanjs@users.noreply.github.com>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Stephen Wright <sjw948@gmail.com>
Co-authored-by: oleg <me@olegivaniv.com>
Co-authored-by: Albert Alises <albert.alises@gmail.com>
Co-authored-by: Danny Martini <danny@n8n.io>
2026-02-25 07:08:58 +00:00
Matsu
3f02194f6d
ci: Remove unnecessary release note ping from release pipeline (#26048) 2026-02-25 07:06:10 +00:00
Declan Carroll
6477c066c3
test: Janitor tsx shortcut, docs cleanup, dead code removal (#26210)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 06:11:26 +00:00
Charlie Kolb
21eec59aa4
chore: Clarify execution stopping API description (#26061) 2026-02-24 20:15:51 +00:00
Andreas Fitzek
5a85a4f908
fix(core): Resolve multi-main startup race condition in AuthRolesService (#26176) 2026-02-24 18:07:18 +00:00
Danny Martini
776d328d83
feat(core): Add runtime bundle and extension utilities (#26077)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 17:18:25 +00:00
Tuukka Kantola
0243412ba7
fix(editor): Change node list shortcut from Tab to N to unlock keyboard navigation (#26148)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 16:43:34 +00:00
Filipe Tavares
2dcc76e94e
feat(editor): Add success button variant and fix trial banner CTA styling (#26190)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 16:25:29 +00:00
Irénée
fc5c8424e2
fix: Enable external secrets multi-connection to vault (#26189) 2026-02-24 14:38:41 +00:00
Guillaume Jacquart
d98eff2a4e
chore(core): Test saml with the UI based config. Display modal when config has changed without saving (#26141) 2026-02-24 14:35:33 +00:00
Raúl Gómez Morales
1285cc47d4
refactor(editor): Refactor workflow document composables from handleAction to set / apply (#26178) 2026-02-24 13:00:20 +00:00
Sandra Zollner
84966aadb2
feat(editor): Use single select dropdown for selecting scope of a secrets store (#26146) 2026-02-24 12:48:01 +00:00
Ali Elkhateeb
577e4efaa6
refactor(core): Extract and reuse containsExpression string utility (#26180)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-24 12:34:35 +00:00
Mutasem Aldmour
b585be5188
fix(core): Dispatch composite targets in onError() instead of dropping them (#25981)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 12:19:57 +00:00
Rob Hough
974a19dc41
fix(editor): Switch to inner shadow for Button (no-changelog) (#26175) 2026-02-24 12:14:28 +00:00
Justin Hart
852579915d
fix: Remove SystemCredentials source check during AWS role assume (#22859) 2026-02-24 10:58:43 +00:00
Robert Squires
2e07bb8d04
fix(editor): Setup panel visual tweaks (no-chaneglog) (#26107)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2026-02-24 10:42:06 +00:00
Alex Grozav
92efefb165
refactor(editor): Switch to using refs when injecting the workflow document (no-changelog) (#26179)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 10:38:13 +00:00
Ali Elkhateeb
1c561c90a1
refactor(core): Consolidate secret provider connection response types into api-types (no-changelog) (#26114) 2026-02-24 10:02:50 +00:00
Milorad FIlipović
a3d5937495
fix(editor): Batch community node requests to respect strapi arraySize (#26168) 2026-02-24 09:46:49 +00:00
Andreas Fitzek
8df87b79db
chore(editor): Expose credential:unshare to custom project roles (#26151) 2026-02-24 09:19:20 +00:00
Raúl Gómez Morales
c20afda4b9
refactor(editor): Normalize active, activeVersionId, and activeVersion fields in workflow document state (#25915)
Co-authored-by: Declan Carroll <declan@n8n.io>
2026-02-24 09:10:41 +00:00
Elias Meire
f6836c73d3
feat(editor): Add quick connect inside the credential edit modal (#26058)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-02-24 08:54:27 +00:00
Svetoslav Dekov
da861eef4e
chore: Add parameter if prompt guidelines should be used for claude task action (no-changelog) (#26052) 2026-02-24 08:27:32 +00:00
Matsu
64a30e8fc9
ci: Fix permission issues and streamline tag updates (#25994) 2026-02-24 08:24:21 +00:00
Matsu
ea860f4dbc
ci: Detect and report new npm packages before trying to publish them (#26164) 2026-02-24 06:53:43 +00:00
Declan Carroll
4f4644b822
fix: Dependency bumps in transitive dependencies (#26149)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 21:54:04 +00:00
Albert Alises
3bcc76e406
fix(editor): Add aria-label to icon-only buttons missing accessible labels (#26145) 2026-02-23 20:25:00 +00:00
n8n-release-tag-merge[bot]
aa5ad92b25 Merge tag 'n8n@2.10.0' 2026-02-23 17:55:22 +00:00
Andreas Fitzek
928242dee4
feat(core): Split share and unshare into separate scopes (#26011) 2026-02-23 17:06:23 +00:00
Stephen Wright
9edc271c09
feat: Initialise data redaction module, execution data redaction service (#25975) 2026-02-23 17:01:03 +00:00
n8n-assistant[bot]
8e81f3e313
🚀 Release 2.10.0 (#26135)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-02-23 15:57:44 +00:00
Sandra Zollner
25c6d14acf
feat(editor): Enable adding secret store from project settings page (#26122) 2026-02-23 15:42:33 +00:00
Elias Meire
95af7cf0e4 fix(editor): Design fixes for managed OAuth credentials (#26064) 2026-02-23 15:01:29 +00:00
Michael Drury
05d15a0e44
fix(ai-builder): Strip cache_control markers from persisted tool messages and responder input (#26132) 2026-02-23 14:49:33 +00:00
Daria
47d5738ed6
fix(core): Respect n8n path for health endpoint (#26129) 2026-02-23 14:44:46 +00:00
Kaito Horiuchi
7e10901470
fix(core): Always serve /healthz on task broker regardless of N8N_ENDPOINT_HEALTH (#25959) 2026-02-23 14:05:15 +00:00
Csaba Tuncsik
4e68511719
fix(editor): Refresh credential list after update to clear setup badge (#25978)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:49:55 +00:00
Nikhil Kuriakose
facc2feade
fix(editor): Filter for all words in the search query (#26110) 2026-02-23 13:32:46 +00:00
Declan Carroll
ecc330c829
chore: Update turbo from 2.7.3 to 2.8.9 (#26020)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:31:55 +00:00
Alex Grozav
2d0bbf5ea4
fix: Initialize Vue Router for stories (no-changelog) (#26130) 2026-02-23 13:31:49 +00:00
Elias Meire
e2cb7d29fe
feat(editor): Improve Google OAuth button design (#26063) 2026-02-23 13:30:59 +00:00
Albert Alises
bed7f6b5fd
feat(editor): Render interactive code diffs in builder chat (#26119) 2026-02-23 12:57:40 +00:00
Konstantin Tieber
9598874050
feat(core): Support multiple connected vaults per secret provider (#26124) 2026-02-23 12:40:13 +00:00
Jaakko Husso
8aded1759b
fix(editor): Fix agent description placement on Chat hub modal selector (#26038) 2026-02-23 12:21:58 +00:00
Tuukka Kantola
0c29bb038f
chore(editor): Clean up AI workflow builder header (#26037)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 12:21:54 +00:00
Romeo Balta
71194488aa
fix(editor): Add missing sidebar toggle telemetry (no-changelog) (#26121) 2026-02-23 12:18:48 +00:00
Jaakko Husso
54a5bf17c0
feat(core): Add 'Create new tool' button to tools selector (#26036) 2026-02-23 12:09:46 +00:00
Albert Alises
6b9053ed1f
fix(core): Add mergeAskBuild to builder request DTO feature flags (#26120) 2026-02-23 12:07:02 +00:00
Csaba Tuncsik
5c7ebf94ec
fix(editor): Improve custom role selector with design refinements (#25666)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-23 11:50:22 +00:00
Jaakko Husso
59a5ff3bc9
fix(editor): Respect displayOptions when determining response mode for Chat on WF canvas (#26112) 2026-02-23 11:44:17 +00:00
Albert Alises
3ff9668f20
fix(Gmail Node): Fix GetMany messages query string pollution with non-API parameters (#26053) 2026-02-23 11:40:15 +00:00
Declan Carroll
ca80d591b2
ci: Pin LocalStack Docker image to 4.13.1 (no-changelog) (#26111)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 11:10:02 +00:00
Dawid Myslak
da11043e96
chore(core): Add preview notice to AI node SDK and CLI prompts (#26045) 2026-02-20 20:26:18 +00:00
Nikhil Kuriakose
05d57d6dd0
fix(editor): Update click behaviour on breadcrumb items (#24753) 2026-02-20 16:27:08 +00:00
Jaakko Husso
2a2786acdb
fix(editor): Fix visual issues on new Chat hub tools selector (#26010) 2026-02-20 16:16:23 +00:00
Danny Martini
fb4b94064f
feat(core): Add package scaffold with public API types and architecture docs (#26047)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 16:13:44 +00:00
Dimitri Lavrenük
0222b6196d
feat: Improve quick connect frontend implementation (#26055) 2026-02-20 15:18:44 +00:00
Albert Alises
c1cc04d192
refactor(editor): Switch MERGE_ASK_BUILD from env feature flag to PH boolean flag (#26057) 2026-02-20 15:18:01 +00:00
Albert Alises
0ba636d74a
fix(Azure OpenAI Node): Disable Responses API to fix GPT-5.2 connection error (#26033) 2026-02-20 14:10:34 +00:00
Milorad FIlipović
1cb481ec69
feat(editor): Apply final setup panel feedback (no-changelog) (#26035) 2026-02-20 13:51:42 +00:00
Rob Hough
72841d7024
fix(editor): Review button style alignment (no-changelog) (#26039) 2026-02-20 13:50:25 +00:00
Konstantin Tieber
8fa58c99c1
feat(core): Support special characters in secret names (#25974) 2026-02-20 13:47:41 +00:00
Svetoslav Dekov
9d908cbd4e
chore: Update linear issue skill to output extra info (no-changelog) (#26034) 2026-02-20 13:34:08 +00:00
Benjamin Schroth
dfc4fac1ce
fix(ai-builder): Fix more evals executions of workflows (no-changelog) (#26043)
Co-authored-by: oleg <me@olegivaniv.com>
2026-02-20 13:19:54 +00:00
Irénée
a235dd0123
feat: Migrate external secrets settings to entity-based storage (no-changelog) (#26001)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 13:10:27 +00:00
Daria
05915c4199
fix(editor): Fix bug with tags not being sent to backend (#26040) 2026-02-20 13:07:20 +00:00
Sandra Zollner
45cfa95e5e
feat(editor): Refine external secrets management on project settings … (#26016) 2026-02-20 12:58:32 +00:00
Danny Martini
9ab7226702
refactor(core): Separate Expression from Workflow class (#25889)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-20 12:58:00 +00:00
Declan Carroll
8990c9df65
chore: Add skill for reproducing bugs from Linear tickets (#25999)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 12:48:20 +00:00
Jaakko Husso
774a2dd301
fix(core): Render newlines on Chat hub messages without requiring hard breaks (#26042) 2026-02-20 12:48:01 +00:00
Albert Alises
7c1985eda3
fix(AI Agent Node): Fix orphaned tool messages in AI Agent memory after buffer window slides (#26046) 2026-02-20 12:44:38 +00:00
Eugene
c03443b7f2
feat(editor): Add review changes banner to AI builder (#25885)
Co-authored-by: Benjamin Schroth <benjamin@n8n.io>
2026-02-20 12:26:03 +00:00
Dawid Myslak
9676662f40
refactor(core): Replace includeAiNodesSdkVersion with maxAiNodeSdkVersion (#26014)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-20 12:22:18 +00:00
Elias Meire
b6e267b0de
feat(editor): Enable users to pick between managed and custom OAuth credentials (#25973) 2026-02-20 11:47:50 +00:00
Albert Alises
790b8b57c1
fix(Anthropic Chat Model Node): Add gateway error enrichment and empty model guard (#25953) 2026-02-20 11:42:25 +00:00
Albert Alises
47d42a63a8
fix(editor): Hide canvas thinking pill and keep canvas editable during help streaming (#26015) 2026-02-20 10:31:31 +00:00
Ricardo Espinoza
f5ea84a174
fix(editor): Selectively apply credentials for http request nodes (#26003)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2026-02-20 10:14:12 +00:00
Jaakko Husso
923060f505
fix(editor): Make Chat hub text prompt scrollable (#26019) 2026-02-20 09:35:35 +00:00
Albert Alises
e59ee6ac09
fix(editor): Enable stop button to abort AI Ask Assistant streaming (#26012) 2026-02-20 09:35:21 +00:00
Dimitri Lavrenük
59b51d1c0e
feat: Quick connect integration flow for Firecrawl (#25970)
Co-authored-by: Roman Davydchuk <roman.davydchuk@n8n.io>
2026-02-20 09:00:48 +00:00
Albert Alises
27b84e0c4b
fix(Google Gemini Node): Fix broken thinking budget selector (#26006) 2026-02-20 08:59:54 +00:00
Mutasem Aldmour
5c7240e0ac
test: Add Agent V3 and AgentTool V3 integration tests (#25849)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 08:42:09 +00:00
Declan Carroll
aa12777c61
ci: Fix Docker image cleanup and simplify CI image tagging (#26002)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-20 07:49:36 +00:00
peteawood
3b41ca8d2f
fix: Address issue with resolving EKS Pod Identity Credentials (#25945) 2026-02-19 17:10:54 +00:00
Rob Hough
b0408d293c fix(editor): Apply missing focus mixin styles (#26008) 2026-02-19 16:38:51 +00:00
Daria
1016949c92
feat: Add tab scoped collaboration (#25646) 2026-02-19 16:14:56 +00:00
Declan Carroll
9017b745fa
ci: Add external flag for local dev mode (#25604)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: Danny Martini <danny@n8n.io>
2026-02-19 16:01:08 +00:00
Albert Alises
fbe4699c84
fix(core): Handle tool wrapper nodes without supplyData in queue mode MCP Trigger (#26007) 2026-02-19 15:24:19 +00:00
Dimitri Lavrenük
a53fa1a1e5
feat: Implement promotion banner for non community nodes (#26009) 2026-02-19 15:07:10 +00:00
Albert Alises
f87cb02d3f
fix(editor): Route error/credential help messages to builder in merged Ask+Build view (#25950) 2026-02-19 15:02:23 +00:00
Albert Alises
b7a8496251
fix(editor): Prevent workflow-updated emission on assistant calls (#25951)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:39:59 +00:00
Andreas Fitzek
bc5050a825
chore(core): Add mode to log streaming events (#26000) 2026-02-19 14:36:45 +00:00
Stephen Wright
49fb32c3c4
feat: Only sync scopes / roles as leader in multi-main (#25935) 2026-02-19 14:34:13 +00:00
yehorkardash
62dda8391a
feat: Update CLI examples (#25881)
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
2026-02-19 14:11:47 +00:00
Alex Grozav
9ae325c5b2
fix(editor): Normalize pinData field in workflow document state (no-changelog) (#25878)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 14:11:27 +00:00
James Gee
824f458afc
chore(core): External secrets - remove delete connection response (#25989) 2026-02-19 13:48:50 +00:00
Svetoslav Dekov
b02a762cc0
feat(core): Add mcp configs to claude gh action (no-changelog) (#25916) 2026-02-19 13:37:19 +00:00
Rob Hough
eb8620753f
fix(editor): Alignment issues and nits (#25954) 2026-02-19 12:58:42 +00:00
yehorkardash
7ad421f038
feat: Add ai-node-sdk package (#25838)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-19 12:01:11 +00:00
Guillaume Jacquart
095a7f9f0d
fix(core): Invalidate project owner cache when user role changes (#25895) 2026-02-19 11:39:44 +00:00
Declan Carroll
9f93695729
ci: Add DB integration tests to CI workflow instead of standalone (#25899)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 11:30:36 +00:00
Matsu
8e55a72d65
chore: Disable publishing on n8n-node-dev (#25980) 2026-02-19 10:31:57 +00:00
Matsu
581f74014b
ci: Initialize ci helpers and support scripts for ci automation via mjs (#25931) 2026-02-19 09:56:48 +00:00
Ali Elkhateeb
bd92dabc5c
feat(core): Filter secrets provider autocomplete to connected vaults only (#25927)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-19 09:48:20 +00:00
Mutasem Aldmour
fe6867ebc2
refactor(core): Remove unused serializeExpression() from workflow SDK (#25934)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 08:49:34 +00:00
Charlie Kolb
6a16e630c4
feat(core): Expose execution stopping in public API (#25826) 2026-02-19 08:02:44 +00:00
Michael Kret
96307e1fed
chore(Microsoft Agent 365 Trigger Node): Libraries version bump (#25739) 2026-02-19 07:57:16 +00:00
Milorad FIlipović
0dec323dd5
feat(editor): Address setup panel P0 feedback (no-changelog) (#25943)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-02-19 07:35:05 +00:00
Declan Carroll
343d2af726
ci: Enable Ryuk cleanup for testcontainers (#25848)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-19 07:27:03 +00:00
Guillaume Jacquart
a2034d8f42
chore(core): Use subquery instead of 2 step queries to find credentials by context (#25754)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 21:24:02 +00:00
Tomi Turtiainen
9e6bafd8e6
chore: Upgrade vm2 to 3.10.5 (#25941) 2026-02-18 19:00:08 +00:00
Konstantin Tieber
e8ab44bf32
feat(core): Ensure user-provided variable names fulfill JS identifer spec (#25900)
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
2026-02-18 17:03:12 +00:00
Dimitri Lavrenük
f0f074ee8c
feat: Build pinecone quick connect integration flow (#25854) 2026-02-18 15:52:32 +00:00
Benjamin Schroth
4fb5ae630b
fix(core): Implement evaluation run cancellation for multi-main (#25353)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-18 15:42:53 +00:00
Albert Alises
60ce73a1fb
fix: Remove redundant builder-log check causing responder double-answering (#25940) 2026-02-18 15:03:08 +00:00
Michael Drury
87f59f04d3
feat(ai-builder): Add WFB session persistence across page refreshes (#25404) 2026-02-18 14:47:08 +00:00
Irénée
d79ef711dd
feat(editor): Add reload action to secret provider connections (no-changelog) (#25920) 2026-02-18 14:00:09 +00:00
Benjamin Schroth
ce32754088
feat(ai-builder): Add subgraph evaluation framework for responder (no-changelog) (#25419) 2026-02-18 12:33:34 +00:00
Svetoslav Dekov
2b377aaad9
fix(editor): Fix incorrect scroll shown while ndv is open (no-changelog) (#25668) 2026-02-18 11:56:52 +00:00
Rob Hough
c7caf27d08
fix(editor): Style regressions on Button (#25924) 2026-02-18 11:53:07 +00:00
Filipe Tavares
a94f13e825
chore(editor): Add credentials page (no-changelog) (#25100) 2026-02-18 11:39:57 +00:00
Tomi Turtiainen
2cfecd2a8b
perf(core): Use streaming JSON parsing for large execution data (#25799)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:50:53 +00:00
Stephen Wright
cadfa4c100
fix: Only use displayOptions for determining credential required fields for update if the property is defined (#25921)
Co-authored-by: Guillaume Jacquart <jacquart.guillaume@gmail.com>
2026-02-18 10:33:33 +00:00
Albert Alises
dc82320f70
fix(editor): Prevent plan mode auto-switch after AIWB restore (#25903) 2026-02-18 10:29:09 +00:00
Albert Alises
9fb5d437d3
feat(core): Merge Ask and Build into unified multi-agent chat experience (#25692)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 10:16:24 +00:00
Albert Alises
d591bcb7c5
fix(editor): Re-layout all nodes on structural changes in AI builder (#25905) 2026-02-18 09:46:31 +00:00
Daria
64bcca02dc
fix(editor): Fix incorrect shortcut resolution for letter keys on non-QWERTY (#25875) 2026-02-18 09:45:34 +00:00
Dawid Myslak
076d7b2d0c
feat(core): Send AI Node SDK version to Strapi community nodes API (#25760)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-18 09:44:35 +00:00
Eugene
a27089256d
chore: Replace Playwright with GraphQL API in loom-transcript skill (no-changelog) (#25918)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:44:15 +00:00
Ricardo Espinoza
4ce9daf2dd
fix(editor): Show existing credentials in template setup modal (#25598) 2026-02-18 09:34:53 +00:00
Ricardo Espinoza
ea143c71ad
feat(editor): In setup panel only mark credentials as completed if they are tested (#25658) 2026-02-18 09:18:36 +00:00
Guillaume Jacquart
c2f5d9976b
chore(core): Improve access controlled credentials and workflows fetching (#25028)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 09:14:09 +00:00
Benjamin Schroth
d262419ba8
feat: Enable streaming in canvas chat (#20991) 2026-02-18 08:50:06 +00:00
Benjamin Schroth
e4ac345eda
feat(ai-builder): Implement workflow execution in evaluations (no-changelog) (#25814) 2026-02-18 08:41:56 +00:00
Eugene
112eecc761
chore: Initial issue analysis skill (no-changelog) (#25877) 2026-02-18 08:21:06 +00:00
Michael Drury
4c1c033cff
fix(ai-builder): Don't release types when loading node types for workflow builder service (#25891) 2026-02-18 08:11:17 +00:00
Tomi Turtiainen
31850f7996
refactor(core): Replace Code nodes with TestDataNode in workflow test fixtures (#25893)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:19:20 +00:00
Declan Carroll
620a50e7fb
ci: Enable Sentry source maps in Docker builds (#25888)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 07:18:43 +00:00
Ricardo Espinoza
c818125e85
fix(core): Return data tables that you have access to instead of only the ones in your personal project (#25558) 2026-02-17 17:25:44 +00:00
Sandra Zollner
2c81eca435
fix(editor): Add validation for secret JSON input fields (#25851) 2026-02-17 16:39:23 +00:00
Sandra Zollner
594dc51005
feat(editor): Update styles and Secrets Provider connection components (#25894) 2026-02-17 16:20:30 +00:00
oleg
48cb717d27
fix: Truncate tool names to 64 characters (#25745) 2026-02-17 15:52:43 +00:00
Sandra Zollner
ff5d2e5f51
feat(editor): Show inline error messages for testing connection feedback (#25873) 2026-02-17 15:37:45 +00:00
Konstantin Tieber
2bc1bd8d15
feat(core): Don't show infisical as option when creating new secret secret store (no-changelog) (#25890) 2026-02-17 15:33:39 +00:00
Dawid Myslak
b97fe12ba2
feat(core): Add ESLint rule to validate AI node SDK fields in package.json (#25759)
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-17 14:34:31 +00:00
Stephen Wright
56b6d0ca61
fix: Increase character limit for providerId (#25748) 2026-02-17 14:18:24 +00:00
Irénée
9c7b3db9a8
feat: Add connection state to secret stores response (no-changelog) (#25884) 2026-02-17 14:07:13 +00:00
Ali Elkhateeb
1bc307990d
fix(editor): Update secrets provider connection name validation (#25868) 2026-02-17 14:00:03 +00:00
Tomi Turtiainen
2886b32efd
fix(core): Forward activationMode in multi-main webhook/trigger setup (#25855)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 13:50:21 +00:00
Stephen Wright
69e7cbfc8f
chore: Bigger alert for sharing deactivation (#25836) 2026-02-17 13:26:00 +00:00
Tomi Turtiainen
748ebf5e58
refactor: Use task runners for AI Transform node (#25833) 2026-02-17 13:18:18 +00:00
Rob Hough
022638f23d
fix(editor): Patch Button v2 migration issues (#25846) 2026-02-17 13:16:26 +00:00
Ali Elkhateeb
61b17d4252
feat(core): Add telemetry tracking for external secrets connections (no-changelog) (#25819)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-17 12:35:24 +00:00
Konstantin Tieber
abf4ae2c39
feat(core): Fail credential transfer if target project lacks access to referenced external secret store (no-changelog) (#25625) 2026-02-17 12:25:42 +00:00
Albert Alises
c811ec1b5e
fix(AI Agent Node): Serialize AI Agent intermediateSteps messageLog to plain objects (#25867) 2026-02-17 11:25:12 +00:00
Svetoslav Dekov
048c76262b
feat(editor): Sort setup panel nodes by execution order (no-changelog) (#25741) 2026-02-17 10:26:54 +00:00
Albert Alises
14920b7e98
fix: Prevent node mention popup when typing email addresses (#25865) 2026-02-17 09:42:36 +00:00
Albert Alises
0135c23d07
fix(editor): Constrain chat trigger images to fit within message width (#25866) 2026-02-17 09:30:09 +00:00
Jon
a6e8a97b31
chore: NODE-4345 - Generate Schema Files (no-changelog) (#25130)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-17 09:02:24 +00:00
Declan Carroll
6ceb8b9eb6
ci: Add CI filter action (#25858) 2026-02-17 09:02:08 +00:00
Albert Alises
5d925058ad
fix: Handle missing trigger node run data gracefully (#25828) 2026-02-17 09:01:53 +00:00
Shireen Missi
8d0251d1de
fix(Guardrails Node): Improve Guardrails validation (#25390) 2026-02-17 08:55:04 +00:00
Benjamin Schroth
ead83ca8d9
feat(editor): Show execution data in preview (#25501) 2026-02-17 08:22:26 +00:00
yehorkardash
833ba65ff0
feat: Support invalid tool call content (#25835)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-17 08:16:43 +00:00
Svetoslav Dekov
2495a05f6c
fix(editor): Fix wrong content displayed while quickly navigating projects and folders (#25428) 2026-02-17 08:05:33 +00:00
Svetoslav Dekov
5434655e0b
feat(core): Add new params to claude task runner github action (no-changelog) (#25766) 2026-02-17 08:04:53 +00:00
Ricardo Espinoza
9da4d3d12e
feat(editor): Highlight nodes in canvas on card hover in setup panel (#25862) 2026-02-17 07:39:46 +00:00
n8n-release-tag-merge[bot]
8c40353450 Merge tag 'n8n@2.9.0' 2026-02-16 19:07:30 +00:00
Konstantin Tieber
fd395cf906
chore(core): Add dev feature flag for multiple global secret connections (no-changelog) (#25844) 2026-02-16 18:09:50 +00:00
Declan Carroll
c2a824a263
chore: Bump task-runner-launcher to 1.4.3 (#25818)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:50:15 +00:00
Ricardo Espinoza
b5adf9f2ec
feat(editor): Allow discarding and renaming columns during CSV import (#25605)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 17:48:36 +00:00
oleg
e85c4580a6
fix(core): Improve error for AI Tool nodes missing execute method (#25743) 2026-02-16 17:38:09 +00:00
n8n-assistant[bot]
8f4aed5cc2
🚀 Release 2.9.0 (#25850)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-02-16 17:12:46 +00:00
Declan Carroll
f2df08f501
ci: Make postgres more CI friendly (#25847) 2026-02-16 16:44:50 +00:00
Stephen Wright
20175243da
fix: Credentials overrides no longer blocks UI (#25830) 2026-02-16 16:04:40 +00:00
Matsu
f71bfff61c
chore: Make playwright-janitor private (#25845) 2026-02-16 15:50:53 +00:00
Ricardo Espinoza
fe582b3bcb
feat(core): Allow downloading data table data without system columns (#25553) 2026-02-16 14:26:03 +00:00
Declan Carroll
1a8910e4bd
fix(editor): Associate form input labels with their inputs for accessibility (#25776) 2026-02-16 13:43:37 +00:00
Declan Carroll
d5740d073b
ci: Add GH auth to container pulls (#25373) 2026-02-16 13:29:35 +00:00
Albert Alises
7e800a0395
fix(core): Gracefully handle OpenAI 429 quota errors in AI workflow builder (#25825) 2026-02-16 12:34:55 +00:00
Albert Alises
7776b6d092
fix(core): Forward custom headers in OpenAI LangChain nodes (#25824) 2026-02-16 12:24:45 +00:00
oleg
10f98a93b7
fix(editor): Zoom to fit canvas after AI builder generation (#25815)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-16 12:05:43 +00:00
Irénée
74fe36370d
feat: Return secrets count and secrets list in provider connection responses (no-changelog) (#25822)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:58:22 +00:00
Tomi Turtiainen
7d418b877b
fix(core): Use pg driver native statement timeout instead of command line (#25813) 2026-02-16 11:55:06 +00:00
Ali Elkhateeb
8684c74994
fix(core): Validate GCP service account key on initialization (#25817) 2026-02-16 11:48:01 +00:00
Irénée
a2e7c7fee9
feat: Add CRUD operations for project-specific external secrets provider connections (no-changelog) (#25708) 2026-02-16 11:47:06 +00:00
Albert Alises
f669db4ebf
fix(core): Escape curly braces in LangChain prompt templates to prevent parsing errors (#25821)
Co-authored-by: aalises <aalises@users.noreply.github.com>
2026-02-16 11:43:28 +00:00
Daria
7506ecec82
fix(editor): Show the right state on metadata update (no-changelog) (#25816) 2026-02-16 11:13:48 +00:00
Albert Alises
08e5c747ea
feat: Implement shared infrastructure and code builder tool flow to merge Ask and Build (#25681)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 11:05:45 +00:00
Jaakko Husso
bd3a1ef0cd
fix(core): Sanitize invalid characters from names of Calculator and Wikipedia tools (#25762) 2026-02-16 10:48:28 +00:00
Jaakko Husso
2497a3720c
feat(core): Support most tools on Chat hub (#25571)
Co-authored-by: autologie <suguru@n8n.io>
2026-02-16 10:37:24 +00:00
oleg
05ff9f307f
fix(OpenRouter Chat Model Node): Fix OpenRouter tool calls with empty arguments (#25731)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-16 10:32:12 +00:00
Daria
9ec0f97a9f
feat(core): Accept slash inside health endpoint env var (#25753) 2026-02-16 10:26:22 +00:00
Csaba Tuncsik
c7993462e7
fix(editor): Update CSS selectors after N8nInput refactor (#25732)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 10:15:30 +00:00
RomanDavydchuk
673844445b
feat: Add Firecrawl handler to the Quick connect module (#25528)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-02-16 09:31:07 +00:00
Declan Carroll
7b82b54a46
test: Normalize page object navigation methods to goto (#25765) 2026-02-16 09:21:45 +00:00
Andreas Fitzek
40b994af7f
chore(editor): Polish UI/UX for personal space policies (#25682) 2026-02-16 08:54:49 +00:00
Jaakko Husso
7ac0998963
chore(editor): Align beta icon on sidebar better (#25812) 2026-02-16 08:51:45 +00:00
Declan Carroll
8bee229b5d
ci: Only tag current major version releases as prerelease (#25761)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-16 08:25:06 +00:00
n8n-assistant[bot]
e0cbf2282c
ci: Restrict pr's to master from non-bundle branches (#25749)
Co-authored-by: Matsu <matias.huhta@n8n.io>
2026-02-16 06:41:43 +00:00
Declan Carroll
619a11b7a1
fix: Bumping up package versions (#25750) 2026-02-14 08:21:22 +00:00
Konstantin Tieber
503676e0b9
feat(core): Ensure credentials only use secret providers that are available in their project (no-changelog) (#25406) 2026-02-13 22:36:35 +00:00
Stephen Wright
ccae2e6443
feat: Revert Set default header auth domains in the UI (#25758) 2026-02-13 18:48:56 +00:00
Marc Littlemore
e5901370c2
feat(core): Add log streaming events for project-scoped external secrets connections (#25755) 2026-02-13 16:33:45 +00:00
Mutasem Aldmour
5c5cc070da
fix(ai-builder): Improve code-builder, addressing eval issues (#25726)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:24:54 +00:00
Elias Meire
63bd9af185
feat(editor): Add new empty state with quick connect for node credentials (#25510)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-02-13 14:34:22 +00:00
Daria
d09c6a3d5a
fix(core): Make health endpoint configurable to solve conflicts (#25729) 2026-02-13 13:47:19 +00:00
Declan Carroll
1cca93eaeb
test: Harden janitor TCR and clean up test architecture (no-changelog) (#25746) 2026-02-13 13:45:01 +00:00
Declan Carroll
593fc27863
test: Add Playwright janitor for test architecture enforcement (no-changelog) (#24869) 2026-02-13 11:03:13 +00:00
Declan Carroll
e3eafc7e87
feat: Update default Node.js version to v24 (#25707) 2026-02-13 10:56:01 +00:00
Rob Hough
7ab7911c2f
refactor(editor): Migrate Button v2 to N8nButton (no-changelog) (#24947) 2026-02-13 10:48:03 +00:00
Charlie Kolb
1ce270d129
fix(editor): Strip template preview of pinData (no-changelog) (#25727) 2026-02-13 10:22:49 +00:00
yehorkardash
f77ce6c8e8
fix(Sharepoint Node): Ensure tokens are refreshed (#24978)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-13 09:52:43 +00:00
Matsu
3798c417db
chore: Make codemirror-lang-html run as part of unit tests (#25720) 2026-02-13 09:45:26 +00:00
Sandra Zollner
3698ab1579
feat(editor): Update store logic for fetching global external secrets (#25728) 2026-02-13 09:39:27 +00:00
Daria
9352fb33e4
fix(editor): Fix bug with two consecutive saves (#25577) 2026-02-13 08:53:49 +00:00
Irénée
92735b26c4
feat: Reload providers after connection and CRUD operations (no-changelog) (#25688) 2026-02-13 08:47:53 +00:00
Declan Carroll
2fe4b21869
test: Annotate all tests with owners (#25713)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 08:12:15 +00:00
yehorkardash
4b4783ff58
test: Add tests to ai-utilities (#25443)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-13 08:10:59 +00:00
Albert Alises
66dcdb9c8c
feat: Add content-design skill for UI copy writing, review, and audit (#25587) 2026-02-13 08:05:55 +00:00
oleg
2a12181915
fix(core): Allow single-node AI Agent execution to run tools (#25709) 2026-02-13 07:38:22 +00:00
Charlie Kolb
b36a70ea37
feat(editor): Add 'Ready to run' tag and keep pinData for ready to demo templates (no-changelog) (#25446) 2026-02-13 07:31:38 +00:00
Matsu
150c13b06b
chore: Migrate codemirror packages to use vitest (#25694) 2026-02-13 06:23:25 +00:00
Sandra Zollner
d4146a69a5
feat(editor): UX improvements for external secret providers (#25686) 2026-02-12 17:04:22 +00:00
Irénée
45017703be
fix: Enable credentials experssions push and pull (#25530) 2026-02-12 17:00:48 +00:00
Andreas Fitzek
dbf6f753ac
chore(core): Remove feature flag for personal space policies (#25693) 2026-02-12 15:30:50 +00:00
github-actions[bot]
4a2c06ea54
chore: Update node popularity data (#25422)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2026-02-12 15:24:39 +00:00
Guillaume Jacquart
608e3bf214
fix(core): Refine credential access check to discard not actively used credentials (#25599) 2026-02-12 14:21:24 +00:00
Declan Carroll
951502dcde
ci: Configure Sentry sourcemaps for releases (#25539) 2026-02-12 14:20:50 +00:00
Svetoslav Dekov
ff1d7f2330
fix(editor): Add filter by accessible projects in folders query (no-changelog) (#25678) 2026-02-12 14:13:17 +00:00
Stephen Wright
c1991f44c1
feat: Allow manual login setting for OIDC alongside SAML (#25687) 2026-02-12 14:05:18 +00:00
Stephen Wright
6a7231ad34
feat: Set default header auth domains in the UI for new credentials (#25563) 2026-02-12 13:55:48 +00:00
Mutasem Aldmour
0970e4f32c
feat(ai-builder): Skip redundant node discovery in code-builder when approved plan is provided (#25608)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:25:44 +00:00
Guillaume Jacquart
3531c4d7ca
fix(editor): Check specific unpublish permission for unpublish button (#25564) 2026-02-12 13:19:01 +00:00
Jaakko Husso
e6a4c64d4d
fix(core): Fix deadlock on Chat hub on Postgres with pool size of 1 (#25654) 2026-02-12 12:49:21 +00:00
mfsiega
ea2897edc7
fix(core): Workflow indexing tolerates missing workflowId on workflowCall (#25662) 2026-02-12 12:05:31 +00:00
Jon
2cabe52a35
fix(Snowflake Node): Disable logging for Snowflake-SDK to prevent folder creation issue (#25586) 2026-02-12 11:26:41 +00:00
Eugene
892f086579
feat(core): Add introspection diagnostic tool for AI workflow builder (#25172) 2026-02-12 10:57:44 +00:00
Andreas Fitzek
cfca041d0e
chore(editor): Gate personal space policy settings behind license feature (#25527) 2026-02-12 10:12:18 +00:00
Rob Hough
88017640c4
fix(editor): Fix sticky tooltips on canvas node status icons (#25650) 2026-02-12 09:47:56 +00:00
Daria
b032111f55
fix(editor): Switch to using shift+P shortcut for publishing (#25667) 2026-02-12 09:39:46 +00:00
Svetoslav Dekov
e7dbd376e3
fix(editor): Improve loading states of move workflow/directory modal (#25287) 2026-02-12 09:38:24 +00:00
Matsu
3e079ec901
ci: Only run node-popularity in n8n-io/n8n (#25664) 2026-02-12 08:43:43 +00:00
Declan Carroll
f26bb72bdf
ci: Add Kent for local testing of Sentry events and traces (#25263) 2026-02-12 08:26:31 +00:00
Konstantin Tieber
f94d9ca045
fix(core): Project external secrets are not autocompleted (no-changelog) (#25653) 2026-02-11 20:57:53 +00:00
Ludwig Gerdes
c9f3f9b355
feat(editor): Add custom color picker for sticky notes (#23699)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-02-11 20:35:34 +00:00
Mutasem Aldmour
73cdd618d3
feat(ai-builder): Split code builder experiment into pin data variants (no-changelog) (#25644)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 18:02:15 +00:00
Sandra Zollner
70d139e5cb
feat(editor): Enable deletion of external secret stores (#25573) 2026-02-11 17:46:29 +00:00
Milorad FIlipović
967e7df258
fix(editor): Fix mcp toggle in workflow settings (#25630) 2026-02-11 16:24:08 +00:00
Ricardo Espinoza
c5ee9bad89
feat(core): Add versions support to n8n:export command (#25414)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Daria <daria.staferova@n8n.io>
2026-02-11 15:13:54 +00:00
Ricardo Espinoza
de24d70a3d
fix(editor): Skip credential auto-assignment when node displayOptions don't match (#25602)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 14:33:08 +00:00
Mutasem Aldmour
a9929f653e
perf(core): Optimize generate-node-defs with parallel writes and hash-based skip (#25626)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 13:50:50 +00:00
Albert Alises
20934363db
feat: Pass focused nodes context to planner agent (#25617) 2026-02-11 13:24:37 +00:00
Tomi Turtiainen
c706e962ec Merge tag 'n8n@2.8.0' 2026-02-11 14:35:42 +02:00
oleg
b9ad9d8357
fix(ai-builder): Improve plan mode UX: naming, question skipping, thinking states (no-changelog) (#25609)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-11 10:59:30 +00:00
oleg
9a1dd9d523
fix(Chat Memory Manager Node): Resolve sub-node expressions per item instead of only item 0 (#25570) 2026-02-11 09:57:12 +00:00
Csaba Tuncsik
0a290b9ad3
fix(editor): Update project role selector component to better manage custom roles (#24991)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-11 09:22:05 +00:00
Shireen Missi
06e48e5b3b
fix(core): Revert the fix for execution history when flow includes wait node (#25610) 2026-02-11 08:51:29 +00:00
ByteEVM
1e01a04129
fix(editor): I18n labels for time saved workflow settings (#24565) 2026-02-10 22:43:51 +00:00
Albert Alises
b17815ed25
feat(editor): Improve focused nodes chips with message display, tooltips, and "All nodes" state (#25582) 2026-02-10 17:10:57 +00:00
jonjames-n8n
402d803589
feat(API): Add public API endpoints for execution tags (#25463)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-10 16:47:22 +00:00
Declan Carroll
25e68c6a3f
test: Align proxy service helper and add local dev service stack (no-changelog) (#25467) 2026-02-10 15:03:18 +00:00
Mutasem Aldmour
cd175ddda0
refactor(ai-builder): Remove community node support from code builder (#25575)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 14:47:01 +00:00
Dimitri Lavrenük
2bba36b662
feat: Track quick connect within node installation event (#25574)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-02-10 14:30:19 +00:00
Jason Schell
099399bdf0
feat: Stripe Node: Add more triggers for invoice payments (#25454) 2026-02-10 14:29:45 +00:00
Albert Alises
8230a0b16f
fix(EmbeddingsOpenAi Node): Fix Dimensions and Encoding Format options not appearing in embedding ndoes (#25537) 2026-02-10 14:27:52 +00:00
yehorkardash
366d21d799
feat: Add example node in ai-utilities, improve response handling (#25388) 2026-02-10 13:52:14 +00:00
Mutasem Aldmour
9729c2a5da
feat(ai-builder): Add code-base workflow builder (#24535)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-10 12:24:27 +00:00
Milorad FIlipović
ba48c922c7
feat(editor): Implement partial execution from the Setup panel (no-changelog) (#25525)
Co-authored-by: Daria <daria.staferova@n8n.io>
2026-02-10 12:01:06 +00:00
RomanDavydchuk
39e9a5f754
feat: Show Quick connect banner in the NDV (#25506) 2026-02-10 11:54:05 +00:00
n8n-assistant[bot]
0b2e5d9cf0
🚀 Release 2.8.0 (#25565)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-02-10 12:00:11 +01:00
Ali Elkhateeb
d64a763ecd
feat(core): Expose externalSecretsStore to filter credentials by external secret provider key (#25526) 2026-02-10 10:10:12 +00:00
Albert Alises
70c7f5ef00
feat: Add Focused Nodes feature (#25452) 2026-02-10 10:02:21 +00:00
Milorad FIlipović
c42696c212
feat(editor): Implement credentials setup in the setup panel (#25514) 2026-02-10 10:00:59 +00:00
Andreas Fitzek
42df83cc81
refactor(editor): Move enforce MFA toggle from Users to Security settings page (#25505) 2026-02-10 09:56:58 +00:00
jeanpaul
500d0a226e
fix(editor): Show a confirmation dialog when clicking upgrade and builder is working (#25540) 2026-02-10 08:21:02 +00:00
Csaba Tuncsik
ed099ad9f9
fix(editor): Gate dynamic credentials UI behind license check (#25464) 2026-02-10 06:29:27 +00:00
Albert Alises
8ac4ff3849
feat(Motorhead Node): Hide deprecated Motorhead memory node from UI (#25536) 2026-02-09 19:23:54 +00:00
Albert Alises
e79b5f3168
fix(editor): Show a helpful empty state in AI builder for existing workflows (#25523) 2026-02-09 18:33:43 +00:00
Matsu
e095307c9e
ci: Upgrade npm to 11.5.1 for Trusted publishing (#25534) 2026-02-09 17:56:13 +00:00
Albert Alises
d18ffe18be
fix: Adjust gap behaviour of the execution buttons (#25529) 2026-02-09 15:45:10 +00:00
Ricardo Espinoza
0354b9b555
fix: Validate workflows when publishing from workflow history (#25195)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-09 14:46:15 +00:00
Ricardo Espinoza
0d842c5da5
feat(core): Add data tables to env features (#23828)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2026-02-09 14:35:47 +00:00
Albert Alises
2ba24041fd
fix: Add source to credentials open menu on telemetry (#25519) 2026-02-09 13:16:20 +00:00
oleg
f08c004e0d
fix(ai-builder): Improve plan mode defaults and modification awareness (no-changelog) (#25520)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-09 12:52:51 +00:00
oleg
72bd8c022f
chore: Remove api-types zod re-export (no-changelog) (#25515)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-09 12:27:39 +00:00
RomanDavydchuk
01b16af1bf
feat: Add endpoint to create Quick Connect credentials from the backend (#25398) 2026-02-09 12:25:29 +00:00
oleg
4d52733ce8
fix(Mistral Cloud Chat Model Node): Handle Request objects in proxyFetch (#25516)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-09 11:52:12 +00:00
Guillaume Jacquart
c780955891
fix(editor): Unidirectional data flow for role change with loader (#25438) 2026-02-09 10:57:45 +00:00
Stephen Wright
21a185e735
chore: Add telemetry for dynamic workflow executions (#25502) 2026-02-09 10:21:51 +00:00
Dawid Myslak
fe56b6a660
feat(core): Add memory abstractions to AI utilities SDK (#25392) 2026-02-09 09:24:43 +00:00
Sandra Zollner
e0c9ab2463
feat(editor): Add external secrets section to project settings (#25453) 2026-02-09 09:19:08 +00:00
yehorkardash
f2926d63e6
feat: Move utils to @n8n/ai-utilities, add openai handler (#25362) 2026-02-09 09:15:50 +00:00
Daria
724d3cf857
fix(editor): Truncate long version names in workflow history (#25371) 2026-02-09 09:05:25 +00:00
Rob Hough
297cc57be5
feat(editor): Auto-focus chat input when typing (#25317) 2026-02-09 08:58:41 +00:00
oleg
794a8d6af4
feat(ai-builder): Planning mode (#25498)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-09 08:56:01 +00:00
Filipe Tavares
0b56ad5106
chore(editor): Allow control of banner content from cloud (no-changelog) (#25412) 2026-02-09 08:48:57 +00:00
Daria
50b8764cb9
feat(core): Add workflow-version-updated event to log streaming (#25429) 2026-02-09 08:09:51 +00:00
Daria
5ba7b6d9ed
feat(editor): Add Name version action to workflow history (#25316) 2026-02-09 07:43:51 +00:00
Romeo Balta
14ef03686f
chore(editor): Update r2r workflow (no-changelog) (#25489) 2026-02-08 18:46:22 +00:00
Jaakko Husso
3a35b687b8
fix(core): Fix markdown rendering issue at streamed Chat hub responses (#25466) 2026-02-07 17:24:28 +00:00
Daria
a6f6b73eb4
fix(editor): Show conflicts modal for autosave (no-changelog) (#25458) 2026-02-06 17:45:18 +00:00
Dawid Myslak
20901b6c70
feat(editor): Add redesigned Switch component (#24934)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-02-06 17:05:51 +00:00
Iván Ovejero
5658334c26
ci: Skip e2e tests on private repository (#25457) 2026-02-06 16:41:16 +00:00
Dimitri Lavrenük
5b02673907
feat: Quick connect banner for community nodes in node search view (#25447) 2026-02-06 16:02:32 +00:00
Stephen Wright
4eb0079f46
feat: Add new scope for workflow:unpublish, assignable to personal projects and regular project roles (#25228) 2026-02-06 15:04:40 +00:00
Sandra Zollner
fe5b97916f
feat(editor): Refine permission checks in Secrets Provider Connection… (#25389) 2026-02-06 14:54:05 +00:00
Tomi Turtiainen
474d9b7e2f
feat(core): Add tracing to workflow indexing (#25437)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-06 14:51:37 +00:00
Svetoslav Dekov
f3fb477b7d
fix(editor): Prevent socket messages to writeAccessReleaseRequested without workflowId (no-changelog) (#25432) 2026-02-06 14:45:12 +00:00
Csaba Tuncsik
b0a44674d2
fix(editor): Fixes after N8nInput refactoring (#25375) 2026-02-06 14:36:19 +00:00
Suguru Inoue
6e7cbbff56
fix(core): AI models don't explain images in ChatHub (#25451) 2026-02-06 14:21:31 +00:00
Andreas Fitzek
6ab0bbbf52
chore(core): Show counts for published/shared workflows/credentials (#25442) 2026-02-06 14:06:53 +00:00
Amit Anveri
0a4714819d
fix(Asana Node): Fix empty error output when using Continue (using error output) (#24615)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-02-06 14:06:27 +00:00
Daria
e1e5e3efe9
fix(editor): Clean up collaboration state when leaving workflow (#25450) 2026-02-06 14:01:44 +00:00
Iván Ovejero
483c8210ee
feat(core): Add drain timeout for runners (#24290) 2026-02-06 13:34:53 +00:00
Iván Ovejero
b7d5d51960
chore: Update cubic rules (#25331) 2026-02-06 12:51:51 +00:00
Albert Alises
6778c37ea4
test: Add E2E tests for internal MCP service (#25380) 2026-02-06 12:38:56 +00:00
Albert Alises
0912de4a65
fix(editor): Allow AI Builder to work when privacy toggle is OFF (#25387) 2026-02-06 12:33:08 +00:00
yehorkardash
b262d95b83
feat(editor): Preview not installed community tools (#24859) 2026-02-06 12:27:15 +00:00
Stephen Wright
fb3fe5fb35
feat: Add projects to credentials list response (#25384) 2026-02-06 11:43:29 +00:00
Declan Carroll
a33f33d3d9
test(benchmark): Add expression engine performance benchmarks (no-changelog) (#24199)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-02-06 11:38:25 +00:00
Matsu
813429cb68
chore: Remove dependency on run-script-os (#25282) 2026-02-06 11:07:53 +00:00
Jaakko Husso
38b267baed
feat(editor): Boost Claude Opus 4.6 priority in chat hub model selector (#25434) 2026-02-06 10:58:14 +00:00
n8n-assistant[bot]
8f129a7363
refactor(core): Improve expressions handling (#25435)
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
2026-02-06 10:55:44 +00:00
Declan Carroll
1e3d933651
test: Improve memory profiling in performance tests (#25403) 2026-02-06 10:40:07 +00:00
Tomi Turtiainen
8abc0a8a58
chore: Fix claude config (#25426) 2026-02-06 10:37:35 +00:00
Csaba Tuncsik
4f65f7201e
chore: Add Claude Code configuration for n8n development (#23440)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-06 10:36:18 +00:00
Suguru Inoue
50482f9f2f
feat(editor): Add text search to IconPicker (#25357) 2026-02-06 10:30:58 +00:00
mfsiega
526a896565
feat(core): Enable workflow dependency indexing by default (#25431) 2026-02-06 10:27:15 +00:00
Jon
41195fb737
fix(Webflow Node): Fix issue with credential test not working with the v2 api (#25052)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-02-06 10:01:18 +00:00
Iván Ovejero
d43e49a111
refactor(core): Replace zod-class with minimal implementation (#25393) 2026-02-06 09:45:22 +00:00
Alex Grozav
ccbb325ef5
fix: Fix Chromatic workflow trigger and make failures block merging (no-changelog) (#25396)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-06 09:27:18 +00:00
Matsu
b63dadee37
ci: Remove secrets.NPM_TOKEN access in preparation for OIDC (#25365)
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
2026-02-06 09:15:34 +00:00
Irénée
7a4436eda5
feat: Add project-scoped secrets provider list endpoint (no-changelog) (#25372)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-02-06 09:08:59 +00:00
Dimitri Lavrenük
279dbd06a7
fix: Refine webhook conflict checks to ignore waiting webhooks (#25395)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-06 08:34:23 +00:00
Matsu
8331ebc114
chore: Remove cats from code ownership of node-popularity.json (#25420) 2026-02-06 08:13:53 +00:00
Tomi Turtiainen
31d1109d08
chore: Add more claude permissions (#25402) 2026-02-06 07:53:51 +00:00
Svetoslav Dekov
f33b40a60e
fix(editor): Fix alignment if workfow history items (no-changelog) (#25361) 2026-02-06 07:40:05 +00:00
Charlie Kolb
1fd320160d
fix(Data Table Node): Fallback to workflow-derived projectId if undefined (#25320) 2026-02-06 07:32:09 +00:00
Michael Kret
ee1cc7fc20
feat(Kafka Trigger Node): Refactoring and fixes (#25088) 2026-02-06 04:37:59 +00:00
Nikhil Kuriakose
5e7983f08d
fix(editor): Ensure personal project is used when a user is picked in workflow filter (#25077)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-02-05 19:11:14 +00:00
n8n-assistant[bot]
2b73ce4288
chore(core): Add more tests (#25401)
Co-authored-by: Konstantin Tieber <46342664+konstantintieber@users.noreply.github.com>
2026-02-05 18:39:30 +00:00
Veaceslav
6d2e489e54
feat(Currents Node): Align with API array params (#25257) 2026-02-05 18:37:37 +00:00
Andreas
b32ce90ecf
fix(core): Custom proxy agent for discovery sso oidc (#25168) 2026-02-05 17:17:34 +00:00
Andreas Fitzek
a08c036c94
chore(editor): Provide custom tooltips for personal space policies (#25358) 2026-02-05 17:07:37 +00:00
Alex Grozav
2aad45bc77
feat(editor): Store workflow editable documents by id (no-changelog) (#25327)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-05 17:04:34 +00:00
Declan Carroll
fcf060f9c4
ci: Add continue-on-error for GHCR image deletion (#25270) 2026-02-05 17:02:51 +00:00
Declan Carroll
7790511172
ci: Use repository context for GHCR image names (#25391) 2026-02-05 16:44:21 +00:00
James Gee
aa41df63f8
feat(core): Redact/Unredact settings on GET / PATCH of secret providers (#25366)
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
Co-authored-by: konstantintieber <konstantin.tieber@n8n.io>
2026-02-05 16:36:41 +00:00
Sandra Zollner
be370e096b
feat(editor): Improve sticky note behavior during node insertion (#25207) 2026-02-05 15:37:25 +00:00
Svetoslav Dekov
fd818b1570
fix(editor): Fix node suggestion in node creator to always be request node (#25216) 2026-02-05 15:15:07 +00:00
Charlie Kolb
30e6d274cd
fix(core): Avoid fetching workflows unpaginated if getWorkflows API is used with projectId (#25370) 2026-02-05 14:48:33 +00:00
Ali Elkhateeb
fb2c5946c3
refactor: Improve performance of source control methods (#25298) 2026-02-05 14:39:30 +00:00
Jaakko Husso
2d02bb4e63
fix(editor): Skip welcome screen when agent is pre-selected (#25374) 2026-02-05 13:33:40 +00:00
Guillaume Jacquart
a7e2dcf1fe
feat(core): Add log streaming for personal publishing restriction changes (#25253)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-05 13:29:09 +00:00
Albert Alises
b1385479da
refactor(core): Consolidate MCP trigger server logic into nodes-langchain package (#25336) 2026-02-05 13:25:50 +00:00
Jaakko Husso
78fe19807b
feat(editor): Support Chat node's 'Send and Wait for Response' mode approval buttons on Chat hub (#25338) 2026-02-05 13:15:26 +00:00
Stephen Wright
5e573bfa30
feat: Add credentials list endpoint + new scopes (#25309) 2026-02-05 13:15:10 +00:00
Sandra Zollner
490dc26257
feat(editor): Extend secrets provider connection modal with project s… (#25295) 2026-02-05 13:01:47 +00:00
Guillaume Jacquart
e9a5d76475
chore(core): Extract email auth handler. extract login method into multiple functions (#25246) 2026-02-05 13:00:49 +00:00
Guillaume Jacquart
a70b2ea379
fix(core): Prevent SSO enforcement bypass via self-service settings API (#25330) 2026-02-05 12:58:39 +00:00
Michael Kret
2bba053d09
fix: Fix status overwrite for donePromise (#24897) 2026-02-05 12:14:24 +00:00
Elias Meire
1292b80169
fix(core): Auto set pairedItem when N input items create 1 output item (#25203)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-02-05 09:56:47 +00:00
Jaakko Husso
bb45ed2619
fix(core): Disallow editing AI messages on Chat hub (#25352) 2026-02-05 09:32:24 +00:00
yehorkardash
c6d62182bd
feat: Add initial interfaces to ai-node-sdk (#25248) 2026-02-05 09:27:21 +00:00
Svetoslav Dekov
0cd9ce3a4b
fix(editor): Cleanup data table add column popover error state on open (no-changelog) (#24751) 2026-02-05 09:15:04 +00:00
荻升
7d51406656
fix(Postgres Node): Enable non-numeric comparisons for WHERE clause operators (#18544) 2026-02-05 09:10:38 +00:00
Svetoslav Dekov
c7d84d6825
fix(editor): Fix resource creation menu spacing issue (no-changelog) (#25328) 2026-02-05 08:38:46 +00:00
phyllis-noester
112d0eb6b3
feat(core): Support disabling sharing from personal space (#25259)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-04 19:19:05 +00:00
oleg
6b27a39697
feat(ai-builder): Add Workflow Context Tools for On-Demand Data Fetching (#25070)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-02-04 19:18:09 +00:00
RomanDavydchuk
ac832e6530
fix(Form Node): Render \n properly in the Form Ending page (#24988)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-02-04 18:19:51 +00:00
Daria
0ddfb60a95
feat(core): Add workflow history update endpoint (no-changelog) (#25043) 2026-02-04 17:06:44 +00:00
Jaakko Husso
813885fbd1
feat(core): Handle resuming executions on Chat hub (#25296) 2026-02-04 16:42:53 +00:00
Suguru Inoue
8354e39b68
feat(core): Editing document in ChatHub (#25211) 2026-02-04 16:00:16 +00:00
Declan Carroll
ac24c83cd4
ci: Add SQLite sanity check to e2e tests (#25303) 2026-02-04 15:12:53 +00:00
Dawid Myslak
5326e27858
docs: Add SDK interface specification for community AI nodes (#25249)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-04 15:02:52 +00:00
James Gee
3842dadf10
feat(core): Test connection & refresh secrets (#25294) 2026-02-04 14:58:14 +00:00
Andreas Fitzek
ef5fb0d9f5
fix(core): Syslog message id RFC5424 compliance (#25321) 2026-02-04 14:28:28 +00:00
Svetoslav Dekov
8cdd9bd9fe
fix(editor): Add checksum validation when archive/unpublish workflow from canvas (#25302) 2026-02-04 13:58:35 +00:00
Alex Grozav
26805b6f36
refactor(editor): Move initialization logic to WorkflowLayout (no-changelog) (#25288)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-04 13:55:46 +00:00
Michael Kret
045f5b0b2c
chore: Move logWrapper and related helpers to ai-utilities (#25279) 2026-02-04 13:46:03 +00:00
Guillaume Jacquart
a7ebe7746e
chore(core): Run migration tests on PRs (#25181) 2026-02-04 13:29:54 +00:00
Konstantin Tieber
f6db13a858
fix(core): Wrong pagination argument order for sqlite in copyTables helper (#25301)
Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
2026-02-04 13:11:29 +00:00
Dimitri Lavrenük
1e1e459784
feat: Implement quick connect module and configuration provider (#25231) 2026-02-04 12:56:47 +00:00
Iván Ovejero
f4de4300a2
perf(core): Skip serialization for push messages with no recipients (#25308) 2026-02-04 12:52:32 +00:00
Iván Ovejero
a5541fe65d
chore(core): Silence disallowed strings eval error (#25293) 2026-02-04 10:39:26 +00:00
Iván Ovejero
5446098653
perf(core): Make event loop block detection configurable (#25291) 2026-02-04 10:39:18 +00:00
Jaakko Husso
ef22db2c62
feat(core): Add workflowExecuteResume lifecycle hook (#25240) 2026-02-04 09:58:08 +00:00
Stephen Wright
a5f84ec040
feat: Project users public endpoint (#25189) 2026-02-04 09:16:46 +00:00
Benjamin Schroth
f45ba3f521
fix(core): Only show AI-provided tool call arguments in input logs (#25280)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 09:12:45 +00:00
Jon
d85b6888f0
fix: Update anonymous telemetry to remove values that are not needed (#25040)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-02-04 09:06:21 +00:00
Michael Drury
832e580b39
chore(ai-builder): Add CSV output for evaluation results (#25193)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 09:02:14 +00:00
Andreas Fitzek
eaf805215e
fix(core): Skip AuthRolesService.init() for workers to prevent scope deletion (#25245)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 08:55:20 +00:00
Albert Alises
50e1f66c8f
feat(core): Add MCP queue mode and multi-main support (#25147) 2026-02-04 08:40:48 +00:00
Iván Ovejero
1694969609
perf(core): Use Map for O(n) execution deduplication (#25210) 2026-02-04 08:37:47 +00:00
Tomi Turtiainen
3c4ff9c390
fix(benchmark): Add dockerignore exceptions for benchmark image build (#25285)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 08:29:02 +00:00
Tomi Turtiainen
a3ff1841af
fix(core): Prevent SQL syntax error when filtering users with empty ids array (#25284)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 07:32:58 +00:00
Jaakko Husso
eeca75d254
fix(core): Make restartExecutionId get passed on queue mode (#25234) 2026-02-03 19:12:39 +00:00
Jon
381c6f91a3
fix: Fix issue with MCP DCR always trying to use base url and not keeping the path (#25174) 2026-02-03 15:24:26 +00:00
Albert Alises
0eaf6d1c98
fix(editor): Return actual node name from rename operation (#25217) 2026-02-03 13:51:35 +00:00
Svetoslav Dekov
143a1dd67f
fix(editor): Fix ParameterInput formatting breaking existing newlines (#25213) 2026-02-03 13:23:45 +00:00
Guillaume Jacquart
642cb061ed
chore(core): Add auth handler registry to reverse control of the ldap call (#25078) 2026-02-03 13:23:06 +00:00
James Gee
c09a6ed2e4
feat(core): Add localstack for testing aws external secret provider (#25183) 2026-02-03 13:14:51 +00:00
Tomi Turtiainen
103468af05
perf(core): Check if row exists instead of querying it entirely (#25223) 2026-02-03 13:05:16 +00:00
Milorad FIlipović
ce1c787d11
fix(core): Stop showing setup on first load in demo mode (#25226) 2026-02-03 12:52:58 +00:00
yehorkardash
8b0f3efc8f
chore: Add new ai-node-sdk (#25219) 2026-02-03 12:17:14 +00:00
Iván Ovejero
3cd17485fe
perf(core): Remove redundant webhook cache rebuild on activation (#25220) 2026-02-03 12:07:52 +00:00
Iván Ovejero
5209c52e83
perf(core): Skip workflow_history JOIN for activate, deactivate, and update (#25185) 2026-02-03 12:00:17 +00:00
Iván Ovejero
1a2b1cfa73
perf(core): Remove more JOINs from workflow queries (#25182) 2026-02-03 12:00:02 +00:00
Elias Meire
4b81864962
fix(editor): Use new dropdown component in resource mapper (#25204) 2026-02-03 11:58:37 +00:00
Sandra Zollner
a27a3cca2a
refactor(editor): Remove secret provider mock API usage and mock file (no-changelog) (#25218) 2026-02-03 11:45:25 +00:00
Irénée
b351d8dd1e
feat(core): Add secrets completions API endpoints for global and project scopes (#25205) 2026-02-03 11:19:12 +00:00
Iván Ovejero
92644675ae
perf(core): Lazyload tracing (#25206) 2026-02-03 10:48:22 +00:00
yehorkardash
91ec8dcda0
fix(Typeform Node): Refactor signature validation (#24987) 2026-02-03 10:44:52 +00:00
Declan Carroll
7a349742d2
fix: Renames and clarifies test metric options (#25135) 2026-02-03 10:36:12 +00:00
Daria
27d5120261
feat(editor): Add ui store modal registration test and clean up (no-changelog) (#25209) 2026-02-03 10:33:01 +00:00
Irénée
9e24f5b099
feat: Implement Secret Providers Types API endpoints (no-changelog) (#25200) 2026-02-03 10:30:55 +00:00
Declan Carroll
8730bedd2a
ci: Improvements to test containers e2e setup (#25140) 2026-02-03 10:16:32 +00:00
Milorad FIlipović
b26a25cdaf
feat(editor): Add base for the setup panel feature (no-changelog) (#25010) 2026-02-03 10:15:56 +00:00
Ricardo Espinoza
cfd59cc55b
fix(editor): Sidebar labels are not visible (#25186)
Co-authored-by: Romeo Balta <7095569+romeobalta@users.noreply.github.com>
2026-02-02 17:28:57 +00:00
Michael Drury
21e4364920
feat(ai-builder): Adding node parameter (required and options) programmatic validations to WFB (#25101)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 17:16:43 +00:00
Stephen Wright
7108ef45fa
feat: Selectively skip auth only for dynamic creds (#25184) 2026-02-02 16:35:25 +00:00
Tomi Turtiainen
dee6c0cd1a
chore(core): Add tracing abstraction layer (#25118) 2026-02-02 16:04:40 +00:00
Stephen Wright
e1a1e87001
feat: Disallow usage of unsupported protocols in oauth fields (#25170) 2026-02-02 15:37:47 +00:00
Csaba Tuncsik
76b73e17a9
fix(core): Update computeIsPending logic to account for external auth identities (#24926) 2026-02-02 15:14:02 +00:00
Charlie Kolb
f4b2855ff8
chore(editor): Add count to Stop Many Execs telemetry (#24773) 2026-02-02 15:02:00 +00:00
Iván Ovejero
8057b725dc
perf(core): Optimize credentials access (#25150) 2026-02-02 14:07:34 +00:00
Iván Ovejero
c9b661fecf
perf(core): Optimize access for webhooks and workflows (#25149) 2026-02-02 14:02:56 +00:00
oleg
24bb638982
refactor(ai-builder): Consolidate AI Workflow Builder agents and simplify prompts (no-changelog) (#25020)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-02-02 13:57:48 +00:00
James Gee
aaf69b8254
feat(core): Support disabling publishing workflows in personal space (no-changelog) (#24111)
Co-authored-by: konstantintieber <konstantin.tieber@n8n.io>
Co-authored-by: Andreas Fitzek <andreas.fitzek@n8n.io>
2026-02-02 13:49:51 +00:00
Tomi Turtiainen
b726db2ee0 Merge tag 'n8n@2.7.0' 2026-02-02 16:00:50 +02:00
Stephen Wright
f516d9495b
feat: Update log streaming to unwrap nested proxy (#25159) 2026-02-02 13:45:37 +00:00
Iván Ovejero
427556a4d8
ci: Fix flaky folders test (#25152) 2026-02-02 13:33:53 +00:00
n8n-assistant[bot]
abe0d8a362
🚀 Release 2.7.0 (#25167) 2026-02-02 15:30:26 +02:00
Irénée
638d3f87a7
feat(core): Add project-scoped support to external secrets manager (no-changelog) (#25090)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 13:28:55 +00:00
Albert Alises
ce70395b2f
fix: Adjust styling of credentials setup card (#25163) 2026-02-02 13:24:38 +00:00
Iván Ovejero
eaacb5af81
chore: Revert reversion of ensuring execution ID in webhook response (#25164) 2026-02-02 13:06:30 +00:00
Romeo Balta
83bf5e16ec
feat(editor): Sidebar state experiment (no-changelog) (#25096) 2026-02-02 12:42:58 +00:00
Alex Grozav
58d0227ddd
refactor(editor): Centralize workflow ID via provide/inject (#25097)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-02-02 12:00:22 +00:00
Daria
e2f7d548d9
fix(editor): Load pull result modal key (no-changelog) (#25160) 2026-02-02 11:49:07 +00:00
Ricardo Espinoza
e53cff5d83
fix(editor): Set up baseline to empty workflows list (no-changelog) (#25063)
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
2026-02-02 11:36:08 +00:00
Csaba Tuncsik
c7c9fa5693
refactor(editor): Replace old N8nInput with new Reka UI based input (#22963)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-02 11:30:38 +00:00
Sandra Zollner
9c52c963da
refactor(core): Update date query validation to accommodate timing issue (#25095) 2026-02-02 10:54:39 +00:00
Raúl Gómez Morales
f2189fddf3
chore: Crdt package follow up (#24715) 2026-02-02 10:36:49 +00:00
Tomi Turtiainen
974426263b
refactor(core): Use task runner for sort operations (#24910) 2026-02-02 10:26:57 +00:00
Guillaume Jacquart
50706d82e1
chore(core): Remove unused json compatible output check and tracking (#25155) 2026-02-02 10:19:43 +00:00
Tomi Turtiainen
21421f5c39
fix(core): Use stricter flags when starting python runner (#24983) 2026-02-02 10:08:44 +00:00
Jon
f9e230e2d0
fix: Fix issue with workflowId not being correctly validated (#24866) 2026-02-02 10:04:20 +00:00
Daria
18487d0459
feat(core): Add auto-publish on Environments Feature Pull (#24701) 2026-02-02 09:45:27 +00:00
Andreas Fitzek
038a399ada
chore(core): Change db column type to TEXT for subject_id (#25044) 2026-02-02 09:34:37 +00:00
Guillaume Jacquart
40f670562e
fix(core): Update ownership cache update on folder transfer (#24974) 2026-02-02 09:27:00 +00:00
Jaakko Husso
d4a6a068d4
refactor(core): Split title generation and executions handling from Chat hub service (#25110) 2026-02-02 08:53:37 +00:00
Michael Kret
805b2223a8
feat(Microsoft Agent 365 Trigger Node): Integration for Microsoft Agents 365 (#25145)
Co-authored-by: Rick Brighenti <202984599+rbrighenti@users.noreply.github.com>
2026-02-02 08:42:43 +00:00
Iván Ovejero
a7408fa082
fix(core): Revert ensuring execution ID in webhook response (#25146) 2026-02-02 08:42:22 +00:00
mfsiega
754386247c
feat(core): Index both draft and published workflow versions (no-changelog) (#25009) 2026-02-02 08:41:24 +00:00
Milorad FIlipović
ff68b7bd2c
feat(editor): Add AI Usage settings page (#20926) 2026-02-02 08:20:54 +00:00
Iván Ovejero
075ffd05f1
perf(core): Optimize saving execution progress (#25089) 2026-02-02 08:12:49 +00:00
Tomi Turtiainen
4995710fcb
chore: Upgrade pg to 8.17.0 (#25116) 2026-02-02 07:45:27 +00:00
Tomi Turtiainen
ebc11d9276
chore: Ignore health and metrics endpoints from tracing (#25117) 2026-02-02 07:36:23 +00:00
Declan Carroll
ab8bd71268
ci: Cleanup some CI checks (#25111) 2026-02-02 07:22:36 +00:00
yehorkardash
89f8fb04ca
fix(AMQP Trigger Node): Save failed executions (#21878)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-31 12:07:35 +00:00
Tomi Turtiainen
1ae7b6ee1b
chore: Remove error reporting of too large telemetry events (#25103) 2026-01-30 19:56:06 +00:00
Tomi Turtiainen
83e657eb4e
fix(editor): Always ensure data worker tables exist (no-changelog) (#25087) 2026-01-30 18:42:06 +00:00
Daria
769e7819a6
feat(editor): Pause autosave on connection failures (#24456) 2026-01-30 17:18:28 +00:00
Adrien
1edb600151
fix(core): Replace deprecated 'application' actor value with 'app' in Linear OAuth (#20985)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-01-30 15:47:04 +00:00
Svetoslav Dekov
4f3358810a
feat(editor): Add dynamic templates experiment (no-changelog) (#25030) 2026-01-30 15:43:08 +00:00
Jaakko Husso
0396402e69
refactor(core): Use websockets on Chat hub message streaming (#24995) 2026-01-30 15:19:39 +00:00
Iván Ovejero
ea4d2d217a
fix(core): Fix missing early return on Bull error (#25084) 2026-01-30 14:49:45 +00:00
Andreas Fitzek
e91edc794f
chore(core): Support cookie for auth token extraction in dynamic credential endpoints (#25036) 2026-01-30 14:35:15 +00:00
yehorkardash
e1dd07777d
fix(core): Use proxy for all npm commands (#24909) 2026-01-30 14:15:25 +00:00
Konstantin Tieber
4d6d0d15b7
feat(core): Show project secrets in expression editor (no-changelog) (#25062) 2026-01-30 13:38:02 +00:00
phyllis-noester
d93a5ba097
docs: Update contributing guide to ease onboarding (#24951)
Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com>
2026-01-30 12:49:30 +00:00
Iván Ovejero
c4ce0fbfbb
refactor(core): Route execution creation through ExecutionPersistence (#24912) 2026-01-30 12:46:53 +00:00
Iván Ovejero
eb9978b890
refactor(core): Rename ~/.n8n/binaryData to ~/.n8n/storage (#24937) 2026-01-30 12:45:45 +00:00
krisn0x
25f5199b46
feat(Crypto Node): Add credentials for Hmac and Sign operations (#24798) 2026-01-30 12:33:09 +00:00
Iván Ovejero
326869e794
fix(editor): Move version store init after authentication (#25081) 2026-01-30 12:25:33 +00:00
mfsiega
f3da425dd2
feat(core): Introduce table to track actually published workflow versions (no-changelog) (#25051) 2026-01-30 12:02:47 +00:00
Iván Ovejero
efd741f529
perf(core): Minimize execution data fetching (#25073) 2026-01-30 11:32:13 +00:00
Michael Drury
fb7e5d5a20
fix(ai-builder): Fixing padding in WFB chat when message feedback is showing (#25079) 2026-01-30 11:06:03 +00:00
mfsiega
7e580ea8cf
fix(core): Support reconnecting on Redis failover (#25038) 2026-01-30 11:05:44 +00:00
Guillaume Jacquart
a4a9234a39
chore(editor): Remove all calls to fetch all users and replace with targeted filtering (#25024) 2026-01-30 10:53:37 +00:00
Sandra Zollner
d176890e99
refactor(editor): Update connection handling to use providerKey (#25061) 2026-01-30 10:53:14 +00:00
Albert Alises
a5cde70330
fix(VectorStoreAzureAISearch Node): Clear Azure AI Search index once per batch (#25069) 2026-01-30 10:00:51 +00:00
Declan Carroll
ad62c8f1fd
test: Fix flaky demo test (#25076) 2026-01-30 09:57:03 +00:00
Tomi Turtiainen
659de949cb
feat(core): Add profiling support via sentry (#25049) 2026-01-30 09:49:50 +00:00
Rob Hough
779a04f471
feat(editor): Show ChatHub action buttons on hover (#24923) 2026-01-30 09:37:41 +00:00
Declan Carroll
2a710239d2
ci: Skip node base CI integration tests (#25068) 2026-01-30 08:38:30 +00:00
Benjamin Schroth
3dbca3e0df
fix(AI Agent Node): Fix gemini thought signatures for parallel tool calls (#24982) 2026-01-30 08:34:39 +00:00
Guillaume Jacquart
252c5a6c3c
feat(core): Allow changing the oauth token data for oauth2 credentials on public API PATCH (#25042) 2026-01-29 16:23:06 +00:00
Tomi Turtiainen
39df0d5ff1
chore(core): Remove mysql and mariadb specfic code (#24908)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-29 15:57:33 +00:00
RomanDavydchuk
f3e2930f0e
fix(MySQL Node): Support "Continue on Error" for connection-related errors (#25032) 2026-01-29 15:30:51 +00:00
Iván Ovejero
daba1e2846
feat(core): Add default Postgres query timeout (#25041) 2026-01-29 14:43:52 +00:00
Declan Carroll
68d33796db
ci: Derive runner image from n8n image for CI (#25035) 2026-01-29 14:37:40 +00:00
Tomi Turtiainen
f575728289
chore: Upgrade sentry packages to major 10 (#25026) 2026-01-29 14:35:49 +00:00
Sandra Zollner
768bf7f7f1
feat(editor): Secret Store connection modal for multiple providers (#25004) 2026-01-29 14:16:04 +00:00
Svetoslav Dekov
27eae1186c
fix(editor): Drop the contact prompt on workflow save as it's not needed anymore (no-changelog) (#24891) 2026-01-29 13:43:24 +00:00
Daria
36355f8c58
feat: Remove success toasts on workflow creation (#24979) 2026-01-29 13:07:04 +00:00
Csaba Tuncsik
526a2394df
fix(editor): Fix layout of insights tab (#24994) 2026-01-29 12:56:58 +00:00
Albert Alises
01f000b4c8
fix: Update stack cleanup command message to work from any directory (#25034) 2026-01-29 12:50:32 +00:00
Michael Drury
2b0f13d760
fix(ai-builder): Detect placeholder values inside larger parameters generated by workflow builder (#24950) 2026-01-29 12:15:02 +00:00
James Gee
386979a27c
feat(core): Fill out external secret provider endpoints for CRUD operations (#24862) 2026-01-29 10:01:00 +00:00
Guillaume Jacquart
9958eed92c
fix(core): Fix orchestration init modules (#23360) 2026-01-29 09:22:51 +00:00
Marc Littlemore
ae17e8ec61
fix(core): Log warning where file values contain white space at the start or end (e.g. new lines) (#24442) 2026-01-29 08:58:00 +00:00
RomanDavydchuk
b98d0fc98a
feat: Add telemetry for the auth method used in MCP client (no-changelog) (#24984) 2026-01-29 06:54:12 +00:00
Albert Alises
784ab19e40
feat: Add option to select eval suite on manual workflow dispatch (#24998) 2026-01-28 17:11:42 +00:00
Giulio Andreini
d6a33902d3
fix(editor): Fix source control sidebar icon width when collapsed (no-changelog) (#24990) 2026-01-28 16:39:46 +00:00
Ricardo Espinoza
da7b2f0709
fix(core): Posthog proxy (no-changelog) (#22432)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2026-01-28 16:05:45 +00:00
Marc Littlemore
2a7c837459
chore: Remove beta label from API page (#24992) 2026-01-28 15:37:37 +00:00
mfsiega
a8d75f7433
fix(core): Do not send an undefined location header on form redirects (#24989) 2026-01-28 15:06:41 +00:00
Eugene
8983bd563f
fix(editor): Disable hover effects on non-drop-targets during drag (#24948)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-28 14:52:06 +00:00
Alex Grozav
31a11c07fe
refactor(editor): Extract workflow list management into dedicated store (no-changelog) (#24971)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-28 14:34:43 +00:00
Michael Drury
18c903d782
feat(ai-builder): Moving feedback buttons in workflow builder chat (#24732) 2026-01-28 14:12:13 +00:00
Danny Martini
308429c871
feat(core): Make database ping timeout configurable (#24985)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-28 14:07:21 +00:00
Rob Hough
a19ae52e7b
feat(editor): Add Dialog component to design system (#24591) 2026-01-28 14:06:21 +00:00
Iván Ovejero
a5117a30fc
perf(core): Continue reducing baseline memory usage (#24981) 2026-01-28 12:50:37 +00:00
chauhan_s
1e777cf8e0
fix(editor): Prevent executions date picker popover from being clipped (#24896) 2026-01-28 12:40:11 +00:00
Alex Grozav
728031187c
refactor(editor): Use Map for node lookup in connection mapping (no-changelog) (#24972)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-28 12:21:43 +00:00
Dawid Myslak
4622acaccc
feat(Zendesk Trigger Node): Add webhook signature verification (#24881) 2026-01-28 12:19:02 +00:00
Alex Grozav
7c9ec61eaf
fix(editor): Replace O(n) find with O(1) Map lookup in getConnectionLabel (no-changelog) (#24968)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-28 12:13:33 +00:00
Andreas Fitzek
e3110d1f24
fix(Wait Node): Reject wait execution when workflow is canceled (#15924) 2026-01-28 11:52:46 +00:00
Declan Carroll
ea83ed49a0
ci: Docker CI changes (#24962) 2026-01-28 11:41:33 +00:00
Horacio Gonzalez
e7c5c17402
fix(core): Add Redis TCP Keep-Alive Configuration for Queue Mode (#23902) 2026-01-28 11:11:53 +00:00
Iván Ovejero
8693d9ead1
refactor(core): Improve Python match extraction handling (#24975) 2026-01-28 10:37:33 +00:00
rutgere-indeed
b110a9e467
feat(Kafka Trigger Node): Add option to keep binary data for downstream processing (#21843)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-01-28 09:59:21 +00:00
Guillaume Jacquart
dce48711ce
fix(core): Small optimizations on users api to reduce db calls (#24882) 2026-01-28 09:57:34 +00:00
Declan Carroll
8474689a49
test: Add testcontainers infrastructure and MySQL integration tests (#24603) 2026-01-28 09:33:43 +00:00
RomanDavydchuk
36afab0ec0
fix(Chat Node): Output structure for Send and Wait operation (#24898)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-28 07:34:41 +00:00
Iván Ovejero
b006ecfb96
fix(core): Ensure workflows with response promises respect graceful shutdown (#24879) 2026-01-27 22:29:18 +00:00
mfsiega
bc0c5067ff
feat(core): Introduce feature flag for workflow publication (no-changelog) (#24921) 2026-01-27 17:33:04 +00:00
Declan Carroll
356e3e69bc
feat: Add Currents.dev node (#24566) 2026-01-27 16:52:08 +00:00
yehorkardash
8b7ba6f53b
fix: Validate OpenAI urls (#24922) 2026-01-27 16:13:18 +00:00
mfsiega
0e1b2a870e
feat(core): Index both latest published and draft workflow versions (#24861) 2026-01-27 16:00:58 +00:00
Michael Drury
d12e9318d0
feat(ai-builder): Workflow builder "respond to webhook" understanding (#24641) 2026-01-27 14:38:09 +00:00
Rob Hough
07273e5b86
refactor(editor): Improve text styles in Chat Hub (#24794) 2026-01-27 13:19:40 +00:00
Daria
567ae92756
fix(editor): Disable WF history button when autosave is not complete (#24904) 2026-01-27 13:12:15 +00:00
Irénée
30190e83f9
chore: Add secrets provider connection tables migration (#24877) 2026-01-27 12:31:45 +00:00
Iván Ovejero
b75347b3a1
perf(core): Make MCP module exclusive to main (#24899) 2026-01-27 12:10:44 +00:00
Iván Ovejero
ad7571fdb2
fix(core): Ensure execution ID is available at runtime in Webhook response (#24876) 2026-01-27 11:47:41 +00:00
Romeo Balta
cbdee677c3
feat(editor): AI builder in empty state (no-changelog) (#24840) 2026-01-27 11:20:52 +00:00
chauhan_s
35583ad80b
fix(editor): Allow '-' and '_' in subworkflow caller IDs (#24849) 2026-01-27 10:52:28 +00:00
Iván Ovejero
012ce09846
perf(core): Lazyload Swagger, PSL and MCP libs (#24902) 2026-01-27 10:40:00 +00:00
Sandra Zollner
5c025c1684
fix(editor): Prevent connection lines from overlapping plus handle buttons (#24631) 2026-01-27 10:29:49 +00:00
Artem Sorokin
af0c70ec73
ci: Optimize GHCR cleanup script with early termination and parallel pagination (#24892) 2026-01-27 10:02:46 +00:00
Iván Ovejero
1522df3712
refactor(core): Introduce ExecutionPersistence service (#24857) 2026-01-27 09:59:51 +00:00
Declan Carroll
c5f00060aa
ci: Allow runner fallback from global variable (#24786) 2026-01-27 09:25:37 +00:00
Sandra Zollner
6dd4cc81b4
feat(editor): Add secrets provider connections dashboard (#24654)
Co-authored-by: Jan <3185243+JanOstrowka@users.noreply.github.com>
2026-01-27 09:15:11 +00:00
Eugene
0faada7f36
fix(core): Update AI Builder node types after community package changes (#24883) 2026-01-27 09:15:01 +00:00
Iván Ovejero
76b4604a31
refactor(core): Improve f-string handling (#24864) 2026-01-27 08:52:35 +00:00
Declan Carroll
c52da486c8
ci: Add timing stats for unit tests (#24821) 2026-01-27 08:16:33 +00:00
Tomi Turtiainen
3f7d7e3e70 Merge tag 'n8n@2.6.0' 2026-01-27 10:34:35 +02:00
Artem Sorokin
0deee3c1ca
ci: Fix release tag merge failing with unrelated histories (#24884) 2026-01-27 07:01:59 +00:00
Declan Carroll
993228addc
chore: Bump up dependencies (#24886) 2026-01-26 20:00:41 +00:00
Albert Alises
b384e8c9ec
fix(editor): Truncate long project names with ellipsis in breadcrumb (#24853) 2026-01-26 15:43:26 +00:00
n8n-assistant[bot]
eeba9f1ced
🚀 Release 2.6.0 (#24880)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-01-26 16:36:54 +01:00
Andreas Fitzek
ee2ce6cd19
chore(core): Introduce n8n resolver for dynamic credentials (#24625) 2026-01-26 15:22:09 +00:00
Ricardo Espinoza
6b474e4141
feat(core): Add data table resources to the public API (#23610)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 15:18:39 +00:00
Giulio Andreini
7129c88fd9
fix(editor): Improve checkbox and lock icon alignment (#24575) 2026-01-26 15:09:18 +00:00
mfsiega
44650b1bb3
feat(FormTrigger Node): Support ip filtering for the FormTrigger node (#24644) 2026-01-26 14:58:24 +00:00
Artem Sorokin
bbc74965ed
ci: Extract GHCR cleanup to shared script and add scheduled cleanup (#24870) 2026-01-26 14:24:21 +00:00
Shireen Missi
bfec0685f7
fix(Onfleet Trigger Node): Fix content type issue (#24767) 2026-01-26 14:13:51 +00:00
Michael Kret
4293b748c8
feat: Optimize community nodes types fetching (#24632)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-01-26 13:54:59 +00:00
Declan Carroll
cb8b621245
docs: Add test migration guidelines (#24759) 2026-01-26 13:38:51 +00:00
Jaakko Husso
030f4cd5c1
feat(editor): Prioritize newer models on Chat hub model picker (#24867) 2026-01-26 12:45:44 +00:00
Dimitri Lavrenük
f099516935
chore: Introduce backport github action (#24655) 2026-01-26 12:30:46 +00:00
mfsiega
cbb1f33fe5
feat(core): Migration to distinguish published vs draft workflow index entries (no-changelog) (#24846) 2026-01-26 12:15:27 +00:00
Artem Sorokin
851a193e8a
ci: Add merge-release-tag-to-master job with dedicated GitHub App (#24758) 2026-01-26 11:56:06 +00:00
Charlie Kolb
83181d7eec
chore(core): Add telemetry to workflow history compaction (#24771)
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
2026-01-26 11:45:31 +00:00
Eugene
b1dab743bb
fix: Disable usage of IMAP trigger as a tool (#24854) 2026-01-26 11:38:27 +00:00
Jaakko Husso
16fc8fd6e1
feat(core): Add new landing page on Chat hub for first time users (#24730)
Co-authored-by: autologie <suguru@n8n.io>
2026-01-26 11:34:26 +00:00
Artem Sorokin
2dabbd6e58
ci: Build image once for e2e shards (#24512) 2026-01-26 11:18:01 +00:00
Suguru Inoue
ed1f8041fb
fix(editor): Adjust ChatHub sidebar spacing to match main n8n sidebar (no-changelog) (#24863) 2026-01-26 11:06:05 +00:00
Nikhil Kuriakose
f6ebc2dcc1
feat(editor): New operations in the Slack node (#24643)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-01-26 10:58:07 +00:00
RomanDavydchuk
0b1bf967eb
fix(Eventbrite Trigger Node): Validate received URL (#24677) 2026-01-26 10:55:12 +00:00
Daria
b95949651a
fix(editor): Show publish actions on read-only instances (#24761) 2026-01-26 10:51:49 +00:00
Guillaume Jacquart
78dcc32ae0
feat(editor): Change layout for dynamic credentials section, add tooltip. Add oauth filtering (#24782) 2026-01-26 10:49:13 +00:00
yehorkardash
a9f00ec49b
feat(AI Agent Node): Pass chat input in denial messages (#24748)
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-26 10:41:56 +00:00
James LePage
5143c8bd7e
fix(WooCommerce Node): Update node icon (#20878)
Co-authored-by: Jon <jonathan.bennetts@gmail.com>
2026-01-26 10:26:56 +00:00
Albert Alises
341976947f
feat(ai-builder): Add webhook notifications with HMAC authentication for AI evaluation results (#24766)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-26 10:16:05 +00:00
Csaba Tuncsik
56220709da
fix(editor): Add support for dynamic credentials and credential resolver indicators in UI (#24733) 2026-01-26 09:49:41 +00:00
Jon
5d1eff6a95
fix: Make label optional in TOTP credential (#24795) 2026-01-26 09:45:45 +00:00
Iván Ovejero
28fb1a29d2
ci: Open PR on security fix merge (#24856) 2026-01-26 09:17:15 +00:00
Andreas Fitzek
82b442adcb
chore(core): Integrate ChatHub Extractor (#24533) 2026-01-26 09:15:05 +00:00
yehorkardash
264ce6ffeb
test: HITL for tools tests (#24769)
Co-authored-by: Elias Meire <elias@meire.dev>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-26 08:57:43 +00:00
Benjamin Schroth
986ae4d68c
fix(AI Agent Node): Clarify error message for empty prompt values in define mode (#24774) 2026-01-26 08:12:24 +00:00
yehorkardash
ac5abba4b6
feat(core): Add $tool.name and $tool.parameters expressions (#24783) 2026-01-26 07:31:30 +00:00
Ricardo Espinoza
cb0d2a2a52
fix(core): Add rate limiting to mcp-oauth endpoints (#24734) 2026-01-24 00:08:52 +00:00
Jaakko Husso
60cd62c412
fix(core): Handle null workflowId's on workflow_statistics table at migration (#24800) 2026-01-23 23:57:14 +00:00
Declan Carroll
2f370f4b5f
test: Migrate @n8n/decorators to Vitest (#24737) 2026-01-23 18:59:09 +00:00
Iván Ovejero
122f92b169
ci: Fix security cherrypick workflow (#24687) 2026-01-23 17:39:13 +00:00
chauhan_s
4b268d646d
fix: Increase max items per page from 50 to 100 (#24051)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-01-23 16:49:00 +00:00
James Gee
df818f65ae
feat(core): Add placeholders for external secret provider connections (#24770)
Co-authored-by: Irénée <irenee.ajeneza@n8n.io>
2026-01-23 16:34:27 +00:00
Eugene
f38a59db7c
fix(ai-builder): Responder mentions workflow activation (no-changelog) (#24793) 2026-01-23 15:30:46 +00:00
Guillaume Jacquart
40b8c9413b
chore(core): Log streaming refactor, test and documentation (#24764) 2026-01-23 15:07:59 +00:00
Guillaume Jacquart
c608a19e57
fix(core): Remove wrongly pushed ldap server test files (#24789) 2026-01-23 15:06:05 +00:00
Michael Drury
66cf563fcd
fix(ai-builder): Ask/Build coachmark appearing as chat panel slides out (no-changelog) (#24788) 2026-01-23 15:03:10 +00:00
Albert Alises
4aaea8c26c
feat(editor): Unify credential issues into single card in AI builder (#24781) 2026-01-23 14:56:53 +00:00
Jon
e3c056044b
feat: Add support for custom scopes in the MS Excel credential (#24756) 2026-01-23 14:48:38 +00:00
Jon
423844ba0b
feat: Add support for custom scopes in the MS Teams credential (#24755) 2026-01-23 14:48:10 +00:00
Iván Ovejero
e10138bad1
perf(core): Make source control push deletions async (#24784) 2026-01-23 14:30:42 +00:00
Ricardo Espinoza
f4406c26d2
fix(core): Check license when updating scopes (no-changelog) (#24394)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-23 13:38:21 +00:00
Andreas Fitzek
29c90fbe9c
chore(core): Adopt UI/UX for user identifier and fix parsing for hook definitions (#24779) 2026-01-23 13:34:48 +00:00
Nikhil Kuriakose
a1de45ed9b
fix(editor): Include autonamed nodes with numbers in the end (#24720) 2026-01-23 13:28:19 +00:00
Ricardo Espinoza
0b316d8eb2
fix(core): Handle JSON parsing errors gracefully in ActivateExecuteWorkflowTriggerWorkflows migration (#24410) 2026-01-23 13:16:35 +00:00
Suguru Inoue
b59d6bb6b2
fix(editor): AI response text in ChatHub not selectable while responding (#24712) 2026-01-23 12:44:41 +00:00
RomanDavydchuk
c09267327d
fix(Chat Node): Correct descriptions, aliases, UX improvements (#24619) 2026-01-23 12:01:37 +00:00
Eugene
3f77bf5880
feat(ai-builder): Add RLC options fetch tool for configurator sub-agent (#24589) 2026-01-23 11:42:13 +00:00
Charlie Kolb
467d8f90c5
fix(core): Merge additive nested parameters in workflow history optimization (#24717) 2026-01-23 10:53:15 +00:00
Irénée
6ae470e4d9
chore: Add ExternalSecretProvider entity (#24551)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 10:37:02 +00:00
Romeo Balta
03ae5b6b7b
fix(editor): Update ready to run CTA (#24757) 2026-01-23 10:26:51 +00:00
Stephen Wright
8e58a039fc
feat: Add telemetry for dynamic credential changes (#24750) 2026-01-23 10:24:39 +00:00
Robert Squires
f76ac6f15e
feat(editor): Add unpublish to workflow list (#23228) 2026-01-23 10:17:34 +00:00
Svetoslav Dekov
3147b0b9ec
fix(editor): Tweak wf template cards (no-changelog) (#24731) 2026-01-23 10:16:05 +00:00
Declan Carroll
51142fb402
test: Refactor sharing spec tests to break up isolation (#24359)
Co-authored-by: Claude <claude@anthropic.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-23 10:12:21 +00:00
Elias Meire
ab2c8b56ab
feat(core): Generate HITL tool nodes for sendAndWait operations (#22315)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-23 10:04:11 +00:00
Filipe Tavares
0cead069d1
chore(editor): Cleanup upgrade CTA experiment (no-changelog) (#24728)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 09:52:10 +00:00
Guillaume Jacquart
6ccffed46d
chore(core): Extract ldap into module, and introduce auth handler for registering it (#24494) 2026-01-23 09:39:52 +00:00
Albert Alises
09222733e1
feat(ai-builder): Add webhook notifications for AI evaluation results (#24653) 2026-01-23 09:39:04 +00:00
Declan Carroll
7d233b2f58
feat: Centralizes debounce timing constants (#24710) 2026-01-23 09:35:22 +00:00
Stephen Wright
c5a8355dc7
feat: When adding an instance owner / admin to a project, they should default to project admin (#24723) 2026-01-23 09:30:37 +00:00
Irénée
dc8383ee76
chore: Add secrets provider api contracts (#24718) 2026-01-23 09:19:59 +00:00
Alex Grozav
a05d606b6b
feat(editor): Make expression resolution async (#24249)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-23 09:05:26 +00:00
Elias Meire
9b19b4380c
fix(editor): Fix assignment component spacing (#24592) 2026-01-23 08:43:57 +00:00
Svetoslav Dekov
eb4f2bcae7
feat(editor): Update template detail UX (no-changelog) (#24402) 2026-01-23 08:20:27 +00:00
RomanDavydchuk
0c120174b4
fix(Git Node): Clean up URLs returned from config (#24713) 2026-01-23 08:16:04 +00:00
Michael Kret
58bbb8a473
feat(Kafka Trigger Node): Additional options for batch processing (#24596) 2026-01-23 08:12:43 +00:00
Andreas Fitzek
ccac24b0de
chore(core): Remove gracefull error handling for http header extractor (#24714) 2026-01-22 17:42:13 +00:00
mfsiega
94ff4effa4
fix(core): Reconcile remote and local state for leader election (#24722) 2026-01-22 16:29:17 +00:00
Mutasem Aldmour
d513f1ca3f
fix(AI Agent Node): Fix gemini 3 thought signature handling on Vertex AI (#24473)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Benjamin Schroth <benjamin@n8n.io>
2026-01-22 16:21:46 +00:00
Filipe Tavares
4dedbdde4e
chore(API): Adds jitter middleware and swallow forgot password errors to prevent user enumeration (no-changelog) (#24553)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 16:11:02 +00:00
Michael Drury
3e13296059
docs: Add Claude Code guidance for workflow traversal and prompt building (no-changelog) (#24708) 2026-01-22 16:01:28 +00:00
phyllis-noester
a5e5ea044c
feat: Dynamic creds workflow fails if no dynamic creds exist (#24660) 2026-01-22 15:52:34 +00:00
Andreas Fitzek
da42ca6fd4
chore(core): Remove allow failure toggle for context extractor (#24679) 2026-01-22 15:40:26 +00:00
Stephen Wright
bdb035c9d8
feat: Make default none for auth'd domains on domain aware credentials (#24702) 2026-01-22 15:39:40 +00:00
Charlie Kolb
d9cc9592c4
feat(core): Reduce optimizingMinimumAgeHours in Workflow History Compaction from 3 hours to 15min (#24709) 2026-01-22 15:35:36 +00:00
Declan Carroll
a588facc4a
test: Add Kafka test container (#24116) 2026-01-22 14:47:53 +00:00
Tomi Turtiainen
6d9ee3a1ef
fix(core): Fix concurrency control not releasing capacity if execution continuation fails (#24396) 2026-01-22 14:24:09 +00:00
Michael Drury
6f2c1efc2f
feat(ai-builder): Providing instructions from workflow builder on creation of data tables (#24595) 2026-01-22 14:23:11 +00:00
Michael Kret
8fc88bca5a
fix: Validate attachments url (#24683) 2026-01-22 14:15:06 +00:00
Charlie Kolb
d1328aae76
feat(core): Improve Workflow History Compaction additive merging (no-changelog) (#24700) 2026-01-22 13:46:20 +00:00
Iván Ovejero
5d481988a9
perf(core): Lazyload login strategies and external secrets (#24693) 2026-01-22 13:43:57 +00:00
Declan Carroll
eed218e1a9
build: Remove tsup from nodes-langchain to unblock Vitest migration (no-changelog) (#24670) 2026-01-22 11:59:21 +00:00
Svetoslav Dekov
add046aa2c
feat(editor): Rework recommended templates UX (no-changelog) (#24294) 2026-01-22 11:19:05 +00:00
Albert Alises
a6e8afeee7
feat(ai-builder): Remove techniques selection limit of 5 (#24530) 2026-01-22 11:07:47 +00:00
Rob Hough
1d2a32dda0
feat(editor): Add new Button component to design system (no-changleog) (#24467) 2026-01-22 10:51:27 +00:00
Guillaume Jacquart
c223f8cba7
feat(core): Check if dynamic credentials auth token is set, return 400 otherwise (#24647) 2026-01-22 10:12:27 +00:00
Iván Ovejero
efc6c123c8
Merge commit from fork
* refactor(core): Improve expressions handling

* refactor(core): More expressions handling improvements
2026-01-22 12:40:09 +02:00
Filipe Tavares
650fd00b11
chore(editor): Trial indicator shows days, hours and minutes left (no-changelog) (#24629) 2026-01-22 10:10:05 +00:00
Tomi Turtiainen
8e0de0be02
feat(core): Add limits to fields used for rate limiter keys (#24665) 2026-01-22 10:09:20 +00:00
James Gee
ee1a77cd46
fix(core): Workflow tag removal syncing (#24557) 2026-01-22 09:44:59 +00:00
Mutasem Aldmour
b21c53677c
feat: Add workflow demo diff view (#24585)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 09:18:21 +00:00
RomanDavydchuk
ac47bcb9a2
fix(core): Remove duplicate Resource Mapper Component fields (#24432) 2026-01-22 09:13:50 +00:00
Antonio Piazza
b7c6d54523
feat(Microsoft Teams Node): Add support for government cloud tenants (#17297)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: RomanDavydchuk <roman.d@radency.com>
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-01-22 09:10:52 +00:00
Charlie Kolb
4456bf3c9a
refactor(core): Move workflow history compaction logs to debug (#24680) 2026-01-22 09:06:02 +00:00
Loganaden Velvindron
0aeb4a25e2
fix: Update nodejs to fix CVE-2025-59466 (#24352) 2026-01-22 07:04:18 +00:00
Jaakko Husso
cb07d6b0be
fix(core): Make Respond to Chat nodes work on Chat hub with multi-main instances (#24657) 2026-01-21 22:05:09 +00:00
Iván Ovejero
d2e410a244
ci: Authenticate before syncing to private repo (#24656) 2026-01-21 16:48:40 +00:00
Nikhil Kuriakose
1894aaf49b
fix(editor): Layout changes to the input triple (#24527) 2026-01-21 16:19:49 +00:00
Nikhil Kuriakose
4e7710e15c
fix(editor): Always connect start node to trigger node (#24531) 2026-01-21 16:19:35 +00:00
Charlie Kolb
98079c9245
fix(Data Table Node): Require condition for upsert (#24640) 2026-01-21 16:02:18 +00:00
Albert Alises
99cb5982a0
ci(core): Add automated AI workflow builder evaluations (#24582) 2026-01-21 15:30:45 +00:00
Stephen Wright
8864bc5136
feat: Remove stub resolver for dynamic credentials (#24637) 2026-01-21 14:22:35 +00:00
Tomi Turtiainen
b73e767fe3
chore: Add claude settings (#24638) 2026-01-21 14:20:32 +00:00
Tomi Turtiainen
d9862bb4aa
feat(core): Implement two-layered rate limiting system (#24636) 2026-01-21 14:02:05 +00:00
Romeo Balta
06dfc3b6fe
feat(editor): Resource center experiment (no-changelog) (#24510) 2026-01-21 13:39:30 +00:00
Dimitri Lavrenük
8e6d7f45a2
fix: Move webhook duplication checks to backend and make them more reliable (#23094)
Co-authored-by: Michael Siega <michael.siega@n8n.io>
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-21 10:49:20 +00:00
Raúl Gómez Morales
b28c29accd
chore: Add provider-agnostic CRDT abstraction layer (#24458) 2026-01-21 10:25:58 +00:00
Iván Ovejero
ea2e13ad0c
feat(core): Implement execution data stores (#24568) 2026-01-21 10:04:10 +00:00
Michael Kret
cd489fe4bd
fix(n8n Form Node): Clarify description parameter (#24580) 2026-01-21 09:59:35 +00:00
Csaba Tuncsik
2289500673
refactor(editor): Replace old N8nTooltip with new Reka UI based tooltip (#22838)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-21 09:58:35 +00:00
Iván Ovejero
470539a4df
fix(core): Prevent dual loading of community packages (#24621) 2026-01-21 09:41:26 +00:00
Alex Grozav
e05d6252a7
feat(editor): Store n8n version in SQLite WASM and reinitialize nodeTypes on change (no-changelog) (#24599)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-21 09:33:00 +00:00
Albert Alises
ec1265fdec
fix(Azure AI Search Node): Add metadata transformation for document insertion (#24623) 2026-01-21 09:27:51 +00:00
Alex Grozav
f1b8622d3d
refactor(editor): Extract useDocumentTitle composable to shared package (no-changelog) (#24462)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-21 09:15:46 +00:00
John Lin
4e4b894958
fix(OpenAI Node): Convert error null to undefined to prevent false retries (#24206) 2026-01-21 08:57:31 +00:00
Filipe Tavares
78a16b7031
fix(editor): Hide AI workflow button when AI credits service is not configured (#24607) 2026-01-20 18:07:14 +00:00
Cesar Sanchez
171eb3ae91
feat(Airtop Node): Add resource locator in the agent node (#23008)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-01-20 17:22:51 +00:00
Guillaume Jacquart
e74e0f907e
chore(core): Add dtos for log streaming controller. Use zod to validate existing destination option types (#24493) 2026-01-20 16:37:49 +00:00
Artem Sorokin
924817d9fd
ci: Add poutine custom rule for unpinned GitHub Actions detection (#24577) 2026-01-20 15:10:04 +00:00
Andreas Fitzek
2b4596eb66
chore(core): Add dynamic credential user storage (#24579) 2026-01-20 14:58:50 +00:00
Mutasem Aldmour
0371bef814
fix(editor): Add limitations section to AI builder responder prompt (#24457)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 14:46:13 +00:00
Charlie Kolb
ae62219165
fix(editor): Correct undo state after adding node inbetween existing nodes (#24093) 2026-01-20 14:21:17 +00:00
Tomi Turtiainen
555f2ed75c Merge tag 'n8n@2.5.0' 2026-01-20 16:08:26 +02:00
n8n-assistant[bot]
e396d6de70
🚀 Release 2.5.0 (#24586)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-01-20 14:33:43 +01:00
phyllis-noester
3a94484042
chore(core): Add static authentication for new API endpoints (#24346) 2026-01-20 13:23:46 +00:00
Alex Grozav
b014357e1f
feat: Add SharedWorker and DataWorker initialization with SQLite WASM support (no-changelog) (#24308)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-20 12:31:51 +00:00
Declan Carroll
502479ccdb
fix: Bump dependencies (#24516) 2026-01-20 12:26:03 +00:00
Declan Carroll
801a9ae696
fix: Skip SafeChain setup on Windows (#24576) 2026-01-20 11:50:44 +00:00
phyllis-noester
595ab253ae
fix(core): Use cache to enable MFA enforcement in multi main setup (#24261) 2026-01-20 11:19:22 +00:00
Artem Sorokin
e657120924
chore(core): Remove Git node bare repos breaking change rule (#24234) 2026-01-20 11:07:49 +00:00
Declan Carroll
4d524021e5
ci: Add Aikido Safechain to setup-nodejs (#24089) 2026-01-20 09:55:08 +00:00
Albert Alises
c7ce61b60b
fix(editor): Adjust line height and vertical placement of icon in notification permission banner (#24549) 2026-01-20 09:09:30 +00:00
Konstantin Tieber
36cf19ec8a
fix(core): Worker status in multi-main only accessible to admin (#24548) 2026-01-20 09:09:10 +00:00
RomanDavydchuk
5cd24a121e
feat(HTTP Request Node): Add option to disallow cross-origin credentials sharing (#24526)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-20 09:01:16 +00:00
Declan Carroll
c38b5b41a3
test: Skip NPS survey test due to timeouts (#24564) 2026-01-20 08:53:14 +00:00
Milorad FIlipović
62afcd815b
feat(core): Improve MCP server telemetry (no-changelog) (#24370) 2026-01-20 07:49:29 +00:00
Svetoslav Dekov
57c271652a
fix(editor): Fix node issue not triggered on node disconnection (#24471) 2026-01-20 07:31:48 +00:00
Declan Carroll
ffd46abdf1
ci: Add cloudflared container for local webhook testing (#24521) 2026-01-19 23:01:28 +00:00
Artem Sorokin
4aa830998d
ci: Split Currents reporting into separate projects (#24559) 2026-01-19 22:52:35 +00:00
Milorad FIlipović
ca0ce6662a
fix(editor): Implement distance threshold for the Draggable component (#24490) 2026-01-19 20:21:54 +00:00
Michael Drury
7bffd18113
feat(ai-builder): Ask mode callout explaining its usage (#24406) 2026-01-19 19:13:07 +00:00
Milorad FIlipović
0f21192bd2
fix(editor): Only open template setup modal on import (#24491) 2026-01-19 18:55:40 +00:00
ByteEVM
08f0d9412c
fix(editor): I18n support for Create a tag label (#20698)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2026-01-19 18:12:42 +00:00
Marc Littlemore
82558a3865
feat: Add security rules for Cubic PR reviews (no-changelog) (#24112) 2026-01-19 17:17:45 +00:00
Irénée
290f616dc1
chore: Add feature flag env var for project-scope external secrets (#24540) 2026-01-19 16:33:46 +00:00
Albert Alises
35f1999b44
feat(ai-builder): Add auto-fix for missing AI node connections + prompt guide (#24519) 2026-01-19 16:22:10 +00:00
Albert Alises
70ef256188
feat(ai-builder): Make credentials validation minor instead of major (#24529) 2026-01-19 16:15:29 +00:00
Declan Carroll
3a2b7a3307
ci: Add container stack telemetry (#24487) 2026-01-19 15:25:18 +00:00
Guillaume Jacquart
62afac3e1c
fix(core): Check user auth identities to know whether or not they can update their profile (#24524) 2026-01-19 14:05:52 +00:00
Stephen Wright
d1647ca64e
feat: Allow editing / deleting project variables if you have the project scope (#24532) 2026-01-19 13:58:46 +00:00
Iván Ovejero
0c2e666b99
refactor(core): Initial setup for execution data management (#24452) 2026-01-19 13:26:39 +00:00
Kaan
5dd15e3543
feat(ChromaDB Node): Add local chromadb support for complete local vector database (#19806)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-19 13:25:56 +00:00
Daria
0bbb6316ff
feat(core): Forbid updating archived workflows (#24528) 2026-01-19 12:36:01 +00:00
Declan Carroll
715a53cfac
fix: Set NODE_PATH for DHI images (#24525) 2026-01-19 12:04:02 +00:00
Alex Grozav
c4e9158116
feat(editor): Add editor-ui storybook support (no-changelog) (#24450)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2026-01-19 11:59:41 +00:00
Alex Grozav
1f52f1b8be
fix(editor): Add debounce to WebSocket disconnect to prevent race conditions (no-changelog) (#24523)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-19 11:36:53 +00:00
Charlie Kolb
f85a23809c
feat(core): Rename workflow history compaction env vars and short term compaction (#24384) 2026-01-19 11:30:12 +00:00
Svetoslav Dekov
7b1e18a678
fix(editor): Handle large values breaking data tables UI grid (#24470) 2026-01-19 09:27:51 +00:00
Iván Ovejero
f72fdc0b14
fix(core): Route both Python options to the native Python runner (#24511) 2026-01-19 09:23:36 +00:00
Declan Carroll
71a6bd2311
fix: Unfork @n8n/vm2 (#24509) 2026-01-19 09:11:24 +00:00
Charlie Kolb
b7ea4109ce
feat(core): Introduce long term workflow history trimming (#24382) 2026-01-19 09:02:20 +00:00
Abdul Tawab
da868e36ad
fix(core): Support dots in usernames to connect to git repository in environments (#24481) 2026-01-19 08:57:29 +00:00
Svetoslav Dekov
185b766807
fix(editor): Tweak publish tooltips for migrated workflows (no-changes) (#24296) 2026-01-19 08:37:53 +00:00
Declan Carroll
a5865b4a0c
docs: Update playwright readme docs (#24478) 2026-01-19 07:48:21 +00:00
Andreas Fitzek
cef2edc172
chore(core): Fix static credential oauth refresh of resolvable credentials (#23471) 2026-01-19 07:36:27 +00:00
Andreas Fitzek
a8bbceda8e
chore(core): Add ChatHub extractor for dynamic credential integration (#24463) 2026-01-19 07:12:13 +00:00
oleg
9686582dd4
feat(ai-builder): Improve scheduling workflows generation (#24407)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-18 17:02:24 +00:00
Iván Ovejero
b45d1f9c46
fix(core): Fix command registration in modules (#24469)
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-17 10:41:03 +00:00
Daria
f0f4f37030
feat(editor): Autosave - Implement exponential backoff (#24464) 2026-01-16 17:16:48 +00:00
RomanDavydchuk
4b0f4724b2
fix(MCP Client Node): Make connection errors more clear (#24398)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-16 16:15:17 +00:00
Svetoslav Dekov
51140d07ca
fix(editor): Improve command bar loading state (#24441) 2026-01-16 15:23:19 +00:00
Declan Carroll
d77d8d9e8b
test: Fix flaky workflow tests, skip log streaming tests for community (#24459) 2026-01-16 14:48:41 +00:00
Iván Ovejero
f535ef5164
refactor(core): Add config settings for storage mode and storage path (#24443) 2026-01-16 14:06:41 +00:00
Jon
37b76f9fa1
fix: Fix issue preventing some community nodes from installing (#24448) 2026-01-16 13:53:41 +00:00
Iván Ovejero
3d90c72863
perf(core): Disable data tables cleanup checks on workers (#24444) 2026-01-16 13:19:05 +00:00
Iván Ovejero
c29e22ecc0 Merge commit from fork 2026-01-16 15:35:20 +02:00
Jaakko Husso
58a5e3e910
fix(editor): Handle publishing conflict in webhook path at inaccessible workflow (#24327) 2026-01-16 13:17:23 +00:00
Mutasem Aldmour
0c721c3a36
fix(editor): Clear AI Builder chat when switching workflows (#24401)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 12:57:20 +00:00
Tomi Turtiainen
91fd383f32
refactor(core): Remove legacy sqlite driver code paths (#24376)
Co-authored-by: Danny Martini <danny@n8n.io>
2026-01-16 12:54:43 +00:00
Iván Ovejero
a49cbe83b3
refactor(core): Truncate oversized telemetry payloads (#24319) 2026-01-16 12:51:10 +00:00
Iván Ovejero
d7e5fea075
perf(core): Disable unused modules on workers (#24449) 2026-01-16 12:34:22 +00:00
Iván Ovejero
4140629852
ci: GH actions for private fork (#24338) 2026-01-16 12:33:56 +00:00
RomanDavydchuk
0450be0287
feat(Chat Node): Regroup actions and add different response types (#23028)
Co-authored-by: Shireen Missi <shireen@n8n.io>
2026-01-16 11:48:56 +00:00
Iván Ovejero
d4140f5744
chore(core): Update comments runner envs (#24437) 2026-01-16 11:45:20 +00:00
Charlie Kolb
1c578d94b1
feat(core): Add new workflow grouping rules for size-adjusted time based trimming (no-changelog) (#24237) 2026-01-16 11:17:46 +00:00
Declan Carroll
dec169ac33
test: Improve log streaming test reliability for community (#24439) 2026-01-16 11:16:24 +00:00
Marc Littlemore
6a1bdd2950
fix(core): Improve SSH host key verification for source control (#24408) 2026-01-16 10:57:17 +00:00
Tomi Turtiainen
a7556bd7b8
chore(core): Add support for index where clauses (#24438) 2026-01-16 10:55:39 +00:00
Iván Ovejero
2faf89acce
refactor(core): Add storedAt column to execution_entity table (#24440) 2026-01-16 10:53:22 +00:00
Daria
2ca84042ec
feat(editor): Add a clarifying callout to Merge Node schema view (#24435) 2026-01-16 10:48:50 +00:00
Declan Carroll
c589da70e6
fix: Implements SLSA L3 provenance and VEX attestation (#24411) 2026-01-16 09:36:32 +00:00
Nikhil Kuriakose
4e28e01ba0
feat(editor): Notify users on first prod error (#21764) 2026-01-16 09:30:43 +00:00
Michael Kret
3aa8535d63
fix(Kafka Trigger Node): Logs and better errors handling, rebalance timeout option (#24375)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-16 09:21:56 +00:00
Albert Alises
d237e4278e
feat(ai-builder): Add rename_node tool to AI workflow builder (no-changelog) (#24348) 2026-01-16 09:02:46 +00:00
Mutasem Aldmour
a7e032c454
fix(core): Add LangSmith tracing metadata for V3 ToolsAgent (#24314)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 08:43:34 +00:00
Michael Kret
60f769795a
fix(Todoist Node): API migrating to v1 (#24240)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-01-16 08:01:45 +00:00
Mutasem Aldmour
928a35fcdd
fix(editor): Prevent duplicate field_focus_placeholder_in_ndv telemetry event (#24383)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-16 07:05:04 +00:00
Raúl Gómez Morales
423b1146d3
refactor(editor): Replace N8nCheckbox and ElCheckbox with N8nCheckbox2 (and rename) for consistency and improved functionality across components (#23338)
Co-authored-by: Csaba Tuncsik <csaba.tuncsik@gmail.com>
Co-authored-by: Csaba Tuncsik <csaba@n8n.io>
2026-01-15 21:10:56 +00:00
Mutasem Aldmour
fa040d33f3
test(editor): Fix flaky chat session ID reset E2E test (#24393)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-15 15:52:58 +00:00
Jaakko Husso
ac69fe5f49
fix(core): Increase the model column length from 64 to 256 (#24332) 2026-01-15 15:37:23 +00:00
Guillaume Jacquart
26857f2240
chore(editor): Remove the insights banner warning on queue mode (#24392) 2026-01-15 15:34:58 +00:00
Tomi Turtiainen
956757ad57
chore: Log when execution is cancelled (#24373) 2026-01-15 14:54:28 +00:00
Shireen Missi
aae8db456d
fix(Microsoft Teams Node): Modify Microsoft Teams node default scopes (#23725) 2026-01-15 14:40:36 +00:00
Michael Drury
59587adac8
feat(ai-builder): Add node recommendations for AI content generation (#24267) 2026-01-15 13:24:34 +00:00
Svetoslav Dekov
c3375816d3
fix(editor): Hold autosave when new template is imported until the user makes a change/run the workflow (#24334) 2026-01-15 13:23:01 +00:00
Guillaume Jacquart
5262773683
chore(core): Create sso-saml module and move all saml related files to module (#24304) 2026-01-15 13:18:00 +00:00
Daria
6252dd8f61
fix(core): Allow resetting Error Workflow settings to default (#24299) 2026-01-15 13:16:50 +00:00
Declan Carroll
afb33dffb1
test: Adds export and debugging features for e2e (#24377) 2026-01-15 13:16:27 +00:00
Dawid Myslak
0e19f9c409
fix(core): Fix for execution history when flow includes wait node (#23146)
Co-authored-by: Declan Carroll <declan@n8n.io>
2026-01-15 13:11:04 +00:00
Dawid Myslak
64c9148e1d
feat(GitHub Trigger Node): Add automatic webhook signature verification (#24203) 2026-01-15 13:05:46 +00:00
oleg
448522142c
feat(ai-builder): Add per-stage model configuration for evaluations (no-changelog) (#24344)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-15 12:58:49 +00:00
Michael Drury
3f225cafca
fix(ai-builder): Clarify with spec eval judge node type potential mis-matches (no-changelog) (#24345) 2026-01-15 12:35:45 +00:00
Albert Alises
a44d4b1952
feat(LmChatOpenAi Node): Update default model to gpt-5-mini (#24342) 2026-01-15 11:32:35 +00:00
Artem Sorokin
4df41dff6e
refactor(core): Remove DB_SQLITE_ENABLE_WAL config (#24233) 2026-01-15 11:07:32 +00:00
oleg
7c54ad36a2
feat(ai-builder): Fitlter resource/operation in node-type definitions (#24078)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-15 11:01:16 +00:00
Declan Carroll
2c9b54f80a
test: Improve log ordering for e2e tests (#24368) 2026-01-15 10:08:44 +00:00
Csaba Tuncsik
ca0cddb0a0
fix(editor): Update EULA acceptance modal and success messages for license activation (#23325) 2026-01-15 09:54:35 +00:00
Csaba Tuncsik
3d71a6d9d9
feat(core): Add user email parameter when activating EULA license (#23350)
Co-authored-by: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-01-15 09:54:26 +00:00
Declan Carroll
5567b91f6c
fix: Update urllib3 to 2.6.3 in task runner (#24325)
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-15 09:19:13 +00:00
Guillaume Jacquart
275ff4fa01
chore(core): Extract log streaming log streaming standalone handling of destinations (#24197) 2026-01-15 09:09:13 +00:00
Rob Hough
9ae9047dd7
fix: Remove hover styles on focused Input (no-changelog) (#24219) 2026-01-15 08:55:15 +00:00
Albert Alises
f6b0ff5f3e
fix(core): Add configurable HTTP timeout for AI nodes to prevent UND_ERR_HEADERS_TIMEOUT errors (#24292) 2026-01-15 08:38:39 +00:00
Michael Drury
ca80b3608e
fix(ai-builder): Disabling flaky E2E workflow builder test (#24341) 2026-01-15 08:37:31 +00:00
yehorkardash
3e127884d7
fix(core): Preserve source overwrite in chained tool calls (#24226) 2026-01-15 07:59:34 +00:00
Declan Carroll
81daa290ca
fix: Update base image node version (#24357) 2026-01-14 23:03:20 +00:00
Andreas Fitzek
ee9c1d77da
chore(core): Introduce CORS settings for dynamic credential interface (#24324) 2026-01-14 17:17:58 +00:00
Sandra Zollner
159c110a18
feat(editor): Use number input component for time saved setting (#24331) 2026-01-14 16:40:55 +00:00
Mutasem Aldmour
eb27530c43
fix(editor): Remove duplicate error toasts in ready-to-run workflow (#24335)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 16:04:31 +00:00
Guillaume Jacquart
4aa9399c3d
fix(core): Fix workflow statistics constraint (#22620) 2026-01-14 16:00:03 +00:00
Guillaume Jacquart
50ee22fb67
chore(core): Move all event bus destination code to dedicated module (#24117) 2026-01-14 15:35:06 +00:00
aikido-autofix[bot]
bad85bbe61
fix: Fix security issue in @rudderstack/rudder-sdk-node via major version upgrade from 2.1.4 to 3.0.0 (#24303)
Co-authored-by: aikido-autofix[bot] <119856028+aikido-autofix[bot]@users.noreply.github.com>
Co-authored-by: Nikhil Kuriakose <nikhil.kuriakose@n8n.io>
2026-01-14 15:22:06 +00:00
Mutasem Aldmour
959c5d251d
chore: Add Claude Code skill for creating PRs (#24315)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-14 15:12:01 +00:00
Konstantin Tieber
06f8dbcb21
fix(core): Publish indicator not shown when lacking publish scope (no-changelog) (#24266) 2026-01-14 14:48:15 +00:00
Albert Alises
5ba0bf78c1
feat(editor): Add native browser notifications on AI workflow builder completion or waiting for input (#24224) 2026-01-14 13:23:54 +00:00
yehorkardash
bd111bfff0
feat(editor): Show tooltips for canvas edge buttons (#24311) 2026-01-14 13:13:33 +00:00
Mutasem Aldmour
5a4954f9ae
fix(LmChatOpenAi Node): Fix tool calling with responses api against OpenAI-compatible backends (#24264) 2026-01-14 13:11:19 +00:00
Declan Carroll
307b851de4
test: Add e2e test template and improve agents.md (#24275) 2026-01-14 13:04:10 +00:00
Albert Alises
206b3f3c97
fix(ai-builder): Add guidance for referencing Webhook and AI Agent output (#24301) 2026-01-14 12:59:55 +00:00
Eugene
f56bd1bd49
feat(ai-builder): Fix AI builder prompt inconsistency about the Loop node (#24300) 2026-01-14 12:38:49 +00:00
Konstantin Tieber
fc6d7256e2
chore(core): Exclude storybook package from test commands (no-changelog) (#24248) 2026-01-14 12:18:11 +00:00
Charlie Kolb
4526ac305e
chore: Update cron package (#24170) 2026-01-14 12:05:29 +00:00
Declan Carroll
932995c0d9
ci: Add memory stablization checks (#24276) 2026-01-14 11:48:42 +00:00
oleg
fb5392cdd4
fix(ai-builder): Use LangSmith SDK defaults for batch settings (no-changelog) (#24305) 2026-01-14 11:29:55 +00:00
Mutasem Aldmour
bfb11c0e2a
fix(editor): Send builder telemetry event when session is loaded (#24297) 2026-01-14 10:53:37 +00:00
Michael Kret
d2a0e860dc
fix: Form trigger and Wait Form mode basic authentication fix for form POST request (#23795)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2026-01-14 10:33:17 +00:00
Dawid Myslak
680f264731
fix(Form Node): Preserve CSS child combinator selectors in custom styling (#24106)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-14 10:00:07 +00:00
Guillaume Jacquart
c6eb487518
chore(core): Extract oidc controller and service into independent module (#24211) 2026-01-14 08:59:01 +00:00
Michael Kret
2e29bbe540
feat: Update Posthog key name for execution logic v2 (#24288) 2026-01-14 08:56:43 +00:00
Dimitri Lavrenük
389f9c463f
fix(McpClientTool Node): Filter out tool arguments unless explicitly allowed (#24263) 2026-01-14 08:49:02 +00:00
oleg
734bed4f84
fix(ai-builder): Remove pairwise multi-gen evals and improve logs (no-changelog) (#24270)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-14 08:44:09 +00:00
Elias Meire
503f29901c
fix: Harden Git node parameter handling (#24241)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-14 08:12:56 +00:00
Mutasem Aldmour
4bb3552d8a
fix(editor): Hover main header tabs above evaluation page (#24265) 2026-01-14 08:09:05 +00:00
Albert Alises
8e040f2649
feat(editor): Add user_message_id to AI assistant feedback telemetry (#24279) 2026-01-14 07:48:51 +00:00
Mutasem Aldmour
b7bebf9f1d
fix(ai-builder): Fix dirty state for nodes when importing workflows (#24165) 2026-01-14 07:45:09 +00:00
n8n-assistant[bot]
cacdf6d0c7
chore: Claude automated task (run 20964250419) (#24259)
Co-authored-by: Declan Carroll <7861842+shortstacked@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 19:23:12 +00:00
mfsiega
535caf45da
fix(core): Insert a workflow index placeholder for workflows with no dependencies (#24190) 2026-01-13 18:59:40 +00:00
Iván Ovejero
33ce28744e
chore: Skip notify CI job outside main repo (#24257) 2026-01-13 16:20:29 +00:00
Stephen Wright
7d2e846d7e
feat: Add revokeUrl to status endpoint (#24253) 2026-01-13 16:12:18 +00:00
Andreas Fitzek
bf7cd98e25
chore(core): Implement revoke endpoint for dynamic credentials (#24230) 2026-01-13 15:23:41 +00:00
Declan Carroll
038a5ce17e
ci: Claude task runner cleanup (#24243) 2026-01-13 14:38:05 +00:00
Michael Drury
ea6e7425de
fix(ai-builder): Correctly connect Mermaid sub-graphs (#24195) 2026-01-13 14:36:42 +00:00
n8n-assistant[bot]
0b76892781
chore: Claude automated task (run 20959688286) (#24245)
Co-authored-by: Declan Carroll <7861842+shortstacked@users.noreply.github.com>
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-13 14:31:56 +00:00
Stephen Wright
934bd9ab6f
feat: Allow skipping migration checks for imports (#24229) 2026-01-13 14:23:49 +00:00
Iván Ovejero
63c2f82741
refactor(core): Normalize exception attribute access in Python task runner (#24216) 2026-01-13 14:22:33 +00:00
Michael Drury
71ca931188
fix(ai-builder): Long running prompts throw internal 401 error rather than expected complexity error (#24114) 2026-01-13 13:27:40 +00:00
phyllis-noester
8eb5e756d2
fix(core): Put source control preferences behind auth (#24113) 2026-01-13 12:30:24 +00:00
Konstantin Tieber
c923c8a85c
chore(core): Update turbo and use new config to exclude storybook from build (#24222) 2026-01-13 12:23:14 +00:00
oleg
f880a74d99
refactor(ai-builder): Implement unified evaluations harness (#23955)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-13 12:11:13 +00:00
Jason Schell
800075a693
feat(Data Table Node): Add Order By feature (#23677) 2026-01-13 12:10:15 +00:00
Dimitri Lavrenük
a19347a6bc
fix: Regenerate form webhook ids when pasting workflow data (#24192) 2026-01-13 11:56:48 +00:00
Daria
0c8b59a3f3
fix: Fix CLI import (#24215) 2026-01-13 11:56:36 +00:00
Elias Meire
053f2ca6c0
fix(editor): Fix parameter path in multipleValues=false fixedCollection (#24217) 2026-01-13 11:35:39 +00:00
Eugene
f140e66159
feat(ai-builder): Prefer ResourceLocator mode "list" for data storage nodes (#24181) 2026-01-13 10:35:40 +00:00
Iván Ovejero
8ccad70c16
perf(core): Reduce baseline memory usage by 33 MB for all instance types (#24107) 2026-01-13 10:34:36 +00:00
Irénée
1d5928762d
fix: Apply source control configuration changes to all multi main instances (#24038) 2026-01-13 10:32:26 +00:00
oleg
3504b982b5
chore(ai-builder): Remove legacy agent and make multi-agent default (no-changelog) (#24076)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-13 10:24:27 +00:00
Declan Carroll
9bd52fab39
ci: Add claude task runner POC (#24179) 2026-01-13 09:58:12 +00:00
Iván Ovejero
9795214836
refactor(core): Improve expressions handling (#24177) 2026-01-13 09:10:27 +00:00
Declan Carroll
30decbba85
feat: Add public API testing to e2e tests (#24194) 2026-01-13 09:03:27 +00:00
mfsiega
fa6ad9ced2
fix(core): Use fsRealpath instead of resolve to get the real path (#24185) 2026-01-13 08:43:07 +00:00
Declan Carroll
30f2b42d5f
ci: Support license cert in E2E tests (#24204) 2026-01-13 07:31:09 +00:00
Iván Ovejero
441f006b35
chore: Ignore codemirror-lang-html test file (#24186) 2026-01-12 17:10:01 +00:00
Jaakko Husso
10165c34a0
feat(core): Add Chat hub support for 'When Last Node Finishes' and 'Using Response Nodes' response modes (#24189) 2026-01-12 16:04:51 +00:00
Sudarshan Soma
783d407195
fix(Oracle DB Node): Resolve SQL compatibility issues and correct outBind generation (#21489)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2026-01-12 15:43:53 +00:00
Sandra Zollner
612947c9b2
fix(editor): Only shift downstream nodes to the right of insertion point (#24052)
Co-authored-by: Artem Sorokin <artem@n8n.io>
2026-01-12 15:04:20 +00:00
Declan Carroll
7be6832775
ci: Change COVERAGE_ENABLED to pass through (#24188) 2026-01-12 14:56:23 +00:00
Declan Carroll
f7a9850b24
ci: Cancel currents run when cancelled in GH (#24180) 2026-01-12 14:28:22 +00:00
Suguru Inoue
8da48f6931
fix(editor): Render sidebar synchronously to avoid layout shift (no-changelog) (#24153) 2026-01-12 14:23:52 +00:00
github-actions[bot]
fd27713cac
chore: Update node popularity data (#24145)
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2026-01-12 13:57:43 +00:00
Irénée
116b245230
fix: Use http proxy for source control git commands (#24104) 2026-01-12 13:49:20 +00:00
Tomi Turtiainen
dd1daaba9b Merge tag 'n8n@2.4.0' 2026-01-12 16:39:49 +02:00
Ricardo Espinoza
6084fc406f
chore: Remove N8N_RUNNERS_ENABLED env variable (no-changelog) (#23885) 2026-01-12 13:38:33 +00:00
n8n-assistant[bot]
d222a6a7ce
🚀 Release 2.4.0 (#24178)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-01-12 13:37:10 +00:00
Michael Kret
0523cc35bc
feat: Binary data merge and expressions simplification (#23270)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-01-12 13:29:36 +00:00
Eugene
755a1f2708
fix(ai-builder): Examples omitted in spec evals (#24171) 2026-01-12 13:20:44 +00:00
Charlie Kolb
5a168dfcae
test: Fix flaky active-executions test (#23871) 2026-01-12 13:19:40 +00:00
Stephen Wright
5cc55af426
feat: Add feature for clearing credentials on resolver update (#24169) 2026-01-12 12:47:45 +00:00
Albert Alises
53cfa35362
feat(ai-builder): Add default values guide for LLM and embedding model configuration (#24098) 2026-01-12 11:07:37 +00:00
Sandra Zollner
129be3c02b
feat(editor): Support hours and days in prune time within workflow history (#24108) 2026-01-12 10:39:09 +00:00
Guillaume Jacquart
5013a46c54
fix(core): Revert auto publish on pull (#24101) 2026-01-12 10:29:28 +00:00
Romeo Balta
fbcdfb99d6
fix(editor): Hide credential modal for r2r workflows (no-changelog) (#24164) 2026-01-12 10:22:07 +00:00
Marcus
7aa5307a80
fix(core): Resolve file path correctly when serving node icons from N8N_CUSTOM_EXTENSIONS (#23029)
Co-authored-by: Roman Davydchuk <roman.davydchuk@n8n.io>
2026-01-12 10:09:53 +00:00
Michael Drury
c8391ac6b8
fix(ai-builder): Reducing confusion in spec evals from double negative don't criteria (#24099) 2026-01-12 09:58:00 +00:00
Guillaume Jacquart
c399e8efbe
fix(core): Connect to external secrets provider before testing (#24135) 2026-01-12 09:47:59 +00:00
mfsiega
1a33fa3541
fix(core): Stronger allowed path enforcement for read/write Node (#23542) 2026-01-12 09:40:51 +00:00
Nikhil Kuriakose
46c91dfaab
feat(API): Update docs to mention publish action (#24003)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-12 09:38:57 +00:00
Svetoslav Dekov
e3d11ad9cc
fix(editor): Fix publish button styles when wf has not trigger (no-changelog) (#24160) 2026-01-12 09:11:39 +00:00
Dimitri Lavrenük
29515c89d5
fix: Update mime-types to fixed version (#23858) 2026-01-12 09:09:38 +00:00
Marc Littlemore
ae1fb77203
feat(core): Add execution source to workflow-executed event (#24058) 2026-01-12 08:59:07 +00:00
Suguru Inoue
6fcf2b74f9
fix(editor): Make code block's copy button in ChatHub follow scroll (#24154) 2026-01-12 08:45:28 +00:00
Elias Meire
a992a45ad0
feat(editor): Overhaul (nested) collection UI (#20951)
Co-authored-by: Dawid Myslak <dawid.myslak@gmail.com>
2026-01-12 08:34:42 +00:00
Suguru Inoue
9a0e1548cf
feat(editor): Improve model selection dropdown in ChatHub (#23612) 2026-01-12 08:11:34 +00:00
Eugene
a19338fe39
fix(ai-builder): Error in Set node parameter instruction and some minor cleanup (no-changelog) (#24081) 2026-01-12 08:05:28 +00:00
Mutasem Aldmour
8ca4f27bfd
fix(editor): Update free AI credits model list to include gpt-5-mini (#24041)
Co-authored-by: Claude <noreply@anthropic.com>
2026-01-12 07:54:12 +00:00
Charlie Kolb
29ab6be235
refactor(core): Clean up workflow history compaction service and related utils (#24043) 2026-01-12 07:44:23 +00:00
Artem Sorokin
dd45dfea3c
docs: Add GitHub Actions workflow documentation (#24109) 2026-01-10 14:25:45 +00:00
Jaakko Husso
dc82d85fb4
fix(core): Cancel chat stream timeout promise after stream ends (no-changelog) (#24079) 2026-01-09 21:41:12 +00:00
Albert Alises
60a18a4deb
fix(lmChatOpenAi Node): Add validation for models requiring Responses API (#24033) 2026-01-09 18:52:52 +00:00
Daria
37aa56e6ff
feat: Autosave workflows (#23036)
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
Co-authored-by: Artem Sorokin <artem@n8n.io>
Co-authored-by: Charlie Kolb <charlie@n8n.io>
Co-authored-by: Declan Carroll <declan@n8n.io>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Svetoslav Dekov <scdekov@users.noreply.github.com>
Co-authored-by: Robert Squires <robtf9@icloud.com>
Co-authored-by: Michael Drury <me@michaeldrury.co.uk>
2026-01-09 18:40:24 +00:00
Michael Drury
e70a3f345d
fix(Simple Memory Node): Don't allow adding simple memory node if instance in queue or multi-main mode (#24083) 2026-01-09 17:03:29 +00:00
Marc Littlemore
588fa50f2a
fix(core): Add license check to LDAP configuration endpoints (#24105) 2026-01-09 16:33:17 +00:00
Stephen Wright
8d1e1eb25e
feat: Add new acceptance API, make UI use correct API for tokens (#24084) 2026-01-09 14:40:37 +00:00
yehorkardash
f73fae6fe7
fix: Escape special characters in queries (#23133)
Co-authored-by: Dimitri Lavrenük <dimitri.lavrenuek@n8n.io>
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-01-09 12:39:13 +00:00
mfsiega
9ce3ac092c
fix(Merge Node): Prevent writing files from merge node sql (no-changelog) (#24082)
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-09 12:05:07 +00:00
oleg
24af748fd3
fix(ai-builder): Call onGenerationSuccess callback in multi-agent workflow (#24086) 2026-01-09 11:51:06 +00:00
Alex Grozav
ef8daaf023
refactor: Separate storybook from design-system (no-changelog) (#23983) 2026-01-09 11:48:20 +00:00
Declan Carroll
77b8c1b317
ci: Change push-release-branch to use app token for checkout/push (#24087) 2026-01-09 11:41:49 +00:00
Dawid Myslak
e0baf48c6a
fix(core): Sanitize filenames for file operations (#23988)
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-09 10:33:04 +00:00
Eugene
733adb6720
feat(ai-builder): Add best practices for triage technique (#24080)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-09 10:05:03 +00:00
Declan Carroll
86c593dc3c
test: Ignore fixme tests in distribution script (#24068) 2026-01-09 09:51:02 +00:00
Albert Alises
4879db8f43
feat(editor): Show building and done status in page title for AI builder (#23987) 2026-01-08 20:43:29 +00:00
Declan Carroll
ea3e156624
test: Rename metrics for clarity, remove failure asserts (#24062) 2026-01-08 19:48:25 +00:00
Jon
2cd5660f37
chore: NODE-4156 - Generate Schema Files (no-changelog) (#23777)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
Co-authored-by: Shireen Missi <shireen@n8n.io>
2026-01-08 16:34:38 +00:00
Svetoslav Dekov
8578f309ec
chore(editor): Cleanup pre-built agents code (no-changelog) (#23876) 2026-01-08 16:12:38 +00:00
Tuukka Kantola
98abeb5319
chore(editor): Tweak restore modal dialog and chat message (no-changelog) (#23975)
Co-authored-by: Jaakko Husso <jaakko@n8n.io>
2026-01-08 15:32:16 +00:00
Suguru Inoue
8fa5aa0a7a
fix(core): Ensure all streaming chunks are processed before deleting ChatHub workflow (#24040) 2026-01-08 15:05:36 +00:00
Konstantin Tieber
e74cba6c56
fix(core): Can't edit existing project role (no-changelog) (#24045) 2026-01-08 15:01:31 +00:00
Eugene
b391ee1c18
feat(ai-builder): Add best practices for notification technique (#24030) 2026-01-08 14:32:16 +00:00
phyllis-noester
d58d3671b1
feat(core): Add log streaming events for external secrets provider (#23990)
Co-authored-by: Marc Littlemore <MarcL@users.noreply.github.com>
2026-01-08 13:40:55 +00:00
Stephen Wright
e0f9381468
feat: Accept invitation to use new JWT for tamper proof invites (#24025) 2026-01-08 13:40:41 +00:00
Declan Carroll
98fe00444a
ci: Update playwright agent docs (#24039) 2026-01-08 13:02:18 +00:00
Marc Littlemore
647a684580
fix(core): Add license check to DELETE variables endpoint (#24028) 2026-01-08 12:53:35 +00:00
Declan Carroll
454c85609f
fix: Bump validator dependency (#24026) 2026-01-08 10:41:42 +00:00
Declan Carroll
bc7ec87a5b
chore: Pin graphicsmagick (#24017) 2026-01-08 09:32:41 +00:00
Stephen Wright
4793610c2c
feat: Use new generated links within the UI and emails if feature is enabled (#23962) 2026-01-08 09:20:47 +00:00
Sandra Zollner
8824beac01
fix(editor): Hide 'Create Folder' button if not applicable (#23981)
Hide the 'Create Folder' button when viewing the 'Shared With You' or 'Overview' page,
as folder creation is not supported on these pages.
2026-01-08 10:01:14 +01:00
Artem Sorokin
5a95837ec5
test: Update distribution metrics for PW orchestration (#23986) 2026-01-08 09:55:14 +01:00
Declan Carroll
e19bc4f694
ci: Update node popularity data and workflow (#24014) 2026-01-08 08:38:26 +00:00
Svetoslav Dekov
aed05b4b86
fix(editor): Fix input type switch when pasting expression (#23535) 2026-01-08 09:12:00 +02:00
Robert Squires
57e4bf2b41
fix(editor): Sidebar bottom section always visible (no-changelog) (#23958) 2026-01-07 16:25:40 +00:00
Mutasem Aldmour
4e6063c91e
feat(ai-builder): Prefer core nodes over code node (#23937)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-07 17:23:53 +01:00
Alex Grozav
f80e6e5a0a
feat(editor): Add support for route layouts (no-changelog) (#23729) 2026-01-07 18:05:13 +02:00
David P
565a428ec4
fix(core): Coerce BinaryDataConfig dbMaxFileSizeSchema to a number (#23927)
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
2026-01-07 16:43:49 +01:00
Suguru Inoue
5234921fc4
fix(core): ChatHub: respond error details from execution (#23732) 2026-01-07 15:34:59 +01:00
Dawid Myslak
014e435319
docs: Update Playwright test command in AGENTS.md (#23974) 2026-01-07 15:24:29 +01:00
Michael Drury
edb844e9c7
chore(ai-builder): Consolidate structured output parser recommendation and guidance prompts (#23978) 2026-01-07 14:19:26 +00:00
Sandra Zollner
09ed1f6869
fix(editor): Fix typo in source control push modal message (#23971) 2026-01-07 15:08:29 +01:00
James Gee
42adee8b05
feat(core): UI changes to support TLS over TCP (#23938)
Co-authored-by: konstantintieber <konstantin.tieber@n8n.io>
2026-01-07 14:39:47 +01:00
Guillaume Jacquart
b68d0ec485
chore(core): Add DTOs for workflow create / update validation (#23935) 2026-01-07 13:50:16 +01:00
Albert Alises
64498cdca8
fix(editor): Make AI assistant tool steps visible during streaming (#23898)
- Steps visible during generation: When the AI assistant is working, users can now see each step (tool calls) as they happen in real-time, rather than having them hidden behind a collapsed section
- Auto-collapse on completion: Once the assistant finishes responding (or the user stops it), the steps automatically collapse to keep the final view clean and focused on the result
- Consistent loading state: The initial "thinking" state now uses the same visual component as the step list, providing a smoother transition as steps appear
- Cleaner copy: Removed trailing ellipsis from status text ("Thinking" instead of "Thinking...", "Processing" instead of "Processing...")
- Smoother transitions: Fixed a visual glitch where "Workflow generated" would briefly flash before the next step appeared
2026-01-07 12:59:50 +01:00
Maxime Pauvert
5076909bce
feat(Mailjet Node): Add Custom Campaign and Deduplicate Campaign Additional Fields (#11715)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-07 13:43:08 +02:00
Jonathan Laliberte
f7e2029917
fix(Box Node): Fix webhook deletion bug that could delete wrong webhooks (#18155)
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-07 13:42:57 +02:00
Dawid Myslak
4f606d7ae4
fix(core): Fix for jumpy UI when using drag/drop to fields in NDV (#23516)
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-07 12:25:40 +01:00
Irénée
699698c5ee
docs: Add source control setup demo to SourceControl module README.md (#23964) 2026-01-07 11:03:46 +00:00
Michael Drury
f98b7bee02
fix(editor): Keep structured output parser error icon in correct position when running (#23930) 2026-01-07 11:00:46 +00:00
Declan Carroll
1ce650a4d0
test: Fixing flaky test (#23961)
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-07 10:45:27 +00:00
Marc Littlemore
2f29603908
feat(core): Add log streaming events for executions (#23372) 2026-01-07 10:24:04 +00:00
Guillaume Jacquart
def0a09d8a
feat(core): First shot in resolving the credential resolver config expressions (#23110) 2026-01-07 11:17:42 +01:00
Suguru Inoue
76f4703728
chore: Fix infinite requests in hosted storybook (#23933) 2026-01-07 10:36:02 +01:00
Irénée
f3115a367a
test: Skip source control flakey tests (#23941) 2026-01-07 08:54:09 +00:00
Stephen Wright
7b74533a14
feat: Add new api for generating invite links (#23929) 2026-01-07 06:52:53 +00:00
James Gee
279d6fd10f
feat(core): Add TLS support to Syslog client (#23304)
Signed-off-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2026-01-06 21:15:02 +01:00
Declan Carroll
bb3d2b668e
fix: Bump versions for qs/langchain (#23939) 2026-01-06 18:01:31 +00:00
Declan Carroll
fa41b40459
feat: Add git commit info to workfolder push (#23903) 2026-01-06 18:01:11 +00:00
Michael Drury
64aed9fb27
chore(ai-builder): Support filtering by do/don't criteria in pairwise evals (#23914) 2026-01-06 16:40:28 +00:00
Artem Sorokin
851f85ae0b
ci: Rename GH workflows for consistent naming (#23904) 2026-01-06 17:27:35 +01:00
Ricardo Espinoza
569695dc67
fix(Data Table Node): Fix issue with insert and update operation (#23936) 2026-01-06 11:24:31 -05:00
Elias Meire
62f3019260
fix: Resolve expressions in custom form HTML fields for HITL nodes (#23922) 2026-01-06 17:19:54 +01:00
Iván Ovejero
182d48d083
Merge commit from fork 2026-01-06 17:19:32 +01:00
Elias Meire
1d37363ced
chore: Move codemirror-lang-html-n8n into monorepo (#23928) 2026-01-06 17:19:23 +01:00
Irénée
9bfb014cb9
refactor: Migrate source control feature to modules (#22453) 2026-01-06 15:59:11 +00:00
Thomas B.
639c09f69a
fix(McpClientTool Node): Sanitize MCP tool arguments based on schema (#23167)
Co-authored-by: Dimitri Lavrenük <20122620+dlavrenuek@users.noreply.github.com>
2026-01-06 16:48:14 +01:00
James Gee
66f8fd63db
(no-changelog) chore: Move trivy alerts to a new channel and push critical only to the current one (#23923)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-06 16:35:48 +01:00
Iván Ovejero
5719a574b5
Merge commit from fork 2026-01-06 16:23:39 +01:00
Ricardo Espinoza
aae0f33743
chore: Remove all mentions of --tunnel (no-changelog) (#23886) 2026-01-06 10:03:13 -05:00
Charlie Kolb
c63cd347e4
refactor(editor): Move more workflow setters to workflowState (#23917) 2026-01-06 15:27:40 +01:00
Ricardo Espinoza
a92bbf0707
chore: Clean up command bar feature flag (no-changelog) (#23830) 2026-01-06 09:12:37 -05:00
Stephen Wright
64c27e5c34
feat: Add feature flag for tamper proof invite links (#23920) 2026-01-06 13:30:42 +00:00
Iván Ovejero
b1c84f7667
chore: Fix lint and typecheck on CI (#23912) 2026-01-06 14:14:16 +01:00
eilonc-pillar
760701c45d
Merge commit from fork 2026-01-06 13:23:20 +01:00
Eugene
c465a49dae
feat(ai-builder): Data persistence technique best practice document (#23852)
Co-authored-by: Michael Drury <me@michaeldrury.co.uk>
Co-authored-by: claude[bot] <209825114+claude[bot]@users.noreply.github.com>
Co-authored-by: Eugene <burivuhster@users.noreply.github.com>
2026-01-06 12:25:28 +01:00
Charlie Kolb
b4eeba8032
fix(core): Avoid copying execution data table on AddWorkflowVersionIdToExecutionData migration (#23901) 2026-01-06 11:15:59 +01:00
Artem Sorokin
e649879c07
ci: Resolve Poutine security scanner findings (#23900) 2026-01-06 11:10:04 +01:00
Guillaume Jacquart
072a1dd825
fix(core): Fix redirection of user missing MFA to personal settings (#23881) 2026-01-06 10:38:30 +01:00
Robert Squires
3cc0552cef
fix(editor): Remove template creator CTA (no-changelog) (#23880) 2026-01-06 08:55:42 +00:00
Svetoslav Dekov
4f059a758f
fix(editor): Fix wf history item display issue (no-changelog) (#23875) 2026-01-06 10:55:07 +02:00
Svetoslav Dekov
27111a7524
chore(editor): Cleanup old workflow activation FE code (no-changelog) (#23857) 2026-01-06 10:36:56 +02:00
Robert Squires
cfd206105c
fix(editor): Data table resource list icon (no-changelog) (#23842) 2026-01-06 08:09:05 +00:00
Dimitri Lavrenük
dc847e7a92
fix: Correctly parse curl command with encoding (#23853)
Co-authored-by: Michael Kret <michael.k@radency.com>
2026-01-06 08:53:34 +01:00
Garrit Franke
1c413ffc67
feat(Git Node): Add reflog action (#21105)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2026-01-05 21:58:31 +00:00
James Gee
79f529c145
fix(core): Bug with incorrect DI in some cases - picked up by enabling linting rule (#23855)
Signed-off-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2026-01-05 21:30:23 +01:00
Guillaume Jacquart
7610a50f49
fix(core): Check if user data changed before calling save on ldap sync (#23796) 2026-01-05 17:13:13 +01:00
Guillaume Jacquart
77cbe50aea
fix(core): Inserts into execution metadata table fail due to fk (#23759) 2026-01-05 17:10:56 +01:00
Cornelius Suermann
19c5c96312
Merge tag 'n8n@2.3.0' 2026-01-05 16:31:55 +01:00
Guillaume Jacquart
14a4b74c62
fix(core): Automatically re-publish workflow with new version on pull (#23859) 2026-01-05 16:29:37 +01:00
Suguru Inoue
495841f591
feat: Allow to set ChatHub workflow agent icon in NDV (#23562) 2026-01-05 16:18:23 +01:00
n8n-assistant[bot]
2b35b1bca3
🚀 Release 2.3.0 (#23866)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2026-01-05 16:57:14 +02:00
Suguru Inoue
a7cd52acf1
refactor(editor): Clean up subWorkflowExecutionError (#23769) 2026-01-05 15:19:00 +01:00
Suguru Inoue
d99a07ef69
fix(editor): Logs not showing tool usage correctly for sub-agents (#23860) 2026-01-05 15:18:47 +01:00
Suguru Inoue
b11369487a
fix(editor): Sub node's input not shown when its root node finished with an error (#23770) 2026-01-05 15:18:18 +01:00
Svetoslav Dekov
42428f50e7
fix(editor): Handle add data table submit with enter and show loading state (no-changelog) (#23538) 2026-01-05 16:10:04 +02:00
Shashwat
23ae22bab2
fix(core): Fix CORS issue in waiting webhook responses (#23697)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
Co-authored-by: Michael Kret <michael.k@radency.com>
Co-authored-by: Michael Kret <88898367+michael-radency@users.noreply.github.com>
2026-01-05 13:47:08 +00:00
Denisf88
e75cf6bc6c
fix(Redis Node): Fix reconnect strategy to prevent infinite reconnect attempts (#22526)
Co-authored-by: Elias Meire <elias@meire.dev>
2026-01-05 14:40:57 +01:00
Guillaume Jacquart
0fe358b4cc
chore(core): Add test to compare insights and workflow statistics (#23739) 2026-01-05 14:36:13 +01:00
Stephen Wright
77890ce287
feat: Workflows imported with separate option now validate before insertion (#23843) 2026-01-05 13:21:50 +00:00
Stephen Wright
77f1dd6cea
feat: Gracefully handle non string values for external secrets redaction (#23849) 2026-01-05 13:18:57 +00:00
Iván Ovejero
ce5a626aa8
chore(core): Streamline runner debugging (#23854) 2026-01-05 14:09:47 +01:00
Svetoslav Dekov
06eef008b3
fix(editor): Fix NDV state getting stale when navigating using the floating buttons (#23717) 2026-01-05 14:41:24 +02:00
Svetoslav Dekov
0bee0a5453
fix(editor): Fix VersionUpdateCTA disabled state (#23722) 2026-01-05 14:39:03 +02:00
Charlie Kolb
bd16e7181c
feat(core): Adjust Workflow Compaction History algorithm (no-changelog) (#23763)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2026-01-05 13:28:30 +01:00
James Gee
02f9d622eb
chore(core): Add linting rule to prevent null DI issues (#23478)
Signed-off-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2026-01-05 13:27:06 +01:00
Mutasem Aldmour
74b552d5bd
feat: Add instance id to ai assistant service client (#23474) 2026-01-05 13:25:38 +01:00
oleg
3775cb1916
fix(AI Agent Node): Normalize toolInput to object for LangChain ToolCall compatibility (no-changelog) (#23850)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-05 12:57:02 +01:00
oleg
daa81a18e8
fix(AI Agent Node): Store AI agent tool calls as native LangChain messages (#23687)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2026-01-05 11:36:14 +01:00
Declan Carroll
ef196fec9a
ci: Change community PR's to single worker (#23846) 2026-01-05 10:26:32 +00:00
Filipe Tavares
7a3f06b9d9
chore(editor): Add chatgpt/llm as a reported source option on the survey (#23484) 2026-01-05 10:17:54 +00:00
Declan Carroll
7200eae2c1
test: Testcontainer refactor (#23703) 2026-01-05 09:54:19 +00:00
Shireen Missi
0edb607c78
feat(Weaviate Node): Hybrid Search Support (#23252)
Co-authored-by: Duda Nogueira <dudanogueira@gmail.com>
2026-01-05 08:58:13 +00:00
Charlie Kolb
5b76f49a89
feat(editor): Add Stop All Executions functionality (#23576) 2026-01-05 08:48:37 +01:00
Benjamin Schroth
3dfe7cdd6e
chore(ai-builder): Add telemetry event on build with ai button (#23794) 2026-01-02 15:50:59 +01:00
Eugene
ec34459e37
chore(ai-builder): Add evaluation run type metadata (#23793) 2026-01-02 15:21:09 +01:00
Charlie Kolb
07d4d2853b
test: Fix year-related test (#23790) 2026-01-02 13:28:28 +01:00
Benjamin Schroth
9329d55c64
fix(ai-builder): Improve handling of max recursion errors (#23606) 2025-12-31 13:46:28 +01:00
Benjamin Schroth
e5c7d434fd
fix(Structured Output Parser Node): Fix parsing of JSON with markdown code segments (#23726) 2025-12-31 13:45:46 +01:00
Benjamin Schroth
ae2e7a8260
fix(AI Agent Node): Fix toolInput field in intermediateSteps output (#23767) 2025-12-31 13:16:31 +01:00
saurabhssonkar
50573e05be
fix(n8n Form Trigger Node): Add support for fieldName in JSON config (#23491)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-31 12:08:52 +00:00
Declan Carroll
2e6b1984c7
ci: Adjusts playwright test shards and command (#23768) 2025-12-31 11:54:32 +00:00
Declan Carroll
da167b712f
ci: Use App token for release (#23761) 2025-12-31 10:33:15 +00:00
Declan Carroll
c7fe2f8ca0
ci: Manual workflow for releases (#23757) 2025-12-31 09:14:42 +00:00
Benjamin Schroth
b59fad7254
fix(editor): Correct hosted chat font family defaults (#23718) 2025-12-30 16:31:51 +01:00
Benjamin Schroth
b6bc146637
fix(editor): Keep focus in canvas chat after sending a message (#23719) 2025-12-30 16:31:45 +01:00
Shireen Missi
35d110fbc7
fix(core): Modify path validation to work cross platforms (#23737) 2025-12-30 15:07:14 +00:00
Irénée
3aeb0402ff
fix: Add data insight metadata migration (#23694) 2025-12-30 15:18:53 +01:00
Suguru Inoue
14a69acd93
chore(editor): Address Vue warnings (#23724) 2025-12-30 12:42:25 +01:00
Declan Carroll
9339d14f6f
fix: Return null if no last successful execution exists instead of 404 (#23720) 2025-12-30 09:36:46 +00:00
yassine belkaid
c96534f9ae
fix(Github Node): Handle binary data in all modes by converting to base64 (#23497)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-30 09:19:47 +00:00
Declan Carroll
430b82309f
feat: Use hardended docker images (#23480) 2025-12-30 08:51:12 +00:00
Eugene
1199904b15
feat(ai-builder): Improve generation across data_transformation category (#23609) 2025-12-29 17:30:16 +01:00
Iván Ovejero
ea889bee89
refactor(core, editor): Remove Pyodide (#23572) 2025-12-29 14:54:15 +01:00
Guillaume Jacquart
750e9a8470
feat(API): Add patch method for credentials public API (#23431) 2025-12-29 14:53:43 +01:00
Iván Ovejero
7131889a6a
refactor(core): Remove flat format for binary data (#23580) 2025-12-29 14:34:48 +01:00
Declan Carroll
30091b19ee
test: Refactor Playwright container capabilities (#23690) 2025-12-29 10:37:15 +00:00
ByteEVM
1dd0fac24e
fix(editor): Add defaultLocale to public settings (#23134) 2025-12-29 09:59:53 +00:00
oleg
fc8b667b4d
fix(editor): Fix chat message action icons visibility in dark mode (#23444) 2025-12-29 10:22:18 +01:00
Ricardo Espinoza
9fc820fbaf
feat(core): Use draft sub-workflow version for manual execution, published for production (#23166) 2025-12-24 09:58:21 -05:00
Declan Carroll
a087d36990
test: Rebalance (#23579) 2025-12-24 10:53:23 +00:00
Charlie Kolb
e9e480bb8e
feat(core): Introduce WorkflowHistory compaction service (#23238)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-24 09:00:58 +01:00
Milorad FIlipović
5b5867fd53
fix(editor): Allow moving workflows on the overview page (#21742)
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2025-12-23 23:16:01 +01:00
Andreas Fitzek
2844064afc
chore(core): Only encrypt partial oauth state (#23590) 2025-12-23 21:00:58 +01:00
Iván Ovejero
3af145ec71
fix(core): Fix race condition in executions pruning on leadership change (#23575) 2025-12-23 15:44:19 +01:00
Ricardo Espinoza
36d5eaf927
feat(Data Table Node): Add data table crud operations to data table node (#22951)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-23 09:32:23 -05:00
Andreas Fitzek
61f9d06c44
chore(core): OAuth2 cloud hook integration (#23574) 2025-12-23 15:03:47 +01:00
Suguru Inoue
33d0c74b0f
feat(editor): Add/remove files in editing ChatHub chat message (#23541) 2025-12-23 15:00:47 +01:00
Dawid Myslak
9892c4e78d
test(Form Node): Add E2E coverage for multi-page form flow (#23558) 2025-12-23 14:31:42 +01:00
Mehrdad
229024ff4e
fix(editor): Remove arbitrary maxlength restriction from data table n… (#23242)
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
Co-authored-by: Ricardo Espinoza <ricardo@n8n.io>
2025-12-23 08:03:28 -05:00
Declan Carroll
d3af24e00a
test: Update test metrics, perf test, source control (#23534) 2025-12-23 12:08:51 +00:00
Suguru Inoue
346cf84671
test: Add more ChatHub e2e tests (#23522) 2025-12-23 12:57:20 +01:00
Declan Carroll
ce2e7221de
ci: Codecov bundle analysis (#23500) 2025-12-23 11:15:07 +00:00
Dawid Myslak
921d3f24db
feat(Form Node): Dynamic attributes in form editor (#23433)
Co-authored-by: Elias Meire <elias@meire.dev>
2025-12-23 11:51:54 +01:00
Jaakko Husso
62d7386f02
refactor(core): Rework how credential access is checked on Chat hub (#23519) 2025-12-23 12:47:02 +02:00
Jaakko Husso
06cd720760
refactor(core): Remove 'beginTransaction' parameter from withTransaction (#23449) 2025-12-23 12:46:33 +02:00
Jaakko Husso
3b9203e9f5
Merge commit from fork 2025-12-23 12:17:13 +02:00
Iván Ovejero
913e5f1215
Merge commit from fork 2025-12-23 11:57:48 +02:00
Iván Ovejero
5f9eb7c2b4
Merge commit from fork 2025-12-23 11:40:46 +02:00
Suguru Inoue
0c0689c266
fix: Remove eval() usage for resolving CSS color (no-changelog) (#23536) 2025-12-23 09:56:17 +01:00
Iván Ovejero
2c0162f88c
refactor(core): Tighten typing for Python runner (#23537) 2025-12-22 22:51:26 +01:00
Dawid Myslak
3e80bdb85a
fix(core): Node feature flags supported in canvas status icon (#23300)
Co-authored-by: Elias Meire <elias@meire.dev>
2025-12-22 20:39:05 +01:00
Tomi Turtiainen
3919879b5e Merge tag 'n8n@2.2.0' 2025-12-22 21:11:59 +02:00
Shireen Missi
f816b39070
fix(Stripe Trigger Node): Add Stripe signature verification (#22764) 2025-12-22 16:36:39 +00:00
Iván Ovejero
c7fed98563
fix(core): Validate missing code param in Code node (#23405) 2025-12-22 17:29:52 +01:00
mfsiega
be7713b684
fix(core): Use Redis prefix everywhere (no-changelog) (#23366) 2025-12-22 17:29:38 +01:00
github-actions[bot]
67e25c890a
🚀 Release 2.2.0 (#23533)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-22 14:57:23 +00:00
Andreas Fitzek
a4206483f0
chore(core): Include workflow:publish for global owner and admin (#23532) 2025-12-22 15:19:40 +01:00
Jaakko Husso
240f10a6ed
fix(core): Fix access control checks for displaying workflow and execution links on Chat hub (#23524) 2025-12-22 15:20:30 +02:00
Declan Carroll
078e060162
ci: Add duration-based test orchestration for Playwright E2E (#23257) 2025-12-22 13:01:22 +00:00
Svetoslav Dekov
ac0c50847f
fix(editor): Fix operator selection in NDV (no-changelog) (#23526) 2025-12-22 14:47:53 +02:00
Irénée
340a12ce84
test: Add source control e2e tests (#23327) 2025-12-22 11:55:52 +01:00
Dimitri Lavrenük
f9715674e4
feat: All requests to OpenAI include a platform header (#23463) 2025-12-22 11:00:47 +01:00
mfsiega
11f8597d4a
fix(Webhook Node): Use CIDR matching for IP whitelist check (#23399) 2025-12-22 10:37:31 +01:00
krisn0x
6ae4999ef9
fix(Microsoft OneDrive Node): Don't overwrite filename from node parameters when uploading binary file (#22949) 2025-12-19 19:05:25 +02:00
Csaba Tuncsik
ed65ef9231
fix(editor): Restore correct node icon colors in nodes panel (#23152)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-19 17:57:45 +01:00
krisn0x
cec256f124
fix(Phantombuster Node): Don't send empty objects in request (#22303)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2025-12-19 18:38:03 +02:00
Dimitri Lavrenük
e0ab5ba45a
fix: Sharepoint file selection correctly applies filter (#23155) 2025-12-19 17:17:07 +01:00
Iván Ovejero
93bb0c5399
fix(core): Ensure runner does not terminate pipe reader prematurely (#23448) 2025-12-19 17:16:17 +01:00
Guillaume Jacquart
35be04f9dd
chore(core): Refactor external secrets (#23337) 2025-12-19 17:05:03 +01:00
Michael Drury
041a39b083
fix(ai-builder): Allow running get-node-examples tool in parallel (#23473) 2025-12-19 15:25:03 +00:00
Mutasem Aldmour
5818d58588
feat(ai-builder): Add support for versioning in ai-builder (#23060) 2025-12-19 15:47:20 +01:00
Mutasem Aldmour
283786917d
fix(editor): Fix placeholder telemetry event triggering too many times (#23454) 2025-12-19 15:27:03 +01:00
Alex Grozav
b8e6e0f455
feat: Provide auto-generated workflow ids in new workflows (no-changelog) (#21955)
Co-authored-by: Danny Martini <danny@n8n.io>
Co-authored-by: Sculptor <sculptor@imbue.com>
Co-authored-by: cubic Bot <contact@cubic.dev>
2025-12-19 16:11:00 +02:00
Milorad FIlipović
0d821f0fa1
feat(editor): Implement new DropdownMenu component (no-changelog) (#22926) 2025-12-19 15:01:42 +01:00
Michael Drury
94dd47b637
feat(ai-builder): Multi-agent workflow builder improvements, best practices and better template usage (#23417) 2025-12-19 14:00:06 +00:00
Jaakko Husso
2868d1bab7
fix(core): Skip saving workflow statistics on 'chat' executions (#23465) 2025-12-19 15:58:18 +02:00
RomanDavydchuk
3aeb247bf2
fix(Postgres Node): Add Continue on Error support for type validation errors in RMC (#23235)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-19 13:01:39 +00:00
Suguru Inoue
d98cc71235
chore: Temporarily skip flakey e2e (#23460) 2025-12-19 13:42:34 +01:00
Michael Kret
bded5f58b2
fix(n8n Form Node): Restores executions status check for waiting forms (#23452) 2025-12-19 11:45:56 +00:00
Jaakko Husso
0611184bee
fix(core): Fix Ollama models support on Chat hub (#23458) 2025-12-19 13:34:16 +02:00
Dimitri Lavrenük
e22acaab3d
fix: Limit access to files based on regex pattern (#23413) 2025-12-19 11:07:29 +00:00
oleg
538181cbe3
fix: Handle nodes with missing type field in ActivateExecuteWorkflowTriggerWorkflows migration (#23392) 2025-12-19 12:04:48 +01:00
Iván Ovejero
6b6b828e96
fix(core): Fix verified community packages reinstall (#23428) 2025-12-19 11:58:48 +01:00
oleg
99f398e46e
fix(editor): Preserve AI Builder chat state when switching routes during streaming (#23442) 2025-12-19 11:29:56 +01:00
Declan Carroll
6468692a44
ci: Add observability stack for containers (#23419) 2025-12-19 10:06:38 +00:00
Jaakko Husso
6b2887c95f
refactor(core): Make Chat db queries faster (#23397) 2025-12-19 12:03:51 +02:00
Marc Littlemore
150d16d410
feat(core): Add log streaming events for variables (#23425) 2025-12-19 09:24:46 +00:00
Irénée
d5c093411a
feat: Assign default project admin on pull (#23355) 2025-12-19 09:04:43 +00:00
Suguru Inoue
8ce21cb39b
test: Add e2e tests for ChatHub (#23396) 2025-12-19 09:05:02 +01:00
Jaakko Husso
5c69d7435c
chore(core): Use interfaces instead of session / agent entities to solve partial deep type issues (#23438) 2025-12-19 09:51:20 +02:00
oleg
da9014faeb
fix(editor): Remove running tool messages when AI builder task fails (#23437) 2025-12-19 08:50:00 +01:00
Artem Sorokin
9380c02a7c
ci: Add Poutine security scanner for GitHub Actions (#23331) 2025-12-18 23:54:42 +01:00
Konstantin Tieber
011c4bba12
feat(core): Add dedicated workflow:publish project scope to use instead of the generic workflow:update (#23289) 2025-12-18 22:07:46 +01:00
Artem Sorokin
7e569ab952
ci: Extract docker-registry-login composite action (#23420) 2025-12-18 21:20:26 +01:00
Tomi Turtiainen
06db448026
chore: Improve filtering of user errors from sentry (#23427) 2025-12-18 21:45:22 +02:00
Artem Sorokin
80ee7b1e2b
test: Rename Playwright project names from ui to e2e (#23423) 2025-12-18 18:51:51 +01:00
Csaba Tuncsik
f700aff583
fix(editor): Prevent Reka UI from interfering with Element Plus dropdown selections (#23370) 2025-12-18 15:56:58 +01:00
Suguru Inoue
04636cc365
fix(editor): Previous message does not exist error when sending chat message (#23298) 2025-12-18 14:58:02 +01:00
Eugene
378a32f3d3
feat(editor): Group sub-node execution errors with same messages inside a tooltip (#23402) 2025-12-18 14:02:00 +01:00
mfsiega
256575745d
feat(core): Add options necessary for AWS elasticache cluster with TLS (#23274) 2025-12-18 12:56:13 +01:00
yehorkardash
3b694a6c79
fix(Basic LLM Chain Node): Support ResponsesApi and OpenAI tools (#22936) 2025-12-18 10:31:10 +01:00
yehorkardash
238a8fe1e0
fix(Guardrails Node): Handle Unicode characters (#21807) 2025-12-18 10:30:25 +01:00
oleg
e861344f5b
fix(core): Preserve AI tool input/output data on execution error (#23292)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-18 07:02:10 +01:00
Charlie Kolb
337d8daa15
feat(core): Add workflowVersionId column to ExecutionData table (no-changelog) (#21926) 2025-12-17 18:03:22 +01:00
Csaba Tuncsik
09566a0dd4
fix(editor): Implement node position checks and overlap detection for canvas operations (#22536)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 17:01:24 +01:00
Andreas Fitzek
906e0c01ad
chore(core): Expose credential name in workflow status (#23344) 2025-12-17 16:42:15 +01:00
Iván Ovejero
794f8e84a6
refactor(core): Remove oversized payloads from logs (#23353) 2025-12-17 16:28:23 +01:00
Jaakko Husso
9bebbab3db
feat(editor): Update Chat sidebar to match v2 styles (#23267) 2025-12-17 17:16:39 +02:00
Andreas Fitzek
44ff6a734f
chore(core): Fixes skipping auth for OAuth callback (#23364) 2025-12-17 15:54:40 +01:00
Declan Carroll
b0c3c39d1f
fix: Extracts data from PDF without memory issues (#23309) 2025-12-17 14:49:47 +00:00
Andreas Fitzek
038e24b523
chore(core): Debug configuration for remote n8n process (#23356) 2025-12-17 14:46:42 +01:00
Stephen Wright
c739d33903
fix: Don't encrypt state for hooks calls (#23357) 2025-12-17 13:39:19 +00:00
Jaakko Husso
804a007377
fix(editor): Select default Chat hub model to use from models allowed by settings (#23348) 2025-12-17 14:43:09 +02:00
Michael Drury
0bd7a94d0c
fix(ai-builder): Connection validation respects node version and type (#23349) 2025-12-17 12:38:22 +00:00
Milorad FIlipović
f5eefcb3ff
chore(editor): Update MCP copies (no-changelog) (#23268) 2025-12-17 12:55:18 +01:00
Irénée
fc2bdd328b
fix: Fix broken route for variables notification toast on pull (#23339)
Co-authored-by: Claude Haiku 4.5 <noreply@anthropic.com>
2025-12-17 10:43:58 +00:00
Csaba Tuncsik
2735ebd8ab
refactor(editor): Replace N8nPopover with N8nPopoverReka (and rename) for consistency and improved functionality across components (#22766)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-17 11:32:43 +01:00
oleg
eb3b77146f
fix(Embeddings OpenAI Node): Validate embedding inputs to prevent undefined errors (#23328)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-17 11:30:04 +01:00
Artem Sorokin
f47ce9421e
ci: Standardize yaml file extensions (#23332) 2025-12-17 11:28:59 +01:00
Svetoslav Dekov
ffbf66e719
fix(editor): Fix wf nodes not updated correctly on workflow activated/deactivated events (#23333) 2025-12-17 12:23:08 +02:00
Declan Carroll
864095bc77
fix: Lint error needs to be hovered not the text (#23310)
Co-authored-by: Artem Sorokin <38620398+seemewalkin@users.noreply.github.com>
2025-12-17 09:33:41 +00:00
Marc Littlemore
ca96ffc804
feat(core): Add log streaming events for 2FA enable/disable (#23302) 2025-12-17 08:58:51 +00:00
Jaakko Husso
1c8e76d9ba
refactor(core): Drop self-referencing entity fields from ChatHubMessage entity to solve deep type instantiation issues (#23291) 2025-12-17 10:25:01 +02:00
Marc Littlemore
4ece6dc4c8
feat(core): Add workflow settings to log streaming (#23294) 2025-12-16 16:29:59 +00:00
Andreas Fitzek
3041f45f15
chore(core): Dynamic credential resolution depends on credential context (#23290) 2025-12-16 16:35:39 +01:00
Andreas Fitzek
7e94eb88c3
chore(core): Update workflow status endpoint to use absolute URL (#23285) 2025-12-16 16:08:05 +01:00
Suguru Inoue
5c3b7b6186
fix(core): Check mime type when restoring attachments in chat memory (#23287) 2025-12-16 15:35:52 +01:00
Ricardo Espinoza
2f4cda5a8e
chore: Clean up references to the Start node (no-changelog) (#23183) 2025-12-16 09:30:46 -05:00
Suguru Inoue
0ed70e0c09
chore(core): Set foreign key constraint on ChatHub agentId (#23275) 2025-12-16 14:37:58 +01:00
Csaba Tuncsik
9cfd6e5678
fix(editor): Allow space key in input fields when holding shift (#23153)
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-16 14:20:42 +01:00
Csaba Tuncsik
07a1a4e656
fix(core): Add isToolExecution method to context classes and update HttpRequestV3 to conditionally show hints (#23143) 2025-12-16 14:20:17 +01:00
Artem Sorokin
6b9f8da1ad
test: Add Keycloak Testcontainer for OIDC testing (#23078) 2025-12-16 14:11:33 +01:00
Svetoslav Dekov
a9a9955c1b
feat(editor): Rework workflow history list UI (no-changelog) (#23007)
Co-authored-by: Rob <robtf9@icloud.com>
2025-12-16 14:24:50 +02:00
Eugene
d9d5a01ca5
fix(core): Error running evaluations in queue mode (#23248) 2025-12-16 12:39:53 +01:00
Dimitri Lavrenük
8382e27c5a
fix: Only support specified git config keys in Git node (#23264) 2025-12-16 11:59:55 +01:00
Suguru Inoue
a211e62b50
fix(editor): Fix navigation menu layout (#23271) 2025-12-16 11:29:36 +01:00
Andreas Fitzek
662ec62122
chore(core): OAuth2 data storage for dynamic credentials (#23227) 2025-12-16 10:29:23 +01:00
Marc Littlemore
42effef538
feat(core): Add workflow activation events to log streaming (#23251) 2025-12-16 08:50:41 +00:00
Nikhil Kuriakose
9c19072ece
fix(editor): Not close publish modal when clicking outside (#23240) 2025-12-16 09:24:08 +01:00
Declan Carroll
b8cd1657b7
ci: Improve e2e test timings (#23159) 2025-12-15 22:07:31 +00:00
Milorad FIlipović
a84b0e544d
feat(editor): Connect workflows from MCP settings page (#23025) 2025-12-15 19:25:29 +01:00
Tomi Turtiainen
0cdfcffa0a Merge tag 'n8n@2.1.0' 2025-12-15 18:30:44 +02:00
Declan Carroll
3acba8e541
ci: Revert jest memory change (#23243) 2025-12-15 16:06:49 +00:00
github-actions[bot]
5a825a01c5
🚀 Release 2.1.0 (#23236)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-15 17:51:59 +02:00
Charlie Kolb
84573738b5
feat(core): Change data table size limit refresh rate from 60 to 5 seconds (#22852) 2025-12-15 16:29:25 +01:00
Stephen Wright
0f17bef1a0
feat: Support dynamic credentials in oauth refresh (#23225) 2025-12-15 15:16:25 +00:00
Romeo Balta
b22524fd5c
feat(editor): Iterate on ready to run v2 (no-changelog) (#23122) 2025-12-15 14:56:55 +00:00
Suguru Inoue
b7c92e07c7
feat(core, editor): Better distinguish personal and workflow agents in chat (no-changelog) (#23032)
Co-authored-by: Jaakko Husso <jaakko@n8n.io>
2025-12-15 15:40:13 +01:00
yehorkardash
1b256ccc52
feat(editor): Add JS method aliases (#21799) 2025-12-15 15:36:03 +01:00
Michael Drury
31cc49ee2d
chore(ai-builder): Adding a script to convert workflow JSON to a mermaid chart (#23214) 2025-12-15 14:33:10 +00:00
Declan Carroll
630fe3bfb9
ci: Improves CI test performance (#23189) 2025-12-15 14:22:18 +00:00
Alex Grozav
6abed53a8b
fix: Add cleanup for e2e dev (no-changelog) (#23220) 2025-12-15 16:18:28 +02:00
Benjamin Schroth
95af975a37
fix(AI Agent Node): Handle continueOnFail for maxIterations correctly (#23218) 2025-12-15 15:12:44 +01:00
Guillaume Jacquart
957ebef54e
fix(API): Fixes how toJsonSchema creates dependant allOf checks when multiple fields depend on same field (#23114) 2025-12-15 14:56:18 +01:00
Jaakko Husso
e3da10e20f
feat(core): Add Chat commands on command bar (#23063) 2025-12-15 15:21:23 +02:00
Raúl Gómez Morales
f987817300
fix(ai-builder): Fix error message for large context windows (#23135)
Co-authored-by: Eugene Molodkin <eugene@n8n.io>
2025-12-15 14:14:46 +01:00
Jaakko Husso
8619e07ee1
feat(core): Add SerpApi Google search support to Chat hub (#23199) 2025-12-15 15:07:24 +02:00
Marc Littlemore
568dba2c8f
feat(core): Add workflow cancellation events to log streaming (#23151) 2025-12-15 13:06:22 +00:00
Andreas Fitzek
173666fd71
chore(core): Workflow credential status endpoint (#23066) 2025-12-15 14:00:16 +01:00
Dawid Myslak
c4d6502b05
feat(Google Gemini Node): Ability to create a file store and upload files to it (#22988) 2025-12-15 13:59:20 +01:00
Jaakko Husso
2a6e49925e
fix(editor): Make new custom agents appear on the modal selector immediately (no-changelog) (#23219) 2025-12-15 14:54:06 +02:00
Mutasem Aldmour
7a4effab1e
feat(ai-builder): Add "workflow_modified" to builder end of response telemetry (#23226) 2025-12-15 13:49:49 +01:00
Nikhil Kuriakose
88b29bb957
fix(editor): Rename active with publish for workflows (#23111) 2025-12-15 13:48:24 +01:00
Dawid Myslak
182313a0ac
feat(core): Node feature flags (#22950)
Co-authored-by: Elias Meire <elias@meire.dev>
2025-12-15 13:32:10 +01:00
Declan Carroll
d490cc93f9
fix: Improve webhook trigger node tests (#23187) 2025-12-15 12:31:34 +00:00
Declan Carroll
8722ba38db
ci: Conditional legacy browser support (#23217) 2025-12-15 12:14:02 +00:00
Suguru Inoue
be29a4c230
fix(editor): Don't show unnecessary callout when submitting a chat message (#23207) 2025-12-15 13:11:21 +01:00
Jaakko Husso
342c851499
chore: Remove debug logging from chat controller (no-changelog) (#23222) 2025-12-15 13:46:54 +02:00
Jaakko Husso
f248b53e77
fix(SerpApi Tool Node): Fix SerpApi tool calling to work with Tools Agent v3 (#23198) 2025-12-15 13:42:09 +02:00
Eugene
69cb29c532
fix(editor): Workflow sharing modal 'no users found' message (#23213) 2025-12-15 12:25:15 +01:00
Suguru Inoue
ec0c87dc32
fix(editor): Preserve expression in webhook path when duplicating a workflow (#23140) 2025-12-15 12:20:45 +01:00
oleg
be6d68408d
refactor(ai-builder): Improve pairwise evaluation architecture and LangSmith integration (no-changelog) (#23084) 2025-12-15 12:11:25 +01:00
Daria
a3971d8b72
fix(Data Table Node): Convert dates to ISO strings in the output (#23123) 2025-12-15 12:06:00 +02:00
Robert Squires
e391a2830b
fix(editor): Disable publish button when no changes (#23137)
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
2025-12-15 09:41:52 +00:00
Guillaume Jacquart
2f329b38f9
feat(core): Add isResolvable in public and internal APIs (#23119)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-15 10:33:23 +01:00
Eugene
8c7267f347
fix(editor): Remove fallback model connection when disabled in root node (#23089) 2025-12-15 10:29:42 +01:00
Eugene
2c7bd9ac11
fix(ai-builder): Hide execute and refine button when there's no trigger (#23144) 2025-12-15 09:43:19 +01:00
Eugene
6e6b08b686
chore(Qdrant Vector Store Node): Upgrade Qdrant client library to v1.16.2 (#23075) 2025-12-15 09:39:29 +01:00
oleg
49a709b5e3
fix(Chat Trigger Node): Fix file upload with streaming in public chat (#23138)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-15 09:35:38 +01:00
Declan Carroll
9edc008124
test: Target correct canvas handle wrapper (#23211) 2025-12-15 08:30:29 +00:00
Ricardo Espinoza
2f78ed9718
fix(editor): Make sure when you duplicate a workflow MCP is disabled (#22784)
Co-authored-by: Milorad FIlipović <milorad@n8n.io>
2025-12-12 16:38:14 -05:00
Robert Squires
b358940584
fix(editor): Sync sidebar state (no-changelog) (#23080) 2025-12-12 20:02:42 +00:00
Ricardo Espinoza
810edf2df9
feat(core): Add breaking change rule for start node deprecation (#23097)
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
2025-12-12 21:53:53 +02:00
Declan Carroll
890ca377f2
ci: Optimize Docker image build process (#23149) 2025-12-12 18:59:48 +00:00
Artem Sorokin
3dcb98b6f7
test: Revert the orchestration due to limitations with re-running the suites (#23156) 2025-12-12 19:12:08 +01:00
Artem Sorokin
b9027ea405
test: Add playwright-last-failed action for Currents orchestration (#23139) 2025-12-12 17:51:36 +01:00
Irénée
ce8fc2a4b6
fix: Reset git files when push fails (#23142) 2025-12-12 16:26:58 +00:00
Elias Meire
9677c5f00a
fix(editor): Clear sticky notifications when leaving workflow (#23067) 2025-12-12 17:02:39 +01:00
Milorad FIlipović
11a68a8b18
fix(editor): Address MCP re-design feedback (no-changelog) (#23077) 2025-12-12 16:51:48 +01:00
Declan Carroll
6ac5ee72b5
fix: Improve schema preview handling for trigger nodes (#23126) 2025-12-12 15:26:42 +00:00
Jaakko Husso
efb0226ddc
fix(core): Get chat title even after stopping and give more time for title generation (no-changelog) (#23106) 2025-12-12 17:14:36 +02:00
Frank Prößdorf
a2fd770763
fix(Evaluation Node): Docs link falls back to default (#23130)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2025-12-12 16:07:47 +02:00
Dimitri Lavrenük
f2d5cdfc9f
fix: Fix error branching in Set Node (#23127) 2025-12-12 14:44:18 +01:00
Elias Meire
c9abeff5e3
fix: Harden form and trigger response handling (#23061) 2025-12-12 14:08:59 +01:00
Suguru Inoue
e77037c0be
fix(editor): Cannot copy JSON in log view for sub executions (#23117) 2025-12-12 14:00:02 +01:00
Artem Sorokin
a92b744319
test: Enable orchestration for e2e tests (#22747)
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-12 13:30:41 +01:00
Jaakko Husso
83fb0d4c9f
fix(core): Support chat triggers >=v1.2 on Chat hub (no-changelog) (#23104) 2025-12-12 14:28:08 +02:00
Andreas Fitzek
28bdd5e82b
chore(core): Prevent prototype pollution in deep merge (#23088) 2025-12-12 13:18:49 +01:00
Daria
260c2d27a3
fix: Make sure duplicating workflows creates them as unpublished (no-changelog) (#23113) 2025-12-12 14:13:05 +02:00
Eugene
dcc41a1b3f
fix(editor): Fix style of concurrent execution header (#23118) 2025-12-12 12:56:32 +01:00
Andreas Fitzek
bb7311aadf
chore(core): Skip dynamic credentials for manual executions (#23085) 2025-12-12 12:38:29 +01:00
Guillaume Jacquart
551dbfde24
feat(core): Use credential entity resolver fields on resolving and storing process (#23107) 2025-12-12 11:48:35 +01:00
Csaba Tuncsik
fb328d7603
chore(editor): Add Reka UI based popover component (#22591) 2025-12-12 11:20:46 +01:00
Marc Littlemore
e47c435ae8
fix(editor): Update credential sharing tooltip (#23095) 2025-12-12 09:40:18 +00:00
Raúl Gómez Morales
08754cbeb2
feat(editor): Add credentials resolvers list UI (#23082) 2025-12-12 10:05:28 +01:00
Stephen Wright
3ced9b3cc3
feat: Fix types, add resolver id to csrf state (#23087) 2025-12-12 08:52:09 +00:00
Guillaume Jacquart
a19fefece5
feat(core): Add resolvable fields to credential entity (#22712) 2025-12-12 08:06:04 +01:00
Daria
9a608dc00c
feat: Set autosave for history versions (no-changelog) (#23076) 2025-12-11 18:14:42 +02:00
Andreas Fitzek
f9a592b966
chore(core): Allow marking fields in credentials as resolvable (#23074) 2025-12-11 16:17:58 +01:00
Nikhil Kuriakose
90c2d2ea70
fix(editor): Cannot close focus tab in version tab (#23071) 2025-12-11 14:15:11 +01:00
S Rishiraj
9a2f2e77aa
fix(editor): Column order in workflow UNION query to fix sorting (#22026)
Co-authored-by: Nikhil Kuriakose <nikhilkuria@gmail.com>
2025-12-11 13:41:06 +01:00
oleg
51a460d634
refactor(ai-builder): Add PromptBuilder and registry system for prompts (no-changelog) (#22992)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-11 13:10:33 +01:00
Svetoslav Dekov
94ea8854ce
chore(editor): Refactor wf checksum setting (no-changelog) (#23039) 2025-12-11 13:47:04 +02:00
Guillaume Jacquart
74ede64bdc
fix(core): Reload external secrets settings and providers from db on pubsub event (#23045) 2025-12-11 12:19:47 +01:00
Arvind Kumar
d42654ff3f
fix(core): Support lowercase proxy environment variables (#21201)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-11 11:11:56 +00:00
Svetoslav Dekov
814ff8b491
fix(editor): Fix workflow card spacing (no-changelog) (#23005) 2025-12-11 13:09:40 +02:00
Daria
5074c992c7
fix: Backfill missing workflow history records (#23070) 2025-12-11 12:54:56 +02:00
Stephen Wright
9e7fafbc24
feat: Add validate identity helper to resolver (#23068) 2025-12-11 10:48:12 +00:00
Andreas Fitzek
8ecf6e0e2f
chore(core): Add userinfo identifier to auth2 resolver (#23062) 2025-12-11 10:15:20 +01:00
Suguru Inoue
2eecc8f11d
fix(editor): Model selector dropdown menu in chat closes too eagerly (#23058) 2025-12-11 10:05:25 +01:00
Ross Lafferty
dd9585828b
feat: Add Support for AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE (EKS Pod Identity) (#21584)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
Co-authored-by: Artem Sorokin <38620398+seemewalkin@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-11 08:43:32 +00:00
Stephen Wright
ce317e30a8
feat: Add support for dynamic credentials to oauth callback (#23013) 2025-12-11 08:28:03 +00:00
Milorad FIlipović
1c2e89fa52
feat(editor): Edit workflow descriptions from the MCP page (#22967) 2025-12-11 09:04:16 +01:00
Guillaume Jacquart
9bffc72c8c
feat(editor): UI improvements for credential resolver modal (#23027) 2025-12-10 19:11:36 +01:00
Declan Carroll
223b60024d
ci: Ensure coverage for container builds is caught (#23040) 2025-12-10 15:50:59 +00:00
Benjamin Schroth
537747bd63
chore: Make workflow comparison run in CI (#23011) 2025-12-10 16:42:39 +01:00
Jaakko Husso
fa1c87f503
feat(core): Add new Chat hub feature for chatting with LLMs and your n8n agent workflows (#23035) 2025-12-10 17:19:08 +02:00
Jaakko Husso
8ec8864413
feat(core): Make Chat credential picker filterable and show projects (no-changelog) (#23012) 2025-12-10 16:56:06 +02:00
Charlie Kolb
124aa7bd73
fix(core): Use correct entity manager in Data Table update transaction (no-changelog) (#23019) 2025-12-10 15:40:08 +01:00
Declan Carroll
840deaddf4
ci: Remove release exclusion from PR's (#23033) 2025-12-10 14:14:53 +00:00
Irénée
b916c453c3
fix: Reduce OAuth authorization request by excluding shared projects (#22986) 2025-12-10 14:11:18 +00:00
Daria
34260fe4be
fix: Fix checksum hashing when WebCrypto is unavailable (#23024) 2025-12-10 15:22:49 +02:00
Jaakko Husso
8252909456
feat(core): Add beta tag on Chat (no-changelog) (#22981) 2025-12-10 15:18:16 +02:00
mfsiega
37d2d46267
fix(core): Don't resume parent workflow when the child workflow goes into waiting (#22964) 2025-12-10 14:13:33 +01:00
Andreas Fitzek
8a70151aa1
chore(core): Write path for dynamic credentials (#23026) 2025-12-10 14:08:40 +01:00
Michael Drury
c3190fcfec
fix(ai-builder): Updating stream recursion limit and removing tool node static parameter validation (#23023) 2025-12-10 12:15:44 +00:00
Declan Carroll
494f9ba66b
fix: Update Node.js version to 22.21.1 (#23016) 2025-12-10 11:53:58 +00:00
Declan Carroll
117068b868
ci: Update Node.js version in base image workflow (#23018) 2025-12-10 11:05:41 +00:00
Harshal Patil
fa82e91a83
feat(ai-builder): Add best practices for referencing data, prompt edits, add Gmail node best practices (no-changelog) (#22938)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-10 11:58:51 +01:00
Michael Drury
272a5d4435
feat(ai-builder): WF builder programmatic validation for HTTP request and set nodes (correct credential usage) (#22941) 2025-12-10 10:35:54 +00:00
Alex Grozav
94137d08db
fix(editor): Allow running webhook workflow even when a node has error (#22239)
Co-authored-by: Danny Martini <danny@n8n.io>
2025-12-10 12:31:19 +02:00
Tomi Turtiainen
48b2b44967 Merge branch 'v2' 2025-12-10 12:10:46 +02:00
Declan Carroll
c554666c24
test: Removes Github reporter from Playwright tests (#23014) 2025-12-10 10:09:05 +00:00
Guillaume Jacquart
bc1f238f2e
feat(core): Implement credential resolution service (#23015) 2025-12-10 11:08:07 +01:00
Tomi Turtiainen
2747106e5a Merge branch 'master' into v2 2025-12-10 11:47:33 +02:00
Tomi Turtiainen
4b09019f06 test: Fix workflow integration test after merge 2025-12-10 11:42:39 +02:00
Tomi Turtiainen
9d72e1ddc8 test: Fix e2e tests after merge 2025-12-10 11:41:52 +02:00
Guillaume Jacquart
432545a4c8
feat(editor): Implement modal to edit/create credential resolver, and resolver workflow settings (#22977) 2025-12-10 10:32:33 +01:00
Declan Carroll
9f641cdca1
chore: Upgrade launcher to 1.4.2 (#22995) 2025-12-10 09:17:36 +00:00
Tomi Turtiainen
ddd0c3c6e6 test: Fix SidebarPage 2025-12-10 11:03:20 +02:00
Raúl Gómez Morales
b420987e53
fix(editor): Show node settings in protected view for read-only review (#23009) 2025-12-10 09:58:05 +01:00
Guillaume Jacquart
e59be66c8b
feat(editor): First shot at adding a dynamic credential section on the credential modal (#22983) 2025-12-10 09:51:14 +01:00
Tomi Turtiainen
fea083527a Fix SidebarPage 2025-12-10 10:34:58 +02:00
Tomi Turtiainen
9144314476 Merge branch 'master' into v2 2025-12-10 10:08:10 +02:00
Suguru Inoue
c7fd47d31f
fix(core): Files are not included in memory in chat (no-changelog) (#22922) 2025-12-10 08:38:29 +01:00
Raúl Gómez Morales
c5a31a3be8
fix(editor): Fix project selector scroll (#22728) 2025-12-10 08:37:49 +01:00
Declan Carroll
3b898985d2
ci: Add ui-e2e to codecov reports (#22996) 2025-12-10 07:03:06 +00:00
Declan Carroll
90cafaa336
ci: Increase timer for e2e CI (#22991) 2025-12-09 18:30:39 +00:00
Daria
50e337f0ba
fix: Add version history records when importing workflows (#22974) 2025-12-09 19:22:31 +02:00
Stephen Wright
87f6b51de3
fix: Duplicate selector in workflow settings (#22984) 2025-12-09 15:56:43 +00:00
Mutasem Aldmour
776152dbe3
fix(ai-builder): Refresh license in sdk when renewed (#22969) 2025-12-09 16:51:45 +01:00
Andreas Fitzek
87e7f60f45
chore(core): Use correct license flag for dynamic credentials (#22982) 2025-12-09 16:24:43 +01:00
Declan Carroll
484f75e078
ci: Add UI checks for community PR's (#22980) 2025-12-09 16:10:57 +01:00
Stephen Wright
0a56a56dc5
feat: Support oauth1 authorization for dynamic credentials (#22972) 2025-12-09 14:42:11 +00:00
Alex Grozav
e1e4c821a4
feat: Allow running Playwright e2e tests using Vite dev server (no-changelog) (#22742) 2025-12-09 16:21:21 +02:00
Declan Carroll
c6d74234c6
fix: Upgrade urllib3 in runners image (#22975) 2025-12-09 14:01:13 +00:00
Andreas Fitzek
a7efa2f097
chore(core): License flag for the dynamic credential module (#22971) 2025-12-09 14:27:48 +01:00
Andreas Fitzek
51e4adf80b
chore(core): Implement oauth introspection resolver and bearer token extractor (#22968) 2025-12-09 14:26:08 +01:00
Declan Carroll
f9c149869a
ci: Increase timeout for docker building (#22970) 2025-12-09 12:32:46 +00:00
Dawid Myslak
f8304472f8
feat(Google Gemini Node): Introduce built-in Gemini tools (#22454)
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
2025-12-09 13:31:06 +01:00
Raúl Gómez Morales
ec8ed89273
fix(editor): Propagate last successful execution to expression edit modal (#22666)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-09 13:01:06 +01:00
Dimitri Lavrenük
a08944835d
feat(ai-builder): Add autofocus for input field (#22919) 2025-12-09 12:32:41 +01:00
Stephen Wright
5214afa686
feat: Dynamic credentials authorization endpoint for oauth2 (#22944) 2025-12-09 11:30:08 +00:00
Jaakko Husso
98ea4c04aa
feat(core): Make n8n workflows on Chat require streaming response mode (no-changelog) (#22947) 2025-12-09 13:25:18 +02:00
Dimitri Lavrenük
cf6f75b8dd
fix: Allow negative numbers when parsing objects from string (#22937) 2025-12-09 11:59:43 +01:00
yehorkardash
756ea6ec78
fix(Slack Node): Rate limit requests in RLC getChannels (#22149)
Co-authored-by: Shireen Missi <shireen@n8n.io>
2025-12-09 10:52:48 +00:00
Stephen Wright
c57052a1da
feat: Enable time saved node for testing (#22650) 2025-12-09 10:29:11 +00:00
Iván Ovejero
7e08952455
fix(core): Add missing env vars to internal mode (#22965) 2025-12-09 11:14:25 +01:00
yehorkardash
fd08baf141
fix(core): Throw error when workflow is too big for webhook registration (#21860) 2025-12-09 10:47:25 +01:00
Konstantin Tieber
07e84c9d63
refactor: Use paginated query to generate user access export csvs in SSO form (no-changelog) (#22930) 2025-12-09 09:48:33 +01:00
Andreas Fitzek
00dfd3f7b8
chore(core): Implement identifiers for resolvers (#22826) 2025-12-09 09:34:58 +01:00
Charlie Kolb
10b52b1817
test(core): Add withPublishHistory parameter to workflow test utils (#22902) 2025-12-09 09:10:56 +01:00
Jaakko Husso
a77cf97d48
fix(core): Adjust chat hub system prompt to avoid claiming it can generate images (no-changelog) (#22932) 2025-12-08 21:59:20 +02:00
RomanDavydchuk
d710895dc0
feat(FTP Node): Add timeout option (#21868)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-08 19:39:35 +00:00
RomanDavydchuk
cb2ac85725
fix(Webhook Node): Assign default binary property names if it's empty or whitespace (#21857)
Co-authored-by: Shireen Missi <94372015+ShireenMissi@users.noreply.github.com>
2025-12-08 18:26:08 +00:00
Csaba Tuncsik
edeeacfeef
chore: Use wrangler-action@v3 for Storybook Cloudflare deploy (PAY-4282) (#22933)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-08 18:24:59 +01:00
github-actions[bot]
a8ecda44f7
🚀 Release 2.0.0 (#22939)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-08 19:11:21 +02:00
Artem Sorokin
f62e698fb8
test: Rename tests/ui to tests/e2e and reorganize, move tests to api … (#22935) 2025-12-08 17:41:57 +01:00
Elias Meire
5dcd75bd46
chore: Remove feature flag for NDV overhaul (#22924)
Co-authored-by: Shireen Missi <shireen@n8n.io>
2025-12-08 17:29:32 +01:00
mfsiega
fc93272021
fix(core): Only resolve the filepath once (#22767)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
2025-12-08 16:04:21 +01:00
Jaakko Husso
58cf94a9d9
feat(core): Add 'Project Chat User' role for chat only access use case (no-changelog) (#22837) 2025-12-08 16:50:40 +02:00
Daria
22609531c3
fix: Fetch workflow before updating checksum (#22927) 2025-12-08 16:48:13 +02:00
Declan Carroll
902e1a8706
fix: Remove apk tools from runner image (#22925) 2025-12-08 14:35:31 +00:00
Michael Drury
c69a517579
feat(ai-builder): Design updates for workflow builder chat experience (#22765) 2025-12-08 14:35:20 +00:00
Guillaume Jacquart
fd7cc85f06
feat(core): Add types endpoint to get all credential resolver types (#22923) 2025-12-08 15:01:25 +01:00
Suguru Inoue
df9b15c734
fix: Don't show unavailable models in model selector (no-changelog) (#22763) 2025-12-08 14:59:45 +01:00
mfsiega
dcd094eaf9
fix(core): Handle misformed nodes in credential indexing (no-changelog) (#22915) 2025-12-08 14:54:02 +01:00
Svetoslav Dekov
311d347226
fix(editor): Fix workflow list endpoint triggerNodeType filter query (no-changelog) (#22912) 2025-12-08 15:50:44 +02:00
Daria
1aa325a64f
feat: Validate nodes before activating (#22916) 2025-12-08 15:47:55 +02:00
mfsiega
15a8e1b567
fix(Form Node): Remove uploaded files from tmp (#22873) 2025-12-08 14:36:15 +01:00
Charlie Kolb
a2da5641fc
fix(core): Exclude Sub-workflow and Error triggers from triggerCount again (no-changelog) (#22906) 2025-12-08 14:18:49 +01:00
Daria
207c3f8ba8
fix: Update checksum after restoring workflow (#22920) 2025-12-08 14:55:07 +02:00
Tomi Turtiainen
f8271efe19
chore: Clean up deprecation warnings (#22914) 2025-12-08 14:32:37 +02:00
Benjamin Schroth
f35c65e625 chore: Update @modelcontextprotocol/sdk (#22823) 2025-12-08 14:30:15 +02:00
Milorad FIlipović
40ff0479a8
feat(editor): Redesign MCP settings page (#22677)
Co-authored-by: Robert Squires <robtf9@icloud.com>
2025-12-08 13:29:06 +01:00
Mutasem Aldmour
bbdc99176b
feat: Add and update telemetry events (#22762) 2025-12-08 13:26:44 +01:00
Declan Carroll
a642722115
fix: Security patches for jws (#22918) 2025-12-08 12:22:51 +00:00
Iván Ovejero
a31ca3d190 fix(core): Allowlist HOME env var in JS runner config (#22839) 2025-12-08 14:07:20 +02:00
Iván Ovejero
eb18c05816 refactor(core): Make Sentry init non-fatal for JS runner (#22800) 2025-12-08 14:07:20 +02:00
Iván Ovejero
2cf10216bd fix: Add HOME env var to distroless runners image (#22796) 2025-12-08 14:07:20 +02:00
Guillaume Jacquart
5799cf712a
feat(core): Dynamic credential resolvers API routes (#22862) 2025-12-08 12:52:24 +01:00
Ricardo Espinoza
f7cb18ce38
fix(core): Update migration that activate workflows with executeWorkflowTrigger (#22860) 2025-12-08 12:39:31 +01:00
Konstantin Tieber
b8d433f3bf
fix(core): Workflow diff preview errors out in push dialog for workflow that's newly created (#22861) 2025-12-08 12:31:54 +01:00
Iván Ovejero
fb9f913492
fix(core): Allowlist HOME env var in JS runner config (#22839) 2025-12-08 12:30:24 +01:00
Svetoslav Dekov
a2373d846e
fix(editor): Use active workflow nodes to determine wf inputs when executing by parent (no-changelog) (#22907) 2025-12-08 13:12:56 +02:00
James Gee
99c30edf1d
fix(core): Make workers memory constraints more container aware (#22698) 2025-12-08 12:00:14 +01:00
yehorkardash
f20420e36f
fix(Guardrails Node): Remove Guardrails from "Source for Prompt" (#22435) 2025-12-08 12:36:29 +02:00
Mutasem Aldmour
dcbc24d3f7
feat(ai-builder): Consolidate builder telemetry (#22644) 2025-12-08 10:56:38 +01:00
yehorkardash
4df815e6dd
fix(Read/Write Files from Disk Node): Throw error when file not found, normalize windows path (#22455) 2025-12-08 10:54:11 +01:00
Filipe Tavares
8364430471
chore(editor): Add trial upgrade button to main sidebar experiment (no-changelog) (#22151)
Co-authored-by: Giulio Andreini <g.andreini@gmail.com>
Co-authored-by: Romeo Balta <7095569+romeobalta@users.noreply.github.com>
2025-12-08 09:43:46 +00:00
Suguru Inoue
bc557ec9e9
fix(editor): Improve chat error handling (no-changelog) (#22822) 2025-12-08 10:38:08 +01:00
yehorkardash
85d9465ad9
chore: Fix lefthook config for windows (#22676)
Co-authored-by: RomanDavydchuk <roman.davydchuk@n8n.io>
2025-12-08 07:53:13 +02:00
Suguru Inoue
f72bbaf088
fix(core): GET /models endpoint doesn't return n8n workflow agents (no-changelog) (#22845) 2025-12-05 22:15:48 +02:00
James Gee
5c76f1ec56
fix: PAY-4074 - Owner registration in multi-main setup (#22520)
Signed-off-by: James Gee <james@justec.io>
Signed-off-by: James Gee <1285296+geemanjs@users.noreply.github.com>
2025-12-05 21:04:12 +01:00
Artem Sorokin
68693b5b26
test: Split workflow-actions.spec.ts into focused test files (#22850) 2025-12-05 18:37:18 +01:00
Artem Sorokin
d3e7713632
test: Split sharing tests into sharing/ directory (#22849) 2025-12-05 18:13:26 +01:00
renovate[bot]
e9c4c8d99a
chore: Update cloudflare/wrangler-action digest to 707f637 (#22322)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-05 16:53:52 +00:00
Artem Sorokin
39a4b29b9d
test: Rename building-blocks tests to remove numeric prefixes (#22846) 2025-12-05 17:51:00 +01:00
Artem Sorokin
5234b286ac
test: Migrate data tables tests to data-tables/ directory (#22841) 2025-12-05 17:30:12 +01:00
Ricardo Espinoza
ca8494af95
fix: Allow the activation of workflows with the errorTrigger and the executionWorkflowTrigger trigger (no-changelog) (#22019)
Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
2025-12-05 11:24:33 -05:00
Daria
3dc44fe012
feat: Include active version id in workflowActivated broadcast event (no-changelog) (#22805)
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
2025-12-05 18:22:19 +02:00
oleg
b97b5d5bf8
feat(ai-builder): Add multi-judge pairwise evals and local mode (no-changelog) (#22708)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-05 17:12:18 +01:00
Artem Sorokin
a939ac6e1a
test: Migrate tests to app-config/ and capabilities/ directories (#22843) 2025-12-05 17:08:31 +01:00
Nikhil Kuriakose
d718f5ca76
feat(editor): Add message active workflow usage (no-changelog) (#22824) 2025-12-05 16:56:58 +01:00
Artem Sorokin
b04970a478
test: Move cloud tests to cloud/ directory (#22840) 2025-12-05 16:42:37 +01:00
Artem Sorokin
3292132c49
test: Migrate node-specific tests to nodes/ directory (#22835) 2025-12-05 16:27:08 +01:00
Artem Sorokin
f85f1107a6
test: Migrate trigger tests to triggers/ directory (#22832) 2025-12-05 16:25:37 +01:00
Stephen Wright
5926ebf094
feat: Make underlying oauth abstractions more generic (#22741) 2025-12-05 15:16:10 +00:00
Artem Sorokin
decbc162aa
test: Migrate subworkflow tests to workflows/editor/subworkflows/ (#22827) 2025-12-05 16:15:44 +01:00
Artem Sorokin
be254b270f
test: Migrate workflow list/templates/checklist tests to workflows/ (#22831) 2025-12-05 16:15:23 +01:00
Tuukka Kantola
2a7db9212f
fix(editor): Fix animation border radii in non-rectangular nodes (no-changelog) (#22828) 2025-12-05 15:51:49 +01:00
Guillaume Jacquart
03744c30c5 fix(core): Do not prevent credential save if property has default value (#22720) 2025-12-05 16:36:56 +02:00
Benjamin Schroth
fe4f4677c4
chore: Update @modelcontextprotocol/sdk (#22823) 2025-12-05 15:13:49 +01:00
Artem Sorokin
0596e1a5b3
test: Migrate expression and code editor tests (#22820) 2025-12-05 14:57:22 +01:00
Konstantin Tieber
3979e76c1b
chore: Revert add version back to public settings (no-changelog) (#22821) 2025-12-05 14:53:41 +01:00
Suguru Inoue
367643025d
fix(editor): Address chat UI feedback (no-changelog) (#22819) 2025-12-05 14:47:23 +01:00
Michael Drury
33a6aa665c
fix(ai-builder): Allow setting evaluation feature flags via environment variables (no-changelog) (#22813) 2025-12-05 13:37:56 +00:00
Artem Sorokin
305ba9201a
test: Migrate execution tests to workflows/editor/execution/ (#22818) 2025-12-05 14:35:05 +01:00
Artem Sorokin
5c5de5c7ae
test: Move canvas and editor tests to workflows/editor/ directory (#22801) 2025-12-05 14:29:30 +01:00
Declan Carroll
d22c173aec
fix: Security patches (#22748) 2025-12-05 13:28:39 +00:00
oleg
4b1e0ce796
chore(ai-builder): Use isAIMessage for LangGraph v1 compatibility (no-changelog) (#22807) 2025-12-05 14:24:24 +01:00
Svetoslav Dekov
8e68a67d38
fix(editor): Replace activate with publish in trigger nodes (no-changelog) (#22811) 2025-12-05 15:17:37 +02:00
Milorad FIlipović
e4d8812541
chore(core): Update mcp lingo around active workflows (no-changelog) (#22810) 2025-12-05 14:14:13 +01:00
Jaakko Husso
1d952014d8
refactor(core): Move the chat link (no-changelog) (#22812) 2025-12-05 15:01:54 +02:00
Konstantin Tieber
28c3018c95
fix(core): Add version back to public settings (no-changelog) (#22804) 2025-12-05 13:30:04 +01:00
Declan Carroll
7091bc7806
fix: AI session metadata call fix (#22775) 2025-12-05 12:14:55 +00:00
oleg
661dada572
refactor(ai-builder): Centralize prompts into dedicated directory (no-changelog) (#22751)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-05 13:07:45 +01:00
Suguru Inoue
0fd0904103
refactor(core): Extract model retrieval methods from ChatHubService (#22809) 2025-12-05 13:07:14 +01:00
Iván Ovejero
08729ce6c6
refactor(core): Make Sentry init non-fatal for JS runner (#22800) 2025-12-05 12:50:47 +01:00
Artem Sorokin
79fd0b5d40
test: Reorganize NDV tests into workflows/editor/ndv/ directory (#22806) 2025-12-05 12:39:00 +01:00
Artem Sorokin
679cfc5572
test: Move project and folder tests to projects/ directory (#22802) 2025-12-05 12:35:04 +01:00
Charlie Kolb
feab6d3f34
fix(editor): Restore workflow tool view-execution link for V3 Agents (#22730) 2025-12-05 12:20:39 +01:00
Charlie Kolb
492aca09ff
feat(editor): Move workflow description edit button to settings (#22301) 2025-12-05 12:20:27 +01:00
Robert Squires
98efa19ca4
fix(editor): Design tweaks for publish modals (#22694)
Co-authored-by: Svetoslav Dekov <svetoslav.dekov@n8n.io>
2025-12-05 11:20:12 +00:00
yehorkardash
c43543fb84
fix(editor): Disable noImplicitAny in typescript plugin (#22104) 2025-12-05 11:45:18 +01:00
Suguru Inoue
132f9c6f70
fix(editor): Improve table rendering in chat history (no-changelog) (#22738) 2025-12-05 11:19:41 +01:00
Iván Ovejero
064f90ce1e
fix: Add HOME env var to distroless runners image (#22796) 2025-12-05 11:15:29 +01:00
Andreas Fitzek
e78250f94c
chore(core): Implement generic credential storage provider (#22662) 2025-12-05 11:04:26 +01:00
renovate[bot]
fcc6d86326
chore: Update peter-evans/create-pull-request digest to 84ae59a (#22376)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-05 10:03:18 +00:00
Jaakko Husso
480d1e609b
feat(core): Put Chat users behind license checks (no-changelog) (#22781) 2025-12-05 11:38:12 +02:00
Nikhil Kuriakose
b22654709a
feat(editor): Rename columns in data tables (#21747) 2025-12-05 10:06:54 +01:00
Suguru Inoue
8d7f438e1f
fix(editor): Fix chat telemetry (no-changelog) (#22793) 2025-12-05 10:04:20 +01:00
Milorad FIlipović
829135ceee
feat(editor): Open template setup modal automatically (no-changelog) (#22596) 2025-12-05 09:54:05 +01:00
Declan Carroll
3f382a0369
test: Fixing flaky/failing workflow action test (#22792) 2025-12-05 08:37:55 +00:00
Svetoslav Dekov
88aa5ed889
fix(editor): Fix display of publish info for migrated records (no-changelog) (#22791) 2025-12-05 10:33:26 +02:00
Tuukka Kantola
3d46b97bdf
fix(editor): Bind color-scheme to app theme setting (#22774) 2025-12-05 09:18:28 +01:00
Daria
9f14cd05fa
feat(n8n Node): Update operations (no-changelog) (#22740) 2025-12-05 09:39:37 +02:00
Jaakko Husso
54ca0c1abc
fix(core): Filter out workflows from custom agents that use too old agents (no-changelog) (#22752) 2025-12-05 00:53:02 +02:00
Artem Sorokin
e219e7e915
test: Move auth tests to separate folder (#22726) 2025-12-04 23:01:55 +01:00
Declan Carroll
6e77f0eb81
ci: GH bot has a bypass for our CLA (#22773) 2025-12-04 21:23:59 +00:00
Artem Sorokin
813d33372c
test: Move AI features tests to separate folder (#22727) 2025-12-04 21:43:07 +01:00
Artem Sorokin
bcfc95b08f
test: Move workflow executions to separate folder (#22723) 2025-12-04 21:01:23 +01:00
Artem Sorokin
ba1ac9e1a8
test: Move credentials tests to separate folder (#22724) 2025-12-04 21:01:09 +01:00
Artem Sorokin
8928522991
test: Reorganize Playwright settings tests to match UI structure (#22618) 2025-12-04 21:00:52 +01:00
Guillaume Jacquart
ad56240013
fix(core): Hide migration rule issues not relevant to cloud (#22749) 2025-12-04 20:20:35 +01:00
Guillaume Jacquart
b8d045b050
feat(core): Add credential resolver service for CRUD operations (#22653) 2025-12-04 20:20:24 +01:00
mfsiega
803ab42164
fix(core): During partial execution don't include loop as start node if the loop isn't closed (#22555)
Co-authored-by: Danny Martini <danny@n8n.io>
2025-12-04 18:20:33 +01:00
mfsiega
3026a813b0
fix(core, editor): Move single webhook trigger check to the backend (#22450)
Co-authored-by: Danny Martini <danny@n8n.io>
2025-12-04 18:20:13 +01:00
Svetoslav Dekov
f66683e0eb
fix(editor): Improve loading states for publish workflow (no-changelog) (#22755) 2025-12-04 17:39:08 +02:00
Declan Carroll
5851265ded
test: Fixing task runner test (#22756) 2025-12-04 16:07:20 +01:00
github-actions[bot]
c0407fd76c
🚀 Release 2.0.0-rc.3 (#22757)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-04 17:01:22 +02:00
Tuukka Kantola
3fc1c566a4 feat(editor): Improve node component visual states (#20242)
Co-authored-by: Giulio Andreini <g.andreini@gmail.com>
Co-authored-by: Rob <robtf9@icloud.com>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: Daria <daria.staferova@n8n.io>
2025-12-04 16:50:23 +02:00
Tomi Turtiainen
46249a9cf3 Merge tag 'n8n@2.0.0-rc.2' into v2 2025-12-04 16:48:37 +02:00
Svetoslav Dekov
14d4434920
fix(editor): Address publish wf UI feedback (no-changelog) (#22671) 2025-12-04 16:30:43 +02:00
Iván Ovejero
55e15fb8a7
refactor(core): Mark native Python as stable (#22739) 2025-12-04 14:51:37 +01:00
Danny Martini
ce6403262b
fix(core): Address review feedback for sub-workflow wait fix (#22745) 2025-12-04 14:39:47 +01:00
Jaakko Husso
f3fa3f9c30
fix(core): Address chat feedback items (no-changelog) (#22725) 2025-12-04 15:17:59 +02:00
Michael Drury
0866f644b1
chore(ai-builder): Telemetry updates for pinned data (#22625) 2025-12-04 12:54:36 +00:00
Iván Ovejero
727a12da56
refactor(core): Mark native Python as stable (#22737) 2025-12-04 13:34:48 +01:00
Declan Carroll
70aad196d6
ci: Use multimain as default for e2e (#22255) 2025-12-04 12:23:11 +00:00
Declan Carroll
31e5b4590b
ci: Add consolidated check job so we can change branch protection rules (#22732) 2025-12-04 12:01:52 +00:00
github-actions[bot]
07698d132b
🚀 Release 2.0.0-rc.2 (#22735)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-04 13:48:57 +02:00
Danny Martini
f603bc891f fix(core): Prevent execution data from being overwritten on manual workflow resume (#22665)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 13:36:35 +02:00
Benjamin Schroth
599c6ebe98
fix(editor): Don't create duplicate placeholder nodes on agent failure (#22715) 2025-12-04 12:32:05 +01:00
github-actions[bot]
030b25ed89
🚀 Release 2.0.0-rc.1 (#22729)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-04 13:04:22 +02:00
Tomi Turtiainen
2e26b04f11 docs: Remove incorrect changelog 2025-12-04 12:52:51 +02:00
Raúl Gómez Morales
f2eb85dc08
fix(editor): Fix correct $fromAi expression showing as error (#22711) 2025-12-04 11:52:45 +01:00
Suguru Inoue
5fba6c9f2e
fix(editor): Syntax highlighting in chat message not working (no-changelog) (#22721) 2025-12-04 11:51:32 +01:00
Tomi Turtiainen
a3278e9d65 Merge tag 'n8n@2.0.0-rc.0' into v2 2025-12-04 12:49:38 +02:00
Daria
9a72da03fd
feat: Forbid creating active workflows (no-changelog) (#22718) 2025-12-04 12:44:02 +02:00
Danny Martini
14205dc0c6
fix(core): Make sub-workflows with waits return correct data to parents (#22611)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-04 11:32:30 +01:00
Guillaume Jacquart
9913991d20
fix(core): Do not prevent credential save if property has default value (#22720) 2025-12-04 11:09:50 +01:00
Raúl Gómez Morales
5f3ef83d9e
test(editor): Increase timeout for loader not to be present (#22717) 2025-12-04 10:34:46 +01:00
Tomi Turtiainen
553b24458e
fix(core): Fix html header check (#22713) 2025-12-04 11:22:42 +02:00
Guillaume Jacquart
a02d7ba9d4
feat(core): Add credential resolver entity for dynamic credential module (#22609) 2025-12-04 09:41:47 +01:00
Tuukka Kantola
25043d35c1
feat(editor): Improve node component visual states (#20242)
Co-authored-by: Giulio Andreini <g.andreini@gmail.com>
Co-authored-by: Rob <robtf9@icloud.com>
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Tomi Turtiainen <10324676+tomi@users.noreply.github.com>
Co-authored-by: yehorkardash <yehor.kardash@n8n.io>
Co-authored-by: Daria <daria.staferova@n8n.io>
2025-12-04 09:29:41 +01:00
Jaakko Husso
40f8007415
fix(core): Don't render empty completed messages (tool calls) on chat (no-changelog) (#22686) 2025-12-04 10:04:59 +02:00
Robert Squires
ed3003ccc3
fix(editor): Design fixes tabs, callout, modal (no-changelog) (#22707) 2025-12-04 07:59:25 +00:00
Svetoslav Dekov
1fd930afd4
feat(editor): Update frontend external hooks with publish/unpublish (no-changelog) (#22693) 2025-12-04 09:04:20 +02:00
Dawid Myslak
271a9dd218
feat(Form Node): Split form name and label (#22304) 2025-12-03 22:49:58 +02:00
Suguru Inoue
44e2bc0beb
fix: Improve instructions for chat title generation (no-changelog) (#22690) 2025-12-03 19:15:19 +01:00
Jaakko Husso
1425f454ff
fix(core): Fix selected tools not being passed to custom agents (no-changelog) (#22675) 2025-12-03 19:23:43 +02:00
Benjamin Schroth
07be71bf74
fix(AI Agent Node): Support thinking mode for Anthropic models (#22585) 2025-12-03 17:53:35 +01:00
Jaakko Husso
4e972d8d56
fix(core): Fix tools not working on custom agents on chat hub (no-changelog) (#22672) 2025-12-03 18:53:09 +02:00
oleg
f2930e2db9
chore(ai-builder): Add workflow naming, compaction, and session cleanup to multi-agent (no-changelog) (#22646)
Signed-off-by: Oleg Ivaniv <me@olegivaniv.com>
2025-12-03 17:50:22 +01:00
Iván Ovejero
8424755513
fix(core)!: Make runners the only Code node option (#22689) 2025-12-03 17:36:55 +01:00
Svetoslav Dekov
7a04304b7c
feat(editor): Update command bar with publish wf flow (no-changelog) (#22688) 2025-12-03 18:34:16 +02:00
Nikhil Kuriakose
f5d144cfaf
fix(editor): Update the value of updated at on data changes (#22634) 2025-12-03 17:30:42 +01:00
Suguru Inoue
deb4c208b0
fix(editor): Chat UI feedback (no-changelog) (#22678) 2025-12-03 17:29:03 +01:00
Iván Ovejero
49a540aaf6
test: Disable banners for e2e tests (#22691)
Co-authored-by: Declan Carroll <declan@n8n.io>
2025-12-03 17:20:42 +01:00
Jaakko Husso
241bb0fe59
feat(core): Chat only users (no-changelog) (#22355) 2025-12-03 17:54:10 +02:00
Declan Carroll
bc8ac3854d
test: Disable banners for e2e tests (#22680) 2025-12-03 15:28:01 +00:00
Iván Ovejero
35014be533
fix(core)!: Make runners the only Code node option (#22661) 2025-12-03 16:25:32 +01:00
Jaakko Husso
762cabbd15
feat(core): Count 'chat' mode executions towards production execution concurrency limits (no-changelog) (#22624) 2025-12-03 16:40:53 +02:00
Jaakko Husso
5ebe3729fc
feat(core): Add more context window limits for our supported Chat models (no-changelog) (#22651) 2025-12-03 16:40:34 +02:00
Danny Martini
85e204c64f
fix(core): Prevent execution data from being overwritten on manual workflow resume (#22665)
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-03 14:02:10 +01:00
Milorad FIlipović
f1439c0b9b
feat(editor): Update ActionBox component (no-changelog) (#22606) 2025-12-03 13:41:39 +01:00
Daria
bda75d49ce
fix: Update activate request for benchmark (no-changelog) (#22649) 2025-12-03 14:10:01 +02:00
Robert Squires
83e65cfb21
fix(editor): Data table color adjustments (no-changelog) (#22642) 2025-12-03 11:40:26 +00:00
Alex Grozav
a732c4e820
refactor(editor): Refactor NDV parameter list implementation and performance (no-changelog) (#22357) 2025-12-03 13:30:01 +02:00
Iván Ovejero
b1bc7786d8
feat(core): Introduce native Python code tool for AI agent (#22658) 2025-12-03 12:20:43 +01:00
Guillaume Jacquart
1be7404a7d
feat(core): Add toolCode nodes to the pyodide check for v2 migration (#22659) 2025-12-03 12:12:11 +01:00
Artem Sorokin
f986ea0d1f
ci: Add cubic.yaml rules in repo root (#22626) 2025-12-03 11:59:25 +01:00
Tomi Turtiainen
0ffd76093c
feat(core): Block access to env in code and expressions by default (#22643) 2025-12-03 12:33:18 +02:00
Michael Drury
0c04e9294a
chore(ai-builder): Add template usage to multi-agent architecture (#22600) 2025-12-03 10:25:26 +00:00
Daria
41ef19bc06
feat: Stop bumping versionId on every workflow change (no-changelog) (#22602) 2025-12-03 12:14:26 +02:00
Iván Ovejero
763b858548
feat(core): Introduce native Python code tool for AI agent (#22595) 2025-12-03 10:34:30 +01:00
RomanDavydchuk
5ded4e8dad
fix(MCP Client Node): Make "Use Dynamic Client Registration" toggle not required (#22645) 2025-12-03 11:04:58 +02:00
Stephen Wright
9245f2d896
feat: Collect dynamic and fixed time saved insights (#22607) 2025-12-03 08:27:12 +00:00
Nikhil Kuriakose
c08884052e
fix(editor): External link aligned to the right in resource locator (#22631) 2025-12-03 09:18:39 +01:00
Robert Squires
0ba2043047
feat(editor): Sidebar redesign (#22395)
Co-authored-by: Iván Ovejero <ivov.src@gmail.com>
Co-authored-by: Daria <daria.staferova@n8n.io>
2025-12-03 08:03:16 +00:00
Raúl Gómez Morales
d4d7cb776f
fix(editor): Fix scope based - move nodes and node pasting (#22608) 2025-12-03 08:28:50 +01:00
Artem Sorokin
e46f5137a0
test: Organize regression tests into categorized folder structure (#22560) 2025-12-02 17:42:04 +01:00
Svetoslav Dekov
f69721ffec
fix(editor): Fix displaying of workflow publish info (no-changelog) (#22605) 2025-12-02 17:55:24 +02:00
github-actions[bot]
84148c1774
🚀 Release 2.0.0-rc.0 (#22613)
Co-authored-by: tomi <10324676+tomi@users.noreply.github.com>
2025-12-02 16:50:45 +02:00
Jaakko Husso
38f06325b1
fix(core): Allow users to update tools on their Chat sessions (no-changelog) (#22612) 2025-12-02 16:41:53 +02:00
Andreas Fitzek
a3f00386bd
chore(core): Implement stub credential resolver for development (#22597) 2025-12-02 14:15:31 +01:00
Jaakko Husso
26e2754fc0
fix(core): Make chat hub work correctly with multi-main (no-changelog) (#22564) 2025-12-02 14:54:34 +02:00
Artem Sorokin
b5c19e1b89
ci: Fix rc versioning to properly bump major version (#22603) 2025-12-02 13:18:13 +01:00
Tomi Turtiainen
00d33ed23a
chore: Remove mistakenly committed file (#22601) 2025-12-02 13:41:26 +02:00
Suguru Inoue
d241921bd7
fix(editor): Make chat credential picker work (no-changelog) (#22594) 2025-12-02 11:17:04 +01:00
mfsiega
b8fa03bf6d
fix(core): Use the structured destination node in test webhook registration (#22456) 2025-12-02 11:04:26 +01:00
Andreas Fitzek
1b2d8b1340
chore(core): Implement Credential resolver registry (#22593) 2025-12-02 10:55:26 +01:00
Dawid Myslak
2a05c6ae20
docs: Introduce AGENTS.md for nodes-base directory (#22354) 2025-12-02 10:39:41 +01:00
Benjamin Schroth
ebca18b709
fix(AI Agent Tool Node): Implement version 3 for agent tool node (#22587) 2025-12-02 10:39:31 +01:00
Mutasem Aldmour
1a342fce56
fix(ai-builder): Only tidy up nodes if a new node is added (#22514) 2025-12-02 10:25:59 +01:00
Andreas Fitzek
2f7a979fe4
chore(core): Credential resolver interface and decorator (#22584) 2025-12-02 10:22:47 +01:00
Benjamin Schroth
f482809f91
fix(editor): Align execute button in modal when executing tools (#22588) 2025-12-02 10:01:42 +01:00
Guillaume Jacquart
0e0410c97a
fix(core): Move subworfklow binary duplication to workflowExecuteAfter before execution cleaning (#22390) 2025-12-02 09:43:10 +01:00
Andreas Fitzek
624eb09b07
chore(core): Http Header Extractor Hook (#22404) 2025-12-02 09:05:50 +01:00
Suguru Inoue
c9e4d2b1c8
feat: Reflect model's capabilities in UI (no-changelog) (#22356) 2025-12-02 08:50:14 +01:00
9010 changed files with 1071195 additions and 155791 deletions

View file

@ -0,0 +1,62 @@
# Design System Style Review Rules
Use these rules when reviewing CSS/SCSS/Vue style changes, especially in
`packages/frontend/` and `packages/frontend/@n8n/design-system/`.
## 1) Token source priority
Prefer this order when choosing visual values:
1. Semantic tokens from
`packages/frontend/@n8n/design-system/src/css/_tokens.scss`
2. Primitives from
`packages/frontend/@n8n/design-system/src/css/_primitives.scss`
3. Hard-coded values only when no suitable token exists
If no token exists, request a short rationale in the PR.
## 2) Hard-coded visual values
Flag hard-coded visual values and suggest token alternatives. This includes:
- Colors (`#fff`, `rgb()`, `hsl()`, `oklch()`)
- Spacing and sizing (`px`, `rem`, numeric layout constants in styles)
- Radius, border widths/styles, and shadows
- Typography values (font size, weight, line-height)
- Motion values (durations and easing like `cubic-bezier(...)`)
Severity: strong warning (expected migration to tokens/primitives when possible).
## 3) Legacy token usage
In `_tokens.scss`, the compatibility section labeled
"Legacy tokens (kept for compatibility)" is considered legacy usage.
When new or modified code uses these legacy token families, flag it as a
migration opportunity and recommend semantic token usage where available.
Severity: strong warning (discourage new usage, allow compatibility paths).
## 4) Deprecated style and component surfaces
Flag new usage of deprecated/legacy style surfaces in design-system components,
for example:
- `Button.legacy.scss` and legacy button override classes
- Legacy button variants/types (for example `highlight`, `highlight-fill`)
- Legacy component variants that exist for compatibility (for example legacy
tabs variant)
Severity: strong warning (prefer modern semantic variants/components).
## 5) Token substitution changes
If a PR changes one token reference to another (for example
`--text-color` -> `--text-color--subtle`), flag it as a soft warning.
Ask for intent in the PR description/comment:
- Intentional design adjustment, or
- Potential accidental visual regression
Do not treat token substitution as a hard failure by default.

View file

@ -1,30 +0,0 @@
{
"baseDir": "packages/frontend/editor-ui/dist",
"defaultCompression": "gzip",
"reportOutput": [
[
"github",
{
"checkRun": true,
"commitStatus": "off",
"prComment": true
}
]
],
"files": [
{
"path": "*.wasm",
"friendlyName": "WASM Dependencies"
}
],
"groups": [
{
"groupName": "Editor UI - Total JS Size",
"path": "**/*.js"
},
{
"groupName": "Editor UI - Total CSS Size",
"path": "**/*.css"
}
]
}

46
.claude/README.md Normal file
View file

@ -0,0 +1,46 @@
# Claude Code Configuration
This directory contains shared Claude Code configuration for the n8n team.
All skills, agents, and commands live under the `n8n` plugin at
`.claude/plugins/n8n/` for `n8n:` namespacing. See
[plugin README](plugins/n8n/README.md) for full details.
## Setup
### Linear MCP Server
The Linear MCP server uses OAuth authentication. To connect:
1. Start Claude Code in this repository
2. Run `/mcp` command
3. Click the Linear authentication link in your browser
4. Authorize with your Linear account
You only need to do this once per machine.
### Permissions
Configure tool permissions in your global Claude Code settings (`~/.claude/settings.json`), not in this repo. This allows each developer to customize their own approval preferences.
To auto-approve Linear MCP tools, add to your global settings:
```json
{
"permissions": {
"allow": [
"mcp__linear-server__*"
]
}
}
```
**Note:** For GitHub/git operations, we use `gh` CLI and `git` commands instead of GitHub MCP.
## Plugin
All skills, commands, and agents are auto-discovered from
`.claude/plugins/n8n/`. They get the `n8n:` namespace prefix automatically
(e.g. `n8n:create-pr`, `/n8n:plan`, `n8n:developer`).
See [plugin README](plugins/n8n/README.md) for structure and design decisions.

View file

@ -0,0 +1,12 @@
{
"name": "n8n",
"owner": {
"name": "n8n"
},
"plugins": [
{
"name": "n8n",
"source": "./"
}
]
}

View file

@ -0,0 +1,5 @@
{
"name": "n8n",
"version": "0.2.0",
"description": "n8n Claude Code plugin — shared skills, commands, and agents for n8n development"
}

View file

@ -0,0 +1,46 @@
# n8n Claude Code Plugin
Shared skills, commands, and agents for n8n development. All items are
namespaced under `n8n:` to avoid collisions with personal or third-party
plugins.
## Usage
Skills, commands, and agents are auto-discovered by Claude Code from this
plugin directory. Everything gets the `n8n:` namespace prefix automatically.
| Type | Example | Invocation |
|------|---------|------------|
| Skill | `skills/create-pr/SKILL.md` | `n8n:create-pr` |
| Command | `commands/plan.md` | `/n8n:plan PAY-XXX` |
| Agent | `agents/developer.md` | `n8n:developer` |
## Plugin Structure
```
.claude/plugins/n8n/
├── .claude-plugin/
│ ├── marketplace.json # Marketplace manifest
│ └── plugin.json # Plugin identity
├── agents/
│ └── <name>.md # → n8n:<name> agent
├── commands/
│ └── <name>.md # → /n8n:<name> command
├── skills/
│ └── <name>/SKILL.md # → n8n:<name> skill
└── README.md
```
## Design Decisions
### Why a plugin instead of standalone skills?
To get the `n8n:` namespace prefix, avoiding collisions with personal or
third-party plugins. Claude Code only supports colon-namespaced items through
the plugin system — standalone `.claude/skills/` entries cannot be namespaced.
### Known Issues
- Plugin skill namespacing requires omitting the `name` field from SKILL.md
frontmatter due to a [Claude Code bug](https://github.com/anthropics/claude-code/issues/17271).
The directory name is used as the skill identifier instead.

View file

@ -0,0 +1,40 @@
---
name: developer
description: Use this agent for any n8n development task - frontend (Vue 3), backend (Node.js/TypeScript), workflow engine, node creation, or full-stack features. The agent automatically applies n8n conventions and best practices. Examples: <example>user: 'Add a new button to the workflow editor' assistant: 'I'll use the developer agent to implement this following n8n's design system.'</example> <example>user: 'Create an API endpoint for workflow export' assistant: 'I'll use the developer agent to build this API endpoint.'</example> <example>user: 'Fix the CSS issue in the node panel' assistant: 'I'll use the developer agent to fix this styling issue.'</example>
model: inherit
color: blue
---
You are an expert n8n developer with comprehensive knowledge of the n8n workflow automation platform. You handle both frontend (Vue 3 + Pinia + Design System) and backend (Node.js + TypeScript + Express + TypeORM) development.
## Core Expertise
**n8n Architecture**: Monorepo structure with pnpm workspaces, workflow engine (n8n-workflow, n8n-core), node development patterns, frontend (editor-ui package with Vue 3), backend (CLI package with Express), authentication flows, queue management, and event-driven patterns.
**Key Packages**:
- Frontend: packages/frontend/editor-ui (Vue 3 + Pinia), packages/frontend/@n8n/design-system, packages/frontend/@n8n/i18n
- Backend: packages/cli (Express + REST API), packages/core (workflow execution), packages/@n8n/db (TypeORM)
- Shared: packages/workflow, packages/@n8n/api-types
## Development Standards
**TypeScript**: Strict typing (never `any`), use `satisfies` over `as`, proper error handling with UnexpectedError from n8n-workflow.
**Frontend**: Vue 3 Composition API, Pinia stores, n8n design system components, CSS variables from design system, proper i18n with @n8n/i18n.
**Backend**: Controller-service-repository pattern, dependency injection with @n8n/di, @n8n/config for configuration, Zod schemas for validation, TypeORM with multi-database support.
## Workflow
1. **Analyze Requirements**: Identify affected packages and appropriate patterns using n8n conventions
- If working from a Linear ticket, use Linear MCP (`mcp__linear-server__get_issue`) to fetch complete context
- Review ticket description, comments, and linked GitHub issues
- Use `gh` CLI and `git` commands for GitHub/git operations (e.g., `gh pr view`, `git log`)
2. **Plan Implementation**: Outline steps and dependencies
3. **Follow Patterns**: Apply n8n architectural patterns consistently
4. **Ensure Quality**: Run typecheck/lint, write tests, validate across databases
5. **Complete Implementation**: Provide working code with proper error handling and logging. Review for security vulnerabilities and only finalize when confident the solution is secure
Use pnpm for package management, work within appropriate package directories using pushd/popd, and build when type definitions change.
You deliver maintainable, well-typed code that integrates seamlessly with n8n's monorepo architecture.

View file

@ -0,0 +1,74 @@
---
name: linear-issue-triager
description: Use this agent proactively when a Linear issue is created, updated, or needs comprehensive analysis. This agent performs thorough issue investigation and triage including root cause analysis, severity assessment, and implementation scope identification.
model: inherit
color: red
---
You are an expert n8n Linear Issue Explorer and Analysis Agent, specializing in comprehensive investigation of Linear tickets and GitHub issues within the n8n workflow automation platform ecosystem.
**n8n Conventions**: This agent has deep knowledge of n8n conventions, architecture patterns, and best practices embedded in its expertise.
Your primary role is thorough investigation and context gathering to enable seamless handover to developers or implementation agents through comprehensive analysis and actionable intelligence.
## Core Mission
Provide thorough analysis and sufficient context for smooth handover - not implementation. Focus on investigation, root cause identification, and actionable intelligence gathering leveraging your deep n8n ecosystem knowledge.
## Investigation Capabilities
### 1. Deep Issue Analysis
- Fetch Linear ticket details including descriptions, comments, attachments, and linked resources
- Cross-reference related GitHub issues, pull requests, and community reports
- Examine and analyze git history and identify specific problematic commits to understand code evolution and potential regressions
- Analyze patterns and correlations across related issues within the n8n ecosystem
- Check for related issues or PRs with similar descriptions or file paths.
### 2. Root Cause Investigation
- Trace issues to specific commits, files, and line numbers across the monorepo
- Identify whether problems stem from recent changes, workflow engine updates, or node ecosystem changes
- Distinguish between configuration issues, code bugs, architectural problems, and node integration issues
- Analyze dependencies and cross-package impacts in TypeScript monorepo structure
### 3. Context Gathering
- **Implementation Area**: Clearly identify FRONTEND / BACKEND / BOTH / NODE ECOSYSTEM
- **Technical Scope**: Specific packages, files, workflow components, and code areas involved
- **User Impact**: Affected user segments, workflow types, and severity assessment
- **Business Context**: Customer reports, enterprise vs community impact, node usage patterns
- **Related Issues**: Historical context, similar resolved cases, and ecosystem-wide implications
### 4. Severity Assessment Framework
- **CRITICAL**: Data loss, silent failures, deployment blockers, workflow execution failures, security vulnerabilities
- **HIGH**: Core functionality broken, affects multiple users, monitoring/observability issues, node integration problems
- **MEDIUM**: UI/UX issues, non-critical feature problems, performance degradation, specific node issues
- **LOW**: Enhancement requests, minor bugs, cosmetic issues, node improvements
## Workflow
1. **Fetch Issue Details**: Get Linear ticket, comments, attachments, and related resources
- Use Linear MCP tools (`mcp__linear-server__get_issue`, `mcp__linear-server__list_comments`) to fetch complete ticket data
- Get all comments, attachments, and linked GitHub issues
- Check for related Linear issues with similar symptoms
2. **Investigate Root Cause**: Trace to commits, files, and identify problematic changes
- Use `git` commands to examine commit history, blame, and file changes
- Use `gh` CLI to view PRs and issues (e.g., `gh pr view`, `gh issue view`)
- Search codebase for related implementations
3. **Assess Severity**: Apply framework to determine priority level
4. **Generate Analysis**: Provide comprehensive handover report with actionable intelligence
## Investigation Output
Provide comprehensive analysis including:
1. **Root Cause Analysis**: Specific technical reason with commit/file references and ecosystem context
2. **Implementation Scope**: FRONTEND/BACKEND/BOTH/NODE with exact file paths and affected components
3. **Impact Assessment**: User segments affected, workflow scenarios impacted, and severity level
4. **Technical Context**: Architecture areas involved, workflow engine implications, node dependencies, related systems
5. **Investigation Trail**: Commits examined, patterns identified, related issues, ecosystem considerations
6. **Handover Intelligence**: Everything needed for developer or implementation agent to proceed immediately with full context
## Goal
Generate detailed investigative reports that provide complete context for immediate development handover, leveraging deep n8n ecosystem knowledge to ensure comprehensive analysis and actionable intelligence for complex workflow automation
platform issues.
## Important
**DO NOT post triage results to Linear.** Only generate the analysis as output. The user will decide what to share with the Linear ticket.

View file

@ -0,0 +1,25 @@
---
description: Plan n8n Linear ticket implementation
argument-hint: [PAY-XXXX | DEV-XXXX | ENG-XXXX]
allowed-tools: Task, Agent, Read, Glob, Grep, Write, Bash
---
Launch a Plan agent (built-in) to research and design an implementation plan for Linear issue $ARGUMENTS.
The agent should:
1. Fetch and analyze the Linear ticket using Linear MCP
2. Identify affected packages and files
3. Design implementation approach following n8n conventions
4. Define testing strategy
5. Document potential risks
Apply n8n architectural patterns (monorepo structure, TypeScript standards, Vue 3 Composition API, Controller-Service-Repository, etc.).
The agent should return the full plan as text (it cannot write files). After receiving the result, save it to `.claude/plans/<TICKET-ID>.md` (e.g. `.claude/plans/PAY-1234.md`). Create the directory if needed. This directory is gitignored.
The plan file should contain:
- The ticket title and link
- A summary of the ticket
- The full implementation plan
- Testing strategy
- Risks and open questions

View file

@ -0,0 +1,7 @@
---
description: Triage Linear issue with comprehensive analysis
argument-hint: [PAY-XXXX | DEV-XXXX | ENG-XXXX]
allowed-tools: Task
---
Use the n8n:linear-issue-triager agent to triage Linear issue $ARGUMENTS.

View file

@ -0,0 +1,55 @@
#!/usr/bin/env node
// Tracks n8n plugin skill usage by sending anonymized analytics.
// Called as a PostToolUse hook for the Skill tool.
// Receives JSON on stdin: { "tool_name": "Skill", "tool_input": { "skill": "n8n:foo", ... }, "tool_response": ... }
import { createHash } from 'node:crypto';
import { hostname, userInfo, platform, arch, release } from 'node:os';
const TELEMETRY_HOST = 'https://telemetry.n8n.io';
const TELEMETRY_WRITE_KEY = '1zPn7YoGC3ZXE9zLeTKLuQCB4F6';
const input = await new Promise((resolve) => {
let data = '';
process.stdin.on('data', (chunk) => (data += chunk));
process.stdin.on('end', () => resolve(data));
});
const { tool_input: toolInput } = JSON.parse(input);
const skillName = toolInput?.skill;
// Only track n8n-namespaced skills ("n8n-foo" or "n8n:foo")
const isN8nSkill = skillName.startsWith('n8n:') || skillName.startsWith('n8n-');
if (!skillName || !isN8nSkill) {
process.exit(0);
}
// Generate anonymized user ID: SHA-256 of (username + hostname + OS + arch + release)
const raw = `${userInfo().username}@${hostname()}|${platform()}|${arch()}|${release()}`;
const userId = createHash('sha256').update(raw).digest('hex');
const payload = JSON.stringify({
userId,
event: 'Claude Code skill activated',
properties: {
skill: skillName,
},
context: {
ip: '0.0.0.0',
},
});
// Send to telemetry HTTP Track API (fire-and-forget, never block the user)
try {
await fetch(`${TELEMETRY_HOST}/v1/track`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${Buffer.from(`${TELEMETRY_WRITE_KEY}:`).toString('base64')}`,
},
body: payload,
});
} catch {
// Silently ignore network errors
}

View file

@ -0,0 +1,329 @@
---
description: >
Product content designer for UI copy. Use when writing, reviewing, or auditing
user-facing text: button labels, error messages, tooltips, empty states, modal copy,
placeholder text, confirmation dialogs, onboarding flows, or i18n strings.
Also use when the user says /copy, /content, or /ux-copy.
allowed-tools: Read, Grep, Glob, Edit
---
# n8n content design
You are a Senior Content Designer specializing in SaaS tools. You've written UI
copy for complex products — whiteboard tools, workflow automation, enterprise
software — where terminology precision directly impacts user success. You treat
content as interface: every label, error message, and tooltip is a design decision.
You think about what the user needs to know first. In any UI surface — modal,
tooltip, banner, empty state — you lead with the action or outcome, then add
context only if it earns its space.
You default to concise and neutral, but you know when a moment of warmth or
encouragement earns its place — onboarding, empty states, success confirmations.
You never force personality where clarity is the job.
You check your work against the terminology glossary, voice and tone guidelines,
and existing UI patterns below. When no guideline covers a case, you flag the
inconsistency rather than guessing.
You push back on feature names that sound good in marketing but confuse
in-product. You know the difference between onboarding copy that holds hands
and copy that respects user intelligence.
You write in short sentences. You cut filler words. You prefer "Save" over
"Save changes" and "Delete project?" over "Are you sure you want to delete this
project?" unless disambiguation is genuinely needed. You understand that empty
states, loading states, and error states are content design problems, not
afterthoughts.
---
## How to work
### Modes
When invoked, determine what the user needs:
1. **Write** — Draft new UI copy. Ask what surface (button, modal, tooltip,
error, empty state, and so on) and what the user action or system state is.
Deliver 1-3 options ranked by recommendation. For each option, include:
- The copy itself
- Which surface it targets (if ambiguous from context)
- Suggested i18n key (following the naming convention below)
- One-line rationale (which guideline it leans on)
2. **Review** — The user shares existing copy or points to a file. Check it
against every rule below. Return a table:
| Location | Current copy | Issue | Suggested fix |
|----------|-------------|-------|---------------|
Group issues by severity: terminology violations first, then tone, then
grammar and formatting. If the copy follows all guidelines, confirm with a
brief summary of what was checked (e.g., "Checked against terminology
glossary, tone guidelines, grammar rules, and UI patterns — no issues
found.").
3. **Audit** — Scan a file or set of files (Vue components, i18n JSON) for
violations. Use Grep and Glob to find patterns, then report.
### Where copy lives in n8n
| Location | What's there |
|----------|-------------|
| `packages/frontend/@n8n/i18n/src/locales/en.json` | All UI strings (i18n keys) |
| `packages/frontend/editor-ui/src/**/*.vue` | Inline copy in Vue templates |
| `packages/frontend/@n8n/design-system/src/**/*.vue` | Design system component defaults |
| `packages/nodes-base/nodes/**/*.ts` | Node descriptions, parameter labels, placeholders |
| `packages/@n8n/nodes-langchain/nodes/**/*.ts` | AI node descriptions and labels |
| `packages/nodes-base/nodes/**/*Description.ts` | Node parameter `displayName`, `description`, `action`, `placeholder` fields (hardcoded, not i18n'd) |
| `packages/@n8n/nodes-langchain/nodes/**/*Description.ts` | AI node parameter descriptions (hardcoded, not i18n'd) |
| `packages/cli/src/**/*.ts` | Backend error messages in services/controllers that surface to users (hardcoded) |
When editing copy, prefer changing the i18n JSON (`en.json`) over hardcoded
strings in Vue files. If you find hardcoded user-facing strings in Vue
templates, flag them — they should use i18n.
**i18n patterns** (in order of preference):
1. `i18n.baseText('key')` — preferred, most common
2. `$t('key')` / `t('key')` — Vue i18n plugin shorthand
3. `locale.baseText('key')` — legacy pattern, still present in older code
### i18n key naming convention
Keys use hierarchical dot-notation matching the feature area:
| Pattern | Example | When to use |
|---------|---------|-------------|
| `generic.*` | `generic.cancel`, `generic.save` | Universal labels used across many surfaces |
| `featureArea.subArea.element` | `settings.communityNodes.empty.title` | Feature-scoped copy |
| `_reusableBaseText.*` | `_reusableBaseText.credential` | Shared constants referenced by other keys |
| `_reusableDynamicText.*` | `_reusableDynamicText.simpleInput` | Shared text with dynamic fallbacks |
When suggesting new keys, follow the existing hierarchy. Browse nearby keys in
`en.json` to match the nesting depth and naming style of the feature area.
---
## Content guidelines
### Language and grammar
**US English.** Always. No exceptions.
- Do: "categorizing", "color", "analyze"
- Don't: "categorising", "colour", "analyse"
**Active voice** whenever possible.
- Do: "Administrators control user access to n8n Cloud."
- Don't: "User access to n8n Cloud is controlled by administrators."
**Sentence case** for all titles, headings, menu items, labels, and buttons.
Only capitalize the first word and proper nouns.
- Do: "What triggers this workflow?", "Zoom in"
- Don't: "What Triggers This Workflow?", "Zoom In"
**Periods.** A single sentence or fragment doesn't need one. If there are
multiple sentences (including in tooltips), all of them need one.
- "Settings" — single label, no period
- "New workflow executions will show here." — multiple sentences need periods
- Not: "Settings."
**Contractions.** Use them. They keep the tone conversational.
- Do: can't, don't, it's, you'll, we're
- Don't: cannot, can not, it is, you will, we are
**Oxford comma.** Always.
- Do: "Connect apps, databases, and APIs."
- Don't: "Connect apps, databases and APIs."
**Abbreviations.** Don't use internal abbreviations or jargon in
customer-facing copy. Spell out unfamiliar terms on first use.
- Do: "Role-based access control (RBAC)"
- Don't: "RBAC" alone without introduction
Plural abbreviations: "APIs" not "API's".
**No Latin abbreviations.** Use plain alternatives.
| Don't use | Use instead |
|-----------|-------------|
| e.g. | for example, such as |
| i.e. | that is, in other words |
| etc. | and so on |
| vs / versus | compared to, or |
| via | through, with, using |
| n.b. | note |
| ad hoc | unscheduled, temporary, bespoke |
| per se | necessarily, intrinsically |
**Dates.** US format. Spell out months when space allows.
- Do: "Apr 2", "February 14, 2025"
- Don't: "2. Apr", "02/14/2025"
**Times.** 24-hour format with leading zero (technical audience).
- Do: 13:34, 07:52
- Don't: 1:34 PM, 7:52
**Numbers.** Commas for thousands, period for decimals.
- Do: 23,456 and 346.65
- Don't: 23456 and 346,65
### Tone and voice
Write like a knowledgeable colleague, not a manual or a marketing page. Be
technical when precision matters, but default to plain language.
**Do:**
- Be direct. Lead with the most important information.
- Use simple words: "use" not "utilize", "so" not "therefore", "but" not
"however", "give" not "provide".
- Write short sentences. Break complex ideas into smaller pieces.
- Use humor sparingly and only in low-stakes contexts (tooltips,
parentheticals, empty states). Never in errors or warnings.
- Address the user as "you". Refer to n8n as "n8n" or "we" depending on
context.
**Don't:**
- Use formal business language or marketing-speak.
- Be overly enthusiastic or use filler words.
- Use "please" excessively. One "please" is fine. Three in a paragraph is too
many.
- Anthropomorphize the product ("n8n thinks...", "n8n wants to...").
**Quick reference:**
| Avoid | Prefer |
|-------|--------|
| "Utilize the dropdown to select your preferred option" | "Select an option from the dropdown" |
| "We are sorry, but we are unable to process your request" | "Something went wrong. Try again in a few minutes." |
| "You have successfully created a new workflow!" | "Workflow created" |
| "Please be advised that this action cannot be undone" | "This can't be undone" |
### UI copy patterns
**Action labels (buttons and CTAs).** Start with a verb. Be specific.
- Do: "Add connection", "Save workflow", "Delete credential"
- Don't: "New", "Submit", "OK"
For destructive actions, name what's being destroyed: "Delete workflow" not just
"Delete". Use "Cancel" for aborting a process, "Close" for dismissing
informational dialogs.
**Error messages.** Structure: what happened + why (if known) + what to do next.
Always include at least what happened and what to do.
- Do: "Connection failed. Check that the API key is correct and try again."
- Do: "Workflow can't be saved. The name field is required."
- Don't: "Error 403"
- Don't: "Something went wrong"
- Don't: "Invalid input. Please try again."
Never blame the user: "The API key isn't valid" not "You entered an invalid API
key".
**Empty states.** Guide, don't just inform. Explain what the area is for and
give a clear next step.
- Do: "No executions yet. Run this workflow to see results here."
- Don't: "No data"
**Placeholder text.** Use realistic examples. Don't repeat the label.
- Do: Label: "Webhook URL" / Placeholder: "https://example.com/webhook"
- Don't: Label: "Webhook URL" / Placeholder: "Enter webhook URL"
**Confirmation dialogs.** State the consequence. Use the specific action as the
confirm button label.
- Title: "Delete workflow?"
- Body: "This will permanently delete 'My Workflow' and its execution history.
This can't be undone."
- Buttons: "Delete workflow" / "Cancel"
**Tooltips.** One or two sentences. Add information the label alone can't
convey — don't repeat the label.
- Do: "Pins the output data so the node uses it in future test runs instead of
fetching new data."
- Don't: "Click to pin data"
**Truncation.** Use ellipsis (…). Show full text on hover/tooltip. Node and
workflow names: truncate from end. File paths: truncate from middle.
### Terminology
Use these terms consistently. Don't capitalize unless starting a sentence.
| Term | Usage | Avoid |
|------|-------|-------|
| workflow | The automation a user builds | flow, automation, scenario |
| node | A step in a workflow | block, step, action |
| trigger | The node that starts a workflow | starter, initiator |
| execution | A single run of a workflow | run, instance |
| credential | Stored authentication for a service | secret, key, token (unless technically specific) |
| canvas | The area where users build workflows | editor, board |
| connection | The line between two nodes | edge, link, wire |
| input/output | Data going into or out of a node | payload (unless technically specific) |
| pin | Saving node output for reuse in testing | freeze, lock, save |
### n8n-specific conventions
- **"n8n" is always lowercase**, even at the start of a sentence. Never write
"N8n" or "N8N".
- **Node names are proper nouns** — capitalize both words: "Slack Node",
"GitHub Node", "HTTP Request Node".
- **Feature names are lowercase** unless starting a sentence: canvas, workflow,
credential, execution.
- **"n8n Cloud"** is the hosted product name — always capitalize "Cloud".
### Surfaces not covered by guidelines
The guidelines above cover most UI surfaces. For these additional surfaces,
apply the same voice and tone principles:
**Loading states** — keep short, no period, use ellipsis:
- Do: "Loading workflows…"
- Don't: "Please wait while we load your workflows."
**Success notifications** — state what happened, past tense, no exclamation:
- Do: "Workflow saved"
- Don't: "Workflow was saved successfully!"
**Status labels** — sentence case, present tense or past participle:
- Do: "Active", "Running", "Error", "Disabled"
- Don't: "ACTIVE", "Currently Running", "Has Errors"
### Common audit patterns
When running Audit mode, use these grep patterns against `en.json` and Vue
files to find the most common violations:
| Violation | Grep pattern | Notes |
|-----------|-------------|-------|
| Latin abbreviations | `e\.g\.\|i\.e\.\|etc\.\| via \| vs ` | 50+ instances typical |
| Missing contractions | `cannot\|do not\|will not\|does not\|is not\|are not` | 20+ instances typical |
| "please" overuse | `[Pp]lease` | Review each in context — one per surface is fine |
| User-blaming language | `You need\|You must\|You entered\|You have to` | Rewrite to focus on the system state |
| Passive voice | `was created\|is controlled\|will be shown\|was deleted` | Not exhaustive — scan manually too |
Run each pattern with Grep against the relevant files, then triage results by
severity: terminology violations first, then tone, then grammar/formatting.
---
## Checklist
Before finalizing any copy, verify:
- [ ] US English spelling
- [ ] Active voice
- [ ] Sentence case (not Title Case)
- [ ] Contractions used
- [ ] Oxford comma present in lists
- [ ] No Latin abbreviations (e.g., i.e., etc., via, vs)
- [ ] No "please" overuse
- [ ] No user-blaming language in errors
- [ ] Terminology matches glossary exactly
- [ ] Single fragments have no trailing period
- [ ] Multi-sentence groups all have periods
- [ ] Button labels start with a verb
- [ ] Destructive actions name the thing being destroyed
- [ ] Error messages include what happened + what to do
- [ ] Empty states include a next step
- [ ] Placeholders use realistic examples, not label echoes

View file

@ -0,0 +1,97 @@
---
description: Quick reference for n8n patterns. Full docs /AGENTS.md
---
# n8n Quick Reference
**📚 Full Documentation:**
- **General:** `/AGENTS.md` - Architecture, commands, workflows
- **Frontend:** `/packages/frontend/AGENTS.md` - CSS variables, timing
Use this skill when you need quick reminders on critical patterns.
## Critical Rules (Must Follow)
**TypeScript:**
- Never `any` → use `unknown`
- Prefer `satisfies` over `as` (except tests)
- Shared types in `@n8n/api-types`
**Error Handling:**
```typescript
import { UnexpectedError } from 'n8n-workflow';
throw new UnexpectedError('message', { extra: { context } });
// DON'T use deprecated ApplicationError
```
**Frontend:**
- Vue 3 Composition API (`<script setup lang="ts">`)
- CSS variables (never hardcode px) - see `/packages/frontend/AGENTS.md`
- All text via i18n (`$t('key')`)
- `data-testid` for E2E (single value, no spaces)
**Backend:**
- Controller → Service → Repository
- Dependency injection via `@n8n/di`
- Config via `@n8n/config`
- Zod schemas for validation
**Testing:**
- Vitest (unit), Playwright (E2E)
- Mock external dependencies
- Work from package directory: `pushd packages/cli && pnpm test`
**Database:**
- SQLite/PostgreSQL only (app DB)
- Exception: DB nodes (MySQL Node, etc.) can use DB-specific features
**Commands:**
```bash
pnpm build > build.log 2>&1 # Always redirect
pnpm typecheck # Before commit
pnpm lint # Before commit
```
## Key Packages
| Package | Purpose |
|---------|---------|
| `packages/cli` | Backend API |
| `packages/frontend/editor-ui` | Vue 3 frontend |
| `packages/@n8n/api-types` | Shared types |
| `packages/@n8n/db` | TypeORM entities |
| `packages/workflow` | Core interfaces |
## Common Patterns
**Pinia Store:**
```typescript
import { STORES } from '@n8n/stores';
export const useMyStore = defineStore(STORES.MY_STORE, () => {
const state = shallowRef([]);
return { state };
});
```
**Vue Component:**
```vue
<script setup lang="ts">
type Props = { title: string };
const props = defineProps<Props>();
</script>
```
**Service:**
```typescript
import { Service } from '@n8n/di';
import { Config } from '@n8n/config';
@Service()
export class MyService {
constructor(private readonly config: Config) {}
}
```
---
📖 **Need more details?** Read `/AGENTS.md` and `/packages/frontend/AGENTS.md`

View file

@ -0,0 +1,217 @@
---
description: >-
Create new ESLint rules for the @n8n/eslint-plugin-community-nodes package.
Use when adding a lint rule, creating a community node lint, or working on
eslint-plugin-community-nodes. Guides rule implementation, tests, docs, and
plugin registration.
---
# Create Community Node Lint Rule
Guide for adding new ESLint rules to `packages/@n8n/eslint-plugin-community-nodes/`.
All paths below are relative to `packages/@n8n/eslint-plugin-community-nodes/`.
## Step 1: Understand the Rule
Before writing code, clarify:
- **What** does the rule detect? (missing property, wrong pattern, bad value)
- **Where** does it apply? (`.node.ts` files, credential classes, both)
- **Severity**: `error` (must fix) or `warn` (should fix)?
- **Fixable?** Can it be auto-fixed safely, or only suggest?
- **Scope**: Both `recommended` configs, or exclude from `recommendedWithoutN8nCloudSupport`?
## Step 2: Implement the Rule
Create `src/rules/<rule-name>.ts`:
```typescript
import { AST_NODE_TYPES } from '@typescript-eslint/utils';
import {
isNodeTypeClass, // or isCredentialTypeClass
findClassProperty,
findObjectProperty,
createRule,
} from '../utils/index.js';
export const YourRuleNameRule = createRule({
name: 'rule-name',
meta: {
type: 'problem', // or 'suggestion'
docs: {
description: 'One-line description of what the rule enforces',
},
messages: {
messageId: 'Human-readable message. Use {{placeholder}} for dynamic data.',
},
fixable: 'code', // omit if not auto-fixable
hasSuggestions: true, // omit if no suggestions
schema: [], // add options schema if configurable
},
defaultOptions: [],
create(context) {
return {
ClassDeclaration(node) {
if (!isNodeTypeClass(node)) return;
const descriptionProperty = findClassProperty(node, 'description');
if (!descriptionProperty) return;
const descriptionValue = descriptionProperty.value;
if (descriptionValue?.type !== AST_NODE_TYPES.ObjectExpression) return;
// Rule logic here — use findObjectProperty(), getLiteralValue(), etc.
context.report({
node: targetNode,
messageId: 'messageId',
data: { /* template vars */ },
fix(fixer) {
return fixer.replaceText(targetNode, 'replacement');
},
});
},
};
},
});
```
**Naming**: Export as `PascalCaseRule` (e.g. `MissingPairedItemRule`). The `name` field is kebab-case.
**Available AST helpers** — see [reference.md](reference.md) for the full catalog of `ast-utils` and `file-utils` exports.
## Step 3: Write Tests
Create `src/rules/<rule-name>.test.ts`:
```typescript
import { RuleTester } from '@typescript-eslint/rule-tester';
import { YourRuleNameRule } from './rule-name.js';
const ruleTester = new RuleTester();
// Helper to generate test code — keeps test cases readable
function createNodeCode(/* parameterize the varying parts */): string {
return `
import type { INodeType, INodeTypeDescription } from 'n8n-workflow';
export class TestNode implements INodeType {
description: INodeTypeDescription = {
displayName: 'Test Node',
name: 'testNode',
group: ['input'],
version: 1,
description: 'A test node',
defaults: { name: 'Test Node' },
inputs: [],
outputs: [],
properties: [],
};
}`;
}
ruleTester.run('rule-name', YourRuleNameRule, {
valid: [
{ name: 'class that does not implement INodeType', code: '...' },
{ name: 'node with correct pattern', code: createNodeCode(/* correct */) },
],
invalid: [
{
name: 'descriptive case name',
code: createNodeCode(/* incorrect */),
errors: [{ messageId: 'messageId', data: { /* expected template vars */ } }],
output: createNodeCode(/* expected after fix */), // or `output: null` if no fix
},
],
});
```
**Test guidelines:**
- Always test that non-INodeType classes are skipped (valid case)
- Test both the error message and the fixed output for fixable rules
- For rules with options, test each option combination
- For rules using filesystem, mock with `vi.mock('../utils/file-utils.js')`
- For suggestion-only rules, use `errors: [{ messageId, suggestions: [...] }]`
## Step 4: Register the Rule
### 4a. Add to `src/rules/index.ts`
```typescript
import { YourRuleNameRule } from './rule-name.js';
// Add to the rules object:
export const rules = {
// ... existing rules
'rule-name': YourRuleNameRule,
} satisfies Record<string, AnyRuleModule>;
```
### 4b. Add to `src/plugin.ts` configs
Add to **both** config objects (unless the rule depends on n8n cloud features):
```typescript
'@n8n/community-nodes/rule-name': 'error', // or 'warn'
```
- Use `error` for rules that catch bugs or required patterns
- Use `warn` for style/convention rules (like `options-sorted-alphabetically`)
- If the rule uses `no-restricted-globals` or `no-restricted-imports` patterns,
only add to `recommended` (not `recommendedWithoutN8nCloudSupport`)
## Step 5: Write Documentation
Create `docs/rules/<rule-name>.md`:
```markdown
# Description of what the rule does (`@n8n/community-nodes/rule-name`)
<!-- end auto-generated rule header -->
## Rule Details
Explain why this rule exists and what problem it prevents.
## Examples
### Incorrect
\`\`\`typescript
// code that triggers the rule
\`\`\`
### Correct
\`\`\`typescript
// code that passes the rule
\`\`\`
```
The header above `<!-- end auto-generated rule header -->` will be regenerated by `pnpm build:docs`. Write a reasonable first version — it gets overwritten.
## Step 6: Verify
Run from `packages/@n8n/eslint-plugin-community-nodes/`:
```bash
pushd packages/@n8n/eslint-plugin-community-nodes
pnpm test <rule-name>.test.ts # tests pass
pnpm typecheck # types are clean
pnpm build # compiles
pnpm build:docs # regenerates doc headers and README table
pnpm lint:docs # docs match schema
popd
```
## Checklist
- [ ] Rule file: `src/rules/<rule-name>.ts`
- [ ] Test file: `src/rules/<rule-name>.test.ts`
- [ ] Registered in `src/rules/index.ts`
- [ ] Added to configs in `src/plugin.ts`
- [ ] Doc file: `docs/rules/<rule-name>.md`
- [ ] README table updated via `pnpm build:docs`
- [ ] All verification commands pass

View file

@ -0,0 +1,85 @@
# AST & File Utilities Reference
Helpers available from `../utils/index.js`. Use these instead of writing custom AST traversal.
## ast-utils.ts
### Class/Interface detection
| Function | Returns | Use when |
|----------|---------|----------|
| `isNodeTypeClass(node)` | `boolean` | Check if class implements `INodeType` or extends `Node` |
| `isCredentialTypeClass(node)` | `boolean` | Check if class implements `ICredentialType` |
### Property finding
| Function | Returns | Use when |
|----------|---------|----------|
| `findClassProperty(node, name)` | `PropertyDefinition \| null` | Find a property on a class (e.g. `description`, `icon`) |
| `findObjectProperty(obj, name)` | `Property \| null` | Find a property in an object literal (Identifier key) |
| `findJsonProperty(obj, name)` | `Property \| null` | Find a property with a Literal key (JSON-style `"key"`) |
| `findArrayLiteralProperty(obj, name)` | `Property \| null` | Find a property whose value is an ArrayExpression |
### Value extraction
| Function | Returns | Use when |
|----------|---------|----------|
| `getLiteralValue(node)` | `string \| boolean \| number \| null` | Extract primitive from a Literal node |
| `getStringLiteralValue(node)` | `string \| null` | Extract string specifically |
| `getBooleanLiteralValue(node)` | `boolean \| null` | Extract boolean specifically |
| `getModulePath(node)` | `string \| null` | Get import path from string literal or template literal |
### Array operations
| Function | Returns | Use when |
|----------|---------|----------|
| `hasArrayLiteralValue(arr, value)` | `boolean` | Check if array contains a specific string literal |
| `extractCredentialInfoFromArray(element)` | `{ name, testedBy } \| null` | Parse credential object from array element |
| `extractCredentialNameFromArray(element)` | `string \| null` | Get just the credential name from array element |
### Method matching
| Function | Returns | Use when |
|----------|---------|----------|
| `isThisHelpersAccess(node)` | `boolean` | Match `this.helpers` member expression |
| `isThisMethodCall(node, method)` | `boolean` | Match `this.methodName(...)` calls |
| `isThisHelpersMethodCall(node, method)` | `boolean` | Match `this.helpers.methodName(...)` calls |
### Similarity
| Function | Returns | Use when |
|----------|---------|----------|
| `findSimilarStrings(target, candidates, maxDistance?)` | `string[]` | Suggest similar names (Levenshtein distance) |
## file-utils.ts
### Path operations
| Function | Use when |
|----------|----------|
| `isContainedWithin(child, parent)` | Check path is within a directory |
| `safeJoinPath(base, ...parts)` | Join paths with traversal prevention |
### Package.json
| Function | Returns | Use when |
|----------|---------|----------|
| `findPackageJson(startDir)` | `string \| null` | Walk up to find nearest package.json |
| `readPackageJsonN8n(startDir)` | `N8nPackageJson \| null` | Parse n8n config section |
| `readPackageJsonCredentials(startDir)` | `Set<string>` | Get credential names from package.json |
| `readPackageJsonNodes(startDir)` | `string[]` | Get resolved node file paths |
### File system
| Function | Use when |
|----------|----------|
| `validateIconPath(filePath, iconValue)` | Check icon file exists and is SVG |
| `extractCredentialNameFromFile(filePath)` | Parse credential class name from file |
| `fileExistsWithCaseSync(filePath)` | Case-sensitive existence check |
| `findSimilarSvgFiles(dir, name)` | Suggest similar SVG filenames |
### Credential verification
| Function | Use when |
|----------|----------|
| `areAllCredentialUsagesTestedByNodes(startDir)` | Check all credentials have testedBy |

View file

@ -0,0 +1,360 @@
---
description: Create Linear tickets or GitHub issues following n8n conventions. Use when the user asks to create a ticket, file a bug, open an issue, or says /create-issue.
argument-hint: "[linear|github] <description of the issue>"
compatibility:
requires:
- mcp: linear
description: Required for creating Linear tickets
- cli: gh
description: Required for creating GitHub issues. Must be authenticated (gh auth login)
---
# Create Issue
Create a Linear ticket or GitHub issue for: **$ARGUMENTS**
## Determine Target
Decide where the issue should be created based on user input:
- If the user says "Linear", "ticket", or provides a team key (e.g., AI, NODE, N8N) → **Linear**
- If the user says "GitHub", "GH issue", or "open source" → **GitHub**
- If ambiguous, **ask the user** which platform they want
---
## Linear Tickets
### Prerequisites
Verify the Linear MCP is connected before proceeding.
### Style Guide
#### Title
- **Sentence case** — capitalize only the first word (e.g., "Add webhook verification to Trello trigger")
- **Descriptive** — a reader should understand the scope without opening the ticket
- **515 words** — long enough to be specific, short enough to scan
- **Imperative mood for features/enhancements** — "Add ...", "Support ...", "Improve ..."
- **Bug titles** — prefix with `Bug -` followed by a description of the symptom (e.g., "Bug - Pin data not updating after workflow edit")
- **No ticket IDs in titles** — the identifier (AI-1234) is assigned automatically
- **No trailing punctuation**
#### Description
Structure the description using markdown headers. Use the appropriate template:
**For bugs:**
```markdown
## Description
[Clear explanation of the problem]
## Expected
[What should happen]
## Actual
[What happens instead]
## Attachments
[Screenshots, videos, or screen recordings that illustrate the problem]
## Steps to reproduce
1. [Step-by-step reproduction]
## Additional context
- n8n version: [version]
- Database: [SQLite/PostgreSQL]
- Hosting: [cloud/self-hosted]
```
**For features / enhancements:**
```markdown
## Summary
[One-paragraph overview of what this adds or changes]
## Problem
[What limitation or gap exists today]
## Proposed solution
[How it should work — technical approach if known]
## Out of scope
[Explicitly note what this does NOT cover, if helpful]
```
**For tech debt:**
```markdown
## Summary
[What technical improvement is needed]
## Current state
[What the code/system looks like today and why it's problematic]
## Proposed improvement
[What the improved state should look like]
## Motivation
[Why this matters — maintainability, performance, developer experience, etc.]
## Scope
[What is included / excluded from this work]
```
**For spikes / investigations:**
```markdown
## Goal
[What question are we trying to answer]
## Context
[Why this investigation is needed now]
## Expected output
[What deliverable is expected — RFC, PoC, decision document, etc.]
```
#### Attachments (Screenshots / Videos)
If the user provides screenshots, videos, or screen recordings:
- **URLs** — embed directly in the description using markdown image syntax (`![description](url)`)
- **File paths** — if the user provides a local file path, ask them to upload it to a hosting service (e.g., GitHub, Imgur) or use `mcp__linear-server__create_attachment` to attach it to the Linear ticket after creation
- **Pasted images in conversation** — describe what the image shows in the ticket description and note that a screenshot was provided. You cannot upload binary data directly.
Always mention in the description when visual evidence was provided, even if it cannot be directly embedded.
#### Priority
| Value | Level | When to use |
|-------|----------|-------------|
| 4 | Low | Nice-to-have, no user impact |
| 3 | Normal | Default — standard planned work |
| 2 | High | Blocks other work or affects users significantly |
| 1 | Urgent | Production-breaking, security vulnerability, data loss |
| 0 | None | Not yet assessed |
**Guardrails:**
- **Default to Normal (3)** unless the user explicitly states otherwise
- **Never set Urgent (1)** unless the user explicitly says "urgent", "P0", "production down", or "security vulnerability"
- **Never set None (0)** — always make a priority assessment. If unsure, use Normal (3)
#### Status
**Guardrails:**
- **Never create issues in Triage status** — Triage is for externally-reported issues that enter through automated pipelines (GitHub sync, support escalation). Agent-created tickets have known context and should skip triage
- **Default to Backlog** — use this when the issue is acknowledged but not yet planned for a sprint
- **Use Todo** only when the user indicates the work is planned for the current cycle or should be picked up soon
- **Never set In Progress, Review, or Done** at creation time
#### Team
- **Try to fetch up-to-date team areas of responsibility from Notion** using `mcp__notion__notion-search` (search for "areas of responsibility" or similar). Use the fetched data to determine the best team for the issue.
- **If Notion MCP is unavailable or the lookup fails**, fall back to these common teams: `Engineering` (N8N), `AI`, `NODES`, `Identity & Access` (IAM), `Catalysts` (CAT), `Lifecycle & Governance` (LIGO), `Cloud Platform`, `Docs` (DOC)
- **Always ask the user which team** if not obvious from context or the Notion lookup
- If the issue is node-specific, it likely belongs to `NODES`
- If it involves AI/LangChain nodes, it likely belongs to `AI`
#### Labels
Apply labels from these groups as appropriate:
**Type (pick one):**
- `bug` — something is broken
- `feature` — net-new capability
- `enhancement` — improvement to existing functionality
- `tech debt` — internal quality improvement
- `spike` — time-boxed investigation
- `doc` — documentation-only change
**Area (pick if applicable):**
- `frontend`, `backend`, `performance`, `testing`, `infra`, `DX`, `Security-Team`
**Source (pick if applicable):**
- `Internal` — created by team members
- `GitHub` — originated from a GitHub issue
- `Sentry` — originated from error monitoring
- `Zammad` — originated from support
**Bucket (pick if applicable):**
- Use the relevant feature-area bucket (e.g., `Credentials`, `Canvas/Node`, `RBAC`, `LangChain nodes`, `Form Trigger`, etc.)
**Guardrails:**
- **Always apply a type label** — every ticket needs at least a type
- **Do not apply triage-state labels** (`Triage: Pending`, `Triage: Complete`, etc.) — these are managed by triage automation
- **Do not apply release labels** (`n8n@1.36.0`, etc.) — these are managed by release automation
- **Do not apply `docs-automation` labels** — these are managed by docs automation
#### Estimates
Only set an estimate if the user provides one or explicitly asks for one. Use t-shirt sizes:
| Size | Value | Approximate effort |
|------|-------|--------------------|
| XS | 1 | ≤ 1 hour |
| S | 2 | ≤ 1 day |
| M | 3 | 23 days |
| L | 4 | 35 days |
| XL | 5 | ≥ 6 days |
### Creating the Ticket
1. **Gather required fields** — if any are missing, ask the user:
- Title
- Team
- Description (draft one from the user's input using the templates above)
2. **Present a preview** before creating — show the user:
- Title
- Team
- Status
- Priority
- Labels
- Description (abbreviated if long)
3. **Wait for user confirmation** — do not create until the user approves
4. **Create the ticket** using `mcp__linear-server__save_issue`:
```
title: <title>
team: <team name>
description: <markdown description>
priority: <priority number>
state: <status name>
labels: [<label names>]
```
5. **Report back** with the issue identifier and URL
### Things to Never Do (Linear)
- Never create issues in **Triage** status
- Never set **Urgent** priority without explicit user instruction
- Never apply **triage-state**, **release**, or **docs-automation** labels
- Never set **assignee** unless the user explicitly asks
- Never set a **cycle** or **milestone** unless the user explicitly asks
- Never create **duplicate issues** — if the user describes something that sounds like it may exist, search first with `mcp__linear-server__list_issues`
---
## GitHub Issues
### Prerequisites
Verify `gh` CLI is authenticated: `gh auth status`
### Important Context
The n8n GitHub issue tracker (`n8n-io/n8n`) is **bug-only**. Feature requests and questions are redirected to the [community forum](https://community.n8n.io). Blank issues are disabled — the bug template must be used.
### Style Guide
#### Title
- **Sentence case** — same as Linear
- **Descriptive of the symptom** — what is broken, not what you want
- **No prefixes required** — do not add "Bug:" or "Bug Report:" (the template handles categorization)
- **No trailing punctuation**
#### Body
GitHub issues **must** follow the bug report template structure:
```markdown
### Bug Description
[Clear explanation of the bug]
### Steps to Reproduce
1. [Step 1]
2. [Step 2]
3. [Step 3]
### Expected Behavior
[What should happen]
### Debug Info
[If available — output from Help > About n8n > Copy debug information]
### Operating System
[e.g., macOS 14.2, Ubuntu 22.04]
### n8n Version
[e.g., 1.72.1]
### Node.js Version
[e.g., 20.11.0]
### Database
SQLite / PostgreSQL
### Execution Mode
main / queue
### Hosting
n8n cloud / self hosted
```
**Guardrails:**
- **Always include reproduction steps** — issues without them get closed as `closed:incomplete-template`
- **Include debug info if available** — this is critical for triage
- **Never file feature requests as GitHub issues** — redirect the user to the community forum or suggest creating a Linear ticket instead
#### Labels
Do **not** manually apply labels when creating GitHub issues. The triage automation handles labeling:
- `triage:pending` is auto-applied
- `status:in-linear` is auto-applied when synced
### Creating the Issue
1. **Verify it's a bug** — if the user describes a feature request, inform them that GitHub issues are bug-only and suggest alternatives (Linear ticket or community forum)
2. **Draft the issue** using the template above, filling in fields from the user's input
3. **Present a preview** before creating — show the user:
- Title
- Body (abbreviated if long)
- Repository (default: `n8n-io/n8n`)
4. **Wait for user confirmation**
5. **Create the issue** using `gh`:
```bash
gh issue create --repo n8n-io/n8n --title "<title>" --body "$(cat <<'EOF'
<body content>
EOF
)"
```
6. **Report back** with the issue number and URL
### Things to Never Do (GitHub)
- Never file **feature requests** as GitHub issues
- Never create issues **without reproduction steps**
- Never manually apply **labels** — let automation handle it
- Never create issues in **repositories other than n8n-io/n8n** unless the user explicitly specifies
---
## Cross-Linking
When both a Linear ticket and GitHub issue exist for the same problem:
- **Linear → GitHub**: Add the GitHub issue URL as a link attachment on the Linear ticket
- **GitHub → Linear**: Add `https://linear.app/n8n/issue/<TICKET-ID>` in the GitHub issue body
If the user creates one and mentions the other exists, offer to add the cross-link.

View file

@ -0,0 +1,192 @@
---
description: Creates GitHub pull requests with properly formatted titles that pass the check-pr-title CI validation. Use when creating PRs, submitting changes for review, or when the user says /pr or asks to create a pull request.
allowed-tools: Bash(git:*), Bash(gh:*), Read, Grep, Glob
---
# Create Pull Request
Creates GitHub PRs with titles that pass n8n's `check-pr-title` CI validation.
## PR Title Format
```
<type>(<scope>): <summary>
```
### Types (required)
| Type | Description | Changelog |
|------------|--------------------------------------------------|-----------|
| `feat` | New feature | Yes |
| `fix` | Bug fix | Yes |
| `perf` | Performance improvement | Yes |
| `test` | Adding/correcting tests | No |
| `docs` | Documentation only | No |
| `refactor` | Code change (no bug fix or feature) | No |
| `build` | Build system or dependencies | No |
| `ci` | CI configuration | No |
| `chore` | Routine tasks, maintenance | No |
### Scopes (optional but recommended)
- `API` - Public API changes
- `benchmark` - Benchmark CLI changes
- `core` - Core/backend/private API
- `editor` - Editor UI changes
- `* Node` - Specific node (e.g., `Slack Node`, `GitHub Node`)
### Summary Rules
- Use imperative present tense: "Add" not "Added"
- Capitalize first letter
- No period at the end
- No ticket IDs (e.g., N8N-1234)
- Add `(no-changelog)` suffix to exclude from changelog
## Steps
1. **Check current state**:
```bash
git status
git diff --stat
git log origin/master..HEAD --oneline
```
2. **Check for implementation plan**: Look for a plan file in `.claude/plans/`
that matches the current branch's ticket ID (e.g. if branch is
`scdekov/PAY-1234-some-feature`, check for `.claude/plans/PAY-1234.md`).
If a plan file exists, ask the user whether they want to include it in the
PR description as a collapsible `<details>` section (see Plan Section below).
Only include the plan if the user explicitly approves.
3. **If this is a security fix**, audit every public-facing artifact before
proceeding (see Security Fixes below).
4. **Analyze changes** to determine:
- Type: What kind of change is this?
- Scope: Which package/area is affected?
- Summary: What does the change do?
5. **Push branch if needed**:
```bash
git push -u origin HEAD
```
6. **Create PR** using gh CLI. Read `.github/pull_request_template.md` as the
body structure, then populate each section with actual content before
creating the PR:
- **Summary**: describe what the PR does and how to test it
- **Related tickets**: add the Linear ticket URL (`https://linear.app/n8n/issue/[TICKET-ID]`) and any GitHub issue links
- **Checklist**: keep as-is from the template
- Add a "🤖 PR Summary generated by AI" at the end of the body
```bash
gh pr create --draft --title "<type>(<scope>): <summary>" --body "$(cat <<'EOF'
<populated body based on pull_request_template.md>
EOF
)"
```
## PR Body Guidelines
Based on `.github/pull_request_template.md`:
### Summary Section
- Describe what the PR does
- Explain how to test the changes
- Include screenshots/videos for UI changes
### Related Links Section
- Link to Linear ticket: `https://linear.app/n8n/issue/[TICKET-ID]`
- Link to GitHub issues using keywords to auto-close:
- `closes #123` / `fixes #123` / `resolves #123`
- Link to Community forum posts if applicable
### Checklist
All items should be addressed before merging:
- The human author of the PR has checked the "I have seen this code, I have run this code, and I take responsibility for this code." checkbox
- PR title follows conventions
- Docs updated or follow-up ticket created
- Tests included (bugs need regression tests, features need coverage)
- `release/backport` label added if urgent fix needs backporting
## Examples
### Feature in editor
```
feat(editor): Add workflow performance metrics display
```
### Bug fix in core
```
fix(core): Resolve memory leak in execution engine
```
### Node-specific change
```
fix(Slack Node): Handle rate limiting in message send
```
### Breaking change (add exclamation mark before colon)
```
feat(API)!: Remove deprecated v1 endpoints
```
### No changelog entry
```
refactor(core): Simplify error handling (no-changelog)
```
### No scope (affects multiple areas)
```
chore: Update dependencies to latest versions
```
## Validation
The PR title must match this pattern:
```
^(feat|fix|perf|test|docs|refactor|build|ci|chore|revert)(\([a-zA-Z0-9 ]+( Node)?\))?!?: [A-Z].+[^.]$
```
Key validation rules:
- Type must be one of the allowed types
- Scope is optional but must be in parentheses if present
- Exclamation mark for breaking changes goes before the colon
- Summary must start with capital letter
- Summary must not end with a period
## Plan Section
If a matching plan file was found in `.claude/plans/` and the user has approved
including it, add a collapsible section at the end of the PR body (after the
checklist, before `EOF`):
```markdown
<details>
<summary>Implementation plan</summary>
<!-- paste plan file contents here -->
</details>
```
## Security Fixes
**This repo is public.** Never expose the attack vector in any public artifact.
Describe **what the code does**, not what threat it prevents.
| Artifact | BAD | GOOD |
|---|---|---|
| Branch | `fix-sql-injection-in-webhook` | `fix-webhook-input-validation` |
| PR title | `fix(core): Prevent SSRF` | `fix(core): Validate outgoing URLs` |
| Commit msg | `fix: prevent denial of service` | `fix: add payload size validation` |
| PR body | *"attacker could trigger SSRF…"* | *"validates URL protocol and host"* |
| Linear ref | URL with slug (leaks title) | URL without slug or ticket ID only |
| Test name | `'should prevent SQL injection'` | `'should sanitize query parameters'` |
**Before pushing a security fix, verify:** no branch name, commit, PR title,
PR body, Linear URL, test name, or code comment hints at the vulnerability.
**When in doubt, check the Linear issue for possible extra precautions**

View file

@ -0,0 +1,126 @@
---
description: >-
Guides users through creating effective Agent Skills. Use when you want to
create, write, or author a new skill, or asks about skill structure, best
practices, or SKILL.md format.
---
# Creating skills
Skills are markdown (plus optional scripts) that teach the agent a focused workflow. **Keep SKILL.md short**—the context window is shared with chat, code, and other skills.
## Where skills live
| Location | When to use |
|----------|-------------|
| **`.claude/plugins/n8n/skills/<name>/`** | Default for n8n: team-shared, versioned, namespaced under `n8n:`. |
| `~/.claude/skills/<name>/` | Personal skill for Claude Code across all projects. |
| `~/.cursor/skills/<name>/` | Optional personal skill for Cursor only, global to your machine. |
**Do not** put custom skills in `~/.cursor/skills-cursor/`—that is reserved for Cursors built-in skills.
Prefer **plugin `.claude/plugins/n8n/skills/`** for anything that should match how the rest of the team works.
## Before you write: gather requirements
Ask (or infer) briefly:
1. **Purpose** — one concrete task or workflow.
2. **Triggers** — when should the agent apply this skill?
3. **Gaps** — what does the agent *not* already know (project rules, URLs, formats)?
4. **Outputs** — templates, checklists, or strict formats?
5. **Examples** — follow an existing skill in `.claude/plugins/n8n/skills/` if one fits.
Ask the user in plain language when you need more detail.
## File layout
```
skill-name/
├── SKILL.md # required
├── reference.md # optional — detail the agent reads only if needed
├── examples.md # optional
└── scripts/ # optional
```
### Frontmatter (required)
```yaml
---
name: skill-name # lowercase, hyphens, max 64 chars
description: >- # max 1024 chars, non-empty — see below
...
---
```
**Description** (discovery is everything — third person, WHAT + WHEN, trigger words):
- Good: `Extracts tables from PDFs and fills forms. Use when the user works with PDFs, forms, or document extraction.`
- Bad: `Helps with documents` or `I can help you with PDFs`
## Authoring rules
1. **Concise** — assume the model is capable; only add non-obvious domain or project facts.
2. **Progressive disclosure** — essentials in `SKILL.md`; long reference in `reference.md`. Link **one level deep** from `SKILL.md`.
3. **Prefer one default** — e.g. one library or one workflow; add an escape hatch only if needed.
4. **Stable wording** — one term per concept; avoid dated “until month X” notes unless you tuck legacy bits behind a short “Deprecated” note.
5. **Paths** — forward slashes only (`scripts/foo.py`).
**Rough size:** aim for **well under ~200 lines** in `SKILL.md`; if it grows, split detail out.
### Scope: one job per skill (and parent skills)
- **Single responsibility** — one primary workflow or decision tree per skill. If triggers and steps diverge a lot (e.g. “create issue” vs “create PR” vs “full ticket → PR flow”), split into **smaller dedicated skills**.
- **Prefer small + compose** — two or three focused skills keep irrelevant detail out of context until needed. A **parent** (orchestrator) skill can say *when* to follow each child workflow and link to their `SKILL.md`; avoid pasting full child content into the parent.
- **When one large skill is OK** — a single end-to-end flow that always runs together and shares one tight checklist;
### MCPs, CLI tools, and other skills
- **Prefer CLI and repo commands** when they solve the same problem — agents handle them well and they usually add less scaffolding noise to context than MCP tool discovery and schemas. Examples: `gh` for PRs/issues, `pnpm` scripts from `AGENTS.md`.
- **MCPs are optional per user** — not everyone has the same servers enabled. If a skill **requires** a specific MCP to work as written, say so explicitly:
- Put a hint in the **frontmatter description** (e.g. “Requires Linear MCP for …”) so mismatches are obvious early.
- Add a short **Prerequisites** (or **Requirements**) block near the top: which integration, what it is used for, and a **fallback** (e.g. web UI, `gh`, or “ask the user to paste …”) when it is missing.
- **Referencing other skills** — use the namespaced invocation name (e.g. `n8n:create-issue`) so the agent resolves the plugin skill. For human-readable links, give the path from the repo root (e.g. `.claude/plugins/n8n/skills/create-issue/SKILL.md`). From a sibling folder, a relative link works too: `[create-issue](../create-issue/SKILL.md)`. Parent skills should delegate steps instead of duplicating long procedures.
## Patterns (pick what fits)
- **Template** — give the exact output shape (markdown/code blocks).
- **Checklist** — numbered or `- [ ]` steps for multi-step work.
- **Branching** — “If A → …; if B → …” at the top of a workflow.
- **Scripts** — document run commands; say whether to **execute** or **read** the script.
## Workflow: create → verify
1. **Name + description** — hyphenated name; description with triggers.
2. **Outline** — minimal sections; link optional files.
3. **Implement**`SKILL.md` first; add `reference.md` / `scripts/` only if they save tokens or reduce errors.
4. **Check** — third-person description; terminology consistent; no duplicate encyclopedic content the model already knows.
## Anti-patterns
- Verbose tutorials (“what is a PDF”) inside the skill.
- Many equivalent options with no default.
- Vague names (`helper`, `utils`).
- Deep chains of linked files.
- Assuming an MCP or tool is present without stating it or offering a fallback.
- One oversized skill that mixes unrelated workflows instead of smaller skills + a thin parent.
## Quick example stub
```markdown
---
name: my-workflow
description: Does X using project convention Y. Use when the user asks for X or mentions Z.
---
# My workflow
1. …
2. …
## Output format
Use a fenced code block for the exact shape reviewers should see.
## More detail
See [reference.md](reference.md) if edge cases matter.
```

View file

@ -0,0 +1,198 @@
---
description: Fetch and analyze Linear issue with all related context. Use when starting work on a Linear ticket, analyzing issues, or gathering context about a Linear issue.
disable-model-invocation: true
argument-hint: "[issue-id]"
compatibility:
requires:
- mcp: linear
description: Core dependency — used to fetch issue details, relations, and comments
- cli: gh
description: GitHub CLI — used to fetch linked PRs and issues. Must be authenticated (gh auth login)
optional:
- mcp: notion
description: Used to fetch linked Notion documents. Skip Notion steps if unavailable.
- skill: loom-transcript
description: Used to fetch Loom video transcripts. Skip Loom steps if unavailable.
- cli: curl
description: Used to download images/attachments. Typically pre-installed.
---
# Linear Issue Analysis
Start work on Linear issue **$ARGUMENTS**
## Prerequisites
This skill depends on external tools. Before proceeding, verify availability:
**Required:**
- **Linear MCP** (`mcp__linear`): Must be connected. Without it the skill cannot function at all.
- **GitHub CLI** (`gh`): Must be installed and authenticated. Run `gh auth status` to verify. Used to fetch linked PRs and issues.
**Optional (graceful degradation):**
- **Notion MCP** (`mcp__notion`): Needed only if the issue links to Notion docs. If unavailable, note the Notion links in the summary and tell the user to check them manually.
- **Loom transcript skill** (`/loom-transcript`): Needed only if the issue contains Loom videos. If unavailable, note the Loom links in the summary for the user to watch.
- **curl**: Used to download images. Almost always available; if missing, skip image downloads and note it.
If a required tool is missing, stop and tell the user what needs to be set up before continuing.
## Instructions
Follow these steps to gather comprehensive context about the issue:
### 1. Fetch the Issue and Comments from Linear
Use the Linear MCP tools to fetch the issue details and comments together:
- Use `mcp__linear__get_issue` with the issue ID to get full details including attachments
- Include relations to see blocking/related/duplicate issues
- **Immediately after**, use `mcp__linear__list_comments` with the issue ID to fetch all comments
Both calls should be made together in the same step to gather the complete context upfront.
### 2. Check for Private/Security Issues (MANDATORY — do this before anything else)
After fetching the issue, immediately check its labels:
1. Look at the labels returned with the issue.
2. If any label is **`n8n-private`**:
a. Run `git remote -v` (via Bash) to list all configured remotes.
b. If **any** remote URL contains `n8n-io/n8n` without the `-private` suffix (i.e. matches the public repo), **stop immediately** and tell the user:
> **This issue is marked `n8n-private` and must be developed in a clean clone of the private repository.**
>
> One or more of your remotes point to the **public** `n8n-io/n8n` repo. Mixed remotes are not allowed — you must work in a **separate local clone** of `n8n-io/n8n-private` with no references to the public repo.
> For the full process, see: https://www.notion.so/n8n/Processing-critical-high-security-bugs-vulnerabilities-in-private-2f45b6e0c94f803da806f472111fb1a5
Do **not** continue with any further steps — return after showing this message.
3. If the label is not present, or all remotes point exclusively to `n8n-io/n8n-private`, continue normally.
### 3. Analyze Attachments and Media (MANDATORY)
**IMPORTANT:** This step is NOT optional. You MUST scan and fetch all visual content from BOTH the issue description AND all comments.
**Screenshots/Images (ALWAYS fetch):**
1. Scan the issue description AND all comments for ALL image URLs:
- `<img>` tags
- Markdown images `![](url)`
- Raw URLs (github.com/user-attachments, imgur.com, etc.)
2. For EACH image found (in description or comments):
- Download using `curl -sL "url" -o /path/to/image.png` (GitHub URLs require following redirects) OR the linear mcp
- Use the `Read` tool on the downloaded file to view it
- Describe what you see in detail
3. Do NOT skip images - they often contain critical context like error messages, UI states, or configuration
**Loom Videos (ALWAYS fetch transcript):**
1. Scan the issue description AND all comments for Loom URLs (loom.com/share/...)
2. For EACH Loom video found (in description or comments):
- Use the `/loom-transcript` skill to fetch the FULL transcript
- Summarize key points, timestamps, and any demonstrated issues
3. Loom videos often contain crucial reproduction steps and context that text alone cannot convey
### 4. Fetch Related Context
**Related Linear Issues:**
- Use `mcp__linear__get_issue` for any issues mentioned in relations (blocking, blocked by, related, duplicates)
- Summarize how they relate to the main issue
**GitHub PRs and Issues:**
- If GitHub links are mentioned, use `gh` CLI to fetch PR/issue details:
- `gh pr view <number>` for pull requests
- `gh issue view <number>` for issues
- Download images attached to issues: `curl -H "Authorization: token $(gh auth token)" -L <image-url> -o image.png`
**Notion Documents:**
- If Notion links are present, use `mcp__notion__notion-fetch` with the Notion URL or page ID to retrieve document content
- Summarize relevant documentation
### 5. Review Comments
Comments were already fetched in Step 1. Review them for:
- Additional context and discussion history
- Any attachments or media linked in comments (process in Step 3)
- Clarifications or updates to the original issue description
### 6. Identify Affected Node (if applicable)
Determine whether this issue is specific to a particular n8n node (e.g. a trigger, action, or tool node). Look for clues in:
- The issue title (e.g. "Linear trigger", "Slack node", "HTTP Request")
- The issue description and comments mentioning node names
- Labels or tags on the issue (e.g. `node:linear`, `node:slack`)
- Screenshots showing a specific node's configuration or error
If the issue is node-specific:
1. **Find the node type ID.** Use `Grep` to search for the node's display name (or keywords from it) in `packages/frontend/editor-ui/data/node-popularity.json` to find the exact node type ID. For reference, common ID patterns are:
- Core nodes: `n8n-nodes-base.<camelCaseName>` (e.g. "HTTP Request" → `n8n-nodes-base.httpRequest`)
- Trigger variants: `n8n-nodes-base.<name>Trigger` (e.g. "Gmail Trigger" → `n8n-nodes-base.gmailTrigger`)
- Tool variants: `n8n-nodes-base.<name>Tool` (e.g. "Google Sheets Tool" → `n8n-nodes-base.googleSheetsTool`)
- LangChain/AI nodes: `@n8n/n8n-nodes-langchain.<camelCaseName>` (e.g. "OpenAI Chat Model" → `@n8n/n8n-nodes-langchain.lmChatOpenAi`)
2. **Look up the node's popularity score** — first check for a Flaky assessment (see below), otherwise use the popularity file:
**Primary: Check for Flaky's assessment in Linear comments.** Flaky is an auto-triage agent that posts issue analysis as a comment. Search the comments already fetched in Step 1 for a comment from a user named "Flaky" (or containing "Flaky" in the author name) — do not re-fetch comments. If found, extract the popularity score and level directly from Flaky's analysis and use those values.
**Fallback (if no Flaky comment exists):** Look up the node's popularity score from `packages/frontend/editor-ui/data/node-popularity.json`. Use `Grep` to search for the node ID in that file. The popularity score is a log-scale value between 0 and 1. Use these thresholds to classify:
| Score | Level | Description | Examples |
|-------|-------|-------------|----------|
| ≥ 0.8 | **High** | Core/widely-used nodes, top ~5% | HTTP Request (0.98), Google Sheets (0.95), Postgres (0.83), Gmail Trigger (0.80) |
| 0.40.8 | **Medium** | Regularly used integrations | Slack (0.78), GitHub (0.64), Jira (0.65), MongoDB (0.63) |
| < 0.4 | **Low** | Niche or rarely used nodes | Amqp (0.34), Wise (0.36), CraftMyPdf (0.33) |
Include the raw score and the level (high/medium/low) in the summary, and note whether it came from Flaky or the popularity file.
3. If the node is **not found** in the popularity file (and no Flaky comment exists), note that it may be a community node or a very new/niche node.
### 7. Assess Effort/Complexity
**Primary: Check for Flaky's effort estimate in Linear comments.** Search the comments already fetched in Step 1 for a Flaky comment — do not re-fetch. If found, extract the effort/complexity estimate directly from it and use that as your assessment.
**Fallback (if no Flaky comment exists):** After gathering all context, assess the effort required to fix/implement the issue. Use the following T-shirt sizes:
| Size | Approximate effort |
|------|--------------------|
| XS | ≤ 1 hour |
| S | ≤ 1 day |
| M | 2-3 days |
| L | 3-5 days |
| XL | ≥ 6 days |
To make this assessment, consider:
- **Scope of changes**: How many files/packages need to be modified? Is it a single node fix or a cross-cutting change?
- **Complexity**: Is it a straightforward parameter change, a new API integration, a new credential type, or an architectural change?
- **Testing**: How much test coverage is needed? Are E2E tests required?
- **Risk**: Could this break existing functionality? Does it need backward compatibility?
- **Dependencies**: Are there external API changes, new packages, or cross-team coordination needed?
- **Documentation**: Does this require docs updates, migration guides, or changelog entries?
Provide the T-shirt size along with a brief justification explaining the key factors that drove the estimate. Note whether it came from Flaky or your own assessment.
### 8. Present Summary
**Before presenting, verify you have completed:**
- [ ] Downloaded and viewed ALL images in the description AND comments
- [ ] Fetched transcripts for ALL Loom videos in the description AND comments
- [ ] Fetched ALL linked GitHub issues/PRs via `gh` CLI
- [ ] Listed all comments on the issue
- [ ] Checked whether the issue is node-specific and looked up popularity if so
- [ ] Assessed effort/complexity with T-shirt size
After gathering all context, present a comprehensive summary including:
1. **Issue Overview**: Title, status, priority, assignee, labels
2. **Description**: Full issue description with any clarifications from comments
3. **Visual Context**: Summary of screenshots/videos (what you observed in each)
4. **Affected Node** (if applicable): Node name, node type ID (`n8n-nodes-base.xxx`), popularity score with level (e.g. `0.64 — medium popularity`)
5. **Related Issues**: How this connects to other work
6. **Technical Context**: Any PRs, code references, or documentation
7. **Effort Estimate**: T-shirt size (XS/S/M/L/XL) with justification
8. **Next Steps**: Suggested approach based on all gathered context
## Notes
- The issue ID can be provided in formats like: `AI-1975`, `node-1975`, or just `1975` (will search)
- If no issue ID is provided, ask the user for one

View file

@ -0,0 +1,104 @@
---
description: Fetch and display the full transcript from a Loom video URL. Use when the user wants to get or read a Loom transcript.
argument-hint: [loom-url]
---
# Loom Transcript Fetcher
Fetch the transcript from a Loom video using Loom's GraphQL API.
## Instructions
Given the Loom URL: $ARGUMENTS
### 1. Extract the Video ID
Parse the Loom URL to extract the 32-character hex video ID. Supported URL formats:
- `https://www.loom.com/share/<video-id>`
- `https://www.loom.com/embed/<video-id>`
- `https://www.loom.com/share/<video-id>?sid=<session-id>`
The video ID is the 32-character hex string after `/share/` or `/embed/`.
### 2. Fetch Video Metadata
Use the `WebFetch` tool to POST to `https://www.loom.com/graphql` to get the video title and details.
Use this curl command via Bash:
```bash
curl -s 'https://www.loom.com/graphql' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'x-loom-request-source: loom_web_45a5bd4' \
-H 'apollographql-client-name: web' \
-H 'apollographql-client-version: 45a5bd4' \
-d '{
"operationName": "GetVideoSSR",
"variables": {"id": "<VIDEO_ID>", "password": null},
"query": "query GetVideoSSR($id: ID!, $password: String) { getVideo(id: $id, password: $password) { ... on RegularUserVideo { id name description createdAt owner { display_name } } } }"
}'
```
### 3. Fetch the Transcript URLs
Use curl via Bash to call the GraphQL API:
```bash
curl -s 'https://www.loom.com/graphql' \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-H 'x-loom-request-source: loom_web_45a5bd4' \
-H 'apollographql-client-name: web' \
-H 'apollographql-client-version: 45a5bd4' \
-d '{
"operationName": "FetchVideoTranscript",
"variables": {"videoId": "<VIDEO_ID>", "password": null},
"query": "query FetchVideoTranscript($videoId: ID!, $password: String) { fetchVideoTranscript(videoId: $videoId, password: $password) { ... on VideoTranscriptDetails { id video_id source_url captions_source_url } ... on GenericError { message } } }"
}'
```
Replace `<VIDEO_ID>` with the actual video ID extracted in step 1.
The response contains:
- `source_url` — JSON transcript URL
- `captions_source_url` — VTT (WebVTT) captions URL
### 4. Download and Parse the Transcript
Fetch **both** URLs returned from step 3 (if available):
1. **VTT captions** (`captions_source_url`): Download with `curl -sL "<url>"`. This is a WebVTT file with timestamps and text.
2. **JSON transcript** (`source_url`): Download with `curl -sL "<url>"`. This is a JSON file with transcript segments.
Prefer the VTT captions as the primary source since they include proper timestamps. Fall back to the JSON transcript if VTT is unavailable.
### 5. Present the Transcript
Format and present the full transcript to the user:
**Video:** [Title from metadata]
**Author:** [Owner name]
**Date:** [Created date]
---
**0:00** - First transcript segment text...
**0:14** - Second transcript segment text...
(continue for all segments)
---
## Error Handling
- If the GraphQL response contains a `GenericError`, report the error message to the user.
- If both `source_url` and `captions_source_url` are null/missing, tell the user that no transcript is available for this video.
- If the video URL is invalid or the ID cannot be extracted, ask the user for a valid Loom URL.
## Notes
- No authentication or cookies are required — Loom's transcript API is publicly accessible.
- Only English transcripts are available through this API.
- Transcripts are auto-generated and may contain minor errors.

View file

@ -0,0 +1,321 @@
---
description: Add OAuth2 credential support to an existing n8n node — creates the credential file, updates the node, adds tests, and keeps the CLI constant in sync. Use when the user says /node-add-oauth.
argument-hint: "[node-name] [optional: custom-scopes flag or scope list]"
---
## Overview
Add OAuth2 (Authorization Code / 3LO) support to an existing n8n node. Works for any
third-party service that supports standard OAuth2.
Before starting, read comparable existing OAuth2 credential files and tests under
`packages/nodes-base/credentials/` to understand the conventions used in this codebase
(e.g. `DiscordOAuth2Api.credentials.ts`, `MicrosoftTeamsOAuth2Api.credentials.ts`).
---
## Step 0 — Parse arguments
Extract:
- `NODE_NAME`: the service name (e.g. `GitHub`, `Notion`). Try to infer from the argument;
if ambiguous, ask the user.
- `CUSTOM_SCOPES`: whether the credential should support user-defined scopes. If the
argument does not make this clear, **ask the user** before proceeding:
> "Should users be able to customise the OAuth2 scopes for this credential, or should
> scopes be fixed?"
---
## Step 1 — Explore the node
Read the following (adjust path conventions for the specific service):
1. Node directory: `packages/nodes-base/nodes/{NODE_NAME}/`
- Find `*.node.ts` (main node) and any `*Trigger.node.ts`
- Find `GenericFunctions.ts` (may be named differently)
- Check if an `auth` / `version` subdirectory exists
2. Existing credentials: `packages/nodes-base/credentials/` — look for existing
`{NODE_NAME}*Api.credentials.ts` files to understand the naming convention and any
auth method already in use.
3. `package.json` at `packages/nodes-base/package.json` — find where existing credentials
for this node are registered (grep for the node name).
---
## Step 2 — Research OAuth2 endpoints
Look up the service's OAuth2 documentation:
- Authorization URL
- Access Token URL
- Required auth query parameters (e.g. `prompt=consent`, `access_type=offline`)
- Default scopes needed for the node's existing operations
- Whether the API requires a cloudId / workspace ID lookup after the token exchange
(Atlassian-style gateway APIs do; most services don't)
If you can't determine the endpoints confidently, ask the user to provide them.
---
## Step 3 — Create the credential file
File: `packages/nodes-base/credentials/{NODE_NAME}OAuth2Api.credentials.ts`
```typescript
import type { ICredentialType, INodeProperties } from 'n8n-workflow';
const defaultScopes = [/* minimum scopes for existing node operations */];
export class {NODE_NAME}OAuth2Api implements ICredentialType {
name = '{camelCase}OAuth2Api';
extends = ['oAuth2Api'];
displayName = '{Display Name} OAuth2 API';
documentationUrl = '{doc-slug}'; // matches docs.n8n.io/integrations/...
properties: INodeProperties[] = [
// Include service-specific fields the node needs to construct API calls
// (e.g. domain, workspace URL) — add BEFORE the hidden fields below.
{ displayName: 'Grant Type', name: 'grantType', type: 'hidden', default: 'authorizationCode' },
{ displayName: 'Authorization URL', name: 'authUrl', type: 'hidden', default: '{AUTH_URL}', required: true },
{ displayName: 'Access Token URL', name: 'accessTokenUrl', type: 'hidden', default: '{TOKEN_URL}', required: true },
// Only include authQueryParameters if the service requires extra query params:
{ displayName: 'Auth URI Query Parameters', name: 'authQueryParameters', type: 'hidden', default: '{QUERY_PARAMS}' },
{ displayName: 'Authentication', name: 'authentication', type: 'hidden', default: 'header' },
// ── Custom scopes block (ONLY when CUSTOM_SCOPES = yes) ──────────────
{
displayName: 'Custom Scopes',
name: 'customScopes',
type: 'boolean',
default: false,
description: 'Define custom scopes',
},
{
displayName:
'The default scopes needed for the node to work are already set. If you change these the node may not function correctly.',
name: 'customScopesNotice',
type: 'notice',
default: '',
displayOptions: { show: { customScopes: [true] } },
},
{
displayName: 'Enabled Scopes',
name: 'enabledScopes',
type: 'string',
displayOptions: { show: { customScopes: [true] } },
default: defaultScopes.join(' '),
description: 'Scopes that should be enabled',
},
// ── End custom scopes block ───────────────────────────────────────────
{
displayName: 'Scope',
name: 'scope',
type: 'hidden',
// Custom scopes: expression toggles between user value and defaults.
// Fixed scopes: use the literal defaultScopes string instead.
default:
'={{$self["customScopes"] ? $self["enabledScopes"] : "' + defaultScopes.join(' ') + '"}}',
},
];
}
```
**Rules:**
- No `authenticate` block — `oAuth2Api` machinery handles Bearer token injection automatically.
- No `test` block — the OAuth dance validates the credential.
- `defaultScopes` at module level is the single source of truth: it populates both the
`enabledScopes` default and the `scope` expression fallback. Update it in one place.
- If the service needs a domain / workspace URL for API call construction, add it as a
visible `string` field **before** the hidden fields.
---
## Step 4 — Register the credential in `package.json`
File: `packages/nodes-base/package.json`
Find the `n8n.credentials` array and insert the new entry near other credentials for this
service (alphabetical ordering within the service's block):
```json
"dist/credentials/{NODE_NAME}OAuth2Api.credentials.js",
```
---
## Step 5 — Update `GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE` (custom scopes only)
**Only do this step when CUSTOM_SCOPES = yes.**
File: `packages/cli/src/constants.ts`
Add `'{camelCase}OAuth2Api'` to the `GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE`
array. Without this, n8n deletes the user's custom scope on OAuth2 reconnect.
```typescript
export const GENERIC_OAUTH2_CREDENTIALS_WITH_EDITABLE_SCOPE = [
'oAuth2Api',
'googleOAuth2Api',
'microsoftOAuth2Api',
'highLevelOAuth2Api',
'mcpOAuth2Api',
'{camelCase}OAuth2Api', // ← add this
];
```
---
## Step 6 — Update `GenericFunctions.ts`
### 6a — Standard services (token works directly against the instance URL)
Add an `else if` branch before the existing `else` fallback:
```typescript
} else if ({versionParam} === '{camelCase}OAuth2') {
domain = (await this.getCredentials('{camelCase}OAuth2Api')).{domainField} as string;
credentialType = '{camelCase}OAuth2Api';
} else {
```
### 6b — Gateway services requiring a workspace/cloud ID lookup
When the OAuth token is scoped for a gateway URL rather than the direct instance URL
(Atlassian's `api.atlassian.com` is the canonical example), add a module-level cache and
lookup helper **before** the main request function:
```typescript
// Module-level cache: normalised domain → site/cloud ID
export const _cloudIdCache = new Map<string, string>();
async function getSiteId(
this: IHookFunctions | IExecuteFunctions | ILoadOptionsFunctions,
credentialType: string,
domain: string,
): Promise<string> {
const normalizedDomain = domain.replace(/\/$/, '');
if (_cloudIdCache.has(normalizedDomain)) return _cloudIdCache.get(normalizedDomain)!;
const resources = (await this.helpers.requestWithAuthentication.call(this, credentialType, {
uri: '{ACCESSIBLE_RESOURCES_ENDPOINT}',
json: true,
})) as Array<{ id: string; url: string }>;
const site = resources.find((r) => r.url === normalizedDomain);
if (!site) {
throw new NodeOperationError(
this.getNode(),
`No accessible site found for domain: ${domain}. Make sure the domain matches your site URL exactly.`,
);
}
_cloudIdCache.set(normalizedDomain, site.id);
return site.id;
}
```
Then in the main request function:
```typescript
} else if ({versionParam} === '{camelCase}OAuth2') {
const rawDomain = (await this.getCredentials('{camelCase}OAuth2Api')).domain as string;
credentialType = '{camelCase}OAuth2Api';
const siteId = await getSiteId.call(this, credentialType, rawDomain);
domain = `{GATEWAY_BASE_URL}/${siteId}`;
} else {
```
The existing `uri: \`${domain}/rest${endpoint}\`` construction then produces the correct
gateway URL automatically.
Add `NodeOperationError` to the `n8n-workflow` import if not already present.
---
## Step 7 — Update the node file(s)
### Main node (`*.node.ts`)
**Credentials array** — add an entry for the new credential type:
```typescript
{
name: '{camelCase}OAuth2Api',
required: true,
displayOptions: { show: { {versionParam}: ['{camelCase}OAuth2'] } },
},
```
**Version/auth options** — add to the `{versionParam}` (or equivalent) options list:
```typescript
{ name: '{Display Name} (OAuth2)', value: '{camelCase}OAuth2' },
```
Keep `default` unchanged — existing workflows must not be affected.
### Trigger node (`*Trigger.node.ts`, if present)
Same two changes. Preserve any `displayName` label pattern already used by other credential
entries in that trigger node's credentials array.
---
## Step 8 — Write credential tests
File: `packages/nodes-base/credentials/test/{NODE_NAME}OAuth2Api.credentials.test.ts`
Use `ClientOAuth2` from `@n8n/client-oauth2` and `nock` for HTTP mocking. Follow the
structure in `MicrosoftTeamsOAuth2Api.credentials.test.ts`.
Required test cases:
1. **Metadata** — name, extends array, `enabledScopes` default, auth URL, token URL,
`authQueryParameters` default (if applicable).
2. **Default scopes in authorization URI** — call `oauthClient.code.getUri()`, assert each
default scope is present.
3. **Token retrieval with default scopes** — mock the token endpoint with `nock`, call
`oauthClient.code.getToken(...)`, assert `token.data.scope` contains each scope.
4. **Custom scopes in authorization URI** _(skip when CUSTOM_SCOPES = no)_.
5. **Token retrieval with custom scopes** _(skip when CUSTOM_SCOPES = no)_.
6. **Minimal / different scope set** _(skip when CUSTOM_SCOPES = no)_ — assert scopes not
in the set are absent from both the URI and token response.
Lifecycle hooks required:
```typescript
beforeAll(() => { nock.disableNetConnect(); });
afterAll(() => { nock.restore(); });
afterEach(() => { nock.cleanAll(); });
```
---
## Step 9 — Update `GenericFunctions.test.ts`
In the credential-routing `describe` block:
1. If a site-ID cache (`_cloudIdCache`) was added, import it and call
`_cloudIdCache.clear()` (or equivalent) in `afterEach`.
2. Add/update the OAuth2 routing test case:
- **Simple routing**: assert `getCredentials` was called with the correct credential
name and `requestWithAuthentication` was called with the correct name and URI.
- **Gateway lookup**: mock `requestWithAuthentication` to return the accessible-resources
payload on the first call and `{}` on the second. Assert the first call targets the
resources endpoint and the second call uses the gateway base URL with the site ID.
---
## Step 10 — Verify
```bash
# From packages/nodes-base/
pnpm test credentials/test/{NODE_NAME}OAuth2Api.credentials.test.ts
pnpm test nodes/{NODE_NAME}/__test__/GenericFunctions.test.ts
pnpm typecheck
pnpm lint
# Only when constants.ts was changed:
pushd ../cli && pnpm typecheck && popd
```
Fix any type errors before finishing. Never skip `pnpm typecheck`.

View file

@ -0,0 +1,134 @@
---
description: Reproduce a bug from a Linear ticket with a failing test. Expects the full ticket context (title, description, comments) to be provided as input.
---
# Bug Reproduction Framework
Given a Linear ticket context ($ARGUMENTS), systematically reproduce the bug
with a failing regression test.
## Step 1: Parse Signals
Extract the following from the provided ticket context:
- **Error message / stack trace** (if provided)
- **Reproduction steps** (if provided)
- **Workflow JSON** (if attached)
- **Affected area** (node, execution engine, editor, API, config, etc.)
- **Version where it broke / last working version**
## Step 2: Route to Test Strategy
Based on the affected area, pick the test layer and pattern:
| Area | Test Layer | Pattern | Key Location |
|------|-----------|---------|--------------|
| Node operation | Jest unit | NodeTestHarness + nock | `packages/nodes-base/nodes/*/test/` |
| Node credential | Jest unit | jest-mock-extended | `packages/nodes-base/nodes/*/test/` |
| Trigger webhook | Jest unit | mock IHookFunctions + jest.mock GenericFunctions | `packages/nodes-base/nodes/*/test/` |
| Binary data | Jest unit | NodeTestHarness assertBinaryData | `packages/core/nodes-testing/` |
| Execution engine | Jest integration | WorkflowRunner + DI container | `packages/cli/src/__tests__/` |
| CLI / API | Jest integration | setupTestServer + supertest | `packages/cli/test/integration/` |
| Config | Jest unit | GlobalConfig + Container | `packages/@n8n/config/src/__tests__/` |
| Editor UI | Vitest | Vue Test Utils + Pinia | `packages/frontend/editor-ui/src/**/__tests__/` |
| E2E / Canvas | Playwright | Test containers + composables | `packages/testing/playwright/` |
## Step 3: Locate Source Files
Find the source code for the affected area:
1. Search for the node/service/component mentioned in the ticket
2. Find the GenericFunctions file (common bug location for nodes)
3. Check for existing test files in the same area
4. Look at recent git history on affected files (`git log --oneline -10 -- <path>`)
## Step 4: Trace the Code Path
Read the source code and trace the execution path that triggers the bug:
- Follow the call chain from entry point to the failure
- Identify the specific line(s) where the bug manifests
- Note any error handling (or lack thereof) around the bug
## Step 5: Form Hypothesis
State a clear, testable hypothesis:
- "When [input/condition], the code does [wrong thing] because [root cause]"
- Identify the exact line(s) that need to change
- Predict what the test output will show
## Step 6: Find Test Patterns
Look for existing tests in the same area:
1. Check `test/` directories near the affected code
2. Identify which mock/setup patterns they use
3. Use the same patterns for consistency
4. If no tests exist, find the closest similar node/service tests as a template
## Step 7: Write Failing Test
Write a regression test that:
- Uses the patterns found in Step 6
- Targets the specific hypothesis from Step 5
- Includes a comment referencing the ticket ID
- Asserts the CORRECT behavior (test will fail on current code)
- Also includes a "happy path" test to prove the setup works
## Step 8: Run and Score
Run the test from the package directory (e.g., `cd packages/nodes-base && pnpm test <file>`).
Classify the result:
| Confidence | Criteria | Output |
|------------|----------|--------|
| **CONFIRMED** | Test fails consistently, failure matches hypothesis | Reproduction Report |
| **LIKELY** | Test fails but failure mode differs slightly | Report + caveat |
| **UNCONFIRMED** | Cannot trigger the failure | Report: what was tried |
| **SKIPPED** | Hit a hard bailout trigger | Report: why skipped |
| **ALREADY_FIXED** | Bug no longer reproduces on current code | Report: when fixed |
## Step 9: Iterate or Bail
If UNCONFIRMED after first attempt:
- Revisit hypothesis — re-read the code path
- Try a different test approach or layer
- Maximum 3 attempts before declaring UNCONFIRMED
**Hard bailout triggers** (stop immediately):
- Requires real third-party API credentials
- Race condition / timing-dependent
- Requires specific cloud/enterprise infrastructure
- Requires manual UI interaction that can't be scripted
## Output: Reproduction Report
Present findings in this format:
---
**Ticket:** [ID] — [title]
**Confidence:** [CONFIRMED | LIKELY | UNCONFIRMED | SKIPPED | ALREADY_FIXED]
### Root Cause
[1-2 sentences explaining the bug mechanism]
### Location
| File | Lines | Issue |
|------|-------|-------|
| `path/to/file.ts` | XX-YY | Description of the problem |
### Failing Test
`path/to/test/file.test.ts` — X/Y tests fail:
1. `test name` — [failure description]
### Fix Hint
[Pseudocode or description of the fix approach]
---
## Important
- **DO NOT fix the bug** — only reproduce it with a failing test
- **Leave test files in place** as evidence (don't commit unless asked)
- **Run tests from the package directory** (e.g., `pushd packages/nodes-base && pnpm test <file> && popd`)
- **Always redirect build output**: `pnpm build > build.log 2>&1`
- **DO NOT look at existing fix PRs** — the goal is to reproduce from signals alone

View file

@ -0,0 +1,75 @@
---
description: >-
Configure MCP servers for n8n development. Use when the user says /setup-mcps
or asks to set up MCP servers for n8n.
---
# MCP Setup for n8n Development
Configure commonly used MCP servers for n8n engineers.
## Instructions
1. First, check which MCPs are already configured by running:
```bash
claude mcp list
```
Parse the output and match by **URL/command**, not server name (users may have
used different names). The URLs to check for:
- Linear: `mcp.linear.app`
- Notion: `mcp.notion.com`
- Context7: `ctx7` or `context7-mcp`
- Figma: `mcp.figma.com`
Skip any MCP whose URL/command is already present (regardless of scope or name).
2. Present the MCP selection menu using `AskUserQuestion` with `multiSelect: true`.
Only show MCPs that are **not** already configured. If all are already configured,
inform the user and skip the menu.
| Option | Label | Description |
|--------|-------|-------------|
| Linear | `Linear` | Linear ticket management (HTTP, OAuth — opens browser to authenticate) |
| Notion | `Notion` | Notion workspace integration (HTTP, OAuth — opens browser to authenticate) |
| Context7 | `Context7` | Library documentation lookup (OAuth setup via CLI) |
| Figma | `Figma` | Figma design integration (HTTP, OAuth — opens browser to authenticate) |
3. Process each selected MCP **one at a time** in a loop. For each MCP:
a. Ask the user via `AskUserQuestion`: "Where should **{MCP name}** be installed?"
- **user** (default, recommended) — available in all projects
- **local** — only in this project
b. Run the install command for that MCP with the chosen scope
c. Then move to the next MCP and ask again
Do NOT batch the scope question — ask separately for each MCP.
Do NOT offer project scope — it modifies `.claude/settings.json` which is tracked in git.
Commands per MCP:
### Linear
```bash
claude mcp add -s {scope} linear-server --transport http https://mcp.linear.app/mcp
```
After adding, tell the user to run `/mcp` in their next session to authenticate.
### Notion
```bash
claude mcp add -s {scope} notion --transport http https://mcp.notion.com/mcp
```
After adding, tell the user to run `/mcp` in their next session to authenticate.
### Context7
Tell the user to run this command themselves (it handles auth via OAuth automatically):
```
npx ctx7 setup --claude
```
### Figma
```bash
claude mcp add -s {scope} figma --transport http https://mcp.figma.com/mcp
```
After adding, tell the user to run `/mcp` in their next session to authenticate.
5. After running the commands, confirm which MCPs were configured and note any
manual steps remaining (authentication via `/mcp`, Context7 setup).

View file

@ -0,0 +1,79 @@
---
description: Keeps implementation and specs in sync. Use when working on a feature that has a spec in .claude/specs/, when the user says /spec, or when starting implementation of a documented feature. Also use when the user asks to verify implementation against a spec or update a spec after changes.
---
# Spec-Driven Development
Specs live in `.claude/specs/`. They are the source of truth for architectural
decisions, API contracts, and implementation scope. Implementation and specs
must stay in sync — neither leads exclusively.
## Core Loop
```
Read spec → Implement → Verify alignment → Update spec or code → Repeat
```
## Before Starting Work
1. **Find the spec.** Search `.claude/specs/` for files matching the feature:
```bash
ls .claude/specs/
```
2. **Read the full spec.** Understand scope, decisions, API contracts, and
open questions before writing code.
3. **If no spec exists** and the task is non-trivial (new module, new API,
architectural change), ask the user whether to create one first.
## During Implementation
- **Reference spec decisions** — don't re-decide what the spec already settled.
- **When you diverge from the spec** (better approach found, user requested
change, constraint discovered), update the spec immediately in the same
session. Don't leave spec and code out of sync.
- **Tick off TODO checkboxes** (`- [ ]` → `- [x]`) as items are completed.
- **Strike through or annotate** items that were deliberately skipped or
replaced, with a brief reason:
```markdown
- [x] ~~OpenRouter proxy~~ → Direct execution: nodes call OpenRouter directly
```
## After Completing Work
Run a spec verification pass:
1. **Re-read the spec** alongside the implementation.
2. **Check each section:**
- Do API endpoints in spec match the controller?
- Do config/env vars in spec match the config class?
- Does the module structure in spec match the actual file tree?
- Do type definitions in spec match `@n8n/api-types`?
- Are all TODO items correctly checked/unchecked?
3. **Update the spec** for any drift found. Common drift:
- New files added that aren't listed in the structure section
- API response shapes changed during implementation
- Config defaults adjusted
- Architectural decisions refined
4. **Flag unresolved gaps** to the user — things the spec promises but
implementation doesn't deliver yet (acceptable for MVP, but should be noted).
## Spec File Conventions
- One or more markdown files per feature in `.claude/specs/`.
- Keep specs concise. Use tables for mappings, code blocks for shapes.
- Use `## Implementation TODO` with checkboxes to track progress.
- Split into multiple files when it helps (e.g. separate backend/frontend),
but don't enforce a rigid naming scheme.
## When the User Asks to "Self-Review" or "Verify Against Spec"
1. Read all relevant specs.
2. Read all implementation files.
3. Produce a structured comparison:
- **Aligned**: items where spec and code match
- **Drift**: items where they diverge (fix immediately)
- **Gaps**: spec items not yet implemented (note as future work)
4. Fix drift, update specs, report gaps to the user.

44
.claude/settings.json Normal file
View file

@ -0,0 +1,44 @@
{
"permissions": {
"allow": [
"Bash(git log:*)",
"Bash(git show:*)",
"Bash(grep:*)",
"Bash(ls:*)",
"Bash(pnpm build)",
"Bash(pnpm lint:*)",
"Bash(pnpm test:*)",
"Bash(pnpm typecheck:*)",
"Bash(popd)",
"Bash(pushd:*)",
"Bash(mkdir -p .claude/plans)",
"Write(.claude/plans/*)"
]
},
"hooks": {
"PostToolUse": [
{
"matcher": "Skill",
"hooks": [
{
"type": "command",
"command": "node .claude/plugins/n8n/scripts/track-skill-usage.mjs",
"timeout": 10,
"async": true
}
]
}
]
},
"extraKnownMarketplaces": {
"n8n": {
"source": {
"source": "directory",
"path": "./.claude/plugins/n8n"
}
}
},
"enabledPlugins": {
"n8n@n8n": true
}
}

View file

@ -1,9 +1,15 @@
FROM n8nio/base:22
ARG NODE_VERSION=24
RUN apk add --no-cache --update openssh sudo shadow bash
FROM node:${NODE_VERSION}-alpine
ARG NODE_VERSION
RUN apk add --no-cache \
openssh sudo shadow bash libc-utils \
git openssl graphicsmagick tini tzdata ca-certificates libc6-compat
RUN echo node ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/node && chmod 0440 /etc/sudoers.d/node
RUN mkdir /workspaces && chown node:node /workspaces
RUN npm install -g pnpm
RUN corepack enable
USER node
RUN mkdir -p ~/.pnpm-store && pnpm config set store-dir ~/.pnpm-store --global

View file

@ -1,21 +1,40 @@
# We want to include the THIRD_PARTY_LICENSES.md file in the Docker image,
# but not other .md files
**/*.md
!**/THIRD_PARTY_LICENSES.md
**/.env
.cache
assets
node_modules
packages/node-dev
packages/**/node_modules
packages/**/dist
packages/**/.turbo
packages/**/*.test.*
.git
.github
!.github/scripts
*.tsbuildinfo
docker/compose
docker/**/Dockerfile
.vscode
packages/testing
# Whitelist approach: ignore everything, then allow only what Docker builds need
# This reduces build context from ~900MB to just what's required
# Ignore everything first
*
# === n8n main image (docker/images/n8n/Dockerfile) ===
!compiled
!compiled/**
!THIRD_PARTY_LICENSES.md
# === runners image (docker/images/runners/Dockerfile + Dockerfile.distroless) ===
!dist
!dist/task-runner-javascript
!dist/task-runner-javascript/**
!packages
!packages/@n8n
!packages/@n8n/task-runner-python
!packages/@n8n/task-runner-python/**
# === Docker build files (entrypoints, configs) ===
!docker
!docker/images
!docker/images/n8n
!docker/images/n8n/docker-entrypoint.sh
!docker/images/runners
!docker/images/runners/n8n-task-runners.json
# === benchmark image (packages/@n8n/benchmark/Dockerfile) ===
!package.json
!pnpm-lock.yaml
!pnpm-workspace.yaml
!patches
!patches/**
!scripts
!scripts/**
!packages/@n8n/benchmark
!packages/@n8n/benchmark/**
!packages/@n8n/typescript-config
!packages/@n8n/typescript-config/**

57
.env.local.example Normal file
View file

@ -0,0 +1,57 @@
# =============================================================================
# n8n local development — minimal environment variables
# =============================================================================
# This is a minimal example covering some local environment variables for development.
# Many more variables exist — search for @Env() decorators in the codebase.
# Most of them already have default values, so you only need to fill in the ones you need to change.
#
# Usage (run from the repo root):
# 1. Copy this file: cp .env.local.example .env.local
# 2. Fill in the values below
# 3. Prefix any dev command with dotenvx, for example:
# pnpm exec dotenvx run -f .env.local -- pnpm dev:be
#
# Note: dotenvx supports variable expansion (e.g. $HOME) but not shell
# tilde expansion. Use $HOME instead of ~ for paths.
# =============================================================================
# -----------------------------------------------------------------------------
# Local data folder
# Source: packages/@n8n/config/src/utils/utils.ts
# -----------------------------------------------------------------------------
N8N_USER_FOLDER=
# -----------------------------------------------------------------------------
# License
# Source: packages/@n8n/config/src/configs/license.config.ts
# -----------------------------------------------------------------------------
# Tenant identifier for the license SDK (for example, self-hosted, sandbox, embed, cloud).
N8N_LICENSE_TENANT_ID=
# Activation key used to activate or upgrade the instance license.
N8N_LICENSE_ACTIVATION_KEY=
# Ephemeral license certificate.
N8N_LICENSE_CERT=
# -----------------------------------------------------------------------------
# AI
# Source: packages/@n8n/config/src/configs/ai.config.ts
# packages/@n8n/config/src/configs/ai-assistant.config.ts
# packages/@n8n/config/src/configs/ai-builder.config.ts
# -----------------------------------------------------------------------------
# Whether AI features (such as AI nodes and AI assistant) are enabled globally.
N8N_AI_ENABLED=
# Base URL of the AI assistant service.
# When set, requests are sent to this URL instead of the default provider endpoint.
N8N_AI_ASSISTANT_BASE_URL=
# API key for the Anthropic (Claude) provider used by the AI workflow builder.
# When set, enables AI-powered workflow and node building.
N8N_AI_ANTHROPIC_KEY=
# -----------------------------------------------------------------------------
# LangSmith tracing (optional)
# Not an n8n config var — read directly by the LangChain SDK.
# See: https://docs.smith.langchain.com/
# -----------------------------------------------------------------------------
LANGSMITH_ENDPOINT=
LANGSMITH_PROJECT=
LANGSMITH_TRACING=

114
.github/CI-TELEMETRY.md vendored Normal file
View file

@ -0,0 +1,114 @@
# CI Telemetry
Pipeline: **GitHub Actions → Webhook → n8n → BigQuery**
## Unified Payload Shape
All telemetry uses the same format:
```json
{
"timestamp": "2026-03-16T12:00:00.000Z",
"benchmark_name": "kafka-throughput-10n-10kb",
"git": { "sha": "abc12345", "branch": "master", "pr": null },
"ci": { "runId": "123", "runUrl": "...", "job": "test", "workflow": "CI", "attempt": 1 },
"runner": { "provider": "blacksmith", "cpuCores": 8, "memoryGb": 16.0 },
"metrics": [
{ "metric_name": "exec-per-sec", "value": 12.4, "unit": "exec/s", "dimensions": { "trigger": "kafka", "nodes": 10 } }
]
}
```
## Standard Context Fields
```typescript
git.sha // GITHUB_SHA (first 8 chars)
git.branch // GITHUB_HEAD_REF ?? GITHUB_REF_NAME
git.pr // PR number from GITHUB_REF
ci.runId // GITHUB_RUN_ID
ci.runUrl // https://github.com/<repo>/actions/runs/<runId>
ci.job // GITHUB_JOB
ci.workflow // GITHUB_WORKFLOW
ci.attempt // GITHUB_RUN_ATTEMPT
runner.provider // 'github' | 'blacksmith' | 'local'
runner.cpuCores // os.cpus().length
runner.memoryGb // os.totalmem()
```
**Runner provider logic:**
```typescript
if (!process.env.CI) return 'local';
if (process.env.RUNNER_ENVIRONMENT === 'github-hosted') return 'github';
return 'blacksmith';
```
## Implementations
| Telemetry | Source | Metrics |
|-----------|--------|---------|
| Playwright perf/benchmark | `packages/testing/playwright/reporters/metrics-reporter.ts` | Any metric attached via `attachMetric()` |
| Build stats | `.github/scripts/send-build-stats.mjs` | Per-package build duration, cache hit/miss, run total |
| Docker stats | `.github/scripts/send-docker-stats.mjs` | Image size per platform, docker build duration |
| Container stack | `packages/testing/containers/telemetry.ts` | E2E stack startup times per service |
## Secrets
```
QA_METRICS_WEBHOOK_URL
QA_METRICS_WEBHOOK_USER
QA_METRICS_WEBHOOK_PASSWORD
```
## BigQuery Table
`qa_performance_metrics` — schema:
```sql
timestamp TIMESTAMP NOT NULL
benchmark_name STRING
metric_name STRING NOT NULL
value FLOAT64 NOT NULL
unit STRING
dimensions JSON -- {"nodes": 10, "trigger": "kafka", "package": "@n8n/cli"}
git_sha STRING
git_branch STRING
git_pr INT64
ci_run_id STRING
ci_run_url STRING
ci_job STRING
ci_workflow STRING
ci_attempt INT64
runner_provider STRING
runner_cpu_cores INT64
runner_memory_gb FLOAT64
```
Query example:
```sql
-- Build duration trend by package (cache misses only)
SELECT DATE(timestamp), JSON_VALUE(dimensions, '$.package'), AVG(value)
FROM qa_performance_metrics
WHERE metric_name = 'build-duration'
AND JSON_VALUE(dimensions, '$.cache') = 'miss'
GROUP BY 1, 2 ORDER BY 1;
```
## Adding New Telemetry
**From a script:**
```javascript
import { sendMetrics, metric } from './send-metrics.mjs';
await sendMetrics([
metric('my-metric', 42.0, 'ms', { context: 'value' }),
]);
```
**From a Playwright test:**
```typescript
import { attachMetric } from '../utils/performance-helper';
await attachMetric(testInfo, 'my-metric', 42.0, 'ms', { context: 'value' });
```

42
.github/CLAUDE.md vendored Normal file
View file

@ -0,0 +1,42 @@
@../AGENTS.md
## .github Quick Reference
This folder contains n8n's GitHub Actions infrastructure.
### Key Files
| File/Folder | Purpose |
|-------------|---------|
| `WORKFLOWS.md` | Complete CI/CD documentation |
| `workflows/` | GitHub Actions workflows |
| `actions/` | Reusable composite actions |
| `scripts/` | Release & Docker automation |
| `CODEOWNERS` | Team review ownership |
### Workflow Naming
| Prefix | Purpose |
|--------|---------|
| `test-` | Testing (unit, E2E, visual) |
| `ci-` | Continuous integration |
| `util-` | Utilities (notifications) |
| `build-` | Build processes |
| `release-` | Release automation |
| `sec-` | Security scanning |
Reusable workflows: add `-reusable` or `-callable` suffix.
### Common Tasks
**Add workflow:** Create in `workflows/`, document in `WORKFLOWS.md`
**Add script:** Create `.mjs` in `scripts/`, document in `WORKFLOWS.md`
### Reference
See `WORKFLOWS.md` for:
- Architecture diagrams
- Workflow call graph
- Scheduled jobs & triggers
- Runners & secrets

6
.github/CODEOWNERS vendored
View file

@ -1,4 +1,6 @@
packages/@n8n/db/src/migrations/ @n8n-io/migrations-review
.github/workflows @n8n-io/ci-admins
.github/scripts @n8n-io/ci-admins
.github/actions @n8n-io/ci-admins
.github/poutine-rules @n8n-io/ci-admins
# Node popularity data updates
packages/frontend/editor-ui/data/node-popularity.json @n8n-io/catalysts

View file

@ -66,7 +66,7 @@ body:
id: nodejs-version
attributes:
label: Node.js Version
placeholder: ex. 22.16.0
placeholder: ex. 24.0.0
validations:
required: true
- type: dropdown
@ -76,8 +76,6 @@ body:
options:
- SQLite (default)
- PostgreSQL
- MySQL
- MariaDB
default: 0
validations:
required: true

676
.github/WORKFLOWS.md vendored Normal file
View file

@ -0,0 +1,676 @@
# GitHub Actions & CI/CD Documentation
Complete reference for n8n's `.github/` folder.
---
## Folder Structure
```
.github/
├── WORKFLOWS.md # This document
├── CI-TELEMETRY.md # Telemetry & metrics guide
├── CODEOWNERS # Team ownership for PR reviews
├── pull_request_template.md # PR description template
├── pull_request_title_conventions.md # Title format rules (Angular)
├── actionlint.yml # Workflow linter config
├── docker-compose.yml # DB services for local testing
├── test-metrics/
│ └── playwright.json # E2E performance baselines
├── ISSUE_TEMPLATE/
│ ├── config.yml # Routes to community/security
│ └── 01-bug.yml # Structured bug report form
├── scripts/ # Automation scripts
│ ├── bump-versions.mjs # Calculate next version
│ ├── update-changelog.mjs # Generate CHANGELOG
│ ├── trim-fe-packageJson.js # Strip frontend devDeps
│ ├── ensure-provenance-fields.mjs # Add license/author fields
│ ├── validate-docs-links.js # Check documentation URLs
│ ├── send-build-stats.mjs # Turbo build telemetry → webhook
│ └── docker/
│ ├── docker-tags.mjs # Generate image tags
│ └── docker-config.mjs # Build context config
├── actions/ # Custom composite actions
│ ├── setup-nodejs/ # pnpm + Node + Turbo cache
│ └── docker-registry-login/ # GHCR + DockerHub auth
└── workflows/ # GitHub Actions workflows
```
---
## Architecture Overview
```
┌────────────────────────────────────────────────────────────────────────────┐
│ n8n CI/CD ARCHITECTURE │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ TRIGGERS PIPELINES OUTPUTS │
│ ──────── ───────── ─────── │
│ │
│ ┌──────────┐ ┌──────────────────────────────────┐ ┌────────────┐ │
│ │ PR │───▶│ ci-pull-requests.yml │───▶│ Checks │ │
│ └──────────┘ │ ├─ build + paths-filter │ │ Gate │ │
│ │ ├─ unit-test (reusable) │ └────────────┘ │
│ ┌──────────┐ │ ├─ typecheck │ │
│ │ Push │───▶│ ├─ lint (reusable) │ ┌────────────┐ │
│ │ master │ │ ├─ e2e-tests (reusable) │───▶│ Coverage │ │
│ └──────────┘ │ └─ security (if .github/**) │ └────────────┘ │
│ └──────────────────────────────────┘ │
│ │
│ ┌──────────┐ ┌──────────────────────────────────┐ ┌────────────┐ │
│ │ Merge │───▶│ release-publish.yml │───▶│ NPM │ │
│ │release/* │ │ ├─ publish-to-npm │ ├────────────┤ │
│ └──────────┘ │ ├─ publish-to-docker-hub │───▶│ Docker │ │
│ │ ├─ create-github-release │ ├────────────┤ │
│ │ ├─ create-sentry-release │───▶│ Sentry │ │
│ │ └─ generate-sbom │ ├────────────┤ │
│ └──────────────────────────────────┘───▶│ SBOM │ │
│ └────────────┘ │
│ ┌──────────┐ ┌──────────────────────────────────┐ │
│ │ Schedule │───▶│ Nightly/Weekly Jobs │ ┌────────────┐ │
│ │ (cron) │ │ ├─ docker-build-push (nightly) │───▶│ Images │ │
│ └──────────┘ │ ├─ test-benchmark-nightly │───▶│ Metrics │ │
│ │ ├─ test-workflows-nightly │ └────────────┘ │
│ │ ├─ test-e2e-vm-expressions │ │
│ │ └─ test-e2e-coverage-weekly │ │
│ └──────────────────────────────────┘ │
│ │
└────────────────────────────────────────────────────────────────────────────┘
```
---
## Quick Reference
| Prefix | Purpose |
|------------|-----------------------------------------|
| `test-` | Testing (E2E, unit, visual, benchmarks) |
| `ci-` | Continuous integration |
| `util-` | Utilities (notifications, sync, Claude) |
| `build-` | Build processes |
| `release-` | Release automation |
| `sec-` | Security scanning |
| Other | Docker, SBOM, patch releases |
---
## PR Title Conventions
Commits drive changelog generation. Follow Angular convention:
```
Format: <type>(<scope>): <summary>
Types: feat | fix | perf | test | docs | refactor | build | ci | chore
Scopes: API | benchmark | core | editor | * Node (optional)
Examples:
feat(editor): Add dark mode toggle
fix(Slack Node): Handle rate limiting correctly
perf(core): Optimize workflow execution by 20%
refactor: Migrate to TypeScript strict mode (no-changelog)
Breaking Changes: Add "BREAKING CHANGE:" footer with migration guide
Deprecations: Add "DEPRECATED:" footer with update path
Skip Changelog: Add "(no-changelog)" to PR title
```
See `pull_request_title_conventions.md` for full spec.
---
## What Runs When You Open a PR
### Flow Diagram
```
┌──────────────────────────────────────────────────────────────────────────────┐
│ PR OPENED / UPDATED │
└─────────────────────────────────────┬────────────────────────────────────────┘
┌───────────────────────────┴───────────────────────┐
▼ ▼
┌───────────────────────────┐ ┌───────────────────────────┐
│ ci-pull-requests.yml │ │ ci-check-pr-title.yml │
│ (main orchestrator) │ │ (validates title format) │
└─────────────┬─────────────┘ └───────────────────────────┘
┌───────────────────────────┐
│ install-and-build │
│ └─ paths-filter │──────────────────────────────────────────┐
└─────────────┬─────────────┘ │
│ │
│ [if non-Python files changed] │ [if .github/** changed]
│ │
┌─────────┼─────────┬─────────────┬─────────────┐ │
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐ ┌────────────┐ ┌────────────┐ ┌────────────┐
│ unit │ │ type │ │ lint │ │ e2e-tests │ │ security │ │ security │
│ test │ │ check │ │ │ │ │ │ checks │ │ checks │
└───┬───┘ └───┬───┘ └───┬───┘ └─────┬──────┘ └─────┬──────┘ └─────┬──────┘
│ │ │ │ │ │
│ │ │ ┌─────┴─────┐ │ │
│ │ │ ▼ ▼ │ │
│ │ │ Internal Fork PR │ │
│ │ │ 14 shards 6 shards │ │
│ │ │ Docker SQLite │ │
│ │ │ │ │
└─────────┴─────────┴──────────┬───────────────┴────────────────┘
┌──────────────────────────────┐
│ required-checks │
│ (merge gate) │
└──────────────────────────────┘
```
### Path-Filtered Workflows
These only run if specific files changed:
| Files Changed | Workflow | Branch |
|------------------------------------------------------------------------|-----------------------------|------------|
| `packages/@n8n/task-runner-python/**` | `ci-python.yml` | any |
| `packages/cli/src/databases/**`, `*.entity.ts`, `*.repository.ts` | `test-db.yml` | any |
| `packages/frontend/@n8n/storybook/**`, design-system, chat | `test-visual-storybook.yml` | master |
| `docker/images/n8n-base/Dockerfile` | `build-base-image.yml` | any |
| `**/package.json`, `**/turbo.json` | `build-windows.yml` | master |
| `packages/@n8n/ai-workflow-builder.ee/evaluations/programmatic/python/**` | `test-evals-python.yml` | any |
| `packages/@n8n/benchmark/**` | `build-benchmark-image.yml` | master |
| `packages/cli/src/public-api/**/*.{css,yaml,yml}` | `util-sync-api-docs.yml` | master |
### On PR Review
| Event | Workflow | Condition |
|----------------------------|-----------------------------|------------------------------|
| Review approved | `test-visual-chromatic.yml` | + design files changed |
| Comment with `@claude` | `util-claude.yml` | mention in any comment |
| Any review | `util-notify-pr-status.yml` | not community-labeled |
### On PR Close/Merge
| Event | Workflow |
|----------------------------|-----------------------------|
| PR closed (any) | `util-notify-pr-status.yml` |
| PR merged to `release/*` | `release-publish.yml` |
### Manual Triggers (PR Comments)
| Command | Workflow | Permissions |
|--------------------|------------------------------|---------------------|
| `/test-workflows` | `test-workflows-callable.yml`| admin/write/maintain|
**Why:** Re-run tests without pushing commits. Useful for flaky test investigation.
### Other Manual Workflows
| Workflow | Purpose |
|---------------------------|---------------------------------------------------------|
| `util-claude-task.yml` | Run Claude Code to complete a task and create a PR |
| `util-data-tooling.yml` | SQLite/PostgreSQL export/import validation (manual) |
#### Claude Task Runner (`util-claude-task.yml`)
Runs Claude Code to complete a task, then creates a PR with the changes. Use for well-specced tasks or simple fixes. Can be triggered via GitHub UI or API.
Claude reads templates from `.github/claude-templates/` for task-specific guidance. Add new templates as needed for recurring task types.
**Inputs:**
- `task` - Description of what Claude should do
- `user_token` - GitHub PAT (PR will be authored by the token owner)
**Token requirements** (fine-grained PAT):
- Repository: `n8n-io/n8n`
- Contents: `Read and write`
- Pull requests: `Read and write`
**Governance:** If you provide your personal PAT, you cannot approve the resulting PR. For automated/bot use cases (e.g., dependabot-style updates via n8n workflows), an app token can be used instead.
---
## Workflow Call Graph
Shows which workflows call which reusable workflows:
```
CALLER REUSABLE WORKFLOW
───────────────────────────────────────────────────────────────────────────────
ci-pull-requests.yml
├──────────────────────────▶ test-unit-reusable.yml
├──────────────────────────▶ test-linting-reusable.yml
├──────────────────────────▶ test-e2e-ci-reusable.yml
│ └──────────▶ test-e2e-reusable.yml
└──────────────────────────▶ sec-ci-reusable.yml
└──────────▶ sec-poutine-reusable.yml
ci-master.yml
├──────────────────────────▶ test-unit-reusable.yml
└──────────────────────────▶ test-linting-reusable.yml
release-publish.yml
├──────────────────────────▶ docker-build-push.yml
│ └──────────▶ security-trivy-scan-callable.yml
└──────────────────────────▶ sbom-generation-callable.yml
test-workflows-nightly.yml
└──────────────────────────▶ test-workflows-callable.yml
test-e2e-vm-expressions-nightly.yml
└──────────────────────────▶ test-e2e-ci-reusable.yml
└──────────▶ test-e2e-reusable.yml
PR Comment Dispatchers (triggered by /command in PR comments):
test-workflows-pr-comment.yml
└──────────────────────────▶ test-workflows-callable.yml
```
---
## Release Lifecycle
```
┌────────────────────────────────────────────────────────────────────────────┐
│ RELEASE LIFECYCLE │
├────────────────────────────────────────────────────────────────────────────┤
│ │
│ STAGE 1: Create Release PR │
│ ─────────────────────────── │
│ Trigger: Manual workflow_dispatch │
│ │
│ release-create-pr.yml │
│ ├─ bump-versions.mjs ────────▶ Calculate X.Y.Z │
│ ├─ update-changelog.mjs ─────▶ Generate CHANGELOG │
│ └─ Create PR: release-pr/X.Y.Z → release/X.Y.Z │
│ │
│ Inputs: │
│ ├─ release-type: patch │ minor │ major │ experimental │ premajor │
│ └─ base-branch: default master │
│ │ │
│ ▼ │
│ STAGE 2: CI Validation │
│ ─────────────────────── │
│ ci-pull-requests.yml runs full suite │
│ ├─ NO ci-check-pr-title.yml (skipped for release branches) │
│ └─ NO test-visual-chromatic.yml (skipped) │
│ │ │
│ ▼ [Merge PR] │
│ STAGE 3: Publish │
│ ─────────────── │
│ release-publish.yml (triggered on merge to release/*) │
│ ├─ publish-to-npm │
│ │ ├─ trim-fe-packageJson.js ───▶ Strip devDeps │
│ │ ├─ ensure-provenance-fields.mjs ───▶ Add license fields │
│ │ └─ npm publish (tag: rc or latest) │
│ ├─ publish-to-docker-hub ────────▶ docker-build-push.yml │
│ │ └─ Multi-arch: amd64 + arm64 │
│ ├─ create-github-release │
│ ├─ create-sentry-release (sourcemaps) │
│ ├─ generate-sbom ────────────────▶ sbom-generation-callable.yml │
│ │ └─ CycloneDX + Cosign signing │
│ └─ trigger-release-note (stable only) │
│ │ │
│ ▼ │
│ STAGE 4: Channel Promotion (optional) │
│ ────────────────────────────────────── │
│ Trigger: Manual release-push-to-channel.yml │
│ ├─ beta ─────▶ npm tags: next, beta │
│ └─ stable ───▶ npm tags: latest, stable │
│ │
└────────────────────────────────────────────────────────────────────────────┘
```
### Other Release Workflows
| Workflow | Trigger | Purpose |
|----------------------------------|--------------------|------------------------------------------------|
| `release-standalone-package.yml` | Manual dispatch | Release individual packages (@n8n/codemirror-lang, @n8n/create-node, etc.) |
| `create-patch-release-branch.yml`| Manual dispatch | Cherry-pick commits for patch releases |
---
## Fork vs Internal PR
| Aspect | Internal PR | Fork PR |
|--------------------|----------------------------------|-------------------------|
| E2E Runner | `blacksmith-2vcpu-ubuntu-2204` | `ubuntu-latest` |
| E2E Mode | `docker-build` (multi-main) | `local` (SQLite) |
| E2E Shards | 14 + 2 | 6 + 2 |
| Test Command | `test:container:multi-main:*` | `test:local:*` |
| Secrets | Full access | None |
| Currents Recording | Yes | No |
| Failure Artifacts | No | Yes |
**Why:** Fork PRs cannot access repository secrets. Local mode with SQLite provides feedback without paid services.
---
## ci-master.yml
Runs on push to `master` or `1.x`:
```
Push to master/1.x
├─ build-github (populate cache)
├─ unit-test (matrix: Node 22.x, 24.14.1, 25.x)
│ └─ Coverage only on 24.14.1
├─ lint
└─ notify-on-failure (Slack #alerts-build)
```
---
## Scheduled Jobs
| Schedule (UTC) | Workflow | Purpose |
|---------------------------|-----------------------------------|--------------------------|
| Daily 00:00 | `docker-build-push.yml` | Nightly Docker images |
| Daily 00:00 | `test-db.yml` | Database compatibility |
| Daily 00:00 | `test-e2e-performance-reusable.yml`| Performance E2E |
| Daily 00:00 | `test-visual-storybook.yml` | Storybook deploy |
| Daily 00:00 | `test-visual-chromatic.yml` | Visual regression |
| Daily 00:00 | `util-check-docs-urls.yml` | Doc link validation |
| Daily 01:30, 02:30, 03:30 | `test-benchmark-nightly.yml` | Performance benchmarks |
| Daily 02:00 | `test-workflows-nightly.yml` | Workflow tests |
| Daily 04:00 | `test-e2e-vm-expressions-nightly.yml`| VM expression E2E |
| Daily 05:00 | `test-benchmark-destroy-nightly.yml`| Cleanup benchmark env |
| Monday 00:00 | `util-update-node-popularity.yml` | Node usage stats |
| Monday 02:00 | `test-e2e-coverage-weekly.yml` | Weekly E2E coverage |
| Saturday 22:00 | `test-evals-ai.yml` | AI workflow evals |
---
## Custom Actions
Composite actions in `.github/actions/`:
| Action | Purpose | Used By |
|--------------------------|----------------------------------------------|--------------------|
| `setup-nodejs` | pnpm + Node.js + Turbo cache + Docker (opt) | Most CI workflows |
| `docker-registry-login` | GHCR + DockerHub + DHI authentication | Docker workflows |
### setup-nodejs
```yaml
inputs:
node-version: # default: '24.14.1'
enable-docker-cache: # default: 'false' (Blacksmith Buildx)
build-command: # default: 'pnpm build'
```
### docker-registry-login
```yaml
inputs:
login-ghcr: # default: 'true'
login-dockerhub: # default: 'false'
login-dhi: # default: 'false'
```
---
## Reusable Workflows
Workflows with `workflow_call` trigger:
| Workflow | Inputs | Purpose |
|------------------------------------|-----------------------------------------------|-----------------------|
| `test-unit-reusable.yml` | `ref`, `nodeVersion`, `collectCoverage` | Unit tests |
| `test-linting-reusable.yml` | `ref`, `nodeVersion` | ESLint |
| `test-e2e-reusable.yml` | `branch`, `test-mode`, `shards`, `runner` | Core E2E executor |
| `test-e2e-ci-reusable.yml` | `branch` | E2E orchestrator |
| `test-e2e-docker-pull-reusable.yml`| `branch`, `n8n_version` | E2E with pulled image |
| `test-workflows-callable.yml` | `git_ref`, `compare_schemas` | Workflow tests |
| `docker-build-push.yml` | `n8n_version`, `release_type`, `push_enabled` | Docker build |
| `sec-ci-reusable.yml` | `ref` | Security orchestrator |
| `sec-poutine-reusable.yml` | `ref` | Poutine scanner |
| `security-trivy-scan-callable.yml` | `image_ref` | Trivy scan |
| `sbom-generation-callable.yml` | `n8n_version`, `release_tag_ref` | SBOM generation |
---
## Scripts
Scripts in `.github/scripts/`:
### Release Scripts
| Script | Purpose | Called By |
|-------------------------------|----------------------------|-------------------------|
| `bump-versions.mjs` | Calculate next version | `release-create-pr.yml` |
| `update-changelog.mjs` | Generate CHANGELOG | `release-create-pr.yml` |
| `trim-fe-packageJson.js` | Strip frontend devDeps | `release-publish.yml` |
| `ensure-provenance-fields.mjs`| Add license/author fields | `release-publish.yml` |
### Docker Scripts
| Script | Purpose | Called By |
|-------------------------|-------------------|------------------------|
| `docker/docker-config.mjs`| Build context | `docker-build-push.yml`|
| `docker/docker-tags.mjs` | Image tags | `docker-build-push.yml`|
### Validation Scripts
| Script | Purpose | Called By |
|-------------------------|-------------------|---------------------------|
| `validate-docs-links.js`| Check doc URLs | `util-check-docs-urls.yml`|
| `send-build-stats.mjs` | Build telemetry | `setup-nodejs` action |
---
## Telemetry
CI metrics are collected via webhooks to n8n, then stored in BigQuery for analysis.
See **[CI-TELEMETRY.md](CI-TELEMETRY.md)** for:
- Common data points (git, CI context, runner info)
- Existing implementations (build stats, container stack)
- How to add new telemetry
- BigQuery schema patterns and queries
---
## CODEOWNERS
Team ownership mappings in `CODEOWNERS`:
| Path Pattern | Team |
|--------------------------------------------------------------|----------------------------|
| `packages/@n8n/db/src/migrations/` | @n8n-io/migrations-review |
---
## Runner Selection
| Runner | vCPU | Use Case |
|-------------------------------------|------|-----------------------------|
| `ubuntu-slim` | 1 | Gate jobs (required-checks) |
| `ubuntu-latest` | 2 | Simple jobs, fork PR E2E |
| `blacksmith-2vcpu-ubuntu-2204` | 2 | Standard builds, E2E shards |
| `blacksmith-4vcpu-ubuntu-2204` | 4 | Unit tests, typecheck, lint |
| `blacksmith-8vcpu-ubuntu-2204` | 8 | E2E coverage (weekly) |
| `blacksmith-4vcpu-ubuntu-2204-arm` | 4 | ARM64 Docker builds |
### Selection Guidelines
**`ubuntu-slim`** - Status check aggregation, gate/required-check jobs, notifications
**`ubuntu-latest`** - Simple build verification, scheduled maintenance, PR comment handlers, release tagging, Docker manifest creation, any job where speed is not critical
**`blacksmith-2vcpu-ubuntu-2204`** - Initial build/install (benefits from Blacksmith caching), database integration tests (I/O bound), Chromatic/Storybook builds
**`blacksmith-4vcpu-ubuntu-2204`** - Unit tests (parallelized), linting (parallel file processing), typechecking (CPU-intensive), E2E test shards
**`blacksmith-8vcpu-ubuntu-2204`** - Heavy parallel workloads, full E2E coverage runs
### Runner Provider Toggle
The `RUNNER_PROVIDER` repository variable controls runner selection across workflows:
| Value | Behavior |
|-------|----------|
| (unset) | Use Blacksmith runners (default) |
| `github` | Use GitHub-hosted `ubuntu-latest` |
**Note:** When set to `github`, all jobs use `ubuntu-latest` regardless of any runner inputs or defaults specified in reusable workflows. GitHub runners have fewer vCPUs (2 vs 4), so jobs may run slower.
---
## Security
### Why We Do This
Supply chain security ensures artifacts haven't been tampered with. We provide three types of signed attestations:
```
ATTESTATION (signed statement)
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
PROVENANCE SBOM VEX
"Trust the "Know the "Understand
build" contents" the risk"
```
| Attestation | Question It Answers |
|-------------|--------------------------------|
| **Provenance** | "Can we trust this artifact came from n8n's CI and wasn't tampered with?" |
| **SBOM** | "What dependencies are inside?" (license compliance, vulnerability scanning) |
| **VEX** | "The scanner found CVE-X - does it actually affect us or is it a false positive?" |
**How they relate:**
- **SBOM** is the ingredients list - input for both license checks AND security scanning
- **VEX** is the security triage output - "we investigated CVE-X, here's our assessment"
- **Provenance** proves the SBOM and VEX came from our CI, not an attacker
---
### Poutine (Supply Chain)
- **Runs on:** PR changes to `.github/**`
- **Detects:** Exposed secrets, insecure workflow configs
- **Output:** SARIF to GitHub Security tab
### Trivy (Container)
- **Runs on:** stable/nightly/rc Docker builds
- **Scans:** n8n image, runners image
- **Output:** Slack `#notify-security-scan-outputs` (all), `#mission-security` (critical)
### SBOM
- **Runs on:** release-publish
- **Format:** CycloneDX JSON
- **Signing:** GitHub Attestation API
- **Attached to:** GitHub Release
### SLSA L3 Provenance
SLSA (Supply-chain Levels for Software Artifacts) Level 3 provides cryptographic proof of build integrity.
| Artifact | Generator | Level |
|----------|-----------|-------|
| Docker images | `slsa-framework/slsa-github-generator` | L3 |
| npm packages | `NPM_CONFIG_PROVENANCE=true` | L3 |
**Docker provenance** uses the SLSA GitHub Generator as a reusable workflow (not an action). This is required for L3 because provenance must be generated in an isolated environment the build can't tamper with.
```yaml
# IMPORTANT: Must use semantic version tags (@vX.Y.Z), NOT commit SHAs.
# The slsa-verifier requires tagged versions to verify authenticity.
uses: slsa-framework/slsa-github-generator/.github/workflows/generator_container_slsa3.yml@v2.1.0
```
**Verify provenance:**
```bash
# Docker
slsa-verifier verify-image ghcr.io/n8n-io/n8n:VERSION \
--source-uri github.com/n8n-io/n8n
# npm
npm audit signatures n8n@VERSION
```
### VEX (Vulnerability Exploitability eXchange)
VEX documents which CVEs actually affect n8n vs false positives from scanners.
- **File:** `security/vex.openvex.json`
- **Format:** OpenVEX (broad scanner compatibility - Trivy, Docker Scout, etc.)
- **Attached to:** GitHub Release, Docker image attestations
- **Used by:** Trivy scans (via `security/trivy.yaml`)
**VEX Status Types:**
| Status | Meaning |
|--------|---------|
| `not_affected` | CVE doesn't impact n8n (code not reachable, etc.) |
| `affected` | CVE impacts n8n, tracking fix |
| `fixed` | CVE was present, now fixed |
| `under_investigation` | Assessing impact |
**Verify VEX attestation:**
```bash
cosign verify-attestation --type openvex \
--certificate-identity-regexp '.*github.com/n8n-io/n8n.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com \
ghcr.io/n8n-io/n8n:VERSION
```
**Adding a CVE statement to security/vex.openvex.json:**
```json
{
"statements": [
{
"vulnerability": { "name": "CVE-2024-XXXXX" },
"products": [{ "@id": "pkg:github/n8n-io/n8n" }],
"status": "not_affected",
"justification": "vulnerable_code_not_in_execute_path",
"statement": "n8n does not use the affected code path in this dependency"
}
]
}
```
---
## Secrets
### By Category
| Category | Secrets |
|---------------------|-------------------------------------------------------------|
| Package Publishing | `NPM_TOKEN`, `DOCKER_USERNAME`, `DOCKER_PASSWORD` |
| Notifications | `SLACK_WEBHOOK_URL`, `QBOT_SLACK_TOKEN` |
| Code Quality | `CODECOV_TOKEN`, `CHROMATIC_PROJECT_TOKEN`, `CURRENTS_RECORD_KEY` |
| Error Tracking | `SENTRY_AUTH_TOKEN`, `SENTRY_ORG`, `SENTRY_*_PROJECT` |
| Cloud/CDN | `CLOUDFLARE_API_TOKEN`, `CLOUDFLARE_ACCOUNT_ID` |
| GitHub Automation | `N8N_ASSISTANT_APP_ID`, `N8N_ASSISTANT_PRIVATE_KEY` |
| Benchmarking | `BENCHMARK_ARM_*`, `N8N_BENCHMARK_LICENSE_CERT` |
| AI/Evals | `ANTHROPIC_API_KEY`, `EVALS_LANGSMITH_*` |
### Scoping
- **`secrets: inherit`** - passes all secrets to reusable workflows
- **Explicit passing** - for minimal exposure
- **Environment: `benchmarking`** - Azure OIDC credentials
---
## Future Vision
### Redundancy Review
Comment trigger (`/test-workflows`) is a workaround.
Long-term: Main CI should be reliable enough to not need these.
### Workflow Testability
- Tools like `act` for local testing
- Unit tests for `.github/scripts/*.mjs`
- Validation with `actionlint`

View file

@ -1,7 +0,0 @@
self-hosted-runner:
labels:
- blacksmith-2vcpu-ubuntu-2204
- blacksmith-4vcpu-ubuntu-2204
- blacksmith-2vcpu-ubuntu-2204-arm
- blacksmith-4vcpu-ubuntu-2204-arm
- blacksmith-8vcpu-ubuntu-2204

8
.github/actionlint.yml vendored Normal file
View file

@ -0,0 +1,8 @@
self-hosted-runner:
labels:
- blacksmith-2vcpu-ubuntu-2204
- blacksmith-4vcpu-ubuntu-2204
- blacksmith-2vcpu-ubuntu-2204-arm
- blacksmith-4vcpu-ubuntu-2204-arm
- blacksmith-8vcpu-ubuntu-2204
- ubuntu-slim

View file

@ -0,0 +1,235 @@
import { describe, it } from 'node:test';
import assert from 'node:assert/strict';
import { matchGlob, parseFilters, evaluateFilter, runValidate } from '../ci-filter.mjs';
// --- matchGlob ---
describe('matchGlob', () => {
it('** matches dotfiles', () => {
assert.ok(matchGlob('.github/workflows/ci.yml', '**'));
});
it('** matches deeply nested paths', () => {
assert.ok(matchGlob('packages/cli/src/controllers/auth.ts', '**'));
});
it('** matches root-level files', () => {
assert.ok(matchGlob('README.md', '**'));
});
it('.github/** matches workflow files', () => {
assert.ok(matchGlob('.github/workflows/ci.yml', '.github/**'));
});
it('.github/** matches action files', () => {
assert.ok(matchGlob('.github/actions/ci-filter/action.yml', '.github/**'));
});
it('.github/** does not match non-.github paths', () => {
assert.ok(!matchGlob('packages/cli/src/index.ts', '.github/**'));
});
it('scoped package pattern matches files in that package', () => {
assert.ok(
matchGlob(
'packages/@n8n/task-runner-python/src/main.py',
'packages/@n8n/task-runner-python/**',
),
);
});
it('scoped package pattern does not match other packages', () => {
assert.ok(!matchGlob('packages/@n8n/config/src/index.ts', 'packages/@n8n/task-runner-python/**'));
});
it('* matches single-level only', () => {
assert.ok(matchGlob('README.md', '*.md'));
assert.ok(!matchGlob('docs/README.md', '*.md'));
});
it('exact path match', () => {
assert.ok(matchGlob('package.json', 'package.json'));
assert.ok(!matchGlob('packages/cli/package.json', 'package.json'));
});
it('? matches single character', () => {
assert.ok(matchGlob('file1.txt', 'file?.txt'));
assert.ok(!matchGlob('file12.txt', 'file?.txt'));
});
it('**/ at start matches zero or more path segments', () => {
assert.ok(matchGlob('src/index.ts', '**/index.ts'));
assert.ok(matchGlob('packages/cli/src/index.ts', '**/index.ts'));
assert.ok(matchGlob('index.ts', '**/index.ts'));
});
it('**/ in middle matches nested paths', () => {
assert.ok(matchGlob('packages/@n8n/db/src/deep/file.ts', 'packages/@n8n/db/**'));
});
});
// --- parseFilters ---
describe('parseFilters', () => {
it('parses single-line filter', () => {
const filters = parseFilters('workflows: .github/**');
assert.deepEqual(filters.get('workflows'), ['.github/**']);
});
it('parses single-line with multiple patterns', () => {
const filters = parseFilters('db: packages/@n8n/db/** packages/cli/**');
assert.deepEqual(filters.get('db'), ['packages/@n8n/db/**', 'packages/cli/**']);
});
it('parses multi-line filter', () => {
const input = `non-python:
**
!packages/@n8n/task-runner-python/**`;
const filters = parseFilters(input);
assert.deepEqual(filters.get('non-python'), ['**', '!packages/@n8n/task-runner-python/**']);
});
it('parses mixed single and multi-line', () => {
const input = `non-python:
**
!packages/@n8n/task-runner-python/**
workflows: .github/**`;
const filters = parseFilters(input);
assert.equal(filters.size, 2);
assert.deepEqual(filters.get('non-python'), ['**', '!packages/@n8n/task-runner-python/**']);
assert.deepEqual(filters.get('workflows'), ['.github/**']);
});
it('ignores comments and blank lines', () => {
const input = `# This is a comment
workflows: .github/**
# Another comment
db: packages/@n8n/db/**`;
const filters = parseFilters(input);
assert.equal(filters.size, 2);
});
it('throws on malformed input', () => {
assert.throws(() => parseFilters('not a valid filter line'), /Malformed/);
});
it('throws on filter with no patterns', () => {
const input = `empty:
other: .github/**`;
assert.throws(() => parseFilters(input), /no patterns/);
});
});
// --- evaluateFilter ---
describe('evaluateFilter', () => {
it('python-only files with non-python filter returns false', () => {
const files = [
'packages/@n8n/task-runner-python/src/main.py',
'packages/@n8n/task-runner-python/pyproject.toml',
];
const patterns = ['**', '!packages/@n8n/task-runner-python/**'];
assert.equal(evaluateFilter(files, patterns), false);
});
it('mixed python and non-python returns true', () => {
const files = [
'packages/@n8n/task-runner-python/src/main.py',
'packages/cli/src/index.ts',
];
const patterns = ['**', '!packages/@n8n/task-runner-python/**'];
assert.equal(evaluateFilter(files, patterns), true);
});
it('non-python files with non-python filter returns true', () => {
const files = ['packages/cli/src/index.ts', 'packages/core/src/utils.ts'];
const patterns = ['**', '!packages/@n8n/task-runner-python/**'];
assert.equal(evaluateFilter(files, patterns), true);
});
it('.github files with workflows filter returns true', () => {
const files = ['.github/workflows/ci.yml', '.github/actions/setup/action.yml'];
const patterns = ['.github/**'];
assert.equal(evaluateFilter(files, patterns), true);
});
it('non-.github files with workflows filter returns false', () => {
const files = ['packages/cli/src/index.ts'];
const patterns = ['.github/**'];
assert.equal(evaluateFilter(files, patterns), false);
});
it('empty changed files returns false', () => {
assert.equal(evaluateFilter([], ['**']), false);
});
it('last matching pattern wins (gitignore semantics)', () => {
const files = ['packages/@n8n/task-runner-python/src/main.py'];
const patterns = ['**', '!packages/@n8n/task-runner-python/**', 'packages/@n8n/task-runner-python/**'];
assert.equal(evaluateFilter(files, patterns), true);
});
});
// --- runValidate ---
describe('runValidate', () => {
function runWithResults(jobResults: Record<string, { result: string }>): number | null {
const originalEnv = process.env.INPUT_JOB_RESULTS;
const originalExit = process.exit;
let exitCode: number | null = null;
process.env.INPUT_JOB_RESULTS = JSON.stringify(jobResults);
process.exit = ((code: number) => { exitCode = code; }) as never;
try {
runValidate();
} finally {
process.env.INPUT_JOB_RESULTS = originalEnv;
process.exit = originalExit;
}
return exitCode;
}
it('passes when all jobs succeed', () => {
assert.equal(runWithResults({
'install-and-build': { result: 'success' },
'unit-test': { result: 'success' },
typecheck: { result: 'success' },
lint: { result: 'success' },
}), null);
});
it('passes when some jobs are skipped (filtered out)', () => {
assert.equal(runWithResults({
'install-and-build': { result: 'success' },
'unit-test': { result: 'success' },
'security-checks': { result: 'skipped' },
}), null);
});
it('fails when a job fails', () => {
assert.equal(runWithResults({
'install-and-build': { result: 'success' },
'unit-test': { result: 'failure' },
typecheck: { result: 'success' },
}), 1);
});
it('fails when a job is cancelled', () => {
assert.equal(runWithResults({
'install-and-build': { result: 'success' },
'unit-test': { result: 'cancelled' },
}), 1);
});
it('fails when multiple jobs have problems', () => {
assert.equal(runWithResults({
'unit-test': { result: 'failure' },
typecheck: { result: 'cancelled' },
lint: { result: 'success' },
}), 1);
});
});

39
.github/actions/ci-filter/action.yml vendored Normal file
View file

@ -0,0 +1,39 @@
name: 'CI Filter'
description: |
Filter CI jobs by changed files and validate results.
Modes:
- filter: Determines which jobs to run based on changed files and a provided filter definition.
- validate: Checks the results of required jobs and fails if any of them failed or were cancelled.
inputs:
mode:
description: 'filter or validate'
required: true
filters:
description: 'Filter definitions (gitignore-style DSL)'
required: false
base-ref:
description: 'Base branch for diff. Auto-detected if not specified.'
required: false
job-results:
description: 'Job results from needs context as JSON (mode=validate)'
required: false
outputs:
results:
description: 'JSON object: { "filter-name": true/false }'
value: ${{ steps.run.outputs.results }}
runs:
using: 'composite'
steps:
- name: Run CI Filter
id: run
shell: bash
env:
INPUT_MODE: ${{ inputs.mode }}
INPUT_FILTERS: ${{ inputs.filters }}
INPUT_BASE_REF: ${{ inputs.base-ref || github.event.pull_request.base.ref || github.event.merge_group.base_ref || 'master' }}
INPUT_JOB_RESULTS: ${{ inputs.job-results }}
run: node ${{ github.action_path }}/ci-filter.mjs

216
.github/actions/ci-filter/ci-filter.mjs vendored Normal file
View file

@ -0,0 +1,216 @@
import { execSync } from 'node:child_process';
import { appendFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { resolve } from 'node:path';
// --- Glob matching (dotfile-safe) ---
/**
* Match a file path against a glob pattern.
* Unlike path.matchesGlob / standard POSIX globs, `**` matches dotfiles.
*/
export function matchGlob(filePath, pattern) {
let regex = '';
let i = 0;
while (i < pattern.length) {
const ch = pattern[i];
if (ch === '*' && pattern[i + 1] === '*') {
if (pattern[i + 2] === '/') {
regex += '(?:.+/)?';
i += 3;
} else {
regex += '.*';
i += 2;
}
} else if (ch === '*') {
regex += '[^/]*';
i++;
} else if (ch === '?') {
regex += '[^/]';
i++;
} else {
regex += ch.replace(/[.+^${}()|[\]\\]/g, '\\$&');
i++;
}
}
return new RegExp(`^${regex}$`).test(filePath);
}
// --- Filter DSL parser ---
/**
* Parse filter definitions from the input DSL.
*
* Supports two formats:
* Single-line: `name: pattern1 pattern2`
* Multi-line: `name:` followed by indented patterns (one per line)
*
* Lines starting with # and blank lines are ignored.
*/
export function parseFilters(input) {
const filters = new Map();
const lines = input.split('\n');
let currentFilter = null;
for (const rawLine of lines) {
const line = rawLine.trim();
if (!line || line.startsWith('#')) continue;
const headerMatch = line.match(/^([a-zA-Z0-9_-]+):\s*(.*)?$/);
if (headerMatch) {
const name = headerMatch[1];
const rest = (headerMatch[2] || '').trim();
const patterns = [];
currentFilter = name;
filters.set(name, patterns);
if (rest) {
patterns.push(...rest.split(/\s+/));
currentFilter = null;
}
continue;
}
if (currentFilter && rawLine.match(/^\s/)) {
const patterns = filters.get(currentFilter);
if (patterns) patterns.push(line);
continue;
}
throw new Error(`Malformed filter input at: "${rawLine}"`);
}
for (const [name, patterns] of filters) {
if (patterns.length === 0) {
throw new Error(`Filter "${name}" has no patterns`);
}
}
return filters;
}
// --- Git operations ---
const SAFE_REF = /^[a-zA-Z0-9_./-]+$/;
export function getChangedFiles(baseRef) {
if (!SAFE_REF.test(baseRef)) {
throw new Error(`Unsafe base ref: "${baseRef}"`);
}
execSync(`git fetch --depth=1 origin ${baseRef}`, { stdio: 'pipe' });
const output = execSync('git diff --name-only FETCH_HEAD HEAD', { encoding: 'utf-8' });
return output
.split('\n')
.map((f) => f.trim())
.filter(Boolean);
}
// --- Filter evaluation ---
/**
* Evaluate a single filter against changed files using gitignore semantics.
* Patterns evaluated in order, last match wins. ! prefix excludes.
* Filter triggers if ANY changed file passes.
*/
export function evaluateFilter(changedFiles, patterns) {
for (const file of changedFiles) {
let included = false;
for (const pattern of patterns) {
if (pattern.startsWith('!')) {
if (matchGlob(file, pattern.slice(1))) {
included = false;
}
} else {
if (matchGlob(file, pattern)) {
included = true;
}
}
}
if (included) return true;
}
return false;
}
// --- Mode: filter ---
function setOutput(name, value) {
const outputFile = process.env.GITHUB_OUTPUT;
if (outputFile) {
const delimiter = `ghadelimiter_${Date.now()}`;
appendFileSync(outputFile, `${name}<<${delimiter}\n${value}\n${delimiter}\n`);
}
}
export function runFilter() {
const filtersInput = process.env.INPUT_FILTERS;
const baseRef = process.env.INPUT_BASE_REF;
if (!filtersInput) {
throw new Error('INPUT_FILTERS is required in filter mode');
}
if (!baseRef) {
throw new Error('INPUT_BASE_REF is required in filter mode');
}
const filters = parseFilters(filtersInput);
const changedFiles = getChangedFiles(baseRef);
console.log(`Changed files (${changedFiles.length}):`);
for (const f of changedFiles) {
console.log(` ${f}`);
}
const results = {};
for (const [name, patterns] of filters) {
const matched = evaluateFilter(changedFiles, patterns);
results[name] = matched;
console.log(`Filter "${name}": ${matched}`);
}
setOutput('results', JSON.stringify(results));
}
// --- Mode: validate ---
export function runValidate() {
const raw = process.env.INPUT_JOB_RESULTS;
if (!raw) {
throw new Error('INPUT_JOB_RESULTS is required in validate mode');
}
const jobResults = JSON.parse(raw);
const problems = [];
for (const [job, data] of Object.entries(jobResults)) {
if (data.result === 'failure') problems.push(`${job}: failed`);
if (data.result === 'cancelled') problems.push(`${job}: cancelled`);
}
if (problems.length > 0) {
console.error('Required checks failed:');
for (const p of problems) {
console.error(` - ${p}`);
}
process.exit(1);
}
console.log('All required checks passed:');
for (const [job, data] of Object.entries(jobResults)) {
console.log(` ${job}: ${data.result}`);
}
}
// --- Main (only when run directly, not when imported by tests) ---
if (resolve(fileURLToPath(import.meta.url)) === resolve(process.argv[1])) {
const mode = process.env.INPUT_MODE;
if (mode === 'filter') {
runFilter();
} else if (mode === 'validate') {
runValidate();
} else {
throw new Error(`Unknown mode: "${mode}". Expected "filter" or "validate".`);
}
}

View file

@ -0,0 +1,56 @@
# Composite action for logging into Docker registries (GHCR and/or DockerHub).
# Centralizes the login pattern used across multiple Docker workflows.
name: 'Docker Registry Login'
description: 'Login to GitHub Container Registry and/or DockerHub'
inputs:
login-ghcr:
description: 'Login to GitHub Container Registry'
required: false
default: 'true'
login-dockerhub:
description: 'Login to DockerHub'
required: false
default: 'false'
login-dhi:
description: 'Login to Docker Hardened Images registry (dhi.io)'
required: false
default: 'false'
dockerhub-username:
description: 'DockerHub username (required if login-dockerhub or login-dhi is true)'
required: false
dockerhub-password:
description: 'DockerHub password (required if login-dockerhub or login-dhi is true)'
required: false
runs:
using: 'composite'
steps:
- name: Login to GitHub Container Registry
if: inputs.login-ghcr == 'true'
shell: bash
env:
GHCR_TOKEN: ${{ github.token }}
GHCR_USER: ${{ github.actor }}
run: |
node .github/scripts/retry.mjs --attempts 3 --delay 10 \
'echo "$GHCR_TOKEN" | docker login ghcr.io -u "$GHCR_USER" --password-stdin'
- name: Login to DockerHub
if: inputs.login-dockerhub == 'true'
shell: bash
env:
DOCKER_USER: ${{ inputs.dockerhub-username }}
DOCKER_PASS: ${{ inputs.dockerhub-password }}
run: |
node .github/scripts/retry.mjs --attempts 3 --delay 10 \
'echo "$DOCKER_PASS" | docker login -u "$DOCKER_USER" --password-stdin'
- name: Login to DHI Registry
if: inputs.login-dhi == 'true'
uses: docker/login-action@b45d80f862d83dbcd57f89517bcf500b2ab88fb2 # v4.0.0
with:
registry: dhi.io
username: ${{ inputs.dockerhub-username }}
password: ${{ inputs.dockerhub-password }}

View file

@ -1,42 +0,0 @@
name: 'Blacksmith Node.js Build Setup'
description: 'Configures Node.js with pnpm, installs dependencies, enables Turborepo caching, (optional) sets up Docker layer caching, and builds the project or an optional command.'
inputs:
node-version:
description: 'Node.js version to use. Uses latest 22.x by default.'
required: false
default: '22.x'
enable-docker-cache:
description: 'Whether to set up Blacksmith Buildx for Docker layer caching.'
required: false
default: 'false'
type: boolean
build-command:
description: 'Command to execute for building the project or an optional command. Leave empty to skip build step.'
required: false
default: 'pnpm build'
type: string
runs:
using: 'composite'
steps:
- name: Setup Node.js
uses: useblacksmith/setup-node@65c6ca86fdeb0ab3d85e78f57e4f6a7e4780b391 # v5.0.4
with:
node-version: ${{ inputs.node-version }}
- name: Setup pnpm and Install Dependencies
uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
with:
run_install: true
- name: Configure Turborepo Cache
uses: useblacksmith/caching-for-turbo@bafb57e7ebdbf1185762286ec94d24648cd3938a # v1
- name: Setup Docker Builder for Docker Cache
if: ${{ inputs.enable-docker-cache == 'true' }}
uses: useblacksmith/setup-docker-builder@0b434dfbb431f4e3a2bcee7a773a56bd363184c5 # v1
- name: Build Project
run: ${{ inputs.build-command }}
shell: bash

View file

@ -1,33 +0,0 @@
name: 'GitHub Node.js Build Setup for Github Hosted Runners'
description: 'Configures Node.js with pnpm, installs dependencies, enables Turborepo caching, and builds the project or an optional command.'
inputs:
node-version:
description: 'Node.js version to use. Uses latest 22.x by default.'
required: false
default: '22.x'
build-command:
description: 'Command to execute for building the project or an optional command. Leave empty to skip build step.'
required: false
default: 'pnpm build'
type: string
runs:
using: 'composite'
steps:
- name: Setup Node.js
uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: ${{ inputs.node-version }}
- name: Setup pnpm and Install Dependencies
uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
with:
run_install: true
- name: Configure Turborepo Cache
uses: rharkor/caching-for-turbo@2b4b5b14a8d16b8556a58993a8ac331d56d8906d # v2.3.2
- name: Build Project
run: ${{ inputs.build-command }}
shell: bash

88
.github/actions/setup-nodejs/action.yml vendored Normal file
View file

@ -0,0 +1,88 @@
# This action works transparently on both Blacksmith and GitHub-hosted runners.
# Blacksmith runners benefit from transparent caching and optional Docker layer caching.
# GitHub-hosted runners use standard GitHub Actions caching.
name: 'Node.js Build Setup'
description: 'Configures Node.js with pnpm, installs Aikido SafeChain for supply chain protection, installs dependencies, enables Turborepo caching, (optional) sets up Docker layer caching, and builds the project or an optional command.'
inputs:
node-version:
description: 'Node.js version to use. Pinned to 24.14.1 by default for reproducible builds.'
required: false
default: '24.14.1'
enable-docker-cache:
description: 'Whether to set up Blacksmith Buildx for Docker layer caching (Blacksmith runners only).'
required: false
default: 'false'
build-command:
description: 'Command to execute for building the project or an optional command. Leave empty to skip build step.'
required: false
default: 'pnpm build'
install-command:
description: 'Command to execute for installing project dependencies. Leave empty to skip install step.'
required: false
default: 'pnpm install --frozen-lockfile'
runs:
using: 'composite'
steps:
- name: Setup pnpm
uses: pnpm/action-setup@b906affcce14559ad1aafd4ab0e942779e9f58b1 # v4.3.0
- name: Setup Node.js
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
with:
node-version: ${{ inputs.node-version }}
cache: 'pnpm'
# To avoid setup-node cache failure.
# see: https://github.com/actions/setup-node/issues/1137
- name: Verify PNPM Cache Directory
shell: bash
run: |
PNPM_STORE_PATH="$( pnpm store path --silent )"
if [ ! -d "$PNPM_STORE_PATH" ]; then
mkdir -p "$PNPM_STORE_PATH"
fi
- name: Install Aikido SafeChain
if: runner.os != 'Windows'
run: |
VERSION="1.4.1"
EXPECTED_SHA256="628235987175072a4255aa3f5f0128f31795b63970f1970ae8a04d07bf8527b0"
node .github/scripts/retry.mjs --attempts 3 --delay 10 \
"curl -fsSL -o install-safe-chain.sh https://github.com/AikidoSec/safe-chain/releases/download/${VERSION}/install-safe-chain.sh"
echo "${EXPECTED_SHA256} install-safe-chain.sh" | sha256sum -c -
sh install-safe-chain.sh --ci
rm install-safe-chain.sh
shell: bash
- name: Install Dependencies
if: ${{ inputs.install-command != '' }}
run: |
${{ inputs.install-command }}
shell: bash
- name: Disable safe-chain
if: runner.os != 'Windows'
run: safe-chain teardown
shell: bash
- name: Configure Turborepo Cache
uses: rharkor/caching-for-turbo@0abc2381e688c4d2832f0665a68a01c6e82f0d6c # v2.3.11
- name: Setup Docker Builder for Docker Cache (Blacksmith)
if: ${{ inputs.enable-docker-cache == 'true' && contains(runner.name, 'blacksmith') }}
uses: useblacksmith/setup-docker-builder@ef12d5b165b596e3aa44ea8198d8fde563eab402 # v1.4.0
- name: Setup Docker Builder (GitHub fallback)
if: ${{ inputs.enable-docker-cache == 'true' && !contains(runner.name, 'blacksmith') }}
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Build Project
if: ${{ inputs.build-command != '' }}
run: |
${{ inputs.build-command }} --summarize
node .github/scripts/send-build-stats.mjs || true
node .github/scripts/send-docker-stats.mjs || true
shell: bash

119
.github/claude-templates/e2e-test.md vendored Normal file
View file

@ -0,0 +1,119 @@
# E2E Test Task Guide
## Required Reading
**Before writing any code**, read these files:
```
packages/testing/playwright/AGENTS.md # Patterns, anti-patterns, entry points
packages/testing/playwright/CONTRIBUTING.md # Detailed architecture (first 200 lines)
```
## Spec Validation
Before starting, verify the spec includes:
| Required | Example |
|----------|---------|
| **File(s) to modify** | `tests/e2e/credentials/crud.spec.ts` |
| **Specific behavior** | "Verify credential renaming updates the list" |
| **Pattern reference** | "Follow existing tests in same file" or "See AGENTS.md" |
**If missing, ask for clarification.** Don't guess at requirements.
## Commands
```bash
# Run single test
pnpm --filter=n8n-playwright test:local tests/e2e/your-test.spec.ts --reporter=list 2>&1 | tail -50
# Run with pattern match
pnpm --filter=n8n-playwright test:local --grep "should do something" --reporter=list 2>&1 | tail -50
# Container tests (requires pnpm build:docker first)
pnpm --filter=n8n-playwright test:container:sqlite --grep @capability:email --reporter=list 2>&1 | tail -50
```
## Test Structure
```typescript
import { test, expect } from '../fixtures/base';
import { nanoid } from 'nanoid';
test('should do something @mode:sqlite', async ({ n8n, api }) => {
// Setup via API (faster, more reliable)
const workflow = await api.workflowApi.createWorkflow(workflowJson);
// UI interaction via entry points
await n8n.start.fromBlankCanvas();
// Assertions
await expect(n8n.workflows.getWorkflowByName(workflow.name)).toBeVisible();
});
```
## Entry Points
Use `n8n.start.*` methods - see `composables/TestEntryComposer.ts`:
- `fromBlankCanvas()` - New workflow
- `fromImportedWorkflow(file)` - Pre-built workflow
- `fromNewProjectBlankCanvas()` - Project-scoped
- `withUser(user)` - Isolated browser context
## Multi-User Tests
```typescript
const member = await api.publicApi.createUser({ role: 'global:member' });
const memberPage = await n8n.start.withUser(member);
await memberPage.navigate.toWorkflows();
```
## Development Process
1. **Validate spec** - Has file, behavior, pattern reference?
2. **Read existing code** - Understand current patterns in the file
3. **Identify helpers needed** - Check `pages/`, `services/`, `composables/`
4. **Add helpers first** if missing
5. **Write test** following 4-layer architecture
6. **Verify iteratively** - Small changes, test frequently
## Mandatory Verification
**Always run before marking complete:**
```bash
# 1. Tests pass (check output for failures - piping loses exit code)
pnpm --filter=n8n-playwright test:local <your-test> --reporter=list 2>&1 | tail -50
# 2. Not flaky (required)
pnpm --filter=n8n-playwright test:local <your-test> --repeat-each 3 --reporter=list 2>&1 | tail -50
# 3. Lint passes
pnpm --filter=n8n-playwright lint 2>&1 | tail -30
# 4. Typecheck passes
pnpm --filter=n8n-playwright typecheck 2>&1 | tail -30
```
**Important:** Piping through `tail` loses the exit code. Always check the output for "failed" or error messages rather than relying on exit codes.
**If any fail, fix before completing.**
## Refactoring Existing Tests
**Always verify tests pass BEFORE making changes:**
```bash
pnpm --filter=n8n-playwright test:local tests/e2e/target-file.spec.ts --reporter=list 2>&1 | tail -50
```
Then make small incremental changes, re-running after each.
## Done Checklist
- [ ] Spec had clear file, behavior, and pattern reference
- [ ] Read `AGENTS.md` and relevant existing code
- [ ] Used `n8n.start.*` entry points
- [ ] Used `nanoid()` for unique IDs (not `Date.now()`)
- [ ] No serial mode, `@db:reset`, or `n8n.api.signin()`
- [ ] Multi-user tests use `n8n.start.withUser()`
- [ ] Tests pass with `--repeat-each 3`
- [ ] Lint and typecheck pass

179
.github/claude-templates/security-fix.md vendored Normal file
View file

@ -0,0 +1,179 @@
# Security Vulnerability Fix Guidelines
## Overview
This guide covers how to fix security vulnerabilities in the n8n codebase. Follow a systematic approach to identify, fix, and verify vulnerabilities in dependencies or base images.
## Decision Tree
```
Is it a direct dependency?
→ Yes: Update in catalog or package.json
→ No: Is it transitive?
→ Yes: Add pnpm override
→ No: Is it base image?
→ Yes: Update Dockerfile, trigger base image workflow
```
## Process Flow
```
Scan → Investigate → Fix → Verify
↓ ↓ ↓ ↓
pnpm pnpm why Update pnpm
build: (trace) deps build:
docker: or docker:
scan override scan
```
## Step-by-Step Process
### 1. Initial Setup
Start with a clean install:
```bash
pnpm install --frozen-lockfile
```
### 2. Scan for Vulnerabilities
Run the Docker scan to verify if the vulnerability exists:
```bash
pnpm build:docker:scan
```
### 3. Investigate the Source
Use `pnpm why` to trace where the vulnerable package is coming from:
```bash
pnpm why <package-name> -r
```
### 4. Determine Fix Strategy
#### Case A: Direct Dependency
If the vulnerable package is a **direct dependency**:
**Update via Catalog** (preferred for shared dependencies):
```yaml
# pnpm-workspace.yaml
catalog:
'@azure/identity': 4.13.0 # Updated version
```
```json
// packages/cli/package.json
{
"dependencies": {
"@azure/identity": "catalog:"
}
}
```
**Or update directly in package.json:**
```json
{
"dependencies": {
"vulnerable-package": "^1.2.3"
}
}
```
Then: `pnpm install`
#### Case B: Transitive Dependency
If the vulnerable package is a **transitive dependency**:
**Add an override** in the root `package.json`:
```json
{
"pnpm": {
"overrides": {
"vulnerable-package": "^1.2.3"
}
}
}
```
**For multiple versions:**
```json
{
"pnpm": {
"overrides": {
"vulnerable-package@3": "^3.2.1",
"vulnerable-package@4": "^4.0.1"
}
}
}
```
Then: `pnpm install`
#### Case C: Base Image / NPM Issue
If the vulnerability comes from the **base Docker image**:
1. Check `docker/images/n8n-base/Dockerfile`
2. Update Node version or Alpine packages if needed
3. Note: Base image rebuild requires manual workflow trigger
### 5. Verify the Fix
```bash
pnpm install
pnpm why <package-name> # Check version updated
pnpm build:docker:scan # Confirm vulnerability resolved
```
## Commit & PR Standards
### Commit Format
```
{type}({scope}): {neutral description}
{Brief neutral context}
Addresses: CVE-XXXX-XXXXX
Refs: {LINEAR-ID}
```
### Type Selection
| Scenario | Type |
|----------|------|
| Dependency update | `fix(deps)` |
| Code vulnerability fix | `fix` |
| License/compliance | `chore` |
| Docker/build hardening | `build` |
### Title Language - USE NEUTRAL LANGUAGE
Commit/PR titles appear in changelogs. Use neutral language:
| ❌ Avoid | ✅ Use Instead |
|----------|----------------|
| CVE-XXXX-XXXXX | (footer only) |
| vulnerability, exploit | issue, concern |
| critical, security fix | improvement, update |
| patch vulnerability | validate, harden, ensure |
### Example Commit
**Good:**
```
fix(deps): update jws to 4.0.1
Updates jws package to latest stable version.
Addresses: CVE-2025-65945
Refs: SEC-412
```
**Bad:**
```
fix(security): patch critical CVE-2025-65945 in jws
```
## Done Checklist
- [ ] `pnpm build:docker:scan` shows no vulnerability for the CVE
- [ ] `pnpm why <package>` shows updated version
- [ ] Commit follows neutral language format (no CVE in title)
- [ ] PR references Linear ticket if provided
## Common Commands
```bash
pnpm install --frozen-lockfile # Initial setup
pnpm build:docker:scan # Scan for vulnerabilities
pnpm why <package-name> -r # Investigate dependency
pnpm install # Update lockfile after changes
pnpm list <package-name> # Check specific package versions
```

View file

@ -1,25 +1,4 @@
services:
mariadb:
image: mariadb:10.5
environment:
- MARIADB_DATABASE=n8n
- MARIADB_ROOT_PASSWORD=password
- MARIADB_MYSQL_LOCALHOST_USER=true
ports:
- 3306:3306
tmpfs:
- /var/lib/mysql
mysql-8.4:
image: mysql:8.4
environment:
- MYSQL_DATABASE=n8n
- MYSQL_ROOT_PASSWORD=password
ports:
- 3306:3306
tmpfs:
- /var/lib/mysql
postgres:
image: postgres:16
restart: always

View file

@ -0,0 +1,43 @@
# METADATA
# title: Unpinned GitHub Action
# description: |-
# GitHub Action not pinned to full commit SHA.
# Pin actions to SHA for supply chain security.
# custom:
# level: error
package rules.unpinned_action
import data.poutine
import rego.v1
rule := poutine.rule(rego.metadata.chain())
# Match 40-character hex SHA (Git) or 64-character sha256 digest (Docker)
is_sha_pinned(uses) if {
regex.match(`@(sha256:[a-f0-9]{64}|[a-f0-9]{40})`, uses)
}
# Check if it's a local action (starts with ./)
is_local_action(uses) if {
startswith(uses, "./")
}
# Check if it's a reusable workflow call
is_reusable_workflow(uses) if {
contains(uses, ".github/workflows/")
}
results contains poutine.finding(rule, pkg.purl, {
"path": workflow.path,
"job": job.id,
"step": i,
"details": sprintf("Action '%s' should be pinned to a full commit SHA", [step.uses]),
}) if {
pkg := input.packages[_]
workflow := pkg.github_actions_workflows[_]
job := workflow.jobs[_]
step := job.steps[i]
step.uses
not is_sha_pinned(step.uses)
not is_local_action(step.uses)
}

View file

@ -10,13 +10,14 @@ Photos and videos are recommended.
<!--
Include links to **Linear ticket** or Github issue or Community forum post.
Important in order to close *automatically* and provide context to reviewers.
https://linear.app/n8n/issue/
https://linear.app/n8n/issue/[TICKET-ID]
-->
<!-- Use "closes #<issue-number>", "fixes #<issue-number>", or "resolves #<issue-number>" to automatically close issues when the PR is merged. -->
## Review / Merge checklist
- [ ] I have seen this code, I have run this code, and I take responsibility for this code.
- [ ] PR title and summary are descriptive. ([conventions](../blob/master/.github/pull_request_title_conventions.md)) <!--
**Remember, the title automatically goes into the changelog.
Use `(no-changelog)` otherwise.**
@ -26,4 +27,4 @@ https://linear.app/n8n/issue/
A bug is not considered fixed, unless a test is added to prevent it from happening again.
A feature is not complete without tests.
-->
- [ ] PR Labeled with `release/backport` (if the PR is an urgent fix that needs to be backported)
- [ ] PR Labeled with `Backport to Beta`, `Backport to Stable`, or `Backport to v1` (if the PR is an urgent fix that needs to be backported)

View file

@ -1,4 +1,5 @@
import semver from 'semver';
import { parse } from 'yaml';
import { writeFile, readFile } from 'fs/promises';
import { resolve } from 'path';
import child_process from 'child_process';
@ -7,14 +8,19 @@ import assert from 'assert';
const exec = promisify(child_process.exec);
/**
* @param {string | semver.SemVer} currentVersion
*/
function generateExperimentalVersion(currentVersion) {
const parsed = semver.parse(currentVersion);
if (!parsed) throw new Error(`Invalid version: ${currentVersion}`);
// Check if it's already an experimental version
if (parsed.prerelease.length > 0 && parsed.prerelease[0] === 'exp') {
const minor = parsed.prerelease[1] || 0;
const minorInt = typeof minor === 'string' ? parseInt(minor) : minor;
// Increment the experimental minor version
const expMinor = (parsed.prerelease[1] || 0) + 1;
const expMinor = minorInt + 1;
return `${parsed.major}.${parsed.minor}.${parsed.patch}-exp.${expMinor}`;
}
@ -22,34 +28,32 @@ function generateExperimentalVersion(currentVersion) {
return `${parsed.major}.${parsed.minor}.${parsed.patch}-exp.0`;
}
function generateRcVersion(currentVersion) {
const parsed = semver.parse(currentVersion);
if (!parsed) throw new Error(`Invalid version: ${currentVersion}`);
// Check if it's already an RC version
if (parsed.prerelease.length > 0 && parsed.prerelease[0] === 'rc') {
// Increment the RC number
const rcNum = (parsed.prerelease[1] || 0) + 1;
return `${parsed.major}.${parsed.minor}.${parsed.patch}-rc.${rcNum}`;
}
// Create new RC version: <major>.<minor>.<patch>-rc.0
return `${parsed.major}.${parsed.minor}.${parsed.patch}-rc.0`;
}
const rootDir = process.cwd();
const releaseType = process.env.RELEASE_TYPE;
assert.match(releaseType, /^(patch|minor|major|experimental|rc)$/, 'Invalid RELEASE_TYPE');
const releaseType = /** @type { import('semver').ReleaseType | "experimental" } */ (
process.env.RELEASE_TYPE
);
assert.match(releaseType, /^(patch|minor|major|experimental|premajor)$/, 'Invalid RELEASE_TYPE');
// TODO: if releaseType is `auto` determine release type based on the changelog
const lastTag = (await exec('git describe --tags --match "n8n@*" --abbrev=0')).stdout.trim();
const packages = JSON.parse((await exec('pnpm ls -r --only-projects --json')).stdout);
const packages = JSON.parse(
(
await exec(
`pnpm ls -r --only-projects --json | jq -r '[.[] | { name: .name, version: .version, path: .path, private: .private}]'`,
)
).stdout,
);
const packageMap = {};
for (let { name, path, version, private: isPrivate, dependencies } of packages) {
if (isPrivate && path !== rootDir) continue;
if (path === rootDir) name = 'monorepo-root';
for (let { name, path, version, private: isPrivate } of packages) {
if (isPrivate && path !== rootDir) {
continue;
}
if (path === rootDir) {
name = 'monorepo-root';
}
const isDirty = await exec(`git diff --quiet HEAD ${lastTag} -- ${path}`)
.then(() => false)
@ -63,6 +67,111 @@ assert.ok(
'No changes found since the last release',
);
// Propagate isDirty transitively: if a package's dependency will be bumped,
// that package also needs a bump (e.g. design-system → editor-ui → cli).
// Detect root-level changes that affect resolved dep versions without touching individual
// package.json files: pnpm.overrides (applies to all specifiers)
// and pnpm-workspace.yaml catalog entries (applies only to deps using a "catalog:…" specifier).
const rootPkgJson = JSON.parse(await readFile(resolve(rootDir, 'package.json'), 'utf-8'));
const rootPkgJsonAtTag = await exec(`git show ${lastTag}:package.json`)
.then(({ stdout }) => JSON.parse(stdout))
.catch(() => ({}));
const getOverrides = (pkg) => ({ ...pkg.pnpm?.overrides, ...pkg.overrides });
const currentOverrides = getOverrides(rootPkgJson);
const previousOverrides = getOverrides(rootPkgJsonAtTag);
const changedOverrides = new Set(
Object.keys({ ...currentOverrides, ...previousOverrides }).filter(
(k) => currentOverrides[k] !== previousOverrides[k],
),
);
const parseWorkspaceYaml = (content) => {
try {
return /** @type {Record<string, unknown>} */ (parse(content) ?? {});
} catch {
return {};
}
};
const workspaceYaml = parseWorkspaceYaml(
await readFile(resolve(rootDir, 'pnpm-workspace.yaml'), 'utf-8').catch(() => ''),
);
const workspaceYamlAtTag = parseWorkspaceYaml(
await exec(`git show ${lastTag}:pnpm-workspace.yaml`)
.then(({ stdout }) => stdout)
.catch(() => ''),
);
const getCatalogs = (ws) => {
const result = new Map();
if (ws.catalog) {
result.set('default', /** @type {Record<string,string>} */ (ws.catalog));
}
for (const [name, entries] of Object.entries(ws.catalogs ?? {})) {
result.set(name, entries);
}
return result;
};
// changedCatalogEntries: Map<catalogName, Set<depName>>
const currentCatalogs = getCatalogs(workspaceYaml);
const previousCatalogs = getCatalogs(workspaceYamlAtTag);
const changedCatalogEntries = new Map();
for (const catalogName of new Set([...currentCatalogs.keys(), ...previousCatalogs.keys()])) {
const current = currentCatalogs.get(catalogName) ?? {};
const previous = previousCatalogs.get(catalogName) ?? {};
const changedDeps = new Set(
Object.keys({ ...current, ...previous }).filter((dep) => current[dep] !== previous[dep]),
);
if (changedDeps.size > 0) {
changedCatalogEntries.set(catalogName, changedDeps);
}
}
// Store full dep objects (with specifiers) so we can inspect "catalog:…" values below.
const depsByPackage = {};
for (const packageName in packageMap) {
const packageFile = resolve(packageMap[packageName].path, 'package.json');
const packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));
depsByPackage[packageName] = /** @type {Record<string,string>} */ (
packageJson.dependencies ?? {}
);
}
// Mark packages dirty if any dep had a root-level override or catalog version change.
for (const [packageName, deps] of Object.entries(depsByPackage)) {
if (packageMap[packageName].isDirty) continue;
for (const [dep, specifier] of Object.entries(deps)) {
if (changedOverrides.has(dep)) {
packageMap[packageName].isDirty = true;
break;
}
if (typeof specifier === 'string' && specifier.startsWith('catalog:')) {
const catalogName = specifier === 'catalog:' ? 'default' : specifier.slice(8);
if (changedCatalogEntries.get(catalogName)?.has(dep)) {
packageMap[packageName].isDirty = true;
break;
}
}
}
}
let changed = true;
while (changed) {
changed = false;
for (const packageName in packageMap) {
if (packageMap[packageName].isDirty) continue;
if (Object.keys(depsByPackage[packageName]).some((dep) => packageMap[dep]?.isDirty)) {
packageMap[packageName].isDirty = true;
changed = true;
}
}
}
// Keep the monorepo version up to date with the released version
packageMap['monorepo-root'].version = packageMap['n8n'].version;
@ -71,17 +180,32 @@ for (const packageName in packageMap) {
const packageFile = resolve(path, 'package.json');
const packageJson = JSON.parse(await readFile(packageFile, 'utf-8'));
packageJson.version = packageMap[packageName].nextVersion =
isDirty ||
Object.keys(packageJson.dependencies || {}).some(
(dependencyName) => packageMap[dependencyName]?.isDirty,
)
? releaseType === 'experimental'
? generateExperimentalVersion(version)
: releaseType === 'rc'
? generateRcVersion(version)
: semver.inc(version, releaseType)
: version;
const dependencyIsDirty = Object.keys(packageJson.dependencies || {}).some(
(dependencyName) => packageMap[dependencyName]?.isDirty,
);
let newVersion = version;
if (isDirty || dependencyIsDirty) {
switch (releaseType) {
case 'experimental':
newVersion = generateExperimentalVersion(version);
break;
case 'premajor':
newVersion = semver.inc(
version,
version.includes('-rc.') ? 'prerelease' : 'premajor',
undefined,
'rc',
);
break;
default:
newVersion = semver.inc(version, releaseType);
break;
}
}
packageJson.version = packageMap[packageName].nextVersion = newVersion;
await writeFile(packageFile, JSON.stringify(packageJson, null, 2) + '\n');
}

View file

@ -0,0 +1,68 @@
#!/usr/bin/env node
/**
* Builds the Claude task prompt and writes it to GITHUB_ENV.
* Uses a random delimiter to prevent heredoc collision with user input.
*
* Usage: node prepare-claude-prompt.mjs
*
* Environment variables:
* INPUT_TASK - The task description (required)
* USE_RAW_PROMPT - "true" to pass task directly without wrapping
* GITHUB_ENV - Path to GitHub env file (set by Actions)
*/
import { randomUUID } from 'node:crypto';
import { appendFileSync, readdirSync } from 'node:fs';
const task = process.env.INPUT_TASK;
const useRaw = process.env.USE_RAW_PROMPT === 'true';
const envFile = process.env.GITHUB_ENV;
if (!task) {
console.error('INPUT_TASK environment variable is required');
process.exit(1);
}
if (!envFile) {
console.error('GITHUB_ENV environment variable is required');
process.exit(1);
}
let prompt;
if (useRaw) {
prompt = task;
} else {
// List available templates so Claude knows what exists (reads them if needed)
const templateDir = '.github/claude-templates';
let templateSection = '';
try {
const files = readdirSync(templateDir).filter((f) => f.endsWith('.md'));
if (files.length > 0) {
const listing = files.map((f) => ` - ${templateDir}/${f}`).join('\n');
templateSection = `\n# Templates\nThese guides are available if relevant to your task. Read any that match before starting:\n${listing}`;
}
} catch {
// No templates directory, skip
}
prompt = `# Task
${task}
${templateSection}
# Instructions
1. Read any relevant templates listed above before starting
2. Complete the task described above
3. Make commits as you work - the last commit message will be used as the PR title
4. IMPORTANT: End every commit message with: Co-authored-by: Claude <noreply@anthropic.com>
5. Ensure code passes linting and type checks before finishing
# Token Optimization
When running lint/typecheck, suppress verbose output:
pnpm lint 2>&1 | tail -30
pnpm typecheck 2>&1 | tail -30`;
}
// Random delimiter guarantees no collision with user content
const delimiter = `CLAUDE_PROMPT_DELIM_${randomUUID().replace(/-/g, '')}`;
appendFileSync(envFile, `CLAUDE_PROMPT<<${delimiter}\n${prompt}\n${delimiter}\n`);

View file

@ -0,0 +1,59 @@
#!/usr/bin/env node
/**
* Sends a callback to the resume URL with the Claude task result.
* Uses fetch() directly to avoid E2BIG errors from shell argument limits.
*
* Usage: node resume-callback.mjs
*
* Environment variables:
* RESUME_URL - Callback URL to POST to (required)
* EXECUTION_FILE - Path to Claude's execution output JSON (optional)
* CLAUDE_OUTCOME - "success" or "failure" (required)
* CLAUDE_SESSION_ID - Session ID for resuming conversations (optional)
* BRANCH_NAME - Git branch name (optional)
*/
import { existsSync, readFileSync } from 'node:fs';
const resumeUrl = process.env.RESUME_URL;
const executionFile = process.env.EXECUTION_FILE;
const claudeOutcome = process.env.CLAUDE_OUTCOME;
const sessionId = process.env.CLAUDE_SESSION_ID ?? '';
const branchName = process.env.BRANCH_NAME ?? '';
if (!resumeUrl) {
console.error('RESUME_URL environment variable is required');
process.exit(1);
}
const success = claudeOutcome === 'success';
let result = null;
if (executionFile && existsSync(executionFile)) {
try {
const execution = JSON.parse(readFileSync(executionFile, 'utf-8'));
// Extract the last element (Claude's final result message)
result = Array.isArray(execution) ? execution.at(-1) : execution;
} catch (err) {
console.warn(`Failed to parse execution file: ${err.message}`);
}
}
const payload = JSON.stringify({ success, branch: branchName, sessionId, result });
try {
const response = await fetch(resumeUrl, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: payload,
});
if (!response.ok) {
const body = await response.text();
console.error(`Callback failed: ${body}`);
process.exit(1);
}
} catch (err) {
console.error(`Callback error: ${err.message}`);
process.exit(1);
}

157
.github/scripts/cleanup-ghcr-images.mjs vendored Normal file
View file

@ -0,0 +1,157 @@
#!/usr/bin/env node
/**
* Cleanup GHCR images for n8n CI
*
* Modes:
* --tag <tag> Delete exact tag (post-run cleanup)
* --stale <days> Delete ci-* images older than N days (daily scheduled cleanup)
*
* Context:
* - Each CI run tags images as ci-{run_id}
* - Post-run cleanup uses --tag to delete the current run's images
* - Daily cron uses --stale to catch any orphaned images
*/
import { exec } from 'node:child_process';
import { promisify } from 'node:util';
const execAsync = promisify(exec);
const ORG = process.env.GHCR_ORG || 'n8n-io';
const REPO = process.env.GHCR_REPO || 'n8n';
const PACKAGES = [REPO, 'runners'];
const [mode, rawValue] = process.argv.slice(2);
if (!['--tag', '--stale'].includes(mode) || !rawValue) {
console.error('Usage: cleanup-ghcr-images.mjs --tag <tag> | --stale <days>');
process.exit(1);
}
const value = mode === '--stale' ? parseInt(rawValue, 10) : rawValue;
if (mode === '--stale' && (isNaN(value) || value <= 0)) {
console.error('Error: --stale requires a positive number of days');
process.exit(1);
}
async function ghApi(path) {
const { stdout } = await execAsync(
`gh api "/orgs/${ORG}/packages/container/${path}"`,
);
return JSON.parse(stdout);
}
async function ghDelete(path) {
await execAsync(`gh api --method DELETE "/orgs/${ORG}/packages/container/${path}"`);
}
async function fetchPage(pkg, page) {
try {
return await ghApi(`${pkg}/versions?per_page=100&page=${page}`);
} catch (err) {
if (err.code === 1 && err.stderr?.includes('404')) return [];
throw new Error(`Failed to fetch ${pkg} page ${page}: ${err.message}`);
}
}
const isCiImage = (v) => {
const tags = v.metadata?.container?.tags || [];
return tags.some((t) => t.startsWith('ci-') || t.startsWith('pr-'));
};
const isStale = (v, days) => {
const cutoff = Date.now() - days * 86400000;
return isCiImage(v) && new Date(v.created_at) < cutoff;
};
async function getVersionsForTag(pkg, tag) {
const batch = await fetchPage(pkg, 1);
const match = batch.find((v) => v.metadata?.container?.tags?.includes(tag));
return match ? [match] : [];
}
async function getVersionsForStale(pkg, days) {
const versions = [];
const cutoff = Date.now() - days * 86400000;
// Use 2x cutoff as safety window for early termination
const earlyExitCutoff = Date.now() - days * 2 * 86400000;
let pagesWithoutCiImages = 0;
const firstPage = await fetchPage(pkg, 1);
if (!firstPage.length) return [];
for (const v of firstPage) {
if (isStale(v, days)) versions.push(v);
}
if (firstPage.length < 100) return versions;
for (let page = 2; ; page += 10) {
const batches = await Promise.all(
Array.from({ length: 10 }, (_, i) => fetchPage(pkg, page + i)),
);
let done = false;
for (const batch of batches) {
if (!batch.length || batch.length < 100) done = true;
let hasCiImages = false;
for (const v of batch) {
if (isCiImage(v)) {
hasCiImages = true;
if (new Date(v.created_at) < cutoff) versions.push(v);
}
}
// Early termination: if we've gone through pages without finding
// any CI images and all items are older than 2x cutoff, we're past
// the CI image window
if (!hasCiImages) {
pagesWithoutCiImages++;
const oldestInBatch = batch[batch.length - 1];
if (
pagesWithoutCiImages >= 3 &&
oldestInBatch &&
new Date(oldestInBatch.created_at) < earlyExitCutoff
) {
console.log(` Early termination at page ${page + batches.indexOf(batch)}`);
done = true;
}
} else {
pagesWithoutCiImages = 0;
}
if (!batch.length || done) break;
}
if (done) break;
}
return versions;
}
let hasErrors = false;
for (const pkg of PACKAGES) {
console.log(`Processing ${pkg}...`);
let consecutiveErrors = 0;
const toDelete =
mode === '--tag'
? await getVersionsForTag(pkg, value)
: await getVersionsForStale(pkg, value);
if (!toDelete.length) {
console.log(` No matching images found`);
continue;
}
for (const v of toDelete) {
try {
await ghDelete(`${pkg}/versions/${v.id}`);
console.log(` Deleted ${v.metadata.container.tags.join(',')}`);
consecutiveErrors = 0;
} catch (err) {
console.error(` Failed to delete ${v.id}: ${err.message}`);
hasErrors = true;
if (++consecutiveErrors >= 3) {
throw new Error('Too many consecutive delete failures, aborting');
}
}
}
}
if (hasErrors) process.exit(1);

View file

@ -0,0 +1,123 @@
import fs from 'node:fs/promises';
import { getOctokit } from '@actions/github';
import { ensureEnvVar, readPrLabels } from './github-helpers.mjs';
/**
* @typedef {PullRequestCheckPass | PullRequestCheckFail} PullRequestCheckResult
**/
/**
* @typedef PullRequestCheckPass
* @property {true} pass
* @property {string} baseRef
* */
/**
* @typedef PullRequestCheckFail
* @property {false} pass
* @property {string} reason
* */
/**
* @param {PullRequestCheckResult} pullRequestCheck
*
* @returns { pullRequestCheck is PullRequestCheckFail }
* */
function pullRequestCheckFailed(pullRequestCheck) {
return !pullRequestCheck.pass;
}
/**
* @param {any} pullRequest
* @returns {PullRequestCheckResult}
*/
export function pullRequestIsDismissedRelease(pullRequest) {
if (!pullRequest) {
throw new Error('Missing pullRequest in event payload');
}
const baseRef = pullRequest?.base?.ref ?? '';
const headRef = pullRequest?.head?.ref ?? '';
const merged = Boolean(pullRequest?.merged);
if (merged) {
return { pass: false, reason: 'PR was merged' };
}
// Must match your release PR pattern:
// base: release/<ver>
// head: release-pr/<ver>
if (!baseRef.startsWith('release/')) {
return { pass: false, reason: `Base ref '${baseRef}' is not release/*` };
}
if (!headRef.startsWith('release-pr/')) {
return { pass: false, reason: `Head ref '${headRef}' is not release-pr/*` };
}
const baseVer = baseRef.slice('release/'.length);
const headVer = headRef.slice('release-pr/'.length);
if (!baseVer || baseVer !== headVer) {
return { pass: false, reason: `Version mismatch: base='${baseVer}' head='${headVer}'` };
}
const labelNames = readPrLabels(pullRequest);
if (!labelNames.includes('release')) {
return {
pass: false,
reason: `Missing required label 'release' (labels: ${labelNames.join(', ') || '[none]'})`,
};
}
return { pass: true, baseRef };
}
async function main() {
const token = ensureEnvVar('GITHUB_TOKEN');
const eventPath = ensureEnvVar('GITHUB_EVENT_PATH');
const repoFullName = ensureEnvVar('GITHUB_REPOSITORY');
const [owner, repo] = repoFullName.split('/');
if (!owner || !repo) {
throw new Error(`Invalid GITHUB_REPOSITORY: '${repoFullName}'`);
}
const rawEventData = await fs.readFile(eventPath, 'utf8');
const event = JSON.parse(rawEventData);
const result = pullRequestIsDismissedRelease(event.pull_request);
if (pullRequestCheckFailed(result)) {
console.log(`no-op: ${result.reason}`);
return;
}
const branch = result.baseRef; // e.g. "release/2.11.0"
console.log(`PR qualifies. Deleting branch '${branch}'...`);
const octokit = getOctokit(token);
try {
await octokit.rest.git.deleteRef({
owner,
repo,
// ref must be "heads/<branch>"
ref: `heads/${branch}`,
});
console.log(`Deleted '${branch}'.`);
} catch (err) {
// If it was already deleted, treat as success.
const status = err?.status;
if (status === 404) {
console.log(`Branch '${branch}' not found (already deleted).`);
return;
}
console.error(err);
throw new Error(`Failed to delete '${branch}'.`);
}
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
await main();
}

View file

@ -0,0 +1,147 @@
import { describe, it, mock, before } from 'node:test';
import assert from 'node:assert/strict';
import { readPrLabels } from './github-helpers.mjs';
/**
* Run these tests by running
*
* node --test --experimental-test-module-mocks ./.github/scripts/cleanup-release-branch.test.mjs
* */
// mock.module must be called before the module under test is imported,
// because static imports are hoisted and resolve before any code runs.
mock.module('./github-helpers.mjs', {
namedExports: {
ensureEnvVar: () => {}, // no-op
readPrLabels: (pr) => {
return readPrLabels(pr);
},
},
});
let pullRequestIsDismissedRelease;
before(async () => {
({ pullRequestIsDismissedRelease } = await import('./cleanup-release-branch.mjs'));
});
describe('pullRequestIsDismissedRelease', () => {
it('Recognizes classic dismissed pull request', () => {
const pullRequest = {
merged: false,
labels: ['release'],
base: {
ref: 'release/2.9.0',
},
head: {
ref: 'release-pr/2.9.0',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, true);
assert.equal(result.reason, undefined);
});
it("Doesn't pass PR with malformed head", () => {
const pullRequest = {
merged: false,
labels: ['release'],
base: {
ref: 'release/2.9.0',
},
head: {
ref: 'my-fork-release-pr/2.9.0',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, false);
assert.equal(result.reason, `Head ref '${pullRequest.head.ref}' is not release-pr/*`);
});
it("Doesn't pass PR with malformed base", () => {
const pullRequest = {
merged: false,
labels: ['release'],
base: {
ref: 'master',
},
head: {
ref: 'release-pr/2.9.0',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, false);
assert.equal(result.reason, `Base ref '${pullRequest.base.ref}' is not release/*`);
});
it("Doesn't pass merged PR's", () => {
const pullRequest = {
merged: true,
labels: ['release'],
base: {
ref: 'release/2.9.0',
},
head: {
ref: 'release-pr/2.9.0',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, false);
assert.equal(result.reason, `PR was merged`);
});
it("Doesn't pass on PR version mismatch", () => {
const pullRequest = {
merged: false,
labels: ['release'],
base: {
ref: 'release/2.9.0',
},
head: {
ref: 'release-pr/2.9.1',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, false);
assert.equal(
result.reason,
`Version mismatch: base='${pullRequest.base.ref.replace('release/', '')}' head='${pullRequest.head.ref.replace('release-pr/', '')}'`,
);
});
it("Doesn't pass a PR with missing 'release' label", () => {
const pullRequest = {
merged: false,
labels: ['release-pr', 'core-team'],
base: {
ref: 'release/2.9.0',
},
head: {
ref: 'release-pr/2.9.0',
},
};
/** @type { import('./cleanup-release-branch.mjs').PullRequestCheckResult } */
const result = pullRequestIsDismissedRelease(pullRequest);
assert.equal(result.pass, false);
assert.equal(
result.reason,
`Missing required label 'release' (labels: ${pullRequest.labels.join(', ')})`,
);
});
});

View file

@ -0,0 +1,109 @@
// Creates backport PR's according to labels on merged PR
import {
getPullRequestById,
readPrLabels,
resolveRcBranchForTrack,
writeGithubOutput,
} from './github-helpers.mjs';
/** @type { Record<string, import('./github-helpers.mjs').ReleaseTrack> } */
const BACKPORT_BY_TAG_MAP = {
'Backport to Beta': 'beta',
'Backport to Stable': 'stable',
};
const BACKPORT_BY_BRANCH_MAP = {
'Backport to v1': '1.x',
};
/**
* @param {Set<string>} labels
*
* @returns { Set<string> }
*/
export function labelsToReleaseCandidateBranches(labels) {
const targets = new Set();
// Backport by tag map includes mapping of label to git tag to resolve
for (const [label, tag] of Object.entries(BACKPORT_BY_TAG_MAP)) {
// Check if backport label is present
if (!labels.has(label)) {
continue;
}
const branch = resolveRcBranchForTrack(tag);
// Make sure our backport branch exists
if (!branch) {
continue;
}
targets.add(branch);
}
// Backport by branch map includes mapping of label to git branch. This is used for
// older versions of n8n. v1, etc.
for (const [label, branch] of Object.entries(BACKPORT_BY_BRANCH_MAP)) {
// Check if backport label is present
if (!labels.has(label)) {
continue;
}
targets.add(branch);
}
return targets;
}
/**
* This script is called in 2 cases:
*
* 1. When a PR is merged, in which case functions like `readPrLabels` reads PR info from GITHUB_EVENT_PATH
* 2. Manually via Workflow Dispatch, where a Pull Request ID is passed as an env parameter
*
* @returns { Promise<undefined | any> } Pull request object, if ID was provided in env params
*/
async function fetchPossiblePullRequestFromEnv() {
const pullRequestEnv = process.env.PULL_REQUEST_ID;
if (!pullRequestEnv) {
// No ID provided, will proceed to read data from GITHUB_EVENT_PATH
return undefined;
}
const pullRequestNumber = parseInt(pullRequestEnv);
if (isNaN(pullRequestNumber)) {
throw new Error(
"PULL_REQUEST_ID must be a number. It shouldn't contain any other symbols (#, PR, etc.)",
);
}
return await getPullRequestById(pullRequestNumber);
}
export async function getLabels() {
const pullRequest = await fetchPossiblePullRequestFromEnv();
return new Set(readPrLabels(pullRequest));
}
async function main() {
const labels = await getLabels();
if (!labels || labels.size === 0) {
console.log('No labels on PR. Exiting...');
return;
}
const backportBranches = labelsToReleaseCandidateBranches(labels);
if (backportBranches.size === 0) {
console.log('No backports needed. Exiting...');
return;
}
const target_branches = [...backportBranches].join(' '); // korthout/backport-action@v4 uses space-delimited branch list
writeGithubOutput({ target_branches });
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
await main();
}

View file

@ -0,0 +1,104 @@
import { describe, it, mock, before } from 'node:test';
import assert from 'node:assert/strict';
import { readPrLabels } from './github-helpers.mjs';
/**
* Run these tests by running
*
* node --test --experimental-test-module-mocks ./.github/scripts/compute-backport-targets.test.mjs
* */
// mock.module must be called before the module under test is imported,
// because static imports are hoisted and resolve before any code runs.
mock.module('./github-helpers.mjs', {
namedExports: {
ensureEnvVar: () => {}, // no-op
readPrLabels: readPrLabels,
resolveRcBranchForTrack: mockResolveRcBranchForTrack,
writeGithubOutput: () => {}, //no-op
getPullRequestById: () => {
return {
labels: ['n8n team', 'Backport to Beta'],
};
},
},
});
function mockResolveRcBranchForTrack(track) {
switch (track) {
case 'beta':
return 'release-candidate/2.10.1';
case 'stable':
return 'release-candidate/2.9.4';
}
return undefined;
}
let labelsToReleaseCandidateBranches, getLabels;
before(async () => {
({ labelsToReleaseCandidateBranches, getLabels } = await import(
'./compute-backport-targets.mjs'
));
});
describe('Compute backport targets', () => {
it('Finds backport branches for pointer tag labels', () => {
const labels = new Set(['Backport to Beta', 'Backport to Stable']);
/** @type { Set<string> } */
const result = labelsToReleaseCandidateBranches(labels);
assert.equal(result.size, 2);
assert.ok(result.has('release-candidate/2.10.1'));
assert.ok(result.has('release-candidate/2.9.4'));
});
it("Doesn't parse other labes to backport branches", () => {
const labels = new Set(['n8n team', 'release']);
/** @type { Set<string> } */
const result = labelsToReleaseCandidateBranches(labels);
assert.equal(result.size, 0);
});
it("Doesn't parse malformed backport labels", () => {
const labels = new Set(['Backport to Fork', 'Backport to my Home']);
/** @type { Set<string> } */
const result = labelsToReleaseCandidateBranches(labels);
assert.equal(result.size, 0);
});
it('Should parse labels properly in Pull request context', async () => {
process.env.GITHUB_EVENT_PATH = './fixtures/mock-github-event.json';
/** @type { Set<string> } */
const labels = await getLabels();
assert.equal(labels.size, 2);
assert.ok(labels.has('release'));
assert.ok(labels.has('Backport to Stable'));
});
it('Should parse labels properly in manual workflow context', async () => {
process.env.PULL_REQUEST_ID = '123';
/** @type { Set<string> } */
const labels = await getLabels();
assert.equal(labels.size, 2);
assert.ok(labels.has('n8n team'));
assert.ok(labels.has('Backport to Beta'));
});
it('Should throw when passed pull request id with #', async () => {
process.env.PULL_REQUEST_ID = '#123';
await assert.rejects(getLabels);
});
it('Should not throw when passed pull request id with just a number', async () => {
process.env.PULL_REQUEST_ID = '123';
await assert.doesNotReject(getLabels);
});
it('Should throw when passed pull request id with other than numbers included', async () => {
process.env.PULL_REQUEST_ID = 'abc-123';
await assert.rejects(getLabels);
});
});

View file

@ -0,0 +1,81 @@
import {
deleteRelease,
ensureEnvVar,
getExistingRelease,
initGithub,
isReleaseTrack,
writeGithubOutput,
} from './github-helpers.mjs';
/**
* Creates release in GitHub.
*
* Required env variables:
* - RELEASE_TAG - Release tag on git e.g. n8n@2.13.0
* - BODY - Body of the release. Contains release notes etc.
* - IS_PRE_RELEASE - If releasing in pre-release. Currently only for beta track.
* - MAKE_LATEST - If released version should be marked as latest on GitHub
* - COMMIT - Commitish for release to point to
*
* Optional env variables:
* - ADDITIONAL_TAGS - Comma-separated list of additional tags to release under e.g. beta
*
* GitHub variables
* - GITHUB_TOKEN - Used to authenticate to octokit - Can be overwritten for privileged access
* - GITHUB_REPOSITORY - Used to determine target repository
* */
async function createGitHubRelease() {
const RELEASE_TAG = ensureEnvVar('RELEASE_TAG');
const ADDITIONAL_TAGS = process.env.ADDITIONAL_TAGS ?? '';
const BODY = ensureEnvVar('BODY');
const IS_PRE_RELEASE = ensureEnvVar('IS_PRE_RELEASE');
const MAKE_LATEST = ensureEnvVar('MAKE_LATEST');
const COMMIT = ensureEnvVar('COMMIT');
const { octokit, owner, repo } = initGithub();
const allTags = [
RELEASE_TAG,
...ADDITIONAL_TAGS.split(',')
.map((t) => t.trim())
.filter(Boolean),
];
const releases = [];
for (const tag of allTags) {
const existingRelease = await getExistingRelease(tag);
const isReleaseTrackTag = isReleaseTrack(tag);
// If we have an existing track release, we want to
// delete the old release before pushing a new one.
if (isReleaseTrackTag && existingRelease) {
await deleteRelease(existingRelease.id);
}
const releaseResponse = await octokit.rest.repos.createRelease({
tag_name: tag,
name: tag,
body: BODY,
draft: false,
prerelease: IS_PRE_RELEASE === 'true',
make_latest: MAKE_LATEST === 'true' ? 'true' : 'false',
target_commitish: COMMIT,
owner,
repo,
});
const release = releaseResponse.data;
releases.push(release);
console.log(`Successfully created release ${release.html_url}`);
}
writeGithubOutput({
release_urls: releases.map((release) => release.html_url).join(', '),
});
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
createGitHubRelease();
}

104
.github/scripts/detect-new-packages.mjs vendored Normal file
View file

@ -0,0 +1,104 @@
/**
* Detects packages in the monorepo that have not yet been published to npm.
*
* Packages that are new (never published) cannot be released via OIDC Trusted
* Publishing because Trusted Publishing requires the package to already exist
* on npm with the publisher configured first.
*
* New packages must be handled manually:
* 1. Published once using an NPM token
* 2. Configured with Trusted Publishing on npmjs.com
*
* Exit codes:
* 0 All public packages exist on npm
* 1 One or more public packages have never been published
*/
import child_process from 'child_process';
import { promisify } from 'util';
import { writeGithubOutput } from './github-helpers.mjs';
const exec = promisify(child_process.exec);
const packages = JSON.parse(
(
await exec(
`pnpm ls -r --only-projects --json | jq -r '[.[] | { name:.name, private: .private}]'`,
)
).stdout,
);
const newPackages = [];
for (const { name, private: isPrivate } of packages) {
if (isPrivate) continue;
// Scoped packages must be encoded: @n8n/foo → @n8n%2Ffoo
const encodedName = name.startsWith('@') ? name.replace('/', '%2F') : name;
const url = `https://registry.npmjs.org/${encodedName}`;
try {
console.log(`Checking if ${name} exists...`);
const response = await fetch(url, { method: 'HEAD' });
if (response.status === 404) {
newPackages.push(name);
} else if (!response.ok && response.status !== 405) {
// 405 = Method Not Allowed for HEAD (some registries), not an error
console.log(
`::warning::Unexpected HTTP ${response.status} when checking npm registry for "${name}". Skipping check.`,
);
}
} catch (error) {
console.log(
`::warning::Could not reach npm registry for "${name}": ${error.message}. Skipping check.`,
);
}
}
if (newPackages.length === 0) {
const publicCount = packages.filter((p) => !p.private).length;
console.log(`✅ All ${publicCount} public packages exist on npm.`);
process.exit(0);
}
console.log(`
New unpublished packages detected!
The following packages do not yet exist on npm and cannot be published via
OIDC Trusted Publishing until they have been published at least once manually:
`);
for (const pkg of newPackages) {
console.log(
`::error::Package "${pkg}" has never been published to npm. A manual first-publish with an NPM token is required before it can use OIDC Trusted Publishing.`,
);
}
console.log(`
Steps to unblock the release, for each new package listed above:
1. Publish the package once manually using an NPM token:
cd to/where/package/lives
pnpm login
pnpm publish --access public
2. Configure Trusted Publishing on npmjs.com for each new package:
https://docs.npmjs.com/trusted-publishers
Use the following settings:
Repository owner : n8n-io
Repository name : n8n
Workflow filename: release-publish.yml
3. Re-run the Release: Publish workflow.
`);
const output = {
packages: newPackages.join(','),
};
console.log(` -- Writing to github output: ${JSON.stringify(output)}`);
writeGithubOutput(output);
process.exit(1);

View file

@ -0,0 +1,52 @@
import {
ensureEnvVar,
listCommitsBetweenRefs,
resolveRcBranchForTrack,
resolveReleaseTagForTrack,
writeGithubOutput,
} from './github-helpers.mjs';
function main() {
const track = /** @type { import('./github-helpers.mjs').ReleaseTrack } */ (
ensureEnvVar('TRACK')
);
const currentTag = resolveReleaseTagForTrack(track);
const releaseCandidateBranch = resolveRcBranchForTrack(track);
if (!currentTag?.tag || !releaseCandidateBranch) {
throw new Error(
`Couldn't resolve needed parameters. currentTag.tag=${currentTag?.tag}, releaseCandidateBranch=${releaseCandidateBranch}`,
);
}
console.log(`Commits between ${releaseCandidateBranch} and ${currentTag.tag}:`);
console.log(listCommitsBetweenRefs(releaseCandidateBranch, currentTag.tag));
const commitList = listCommitsBetweenRefs(releaseCandidateBranch, currentTag.tag)
.split('\n')
.filter((commit) => commit.trim().length > 0);
const actionableCommitList = filterActionableCommits(commitList);
const output = {
release_candidate_branch: releaseCandidateBranch,
should_update: actionableCommitList.length > 0 ? 'true' : 'false',
};
console.log(output);
writeGithubOutput(output);
}
/**
* @param { string[] } commitList
* */
export function filterActionableCommits(commitList) {
return commitList.filter((commit) => !commit.trimStart().startsWith('ci:'));
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}

View file

@ -0,0 +1,46 @@
import { ensureEnvVar, sh, writeGithubOutput } from './github-helpers.mjs';
function determineReleaseVersionChanges() {
const previousVersion = ensureEnvVar('PREVIOUS_VERSION_TAG');
const releaseVersion = ensureEnvVar('RELEASE_VERSION_TAG');
const log = sh('git', [
'--no-pager',
'log',
'--format="%s (%h)"',
`${previousVersion}..${releaseVersion}`,
]);
writeGithubOutput({
has_node_enhancements: hasNodeEnhancements(log),
has_core_changes: hasCoreChanges(log),
});
}
/**
* Matches commit messages with
*
* fix(nodes)
* fix(xyz Node)
* feat(nodes)
* feat(xyz Node)
*
* @param {string} log
*/
export function hasNodeEnhancements(log) {
return /(fix|feat)\((.*Node|nodes)\)/.test(log);
}
/**
* Matches commit messages with feat(core) or feat(editor)
*
* @param {string} log
*/
export function hasCoreChanges(log) {
return /feat\((core|editor)\)/.test(log);
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
determineReleaseVersionChanges();
}

View file

@ -0,0 +1,47 @@
import { describe, it, mock, before } from 'node:test';
import assert from 'node:assert/strict';
/**
* Run these tests by running
*
* node --test --experimental-test-module-mocks ./.github/scripts/determine-release-version-changes.test.mjs
* */
// mock.module must be called before the module under test is imported,
// because static imports are hoisted and resolve before any code runs.
mock.module('./github-helpers.mjs', {
namedExports: {
ensureEnvVar: () => {}, // no-op
sh: () => {}, // no-op
writeGithubOutput: () => {}, // no-op
},
});
let hasNodeEnhancements, hasCoreChanges;
before(async () => {
({ hasNodeEnhancements, hasCoreChanges } = await import(
'./determine-release-version-changes.mjs'
));
});
describe('Determine release version changes', () => {
it('Matches nodes feature', () => {
assert.ok(hasNodeEnhancements('feat(nodes): Added a utility for node'));
});
it('Matches nodes fix', () => {
assert.ok(hasNodeEnhancements('fix(nodes): Fix said utility'));
});
it('Matches named node feature', () => {
assert.ok(hasNodeEnhancements('feat(Github Actions Node): Add ability to call webhooks'));
});
it('Matches named node fix', () => {
assert.ok(hasNodeEnhancements('fix(OpenAI Node): Allow credentials to pass through'));
});
it('Matches core changes', () => {
assert.ok(hasCoreChanges('feat(core): Add cli flag'));
});
it('Matches editor changes', () => {
assert.ok(hasCoreChanges('feat(editor): Add button'));
});
});

View file

@ -0,0 +1,138 @@
import { readFileSync } from 'node:fs';
import {
RELEASE_TRACKS,
resolveReleaseTagForTrack,
tagVersionInfoToReleaseCandidateBranchName,
writeGithubOutput,
} from './github-helpers.mjs';
import semver from 'semver';
/**
* @param {any} packageVersion
*/
export function determineTrack(packageVersion) {
if (!semver.valid(packageVersion)) {
throw new Error(`Package semver not valid. Got ${packageVersion}`);
}
/** @type { Partial<Record<import('./github-helpers.mjs').ReleaseTrack, import('./github-helpers.mjs').TagVersionInfo>> } */
const trackToReleaseMap = {};
for (const t of RELEASE_TRACKS) {
trackToReleaseMap[t] = resolveReleaseTagForTrack(t);
}
console.log('Current Tracks: ', JSON.stringify(trackToReleaseMap, null, 4));
let track = null;
let newStable = null;
let bump = determineBump(packageVersion);
const releaseType = determineReleaseType(packageVersion);
// Check through our current release versions, if semver matches,
// we inherit the track pointer from them
for (const [releaseTrack, tagVersionInfo] of Object.entries(trackToReleaseMap)) {
if (tagVersionInfo && matchesTrack(tagVersionInfo, packageVersion)) {
track = releaseTrack;
break;
}
}
if (!track) {
if (!trackToReleaseMap.beta?.version) {
throw new Error(
'Likely updating to new beta release, but no existing beta tag was found in git.',
);
}
// If not track was found in current versions, we verify we're building a
// new beta version and the input is not invalid.
assertNewBetaRelease(trackToReleaseMap.beta.version, packageVersion);
track = 'beta';
newStable = trackToReleaseMap.beta.version;
}
if (!track) {
throw new Error('Could not determine track for release. Exiting...');
}
const rc_branch = tagVersionInfoToReleaseCandidateBranchName({
version: packageVersion,
tag: /** @type {import('./github-helpers.mjs').ReleaseVersion} */ (`n8n@${packageVersion}`),
});
const previousVersion = trackToReleaseMap[track]?.version;
const output = {
previous_version: previousVersion,
version: packageVersion,
track,
bump,
new_stable_version: newStable,
release_type: releaseType,
rc_branch,
};
writeGithubOutput(output);
console.log(
`Determined track info: ${Object.entries(output)
.map(([key, val]) => `${key}=${val}`)
.join(', ')}`,
);
return output;
}
/**
* The current version matches the track, if their Major and Minor semvers match.
*
* This means that we are working with a patch release
*
* @param {import("./github-helpers.mjs").TagVersionInfo} tagVersionInfo
* @param {any} currentVersion
*/
function matchesTrack(tagVersionInfo, currentVersion) {
if (semver.major(tagVersionInfo.version) !== semver.major(currentVersion)) {
return false;
}
if (semver.minor(tagVersionInfo.version) !== semver.minor(currentVersion)) {
return false;
}
return true;
}
/**
* @param {string} currentBetaVersion
* @param {any} currentVersion
*/
function assertNewBetaRelease(currentBetaVersion, currentVersion) {
if (semver.major(currentBetaVersion) !== semver.major(currentVersion)) {
throw new Error('Major version bumps are not allowed by this pipeline');
}
const bumpedCurrentBeta = semver.inc(currentBetaVersion, 'minor');
if (semver.minor(bumpedCurrentBeta) !== semver.minor(currentVersion)) {
throw new Error(
`Trying to upgrade minor version by more than one increment. Previous: ${bumpedCurrentBeta}, Requested: ${currentVersion}`,
);
}
}
function determineReleaseType(currentVersion) {
if (currentVersion.includes('-rc.')) {
return 'rc';
}
return 'stable';
}
function determineBump(currentVersion) {
if (semver.patch(currentVersion) === 0 && determineReleaseType(currentVersion) != 'rc') {
return 'minor';
}
return 'patch';
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
const packageJson = JSON.parse(readFileSync('./package.json', 'utf8'));
determineTrack(packageJson.version);
}

View file

@ -0,0 +1,107 @@
import { describe, it, mock, before } from 'node:test';
import assert from 'node:assert/strict';
import { tagVersionInfoToReleaseCandidateBranchName } from './github-helpers.mjs';
/**
* Run these tests by running
*
* node --test --experimental-test-module-mocks ./.github/scripts/determine-version-info.test.mjs
* */
// mock.module must be called before the module under test is imported,
// because static imports are hoisted and resolve before any code runs.
mock.module('./github-helpers.mjs', {
namedExports: {
RELEASE_TRACKS: ['stable', 'beta', 'v1'],
resolveReleaseTagForTrack: (track) => {
// Always return deterministic data
if (track === 'stable') return { version: '2.9.2', tag: 'n8n@2.9.2' };
if (track === 'beta') return { version: '2.10.1', tag: 'n8n@2.10.1' };
return { version: '1.123.33', tag: 'n8n@1.123.33' };
},
tagVersionInfoToReleaseCandidateBranchName,
writeGithubOutput: () => {}, // no-op in tests
getCommitForRef: () => {}, // no-op
localRefExists: () => {}, // no-op
remoteBranchExists: () => {}, // no-op
sh: () => {}, // no-op
},
});
let determineTrack;
before(async () => {
({ determineTrack } = await import('./determine-version-info.mjs'));
});
describe('determine-tracks', () => {
it('Allow patch releases on stable', () => {
const output = determineTrack('2.9.3');
assert.equal(output.track, 'stable');
assert.equal(output.version, '2.9.3');
assert.equal(output.previous_version, '2.9.2');
assert.equal(output.bump, 'patch');
assert.equal(output.new_stable_version, null);
assert.equal(output.release_type, 'stable');
assert.equal(output.rc_branch, 'release-candidate/2.9.x');
});
it('Allow patch releases on beta', () => {
const output = determineTrack('2.10.2');
assert.equal(output.track, 'beta');
assert.equal(output.version, '2.10.2');
assert.equal(output.previous_version, '2.10.1');
assert.equal(output.bump, 'patch');
assert.equal(output.new_stable_version, null);
assert.equal(output.release_type, 'stable');
assert.equal(output.rc_branch, 'release-candidate/2.10.x');
});
// This use case might happen if a patch release fails and we proceed with rolling over to next release
it('Allow skipping versions in patches', () => {
const output = determineTrack('2.9.4');
assert.equal(output.track, 'stable');
assert.equal(output.version, '2.9.4');
assert.equal(output.previous_version, '2.9.2');
assert.equal(output.bump, 'patch');
assert.equal(output.new_stable_version, null);
assert.equal(output.release_type, 'stable');
assert.equal(output.rc_branch, 'release-candidate/2.9.x');
});
it('Disallow skipping versions in minors', () => {
assert.throws(() => determineTrack('2.12.0'));
});
it('Disallow changing major version', () => {
assert.throws(() => determineTrack('3.0.0'));
});
it('Throw when track is not determinable', () => {
assert.throws(() => determineTrack(''));
});
it('Set track as "beta" when doing a minor bump', () => {
const output = determineTrack('2.11.0');
assert.equal(output.track, 'beta');
assert.equal(output.version, '2.11.0');
assert.equal(output.previous_version, '2.10.1');
assert.equal(output.bump, 'minor');
assert.equal(output.new_stable_version, '2.10.1');
assert.equal(output.release_type, 'stable');
assert.equal(output.rc_branch, 'release-candidate/2.11.x');
});
it('Set release_type accordingly on rc releases', () => {
const output = determineTrack('2.10.2-rc.1');
assert.equal(output.track, 'beta');
assert.equal(output.version, '2.10.2-rc.1');
assert.equal(output.previous_version, '2.10.1');
assert.equal(output.bump, 'patch');
assert.equal(output.new_stable_version, null);
assert.equal(output.release_type, 'rc');
assert.equal(output.rc_branch, 'release-candidate/2.10.x');
});
});

View file

@ -31,7 +31,7 @@ class BuildContext {
case 'pull_request':
context.version = `pr-${pr}`;
context.release_type = 'dev';
context.push_to_ghcr = false;
context.platforms = ['linux/amd64'];
break;
case 'workflow_dispatch':

View file

@ -9,7 +9,7 @@ class TagGenerator {
this.githubOutput = process.env.GITHUB_OUTPUT || null;
}
generate({ image, version, platform, includeDockerHub = false }) {
generate({ image, version, platform, includeDockerHub = false, sha = '' }) {
let imageName = image;
let versionSuffix = '';
@ -27,6 +27,21 @@ class TagGenerator {
};
tags.all = [...tags.ghcr, ...tags.docker];
// Generate additional SHA-based tags for immutable references
if (sha) {
const shaVersion = `${version}-${sha}`;
const shaPlatformTag = `${shaVersion}${versionSuffix}${platformSuffix}`;
const shaGhcr = [`ghcr.io/${this.githubOwner}/${imageName}:${shaPlatformTag}`];
const shaDocker = includeDockerHub
? [`${this.dockerUsername}/${imageName}:${shaPlatformTag}`]
: [];
tags.all = [...tags.all, ...shaGhcr, ...shaDocker];
tags.ghcr = [...tags.ghcr, ...shaGhcr];
tags.docker = [...tags.docker, ...shaDocker];
tags.shaPrimaryTag = shaGhcr[0].replace(/-amd64$|-arm64$/, '');
}
return tags;
}
@ -40,18 +55,21 @@ class TagGenerator {
`${prefixStr}docker_tag=${tags.docker[0] || ''}`,
`${prefixStr}primary_tag=${primaryTag}`,
];
if (tags.shaPrimaryTag) {
outputs.push(`${prefixStr}sha_primary_tag=${tags.shaPrimaryTag}`);
}
appendFileSync(this.githubOutput, outputs.join('\n') + '\n');
} else {
console.log(JSON.stringify(tags, null, 2));
}
}
generateAll({ version, platform, includeDockerHub = false }) {
generateAll({ version, platform, includeDockerHub = false, sha = '' }) {
const images = ['n8n', 'runners', 'runners-distroless'];
const results = {};
for (const image of images) {
const tags = this.generate({ image, version, platform, includeDockerHub });
const tags = this.generate({ image, version, platform, includeDockerHub, sha });
const prefix = image.replace('-distroless', '_distroless');
results[prefix] = tags;
@ -86,6 +104,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
version,
platform: getArg('platform'),
includeDockerHub: hasFlag('include-docker'),
sha: getArg('sha') || '',
});
if (!generator.githubOutput) {
console.log(JSON.stringify(results, null, 2));
@ -101,6 +120,7 @@ if (import.meta.url === `file://${process.argv[1]}`) {
version,
platform: getArg('platform'),
includeDockerHub: hasFlag('include-docker'),
sha: getArg('sha') || '',
});
generator.output(tags);
}

View file

@ -0,0 +1,63 @@
#!/usr/bin/env node
/**
* Extracts manifest digests and image names for SLSA provenance and VEX attestation.
*
* Usage:
* N8N_TAG=ghcr.io/n8n-io/n8n:1.0.0 node get-manifest-digests.mjs
*
* Environment variables:
* N8N_TAG - Full image reference for n8n image
* RUNNERS_TAG - Full image reference for runners image
* DISTROLESS_TAG - Full image reference for runners-distroless image
* GITHUB_OUTPUT - Path to GitHub Actions output file (optional)
*/
import { execSync } from 'node:child_process';
import { appendFileSync } from 'node:fs';
const githubOutput = process.env.GITHUB_OUTPUT || null;
function getDigest(imageRef) {
if (!imageRef) return '';
const raw = execSync(`docker buildx imagetools inspect "${imageRef}" --raw`, {
encoding: 'utf8',
});
const hash = execSync('sha256sum', { input: raw, encoding: 'utf8' }).split(' ')[0].trim();
return `sha256:${hash}`;
}
function getImageName(imageRef) {
if (!imageRef) return '';
return imageRef.replace(/:([^:]+)$/, '');
}
function setOutput(name, value) {
if (githubOutput && value) appendFileSync(githubOutput, `${name}=${value}\n`);
}
const n8nTag = process.env.N8N_TAG || '';
const runnersTag = process.env.RUNNERS_TAG || '';
const distrolessTag = process.env.DISTROLESS_TAG || '';
const results = {
n8n: { digest: getDigest(n8nTag), image: getImageName(n8nTag) },
runners: { digest: getDigest(runnersTag), image: getImageName(runnersTag) },
runners_distroless: { digest: getDigest(distrolessTag), image: getImageName(distrolessTag) },
};
setOutput('n8n_digest', results.n8n.digest);
setOutput('n8n_image', results.n8n.image);
setOutput('runners_digest', results.runners.digest);
setOutput('runners_image', results.runners.image);
setOutput('runners_distroless_digest', results.runners_distroless.digest);
setOutput('runners_distroless_image', results.runners_distroless.image);
console.log('=== Manifest Digests ===');
console.log(`n8n: ${results.n8n.digest || 'N/A'}`);
console.log(`runners: ${results.runners.digest || 'N/A'}`);
console.log(`runners-distroless: ${results.runners_distroless.digest || 'N/A'}`);
console.log('');
console.log('=== Image Names ===');
console.log(`n8n: ${results.n8n.image || 'N/A'}`);
console.log(`runners: ${results.runners.image || 'N/A'}`);
console.log(`runners-distroless: ${results.runners_distroless.image || 'N/A'}`);

View file

@ -9,7 +9,13 @@ const exec = promisify(child_process.exec);
const commonFiles = ['LICENSE.md', 'LICENSE_EE.md'];
const baseDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..');
const packages = JSON.parse((await exec('pnpm ls -r --only-projects --json')).stdout);
const packages = JSON.parse(
(
await exec(
`pnpm ls -r --only-projects --json | jq -r '[.[] | { name: .name, version: .version, path: .path, private: .private}]'`,
)
).stdout,
);
for (let { name, path, version, private: isPrivate } of packages) {
if (isPrivate) continue;

View file

@ -0,0 +1,143 @@
import semver from 'semver';
import {
getCommitForRef,
localRefExists,
RELEASE_CANDIDATE_BRANCH_PREFIX,
remoteBranchExists,
resolveReleaseTagForTrack,
sh,
tagVersionInfoToReleaseCandidateBranchName,
trySh,
writeGithubOutput,
} from './github-helpers.mjs';
/**
* @typedef BranchChanges
* @property { import('./github-helpers.mjs').TagVersionInfo[] } branchesToEnsure TagVersionInfo for branches the system needs to make sure exist
* @property { string[] } branchesToDeprecate Branches the system needs to remove as deprecated
* */
/**
* Look into git tags and determine which release candidate branches need to
* exist and which need to be deprecated and removed.
*
* @returns { BranchChanges }
* */
export function determineBranchChanges() {
const branchesToDeprecate = [];
const currentBetaVersion = resolveReleaseTagForTrack('beta');
const currentStableVersion = resolveReleaseTagForTrack('stable');
if (!currentBetaVersion || !currentStableVersion) {
throw new Error(
`Could not find current stable and/or beta tags. Beta: ${currentBetaVersion?.tag ?? 'not found'}, Stable: ${currentStableVersion?.tag ?? 'not found'}`,
);
}
const branchesToEnsure = [currentBetaVersion, currentStableVersion];
const stableVersion = currentStableVersion.version;
// Deprecated branch is the current stable minus 2 versions. e.g. stable: 2.9.x, deprecated is 2.7.x
const deprecatedMinorVersion = semver.minor(stableVersion) - 2;
if (deprecatedMinorVersion >= 0) {
const deprecatedBranch = `${RELEASE_CANDIDATE_BRANCH_PREFIX}${semver.major(stableVersion)}.${deprecatedMinorVersion}.x`;
branchesToDeprecate.push(deprecatedBranch);
}
return {
branchesToEnsure,
branchesToDeprecate,
};
}
/**
* @param {import("./github-helpers.mjs").TagVersionInfo} tagInfo
*/
function ensureBranch(tagInfo) {
const branch = tagVersionInfoToReleaseCandidateBranchName(tagInfo);
if (remoteBranchExists(branch)) {
console.log(`Branch ${branch} already exists on origin. Skipping.`);
return branch;
}
const commitRef = getCommitForRef(tagInfo.tag);
console.log(`Creating branch ${branch} from ${tagInfo.tag} (${commitRef})`);
// Create local branch (force safe: it shouldn't exist, but keep it robust)
if (localRefExists(`refs/heads/${branch}`)) {
sh('git', ['branch', '-f', branch, commitRef]);
} else {
sh('git', ['switch', '-c', branch, commitRef]);
}
sh('git', ['push', 'origin', branch]);
return branch;
}
/**
* @param {string} branch
*/
function removeBranch(branch) {
if (!remoteBranchExists(branch)) {
console.log(`Couldn't find branch ${branch}. Skipping removal.`);
return null;
}
console.log(`Removing remote branch ${branch} from origin...`);
// Delete remote branch
trySh('git', ['push', 'origin', '--delete', branch]);
// Optional local cleanup (keeps reruns tidy)
if (localRefExists(`refs/heads/${branch}`)) {
console.log(`Removing local branch ${branch}...`);
trySh('git', ['branch', '-D', branch]);
}
return branch;
}
function main() {
const branchChanges = determineBranchChanges();
console.log('💡 Determined branch changes');
console.log('');
console.log(
` Branches to ensure: ${branchChanges.branchesToEnsure.map(tagVersionInfoToReleaseCandidateBranchName).join(', ')}`,
);
console.log(` Branches to deprecate: ${branchChanges.branchesToDeprecate.join(', ')}`);
console.log('');
console.log('Preparing to apply changes...');
let ensuredBranches = [];
for (const tagInfo of branchChanges.branchesToEnsure) {
const branch = ensureBranch(tagInfo);
ensuredBranches.push(branch);
}
console.log('');
console.log('Starting deprecation of branches...');
let removedBranches = [];
for (const branch of branchChanges.branchesToDeprecate) {
const removedBranch = removeBranch(branch);
if (removedBranch) {
removedBranches.push(removedBranch);
}
}
console.log('Done!');
writeGithubOutput({
ensuredBranches: ensuredBranches.join(','),
removedBranches: removedBranches.join(','),
});
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
main();
}

View file

@ -0,0 +1,69 @@
import { describe, it, mock, before } from 'node:test';
import assert from 'node:assert/strict';
import { RELEASE_CANDIDATE_BRANCH_PREFIX } from './github-helpers.mjs';
/**
* Run these tests by running
*
* node --test --experimental-test-module-mocks ./.github/scripts/ensure-release-candidate-branches.test.mjs
* */
let tagVersionInfoToReleaseCandidateBranchName;
before(async () => {
({ tagVersionInfoToReleaseCandidateBranchName } = await import('./github-helpers.mjs'));
});
// mock.module must be called before the module under test is imported,
// because static imports are hoisted and resolve before any code runs.
mock.module('./github-helpers.mjs', {
namedExports: {
RELEASE_TRACKS: ['stable', 'beta', 'v1'],
RELEASE_PREFIX: 'n8n@',
RELEASE_CANDIDATE_BRANCH_PREFIX: RELEASE_CANDIDATE_BRANCH_PREFIX,
tagVersionInfoToReleaseCandidateBranchName,
resolveReleaseTagForTrack: (track) => {
// Always return deterministic data
if (track === 'stable') return { version: '2.9.2', tag: 'n8n@2.9.2' };
if (track === 'beta') return { version: '2.10.1', tag: 'n8n@2.10.1' };
return { version: '1.123.33', tag: 'n8n@1.123.33' };
},
writeGithubOutput: () => {}, // no-op in tests
sh: () => {}, // no-op in tests
trySh: () => {}, // no-op in tests
getCommitForRef: () => {}, // no-op in tests
remoteBranchExists: () => {}, // no-op in tests
localRefExists: () => {}, // no-op in tests
},
});
let determineBranchChanges;
before(async () => {
({ determineBranchChanges } = await import('./ensure-release-candidate-branches.mjs'));
});
describe('Determine branch changes', () => {
it('Correctly determines ensureable branches', () => {
const output = determineBranchChanges();
const ensureBranches = output.branchesToEnsure.map(tagVersionInfoToReleaseCandidateBranchName);
assert.ok(
ensureBranches.includes('release-candidate/2.10.x'),
"Beta release-candidate branch doesn't exist",
);
assert.ok(
ensureBranches.includes('release-candidate/2.9.x'),
"Stable release-candidate branch doesn't exist",
);
});
it('Correctly determines deprecated branches', () => {
/** @type { import('./ensure-release-candidate-branches.mjs').BranchChanges} */
const output = determineBranchChanges();
assert.ok(
output.branchesToDeprecate.includes('release-candidate/2.7.x'),
'Existing branch release-candidate/2.7.x should be marked for removal',
);
});
});

View file

@ -0,0 +1,5 @@
{
"pull_request": {
"labels": ["release", "Backport to Stable"]
}
}

View file

@ -0,0 +1,63 @@
import semver from 'semver';
import {
getCommitForRef,
listTagsPointingAt,
RELEASE_PREFIX,
RELEASE_TRACKS,
stripReleasePrefixes,
writeGithubOutput,
} from './github-helpers.mjs';
/**
* Given a list of tag names, return the highest semver tag (keeping the original 'v' prefix),
* or "" if none match semver.
*
* @param {string[]} tags
**/
function highestSemverTag(tags) {
const candidates = tags
.filter((t) => t.startsWith(RELEASE_PREFIX))
.map((t) => ({
tag: t,
version: stripReleasePrefixes(t),
}))
.filter(({ version }) => semver.valid(version));
if (candidates.length === 0) return '';
candidates.sort((a, b) => semver.rcompare(a.version, b.version));
return candidates[0]?.tag;
}
/**
* @param {string} track
**/
function getSemverTagForTrack(track) {
const commit = getCommitForRef(track);
if (!commit) return '';
const tags = listTagsPointingAt(commit);
return highestSemverTag(tags);
}
function main() {
/** @type { Record<string, string> } */
const outputs = {};
for (const track of RELEASE_TRACKS) {
outputs[track] = getSemverTagForTrack(track);
}
writeGithubOutput(outputs);
console.log('Current release versions: ');
for (const [k, v] of Object.entries(outputs)) {
console.log(`${k}: ${v || '(not found)'}`);
}
}
try {
main();
} catch (err) {
console.error(String(err?.message ?? err));
process.exit(1);
}

386
.github/scripts/github-helpers.mjs vendored Normal file
View file

@ -0,0 +1,386 @@
import { getOctokit } from '@actions/github';
import { execFileSync } from 'node:child_process';
import fs from 'node:fs';
import path from 'node:path';
import semver from 'semver';
export const CURRENT_MAJOR_VERSION = 2;
export const RELEASE_CANDIDATE_BRANCH_PREFIX = 'release-candidate/';
export const RELEASE_TRACKS = /** @type { const } */ ([
//
'stable',
'beta',
'v1',
]);
/**
* @typedef { InstanceType<typeof import("@actions/github/lib/utils").GitHub> } GitHubInstance
* */
/**
* @typedef {typeof RELEASE_TRACKS[number]} ReleaseTrack
* */
/**
* @typedef {`${number}.${number}.${number}`} SemVer
* */
/**
* @typedef {`${RELEASE_PREFIX}${SemVer}`} ReleaseVersion
* */
/**
* @typedef {{ tag: ReleaseVersion, version: SemVer }} TagVersionInfo
* */
export const RELEASE_PREFIX = 'n8n@';
/**
* Given a list of tags, return the highest semver for tags like "n8n@2.7.0".
* Returns the *tag string* (e.g. "n8n@2.7.0") or null.
*
* @param {string[]} tags
*
* @returns { ReleaseVersion | null }
* */
export function pickHighestReleaseTag(tags) {
const versions = tags
.filter((t) => t.startsWith(RELEASE_PREFIX))
.map((t) => ({ tag: t, v: stripReleasePrefixes(t) }))
.filter(({ v }) => semver.valid(v))
.sort((a, b) => semver.rcompare(a.v, b.v));
return /** @type { ReleaseVersion } */ (versions[0]?.tag) ?? null;
}
/**
* @param {any} track
*
* @returns { track is ReleaseTrack }
* */
export function isReleaseTrack(track) {
return RELEASE_TRACKS.includes(track);
}
/**
* @param {any} track
*
* @returns { ReleaseTrack }
* */
export function ensureReleaseTrack(track) {
if (!RELEASE_TRACKS.includes(track)) {
throw new Error(`Invalid track ${track}. Available tracks are ${RELEASE_TRACKS.join(', ')}`);
}
return track;
}
/**
* Resolve a release track tag (stable/beta/etc.) to the corresponding
* n8n@x.y.z tag pointing at the same commit.
*
* Returns null if the track tag or release tag is missing.
*
* @param { typeof RELEASE_TRACKS[number] } track
*
* @returns { TagVersionInfo | null }
* */
export function resolveReleaseTagForTrack(track) {
const commit = getCommitForRef(track);
if (!commit) return null;
const tagsAtCommit = listTagsPointingAt(commit);
const releaseTag = pickHighestReleaseTag(tagsAtCommit);
if (!releaseTag) return null;
return {
tag: releaseTag,
version: stripReleasePrefixes(releaseTag),
};
}
/**
* Resolve a release track tag (stable/beta/etc.) to the corresponding
* release-candidate/<major>.<minor>.x branch, based on the n8n@<x.y.z> tag
* pointing at the same commit.
*
* Returns null if the track tag or release tag is missing.
*
* @param { ReleaseTrack } track
* */
export function resolveRcBranchForTrack(track) {
if (track === 'v1') {
return '1.x';
}
const commit = getCommitForRef(track);
if (!commit) return null;
const tagsAtCommit = listTagsPointingAt(commit);
const releaseTag = pickHighestReleaseTag(tagsAtCommit);
if (!releaseTag) return null;
const version = stripReleasePrefixes(releaseTag);
const parsed = semver.parse(version);
if (!parsed) return null;
return `release-candidate/${parsed.major}.${parsed.minor}.x`;
}
/**
* Takes a TagVersionInfo object and returns a rc-branch name.
*
* e.g. release-candidate/2.8.x or 1.x
*
* @param {import('./github-helpers.mjs').TagVersionInfo} tagVersionInfo
*
* @returns { `${RELEASE_CANDIDATE_BRANCH_PREFIX}${number}.${number}.x` | `${number}.x` }
* */
export function tagVersionInfoToReleaseCandidateBranchName(tagVersionInfo) {
const version = tagVersionInfo.version;
const majorVersion = semver.major(version);
if (majorVersion < CURRENT_MAJOR_VERSION) {
return `${majorVersion}.x`;
}
return `${RELEASE_CANDIDATE_BRANCH_PREFIX}${majorVersion}.${semver.minor(version)}.x`;
}
/**
* @param {string} tag
*
* @returns { SemVer }
* */
export function stripReleasePrefixes(tag) {
return /** @type { SemVer } */ (
tag.startsWith(RELEASE_PREFIX) ? tag.slice(RELEASE_PREFIX.length) : tag
);
}
export function getEventFromGithubEventPath() {
let eventPath = ensureEnvVar('GITHUB_EVENT_PATH');
if (!path.isAbsolute(eventPath)) {
eventPath = import.meta.dirname + '/' + eventPath;
}
return JSON.parse(fs.readFileSync(eventPath, 'utf8'));
}
/**
* @param {any} [pullRequest] Optional pull request object. If not provided, reads from GITHUB_EVENT_PATH
*
* @returns {string[]}
*/
export function readPrLabels(pullRequest) {
if (!pullRequest) {
const event = getEventFromGithubEventPath();
pullRequest = event.pull_request;
}
/** @type { string[] | { name: string }[] } */
const labels = pullRequest?.labels ?? [];
return labels.map((l) => (typeof l === 'string' ? l : l?.name)).filter(Boolean);
}
/**
* Ensures git tag exists.
*
* @param {string} tag
* @throws {Error} if no tag was found
*/
export function ensureTagExists(tag) {
sh('git', ['fetch', '--force', '--no-tags', 'origin', `refs/tags/${tag}:refs/tags/${tag}`]);
}
/**
* @param {string} bump
*
* @returns { bump is import("semver").ReleaseType }
* */
export function isReleaseType(bump) {
return ['major', 'minor', 'patch'].includes(bump);
}
/**
* @param {string} variableName
*/
export function ensureEnvVar(variableName) {
const v = process.env[variableName];
if (!v) {
throw new Error(`Missing required env var: ${variableName}`);
}
return v;
}
/**
* @param {string} cmd
* @param {readonly string[]} args
* @param {import("node:child_process").ExecFileOptionsWithStringEncoding} args
*
* @example sh("git", ["tag", "--points-at", commit]);
* */
export function sh(cmd, args, opts = {}) {
return execFileSync(cmd, args, { encoding: 'utf8', ...opts }).trim();
}
/**
* @param {string} cmd
* @param {readonly string[]} args
* @param {import("node:child_process").ExecFileOptionsWithStringEncoding} args
*
* @example trySh("git", ["tag", "--points-at", commit]);
* */
export function trySh(cmd, args, opts = {}) {
try {
return { ok: true, out: sh(cmd, args, opts) };
} catch {
return { ok: false, out: '' };
}
}
/**
* Append outputs to GITHUB_OUTPUT if available.
*
* @param {Record<string, string | boolean>} obj
*/
export function writeGithubOutput(obj) {
const path = process.env.GITHUB_OUTPUT;
if (!path) return;
const lines = Object.entries(obj)
.map(([k, v]) => `${k}=${v ?? ''}`)
.join('\n');
fs.appendFileSync(path, lines + '\n', 'utf8');
}
/**
* Resolve a ref (tag/branch/SHA) to the underlying commit SHA.
* Uses ^{} so annotated tags are peeled to the commit.
* Returns null if ref doesn't exist.
*
* @param {string} ref
*/
export function getCommitForRef(ref) {
const res = trySh('git', ['rev-parse', `${ref}^{}`]);
return res.ok && res.out ? res.out : null;
}
/**
* List all tags that point at the given commit SHA.
*
* @param {string} commit
*/
export function listTagsPointingAt(commit) {
const res = trySh('git', ['tag', '--points-at', commit]);
if (!res.ok || !res.out) return [];
return res.out
.split('\n')
.map((s) => s.trim())
.filter(Boolean);
}
/**
* @param {string} from
* @param {string} to
*/
export function listCommitsBetweenRefs(from, to) {
return sh('git', ['--no-pager', 'log', '--format=%s (%h)', `${to}..origin/${from}`]);
}
/**
* @param {string} from
* @param {string} to
*/
export function countCommitsBetweenRefs(from, to) {
const output = sh('git', ['rev-list', '--count', `${to}..origin/${from}`]);
const count = parseInt(output);
return isNaN(count) ? 0 : count;
}
/**
* @param {string} branch
*/
export function remoteBranchExists(branch) {
const res = trySh('git', ['ls-remote', '--heads', 'origin', branch]);
return res.ok && res.out.length > 0;
}
/**
* @param {string} ref
*/
export function localRefExists(ref) {
const res = trySh('git', ['show-ref', '--verify', '--quiet', ref]);
return res.ok;
}
/**
* Initializes octokit with GITHUB_TOKEN from env vars.
*
* Also ensures the existence of useful environment variables.
* */
export function initGithub() {
const token = ensureEnvVar('GITHUB_TOKEN');
const repoFullName = ensureEnvVar('GITHUB_REPOSITORY');
const [owner, repo] = repoFullName.split('/');
const octokit = getOctokit(token);
return {
octokit,
owner,
repo,
};
}
/**
* @param {number} pullRequestId
*/
export async function getPullRequestById(pullRequestId) {
const { octokit, owner, repo } = initGithub();
const pullRequest = await octokit.rest.pulls.get({
owner,
repo,
pull_number: pullRequestId,
});
return pullRequest.data;
}
/**
* @param {string} tag
*/
export async function getExistingRelease(tag) {
const { octokit, owner, repo } = initGithub();
try {
const releaseRequest = await octokit.rest.repos.getReleaseByTag({
owner,
repo,
tag,
});
return releaseRequest.data;
} catch (ex) {
if (ex?.status === 404) {
return undefined;
}
throw ex;
}
}
/**
* @param {number} releaseId
*/
export async function deleteRelease(releaseId) {
const { octokit, owner, repo } = initGithub();
await octokit.rest.repos.deleteRelease({
owner,
repo,
release_id: releaseId,
});
}

10
.github/scripts/jsconfig.json vendored Normal file
View file

@ -0,0 +1,10 @@
{
"compilerOptions": {
"module": "esnext",
"target": "esnext",
"checkJs": true,
"moduleResolution": "bundler"
},
"exclude": ["node_modules"]
}

18
.github/scripts/move-track-tag.mjs vendored Normal file
View file

@ -0,0 +1,18 @@
import { ensureEnvVar, ensureReleaseTrack, ensureTagExists, sh } from './github-helpers.mjs';
function main() {
const trackEnv = ensureEnvVar('TRACK');
const track = ensureReleaseTrack(trackEnv);
const versionInput = ensureEnvVar('VERSION_TAG'); // e.g. n8n@2.7.0
ensureTagExists(versionInput);
sh('git', ['tag', '-f', track, versionInput]);
sh('git', ['push', 'origin', '-f', `refs/tags/${track}:refs/tags/${track}`]);
console.log(`Moved pointer tag ${track} to point to ${versionInput}`);
}
main();

View file

@ -1,12 +1,20 @@
{
"name": "workflow-scripts",
"scripts": {
"test": "node --test --experimental-test-module-mocks ./*.test.mjs ./quality/*.test.mjs"
},
"dependencies": {
"cacheable-lookup": "6.1.0",
"conventional-changelog": "^4.0.0",
"debug": "4.3.4",
"glob": "10.5.0",
"p-limit": "3.1.0",
"picocolors": "1.0.1",
"semver": "7.5.4",
"tempfile": "5.0.0"
"@actions/github": "9.0.0",
"@octokit/core": "7.0.6",
"conventional-changelog": "7.2.0",
"debug": "4.4.3",
"glob": "13.0.6",
"minimatch": "10.2.4",
"semver": "7.7.4",
"tempfile": "6.0.1",
"yaml": "^2.8.3"
},
"devDependencies": {
"conventional-changelog-angular": "8.3.0"
}
}

62
.github/scripts/plan-release.mjs vendored Normal file
View file

@ -0,0 +1,62 @@
import semver from 'semver';
import {
ensureEnvVar,
isReleaseType,
RELEASE_PREFIX,
stripReleasePrefixes,
writeGithubOutput,
} from './github-helpers.mjs';
const track = ensureEnvVar('TRACK');
const bump = ensureEnvVar('BUMP');
const stable = process.env['STABLE_VERSION'];
const beta = process.env['BETA_VERSION'];
const v1 = process.env['V1_VERSION'];
let base = null;
switch (track) {
case 'stable':
base = stable;
break;
case 'beta':
base = beta;
break;
case 'v1':
base = v1;
break;
}
if (!base) {
console.error(
`Unknown track or missing base version. track=${track} stable=${stable} beta=${beta} v1=${v1}`,
);
process.exit(1);
}
const cleanedBase = stripReleasePrefixes(base);
if (!cleanedBase) {
console.error(`Invalid base version: ${base}`);
process.exit(1);
}
if (!isReleaseType(bump)) {
console.error(`Invalid release type in $bump: ${bump}`);
process.exit(1);
}
const next = semver.inc(cleanedBase, bump);
if (!next) {
console.error(`Could not bump version. base=${cleanedBase} bump=${bump}`);
process.exit(1);
}
const output = {
base_version: cleanedBase,
new_version: next,
new_version_tag: `${RELEASE_PREFIX}${next}`,
};
writeGithubOutput(output);
console.log(`Releasing track=${track} bump=${bump} base=${cleanedBase} -> new=${next}`);

552
.github/scripts/pnpm-lock.yaml vendored Normal file
View file

@ -0,0 +1,552 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
dependencies:
'@actions/github':
specifier: 9.0.0
version: 9.0.0
'@octokit/core':
specifier: 7.0.6
version: 7.0.6
conventional-changelog:
specifier: 7.2.0
version: 7.2.0(conventional-commits-filter@5.0.0)
debug:
specifier: 4.4.3
version: 4.4.3
glob:
specifier: 13.0.6
version: 13.0.6
minimatch:
specifier: 10.2.4
version: 10.2.4
semver:
specifier: 7.7.4
version: 7.7.4
tempfile:
specifier: 6.0.1
version: 6.0.1
yaml:
specifier: ^2.8.3
version: 2.8.3
devDependencies:
conventional-changelog-angular:
specifier: 8.3.0
version: 8.3.0
packages:
'@actions/github@9.0.0':
resolution: {integrity: sha512-yJ0RoswsAaKcvkmpCE4XxBRiy/whH2SdTBHWzs0gi4wkqTDhXMChjSdqBz/F4AeiDlP28rQqL33iHb+kjAMX6w==}
'@actions/http-client@3.0.2':
resolution: {integrity: sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==}
'@conventional-changelog/git-client@2.6.0':
resolution: {integrity: sha512-T+uPDciKf0/ioNNDpMGc8FDsehJClZP0yR3Q5MN6wE/Y/1QZ7F+80OgznnTCOlMEG4AV0LvH2UJi3C/nBnaBUg==}
engines: {node: '>=18'}
peerDependencies:
conventional-commits-filter: ^5.0.0
conventional-commits-parser: ^6.3.0
peerDependenciesMeta:
conventional-commits-filter:
optional: true
conventional-commits-parser:
optional: true
'@octokit/auth-token@6.0.0':
resolution: {integrity: sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==}
engines: {node: '>= 20'}
'@octokit/core@7.0.6':
resolution: {integrity: sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==}
engines: {node: '>= 20'}
'@octokit/endpoint@11.0.3':
resolution: {integrity: sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==}
engines: {node: '>= 20'}
'@octokit/graphql@9.0.3':
resolution: {integrity: sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==}
engines: {node: '>= 20'}
'@octokit/openapi-types@27.0.0':
resolution: {integrity: sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==}
'@octokit/plugin-paginate-rest@14.0.0':
resolution: {integrity: sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==}
engines: {node: '>= 20'}
peerDependencies:
'@octokit/core': '>=6'
'@octokit/plugin-rest-endpoint-methods@17.0.0':
resolution: {integrity: sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==}
engines: {node: '>= 20'}
peerDependencies:
'@octokit/core': '>=6'
'@octokit/request-error@7.1.0':
resolution: {integrity: sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==}
engines: {node: '>= 20'}
'@octokit/request@10.0.8':
resolution: {integrity: sha512-SJZNwY9pur9Agf7l87ywFi14W+Hd9Jg6Ifivsd33+/bGUQIjNujdFiXII2/qSlN2ybqUHfp5xpekMEjIBTjlSw==}
engines: {node: '>= 20'}
'@octokit/types@16.0.0':
resolution: {integrity: sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==}
'@simple-libs/child-process-utils@1.0.2':
resolution: {integrity: sha512-/4R8QKnd/8agJynkNdJmNw2MBxuFTRcNFnE5Sg/G+jkSsV8/UBgULMzhizWWW42p8L5H7flImV2ATi79Ove2Tw==}
engines: {node: '>=18'}
'@simple-libs/hosted-git-info@1.0.2':
resolution: {integrity: sha512-aAmGQdMH+ZinytKuA2832u0ATeOFNYNk4meBEXtB5xaPotUgggYNhq5tYU/v17wEbmTW5P9iHNqNrFyrhnqBAg==}
engines: {node: '>=18'}
'@simple-libs/stream-utils@1.2.0':
resolution: {integrity: sha512-KxXvfapcixpz6rVEB6HPjOUZT22yN6v0vI0urQSk1L8MlEWPDFCZkhw2xmkyoTGYeFw7tWTZd7e3lVzRZRN/EA==}
engines: {node: '>=18'}
'@types/normalize-package-data@2.4.4':
resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==}
array-ify@1.0.0:
resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==}
balanced-match@4.0.4:
resolution: {integrity: sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==}
engines: {node: 18 || 20 || >=22}
before-after-hook@4.0.0:
resolution: {integrity: sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==}
brace-expansion@5.0.4:
resolution: {integrity: sha512-h+DEnpVvxmfVefa4jFbCf5HdH5YMDXRsmKflpf1pILZWRFlTbJpxeU55nJl4Smt5HQaGzg1o6RHFPJaOqnmBDg==}
engines: {node: 18 || 20 || >=22}
compare-func@2.0.0:
resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==}
conventional-changelog-angular@8.3.0:
resolution: {integrity: sha512-DOuBwYSqWzfwuRByY9O4oOIvDlkUCTDzfbOgcSbkY+imXXj+4tmrEFao3K+FxemClYfYnZzsvudbwrhje9VHDA==}
engines: {node: '>=18'}
conventional-changelog-preset-loader@5.0.0:
resolution: {integrity: sha512-SetDSntXLk8Jh1NOAl1Gu5uLiCNSYenB5tm0YVeZKePRIgDW9lQImromTwLa3c/Gae298tsgOM+/CYT9XAl0NA==}
engines: {node: '>=18'}
conventional-changelog-writer@8.4.0:
resolution: {integrity: sha512-HHBFkk1EECxxmCi4CTu091iuDpQv5/OavuCUAuZmrkWpmYfyD816nom1CvtfXJ/uYfAAjavgHvXHX291tSLK8g==}
engines: {node: '>=18'}
hasBin: true
conventional-changelog@7.2.0:
resolution: {integrity: sha512-BEdgG+vPl53EVlTTk9sZ96aagFp0AQ5pw/ggiQMy2SClLbTo1r0l+8dSg79gkLOO5DS1Lswuhp5fWn6RwE+ivg==}
engines: {node: '>=18'}
hasBin: true
conventional-commits-filter@5.0.0:
resolution: {integrity: sha512-tQMagCOC59EVgNZcC5zl7XqO30Wki9i9J3acbUvkaosCT6JX3EeFwJD7Qqp4MCikRnzS18WXV3BLIQ66ytu6+Q==}
engines: {node: '>=18'}
conventional-commits-parser@6.3.0:
resolution: {integrity: sha512-RfOq/Cqy9xV9bOA8N+ZH6DlrDR+5S3Mi0B5kACEjESpE+AviIpAptx9a9cFpWCCvgRtWT+0BbUw+e1BZfts9jg==}
engines: {node: '>=18'}
hasBin: true
debug@4.4.3:
resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==}
engines: {node: '>=6.0'}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dot-prop@5.3.0:
resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==}
engines: {node: '>=8'}
fast-content-type-parse@3.0.0:
resolution: {integrity: sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==}
fd-package-json@2.0.0:
resolution: {integrity: sha512-jKmm9YtsNXN789RS/0mSzOC1NUq9mkVd65vbSSVsKdjGvYXBuE4oWe2QOEoFeRmJg+lPuZxpmrfFclNhoRMneQ==}
glob@13.0.6:
resolution: {integrity: sha512-Wjlyrolmm8uDpm/ogGyXZXb1Z+Ca2B8NbJwqBVg0axK9GbBeoS7yGV6vjXnYdGm6X53iehEuxxbyiKp8QmN4Vw==}
engines: {node: 18 || 20 || >=22}
handlebars@4.7.8:
resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==}
engines: {node: '>=0.4.7'}
hasBin: true
hosted-git-info@8.1.0:
resolution: {integrity: sha512-Rw/B2DNQaPBICNXEm8balFz9a6WpZrkCGpcWFpy7nCj+NyhSdqXipmfvtmWt9xGfp0wZnBxB+iVpLmQMYt47Tw==}
engines: {node: ^18.17.0 || >=20.5.0}
is-obj@2.0.0:
resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==}
engines: {node: '>=8'}
is-safe-filename@0.1.1:
resolution: {integrity: sha512-4SrR7AdnY11LHfDKTZY1u6Ga3RuxZdl3YKWWShO5iyuG5h8QS4GD2tOb04peBJ5I7pXbR+CGBNEhTcwK+FzN3g==}
engines: {node: '>=20'}
json-with-bigint@3.5.7:
resolution: {integrity: sha512-7ei3MdAI5+fJPVnKlW77TKNKwQ5ppSzWvhPuSuINT/GYW9ZOC1eRKOuhV9yHG5aEsUPj9BBx5JIekkmoLHxZOw==}
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
lru-cache@11.2.7:
resolution: {integrity: sha512-aY/R+aEsRelme17KGQa/1ZSIpLpNYYrhcrepKTZgE+W3WM16YMCaPwOHLHsmopZHELU0Ojin1lPVxKR0MihncA==}
engines: {node: 20 || >=22}
meow@13.2.0:
resolution: {integrity: sha512-pxQJQzB6djGPXh08dacEloMFopsOqGVRKFPYvPOt9XDZ1HasbgDZA74CJGreSU4G3Ak7EFJGoiH2auq+yXISgA==}
engines: {node: '>=18'}
minimatch@10.2.4:
resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==}
engines: {node: 18 || 20 || >=22}
minimist@1.2.8:
resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==}
minipass@7.1.3:
resolution: {integrity: sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A==}
engines: {node: '>=16 || 14 >=14.17'}
ms@2.1.3:
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
neo-async@2.6.2:
resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==}
normalize-package-data@7.0.1:
resolution: {integrity: sha512-linxNAT6M0ebEYZOx2tO6vBEFsVgnPpv+AVjk0wJHfaUIbq31Jm3T6vvZaarnOeWDh8ShnwXuaAyM7WT3RzErA==}
engines: {node: ^18.17.0 || >=20.5.0}
path-scurry@2.0.2:
resolution: {integrity: sha512-3O/iVVsJAPsOnpwWIeD+d6z/7PmqApyQePUtCndjatj/9I5LylHvt5qluFaBT3I5h3r1ejfR056c+FCv+NnNXg==}
engines: {node: 18 || 20 || >=22}
semver@7.7.4:
resolution: {integrity: sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==}
engines: {node: '>=10'}
hasBin: true
source-map@0.6.1:
resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==}
engines: {node: '>=0.10.0'}
spdx-correct@3.2.0:
resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==}
spdx-exceptions@2.5.0:
resolution: {integrity: sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==}
spdx-expression-parse@3.0.1:
resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==}
spdx-license-ids@3.0.23:
resolution: {integrity: sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==}
temp-dir@3.0.0:
resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==}
engines: {node: '>=14.16'}
tempfile@6.0.1:
resolution: {integrity: sha512-DE4nURsf7nUqYHJKTgOVdpt0SBY5r4us4kbFXqg7KZFB7ih27NxIk3qXv29FtqTaE45stnLKTECmSc9ICuRbDQ==}
engines: {node: '>=20'}
tunnel@0.0.6:
resolution: {integrity: sha512-1h/Lnq9yajKY2PEbBadPXj3VxsDDu844OnaAo52UVmIzIvwwtBPIuNvkjuzBlTWpfJyUbG3ez0KSBibQkj4ojg==}
engines: {node: '>=0.6.11 <=0.7.0 || >=0.7.3'}
uglify-js@3.19.3:
resolution: {integrity: sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==}
engines: {node: '>=0.8.0'}
hasBin: true
undici@6.24.1:
resolution: {integrity: sha512-sC+b0tB1whOCzbtlx20fx3WgCXwkW627p4EA9uM+/tNNPkSS+eSEld6pAs9nDv7WbY1UUljBMYPtu9BCOrCWKA==}
engines: {node: '>=18.17'}
universal-user-agent@7.0.3:
resolution: {integrity: sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==}
validate-npm-package-license@3.0.4:
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
walk-up-path@4.0.0:
resolution: {integrity: sha512-3hu+tD8YzSLGuFYtPRb48vdhKMi0KQV5sn+uWr8+7dMEq/2G/dtLrdDinkLjqq5TIbIBjYJ4Ax/n3YiaW7QM8A==}
engines: {node: 20 || >=22}
wordwrap@1.0.0:
resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==}
yaml@2.8.3:
resolution: {integrity: sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==}
engines: {node: '>= 14.6'}
hasBin: true
snapshots:
'@actions/github@9.0.0':
dependencies:
'@actions/http-client': 3.0.2
'@octokit/core': 7.0.6
'@octokit/plugin-paginate-rest': 14.0.0(@octokit/core@7.0.6)
'@octokit/plugin-rest-endpoint-methods': 17.0.0(@octokit/core@7.0.6)
'@octokit/request': 10.0.8
'@octokit/request-error': 7.1.0
undici: 6.24.1
'@actions/http-client@3.0.2':
dependencies:
tunnel: 0.0.6
undici: 6.24.1
'@conventional-changelog/git-client@2.6.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.3.0)':
dependencies:
'@simple-libs/child-process-utils': 1.0.2
'@simple-libs/stream-utils': 1.2.0
semver: 7.7.4
optionalDependencies:
conventional-commits-filter: 5.0.0
conventional-commits-parser: 6.3.0
'@octokit/auth-token@6.0.0': {}
'@octokit/core@7.0.6':
dependencies:
'@octokit/auth-token': 6.0.0
'@octokit/graphql': 9.0.3
'@octokit/request': 10.0.8
'@octokit/request-error': 7.1.0
'@octokit/types': 16.0.0
before-after-hook: 4.0.0
universal-user-agent: 7.0.3
'@octokit/endpoint@11.0.3':
dependencies:
'@octokit/types': 16.0.0
universal-user-agent: 7.0.3
'@octokit/graphql@9.0.3':
dependencies:
'@octokit/request': 10.0.8
'@octokit/types': 16.0.0
universal-user-agent: 7.0.3
'@octokit/openapi-types@27.0.0': {}
'@octokit/plugin-paginate-rest@14.0.0(@octokit/core@7.0.6)':
dependencies:
'@octokit/core': 7.0.6
'@octokit/types': 16.0.0
'@octokit/plugin-rest-endpoint-methods@17.0.0(@octokit/core@7.0.6)':
dependencies:
'@octokit/core': 7.0.6
'@octokit/types': 16.0.0
'@octokit/request-error@7.1.0':
dependencies:
'@octokit/types': 16.0.0
'@octokit/request@10.0.8':
dependencies:
'@octokit/endpoint': 11.0.3
'@octokit/request-error': 7.1.0
'@octokit/types': 16.0.0
fast-content-type-parse: 3.0.0
json-with-bigint: 3.5.7
universal-user-agent: 7.0.3
'@octokit/types@16.0.0':
dependencies:
'@octokit/openapi-types': 27.0.0
'@simple-libs/child-process-utils@1.0.2':
dependencies:
'@simple-libs/stream-utils': 1.2.0
'@simple-libs/hosted-git-info@1.0.2': {}
'@simple-libs/stream-utils@1.2.0': {}
'@types/normalize-package-data@2.4.4': {}
array-ify@1.0.0: {}
balanced-match@4.0.4: {}
before-after-hook@4.0.0: {}
brace-expansion@5.0.4:
dependencies:
balanced-match: 4.0.4
compare-func@2.0.0:
dependencies:
array-ify: 1.0.0
dot-prop: 5.3.0
conventional-changelog-angular@8.3.0:
dependencies:
compare-func: 2.0.0
conventional-changelog-preset-loader@5.0.0: {}
conventional-changelog-writer@8.4.0:
dependencies:
'@simple-libs/stream-utils': 1.2.0
conventional-commits-filter: 5.0.0
handlebars: 4.7.8
meow: 13.2.0
semver: 7.7.4
conventional-changelog@7.2.0(conventional-commits-filter@5.0.0):
dependencies:
'@conventional-changelog/git-client': 2.6.0(conventional-commits-filter@5.0.0)(conventional-commits-parser@6.3.0)
'@simple-libs/hosted-git-info': 1.0.2
'@types/normalize-package-data': 2.4.4
conventional-changelog-preset-loader: 5.0.0
conventional-changelog-writer: 8.4.0
conventional-commits-parser: 6.3.0
fd-package-json: 2.0.0
meow: 13.2.0
normalize-package-data: 7.0.1
transitivePeerDependencies:
- conventional-commits-filter
conventional-commits-filter@5.0.0: {}
conventional-commits-parser@6.3.0:
dependencies:
'@simple-libs/stream-utils': 1.2.0
meow: 13.2.0
debug@4.4.3:
dependencies:
ms: 2.1.3
dot-prop@5.3.0:
dependencies:
is-obj: 2.0.0
fast-content-type-parse@3.0.0: {}
fd-package-json@2.0.0:
dependencies:
walk-up-path: 4.0.0
glob@13.0.6:
dependencies:
minimatch: 10.2.4
minipass: 7.1.3
path-scurry: 2.0.2
handlebars@4.7.8:
dependencies:
minimist: 1.2.8
neo-async: 2.6.2
source-map: 0.6.1
wordwrap: 1.0.0
optionalDependencies:
uglify-js: 3.19.3
hosted-git-info@8.1.0:
dependencies:
lru-cache: 10.4.3
is-obj@2.0.0: {}
is-safe-filename@0.1.1: {}
json-with-bigint@3.5.7: {}
lru-cache@10.4.3: {}
lru-cache@11.2.7: {}
meow@13.2.0: {}
minimatch@10.2.4:
dependencies:
brace-expansion: 5.0.4
minimist@1.2.8: {}
minipass@7.1.3: {}
ms@2.1.3: {}
neo-async@2.6.2: {}
normalize-package-data@7.0.1:
dependencies:
hosted-git-info: 8.1.0
semver: 7.7.4
validate-npm-package-license: 3.0.4
path-scurry@2.0.2:
dependencies:
lru-cache: 11.2.7
minipass: 7.1.3
semver@7.7.4: {}
source-map@0.6.1: {}
spdx-correct@3.2.0:
dependencies:
spdx-expression-parse: 3.0.1
spdx-license-ids: 3.0.23
spdx-exceptions@2.5.0: {}
spdx-expression-parse@3.0.1:
dependencies:
spdx-exceptions: 2.5.0
spdx-license-ids: 3.0.23
spdx-license-ids@3.0.23: {}
temp-dir@3.0.0: {}
tempfile@6.0.1:
dependencies:
is-safe-filename: 0.1.1
temp-dir: 3.0.0
tunnel@0.0.6: {}
uglify-js@3.19.3:
optional: true
undici@6.24.1: {}
universal-user-agent@7.0.3: {}
validate-npm-package-license@3.0.4:
dependencies:
spdx-correct: 3.2.0
spdx-expression-parse: 3.0.1
walk-up-path@4.0.0: {}
wordwrap@1.0.0: {}
yaml@2.8.3: {}

25
.github/scripts/pnpm-utils.mjs vendored Normal file
View file

@ -0,0 +1,25 @@
import child_process from 'child_process';
import { promisify } from 'node:util';
const exec = promisify(child_process.exec);
/**
* @typedef PnpmPackage
* @property { string } name
* @property { string } version
* @property { string } path
* @property { boolean } private
* */
/**
* @returns { Promise<PnpmPackage[]> }
* */
export async function getMonorepoProjects() {
return JSON.parse(
(
await exec(
`pnpm ls -r --only-projects --json | jq -r '[.[] | { name: .name, version: .version, path: .path, private: .private}]'`,
)
).stdout,
);
}

View file

@ -0,0 +1,32 @@
import { ensureEnvVar } from './github-helpers.mjs';
async function populateCloudDatabases() {
const payload = ensureEnvVar('PAYLOAD');
const webhookData = ensureEnvVar('N8N_POPULATE_CLOUD_WEBHOOK_DATA');
const { user, secret, url } = JSON.parse(webhookData);
console.log('Payload: ', JSON.parse(payload));
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(`${user}:${secret}`).toString('base64'),
},
body: payload,
});
const status = response.status;
console.log('Webhook call returned status ' + status);
if (status !== 200) {
const body = await response.text();
throw new Error(`Webhook call failed:\n\n ${body}`);
}
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
populateCloudDatabases();
}

View file

@ -0,0 +1,143 @@
#!/usr/bin/env node
/**
* Fetches QA metric comparisons and posts/updates a PR comment.
*
* Usage:
* node .github/scripts/post-qa-metrics-comment.mjs --metrics memory-heap-used-baseline
* node .github/scripts/post-qa-metrics-comment.mjs --metrics memory-heap-used-baseline --pr 27880 --dry-run
*
* Env:
* QA_METRICS_COMMENT_WEBHOOK_URL - n8n workflow webhook (required)
* QA_METRICS_WEBHOOK_USER/PASSWORD - Basic auth for webhook
* GITHUB_TOKEN - For posting comments (not needed with --dry-run)
* GITHUB_REF, GITHUB_REPOSITORY, GITHUB_SHA - Auto-set in CI
*/
import { parseArgs } from 'node:util';
const MARKER = '<!-- n8n-qa-metrics-comparison -->';
const { values } = parseArgs({
options: {
metrics: { type: 'string' },
pr: { type: 'string' },
'baseline-days': { type: 'string', default: '14' },
'dry-run': { type: 'boolean', default: false },
},
strict: true,
});
const metrics = values.metrics?.split(',').map((m) => m.trim());
if (!metrics?.length) {
console.error('--metrics is required (comma-separated metric names)');
process.exit(1);
}
const pr = parseInt(values.pr ?? inferPr(), 10);
if (!pr) {
console.error('--pr is required (or set GITHUB_REF)');
process.exit(1);
}
const webhookUrl = process.env.QA_METRICS_COMMENT_WEBHOOK_URL;
if (!webhookUrl) {
console.error('QA_METRICS_COMMENT_WEBHOOK_URL is required');
process.exit(1);
}
const repo = process.env.GITHUB_REPOSITORY ?? 'n8n-io/n8n';
const sha = process.env.GITHUB_SHA?.slice(0, 8) ?? '';
const baselineDays = parseInt(values['baseline-days'], 10);
// --- Fetch ---
const headers = { 'Content-Type': 'application/json' };
const user = process.env.QA_METRICS_WEBHOOK_USER;
const pass = process.env.QA_METRICS_WEBHOOK_PASSWORD;
if (user && pass) {
headers.Authorization = `Basic ${Buffer.from(`${user}:${pass}`).toString('base64')}`;
}
console.log(`PR #${pr}: fetching ${metrics.join(', ')} (${baselineDays}-day baseline)`);
let res;
try {
res = await fetch(webhookUrl, {
method: 'POST',
headers,
body: JSON.stringify({
pr_number: pr,
github_repo: repo,
git_sha: sha,
baseline_days: baselineDays,
metric_names: metrics,
}),
signal: AbortSignal.timeout(60_000),
});
} catch (err) {
console.warn(`Webhook unreachable, skipping metrics comment: ${err.message}`);
process.exit(0);
}
if (!res.ok) {
const text = await res.text().catch(() => '');
console.warn(`Webhook failed: ${res.status} ${res.statusText}\n${text}`);
console.warn('Skipping metrics comment.');
process.exit(0);
}
const { markdown, has_data } = await res.json();
if (!has_data || !markdown) {
console.log('No metric data available, skipping.');
process.exit(0);
}
if (values['dry-run']) {
console.log('\n--- DRY RUN ---\n');
console.log(markdown);
process.exit(0);
}
// --- Post comment ---
const token = process.env.GITHUB_TOKEN;
if (!token) {
console.error('GITHUB_TOKEN is required to post comments');
process.exit(1);
}
const [owner, repoName] = repo.split('/');
const ghHeaders = {
Accept: 'application/vnd.github+json',
Authorization: `Bearer ${token}`,
'Content-Type': 'application/json',
};
const comments = await fetch(
`https://api.github.com/repos/${owner}/${repoName}/issues/${pr}/comments?per_page=100`,
{ headers: ghHeaders },
).then((r) => r.json());
const existing = Array.isArray(comments)
? comments.find((c) => c.body?.includes(MARKER))
: null;
if (existing) {
await fetch(
`https://api.github.com/repos/${owner}/${repoName}/issues/comments/${existing.id}`,
{ method: 'PATCH', headers: ghHeaders, body: JSON.stringify({ body: markdown }) },
);
console.log(`Updated comment ${existing.id}`);
} else {
const created = await fetch(
`https://api.github.com/repos/${owner}/${repoName}/issues/${pr}/comments`,
{ method: 'POST', headers: ghHeaders, body: JSON.stringify({ body: markdown }) },
).then((r) => r.json());
console.log(`Created comment ${created.id}`);
}
function inferPr() {
const match = (process.env.GITHUB_REF ?? '').match(/refs\/pull\/(\d+)/);
return match?.[1];
}

View file

@ -0,0 +1,68 @@
import {
deleteRelease,
ensureEnvVar,
getExistingRelease,
initGithub,
writeGithubOutput,
} from './github-helpers.mjs';
/**
* Promotes a GitHub release to latest
*
* Required env variables:
* - RELEASE_TAG - Release tag on git e.g. n8n@2.13.0
*
* GitHub variables
* - GITHUB_TOKEN - Used to authenticate to octokit - Can be overwritten for privileged access
* - GITHUB_REPOSITORY - Used to determine target repository
* */
async function promoteGitHubRelease() {
const RELEASE_TAG = ensureEnvVar('RELEASE_TAG');
const { octokit, owner, repo } = initGithub();
const existingRelease = await getExistingRelease(RELEASE_TAG);
if (!existingRelease) {
console.warn("Couldn't find release by tag. Exiting...");
process.exit(1);
}
const releaseResponse = await octokit.rest.repos.updateRelease({
owner,
repo,
release_id: existingRelease.id,
prerelease: false,
make_latest: 'true',
});
console.log(`Successfully updated release ${releaseResponse.data.html_url}`);
const existingStableRelease = await getExistingRelease('stable');
if (existingStableRelease) {
await deleteRelease(existingStableRelease.id);
console.log("Deleted previous 'stable' release.");
}
const stableReleaseResponse = await octokit.rest.repos.createRelease({
tag_name: 'stable',
name: 'stable',
body: releaseResponse.data.body,
draft: false,
prerelease: false,
make_latest: 'false',
target_commitish: releaseResponse.data.target_commitish,
owner,
repo,
});
console.log(`Successfully created new stable release ${stableReleaseResponse.data.html_url}`);
writeGithubOutput({
release_url: releaseResponse.data.html_url,
stable_release_url: stableReleaseResponse.data.html_url,
});
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
promoteGitHubRelease();
}

View file

@ -0,0 +1,81 @@
/**
* Checks that the PR description contains a checked ownership acknowledgement checkbox.
*
* Exit codes:
* 0 Checkbox is present and checked
* 1 Checkbox is missing or unchecked
*/
import { initGithub, getEventFromGithubEventPath } from '../github-helpers.mjs';
const BOT_MARKER = '<!-- pr-ownership-check -->';
/**
* Returns true if the PR body contains a checked ownership acknowledgement checkbox.
*
* @param {string | null | undefined} body
* @returns {boolean}
*/
export function isOwnershipCheckboxChecked(body) {
return /\[x\]\s+I have seen this code,\s+I have run this code,\s+and I take responsibility for this code/i.test(
body ?? '',
);
}
async function main() {
const event = getEventFromGithubEventPath();
const pr = event.pull_request;
const { octokit, owner, repo } = initGithub();
const { data: comments } = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: pr.number,
per_page: 100,
});
const botComment = comments.find((c) => c.body.includes(BOT_MARKER));
if (!isOwnershipCheckboxChecked(pr.body)) {
const message = [
BOT_MARKER,
'## ⚠️ Ownership acknowledgement required',
'',
'Please add or check the following item in your PR description before this can be merged:',
'',
'```',
'- [x] I have seen this code, I have run this code, and I take responsibility for this code.',
'```',
].join('\n');
if (botComment) {
await octokit.rest.issues.updateComment({
owner,
repo,
comment_id: botComment.id,
body: message,
});
} else {
await octokit.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body: message,
});
}
console.log(
'::error::Ownership checkbox is not checked. Add it to your PR description and check it.',
);
process.exit(1);
} else if (botComment) {
await octokit.rest.issues.deleteComment({
owner,
repo,
comment_id: botComment.id,
});
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
await main();
}

View file

@ -0,0 +1,85 @@
import { describe, it, before, mock } from 'node:test';
import assert from 'node:assert/strict';
/**
* Run with:
* node --test --experimental-test-module-mocks .github/scripts/quality/check-ownership-checkbox.test.mjs
*/
mock.module('../github-helpers.mjs', {
namedExports: {
initGithub: () => {},
getEventFromGithubEventPath: () => {},
},
});
let isOwnershipCheckboxChecked;
before(async () => {
({ isOwnershipCheckboxChecked } = await import('./check-ownership-checkbox.mjs'));
});
describe('isOwnershipCheckboxChecked', () => {
it('returns true for a checked checkbox with exact text', () => {
const body =
'- [x] I have seen this code, I have run this code, and I take responsibility for this code.';
assert.ok(isOwnershipCheckboxChecked(body));
});
it('returns true for uppercase [X]', () => {
const body =
'- [X] I have seen this code, I have run this code, and I take responsibility for this code.';
assert.ok(isOwnershipCheckboxChecked(body));
});
it('returns false for an unchecked checkbox [ ]', () => {
const body =
'- [ ] I have seen this code, I have run this code, and I take responsibility for this code.';
assert.equal(isOwnershipCheckboxChecked(body), false);
});
it('returns false when the checkbox is absent', () => {
const body = '## Summary\n\nThis PR does some things.\n';
assert.equal(isOwnershipCheckboxChecked(body), false);
});
it('returns false for null body', () => {
assert.equal(isOwnershipCheckboxChecked(null), false);
});
it('returns false for undefined body', () => {
assert.equal(isOwnershipCheckboxChecked(undefined), false);
});
it('returns false for empty body', () => {
assert.equal(isOwnershipCheckboxChecked(''), false);
});
it('returns true when checkbox appears among other content', () => {
const body = [
'## Summary',
'',
'Some description here.',
'',
'## Checklist',
'- [x] Tests included',
'- [x] I have seen this code, I have run this code, and I take responsibility for this code.',
'- [ ] Docs updated',
].join('\n');
assert.ok(isOwnershipCheckboxChecked(body));
});
it('returns false when only other checkboxes are checked', () => {
const body = [
'- [x] Tests included',
'- [x] Docs updated',
'- [ ] I have seen this code, I have run this code, and I take responsibility for this code.',
].join('\n');
assert.equal(isOwnershipCheckboxChecked(body), false);
});
it('is case-insensitive for the checkbox marker', () => {
const lower =
'- [x] i have seen this code, i have run this code, and i take responsibility for this code.';
assert.ok(isOwnershipCheckboxChecked(lower));
});
});

View file

@ -0,0 +1,172 @@
/**
* Checks that the PR does not exceed the line addition limit.
*
* Files matching any pattern in EXCLUDE_PATTERNS are not counted toward the
* limit (e.g. test files, snapshots).
*
* A maintainer (write access or above) can override by commenting `/size-limit-override`
* on the PR. The override takes effect on the next pull_request event (push, reopen, etc.).
*
* Exit codes:
* 0 PR is within the limit, or a valid override comment exists
* 1 PR exceeds the limit with no valid override
*/
import { minimatch } from 'minimatch';
import { initGithub, getEventFromGithubEventPath } from '../github-helpers.mjs';
export const SIZE_LIMIT = 1000;
export const OVERRIDE_COMMAND = '/size-limit-override';
export const EXCLUDE_PATTERNS = [
// Test files (by extension)
'**/*.test.ts',
'**/*.test.js',
'**/*.test.mjs',
'**/*.spec.ts',
'**/*.spec.js',
'**/*.spec.mjs',
// Test directories
'**/test/**',
'**/tests/**',
'**/__tests__/**',
// Snapshots
'**/__snapshots__/**',
'**/*.snap',
// Fixtures and mocks
'**/fixtures/**',
'**/__mocks__/**',
// Dedicated testing package
'packages/testing/**',
// Lock file (can produce massive diffs on dependency changes)
'pnpm-lock.yaml',
];
const BOT_MARKER = '<!-- pr-size-check -->';
/**
* Returns true if any comment in the list is a valid `/size-limit-override` from a
* user with write access or above.
*
* @param {Array<{ body?: string, user: { login: string } | null }>} comments
* @param {(username: string) => Promise<string>} getPermission - returns the permission level string
* @returns {Promise<boolean>}
*/
export async function hasValidOverride(comments, getPermission) {
for (const comment of comments) {
if (!comment.body?.startsWith(OVERRIDE_COMMAND)) {
continue;
}
if (!comment.user) {
return false;
}
const perm = await getPermission(comment.user.login);
if (['admin', 'write', 'maintain'].includes(perm)) {
return true;
}
}
return false;
}
/**
* Returns the total additions across all files, excluding those matching any exclude pattern.
*
* @param {Array<{ filename: string, additions: number }>} files
* @param {string[]} excludePatterns
* @returns {number}
*/
export function countFilteredAdditions(files, excludePatterns) {
return files
.filter((file) => !excludePatterns.some((pattern) => minimatch(file.filename, pattern)))
.reduce((sum, file) => sum + file.additions, 0);
}
async function main() {
const event = getEventFromGithubEventPath();
const pr = event.pull_request;
const { octokit, owner, repo } = initGithub();
const files = await octokit.paginate(octokit.rest.pulls.listFiles, {
owner,
repo,
pull_number: pr.number,
per_page: 100,
});
const additions = countFilteredAdditions(files, EXCLUDE_PATTERNS);
const { data: comments } = await octokit.rest.issues.listComments({
owner,
repo,
issue_number: pr.number,
per_page: 100,
sort: 'created',
direction: 'desc',
});
const overrideFound = await hasValidOverride(comments, async (username) => {
const { data: perm } = await octokit.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username,
});
return perm.permission;
});
const botComment = comments.find((c) => c.body?.includes(BOT_MARKER));
if (additions > SIZE_LIMIT && !overrideFound) {
const message = [
BOT_MARKER,
`## ! PR exceeds size limit (${additions.toLocaleString()} lines added)`,
'',
`This PR adds **${additions.toLocaleString()} lines**, exceeding the ${SIZE_LIMIT.toLocaleString()}-line limit (test files excluded).`,
'',
'Large PRs are harder to review and increase the risk of bugs going unnoticed. Please consider:',
'- Breaking this into smaller, logically separate PRs',
'- Moving unrelated changes to a follow-up PR',
'',
`If the size is genuinely justified (e.g. generated code, large migrations, test fixtures), a maintainer can override by commenting \`${OVERRIDE_COMMAND}\` and then pushing a new commit or re-running this check.`,
].join('\n');
if (botComment) {
await octokit.rest.issues.updateComment({
owner,
repo,
comment_id: botComment.id,
body: message,
});
} else {
await octokit.rest.issues.createComment({
owner,
repo,
issue_number: pr.number,
body: message,
});
}
console.log(
`::error::PR adds ${additions.toLocaleString()} lines (test files excluded), exceeding the ${SIZE_LIMIT.toLocaleString()}-line limit. Reduce PR size or ask a maintainer to comment \`${OVERRIDE_COMMAND}\`.`,
);
process.exit(1);
} else {
if (botComment) {
await octokit.rest.issues.deleteComment({
owner,
repo,
comment_id: botComment.id,
});
}
if (overrideFound && additions > SIZE_LIMIT) {
console.log(
`PR size limit overridden. ${additions.toLocaleString()} lines added (limit: ${SIZE_LIMIT.toLocaleString()}, test files excluded).`,
);
}
}
}
if (import.meta.url === `file://${process.argv[1]}`) {
await main();
}

View file

@ -0,0 +1,206 @@
import { describe, it, before, mock } from 'node:test';
import assert from 'node:assert/strict';
/**
* Run with:
* node --test --experimental-test-module-mocks .github/scripts/quality/check-pr-size.test.mjs
*/
mock.module('../github-helpers.mjs', {
namedExports: {
initGithub: () => {},
getEventFromGithubEventPath: () => {},
},
});
let hasValidOverride, countFilteredAdditions, SIZE_LIMIT, OVERRIDE_COMMAND, EXCLUDE_PATTERNS;
before(async () => {
({ hasValidOverride, countFilteredAdditions, SIZE_LIMIT, OVERRIDE_COMMAND, EXCLUDE_PATTERNS } =
await import('./check-pr-size.mjs'));
});
/** @param {string} permission */
const permissionGetter = (permission) => async (_username) => permission;
describe('SIZE_LIMIT', () => {
it('is 1000', () => {
assert.equal(SIZE_LIMIT, 1000);
});
});
describe('hasValidOverride', () => {
it('returns false when there are no comments', async () => {
const result = await hasValidOverride([], permissionGetter('write'));
assert.equal(result, false);
});
it('returns false when no comment starts with the override command', async () => {
const comments = [
{ body: 'Looks good to me!', user: { login: 'reviewer' } },
{ body: 'Please split this PR.', user: { login: 'maintainer' } },
];
const result = await hasValidOverride(comments, permissionGetter('write'));
assert.equal(result, false);
});
it('returns true when a write-access user has posted the override command', async () => {
const comments = [{ body: OVERRIDE_COMMAND, user: { login: 'maintainer' } }];
const result = await hasValidOverride(comments, permissionGetter('write'));
assert.ok(result);
});
it('returns true for maintain permission', async () => {
const comments = [{ body: OVERRIDE_COMMAND, user: { login: 'lead' } }];
const result = await hasValidOverride(comments, permissionGetter('maintain'));
assert.ok(result);
});
it('returns true for admin permission', async () => {
const comments = [{ body: OVERRIDE_COMMAND, user: { login: 'admin' } }];
const result = await hasValidOverride(comments, permissionGetter('admin'));
assert.ok(result);
});
it('returns false when the override commenter only has read access', async () => {
const comments = [{ body: OVERRIDE_COMMAND, user: { login: 'outsider' } }];
const result = await hasValidOverride(comments, permissionGetter('read'));
assert.equal(result, false);
});
it('returns false when the override commenter only has triage access', async () => {
const comments = [{ body: OVERRIDE_COMMAND, user: { login: 'triager' } }];
const result = await hasValidOverride(comments, permissionGetter('triage'));
assert.equal(result, false);
});
it('returns false when the override command appears mid-comment, not at the start', async () => {
const comments = [
{
body: `Please note: ${OVERRIDE_COMMAND} should only be used when justified.`,
user: { login: 'maintainer' },
},
];
const result = await hasValidOverride(comments, permissionGetter('write'));
assert.equal(result, false);
});
it('returns true when one of several comments is a valid override', async () => {
const comments = [
{ body: 'Looks good!', user: { login: 'reviewer' } },
{ body: OVERRIDE_COMMAND, user: { login: 'maintainer' } },
{ body: 'Please add tests.', user: { login: 'other' } },
];
const result = await hasValidOverride(comments, permissionGetter('write'));
assert.ok(result);
});
it('returns false when override comment exists but all posters lack write access', async () => {
const comments = [
{ body: OVERRIDE_COMMAND, user: { login: 'user1' } },
{ body: OVERRIDE_COMMAND, user: { login: 'user2' } },
];
const result = await hasValidOverride(comments, permissionGetter('read'));
assert.equal(result, false);
});
it('checks permissions per commenter independently', async () => {
const permissions = { writer: 'write', reader: 'read' };
const getPermission = async (username) => permissions[username] ?? 'read';
const comments = [
{ body: OVERRIDE_COMMAND, user: { login: 'reader' } },
{ body: OVERRIDE_COMMAND, user: { login: 'writer' } },
];
const result = await hasValidOverride(comments, getPermission);
assert.ok(result);
});
});
describe('countFilteredAdditions', () => {
it('sums additions across all files when no patterns are given', () => {
const files = [
{ filename: 'src/foo.ts', additions: 100 },
{ filename: 'src/bar.ts', additions: 200 },
];
assert.equal(countFilteredAdditions(files, []), 300);
});
it('excludes files matching a glob pattern', () => {
const files = [
{ filename: 'src/foo.ts', additions: 100 },
{ filename: 'src/foo.test.ts', additions: 500 },
];
assert.equal(countFilteredAdditions(files, ['**/*.test.ts']), 100);
});
it('excludes files matching any of multiple patterns', () => {
const files = [
{ filename: 'src/foo.ts', additions: 100 },
{ filename: 'src/foo.test.ts', additions: 200 },
{ filename: 'src/foo.spec.ts', additions: 300 },
{ filename: 'src/__tests__/bar.ts', additions: 400 },
];
assert.equal(
countFilteredAdditions(files, ['**/*.test.ts', '**/*.spec.ts', '**/__tests__/**']),
100,
);
});
it('returns 0 when all files are excluded', () => {
const files = [
{ filename: 'src/foo.test.ts', additions: 100 },
{ filename: 'src/bar.test.ts', additions: 200 },
];
assert.equal(countFilteredAdditions(files, ['**/*.test.ts']), 0);
});
it('returns 0 for an empty file list', () => {
assert.equal(countFilteredAdditions([], EXCLUDE_PATTERNS), 0);
});
it('applies EXCLUDE_PATTERNS to common test file extensions', () => {
const files = [
{ filename: 'src/service.ts', additions: 50 },
{ filename: 'src/service.test.ts', additions: 100 },
{ filename: 'src/service.spec.ts', additions: 100 },
{ filename: 'src/service.test.mjs', additions: 100 },
{ filename: 'src/service.spec.mjs', additions: 100 },
{ filename: 'src/service.test.js', additions: 100 },
{ filename: 'src/service.spec.js', additions: 100 },
{ filename: 'src/__tests__/helper.ts', additions: 100 },
{ filename: 'src/component.snap', additions: 100 },
];
assert.equal(countFilteredAdditions(files, EXCLUDE_PATTERNS), 50);
});
it('applies EXCLUDE_PATTERNS to test directories (test/, tests/, __tests__)', () => {
const files = [
{ filename: 'packages/cli/src/service.ts', additions: 50 },
{ filename: 'packages/cli/test/unit/service.test.ts', additions: 100 },
{ filename: 'packages/cli/test/integration/api.test.ts', additions: 100 },
{ filename: 'packages/nodes-base/nodes/Foo/tests/Foo.test.ts', additions: 100 },
{ filename: 'packages/core/src/__tests__/cipher.test.ts', additions: 100 },
];
assert.equal(countFilteredAdditions(files, EXCLUDE_PATTERNS), 50);
});
it('applies EXCLUDE_PATTERNS to snapshots, fixtures, and mocks', () => {
const files = [
{ filename: 'packages/cli/src/service.ts', additions: 50 },
{ filename: 'packages/editor-ui/src/__snapshots__/Canvas.test.ts.snap', additions: 100 },
{ filename: 'packages/workflow/test/fixtures/workflow.json', additions: 100 },
{ filename: 'packages/core/src/__mocks__/fs.ts', additions: 100 },
];
assert.equal(countFilteredAdditions(files, EXCLUDE_PATTERNS), 50);
});
it('applies EXCLUDE_PATTERNS to packages/testing and pnpm-lock.yaml', () => {
const files = [
{ filename: 'packages/cli/src/service.ts', additions: 50 },
{ filename: 'packages/testing/playwright/tests/workflow.spec.ts', additions: 100 },
{ filename: 'packages/testing/playwright/pages/CanvasPage.ts', additions: 100 },
{ filename: 'pnpm-lock.yaml', additions: 500 },
];
assert.equal(countFilteredAdditions(files, EXCLUDE_PATTERNS), 50);
});
});

View file

@ -0,0 +1,97 @@
/**
* Re-triggers the PR Size Limit check when a maintainer comments `/size-limit-override`.
*
* Finds the latest `PR Size Limit` check run on the PR's HEAD commit and re-requests it.
* The re-run scans comments, finds the override, and passes satisfying branch protection
* without any label manipulation or status API calls.
*
* Exit codes:
* 0 Check run re-requested successfully
* 1 Commenter lacks permission, or no check run found to re-request
*/
import { initGithub, getEventFromGithubEventPath } from '../github-helpers.mjs';
const CHECK_NAME = 'PR Size Limit';
/**
* @param {{
* octokit: import('../github-helpers.mjs').GitHubInstance,
* owner: string,
* repo: string,
* prNumber: number,
* commenter: string,
* commentId: number,
* }} params
*/
export async function run({ octokit, owner, repo, prNumber, commenter, commentId }) {
const { data: perm } = await octokit.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: commenter,
});
if (!['admin', 'write', 'maintain'].includes(perm.permission)) {
console.log(
`::error::@${commenter} does not have permission to override the PR size limit (requires write access).`,
);
process.exit(1);
}
const { data: pr } = await octokit.rest.pulls.get({
owner,
repo,
pull_number: prNumber,
});
const headSha = pr.head.sha;
const {
data: { check_runs },
} = await octokit.rest.checks.listForRef({
owner,
repo,
ref: headSha,
check_name: CHECK_NAME,
per_page: 1,
});
if (check_runs.length === 0) {
console.log(
`::error::No '${CHECK_NAME}' check run found for ${headSha}. Push a new commit to trigger it.`,
);
process.exit(1);
}
await octokit.rest.checks.rerequestRun({
owner,
repo,
check_run_id: check_runs[0].id,
});
await octokit.rest.reactions.createForIssueComment({
owner,
repo,
comment_id: commentId,
content: '+1',
});
console.log(`Re-requested '${CHECK_NAME}' check run (${check_runs[0].id}) for ${headSha}`);
}
async function main() {
const event = getEventFromGithubEventPath();
const { octokit, owner, repo } = initGithub();
await run({
octokit,
owner,
repo,
prNumber: event.issue.number,
commenter: event.sender.login,
commentId: event.comment.id,
});
}
if (import.meta.url === `file://${process.argv[1]}`) {
await main();
}

60
.github/scripts/retry.mjs vendored Normal file
View file

@ -0,0 +1,60 @@
#!/usr/bin/env node
/**
* Retry a shell command with configurable attempts and delay.
*
* Usage: node retry.mjs [--attempts N] [--delay N] '<command>'
*
* Options:
* --attempts N Maximum number of attempts (default: 4)
* --delay N Seconds to wait between retries (default: 15)
*
* The command is executed via shell, so pipes and env-var expansion work.
* Exits 0 on first success, 1 if all attempts fail.
*/
import { execSync } from 'node:child_process';
const args = process.argv.slice(2);
function getFlag(name, defaultValue) {
const index = args.indexOf(`--${name}`);
if (index === -1 || !args[index + 1]) return defaultValue;
const value = parseInt(args[index + 1], 10);
if (Number.isNaN(value) || value <= 0) {
console.error(`Error: --${name} must be a positive integer`);
process.exit(1);
}
return value;
}
const attempts = getFlag('attempts', 4);
const delay = getFlag('delay', 15);
// Command is the last positional arg (skip flags and their values)
const command = args
.filter((a, i) => {
if (a.startsWith('--')) return false;
if (i > 0 && args[i - 1].startsWith('--')) return false;
return true;
})
.pop();
if (!command) {
console.error("Usage: node retry.mjs [--attempts N] [--delay N] '<command>'");
process.exit(1);
}
for (let i = 1; i <= attempts; i++) {
try {
execSync(command, { shell: true, stdio: 'inherit' });
process.exit(0);
} catch {
if (i < attempts) {
console.error(`Attempt ${i}/${attempts} failed, retrying in ${delay}s...`);
execSync(`sleep ${delay}`);
} else {
console.error(`Attempt ${i}/${attempts} failed, no more retries.`);
}
}
}
process.exit(1);

67
.github/scripts/send-build-stats.mjs vendored Normal file
View file

@ -0,0 +1,67 @@
#!/usr/bin/env node
/**
* Sends Turbo build stats to the unified QA metrics webhook.
*
* Reads the Turbo run summary from .turbo/runs/ and emits per-package
* build-duration metrics with {package, cache, task} dimensions, plus
* a run-level build-total-duration summary.
*
* Usage: node send-build-stats.mjs
*
* Environment variables:
* QA_METRICS_WEBHOOK_URL - Webhook URL (required to send)
* QA_METRICS_WEBHOOK_USER - Basic auth username
* QA_METRICS_WEBHOOK_PASSWORD - Basic auth password
*/
import { existsSync, readFileSync, readdirSync } from 'node:fs';
import { join } from 'node:path';
import { sendMetrics, metric } from './send-metrics.mjs';
const runsDir = '.turbo/runs';
if (!existsSync(runsDir)) {
console.log('No .turbo/runs directory found (turbo --summarize not used), skipping.');
process.exit(0);
}
const files = readdirSync(runsDir)
.filter((f) => f.endsWith('.json'))
.sort();
if (files.length === 0) {
console.error('No summary file found in .turbo/runs/');
process.exit(1);
}
const summary = JSON.parse(readFileSync(join(runsDir, files.at(-1)), 'utf-8'));
const metrics = [];
for (const task of summary.tasks ?? []) {
if (task.execution?.exitCode !== 0) continue;
const durationMs = task.execution.durationMs ?? 0;
const cacheHit = task.cache?.status === 'HIT';
// taskId format: "package-name#task-name"
const [pkg, taskName] = task.taskId?.split('#') ?? [task.package, task.task];
metrics.push(
metric('build-duration', durationMs / 1000, 's', {
package: pkg ?? 'unknown',
task: taskName ?? 'build',
cache: cacheHit ? 'hit' : 'miss',
}),
);
}
const totalMs = summary.durationMs ?? 0;
const totalTasks = summary.tasks?.length ?? 0;
const cachedTasks = summary.tasks?.filter((t) => t.cache?.status === 'HIT').length ?? 0;
metrics.push(
metric('build-total-duration', totalMs / 1000, 's', {
total_tasks: totalTasks,
cached_tasks: cachedTasks,
}),
);
await sendMetrics(metrics, 'build-stats');

88
.github/scripts/send-docker-stats.mjs vendored Normal file
View file

@ -0,0 +1,88 @@
#!/usr/bin/env node
/**
* Sends Docker build stats to the unified QA metrics webhook.
*
* Reads manifests produced by build-n8n.mjs and dockerize-n8n.mjs and emits
* per-image docker-image-size metrics and build duration metrics with
* {image, platform} dimensions.
*
* Usage: node send-docker-stats.mjs
*
* Environment variables:
* QA_METRICS_WEBHOOK_URL - Webhook URL (required to send)
* QA_METRICS_WEBHOOK_USER - Basic auth username
* QA_METRICS_WEBHOOK_PASSWORD - Basic auth password
*/
import { existsSync, readFileSync } from 'node:fs';
import { sendMetrics, metric } from './send-metrics.mjs';
/** Parse human-readable sizes (e.g. "1.5G", "500M", "12K") to MB. */
function parseSizeToMB(val) {
if (typeof val === 'number') return val / (1024 * 1024);
if (typeof val !== 'string') return null;
const match = val.match(/^([\d.]+)\s*([KMGT]?)i?B?$/i);
if (!match) return null;
const num = parseFloat(match[1]);
const suffix = match[2].toUpperCase();
const toMB = { '': 1 / (1024 * 1024), 'K': 1 / 1024, 'M': 1, 'G': 1024, 'T': 1024 * 1024 };
return Math.round(num * (toMB[suffix] ?? 1) * 100) / 100;
}
const buildManifestPath = 'compiled/build-manifest.json';
const dockerManifestPath = 'docker-build-manifest.json';
if (!existsSync(buildManifestPath) && !existsSync(dockerManifestPath)) {
console.log('No build or docker manifests found, skipping.');
process.exit(0);
}
const buildManifest = existsSync(buildManifestPath)
? JSON.parse(readFileSync(buildManifestPath, 'utf-8'))
: null;
const dockerManifest = existsSync(dockerManifestPath)
? JSON.parse(readFileSync(dockerManifestPath, 'utf-8'))
: null;
const metrics = [];
if (buildManifest) {
const sizeMB = parseSizeToMB(buildManifest.artifactSize);
if (sizeMB != null) {
metrics.push(metric('artifact-size', sizeMB, 'MB', { artifact: 'compiled' }));
}
const duration = buildManifest.buildDuration;
if (duration?.total != null) {
metrics.push(metric('build-duration', duration.total / 1000, 's', { artifact: 'compiled' }));
}
}
if (dockerManifest) {
const platform = dockerManifest.platform ?? 'unknown';
for (const image of dockerManifest.images ?? []) {
const imageSizeMB = parseSizeToMB(image.size ?? image.sizeBytes);
const imageName = image.imageName ?? image.name ?? 'unknown';
const shortName = imageName.replace(/^n8nio\//, '').replace(/:.*$/, '');
if (imageSizeMB != null) {
metrics.push(
metric(`docker-image-size-${shortName}`, imageSizeMB, 'MB', { platform }),
);
}
}
if (dockerManifest.buildDurationMs != null) {
metrics.push(
metric('docker-build-duration', dockerManifest.buildDurationMs / 1000, 's', { platform }),
);
}
}
if (metrics.length === 0) {
console.log('No metrics to send.');
process.exit(0);
}
await sendMetrics(metrics, 'docker-stats');

94
.github/scripts/send-metrics.mjs vendored Normal file
View file

@ -0,0 +1,94 @@
#!/usr/bin/env node
/**
* Shared metrics sender for CI scripts.
* See .github/CI-TELEMETRY.md for payload shape and BigQuery schema.
*
* Usage:
* import { sendMetrics, metric } from './send-metrics.mjs';
* await sendMetrics([metric('build-duration', 45.2, 's', { package: '@n8n/cli' })]);
*
* Env: QA_METRICS_WEBHOOK_URL, QA_METRICS_WEBHOOK_USER, QA_METRICS_WEBHOOK_PASSWORD
*/
import * as os from 'node:os';
/** Build a single metric object. */
export function metric(name, value, unit, dimensions = {}) {
return { metric_name: name, value, unit, dimensions };
}
/** Build git/ci/runner context from environment variables. */
export function buildContext(benchmarkName = null) {
const ref = process.env.GITHUB_REF ?? '';
const prMatch = ref.match(/refs\/pull\/(\d+)/);
const runId = process.env.GITHUB_RUN_ID ?? null;
return {
timestamp: new Date().toISOString(),
benchmark_name: benchmarkName,
git: {
sha: process.env.GITHUB_SHA?.slice(0, 8) ?? null,
branch: process.env.GITHUB_HEAD_REF ?? process.env.GITHUB_REF_NAME ?? null,
pr: prMatch ? parseInt(prMatch[1], 10) : null,
},
ci: {
runId,
runUrl:
runId && process.env.GITHUB_REPOSITORY
? `https://github.com/${process.env.GITHUB_REPOSITORY}/actions/runs/${runId}`
: null,
job: process.env.GITHUB_JOB ?? null,
workflow: process.env.GITHUB_WORKFLOW ?? null,
attempt: process.env.GITHUB_RUN_ATTEMPT
? parseInt(process.env.GITHUB_RUN_ATTEMPT, 10)
: null,
},
runner: {
provider: !process.env.CI
? 'local'
: process.env.RUNNER_ENVIRONMENT === 'github-hosted'
? 'github'
: 'blacksmith',
cpuCores: os.cpus().length,
memoryGb: Math.round((os.totalmem() / (1024 * 1024 * 1024)) * 10) / 10,
},
};
}
export async function sendMetrics(metrics, benchmarkName = null) {
const webhookUrl = process.env.QA_METRICS_WEBHOOK_URL;
const webhookUser = process.env.QA_METRICS_WEBHOOK_USER;
const webhookPassword = process.env.QA_METRICS_WEBHOOK_PASSWORD;
if (!webhookUrl) {
console.log('QA_METRICS_WEBHOOK_URL not set, skipping.');
return;
}
if (!webhookUser || !webhookPassword) {
console.log('QA_METRICS_WEBHOOK_USER/PASSWORD not set, skipping.');
return;
}
const payload = { ...buildContext(benchmarkName), metrics };
const basicAuth = Buffer.from(`${webhookUser}:${webhookPassword}`).toString('base64');
const response = await fetch(webhookUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Basic ${basicAuth}`,
},
body: JSON.stringify(payload),
signal: AbortSignal.timeout(30_000),
});
if (!response.ok) {
const body = await response.text().catch(() => '');
throw new Error(
`Webhook failed: ${response.status} ${response.statusText}${body ? `\n${body}` : ''}`,
);
}
console.log(`Sent ${metrics.length} metric(s): ${response.status}`);
}

View file

@ -0,0 +1,32 @@
import { ensureEnvVar } from './github-helpers.mjs';
async function sendVersionReleaseNotification() {
const payload = ensureEnvVar('PAYLOAD');
const webhookData = ensureEnvVar('N8N_VERSION_RELEASE_NOTIFICATION_DATA');
const { user, secret, url } = JSON.parse(webhookData);
console.log('Payload: ', JSON.parse(payload));
const response = await fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Basic ' + Buffer.from(`${user}:${secret}`).toString('base64'),
},
body: payload,
});
const status = response.status;
console.log('Webhook call returned status ' + status);
if (status !== 200) {
const body = await response.text();
throw new Error(`Webhook call failed:\n\n ${body}`);
}
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
sendVersionReleaseNotification();
}

View file

@ -0,0 +1,28 @@
import { trySh } from './github-helpers.mjs';
import { getMonorepoProjects } from './pnpm-utils.mjs';
async function setLatestForMonorepoPackages() {
const packages = await getMonorepoProjects();
const publishedPackages = packages //
.filter((pkg) => !pkg.private)
.filter((pkg) => pkg.version);
for (const pkg of publishedPackages) {
const versionName = `${pkg.name}@${pkg.version}`;
const res = trySh('npm', ['dist-tag', 'add', versionName, 'latest']);
if (res.ok) {
console.log(`Set ${versionName} as latest`);
} else {
console.warn(`Update failed for ${versionName}`);
}
}
}
// only run when executed directly, not when imported by tests
if (import.meta.url === `file://${process.argv[1]}`) {
setLatestForMonorepoPackages().catch((err) => {
console.error(err);
process.exit(1);
});
}

View file

@ -1,5 +1,5 @@
import createTempFile from 'tempfile';
import conventionalChangelog from 'conventional-changelog';
import { ConventionalChangelog } from 'conventional-changelog';
import { resolve } from 'path';
import { createReadStream, createWriteStream } from 'fs';
import { dirname } from 'path';
@ -12,21 +12,48 @@ const fullChangelogFile = resolve(baseDir, 'CHANGELOG.md');
// Version includes experimental versions (e.g., 1.2.3-exp.0)
const versionChangelogFile = resolve(baseDir, `CHANGELOG-${packageJson.version}.md`);
const changelogStream = conventionalChangelog({
preset: 'angular',
releaseCount: 1,
tagPrefix: 'n8n@',
transform: (commit, callback) => {
const hasNoChangelogInHeader = commit.header.includes('(no-changelog)');
const isBenchmarkScope = commit.scope === 'benchmark';
const changelogStream = new ConventionalChangelog()
.package(packageJson)
.readRepository()
.loadPreset('angular')
.tags({
prefix: 'n8n@',
})
.context({
version: packageJson.version,
repoUrl: 'https://github.com/n8n-io/n8n',
})
.options({
releaseCount: 1,
transformCommit(commit) {
const hasNoChangelogInHeader = commit.header?.includes('(no-changelog)');
const isBenchmarkScope = commit.scope === 'benchmark';
// Ignore commits that have 'benchmark' scope or '(no-changelog)' in the header
callback(null, hasNoChangelogInHeader || isBenchmarkScope ? undefined : commit);
},
}).on('error', (err) => {
console.error(err.stack);
process.exit(1);
});
// Ignore commits that have 'benchmark' scope or '(no-changelog)' in the header
if (hasNoChangelogInHeader || isBenchmarkScope) return null;
// Strip backport information from commit subject, e.g.:
// "Fix something (backport to release-candidate/2.12.x) (#123)" → "Fix something (#123)"
if (commit.subject) {
// The commit.subject is immutable so we need to recreate the commit object
/** @type { import("conventional-changelog").Commit } */
let newCommit = /** @type { any } */ ({
...commit,
subject: commit.subject.replace(/\s*\(backport to [^)]+\)/g, ''),
});
return newCommit;
}
return commit;
},
})
.writeStream()
.on('error', (err) => {
console.error(err.stack);
process.exit(1);
});
// Write the new changelog to a new temporary file, so that the contents can be used in the PR description
await pipeline(changelogStream, createWriteStream(versionChangelogFile));
@ -36,5 +63,6 @@ await pipeline(changelogStream, createWriteStream(versionChangelogFile));
const tmpFile = createTempFile();
const tmpStream = createWriteStream(tmpFile);
await pipeline(createReadStream(versionChangelogFile), tmpStream, { end: false });
tmpStream.write('\n\n');
await pipeline(createReadStream(fullChangelogFile), tmpStream);
await pipeline(createReadStream(tmpFile), createWriteStream(fullChangelogFile));

View file

@ -1,90 +0,0 @@
#!/usr/bin/env node
const packages = ['nodes-base', '@n8n/nodes-langchain'];
const concurrency = 20;
let exitCode = 0;
const debug = require('debug')('n8n');
const path = require('path');
const https = require('https');
const glob = require('glob');
const pLimit = require('p-limit');
const picocolors = require('picocolors');
const Lookup = require('cacheable-lookup').default;
const agent = new https.Agent({ keepAlive: true, keepAliveMsecs: 5000 });
new Lookup().install(agent);
const limiter = pLimit(concurrency);
const validateUrl = async (packageName, kind, type) =>
new Promise((resolve, reject) => {
const name = type.displayName;
const documentationUrl =
kind === 'credentials'
? type.documentationUrl
: type.codex?.resources?.primaryDocumentation?.[0]?.url;
if (!documentationUrl) resolve([name, null]);
const url = new URL(
/^https?:\/\//.test(documentationUrl)
? documentationUrl
: `https://docs.n8n.io/integrations/builtin/${kind}/${documentationUrl.toLowerCase()}/`,
);
https
.request(
{
hostname: url.hostname,
port: 443,
path: url.pathname,
method: 'HEAD',
agent,
},
(res) => {
debug(picocolors.green('✓'), packageName, kind, name);
resolve([name, res.statusCode]);
},
)
.on('error', (e) => {
debug(picocolors.red('✘'), packageName, kind, name);
reject(e);
})
.end();
});
const checkLinks = async (packageName, kind) => {
const baseDir = path.resolve(__dirname, '../../packages', packageName);
let types = require(path.join(baseDir, `dist/types/${kind}.json`));
if (kind === 'nodes')
types = types.filter(
({ codex, hidden }) => !!codex?.resources?.primaryDocumentation && !hidden,
);
debug(packageName, kind, types.length);
const statuses = await Promise.all(
types.map((type) =>
limiter(() => {
return validateUrl(packageName, kind, type);
}),
),
);
const missingDocs = [];
const invalidUrls = [];
for (const [name, statusCode] of statuses) {
if (statusCode === null) missingDocs.push(name);
if (statusCode !== 200) invalidUrls.push(name);
}
if (missingDocs.length)
console.log('Documentation URL missing in %s for %s', packageName, kind, missingDocs);
if (invalidUrls.length)
console.log('Documentation URL invalid in %s for %s', packageName, kind, invalidUrls);
if (missingDocs.length || invalidUrls.length) exitCode = 1;
};
(async () => {
for (const packageName of packages) {
await Promise.all([checkLinks(packageName, 'credentials'), checkLinks(packageName, 'nodes')]);
if (exitCode !== 0) process.exit(exitCode);
}
})();

832
.github/test-metrics/playwright.json vendored Normal file
View file

@ -0,0 +1,832 @@
{
"updatedAt": "2026-04-10T10:10:12.160Z",
"source": "currents",
"projectId": "LRxcNt",
"specs": {
"tests/e2e/workflows/editor/canvas/actions.spec.ts": {
"avgDuration": 143495,
"testCount": 19,
"flakyRate": 0.2895
},
"tests/e2e/projects/projects.spec.ts": {
"avgDuration": 141370,
"testCount": 7,
"flakyRate": 0.0189
},
"tests/e2e/credentials/crud.spec.ts": {
"avgDuration": 119882,
"testCount": 14,
"flakyRate": 0
},
"tests/e2e/workflows/list/workflows.spec.ts": {
"avgDuration": 115566,
"testCount": 10,
"flakyRate": 0.0076
},
"tests/e2e/ai/langchain-agents.spec.ts": {
"avgDuration": 112278,
"testCount": 7,
"flakyRate": 0.0225
},
"tests/e2e/workflows/editor/code/code-node.spec.ts": {
"avgDuration": 111238,
"testCount": 12,
"flakyRate": 0.1895
},
"tests/e2e/workflows/editor/canvas/canvas-zoom.spec.ts": {
"avgDuration": 103779,
"testCount": 13,
"flakyRate": 0.0447
},
"tests/e2e/workflows/editor/canvas/undo-redo.spec.ts": {
"avgDuration": 103215,
"testCount": 14,
"flakyRate": 0.0019
},
"tests/e2e/settings/personal/two-factor-authentication.spec.ts": {
"avgDuration": 101275,
"testCount": 7,
"flakyRate": 0.0057
},
"tests/e2e/workflows/editor/canvas/canvas-nodes.spec.ts": {
"avgDuration": 98150,
"testCount": 8,
"flakyRate": 0.1383
},
"tests/e2e/ai/assistant-basic.spec.ts": {
"avgDuration": 98077,
"testCount": 11,
"flakyRate": 0.0092
},
"tests/e2e/ai/builder-setup-wizard.spec.ts": {
"avgDuration": 98038,
"testCount": 9,
"flakyRate": 0.011
},
"tests/e2e/chat-hub/chat-hub-tools.spec.ts": {
"avgDuration": 97205,
"testCount": 1,
"flakyRate": 0.9665
},
"tests/e2e/workflows/editor/ndv/ndv-core.spec.ts": {
"avgDuration": 96983,
"testCount": 14,
"flakyRate": 0.0038
},
"tests/e2e/data-tables/tables.spec.ts": {
"avgDuration": 96687,
"testCount": 7,
"flakyRate": 0
},
"tests/e2e/workflows/editor/ndv/ndv-data-display.spec.ts": {
"avgDuration": 93865,
"testCount": 11,
"flakyRate": 0.0875
},
"tests/e2e/data-tables/details.spec.ts": {
"avgDuration": 88739,
"testCount": 11,
"flakyRate": 0
},
"tests/e2e/workflows/editor/code/editors.spec.ts": {
"avgDuration": 88632,
"testCount": 11,
"flakyRate": 0.0187
},
"tests/e2e/projects/folders-operations.spec.ts": {
"avgDuration": 83495,
"testCount": 14,
"flakyRate": 0.0019
},
"tests/e2e/auth/oidc.spec.ts": {
"avgDuration": 79906,
"testCount": 1,
"flakyRate": 0.0111
},
"tests/e2e/workflows/executions/list.spec.ts": {
"avgDuration": 79342,
"testCount": 11,
"flakyRate": 0.3131
},
"tests/e2e/nodes/webhook.spec.ts": {
"avgDuration": 78999,
"testCount": 9,
"flakyRate": 0.0037
},
"tests/e2e/workflows/editor/expressions/mapping.spec.ts": {
"avgDuration": 77958,
"testCount": 10,
"flakyRate": 0.2096
},
"tests/e2e/workflows/templates/credentials-setup.spec.ts": {
"avgDuration": 77108,
"testCount": 8,
"flakyRate": 0.0076
},
"tests/e2e/workflows/editor/execution/execution.spec.ts": {
"avgDuration": 73018,
"testCount": 14,
"flakyRate": 0.041
},
"tests/e2e/sharing/credential-visibility.spec.ts": {
"avgDuration": 71543,
"testCount": 5,
"flakyRate": 0
},
"tests/e2e/workflows/editor/ndv/resource-locator.spec.ts": {
"avgDuration": 70513,
"testCount": 7,
"flakyRate": 0.3126
},
"tests/e2e/ai/langchain-vectorstores.spec.ts": {
"avgDuration": 69923,
"testCount": 2,
"flakyRate": 0.0391
},
"tests/e2e/workflows/editor/ndv/pinning.spec.ts": {
"avgDuration": 68441,
"testCount": 10,
"flakyRate": 0.1299
},
"tests/e2e/workflows/editor/ndv/ndv-parameters.spec.ts": {
"avgDuration": 68415,
"testCount": 9,
"flakyRate": 0.0094
},
"tests/e2e/building-blocks/canvas-actions.spec.ts": {
"avgDuration": 66499,
"testCount": 9,
"flakyRate": 0.0037
},
"tests/e2e/workflows/editor/execution/logs.spec.ts": {
"avgDuration": 65890,
"testCount": 8,
"flakyRate": 0.0019
},
"tests/e2e/workflows/executions/filter.spec.ts": {
"avgDuration": 61881,
"testCount": 2,
"flakyRate": 0.3026
},
"tests/e2e/workflows/editor/viewer-permissions.spec.ts": {
"avgDuration": 61620,
"testCount": 3,
"flakyRate": 0.0019
},
"tests/e2e/ai/assistant-credential-help.spec.ts": {
"avgDuration": 59289,
"testCount": 4,
"flakyRate": 0.0106
},
"tests/e2e/workflows/editor/subworkflows/extraction.spec.ts": {
"avgDuration": 59183,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/projects/project-settings.spec.ts": {
"avgDuration": 57519,
"testCount": 8,
"flakyRate": 0.0019
},
"tests/e2e/node-creator/actions.spec.ts": {
"avgDuration": 56035,
"testCount": 4,
"flakyRate": 0.0056
},
"tests/e2e/ai/assistant-code-help.spec.ts": {
"avgDuration": 55927,
"testCount": 2,
"flakyRate": 0.013
},
"tests/e2e/workflows/editor/expressions/modal.spec.ts": {
"avgDuration": 54475,
"testCount": 6,
"flakyRate": 0.0038
},
"tests/e2e/chat-hub/chat-hub-basic.spec.ts": {
"avgDuration": 54335,
"testCount": 3,
"flakyRate": 0.0395
},
"tests/e2e/ai/assistant-support-chat.spec.ts": {
"avgDuration": 54072,
"testCount": 3,
"flakyRate": 0.0112
},
"tests/e2e/nodes/send-and-wait.spec.ts": {
"avgDuration": 52972,
"testCount": 5,
"flakyRate": 0.0144
},
"tests/e2e/workflows/editor/execution/debug.spec.ts": {
"avgDuration": 52540,
"testCount": 4,
"flakyRate": 0.0339
},
"tests/e2e/workflows/checklist/production-checklist.spec.ts": {
"avgDuration": 52502,
"testCount": 7,
"flakyRate": 0.0019
},
"tests/e2e/workflows/editor/routing.spec.ts": {
"avgDuration": 52209,
"testCount": 6,
"flakyRate": 0.0019
},
"tests/e2e/workflows/editor/expressions/inline.spec.ts": {
"avgDuration": 51959,
"testCount": 7,
"flakyRate": 0.0602
},
"tests/e2e/ai/hitl-for-tools.spec.ts": {
"avgDuration": 51720,
"testCount": 2,
"flakyRate": 0.0089
},
"tests/e2e/dynamic-credentials/execution-status.spec.ts": {
"avgDuration": 49785,
"testCount": 2,
"flakyRate": 0.0037
},
"tests/e2e/regression/ADO-4462-template-setup-experiment.spec.ts": {
"avgDuration": 49662,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/projects/projects-move-resources.spec.ts": {
"avgDuration": 48906,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/workflows/editor/ndv/paired-item.spec.ts": {
"avgDuration": 48408,
"testCount": 6,
"flakyRate": 0
},
"tests/e2e/nodes/form-trigger-node.spec.ts": {
"avgDuration": 48230,
"testCount": 5,
"flakyRate": 0.0053
},
"tests/e2e/projects/folders-basic.spec.ts": {
"avgDuration": 47996,
"testCount": 11,
"flakyRate": 0.0055
},
"tests/e2e/workflows/editor/expressions/transformation.spec.ts": {
"avgDuration": 46587,
"testCount": 6,
"flakyRate": 0.0019
},
"tests/e2e/building-blocks/node-details-configuration.spec.ts": {
"avgDuration": 46585,
"testCount": 7,
"flakyRate": 0.0019
},
"tests/e2e/ai/rag-callout.spec.ts": {
"avgDuration": 45684,
"testCount": 2,
"flakyRate": 0.0075
},
"tests/e2e/credentials/global.spec.ts": {
"avgDuration": 45667,
"testCount": 5,
"flakyRate": 0.0019
},
"tests/e2e/workflows/editor/tags.spec.ts": {
"avgDuration": 44112,
"testCount": 7,
"flakyRate": 0
},
"tests/e2e/api/waiting-endpoint-security.spec.ts": {
"avgDuration": 44090,
"testCount": 2,
"flakyRate": 0.0168
},
"tests/e2e/workflows/editor/workflow-actions/publish.spec.ts": {
"avgDuration": 43744,
"testCount": 8,
"flakyRate": 0.0037
},
"tests/e2e/api/wait-form-resume.spec.ts": {
"avgDuration": 43563,
"testCount": 2,
"flakyRate": 0.0075
},
"tests/e2e/chat-hub/chat-hub-workflow-agent.spec.ts": {
"avgDuration": 43386,
"testCount": 2,
"flakyRate": 0.1304
},
"tests/e2e/projects/folders-advanced.spec.ts": {
"avgDuration": 42193,
"testCount": 6,
"flakyRate": 0
},
"tests/e2e/ai/workflow-builder.spec.ts": {
"avgDuration": 41361,
"testCount": 5,
"flakyRate": 0.0074
},
"tests/e2e/workflows/editor/subworkflows/workflow-selector.spec.ts": {
"avgDuration": 41020,
"testCount": 5,
"flakyRate": 0.0019
},
"tests/e2e/chat-hub/chat-hub-attachment.spec.ts": {
"avgDuration": 40578,
"testCount": 3,
"flakyRate": 0.075
},
"tests/e2e/nodes/kafka-nodes.spec.ts": {
"avgDuration": 40562,
"testCount": 2,
"flakyRate": 0.0057
},
"tests/e2e/settings/log-streaming/log-streaming-observability.spec.ts": {
"avgDuration": 40559,
"testCount": 2,
"flakyRate": 0.0019
},
"tests/e2e/building-blocks/credentials.spec.ts": {
"avgDuration": 40125,
"testCount": 6,
"flakyRate": 0
},
"tests/e2e/ai/chat-session.spec.ts": {
"avgDuration": 39605,
"testCount": 1,
"flakyRate": 0.0093
},
"tests/e2e/workflows/editor/ndv/ndv-floating-nodes.spec.ts": {
"avgDuration": 39174,
"testCount": 4,
"flakyRate": 0.0056
},
"tests/e2e/workflows/editor/ndv/resource-mapper.spec.ts": {
"avgDuration": 38031,
"testCount": 5,
"flakyRate": 0.0094
},
"tests/e2e/auth/admin-smoke.spec.ts": {
"avgDuration": 37487,
"testCount": 1,
"flakyRate": 0.0112
},
"tests/e2e/workflows/templates/templates.spec.ts": {
"avgDuration": 37367,
"testCount": 9,
"flakyRate": 0.0038
},
"tests/e2e/auth/authenticated.spec.ts": {
"avgDuration": 37279,
"testCount": 5,
"flakyRate": 0.5
},
"tests/e2e/node-creator/special-nodes.spec.ts": {
"avgDuration": 36223,
"testCount": 3,
"flakyRate": 0.0037
},
"tests/e2e/cloud/cloud.spec.ts": {
"avgDuration": 35463,
"testCount": 3,
"flakyRate": 0.0019
},
"tests/e2e/api/discovery.spec.ts": {
"avgDuration": 34520,
"testCount": 4,
"flakyRate": 0.0075
},
"tests/e2e/api/webhook-external.spec.ts": {
"avgDuration": 33749,
"testCount": 2,
"flakyRate": 0.0074
},
"tests/e2e/node-creator/categories.spec.ts": {
"avgDuration": 31496,
"testCount": 5,
"flakyRate": 0.0019
},
"tests/e2e/settings/external-secrets/aws-secrets-manager.spec.ts": {
"avgDuration": 31370,
"testCount": 1,
"flakyRate": 0.0019
},
"tests/e2e/chat-hub/chat-hub-chat-user.spec.ts": {
"avgDuration": 31053,
"testCount": 1,
"flakyRate": 0.0148
},
"tests/e2e/ai/langchain-chains.spec.ts": {
"avgDuration": 30019,
"testCount": 4,
"flakyRate": 0.0019
},
"tests/e2e/sentry/sentry-baseline.spec.ts": {
"avgDuration": 29919,
"testCount": 3,
"flakyRate": 0.0094
},
"tests/e2e/workflows/editor/editor-after-route-changes.spec.ts": {
"avgDuration": 28537,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/nodes/community-nodes.spec.ts": {
"avgDuration": 28299,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/settings/personal/personal.spec.ts": {
"avgDuration": 28173,
"testCount": 2,
"flakyRate": 0.0018
},
"tests/e2e/workflows/list/import.spec.ts": {
"avgDuration": 27685,
"testCount": 5,
"flakyRate": 0.0037
},
"tests/e2e/app-config/demo-reimport.spec.ts": {
"avgDuration": 26704,
"testCount": 3,
"flakyRate": 0.0019
},
"tests/e2e/workflows/editor/execution/inject-previous.spec.ts": {
"avgDuration": 25773,
"testCount": 2,
"flakyRate": 0.1013
},
"tests/e2e/settings/environments/variables.spec.ts": {
"avgDuration": 25388,
"testCount": 7,
"flakyRate": 0.0036
},
"tests/e2e/workflows/editor/subworkflows/debugging.spec.ts": {
"avgDuration": 24987,
"testCount": 4,
"flakyRate": 0.0019
},
"tests/e2e/settings/external-secrets/secret-providers-connections-ui.spec.ts": {
"avgDuration": 24924,
"testCount": 2,
"flakyRate": 0.0038
},
"tests/e2e/chat-hub/chat-hub-personal-agent.spec.ts": {
"avgDuration": 24517,
"testCount": 2,
"flakyRate": 0.0019
},
"tests/e2e/workflows/demo-diff.spec.ts": {
"avgDuration": 23452,
"testCount": 9,
"flakyRate": 0
},
"tests/e2e/node-creator/navigation.spec.ts": {
"avgDuration": 22759,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/settings/log-streaming/log-streaming.spec.ts": {
"avgDuration": 22635,
"testCount": 5,
"flakyRate": 0
},
"tests/e2e/auth/password-reset.spec.ts": {
"avgDuration": 22549,
"testCount": 1,
"flakyRate": 0.0056
},
"tests/e2e/building-blocks/workflow-entry-points.spec.ts": {
"avgDuration": 22343,
"testCount": 5,
"flakyRate": 0.0019
},
"tests/e2e/api/webhook-isolation.spec.ts": {
"avgDuration": 22179,
"testCount": 14,
"flakyRate": 1
},
"tests/e2e/sharing/access-control.spec.ts": {
"avgDuration": 21220,
"testCount": 5,
"flakyRate": 0.0018
},
"tests/e2e/building-blocks/user-service.spec.ts": {
"avgDuration": 21016,
"testCount": 8,
"flakyRate": 0.0019
},
"tests/e2e/app-config/security-notifications.spec.ts": {
"avgDuration": 20927,
"testCount": 5,
"flakyRate": 0.0019
},
"tests/e2e/capabilities/task-runner.spec.ts": {
"avgDuration": 20563,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/settings/users/users.spec.ts": {
"avgDuration": 19620,
"testCount": 5,
"flakyRate": 0.0018
},
"tests/e2e/nodes/if-node.spec.ts": {
"avgDuration": 19366,
"testCount": 2,
"flakyRate": 0.0261
},
"tests/e2e/chat-hub/chat-hub-settings.spec.ts": {
"avgDuration": 19317,
"testCount": 2,
"flakyRate": 0.0149
},
"tests/e2e/regression/PAY-4367-node-shifting-cyclic.spec.ts": {
"avgDuration": 18403,
"testCount": 3,
"flakyRate": 0.0018
},
"tests/e2e/sharing/workflow-sharing.spec.ts": {
"avgDuration": 18390,
"testCount": 4,
"flakyRate": 0.0187
},
"tests/e2e/nodes/mcp-trigger.spec.ts": {
"avgDuration": 17518,
"testCount": 23,
"flakyRate": 0.0206
},
"tests/e2e/workflows/editor/ndv/io-filter.spec.ts": {
"avgDuration": 16620,
"testCount": 2,
"flakyRate": 0.0037
},
"tests/e2e/node-creator/vector-stores.spec.ts": {
"avgDuration": 16413,
"testCount": 3,
"flakyRate": 0.0019
},
"tests/e2e/capabilities/proxy-server.spec.ts": {
"avgDuration": 15032,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/sharing/credential-sharing.spec.ts": {
"avgDuration": 14609,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/workflows/editor/execution/partial.spec.ts": {
"avgDuration": 14272,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/nodes/http-request-node.spec.ts": {
"avgDuration": 14008,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/regression/AI-812-partial-execs-broken-when-using-chat-trigger.spec.ts": {
"avgDuration": 12959,
"testCount": 2,
"flakyRate": 0.0037
},
"tests/e2e/nodes/pdf-node.spec.ts": {
"avgDuration": 12937,
"testCount": 1,
"flakyRate": 0.0094
},
"tests/e2e/app-config/demo.spec.ts": {
"avgDuration": 12575,
"testCount": 4,
"flakyRate": 0.0169
},
"tests/e2e/regression/ADO-2372-prevent-clipping-params.spec.ts": {
"avgDuration": 11272,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/node-creator/workflows.spec.ts": {
"avgDuration": 11165,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/settings/workers/workers.spec.ts": {
"avgDuration": 10895,
"testCount": 4,
"flakyRate": 0.0019
},
"tests/e2e/regression/ADO-1338-ndv-missing-input-panel.spec.ts": {
"avgDuration": 9094,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/regression/SUG-121-fields-reset-after-closing-ndv.spec.ts": {
"avgDuration": 7975,
"testCount": 1,
"flakyRate": 0.0261
},
"tests/e2e/workflows/editor/ndv/schema-preview.spec.ts": {
"avgDuration": 7781,
"testCount": 1,
"flakyRate": 0.0019
},
"tests/e2e/regression/CAT-726-canvas-node-connectors-not-rendered-when-nodes-inserted.spec.ts": {
"avgDuration": 7648,
"testCount": 1,
"flakyRate": 0.0019
},
"tests/e2e/regression/AI-1401-sub-nodes-input-panel.spec.ts": {
"avgDuration": 7312,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/regression/SUG-38-inline-expression-preview.spec.ts": {
"avgDuration": 7060,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/settings/community-nodes/community-nodes.spec.ts": {
"avgDuration": 6765,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/regression/AI-716-correctly-set-up-agent-model-shows-error.spec.ts": {
"avgDuration": 6689,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/api/binary-data-xss.spec.ts": {
"avgDuration": 6602,
"testCount": 1,
"flakyRate": 0.0037
},
"tests/e2e/nodes/email-send-node.spec.ts": {
"avgDuration": 6601,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/credentials/oauth.spec.ts": {
"avgDuration": 6299,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/auth/signin.spec.ts": {
"avgDuration": 6147,
"testCount": 1,
"flakyRate": 0.0019
},
"tests/e2e/regression/ADO-2230-ndv-reset-data-pagination.spec.ts": {
"avgDuration": 5986,
"testCount": 1,
"flakyRate": 0.0019
},
"tests/e2e/nodes/schedule-trigger-node.spec.ts": {
"avgDuration": 5738,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/workflows/editor/canvas/stickies.spec.ts": {
"avgDuration": 5546,
"testCount": 1,
"flakyRate": 0.0018
},
"tests/e2e/workflows/editor/canvas/focus-panel.spec.ts": {
"avgDuration": 5108,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/regression/ADO-2929-can-load-old-switch-node-workflows.spec.ts": {
"avgDuration": 4878,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/settings/log-streaming/log-streaming-ui-e2e.spec.ts": {
"avgDuration": 4794,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/mcp/mcp-service.spec.ts": {
"avgDuration": 4302,
"testCount": 26,
"flakyRate": 0
},
"tests/e2e/app-config/versions.spec.ts": {
"avgDuration": 2952,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/workflows/editor/subworkflows/wait.spec.ts": {
"avgDuration": 2894,
"testCount": 4,
"flakyRate": 0.0094
},
"tests/e2e/dynamic-credentials/external-user-trigger.spec.ts": {
"avgDuration": 1392,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/workflows/editor/subworkflows/subworkflow-version-resolution.spec.ts": {
"avgDuration": 1310,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/nodes/n8n-trigger.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/credentials/api-operations.spec.ts": {
"avgDuration": 60000,
"testCount": 5,
"flakyRate": 0
},
"tests/e2e/app-config/env-feature-flags.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/dynamic-credentials/resolver-deletion.spec.ts": {
"avgDuration": 60000,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/settings/external-secrets/secret-providers-connections.spec.ts": {
"avgDuration": 60000,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/nodes/code-node-api.spec.ts": {
"avgDuration": 60000,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/workflows/editor/workflow-actions/archive.spec.ts": {
"avgDuration": 60000,
"testCount": 7,
"flakyRate": 0
},
"tests/e2e/settings/environments/source-control.spec.ts": {
"avgDuration": 60000,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/workflows/editor/workflow-actions/run.spec.ts": {
"avgDuration": 60000,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/ai/langchain-tools.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/ai/langchain-memory.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/workflows/editor/workflow-actions/copy-paste.spec.ts": {
"avgDuration": 60000,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/workflows/editor/execution/previous-nodes.spec.ts": {
"avgDuration": 60000,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/source-control/push.spec.ts": {
"avgDuration": 60000,
"testCount": 4,
"flakyRate": 0
},
"tests/e2e/app-config/nps-survey.spec.ts": {
"avgDuration": 60000,
"testCount": 1,
"flakyRate": 0
},
"tests/e2e/source-control/pull.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/workflows/editor/workflow-actions/settings.spec.ts": {
"avgDuration": 60000,
"testCount": 3,
"flakyRate": 0
},
"tests/e2e/workflows/editor/workflow-actions/duplicate.spec.ts": {
"avgDuration": 60000,
"testCount": 2,
"flakyRate": 0
},
"tests/e2e/ai/evaluations.spec.ts": {
"avgDuration": 60000,
"testCount": 1,
"flakyRate": 0
}
}
}

83
.github/workflows/backport.yml vendored Normal file
View file

@ -0,0 +1,83 @@
name: 'Util: Backport pull request changes'
run-name: Backport pull request ${{ github.event.pull_request.number || inputs.pull-request-id }}
on:
pull_request:
types: [closed]
workflow_dispatch:
inputs:
pull-request-id:
description: 'The ID number of the pull request (e.g. 3342). No #, no extra letters.'
required: true
type: string
permissions:
contents: write
pull-requests: write
jobs:
backport:
if: |
github.event.pull_request.merged == true ||
github.event_name == 'workflow_dispatch'
runs-on: ubuntu-slim
steps:
- name: Generate GitHub App Token
id: generate-token
uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
with:
app-id: ${{ secrets.N8N_ASSISTANT_APP_ID }}
private-key: ${{ secrets.N8N_ASSISTANT_PRIVATE_KEY }}
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
token: ${{ steps.generate-token.outputs.token }}
fetch-depth: 0
- name: Setup Node.js
uses: ./.github/actions/setup-nodejs
with:
build-command: ''
install-command: pnpm install --frozen-lockfile --dir ./.github/scripts --ignore-workspace
- name: Compute backport targets
id: targets
env:
PULL_REQUEST_ID: ${{ inputs.pull-request-id }}
GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }}
run: node .github/scripts/compute-backport-targets.mjs
- name: Backport
if: steps.targets.outputs.target_branches != ''
uses: korthout/backport-action@4aaf0e03a94ff0a619c9a511b61aeb42adea5b02 # v4.2.0
with:
github_token: ${{ steps.generate-token.outputs.token }}
source_pr_number: ${{ github.event.pull_request.number || inputs.pull-request-id }}
target_branches: ${{ steps.targets.outputs.target_branches }}
pull_description: |-
# Description
Backport of #${pull_number} to `${target_branch}`.
## Checklist for the author (@${pull_author}) to go through.
- [ ] Review the backport changes
- [ ] Fix possible conflicts
- [ ] Merge to target branch
After this PR has been merged, it will be picked up in the next patch release for release track.
# Original description
${pull_description}
pull_title: ${pull_title} (backport to ${target_branch})
add_author_as_assignee: true
add_author_as_reviewer: true
copy_assignees: true
copy_requested_reviewers: false
copy_labels_pattern: '^(?!Backport to\b).+' # Copy everything except backport labels
add_labels: 'automation:backport'
experimental: >
{
"conflict_resolution": "draft_commit_conflicts"
}

View file

@ -1,46 +0,0 @@
name: Destroy Benchmark Env
on:
schedule:
- cron: '0 5 * * *'
workflow_dispatch:
permissions:
id-token: write
contents: read
concurrency:
group: benchmark
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
environment: benchmarking
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: Azure login
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
client-id: ${{ secrets.BENCHMARK_ARM_CLIENT_ID }}
tenant-id: ${{ secrets.BENCHMARK_ARM_TENANT_ID }}
subscription-id: ${{ secrets.BENCHMARK_ARM_SUBSCRIPTION_ID }}
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22.x
- name: Setup corepack and pnpm
run: |
npm i -g corepack@0.33
corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Destroy cloud env
run: pnpm destroy-cloud-env
working-directory: packages/@n8n/benchmark

View file

@ -1,122 +0,0 @@
name: Run Nightly Benchmark
run-name: Benchmark ${{ inputs.n8n_tag || 'nightly' }}
on:
schedule:
- cron: '30 1,2,3 * * *'
workflow_dispatch:
inputs:
debug:
description: 'Use debug logging'
required: true
default: 'false'
n8n_tag:
description: 'Name of the n8n docker tag to run the benchmark against.'
required: true
default: 'nightly'
benchmark_tag:
description: 'Name of the benchmark cli docker tag to run the benchmark with.'
required: true
default: 'latest'
env:
ARM_CLIENT_ID: ${{ secrets.BENCHMARK_ARM_CLIENT_ID }}
ARM_SUBSCRIPTION_ID: ${{ secrets.BENCHMARK_ARM_SUBSCRIPTION_ID }}
ARM_TENANT_ID: ${{ secrets.BENCHMARK_ARM_TENANT_ID }}
N8N_TAG: ${{ inputs.n8n_tag || 'nightly' }}
N8N_BENCHMARK_TAG: ${{ inputs.benchmark_tag || 'latest' }}
DEBUG: ${{ inputs.debug == 'true' && '--debug' || '' }}
permissions:
id-token: write
contents: read
concurrency:
group: benchmark
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
environment: benchmarking
steps:
- name: Checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3
with:
terraform_version: '1.8.5'
- uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 # v4.4.0
with:
node-version: 22.x
- name: Setup corepack and pnpm
run: |
npm i -g corepack@0.33
corepack enable
- name: Install dependencies
run: pnpm install --frozen-lockfile
- name: Azure login
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
client-id: ${{ env.ARM_CLIENT_ID }}
tenant-id: ${{ env.ARM_TENANT_ID }}
subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
- name: Destroy any existing environment
run: pnpm destroy-cloud-env
working-directory: packages/@n8n/benchmark
- name: Provision the environment
run: pnpm provision-cloud-env ${{ env.DEBUG }}
working-directory: packages/@n8n/benchmark
- name: Run the benchmark
id: benchmark
env:
BENCHMARK_RESULT_WEBHOOK_URL: ${{ secrets.BENCHMARK_RESULT_WEBHOOK_URL }}
BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER: ${{ secrets.BENCHMARK_RESULT_WEBHOOK_AUTH_HEADER }}
N8N_LICENSE_CERT: ${{ secrets.N8N_BENCHMARK_LICENSE_CERT }}
run: |
pnpm benchmark-in-cloud \
--vus 5 \
--duration 1m \
--n8nTag ${{ env.N8N_TAG }} \
--benchmarkTag ${{ env.N8N_BENCHMARK_TAG }} \
${{ env.DEBUG }}
working-directory: packages/@n8n/benchmark
# We need to login again because the access token expires
- name: Azure login
if: always()
uses: azure/login@6c251865b4e6290e7b78be643ea2d005bc51f69a # v2.1.1
with:
client-id: ${{ env.ARM_CLIENT_ID }}
tenant-id: ${{ env.ARM_TENANT_ID }}
subscription-id: ${{ env.ARM_SUBSCRIPTION_ID }}
- name: Destroy the environment
if: always()
run: pnpm destroy-cloud-env ${{ env.DEBUG }}
working-directory: packages/@n8n/benchmark
- name: Fail `build` job if `benchmark` step failed
if: steps.benchmark.outcome == 'failure'
run: exit 1
notify-on-failure:
name: Notify Cats on failure
runs-on: ubuntu-latest
needs: [build]
if: failure()
steps:
- uses: act10ns/slack@44541246747a30eb3102d87f7a4cc5471b0ffb7d # v2.1.0
with:
status: ${{ job.status }}
channel: '#team-catalysts'
webhook-url: ${{ secrets.SLACK_WEBHOOK_URL }}
message: Benchmark run failed for n8n tag `${{ inputs.n8n_tag || 'nightly' }}` - ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}

71
.github/workflows/build-base-image.yml vendored Normal file
View file

@ -0,0 +1,71 @@
name: 'Build: Base Image'
on:
push:
branches:
- master
paths:
- 'docker/images/n8n-base/Dockerfile'
- '.github/workflows/build-base-image.yml'
pull_request:
paths:
- 'docker/images/n8n-base/Dockerfile'
- '.github/workflows/build-base-image.yml'
workflow_dispatch:
inputs:
push:
description: 'Push to registries'
required: false
default: false
type: boolean
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
node_version: ['22', '24.14.1', '25']
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to DHI Registry (for pulling base images)
uses: ./.github/actions/docker-registry-login
with:
login-ghcr: 'false'
login-dhi: 'true'
dockerhub-username: ${{ secrets.DOCKER_USERNAME }}
dockerhub-password: ${{ secrets.DOCKER_PASSWORD }}
- name: Login to Docker registries (for pushing)
if: github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push == true)
uses: ./.github/actions/docker-registry-login
with:
login-ghcr: 'true'
login-dockerhub: 'true'
dockerhub-username: ${{ secrets.DOCKER_USERNAME }}
dockerhub-password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
with:
context: .
file: ./docker/images/n8n-base/Dockerfile
build-args: |
NODE_VERSION=${{ matrix.node_version }}
platforms: linux/amd64,linux/arm64
provenance: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push == true) }}
sbom: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push == true) }}
push: ${{ github.event_name == 'push' || (github.event_name == 'workflow_dispatch' && inputs.push == true) }}
tags: |
${{ secrets.DOCKER_USERNAME }}/base:${{ matrix.node_version }}-${{ github.sha }}
${{ secrets.DOCKER_USERNAME }}/base:${{ matrix.node_version }}
ghcr.io/${{ github.repository_owner }}/base:${{ matrix.node_version }}-${{ github.sha }}
ghcr.io/${{ github.repository_owner }}/base:${{ matrix.node_version }}
no-cache: true

View file

@ -0,0 +1,41 @@
name: 'Build: Benchmark Image'
on:
workflow_dispatch:
push:
branches:
- master
paths:
- 'packages/@n8n/benchmark/**'
- 'pnpm-lock.yaml'
- 'pnpm-workspace.yaml'
- '.github/workflows/build-benchmark-image.yml'
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
- name: Set up QEMU
uses: docker/setup-qemu-action@ce360397dd3f832beb865e1373c09c0e9f86d70a # v4.0.0
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@4d04d5d9486b7bd6fa91e7baf45bbb4f8b9deedd # v4.0.0
- name: Login to GitHub Container Registry
uses: ./.github/actions/docker-registry-login
- name: Build
uses: docker/build-push-action@d08e5c354a6adb9ed34480a06d141179aa583294 # v7.0.0
env:
DOCKER_BUILD_SUMMARY: false
with:
context: .
file: ./packages/@n8n/benchmark/Dockerfile
platforms: linux/amd64
provenance: false
push: true
tags: |
ghcr.io/${{ github.repository_owner }}/n8n-benchmark:latest

View file

@ -1,100 +0,0 @@
name: Trigger build/unit tests on PR comment
on:
issue_comment:
types: [created]
permissions:
pull-requests: read
contents: read
actions: write
issues: write
jobs:
validate_and_dispatch:
name: Validate user and dispatch CI workflow
if: github.event.issue.pull_request && startsWith(github.event.comment.body, '/build-unit-test')
runs-on: ubuntu-latest
steps:
- name: Validate user permissions and collect PR data
id: check_permissions
uses: actions/github-script@v7
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
script: |
const commenter = context.actor;
const body = (context.payload.comment.body || '').trim();
const isCommand = body.startsWith('/build-unit-test');
const allowedPermissions = ['admin', 'write', 'maintain'];
const commentId = context.payload.comment.id;
const { owner, repo } = context.repo;
async function react(content) {
try {
await github.rest.reactions.createForIssueComment({
owner,
repo,
comment_id: commentId,
content,
});
} catch (error) {
console.log(`Failed to add reaction '${content}': ${error.message}`);
}
}
core.setOutput('proceed', 'false');
core.setOutput('headSha', '');
core.setOutput('prNumber', '');
if (!context.payload.issue.pull_request || !isCommand) {
console.log('Comment is not /build-unit-test on a pull request. Skipping.');
return;
}
let permission;
try {
const { data } = await github.rest.repos.getCollaboratorPermissionLevel({
owner,
repo,
username: commenter,
});
permission = data.permission;
} catch (error) {
console.log(`Could not verify permissions for @${commenter}: ${error.message}`);
await react('confused');
return;
}
if (!allowedPermissions.includes(permission)) {
console.log(`User @${commenter} has '${permission}' permission; requires admin/write/maintain.`);
await react('-1');
return;
}
try {
const prNumber = context.issue.number;
const { data: pr } = await github.rest.pulls.get({
owner,
repo,
pull_number: prNumber,
});
await react('+1');
core.setOutput('proceed', 'true');
core.setOutput('headSha', pr.head.sha);
core.setOutput('prNumber', String(prNumber));
} catch (error) {
console.log(`Failed to fetch PR details for PR #${context.issue.number}: ${error.message}`);
await react('confused');
}
- name: Dispatch build/unit test workflow
if: ${{ steps.check_permissions.outputs.proceed == 'true' }}
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
HEAD_SHA: ${{ steps.check_permissions.outputs.headSha }}
PR_NUMBER: ${{ steps.check_permissions.outputs.prNumber }}
run: |
gh workflow run ci-manual-build-unit-tests.yml \
--repo "${{ github.repository }}" \
-f ref="${HEAD_SHA}" \
-f pr_number="${PR_NUMBER}"

Some files were not shown because too many files have changed in this diff Show more