Skip to content

refactor: migrate n8n node to official n8n-node CLI tooling#7

Open
pranavjana wants to merge 4 commits intomainfrom
refactor/n8n-node-cli-tooling
Open

refactor: migrate n8n node to official n8n-node CLI tooling#7
pranavjana wants to merge 4 commits intomainfrom
refactor/n8n-node-cli-tooling

Conversation

@pranavjana
Copy link
Contributor

Summary

Migrates the n8n-nodes-tinyfish community node from a hand-rolled build setup to the official @n8n/node-cli tooling. This is required for submitting the node for n8n verification and ensures compliance with their technical and UX guidelines.

What changed

Build tooling (package.json)

  • Replaced custom tsc && cp build script with n8n-node build
  • Replaced tsc --noEmit lint with n8n-node lint (ESLint with n8n-specific community node rules)
  • Added n8n-node dev, n8n-node release, n8n-node prerelease scripts
  • Added devDependencies: @n8n/node-cli, eslint@9, prettier, release-it
  • Removed n8n-workflow from devDependencies (stays in peerDependencies only)
  • Removed unnecessary main field (n8n resolves nodes via the n8n.nodes array)
  • Set n8n.strict: true for full cloud-compatible lint rules

Config files (new)

  • eslint.config.mjs — ESLint flat config importing @n8n/node-cli/eslint (includes eslint-plugin-n8n-nodes-base rules for nodes, credentials, and package.json validation)
  • .prettierrc.js — n8n standard Prettier config (tabs, single quotes, trailing commas, 100 char width)

tsconfig.json

  • Aligned with n8n-nodes-starter template: target: es2019, updated lib, added useUnknownInCatchVariables: false, incremental: true

package.json metadata

  • Fixed repository URL to standard git format with directory field for monorepo support

Lint fixes

  • Tinyfish.node.ts: Use NodeConnectionTypes.Main enum instead of string literal 'main' for inputs/outputs
  • TinyfishDescription.ts: Added noDataExpression: true to operation field, alphabetized operation options, set limit default to 50 (n8n conventions)
  • GenericFunctions.ts: Removed useless try/catch wrapper in consumeSseStream(), removed stale retry JSDoc from tinyfishApiRequest()

GitHub Actions workflows (new)

  • n8n-ci.yml — Runs lint + build on PRs and pushes to main
  • n8n-publish.yml — Publishes to npm with --provenance on GitHub Release creation (required for all community nodes from May 2026)

Verification

  • npm run lint passes cleanly (zero errors)
  • npm run build produces correct dist/ output with SVG icons
  • npx @n8n/scan-community-package n8n-nodes-tinyfish passes all security checks
  • All patterns verified against the n8n-nodes-starter template

Follow-up (not in this PR)

  • Add dark mode icon variant (tinyfish.dark.svg) for n8n dark theme support
  • Remove stale "Timeout" option from README that references an unimplemented feature

- Replace custom build/lint scripts with n8n-node CLI commands
- Add ESLint flat config with n8n community node rules (strict mode)
- Add Prettier config matching n8n conventions
- Align tsconfig.json with n8n-nodes-starter template
- Fix repository URL to standard git format with directory field
- Remove unnecessary main field from package.json
- Use NodeConnectionTypes.Main enum instead of string literals
- Alphabetize operation options per n8n lint rules
- Add noDataExpression to operation field
- Set limit default to 50 per n8n conventions
- Remove useless try/catch wrapper in consumeSseStream
- Remove stale retry JSDoc from tinyfishApiRequest
- Add CI workflow for lint/build on PRs
- Add publish workflow with npm provenance for May 2026 requirement
@coderabbitai
Copy link

coderabbitai bot commented Feb 25, 2026

📝 Walkthrough

Walkthrough

Adds CI/CD and code-style tooling for the n8n node package and refactors node configuration and build tooling. Two GitHub Actions workflows are added: one to run build/lint on PRs and main pushes, and one to publish the package to npm on releases or manual dispatch. Prettier and ESLint config files are added/proxied. Tinyfish node updates include enum-based connection types, reworked operation options (add getRun, listRuns, reordering), a noDataExpression flag, and an increased default list limit. package.json and tsconfig.json are updated to use n8n-node CLI tooling, adjust TypeScript targets, and add package metadata.

Sequence Diagram(s)

mermaid
sequenceDiagram
participant Dev as Developer (push/PR)
participant GH as GitHub Actions
participant Repo as Repository (n8n/)
participant Runner as Ubuntu Runner
participant NodeEnv as Node 22
Dev->>Repo: push or open PR under n8n/
Repo->>GH: trigger "n8n Node CI"
GH->>Runner: start job (working-dir: n8n)
Runner->>Repo: checkout
Runner->>NodeEnv: setup-node (v22)
Runner->>Runner: npm install, npm run lint, npm run build
Runner-->>GH: job status (success/failure)

mermaid
sequenceDiagram
participant Maintainer as Maintainer (release or manual)
participant GH as GitHub Actions
participant Repo as Repository (n8n/)
participant Runner as Ubuntu Runner
participant NodeEnv as Node 22
participant Npm as npm Registry
Maintainer->>Repo: publish release / manual dispatch
Repo->>GH: trigger "Publish n8n Node to npm"
GH->>Runner: start publish job (working-dir: n8n)
Runner->>Repo: checkout
Runner->>NodeEnv: setup-node (v22, registry)
Runner->>Runner: npm ci, npm run lint, npm run build
Runner->>Npm: npm publish (using NODE_AUTH_TOKEN)
Npm-->>Runner: publish response
Runner-->>GH: job status (success/failure)

🚥 Pre-merge checks | ✅ 2
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: migrating the n8n node from a custom build setup to the official n8n-node CLI tooling, which aligns with the comprehensive refactoring across multiple files.
Description check ✅ Passed The description is highly detailed and directly related to the changeset, covering build tooling updates, new config files, TypeScript configuration changes, code fixes, and CI/CD workflows that match the file modifications.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/n8n-node-cli-tooling

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (2)
.github/workflows/n8n-ci.yml (1)

3-7: Consider path filters to avoid running this workflow on unrelated monorepo changes.

This CI only validates n8n/, so restricting triggers to relevant paths will save runner time and reduce noise.

⚙️ Suggested trigger refinement
 on:
   pull_request:
+    paths:
+      - 'n8n/**'
+      - '.github/workflows/n8n-ci.yml'
   push:
     branches: [main]
+    paths:
+      - 'n8n/**'
+      - '.github/workflows/n8n-ci.yml'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/n8n-ci.yml around lines 3 - 7, The workflow currently
triggers on broad events "pull_request" and "push"; add path filters to both
triggers so the CI only runs for changes under the n8n package. Update the "on"
block for "pull_request" and "push" to include a "paths:" array with "n8n/**"
(and any other relevant subpaths you want validated) or use "paths-ignore:" to
skip unrelated monorepo directories, ensuring only changes affecting the n8n
codebase run this workflow.
n8n/package.json (1)

26-33: Optional: unify watch/dev flow under n8n-node tooling.

Now that dev is n8n-node dev, keeping build:watch on raw tsc --watch can lead to mixed local workflows.

♻️ Suggested script cleanup
  "scripts": {
    "build": "n8n-node build",
-   "build:watch": "tsc --watch",
+   "build:watch": "n8n-node dev",
    "dev": "n8n-node dev",
    "lint": "n8n-node lint",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@n8n/package.json` around lines 26 - 33, Unify the watch/dev flow by replacing
the raw TypeScript watcher with the n8n-node tooling: update the package.json
script "build:watch" (currently "tsc --watch") to use the n8n-node command
consistent with "dev" (e.g., "n8n-node dev --watch" or "n8n-node watch"
depending on available CLI flags), so all local workflows use the same n8n-node
toolchain; ensure you run/validate the "dev" and "build:watch" scripts
afterwards to confirm parity.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/n8n-publish.yml:
- Around line 3-10: The workflow currently triggers on any repository release
(on: release) which can cause the publish job named publish to run for unrelated
tags; add a tag guard by adding an if condition on the publish job that checks
the release tag pattern (e.g., if: startsWith(github.ref, 'refs/tags/n8n-') or
another agreed prefix) so the publish job only executes for intended release
tags; update the publish job's definition (the publish job block) to include
this if guard.

In `@n8n/nodes/Tinyfish/GenericFunctions.ts`:
- Around line 168-170: The SSE parsing loop leaves the final partial chunk in
buffer (buffer, lines) but breaks immediately when done is true, which can skip
the last "data:" frame; update the loop that reads chunks so that when
done===true you first process any remaining buffer: split buffer by '\n', treat
the residual chunk as a complete line (append it to lines or emit it) so the
final "data:" event (e.g., COMPLETE) is parsed before exiting, then break;
adjust logic around where buffer = lines.pop() is set to ensure leftover content
is not discarded and is parsed when done is seen.

---

Nitpick comments:
In @.github/workflows/n8n-ci.yml:
- Around line 3-7: The workflow currently triggers on broad events
"pull_request" and "push"; add path filters to both triggers so the CI only runs
for changes under the n8n package. Update the "on" block for "pull_request" and
"push" to include a "paths:" array with "n8n/**" (and any other relevant
subpaths you want validated) or use "paths-ignore:" to skip unrelated monorepo
directories, ensuring only changes affecting the n8n codebase run this workflow.

In `@n8n/package.json`:
- Around line 26-33: Unify the watch/dev flow by replacing the raw TypeScript
watcher with the n8n-node tooling: update the package.json script "build:watch"
(currently "tsc --watch") to use the n8n-node command consistent with "dev"
(e.g., "n8n-node dev --watch" or "n8n-node watch" depending on available CLI
flags), so all local workflows use the same n8n-node toolchain; ensure you
run/validate the "dev" and "build:watch" scripts afterwards to confirm parity.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 74fedc5 and e37011a.

⛔ Files ignored due to path filters (1)
  • n8n/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (9)
  • .github/workflows/n8n-ci.yml
  • .github/workflows/n8n-publish.yml
  • n8n/.prettierrc.js
  • n8n/eslint.config.mjs
  • n8n/nodes/Tinyfish/GenericFunctions.ts
  • n8n/nodes/Tinyfish/Tinyfish.node.ts
  • n8n/nodes/Tinyfish/TinyfishDescription.ts
  • n8n/package.json
  • n8n/tsconfig.json

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🧹 Nitpick comments (2)
.github/workflows/n8n-ci.yml (2)

25-25: npm install can silently mutate package-lock.json, hurting reproducibility.

npm ci is the idiomatic choice for CI because it performs a clean install that strictly follows the lockfile. npm install can resolve differently across environments if the lockfile is out of sync. If the "cross-version compatibility" concern is about the Node/npm version, consider pinning via engines in package.json instead and using npm ci here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/n8n-ci.yml at line 25, Replace the CI step that runs the
literal command "npm install" with "npm ci" to ensure a clean,
lockfile-respecting install; locate the workflow step containing the string "npm
install" and update it to "npm ci", and if cross-version compatibility is a
concern, add or update the "engines" field in package.json to pin Node/npm
versions rather than relying on "npm install" behavior.

12-14: Add explicit least-privilege permissions block.

Without an explicit permissions declaration the job inherits the repo/org default, which may be broader than needed.

🔒 Proposed fix
 jobs:
   build:
     runs-on: ubuntu-latest
+    permissions:
+      contents: read
     defaults:
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/n8n-ci.yml around lines 12 - 14, The workflow omits an
explicit permissions declaration for the build job; add a top-level permissions
block under the jobs.build stanza (the 'build' job) that explicitly grants only
the least privileges required by this CI (e.g., read-only for contents,
packages, and any tokens the job needs) by adding a 'permissions:' mapping
beneath the build job; ensure you list only the specific permissions the job
consumes (for example contents: read, checks: write or read as needed, id-token:
write only if OIDC is used) so the job no longer inherits broader repo/org
defaults.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In @.github/workflows/n8n-ci.yml:
- Around line 3-10: The workflow's on: pull_request and push path filters only
include 'n8n/**', which excludes the workflow file itself so CI won't run when
n8n-ci.yml is modified; update the on: block (the pull_request and push -> paths
entries) to also include the workflow file (n8n-ci.yml) so changes to this
workflow will trigger the job—modify the paths arrays under the on: section to
add the workflow filename alongside 'n8n/**'.

In @.github/workflows/n8n-publish.yml:
- Line 6: The manual-dispatch guard silently skips publishes because
workflow_dispatch sets github.ref to a branch (refs/heads/...), so change the
condition that currently uses startsWith(github.ref, 'refs/tags/n8n-') to allow
workflow_dispatch to bypass it by OR-ing with github.event_name ==
'workflow_dispatch' (or explicitly check github.event.action if you use a custom
dispatch payload); update the job condition(s) referencing
startsWith(github.ref, 'refs/tags/n8n-') (and the duplicate at the second
occurrence) so manual runs from branches will proceed instead of being silently
skipped.
- Line 26: Replace the 'run: npm install' step in the publish workflow with
'run: npm ci' so the pipeline performs a clean, lockfile-exact install; locate
the workflow job that currently contains the run step with "npm install" and
update it to "npm ci" to ensure reproducible builds for the publish pipeline.

---

Nitpick comments:
In @.github/workflows/n8n-ci.yml:
- Line 25: Replace the CI step that runs the literal command "npm install" with
"npm ci" to ensure a clean, lockfile-respecting install; locate the workflow
step containing the string "npm install" and update it to "npm ci", and if
cross-version compatibility is a concern, add or update the "engines" field in
package.json to pin Node/npm versions rather than relying on "npm install"
behavior.
- Around line 12-14: The workflow omits an explicit permissions declaration for
the build job; add a top-level permissions block under the jobs.build stanza
(the 'build' job) that explicitly grants only the least privileges required by
this CI (e.g., read-only for contents, packages, and any tokens the job needs)
by adding a 'permissions:' mapping beneath the build job; ensure you list only
the specific permissions the job consumes (for example contents: read, checks:
write or read as needed, id-token: write only if OIDC is used) so the job no
longer inherits broader repo/org defaults.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between e37011a and 150c326.

📒 Files selected for processing (2)
  • .github/workflows/n8n-ci.yml
  • .github/workflows/n8n-publish.yml

Comment on lines +3 to +10
on:
pull_request:
paths:
- 'n8n/**'
push:
branches: [main]
paths:
- 'n8n/**'
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

CI won't self-trigger on workflow file changes.

The n8n/** path filter excludes .github/workflows/n8n-ci.yml itself. A PR that only edits this workflow file won't run the CI job, so workflow changes can't be validated automatically.

Consider adding the workflow path to the trigger:

🔧 Proposed fix
 on:
   pull_request:
     paths:
       - 'n8n/**'
+      - '.github/workflows/n8n-ci.yml'
   push:
     branches: [main]
     paths:
       - 'n8n/**'
+      - '.github/workflows/n8n-ci.yml'
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
on:
pull_request:
paths:
- 'n8n/**'
push:
branches: [main]
paths:
- 'n8n/**'
on:
pull_request:
paths:
- 'n8n/**'
- '.github/workflows/n8n-ci.yml'
push:
branches: [main]
paths:
- 'n8n/**'
- '.github/workflows/n8n-ci.yml'
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/n8n-ci.yml around lines 3 - 10, The workflow's on:
pull_request and push path filters only include 'n8n/**', which excludes the
workflow file itself so CI won't run when n8n-ci.yml is modified; update the on:
block (the pull_request and push -> paths entries) to also include the workflow
file (n8n-ci.yml) so changes to this workflow will trigger the job—modify the
paths arrays under the on: section to add the workflow filename alongside
'n8n/**'.

on:
release:
types: [published]
workflow_dispatch:
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

workflow_dispatch from a branch is silently skipped by the tag guard.

When manually dispatched from a branch (e.g., main), github.ref resolves to refs/heads/main, causing the startsWith(github.ref, 'refs/tags/n8n-') guard to evaluate to false. The job is silently skipped — no error, no publish. Manual dispatch only works when the workflow is triggered from the tag ref directly (via the GitHub UI "Run workflow" drop-down with the tag selected).

This is subtle enough to confuse operators expecting a manual publish to "just work" from the default branch. Consider either documenting this constraint or restructuring the guard:

🔧 Option: make workflow_dispatch always publish (bypass guard)
-    if: startsWith(github.ref, 'refs/tags/n8n-')
+    if: github.event_name == 'workflow_dispatch' || startsWith(github.ref, 'refs/tags/n8n-')

Also applies to: 11-11

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In @.github/workflows/n8n-publish.yml at line 6, The manual-dispatch guard
silently skips publishes because workflow_dispatch sets github.ref to a branch
(refs/heads/...), so change the condition that currently uses
startsWith(github.ref, 'refs/tags/n8n-') to allow workflow_dispatch to bypass it
by OR-ing with github.event_name == 'workflow_dispatch' (or explicitly check
github.event.action if you use a custom dispatch payload); update the job
condition(s) referencing startsWith(github.ref, 'refs/tags/n8n-') (and the
duplicate at the second occurrence) so manual runs from branches will proceed
instead of being silently skipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant