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

# Lint and Test Code Changes On Pull Requests

> Bolt template that runs pre-commit hooks on changed files, then builds and tests modified dbt™ models with Turbo CI whenever a pull request opens.

This template creates a Turbo CI Bolt schedule with two commands. When a pull request is opened, it first runs your [pre-commit](/integrations/pre-commit) hooks (linting, formatting, project checks) against only the files changed in the pull request, then runs the standard Turbo CI dbt™ command to build and test only the modified models and their downstream dependencies in a temporary schema.

<Check>
  **Key Benefits**

  * Enforce code quality (SQLFluff, dbt™ project checks) on every pull request, not just on developer machines
  * Lint only the files changed in the pull request, keeping runs fast
  * Build and test only modified models and their downstream dependencies
  * Run validation in a temporary schema to avoid impacting production
  * Get immediate feedback on pull request status through Paradime integration
</Check>

<Info>
  **Prerequisites**

  * A [pre-commit configuration](/integrations/pre-commit) (`.pre-commit-config.yaml`) at the root of your dbt™ repository, for example with [SQLFluff hooks](/integrations/pre-commit/sqlfluff-hooks)
  * A dedicated CI [environment](/products/settings/connections/index#create-and-manage-environments) exists in **Settings > Environments**, with its own [warehouse connection](/products/settings/connections/scheduler-environment/index) using a target named `ci`, and the schedule's **Environment** is set to it
  * A CI pipeline in your Git provider triggers the Turbo CI schedule when a pull request opens. See the setup guide for [GitHub](/products/bolt/ci-cd/turbo-ci/github), [GitLab](/products/bolt/ci-cd/turbo-ci/gitlab), [Azure DevOps](/products/bolt/ci-cd/turbo-ci/azure-devops), or [BitBucket](/products/bolt/ci-cd/turbo-ci/bitbucket).
</Info>

### Default Configuration

#### Schedule Settings

| Setting           | Value                   | Explanation                                                             |
| ----------------- | ----------------------- | ----------------------------------------------------------------------- |
| Schedule Type     | `Turbo CI`              | Enables automated validation of pull request changes.                   |
| Schedule Name     | `turbo ci lint and run` | A descriptive name indicating the purpose of the schedule               |
| Deferred Schedule | `hourly run`            | Specifies the production schedule to compare against for state changes. |
| Git Branch        | `main`                  | Uses your default production branch to ensure correct code comparison.  |

#### Command Settings

The template runs two commands in order:

1. A [Run pre-commit](/products/bolt/creating-schedules/command-settings/pre-commit) command that lints only the files changed in the pull request:

   ```bash theme={"system"}
   pre-commit run --from-ref origin/main --to-ref HEAD
   ```

   The `--from-ref` / `--to-ref` flags tell pre-commit to check only the files that differ between your base branch and the pull request commit, mirroring how pre-commit behaves locally on staged files.

2. The standard Turbo CI dbt™ command that builds and tests only the modified models and their downstream dependencies:

   ```bash theme={"system"}
   dbt build --select state:modified+
   ```

<Info>
  By default, if the pre-commit command fails, the dbt™ command is skipped and the run is marked as failed. To still build and test models when linting fails, set [`continue_on_error`](/products/bolt/creating-schedules/schedules-as-code/configuration-reference#continue-on-error) on the pre-commit command.
</Info>

#### Trigger Type

* **Type**: Scheduled Run (Cron)
* **Cron Schedule**: `OFF` (This schedule will be triggered by a new pull request event, not a cron schedule)

<Info>
  For custom Trigger configurations, see [Trigger Types](/products/bolt/creating-schedules/trigger-types) documentation.
</Info>

#### Notification Settings

* **Email Alerts**:
  * **Success**: Confirms hooks passed and models built and tested successfully
  * **Failure**: Alerts when a hook fails, models fail to build, or tests fail
  * **SLA Breach**: Alerts if the run takes longer than 120 minutes

<Info>
  For custom notification configurations, see [Notification Settings](/products/bolt/creating-schedules/notification-settings) documentation.
</Info>

### Full Example

#### pre-commit configuration

Add a `.pre-commit-config.yaml` at the root of your dbt™ repository. This example combines [SQLFluff](/integrations/pre-commit/sqlfluff-hooks) linting with [dbt-checkpoint](/integrations/pre-commit/dbt-tm-checkpoint-hooks/index) model and script checks:

```yaml .pre-commit-config.yaml theme={"system"}
repos:
  # SQL linting using SQLFluff
  - repo: https://github.com/sqlfluff/sqlfluff
    rev: 3.3.0
    hooks:
      - id: sqlfluff-lint
        name: SQLFluff Lint
        description: Lints SQL files using SQLFluff
        files: ^.*\.sql$
        additional_dependencies: ["sqlfluff-templater-dbt"]
        args: ["--dialect", "snowflake", "--templater", "dbt"]

  # dbt™ specific checks using dbt-checkpoint
  - repo: https://github.com/dbt-checkpoint/dbt-checkpoint
    rev: v2.0.6
    hooks:
      - id: dbt-parse
      - id: check-model-has-description
        name: Check Model Descriptions
        description: Ensures models have descriptions
      - id: check-model-has-tests
        name: Check Model Tests
        description: Ensures models have minimum test coverage
        args: ["--test-cnt", "2"]
      - id: check-script-has-no-table-name
        name: Check Script Table References
        description: Ensure only source() or ref() macros are used for table references
        files: models/.*\.sql$
      - id: check-script-ref-and-source
        name: Check Script References
        description: Validate all ref() and source() references exist
        files: models/.*\.sql$
        args: [--manifest, target/manifest.json]

# Define what files to exclude from all hooks
exclude: |
  (?x)^(
      target/.*|
      logs/.*|
      .*/snapshots/.*|
      tests/.*_test\.sql|
      analysis/.*
  )$
```

Set the SQLFluff `--dialect` to your warehouse (for example `bigquery`, `snowflake`, or `redshift`). The `dbt-parse` hook runs first so that checks needing `target/manifest.json`, like `check-script-ref-and-source`, have a fresh manifest to validate against.

<Info>
  This schedule is the enforcement point for these hooks, so no local setup is needed. Developers can also run the same checks on demand from the Code IDE terminal with `paradime pre-commit`. See [Paradime Setup and Configuration](/integrations/pre-commit/paradime-setup-and-configuration).
</Info>

#### Schedule configuration

The equivalent [Schedules as Code](/products/bolt/creating-schedules/schedules-as-code/configuration-reference) definition for the Turbo CI schedule:

```yaml paradime_schedules.yml theme={"system"}
schedules:
  - name: turbo ci lint and run
    environment: tagging-iguana-qhhi5i     # Your CI environment's slug, shown in Settings > Environments
    git_branch: main
    commands:
      - pre-commit run --from-ref origin/main --to-ref HEAD
      - dbt build --select state:modified+
    schedule: 'OFF'
    turbo_ci:
      enabled: true
      deferred_schedule_slug: hourly-run   # Production schedule to compare state against
      successful_run_only: true
    sla_minutes: 120
    notifications:
      emails:
        - address: data-team@acme.io
          events:
            - passed
            - failed
            - sla
```

### When to Customize

Tailor this template to your specific needs:

* **Choose your hooks** in `.pre-commit-config.yaml`: [SQLFluff](/integrations/pre-commit/sqlfluff-hooks) for SQL linting, [Prettier](/integrations/pre-commit/prettier-hooks) for YAML and Markdown formatting, or any other pre-commit hook your team uses.
* **Run a single hook** instead of the full suite by using `pre-commit run <hook-id> --from-ref origin/main --to-ref HEAD`, or check the whole project with `pre-commit run --all-files`.
* **Adjust the base branch** in `--from-ref` if your pull requests target a branch other than `main`.
* **Adjust Deferred Schedule** to the production schedule you want Turbo CI to compare against for state changes.
* **Modify command settings** with the dbt™ commands to suit your testing requirements, such as running specific model selectors or additional tests.
* Add more **notification destinations** (Slack, MS Teams) to match your team's workflows.
* [Customize Temporary Schema Naming](/products/bolt/ci-cd/turbo-ci/index#configure-a-custom-schema-for-ci-runs) via the dbt™ `generate_schema_name.sql` macro to handle the temporary schema prefix.


## Related topics

- [CI/CD Templates](/guides/orchestrate-data-pipelines/templates/ci-cd-templates/index.md)
- [Configure pre-commit for your dbt project in Paradime](/integrations/pre-commit/paradime-setup-and-configuration.md)
- [Test Code Changes On Pull Requests](/guides/orchestrate-data-pipelines/templates/ci-cd-templates/test-code-changes-on-pull-requests.md)
- [Lint SQL and YAML in the Code IDE](/products/code-ide/run-and-preview/lint.md)
- [Turbo CI for dbt™ pull requests](/products/bolt/ci-cd/turbo-ci/index.md)
