diff --git a/.github/workflows/ci-gate.yml b/.github/workflows/ci-gate.yml index 01309a731..0fa20fe31 100644 --- a/.github/workflows/ci-gate.yml +++ b/.github/workflows/ci-gate.yml @@ -40,6 +40,8 @@ jobs: openclaw: ${{ steps.filter.outputs.openclaw }} opencode_plugin: ${{ steps.filter.outputs.opencode_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 }} steps: - uses: dorny/paths-filter@v3 @@ -79,6 +81,14 @@ jobs: - 'integrations/pi-agent-plugin/**' - '.github/workflows/pi-agent-plugin-checks.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/**/*.mdx' - 'docs/llms.txt' @@ -136,6 +146,20 @@ jobs: uses: ./.github/workflows/pi-agent-plugin-checks.yml 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: name: docs llms.txt needs: changes @@ -154,6 +178,8 @@ jobs: - openclaw - opencode-plugin - pi-agent-plugin + - n8n-nodes-mem0 + - zapier-mem0 - docs-llms-txt if: always() runs-on: ubuntu-latest diff --git a/.github/workflows/n8n-nodes-mem0-cd.yml b/.github/workflows/n8n-nodes-mem0-cd.yml new file mode 100644 index 000000000..772b4378f --- /dev/null +++ b/.github/workflows/n8n-nodes-mem0-cd.yml @@ -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 diff --git a/.github/workflows/n8n-nodes-mem0-checks.yml b/.github/workflows/n8n-nodes-mem0-checks.yml new file mode 100644 index 000000000..8229820f1 --- /dev/null +++ b/.github/workflows/n8n-nodes-mem0-checks.yml @@ -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) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5be797b7b..a2d474f56 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -45,6 +45,7 @@ jobs: openclaw-v*) workflow="openclaw-cd.yml" ;; opencode-v*) workflow="opencode-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" ;; *) echo "::error::Release tag '$TAG' does not match any known package prefix — nothing will be published. See the tag prefix table in AGENTS.md." diff --git a/.github/workflows/zapier-mem0-cd.yml b/.github/workflows/zapier-mem0-cd.yml new file mode 100644 index 000000000..1a3fca750 --- /dev/null +++ b/.github/workflows/zapier-mem0-cd.yml @@ -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 diff --git a/.github/workflows/zapier-mem0-checks.yml b/.github/workflows/zapier-mem0-checks.yml new file mode 100644 index 000000000..171ecdc48 --- /dev/null +++ b/.github/workflows/zapier-mem0-checks.yml @@ -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 diff --git a/AGENTS.md b/AGENTS.md index b10ac7b90..d81e2fb94 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -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`) | | 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`) | +| 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. - 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. - 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 -cd.yml --ref refs/tags/ -f 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. ### Utility Workflows diff --git a/integrations/zapier-mem0/test/mem0.test.js b/integrations/zapier-mem0/test/mem0.test.js index 0e9e305a5..14a0e0115 100644 --- a/integrations/zapier-mem0/test/mem0.test.js +++ b/integrations/zapier-mem0/test/mem0.test.js @@ -14,10 +14,11 @@ const authData = { const userId = `zapier-e2e-${Date.now()}`; -describe('Mem0 Zapier integration (E2E)', () => { - beforeAll(() => { - if (!authData.apiKey) throw new Error('MEM0_API_KEY env var is required for E2E tests'); - }); +// The E2E suite hits the live Mem0 API, so it only runs when MEM0_API_KEY is +// set (locally / with a secret). In CI without a key it is skipped, not failed. +const describeE2E = authData.apiKey ? describe : describe.skip; + +describeE2E('Mem0 Zapier integration (E2E)', () => { it('authentication.test succeeds', async () => { const res = await appTester(App.authentication.test, { authData });