> ## Documentation Index
> Fetch the complete documentation index at: https://nango.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# CI/CD for Nango Functions

> How to integrate Nango Function deployments into your CI/CD pipeline.

CI/CD for Nango is about keeping your [Functions](https://nango.dev/docs/guides/functions/functions-guide.md) — sync functions, tools, webhook functions, and event functions — in sync with your application across environments.

The core principle: **deploy to Nango as part of the same pipeline step as your application**. Deploying them separately risks your app and your Functions going out of sync, which can cause subtle bugs that are hard to trace.

## Authentication

To deploy from CI, you need a scoped API key for each Nango environment.

1. **Create API keys**: In the Nango UI, go to **Environment Settings > API Keys** and create a key for each environment (e.g., `dev` and `prod`). For CI/CD pipelines, use a key scoped to `environment:deploy` only — see the [CI/CD Deploy profile](https://nango.dev/docs/reference/backend/http-api/api-keys.md#cicd-deploy).
2. **Store the keys**: Add them as secrets in your CI/CD provider. The Nango CLI reads them from these environment variables:
   * `NANGO_SECRET_KEY_DEV`
   * `NANGO_SECRET_KEY_PROD`

## Recommended pipeline

Treat Nango Functions like application code: validate on every PR, deploy to each environment in the same step as your application.

| Pipeline stage | What to do |
| - | - |
| **Pull request** | Run `nango compile` and `npm test` as required checks. Block merge on failure. |
| **Merge to main** | Deploy to your dev/staging Nango environment alongside your app. |
| **Release to production** | Deploy to your prod Nango environment in the same step as your app release. |

The Nango CLI `deploy` command targets a specific environment:

```bash theme={null}
nango deploy <environment>
```

If you don't specify an environment, it defaults to `dev`.

**If you don't have a staging environment**, wire the prod Nango deploy directly to your production release step — use a `workflow_dispatch` trigger or equivalent manual approval. This keeps production deploys intentional, and ensures they always happen through CI using the prod API key rather than from a local machine.

> [!NOTE]
>
> Add the `dist/` folder inside your `nango-integrations` directory to `.gitignore`. The CLI writes compiled JS artifacts there, and committing them creates noisy diffs and risks deploying stale bundles.

## Example: GitHub Actions

Two workflow files implement the pipeline above.

> [accordion] PR validation (.github/workflows/nango-validate.yml)
>
> ```yaml theme={null}
> name: Validate Nango Functions
>
> on:
>   pull_request:
>     branches:
>       - main
>
> jobs:
>   validate:
>     runs-on: ubuntu-latest
>
>     steps:
>       - name: Checkout code
>         uses: actions/checkout@v4
>
>       - name: Set up Node.js
>         uses: actions/setup-node@v4
>         with:
>           node-version: '22.22.2'
>
>       - name: Install dependencies
>         run: npm ci
>
>       - name: Compile
>         run: npx nango@latest compile --no-dependency-update
>
>       - name: Test
>         run: npm test
> ```

> [accordion] Deploy (.github/workflows/nango-deploy.yml)
>
> ```yaml theme={null}
> name: Deploy Nango Functions
>
> on:
>   # Manual trigger to deploy to a specific environment
>   workflow_dispatch:
>     inputs:
>       stage:
>         type: choice
>         description: 'Environment to deploy to'
>         required: true
>         default: 'dev'
>         options:
>           - dev
>           - prod
>       allowDestructive:
>         type: boolean
>         description: 'Allow destructive changes'
>         required: true
>         default: false
>
>   # Automatic deploy to dev on merge to main
>   push:
>     branches:
>       - main
>
> jobs:
>   deploy:
>     runs-on: ubuntu-latest
>     env:
>       NANGO_SECRET_KEY_DEV: ${{ secrets.NANGO_SECRET_KEY_DEV }}
>       NANGO_SECRET_KEY_PROD: ${{ secrets.NANGO_SECRET_KEY_PROD }}
>
>     steps:
>       - name: Checkout code
>         uses: actions/checkout@v4
>
>       - name: Set up Node.js
>         uses: actions/setup-node@v4
>         with:
>           node-version: '22.22.2'
>
>       - name: Install dependencies
>         run: npm ci
>
>       - name: Deploy to Nango
>         run: |
>           if [ "${{ github.event_name }}" == "workflow_dispatch" ]; then
>             stage="${{ inputs.stage }}"
>           else
>             stage="dev"
>           fi
>
>           secret_key_var="NANGO_SECRET_KEY_$(echo "$stage" | tr '[:lower:]' '[:upper:]')"
>           secret_key="${!secret_key_var}"
>
>           if [ -z "$secret_key" ]; then
>             echo "Error: ${secret_key_var} is not set"
>             exit 1
>           fi
>
>           destructive_flag=""
>           if [ "${{ github.event_name }}" == "workflow_dispatch" ] && [ "${{ inputs.allowDestructive }}" == "true" ]; then
>             destructive_flag="--allow-destructive"
>           fi
>
>           npx nango@latest deploy "$stage" --auto-confirm --no-dependency-update $destructive_flag
> ```

> [!WARNING]
>
> **Destructive Changes**
>
> Deleting a sync function with existing connections, removing a sync or tool record model, or deleting any other function requires confirmation.
>
> In CI, use both `--auto-confirm` and `--allow-destructive` to approve destructive changes. We recommend only doing this on a manual trigger, as shown above.

## Testing in CI

Run your test suite in CI before every deployment. Nango's testing framework uses dry runs and snapshot testing to validate your Functions without affecting live data:

```bash theme={null}
npm test
```

See the [Testing integrations guide](https://nango.dev/docs/guides/functions/testing.md) for details.

## Ephemeral preview environments (e.g. Vercel)

If you use ephemeral preview environments — such as Vercel preview deployments — as your staging layer, you'll run into a challenge: each preview has a unique URL, but Nango webhook URLs must be registered in advance and point to a stable destination.

> [!NOTE]
>
> Nango doesn't currently support creating environments programmatically. This is on the roadmap and will make ephemeral environment setups much cleaner when available.

For now, the simplest approach is to designate a fixed, long-lived Nango environment (e.g., `dev`) specifically for Nango-related changes, and use that consistently across preview deployments rather than trying to create a new Nango environment per preview.

If you need previews to receive live webhook events, a proxy server is the current workaround: register a stable URL in Nango, and have the proxy forward incoming webhooks to the correct preview URL.

## Dependency-safe CI and monorepos

When running Nango in CI or monorepos, you often want to avoid modifying `package.json` or running extra installs from within Nango commands. Use `--no-dependency-update` on CLI commands, or set `NANGO_CLI_DEPENDENCY_UPDATE=false` as an environment variable:

```bash theme={null}
npx nango@latest deploy dev --no-dependency-update
```

> [!WARNING]
>
> With `--no-dependency-update`, Nango will not install dependencies. Make sure your pipeline does so first (e.g. `npm ci`, `pnpm install --frozen-lockfile`, `yarn install --immutable`, or `bun install --frozen-lockfile`).

> [!NOTE]
>
> In CI environments, Nango automatically disables dependency updates to prevent modifying `package.json`. Passing `--no-dependency-update` explicitly silences the related warning.

## Related resources

* [Testing integrations](https://nango.dev/docs/guides/functions/testing.md) - A comprehensive guide to testing your Nango Functions.
* [API Keys reference](https://nango.dev/docs/reference/backend/http-api/api-keys.md) - Available scopes and advised profiles for CI/CD and other use cases.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.