Skip to content

feat: n8n workflow JSON import at deploy time#237

Open
wonderwomancode wants to merge 1 commit into
mainfrom
feat/issue-64-n8n-workflow-import
Open

feat: n8n workflow JSON import at deploy time#237
wonderwomancode wants to merge 1 commit into
mainfrom
feat/issue-64-n8n-workflow-import

Conversation

@wonderwomancode

Copy link
Copy Markdown
Contributor

Summary

  • Adds workflowJson Json? field to the Service Prisma model (migration included)
  • Updates n8n template definition with a startCommand wrapper that decodes N8N_IMPORT_WORKFLOW_B64 env var, runs n8n import:workflow --input=/tmp/wf.json, then exec n8n start. No behaviour change when env var is absent.
  • Adds workflowJson: JSON field to DeployFromTemplateInput and DeployToAkashInput GraphQL types
  • deployFromTemplate resolver: stores workflowJson on the service and creates a N8N_IMPORT_WORKFLOW_B64 ServiceEnvVar (base64-encoded JSON) when the template is n8n
  • deployToAkash resolver: upserts N8N_IMPORT_WORKFLOW_B64 when workflowJson is supplied at (re)deploy time — the existing injectPersistedEnvVars pipeline merges it into the SDL env block automatically

Test plan

  • All 847 existing tests pass (pnpm test)
  • TypeScript build passes (pnpm build)
  • Deploy n8n template without workflowJson — container starts normally, no import step
  • Deploy n8n template with a valid workflow JSON — container imports the workflow and starts

Part of https://github.com/alternatefutures/web-app.alternatefutures.ai/issues/64

🤖 Generated with Claude Code

- Add workflowJson Json? field to Service model (migration included)
- Add startCommand to n8n template: decodes N8N_IMPORT_WORKFLOW_B64 env
  var and runs `n8n import:workflow` before `n8n start`; no-op when var
  is absent so existing deployments are unaffected
- Add workflowJson: JSON field to DeployFromTemplateInput and
  DeployToAkashInput GraphQL types
- deployFromTemplate resolver: persist workflowJson on service and
  create N8N_IMPORT_WORKFLOW_B64 ServiceEnvVar (base64-encoded)
- deployToAkash resolver: upsert N8N_IMPORT_WORKFLOW_B64 ServiceEnvVar
  when workflowJson is supplied at (re)deploy time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@claude

claude Bot commented Apr 28, 2026

Copy link
Copy Markdown

Claude encountered an error —— View job


I'll analyze this and get back to you.

@wonderwomancode

Copy link
Copy Markdown
Contributor Author

Quinn QA Review

Verdict: REQUEST CHANGES

⚠️ GitHub blocked a formal review submission (can't request changes on your own PR). This comment carries the same gate status — Senku and Lain should not proceed until the blockers below are addressed.


Test coverage findings

Blocker: zero new tests for all new code paths.

The PR description claims "All 847 existing tests pass" — confirmed, the suite is green. But the 847 tests cover none of the new behaviour. grep -r 'n8n\|workflowJson\|N8N_IMPORT' across every *.test.ts returns no matches.

Missing coverage:

Path What needs a test
deployFromTemplate (n8n + workflowJson) N8N_IMPORT_WORKFLOW_B64 env var created; base64 value round-trips correctly
deployFromTemplate (non-n8n + workflowJson) env var not created; workflowJson still persisted on Service row
deployFromTemplate (n8n, workflowJson omitted) no env var; workflowJson: null; existing path unaffected
deployToAkash (n8n + workflowJson) env var upserted; service record updated
deployToAkash (non-n8n + workflowJson) env var not created
deployToAkash (n8n, no workflowJson) nothing touched; existing path unaffected
n8n startCommand shell import-then-start and no-op (env var absent) paths

templates.test.ts and mutation.test.ts already use Prisma mocks + vitest — adding these is straightforward.


Regression risks

Low overall, but one area to verify:

  1. startCommand added to n8n template — existing n8n deployments without N8N_IMPORT_WORKFLOW_B64 will hit the new wrapper on their next redeploy. The [ -n "$N8N_IMPORT_WORKFLOW_B64" ] guard is correct and exec n8n start always fires, so behaviorally safe. A unit test on the SDL output for the "env var absent" path would confirm this.

  2. workflowJson persisted for all templateIds (templates.ts:404) but the env var is only injected for n8n. A client sending workflowJson with templateId: 'redis' silently stores it with no effect. Not a regression, but a confusing asymmetry worth a comment at that call site.

  3. deployToAkash: env var + service updates happen before billing/policy validation (lines 331–345 before line 347). A deployment rejected by billing leaves a mutated Service row and env var. The upsert makes this idempotent on retry, but workflowJson on the row could reflect a never-completed deploy.


Code quality and maintainability

Clean code overall. Minor notes:

  • 'n8n' string literal used in two separate resolver files (akash.ts:331, templates.ts:425). Should be a shared constant to guard against drift.
  • JSON.parse(JSON.stringify(input.workflowJson)) used in both resolvers is a harmless but unnecessary deep-clone — Prisma accepts JSONB input directly.
  • startCommand shell fragment is correctly written: printf '%s' avoids echo escape issues, variable is quoted in the test condition, exec always fires regardless of import subshell exit.

Security implications (flagging for Lain's deeper review)

  1. N8N_IMPORT_WORKFLOW_B64 stored as secret: false — n8n workflows routinely embed API keys, webhook tokens, and credentials. This blob appears in plaintext in UI env-var lists and any env-var export path. Consider secret: true, or document explicitly why non-secret is the deliberate choice.

  2. No input size limit on workflowJson — GraphQL server applies depth/complexity limits but no request body size cap (confirmed in src/index.ts). A large workflow JSON passes straight to a JSONB column. Consider a resolver-level size guard (e.g. 512 KB stringified).


Blockers

  1. No test coverage for any new code path. Need at minimum: (a) deployFromTemplate n8n+workflowJson happy path, (b) non-n8n workflowJson is silently ignored, (c) deployToAkash upsert path, (d) existing n8n paths unaffected.

Suggested follow-ups (non-blocking)

  • Extract 'n8n' templateId to a shared constant
  • Add comment explaining workflowJson-persisted-for-all / env-var-n8n-only asymmetry
  • Consider secret: true for N8N_IMPORT_WORKFLOW_B64
  • Add max-size guard on workflowJson input

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.

2 participants