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

# GitOps with GitHub Actions

> Automate Kodexa metadata deployments with kdx-sync-action, a GitHub Action providing zero-configuration GitOps workflows for sync, validation, and rollout.

Automate your Kodexa metadata deployments with **kdx-sync-action** - a GitHub Action that makes GitOps workflows simple, secure, and reliable.

<Info>
  **GitHub Action Repository**: [kodexa-ai/kdx-sync-action](https://github.com/kodexa-ai/kdx-sync-action)

  ```yaml theme={null}
  - uses: kodexa-ai/kdx-sync-action@v2
  ```
</Info>

<Note>
  **Philosophy**: Branch determines deployment. One way to do it. Zero knobs, just config.
</Note>

## Quick Start

Deploy to Kodexa in 4 simple steps:

### 1. Define Branch and Tag Mappings

Create `sync-config.yaml` in your repository root:

```yaml theme={null}
metadata_dir: kodexa-metadata

# Branch determines deployment
branch_mappings:
  - pattern: "main"
    target: production
    environment: prod

  - pattern: "staging"
    target: staging
    environment: staging

  - pattern: "feature/*"
    target: development
    environment: dev

# Tag-based deployments (NEW in v0.5.0)
tag_mappings:
  - pattern: "v*.*.*"        # Semantic version tags
    target: production
    environment: prod

  - pattern: "rc-*"          # Release candidates
    target: staging
    environment: staging

# Environments define API endpoints
environments:
  prod:
    url: https://platform.kodexa-enterprise.com
    api_key_from_env: KODEXA_PROD_API_KEY

  staging:
    url: https://staging.kodexa-enterprise.com
    api_key_from_env: KODEXA_STAGING_API_KEY

  dev:
    url: https://dev.kodexa-enterprise.com
    api_key_from_env: KODEXA_DEV_API_KEY

# Targets define what gets deployed
targets:
  production:
    manifests:
      - organizations/acme-corp/manifest.yaml
      - organizations/acme-corp/modules/*/manifest.yaml

  staging:
    manifests:
      - organizations/acme-corp/manifest.yaml

  development:
    manifests:
      - organizations/acme-corp/manifest.yaml
```

### 2. Add Secrets

In GitHub repository settings → Secrets and variables → Actions:

* `KODEXA_PROD_API_KEY`
* `KODEXA_STAGING_API_KEY`
* `KODEXA_DEV_API_KEY`

<Tip>
  Use GitHub environments to add protection rules like required approvals for production deployments.
</Tip>

### 3. Create Workflow

Create `.github/workflows/deploy.yml`:

```yaml theme={null}
name: Deploy

on:
  push:
    branches: [main, staging, 'feature/**']
    tags:              # NEW: Tag-based deployments
      - 'v*.*.*'
      - 'rc-*'

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

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
          KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
```

### 4. Push and Deploy

```bash theme={null}
git add .
git commit -m "Configure automated deployments"
git push origin main
```

**Done!**

* Push to `main` → production
* Push to `feature/new-thing` → dev
* Create tag `v1.0.0` → production
* Branch or tag determines deployment automatically

## Understanding the Action

The kdx-sync-action is a composite GitHub Action that:

1. **Detects your environment** (OS and architecture)
2. **Downloads kdx CLI** (latest or pinned version)
3. **Caches the binary** (faster subsequent runs)
4. **Auto-discovers configuration** (sync-config.yaml, metadata directory)
5. **Runs deployment** (kdx sync deploy with appropriate flags)
6. **Parses results** (extracts statistics and sets outputs)

**You don't need to**:

* Install kdx CLI manually
* Handle OS/architecture detection
* Manage binary caching
* Parse deployment output

**The action handles all of this automatically.**

## Action Inputs

All inputs are optional:

| Input              | Description                        | Required | Default         |
| ------------------ | ---------------------------------- | -------- | --------------- |
| `sync-config`      | Path to sync-config.yaml           | No       | Auto-discovered |
| `metadata-dir`     | Metadata directory override        | No       | Auto-discovered |
| `dry-run`          | Preview only (`true`/`false`)      | No       | `false`         |
| `kdx-version`      | kdx-cli version to use             | No       | `latest`        |
| `threads`          | Number of parallel threads         | No       | `8`             |
| `filter`           | Resource filter pattern            | No       | -               |
| `branch`           | Override branch detection          | No       | -               |
| `tag`              | Override with tag mapping          | No       | -               |
| `slack-channel-id` | Slack channel ID for notifications | No       | -               |
| `slack-token`      | Slack Bot Token for posting        | No       | -               |
| `annotate-summary` | Add summary to GitHub job          | No       | `false`         |

### Example with Inputs

```yaml theme={null}
- uses: kodexa-ai/kdx-sync-action@v2
  with:
    sync-config: config/sync.yaml
    metadata-dir: resources
    kdx-version: v0.5.0
    threads: 8
  env:
    KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

## Action Outputs

The action provides deployment statistics:

| Output              | Description                 |
| ------------------- | --------------------------- |
| `targets-deployed`  | Number of targets deployed  |
| `resources-created` | Resources created           |
| `resources-updated` | Resources updated           |
| `resources-skipped` | Resources unchanged         |
| `json-report`       | JSON deployment report data |
| `json-report-path`  | Path to JSON report file    |

### Using Outputs

```yaml theme={null}
- id: deploy
  uses: kodexa-ai/kdx-sync-action@v2
  env:
    KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}

- name: Show deployment summary
  run: |
    echo "Targets: ${{ steps.deploy.outputs.targets-deployed }}"
    echo "Created: ${{ steps.deploy.outputs.resources-created }}"
    echo "Updated: ${{ steps.deploy.outputs.resources-updated }}"
    echo "Skipped: ${{ steps.deploy.outputs.resources-skipped }}"
```

## Complete Workflow Examples

### Multi-Environment Deployment

The standard pattern - branch determines everything:

```yaml theme={null}
name: Deploy to Multiple Environments

on:
  push:
    branches: [main, staging, develop, 'feature/**']

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

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
          KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
```

With `sync-config.yaml` branch mappings:

```yaml theme={null}
branch_mappings:
  - pattern: "main"
    target: production
    environment: prod

  - pattern: "staging"
    target: staging
    environment: staging

  - pattern: "develop"
    target: development
    environment: dev

  - pattern: "feature/*"
    target: development
    environment: dev
```

<Note>
  No logic in the workflow! All routing is handled by sync-config.yaml.
</Note>

### Pull Request Validation with Preview

Validate changes and comment on PRs:

```yaml theme={null}
name: Validate PR

on:
  pull_request:
    paths:
      - 'kodexa-metadata/**'
      - 'sync-config.yaml'

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

      - id: preview
        uses: kodexa-ai/kdx-sync-action@v2
        with:
          dry-run: true
        env:
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}

      - uses: actions/github-script@v7
        with:
          script: |
            github.rest.issues.createComment({
              issue_number: context.issue.number,
              owner: context.repo.owner,
              repo: context.repo.repo,
              body: `## 🧪 Deployment Preview

              **Targets**: ${{ steps.preview.outputs.targets-deployed }}
              **Create**: ${{ steps.preview.outputs.resources-created }}
              **Update**: ${{ steps.preview.outputs.resources-updated }}
              **Skip**: ${{ steps.preview.outputs.resources-skipped }}

              ✅ Changes validated. Safe to merge.`
            });
```

### Production with Required Approval

Require manual approval before production deployment:

```yaml theme={null}
name: Production Deployment

on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: production  # Requires approval in Settings → Environments
    steps:
      - uses: actions/checkout@v4

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

**Setup required approvals**:

1. Go to Settings → Environments
2. Create "production" environment
3. Add required reviewers
4. Optional: Add wait timer

### Multi-Target Deployment

Deploy to multiple organizations:

```yaml theme={null}
# sync-config.yaml
branch_mappings:
  - pattern: "main"
    targets:
      - name: org-a-prod
        environment: prod
      - name: org-b-prod
        environment: prod

targets:
  org-a-prod:
    manifests: [organizations/org-a/manifest.yaml]
  org-b-prod:
    manifests: [organizations/org-b/manifest.yaml]
```

```yaml theme={null}
# .github/workflows/deploy.yml
name: Multi-Organization Deploy

on:
  push:
    branches: [main]

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

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

The action automatically deploys to both organizations based on branch mapping.

### Tag-Based Release Workflow

<Note>
  **NEW in kdx CLI v0.5.0**: Deploy using git tags for release-driven workflows.
</Note>

Deploy production releases using semantic version tags:

```yaml theme={null}
# sync-config.yaml
tag_mappings:
  # Production releases (v1.0.0, v2.1.3)
  - pattern: "v*.*.*"
    target: production
    environment: prod

  # Release candidates (v1.0.0-rc1, v2.0.0-beta)
  - pattern: "v*-*"
    target: staging
    environment: staging

  # Preview/demo tags
  - pattern: "preview/*"
    target: development
    environment: dev
```

```yaml theme={null}
# .github/workflows/deploy.yml
name: Release Deployment

on:
  push:
    tags:
      - 'v*.*.*'
      - 'v*-*'
      - 'preview/**'

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

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
          KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
```

**Release workflow**:

```bash theme={null}
# 1. Create release candidate
git tag v1.5.0-rc1
git push --tags          # Deploys to staging

# 2. After testing, create production release
git tag v1.5.0
git push --tags          # Deploys to production
```

**Benefits**:

* Immutable deployment references (tags don't move like branches)
* Clear release history in git
* Rollback by creating tag from previous commit
* Integration with GitHub Releases

### Manual Deployment Override

<Note>
  **NEW in kdx CLI v0.5.0**: Manual control with `--branch` and `--tag` flags
</Note>

Override automatic git detection for explicit deployment control:

```yaml theme={null}
# .github/workflows/manual-deploy.yml
name: Manual Deploy

on:
  workflow_dispatch:
    inputs:
      deployment-type:
        description: 'Deployment reference type'
        required: true
        type: choice
        options:
          - branch
          - tag
      reference:
        description: 'Branch or tag name'
        required: true
        type: string
      environment:
        description: 'Target environment'
        required: true
        type: choice
        options:
          - development
          - staging
          - production

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment }}
    steps:
      - uses: actions/checkout@v4

      - name: Deploy
        run: |
          if [[ "${{ github.event.inputs.deployment-type }}" == "branch" ]]; then
            kdx sync deploy --branch "${{ github.event.inputs.reference }}"
          else
            kdx sync deploy --tag "${{ github.event.inputs.reference }}"
          fi
        env:
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
          KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

**Use cases**:

* Manual deployments without git operations
* Testing deployment mappings
* Rollback to specific version
* Deploying from CI/CD without checkout

### Scheduled Synchronization

Keep environments synchronized on a schedule:

```yaml theme={null}
name: Scheduled Sync

on:
  schedule:
    - cron: '0 2 * * *'  # Daily at 2 AM UTC
  workflow_dispatch:     # Allow manual triggers

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

      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}

      - name: Notify on failure
        if: failure()
        run: |
          echo "Scheduled sync failed at $(date)"
          # Add notification logic (Slack, email, etc.)
```

### Built-in Slack Notifications

Send rich deployment summaries to Slack automatically:

```yaml theme={null}
name: Deploy with Slack

on:
  push:
    branches: [main]

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

      - uses: kodexa-ai/kdx-sync-action@v2
        with:
          slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
          slack-token: ${{ secrets.SLACK_BOT_TOKEN }}
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

The Slack message includes:

* 🚀 Deployment status (or 🔍 for dry runs)
* Repository and branch information
* Resource counts (created, updated, unchanged)
* Direct link to the GitHub Actions run

**Slack Setup**:

1. Create a Slack App at [https://api.slack.com/apps](https://api.slack.com/apps)
2. Add `chat:write` OAuth scope
3. Install to your workspace
4. Copy Bot Token (`xoxb-...`) to `SLACK_BOT_TOKEN` secret
5. Get channel ID (right-click channel → Copy link → extract ID)

### GitHub Job Summary

Add a deployment summary directly to the workflow run:

```yaml theme={null}
name: Deploy with Summary

on:
  push:
    branches: [main]

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

      - uses: kodexa-ai/kdx-sync-action@v2
        with:
          annotate-summary: true
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

The summary appears in the "Summary" tab and includes:

* Resource counts (created, updated, unchanged)
* Repository, branch, commit, and actor details
* Environment breakdown (when available)

### Full-Featured Deployment

Combine all notification options:

```yaml theme={null}
name: Deploy with All Features

on:
  push:
    branches: [main]

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

      - id: deploy
        uses: kodexa-ai/kdx-sync-action@v2
        with:
          threads: 8
          annotate-summary: true
          slack-channel-id: ${{ secrets.SLACK_CHANNEL_ID }}
          slack-token: ${{ secrets.SLACK_BOT_TOKEN }}
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}

      - name: Upload JSON Report
        uses: actions/upload-artifact@v4
        with:
          name: deployment-report
          path: ${{ steps.deploy.outputs.json-report-path }}
```

### Tag-Based Deployment

Deploy based on git tags instead of branches:

```yaml theme={null}
name: Deploy on Tag

on:
  push:
    tags: ['v*']

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

      - uses: kodexa-ai/kdx-sync-action@v2
        with:
          tag: ${{ github.ref_name }}
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

With `tag_mappings` in sync-config.yaml:

```yaml theme={null}
tag_mappings:
  - pattern: "v*"
    target: production
    environment: prod

  - pattern: "rc-*"
    target: staging
    environment: staging
```

### Manual Deployment with Parameters

Manual trigger with workflow inputs:

```yaml theme={null}
name: Manual Deploy

on:
  workflow_dispatch:
    inputs:
      environment:
        description: 'Target environment'
        required: true
        type: choice
        options:
          - development
          - staging
          - production
      dry-run:
        description: 'Preview only'
        type: boolean
        default: false

jobs:
  deploy:
    runs-on: ubuntu-latest
    environment: ${{ github.event.inputs.environment }}
    steps:
      - uses: actions/checkout@v4

      - id: deploy
        uses: kodexa-ai/kdx-sync-action@v2
        with:
          dry-run: ${{ github.event.inputs.dry-run }}
        env:
          KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
          KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}

      - name: Deployment summary
        run: |
          echo "## Deployment Summary" >> $GITHUB_STEP_SUMMARY
          echo "Environment: ${{ github.event.inputs.environment }}" >> $GITHUB_STEP_SUMMARY
          echo "Mode: ${{ github.event.inputs.dry-run == 'true' && 'Preview' || 'Live' }}" >> $GITHUB_STEP_SUMMARY
          echo "Targets: ${{ steps.deploy.outputs.targets-deployed }}" >> $GITHUB_STEP_SUMMARY
          echo "Created: ${{ steps.deploy.outputs.resources-created }}" >> $GITHUB_STEP_SUMMARY
          echo "Updated: ${{ steps.deploy.outputs.resources-updated }}" >> $GITHUB_STEP_SUMMARY
```

## Migration from v1 to v2

### What Changed

**v1** (old): Manual environment logic in workflow

```yaml theme={null}
# Old - complex workflow with manual logic
- name: Determine environment
  run: |
    if [[ "${{ github.ref }}" == "refs/heads/main" ]]; then
      echo "url=${{ secrets.PROD_URL }}" >> $GITHUB_ENV
      echo "token=${{ secrets.PROD_TOKEN }}" >> $GITHUB_ENV
    elif [[ "${{ github.ref }}" == "refs/heads/staging" ]]; then
      echo "url=${{ secrets.STAGING_URL }}" >> $GITHUB_ENV
      echo "token=${{ secrets.STAGING_TOKEN }}" >> $GITHUB_ENV
    fi

- uses: kodexa-ai/kdx-sync-action@v1
  with:
    kodexa-url: ${{ env.url }}
    kodexa-token: ${{ env.token }}
```

**v2** (new): Branch mappings in configuration

```yaml theme={null}
# New - simple workflow, logic in sync-config.yaml
- uses: kodexa-ai/kdx-sync-action@v2
  env:
    KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
    KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
```

### Migration Steps

<Steps>
  <Step title="Move mappings to sync-config.yaml">
    Create branch mappings in your configuration:

    ```yaml theme={null}
    branch_mappings:
      - pattern: "main"
        target: production
        environment: prod

      - pattern: "staging"
        target: staging
        environment: staging
    ```
  </Step>

  <Step title="Add environments to config">
    Define environments with API key references:

    ```yaml theme={null}
    environments:
      prod:
        url: https://platform.kodexa-enterprise.com
        api_key_from_env: KODEXA_PROD_API_KEY

      staging:
        url: https://staging.kodexa-enterprise.com
        api_key_from_env: KODEXA_STAGING_API_KEY
    ```
  </Step>

  <Step title="Simplify workflow">
    Replace complex workflow logic:

    ```yaml theme={null}
    # Remove all environment detection logic
    # Replace with simple:
    - uses: kodexa-ai/kdx-sync-action@v2
      env:
        KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
        KODEXA_STAGING_API_KEY: ${{ secrets.KODEXA_STAGING_API_KEY }}
    ```
  </Step>

  <Step title="Update secrets">
    Replace old secret names with new format:

    * `PROD_URL` + `PROD_TOKEN` → `KODEXA_PROD_API_KEY`
    * `STAGING_URL` + `STAGING_TOKEN` → `KODEXA_STAGING_API_KEY`
  </Step>
</Steps>

### Key Benefits of v2

* ✅ **Simpler workflows** - No manual environment detection
* ✅ **Configuration-driven** - Logic lives in sync-config.yaml
* ✅ **Less duplication** - One workflow handles all branches
* ✅ **Easier maintenance** - Change routing in config, not workflow
* ✅ **Auto-discovery** - Finds sync-config.yaml automatically

## Security Best Practices

### 1. Use GitHub Environment Secrets

Store API keys in environment-specific secrets:

```yaml theme={null}
jobs:
  deploy:
    environment: production  # Links to environment in repo settings
    steps:
      - uses: kodexa-ai/kdx-sync-action@v2
        env:
          KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

**Benefits**:

* Environment-specific secrets
* Required approval rules
* Wait timers
* Deployment visibility
* Complete audit trails

### 2. Never Hardcode Credentials

```yaml theme={null}
# ✅ Correct - reference secrets
env:
  KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}

# ❌ Never do this
env:
  KODEXA_PROD_API_KEY: "sk-abc123..."
```

### 3. Require Approvals for Production

Configure environment protection rules:

1. Settings → Environments
2. Select "production"
3. Enable "Required reviewers"
4. Add team members
5. Optional: Add wait timer

### 4. Use Branch Protection

Protect critical branches:

1. Settings → Branches
2. Add protection rule for `main`
3. Require pull request reviews
4. Require status checks to pass
5. Require branch to be up to date

### 5. Limit Workflow Permissions

Use minimal necessary permissions:

```yaml theme={null}
permissions:
  contents: read  # Read repository contents
  pull-requests: write  # Comment on PRs (for validation workflow)
```

### 6. Validate Before Deploying

Always use dry-run on PRs:

```yaml theme={null}
on: pull_request

- uses: kodexa-ai/kdx-sync-action@v2
  with:
    dry-run: true
```

## Development Workflow

### Recommended Git Flow

```mermaid theme={null}
graph LR
    A[develop] --> B[feature/new-taxonomy]
    B --> C[Pull Request]
    C --> D{Dry-run validates}
    D -->|Pass| E[Merge to develop]
    E --> F[Auto-deploy to dev]
    F --> G[Test]
    G --> H[Merge to staging]
    H --> I[Auto-deploy to staging]
    I --> J[UAT]
    J --> K[Merge to main]
    K --> L[Auto-deploy to production]
```

### Step-by-Step Process

<Steps>
  <Step title="Create feature branch">
    ```bash theme={null}
    git checkout -b feature/add-new-taxonomy
    ```
  </Step>

  <Step title="Make changes">
    ```bash theme={null}
    # Add or modify resources
    vim kodexa-metadata/data-definitions/new-taxonomy.yaml

    # Update manifest if needed
    vim manifests/main.yaml
    ```
  </Step>

  <Step title="Test locally">
    ```bash theme={null}
    # Set environment variables
    export KODEXA_DEV_API_KEY="your-dev-key"

    # Preview changes
    kdx sync deploy --dry-run
    ```
  </Step>

  <Step title="Commit and push">
    ```bash theme={null}
    git add .
    git commit -m "feat: add new document taxonomy"
    git push origin feature/add-new-taxonomy
    ```
  </Step>

  <Step title="Open pull request">
    * GitHub automatically runs dry-run validation
    * Review deployment preview in PR comments
    * Request team review
  </Step>

  <Step title="Merge and deploy">
    * After approval, merge PR
    * GitHub Actions automatically deploys based on branch
    * Monitor workflow logs for results
  </Step>
</Steps>

## Advanced: Using Manual kdx CLI

<Note>
  For most GitHub Actions use cases, use kdx-sync-action. Manual CLI is for local development and advanced debugging.
</Note>

### When to Use Manual CLI

* **Local development** - Testing changes before committing
* **Advanced debugging** - Need detailed control and output
* **Custom CI systems** - Not using GitHub Actions
* **One-off operations** - Manual syncs or migrations

### Manual Installation in Workflows

If you need to use kdx CLI directly:

```yaml theme={null}
steps:
  - uses: actions/checkout@v4

  - name: Install KDX CLI
    run: |
      # Download latest release
      curl -sL https://github.com/kodexa-ai/kdx-cli-releases/releases/latest/download/kdx_linux_x86_64.tar.gz | tar xz
      sudo mv kdx /usr/local/bin/

  - name: Deploy
    env:
      KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
    run: |
      kdx sync deploy --confirm-all
```

**Note**: kdx-sync-action handles all of this automatically with caching and cross-platform support.

## Troubleshooting

### Binary Download Failed

**Issue**: "Failed to download kdx from ..."

**Solution**: Specify a specific version:

```yaml theme={null}
- uses: kodexa-ai/kdx-sync-action@v2
  with:
    kdx-version: "v0.1.20"
```

Check available releases at [kdx-cli-releases](https://github.com/kodexa-ai/kdx-cli-releases/releases).

### Branch Mapping Not Found

**Issue**: "No branch mapping found for branch 'feature/xyz'"

**Solution 1** - Add fallback mapping:

```yaml theme={null}
branch_mappings:
  - pattern: "*"  # Fallback for any branch
    target: development
    environment: dev
```

**Solution 2** - Use manual override in workflow:

```yaml theme={null}
- uses: kodexa-ai/kdx-sync-action@v2
  with:
    # Override auto-detection
    # (But this defeats the purpose of branch mappings)
  env:
    KODEXA_DEV_API_KEY: ${{ secrets.KODEXA_DEV_API_KEY }}
  # Then use: kdx sync deploy --target dev --env development
```

### Environment Variable Not Set

**Issue**: "Environment variable KODEXA\_PROD\_API\_KEY not set"

**Fix**: Ensure secret exists and is passed to action:

```yaml theme={null}
- uses: kodexa-ai/kdx-sync-action@v2
  env:
    KODEXA_PROD_API_KEY: ${{ secrets.KODEXA_PROD_API_KEY }}
```

**Verify secret**:

1. Settings → Secrets and variables → Actions
2. Confirm secret name matches exactly
3. Check environment restrictions if using GitHub environments

### Authentication Failed

**Issue**: "Authentication failed" or "Invalid API key"

**Solutions**:

1. **Verify secret value** - Regenerate API key if needed
2. **Check key permissions** - Ensure key has deployment access
3. **Test manually**:
   ```bash theme={null}
   curl -H "Authorization: Bearer YOUR_API_KEY" \
     https://platform.kodexa-enterprise.com/api/workspaces
   ```

### Deployment Validation Passed but Deployment Failed

**Issue**: Dry-run succeeds, but live deployment fails

**Common causes**:

* Resource dependencies don't exist in target environment
* Insufficient API key permissions
* Environment-specific differences

**Solution**: Review error details in workflow logs and check resource dependencies.

## Best Practices

### 1. Use Dry-Run on Pull Requests

Always validate before merging:

```yaml theme={null}
on: pull_request

- uses: kodexa-ai/kdx-sync-action@v2
  with:
    dry-run: true
```

### 2. Use GitHub Environments for Protection

Separate credentials and add approval rules:

```yaml theme={null}
jobs:
  deploy:
    environment: production  # Requires approval
```

### 3. Add Deployment Summaries

Make results visible in workflow summaries:

```yaml theme={null}
- id: deploy
  uses: kodexa-ai/kdx-sync-action@v2

- run: |
    echo "## Deployment" >> $GITHUB_STEP_SUMMARY
    echo "Targets: ${{ steps.deploy.outputs.targets-deployed }}" >> $GITHUB_STEP_SUMMARY
    echo "Created: ${{ steps.deploy.outputs.resources-created }}" >> $GITHUB_STEP_SUMMARY
```

### 4. Monitor Workflows

Set up notifications for failures:

```yaml theme={null}
- name: Notify on failure
  if: failure()
  # Add Slack/email notification
```

### 5. Document Your Configuration

Add comments to sync-config.yaml:

```yaml theme={null}
# Production deployment - requires approval
- pattern: "main"
  target: production
  environment: prod
```

### 6. Version Pin for Stability

Pin kdx-version for production workflows:

```yaml theme={null}
- uses: kodexa-ai/kdx-sync-action@v2
  with:
    kdx-version: "v0.1.20"  # Explicit version
```

### 7. Test Branch Mappings Locally

Before committing configuration:

```bash theme={null}
# See which branch mapping matches
git branch --show-current
kdx sync deploy --dry-run
```

## GitHub Action Repository Resources

The [kodexa-ai/kdx-sync-action](https://github.com/kodexa-ai/kdx-sync-action) repository contains additional resources:

* **[SETUP\_GUIDE.md](https://github.com/kodexa-ai/kdx-sync-action/blob/main/SETUP_GUIDE.md)** - Detailed setup instructions
* **[examples/](https://github.com/kodexa-ai/kdx-sync-action/tree/main/examples)** - Complete workflow templates for common scenarios
* **[action.yml](https://github.com/kodexa-ai/kdx-sync-action/blob/main/action.yml)** - Full action definition with all inputs/outputs

## Next Steps

<CardGroup cols={2}>
  <Card title="Sync Configuration" icon="gear" href="/guides/kdx-cli/sync/overview">
    Learn about sync-config.yaml structure and manifests
  </Card>

  <Card title="Resource Deployments" icon="layer-group" href="/guides/deployment/resource-deployments">
    Complete deployment strategies and patterns
  </Card>

  <Card title="KDX CLI" icon="terminal" href="/guides/kdx-cli/overview">
    Local CLI for development and testing
  </Card>

  <Card title="GitHub Action Repository" icon="github" href="https://github.com/kodexa-ai/kdx-sync-action">
    kdx-sync-action source and documentation
  </Card>
</CardGroup>
