Skip to content

Commit 20c083e

Browse files
committed
sync provider and schema drift
1 parent 73a1c0b commit 20c083e

8 files changed

Lines changed: 607 additions & 3 deletions

File tree

.github/workflows/schema-drift.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
name: Schema Drift
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- ".terraform.lock.hcl"
7+
- "schemas/**"
8+
- "scripts/resource_mapping.yml"
9+
- "scripts/check_schema_drift.py"
10+
- ".github/workflows/schema-drift.yml"
11+
push:
12+
branches: [main]
13+
paths:
14+
- ".terraform.lock.hcl"
15+
- "schemas/**"
16+
- "scripts/resource_mapping.yml"
17+
- "scripts/check_schema_drift.py"
18+
schedule:
19+
- cron: "0 8 * * 1" # Monday 08:00 UTC — catches upstream provider releases
20+
21+
permissions:
22+
contents: read
23+
24+
jobs:
25+
schema-drift:
26+
name: Schema Drift Check
27+
runs-on: ubuntu-latest
28+
29+
steps:
30+
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # v4
31+
32+
- uses: hashicorp/setup-terraform@b9cd54a3c349d3f38e8881555d616ced269862dd # v3
33+
with:
34+
terraform_version_file: .terraform-version
35+
36+
- name: Cache Terraform providers
37+
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4
38+
with:
39+
path: .terraform
40+
key: terraform-${{ hashFiles('.terraform.lock.hcl') }}
41+
restore-keys: terraform-
42+
43+
- name: Init (downloads provider binary, no credentials needed)
44+
run: terraform init -backend=false
45+
46+
- name: Install uv
47+
uses: astral-sh/setup-uv@v5
48+
49+
- name: Check schema drift
50+
id: drift
51+
run: |
52+
uv run --with PyYAML scripts/check_schema_drift.py \
53+
--mapping scripts/resource_mapping.yml \
54+
--schema schemas/v1.json \
55+
--terraform-dir .
56+
57+
- name: Annotate PR on failure
58+
if: failure() && github.event_name == 'pull_request'
59+
run: |
60+
echo "::error::Schema drift detected. Run 'make schema-drift' locally and classify any UNMAPPED fields in scripts/resource_mapping.yml. Add MISSING_FROM_SCHEMA fields to schemas/v1.json."

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,9 @@ terraform.rc
3838

3939
*.DS_Store
4040

41+
# Cached provider schema output (used by scripts/check_schema_drift.py --provider-schema)
42+
provider_schema_cache.json
43+
scripts/provider_schema_cache.json
44+
4145
# Internal publishing checklist (keep local only)
4246
.claude/implementation/public.md

Makefile

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
.DEFAULT_GOAL := help
22

3-
.PHONY: fmt fmt-check lint validate test test-integration docs pre-commit pre-commit-all help
3+
.PHONY: fmt fmt-check lint validate schema-drift schema-drift-verbose test test-integration docs pre-commit pre-commit-all help
44

55
fmt: ## Auto-format all Terraform files
66
terraform fmt -recursive
@@ -15,6 +15,21 @@ validate: ## Run terraform validate (requires terraform init)
1515
terraform init -backend=false -reconfigure
1616
terraform validate
1717

18+
schema-drift: ## Check for drift between dbtcloud provider schema and schemas/v1.json
19+
terraform init -backend=false -reconfigure
20+
uv run --with PyYAML scripts/check_schema_drift.py \
21+
--mapping scripts/resource_mapping.yml \
22+
--schema schemas/v1.json \
23+
--terraform-dir .
24+
25+
schema-drift-verbose: ## Same as schema-drift but also fails on STALE_YAML findings
26+
terraform init -backend=false -reconfigure
27+
uv run --with PyYAML scripts/check_schema_drift.py \
28+
--mapping scripts/resource_mapping.yml \
29+
--schema schemas/v1.json \
30+
--terraform-dir . \
31+
--fail-on-stale
32+
1833
test: ## Run terraform test with mock providers (no credentials needed)
1934
terraform test
2035

modules/environments/main.tf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,8 @@ resource "dbtcloud_environment" "environments" {
9999
enable_model_query_history = try(each.value.env_data.enable_model_query_history, null)
100100
custom_branch = try(each.value.env_data.custom_branch, null)
101101
deployment_type = try(each.value.env_data.deployment_type, null)
102+
is_active = try(each.value.env_data.is_active, null)
103+
target_name = try(each.value.env_data.target_name, null)
102104
use_custom_branch = try(each.value.env_data.custom_branch, null) != null
103105
primary_profile_id = local.resolve_primary_profile_id[each.key]
104106
extended_attributes_id = local.resolve_primary_profile_id[each.key] != null ? null : local.resolve_extended_attributes_id[each.key]
@@ -131,6 +133,8 @@ resource "dbtcloud_environment" "protected_environments" {
131133
enable_model_query_history = try(each.value.env_data.enable_model_query_history, null)
132134
custom_branch = try(each.value.env_data.custom_branch, null)
133135
deployment_type = try(each.value.env_data.deployment_type, null)
136+
is_active = try(each.value.env_data.is_active, null)
137+
target_name = try(each.value.env_data.target_name, null)
134138
use_custom_branch = try(each.value.env_data.custom_branch, null) != null
135139
primary_profile_id = local.resolve_primary_profile_id[each.key]
136140
extended_attributes_id = local.resolve_primary_profile_id[each.key] != null ? null : local.resolve_extended_attributes_id[each.key]

modules/jobs/main.tf

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ resource "dbtcloud_job" "jobs" {
207207
triggers_on_draft_pr = try(each.value.job_data.triggers_on_draft_pr, false)
208208
force_node_selection = local.force_node_selection_effective[each.key]
209209
deferring_environment_id = local.resolve_deferring_environment_id[each.key]
210+
deferring_job_id = try(each.value.job_data.deferring_job_id, null)
210211

211212
schedule_cron = local.schedule_cron_effective[each.key]
212213
schedule_days = try(each.value.job_data.schedule_days, null)
@@ -263,6 +264,7 @@ resource "dbtcloud_job" "protected_jobs" {
263264
triggers_on_draft_pr = try(each.value.job_data.triggers_on_draft_pr, false)
264265
force_node_selection = local.force_node_selection_effective[each.key]
265266
deferring_environment_id = local.resolve_deferring_environment_id[each.key]
267+
deferring_job_id = try(each.value.job_data.deferring_job_id, null)
266268

267269
schedule_cron = local.schedule_cron_effective[each.key]
268270
schedule_days = try(each.value.job_data.schedule_days, null)

modules/project/main.tf

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ locals {
3636
resource "dbtcloud_project" "projects" {
3737
for_each = local.unprotected_projects_map
3838

39-
name = "${var.target_name}${each.value.name}"
39+
name = "${var.target_name}${each.value.name}"
40+
description = try(each.value.description, null)
41+
type = try(each.value.type, null)
42+
dbt_project_subdirectory = try(each.value.dbt_project_subdirectory, null)
4043

4144
# Deferred until dbt-labs/dbtcloud supports resource_metadata on dbtcloud_project (v2 parity).
4245
# resource_metadata = {
@@ -55,7 +58,10 @@ resource "dbtcloud_project" "projects" {
5558
resource "dbtcloud_project" "protected_projects" {
5659
for_each = local.protected_projects_map
5760

58-
name = "${var.target_name}${each.value.name}"
61+
name = "${var.target_name}${each.value.name}"
62+
description = try(each.value.description, null)
63+
type = try(each.value.type, null)
64+
dbt_project_subdirectory = try(each.value.dbt_project_subdirectory, null)
5965

6066
# Deferred until dbt-labs/dbtcloud supports resource_metadata on dbtcloud_project (v2 parity).
6167
# resource_metadata = {

0 commit comments

Comments
 (0)