ci(integrations): add CI/CD workflows for n8n + Zapier packages
Match the repo's per-integration CI/CD convention (vercel-ai / pi-agent pattern): - n8n-nodes-mem0-checks.yml (lint + build + dist verify) and n8n-nodes-mem0-cd.yml (npm publish --provenance via OIDC, dispatched by the release router on tag n8n-nodes-mem0-v*). - zapier-mem0-checks.yml (zapier validate) and zapier-mem0-cd.yml (manual zapier push; requires ZAPIER_DEPLOY_KEY). Zapier deploys to Zapier's platform, not npm, so it is not in the release router. - Wire both packages into ci-gate.yml (path filters + call jobs + gate). - Register the n8n tag prefix in release.yml and document it + the Zapier manual-deploy in AGENTS.md. - Skip the Zapier E2E suite when MEM0_API_KEY is absent so CI is green offline (it still runs locally with a key).
This commit is contained in:
@@ -40,6 +40,8 @@ jobs:
|
|||||||
openclaw: ${{ steps.filter.outputs.openclaw }}
|
openclaw: ${{ steps.filter.outputs.openclaw }}
|
||||||
opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }}
|
opencode_plugin: ${{ steps.filter.outputs.opencode_plugin }}
|
||||||
pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }}
|
pi_agent_plugin: ${{ steps.filter.outputs.pi_agent_plugin }}
|
||||||
|
n8n_nodes_mem0: ${{ steps.filter.outputs.n8n_nodes_mem0 }}
|
||||||
|
zapier_mem0: ${{ steps.filter.outputs.zapier_mem0 }}
|
||||||
docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }}
|
docs_llms_txt: ${{ steps.filter.outputs.docs_llms_txt }}
|
||||||
steps:
|
steps:
|
||||||
- uses: dorny/paths-filter@v3
|
- uses: dorny/paths-filter@v3
|
||||||
@@ -79,6 +81,14 @@ jobs:
|
|||||||
- 'integrations/pi-agent-plugin/**'
|
- 'integrations/pi-agent-plugin/**'
|
||||||
- '.github/workflows/pi-agent-plugin-checks.yml'
|
- '.github/workflows/pi-agent-plugin-checks.yml'
|
||||||
- '.github/workflows/ci-gate.yml'
|
- '.github/workflows/ci-gate.yml'
|
||||||
|
n8n_nodes_mem0:
|
||||||
|
- 'integrations/n8n-nodes-mem0/**'
|
||||||
|
- '.github/workflows/n8n-nodes-mem0-checks.yml'
|
||||||
|
- '.github/workflows/ci-gate.yml'
|
||||||
|
zapier_mem0:
|
||||||
|
- 'integrations/zapier-mem0/**'
|
||||||
|
- '.github/workflows/zapier-mem0-checks.yml'
|
||||||
|
- '.github/workflows/ci-gate.yml'
|
||||||
docs_llms_txt:
|
docs_llms_txt:
|
||||||
- 'docs/**/*.mdx'
|
- 'docs/**/*.mdx'
|
||||||
- 'docs/llms.txt'
|
- 'docs/llms.txt'
|
||||||
@@ -136,6 +146,20 @@ jobs:
|
|||||||
uses: ./.github/workflows/pi-agent-plugin-checks.yml
|
uses: ./.github/workflows/pi-agent-plugin-checks.yml
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
|
n8n-nodes-mem0:
|
||||||
|
name: n8n node
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.n8n_nodes_mem0 == 'true'
|
||||||
|
uses: ./.github/workflows/n8n-nodes-mem0-checks.yml
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
zapier-mem0:
|
||||||
|
name: Zapier app
|
||||||
|
needs: changes
|
||||||
|
if: needs.changes.outputs.zapier_mem0 == 'true'
|
||||||
|
uses: ./.github/workflows/zapier-mem0-checks.yml
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
docs-llms-txt:
|
docs-llms-txt:
|
||||||
name: docs llms.txt
|
name: docs llms.txt
|
||||||
needs: changes
|
needs: changes
|
||||||
@@ -154,6 +178,8 @@ jobs:
|
|||||||
- openclaw
|
- openclaw
|
||||||
- opencode-plugin
|
- opencode-plugin
|
||||||
- pi-agent-plugin
|
- pi-agent-plugin
|
||||||
|
- n8n-nodes-mem0
|
||||||
|
- zapier-mem0
|
||||||
- docs-llms-txt
|
- docs-llms-txt
|
||||||
if: always()
|
if: always()
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
name: Publish n8n-nodes-mem0 📦 to npm
|
||||||
|
|
||||||
|
# Dispatched by release.yml (Release Router) when a release tagged
|
||||||
|
# n8n-nodes-mem0-v* is published. Can also be dispatched manually to
|
||||||
|
# re-publish a tag.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
tag:
|
||||||
|
description: 'Release tag to build and publish (e.g. n8n-nodes-mem0-v0.1.0)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
prerelease:
|
||||||
|
description: 'Publish under the version preid dist-tag instead of latest'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-n-publish:
|
||||||
|
name: Build and publish n8n-nodes-mem0 📦 to npm
|
||||||
|
if: startsWith(inputs.tag, 'n8n-nodes-mem0-v')
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
id-token: write
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: integrations/n8n-nodes-mem0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
ref: ${{ inputs.tag }}
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 10
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '22'
|
||||||
|
registry-url: 'https://registry.npmjs.org'
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: integrations/n8n-nodes-mem0/pnpm-lock.yaml
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: pnpm run build
|
||||||
|
|
||||||
|
- name: Publish to npm
|
||||||
|
run: |
|
||||||
|
if [ "${{ inputs.prerelease }}" = "true" ]; then
|
||||||
|
PREID=$(node -p "require('./package.json').version.split('-')[1].split('.')[0]")
|
||||||
|
npx npm@latest publish --provenance --access public --tag "$PREID"
|
||||||
|
else
|
||||||
|
npx npm@latest publish --provenance --access public
|
||||||
|
fi
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
name: n8n-nodes-mem0 checks
|
||||||
|
|
||||||
|
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||||
|
# push-to-main and manual runs remain standalone.
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'integrations/n8n-nodes-mem0/**'
|
||||||
|
- '.github/workflows/n8n-nodes-mem0-checks.yml'
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: integrations/n8n-nodes-mem0/pnpm-lock.yaml
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: cd integrations/n8n-nodes-mem0 && pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Lint
|
||||||
|
run: cd integrations/n8n-nodes-mem0 && pnpm run lint
|
||||||
|
|
||||||
|
build:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: integrations/n8n-nodes-mem0/pnpm-lock.yaml
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: cd integrations/n8n-nodes-mem0 && pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Build
|
||||||
|
run: cd integrations/n8n-nodes-mem0 && pnpm run build
|
||||||
|
|
||||||
|
- name: Verify dist output exists
|
||||||
|
run: |
|
||||||
|
test -f integrations/n8n-nodes-mem0/dist/nodes/Mem0/Mem0.node.js || (echo "Build output missing: dist/nodes/Mem0/Mem0.node.js" && exit 1)
|
||||||
|
test -f integrations/n8n-nodes-mem0/dist/credentials/Mem0Api.credentials.js || (echo "Build output missing: dist/credentials/Mem0Api.credentials.js" && exit 1)
|
||||||
|
test -f integrations/n8n-nodes-mem0/dist/nodes/Mem0/mem0.svg || (echo "Build output missing: dist/nodes/Mem0/mem0.svg" && exit 1)
|
||||||
@@ -45,6 +45,7 @@ jobs:
|
|||||||
openclaw-v*) workflow="openclaw-cd.yml" ;;
|
openclaw-v*) workflow="openclaw-cd.yml" ;;
|
||||||
opencode-v*) workflow="opencode-plugin-cd.yml" ;;
|
opencode-v*) workflow="opencode-plugin-cd.yml" ;;
|
||||||
pi-agent-v*) workflow="pi-agent-plugin-cd.yml" ;;
|
pi-agent-v*) workflow="pi-agent-plugin-cd.yml" ;;
|
||||||
|
n8n-nodes-mem0-v*) workflow="n8n-nodes-mem0-cd.yml" ;;
|
||||||
v*) workflow="cd.yml" ;;
|
v*) workflow="cd.yml" ;;
|
||||||
*)
|
*)
|
||||||
echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md."
|
echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md."
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
name: Deploy zapier-mem0 to Zapier
|
||||||
|
|
||||||
|
# Zapier apps deploy to Zapier's own platform (not npm), so this is NOT wired
|
||||||
|
# into the npm release router (release.yml). It is manual workflow_dispatch
|
||||||
|
# only and requires the ZAPIER_DEPLOY_KEY repo secret.
|
||||||
|
#
|
||||||
|
# gh workflow run zapier-mem0-cd.yml --ref main
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push:
|
||||||
|
name: Push zapier-mem0 to Zapier
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
defaults:
|
||||||
|
run:
|
||||||
|
working-directory: integrations/zapier-mem0
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: integrations/zapier-mem0/pnpm-lock.yaml
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Push to Zapier
|
||||||
|
env:
|
||||||
|
ZAPIER_DEPLOY_KEY: ${{ secrets.ZAPIER_DEPLOY_KEY }}
|
||||||
|
run: npx zapier-platform-cli@19 push
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
name: zapier-mem0 checks
|
||||||
|
|
||||||
|
# On PRs this is invoked by ci-gate.yml (the single required check);
|
||||||
|
# push-to-main and manual runs remain standalone.
|
||||||
|
#
|
||||||
|
# CI runs `zapier validate` (offline schema + style checks). The end-to-end
|
||||||
|
# jest suite is skipped here because it hits the live Mem0 API — it runs
|
||||||
|
# locally with MEM0_API_KEY set (see the package README).
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
paths:
|
||||||
|
- 'integrations/zapier-mem0/**'
|
||||||
|
- '.github/workflows/zapier-mem0-checks.yml'
|
||||||
|
workflow_call:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
validate:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Install pnpm
|
||||||
|
uses: pnpm/action-setup@v4
|
||||||
|
with:
|
||||||
|
version: 9
|
||||||
|
|
||||||
|
- name: Setup Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 20
|
||||||
|
cache: 'pnpm'
|
||||||
|
cache-dependency-path: integrations/zapier-mem0/pnpm-lock.yaml
|
||||||
|
|
||||||
|
- name: Install dependencies
|
||||||
|
run: cd integrations/zapier-mem0 && pnpm install --frozen-lockfile
|
||||||
|
|
||||||
|
- name: Validate Zapier app definition
|
||||||
|
run: cd integrations/zapier-mem0 && npx zapier-platform-cli@19 validate
|
||||||
@@ -450,11 +450,13 @@ Publishing is routed through a single entry point: **`release.yml` (Release Rout
|
|||||||
| OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) |
|
| OpenClaw | `openclaw-cd.yml` | `openclaw-v*` | npm (`@mem0/openclaw-mem0`) |
|
||||||
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
|
| OpenCode Plugin | `opencode-plugin-cd.yml` | `opencode-v*` | npm (`@mem0/opencode-plugin`) |
|
||||||
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
|
| Pi Agent Plugin | `pi-agent-plugin-cd.yml` | `pi-agent-v*` | npm (`@mem0/pi-agent-plugin`) |
|
||||||
|
| n8n Node | `n8n-nodes-mem0-cd.yml` | `n8n-nodes-mem0-v*` | npm (`n8n-nodes-mem0`) |
|
||||||
|
|
||||||
- Package CD workflows are `workflow_dispatch`-only (inputs: `tag`, `prerelease`); they check out and build the given tag. Registry trusted-publisher settings stay pinned to each package's own workflow filename.
|
- Package CD workflows are `workflow_dispatch`-only (inputs: `tag`, `prerelease`); they check out and build the given tag. Registry trusted-publisher settings stay pinned to each package's own workflow filename.
|
||||||
- All publishing uses **OIDC trusted publishing** — no tokens or secrets required.
|
- All publishing uses **OIDC trusted publishing** — no tokens or secrets required.
|
||||||
- First publish of a new npm package must be done manually; OIDC works for subsequent versions.
|
- First publish of a new npm package must be done manually; OIDC works for subsequent versions.
|
||||||
- To re-publish a release (e.g. after a registry settings fix), do **not** delete/recreate the GitHub release — manually dispatch the package workflow instead: `gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>`.
|
- To re-publish a release (e.g. after a registry settings fix), do **not** delete/recreate the GitHub release — manually dispatch the package workflow instead: `gh workflow run <package>-cd.yml --ref refs/tags/<tag> -f tag=<tag>`.
|
||||||
|
- The **Zapier app** (`integrations/zapier-mem0`) deploys to Zapier's own platform, not npm, so it is **not** in the release router. Deploy it manually: `gh workflow run zapier-mem0-cd.yml --ref main` (requires the `ZAPIER_DEPLOY_KEY` secret).
|
||||||
- When adding a new package: add its CD workflow (`workflow_dispatch` with `tag`/`prerelease` inputs), then register its tag prefix in the `case` block in `release.yml`. Keep the bare `v*` arm last.
|
- When adding a new package: add its CD workflow (`workflow_dispatch` with `tag`/`prerelease` inputs), then register its tag prefix in the `case` block in `release.yml`. Keep the bare `v*` arm last.
|
||||||
|
|
||||||
### Utility Workflows
|
### Utility Workflows
|
||||||
|
|||||||
@@ -14,10 +14,11 @@ const authData = {
|
|||||||
|
|
||||||
const userId = `zapier-e2e-${Date.now()}`;
|
const userId = `zapier-e2e-${Date.now()}`;
|
||||||
|
|
||||||
describe('Mem0 Zapier integration (E2E)', () => {
|
// The E2E suite hits the live Mem0 API, so it only runs when MEM0_API_KEY is
|
||||||
beforeAll(() => {
|
// set (locally / with a secret). In CI without a key it is skipped, not failed.
|
||||||
if (!authData.apiKey) throw new Error('MEM0_API_KEY env var is required for E2E tests');
|
const describeE2E = authData.apiKey ? describe : describe.skip;
|
||||||
});
|
|
||||||
|
describeE2E('Mem0 Zapier integration (E2E)', () => {
|
||||||
|
|
||||||
it('authentication.test succeeds', async () => {
|
it('authentication.test succeeds', async () => {
|
||||||
const res = await appTester(App.authentication.test, { authData });
|
const res = await appTester(App.authentication.test, { authData });
|
||||||
|
|||||||
Reference in New Issue
Block a user