CI/CD Integration

Run the dcupl CLI inside your pipeline to push workspace changes automatically on every merge. The pattern is the same on every platform: install the CLI, set credentials non-interactively from your CI secrets, then push. This page shows the core pattern and ready-to-copy configs for the major platforms.

The pattern

Two steps run in CI: configure credentials, then push.

# 1. Set credentials non-interactively from CI secrets
dcupl config set \
  --project-id "$DCUPL_PROJECT_ID" \
  --api-key "$DCUPL_API_KEY" \
  --yes

# 2. Mirror local files to the cloud, non-interactively
dcupl files push --strict --yes

--strict mirrors the source — including deletions — so the server matches your repository exactly. --yes skips the confirmation prompt, which has no TTY in CI.

--strict deletes on the server. Strict mode is a mirror: any file removed or renamed locally is deleted from the cloud version on the next push. On a clean main that's exactly what you want, but it means a bad checkout, a shallow clone, or a stray rm propagates the deletion to the cloud. Limit the blast radius with --path to scope the mirror to specific folders, and gate the job with validation (below). If you're not sure, drop --strict — a plain dcupl files push is additive and never deletes server files.

Never commit dcupl.secrets.json. Inject the API key from your CI provider's secrets at runtime via the --api-key flag or the DCUPL_API_KEY environment variable. Add dcupl.secrets.json and .dcupl/ to .gitignore.

For self-hosted Console, point the CLI at your instance with the DCUPL_CONSOLE_API_URL environment variable (or dcupl config set --console-api-url <url>).

Gate the push with validation

Optionally run dcupl validate first and fail the job before any files are uploaded. Remember that validate exits 0 even on failure — check the JSON report's top-level ok field, not the exit code (see Validating a Project):

ok=$(dcupl validate --json | jq -r '.ok')
if [ "$ok" != "true" ]; then
  echo "Validation failed — aborting push" && exit 1
fi
dcupl files push --strict --yes

Platform examples

.github/workflows/deploy.yml
name: Deploy to dcupl

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - run: npm install -g @dcupl/cli

      - name: Configure credentials
        run: |
          dcupl config set \
            --project-id "${{ secrets.DCUPL_PROJECT_ID }}" \
            --api-key "${{ secrets.DCUPL_API_KEY }}" \
            --yes

      - name: Push to dcupl
        run: dcupl files push --strict --yes
.gitlab-ci.yml
deploy:
  image: node:20
  rules:
    - if: $CI_COMMIT_BRANCH == "main"
  script:
    - npm install -g @dcupl/cli
    - >
      dcupl config set
      --project-id "$DCUPL_PROJECT_ID"
      --api-key "$DCUPL_API_KEY"
      --yes
    - dcupl files push --strict --yes

Define DCUPL_PROJECT_ID and DCUPL_API_KEY as masked CI/CD variables under Settings → CI/CD → Variables.

.circleci/config.yml
version: 2.1

jobs:
  deploy:
    docker:
      - image: cimg/node:20.19
    steps:
      - checkout
      - run: npm install -g @dcupl/cli
      - run:
          name: Configure credentials
          command: |
            dcupl config set \
              --project-id "$DCUPL_PROJECT_ID" \
              --api-key "$DCUPL_API_KEY" \
              --yes
      - run:
          name: Push to dcupl
          command: dcupl files push --strict --yes

workflows:
  deploy-on-main:
    jobs:
      - deploy:
          filters:
            branches:
              only: main

Set DCUPL_PROJECT_ID and DCUPL_API_KEY as project environment variables in the CircleCI dashboard.

Next Steps