---
title: "CI/CD Integration"
description: "Add compliance checks to your GitHub Actions workflow with the ComplyForm Action."
---

import { Aside, Tabs, TabItem } from '@astrojs/starlight/components';

Block non-compliant changes before they reach production.

## GitHub Action setup

Add the ComplyForm Action to your repository. The action installs the CLI and authenticates using your license key.

```yaml
# .github/workflows/compliance.yml
name: Compliance Check
on: [pull_request]

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

      - uses: complyform/complyform-action@v1
        with:
          version: latest
          license-key: ${{ secrets.COMPLYFORM_LICENSE_KEY }}
```

## Workflow patterns

<Tabs>
<TabItem label="PR Check">

Run assessment on every pull request and post results as a PR comment. Upload SARIF for GitHub Code Scanning integration.

```yaml
name: PR Compliance Check
on:
  pull_request:
    paths: ['**/*.tf']

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

      - uses: complyform/complyform-action@v1
        with:
          version: latest
          license-key: ${{ secrets.COMPLYFORM_LICENSE_KEY }}

      - name: Scan and assess
        run: |
          complyform scan --state=terraform.tfstate \
            --assess --frameworks=soc2 \
            --output=sarif --output-file=results.sarif

      - name: Upload SARIF
        uses: github/codeql-action/upload-sarif@v3
        with:
          sarif_file: results.sarif

      - name: Comment on PR
        run: |
          complyform assess --frameworks=soc2 --output=markdown \
            >> $GITHUB_STEP_SUMMARY
```

</TabItem>
<TabItem label="Merge Gate">

Block merges when critical or high severity findings exist. Runs on pushes to `main`.

```yaml
name: Compliance Gate
on:
  push:
    branches: [main]

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

      - uses: complyform/complyform-action@v1
        with:
          version: latest
          license-key: ${{ secrets.COMPLYFORM_LICENSE_KEY }}

      - name: Validate compliance
        run: |
          complyform scan --state=terraform.tfstate
          complyform assess --frameworks=soc2 --severity=critical,high
          complyform validate
```

The workflow fails if any critical or high findings remain unresolved.

</TabItem>
<TabItem label="Scheduled Scan">

Run a full assessment on a schedule and push results to the ComplyForm dashboard.

```yaml
name: Scheduled Compliance Scan
on:
  schedule:
    - cron: '0 6 * * 1-5'  # Weekdays at 06:00 UTC

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

      - uses: complyform/complyform-action@v1
        with:
          version: latest
          license-key: ${{ secrets.COMPLYFORM_LICENSE_KEY }}

      - name: Full scan and push
        run: |
          complyform scan --state=terraform.tfstate \
            --assess --frameworks=soc2,hipaa \
            --output=json --output-file=results.json
          complyform export --format=dashboard \
            --input=results.json \
            --api-key=${{ secrets.COMPLYFORM_API_KEY }}
```

</TabItem>
</Tabs>

<Aside type="note">
SARIF upload requires GitHub Advanced Security or a public repository. The `github/codeql-action/upload-sarif` step maps compliance findings to the **Security** tab in your repository.
</Aside>

## Next steps

- [`complyform assess`](../../cli-reference/assess/) — assessment options and output formats
- [`complyform validate`](../../cli-reference/validate/) — validation and exit codes
- [Dashboard Push API](../../api-reference/dashboard-push/) — push results programmatically
