Dbt starrocks production readiness
Skill ivanshamaev/de-agent-skills/group_skills/starrocks_group_skills/dbt_starrocks_production_readiness
Профессиональные Data Engineering Agent Skills для разработки AI Agentic Data Platform
npx -y skills add ivanshamaev/de-agent-skills --skill dbt_starrocks_production_readinessAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
- 13 stars13 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its author says it does
Copied from the file, not written here
dbt + StarRocks production readiness — slim CI with state:modified+, manifest.json artifact storage and --defer for dev, dbt Cloud vs dbt Core deployment, RBAC for dbt users in StarRocks, secrets management for profiles.yml, dbt run/test exit codes in CI, breaking change detection, scheduled dbt runs via Airflow/dbt Cloud, dbt docs generation and hosting, model versioning
SKILL.md
10.2 KB, as published. Nobody here has run it
dbt + StarRocks Production Readiness
When to Use
- Setting up CI/CD for a dbt project targeting StarRocks
- Configuring RBAC so dbt has minimum required permissions
- Deploying dbt via Airflow or dbt Cloud
- Detecting breaking changes before merging to main
- Maintaining dbt documentation for the team
Minimum StarRocks RBAC for dbt
-- Create dbt user
CREATE USER dbt_prod IDENTIFIED BY 'strong_password_here';
-- Permissions needed for dbt to run
GRANT SELECT, INSERT, UPDATE, DELETE, DROP, CREATE TABLE, ALTER
ON sales.* TO dbt_prod;
-- For ANALYZE TABLE (post-hooks)
GRANT SELECT ON _statistics_.* TO dbt_prod;
-- If dbt accesses external catalogs
GRANT USAGE ON CATALOG iceberg_hms TO dbt_prod;
GRANT SELECT ON iceberg_hms.raw.* TO dbt_prod;
-- Dev schema: dbt user creates its own tables
GRANT ALL ON dbt_dev.* TO dbt_user;
-- Read-only user for BI tools (queries dbt output)
CREATE USER bi_readonly IDENTIFIED BY 'password';
GRANT SELECT ON sales.* TO bi_readonly;
Secrets Management for profiles.yml
Environment Variables (CI/CD)
# profiles.yml — no hardcoded secrets
starrocks_project:
outputs:
prod:
type: starrocks
host: "{{ env_var('SR_HOST') }}"
port: 9030
username: "{{ env_var('SR_USER') }}"
password: "{{ env_var('SR_PASSWORD') }}"
database: sales
schema: "{{ env_var('SR_SCHEMA', 'sales') }}"
GitHub Actions secrets:
# .github/workflows/dbt_ci.yml
env:
SR_HOST: ${{ secrets.STARROCKS_HOST }}
SR_USER: ${{ secrets.STARROCKS_USER }}
SR_PASSWORD: ${{ secrets.STARROCKS_PASSWORD }}
SR_SCHEMA: sales
Vault Integration
# generate_profiles.py — called before dbt run
import hvac, yaml, os
client = hvac.Client(url=os.environ['VAULT_ADDR'], token=os.environ['VAULT_TOKEN'])
secret = client.secrets.kv.read_secret_version(path="data/starrocks/prod")["data"]["data"]
profile = {
"starrocks_project": {
"outputs": {
"prod": {
"type": "starrocks",
"host": secret["host"],
"port": 9030,
"username": secret["username"],
"password": secret["password"],
"database": "sales",
"schema": "sales",
}
},
"target": "prod",
}
}
with open(os.path.expanduser("~/.dbt/profiles.yml"), "w") as f:
yaml.dump(profile, f)
Slim CI with state:modified+
Only rebuild models that changed + their downstream dependents:
# .github/workflows/dbt_ci.yml
name: dbt CI
on:
pull_request:
paths:
- 'models/**'
- 'tests/**'
- 'macros/**'
- 'dbt_project.yml'
jobs:
dbt-ci:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install dbt
run: pip install dbt-starrocks
- name: Download production manifest
run: |
aws s3 cp s3://dbt-artifacts/prod/manifest.json ./prod_manifest/manifest.json
env:
AWS_DEFAULT_REGION: us-east-1
- name: dbt deps
run: dbt deps
- name: dbt compile (for diff)
run: dbt compile --profiles-dir .
- name: dbt run (changed models only)
run: |
dbt run \
--select state:modified+ \
--defer \
--state ./prod_manifest \
--target ci \
--profiles-dir .
env:
SR_HOST: ${{ secrets.STARROCKS_CI_HOST }}
SR_USER: ${{ secrets.STARROCKS_CI_USER }}
SR_PASSWORD: ${{ secrets.STARROCKS_CI_PASSWORD }}
SR_SCHEMA: "dbt_ci_${{ github.event.pull_request.number }}"
- name: dbt test (changed models + downstream)
run: |
dbt test \
--select state:modified+ \
--defer \
--state ./prod_manifest
Upload Manifest After Prod Run
# Post-production run step
- name: Upload manifest
run: |
aws s3 cp target/manifest.json s3://dbt-artifacts/prod/manifest.json
Breaking Change Detection
# In CI: compare current branch schema vs production
dbt ls --select state:modified --state ./prod_manifest
# Run dbt compile and check for breaking changes
# Breaking = column removed, type changed, model deleted
dbt compile --state ./prod_manifest
# Check for breaking changes via dbt-audit-helper
dbt run-operation compare_relations --args '{
"a_relation": "prod.sales.orders",
"b_relation": "dev.dbt_dev.orders"
}'
Custom macro to detect column drops:
-- macros/check_breaking_changes.sql
{% macro check_breaking_changes(model_name) %}
{% set prod_columns = adapter.get_columns_in_relation(
source('prod', model_name)
) | map(attribute='name') | list %}
{% set new_columns = adapter.get_columns_in_relation(
ref(model_name)
) | map(attribute='name') | list %}
{% set dropped = prod_columns | reject('in', new_columns) | list %}
{% if dropped | length > 0 %}
{{ exceptions.raise_compiler_error(
"Breaking change: columns dropped from " ~ model_name ~ ": " ~ dropped
) }}
{% endif %}
{% endmacro %}
Airflow dbt Operator
from airflow.decorators import dag, task
from airflow.operators.bash import BashOperator
from datetime import datetime
@dag(
dag_id="dbt_starrocks_daily",
schedule="0 6 * * *",
start_date=datetime(2024, 1, 1),
catchup=False,
tags=["dbt", "starrocks"],
)
def dbt_daily():
dbt_deps = BashOperator(
task_id="dbt_deps",
bash_command="cd /dbt && dbt deps --profiles-dir /dbt/profiles",
)
dbt_run = BashOperator(
task_id="dbt_run",
bash_command="cd /dbt && dbt run --target prod --profiles-dir /dbt/profiles",
env={
"SR_HOST": "{{ var('starrocks_host') }}",
"SR_PASSWORD": "{{ conn.get('starrocks_prod').password }}",
},
)
dbt_test = BashOperator(
task_id="dbt_test",
bash_command="cd /dbt && dbt test --target prod --profiles-dir /dbt/profiles",
)
dbt_freshness = BashOperator(
task_id="dbt_source_freshness",
bash_command="cd /dbt && dbt source freshness --profiles-dir /dbt/profiles",
)
dbt_docs = BashOperator(
task_id="dbt_docs_generate",
bash_command="cd /dbt && dbt docs generate --target prod && aws s3 sync target/ s3://dbt-docs/",
)
dbt_deps >> dbt_run >> dbt_test >> dbt_freshness >> dbt_docs
dag = dbt_daily()
Selective Production Runs
# Run only Gold layer (fastest daily refresh)
dbt run --select tag:gold
# Run staging + silver + gold in order
dbt run --select staging+ --exclude tag:expensive
# Run a specific model and all its dependencies
dbt run --select +orders_daily
# Run tests for a specific layer only
dbt test --select silver
# Skip freshness tests in nightly runs (too slow)
dbt test --exclude source:*
Model Versioning
dbt supports versioned models (dbt >= 1.5):
# models/schema.yml
models:
- name: orders
latest_version: 2
versions:
- v: 1
defined_in: orders_v1.sql
deprecation_date: "2024-06-01"
- v: 2
defined_in: orders_v2.sql
Downstream models reference a version:
SELECT * FROM {{ ref('orders', version=2) }}
dbt Documentation
Generate and host docs:
# Generate docs
dbt docs generate
# Serve locally for preview
dbt docs serve --port 8080
# Deploy to S3 + CloudFront
aws s3 sync target/ s3://dbt-docs-bucket/ --delete
aws cloudfront create-invalidation --distribution-id XXXXX --paths "/*"
Enrich with descriptions:
# models/schema.yml
models:
- name: orders
description: |
## Orders (Silver Layer)
Deduplicated and enriched order records. Source: CDC from PostgreSQL orders table.
**Refreshed**: every 15 minutes via Routine Load + dbt incremental.
**SLA**: < 30 minutes freshness.
columns:
- name: order_id
description: "Unique order identifier. Primary Key."
- name: amount
description: "Order amount in USD. Null for cancelled orders."
Exit Code Handling in CI
# dbt exits 0=success, 1=runtime error, 2=compile error
dbt run --select state:modified+
STATUS=$?
if [ $STATUS -eq 1 ]; then
echo "dbt run failed — check run artifacts"
# Upload artifacts even on failure
aws s3 cp target/run_results.json s3://dbt-artifacts/ci/run_results.json
exit 1
elif [ $STATUS -eq 2 ]; then
echo "dbt compilation error — check model SQL"
exit 2
fi
# Continue to tests only if run succeeded
dbt test --select state:modified+
Anti-Patterns
- Hardcoding passwords in profiles.yml — committed to git, rotated manually; use
env_var()exclusively. - No
--deferin CI — without defer, CI must build all upstream models from scratch; costs hours; use--defer --state prod_manifest. dbt runwithoutdbt testin production — silent data quality regressions; always follow run with tests.- Not uploading manifest after prod run — slim CI state comparison breaks; upload
target/manifest.jsonto S3 as last step of prod run. - Running all models in CI on every PR — slow and expensive; use
state:modified+to only rebuild what changed. - Granting
ALLto dbt user in production — dbt should not drop production tables it doesn't own; scope permissions to specific schemas.
References
- dbt slim CI:
docs.getdbt.com/best-practices/best-practice-workflows#run-only-modified-models-to-test-changes-slim-ci - dbt state:
docs.getdbt.com/reference/node-selection/methods#the-state-method - dbt model versioning:
docs.getdbt.com/docs/collaborate/govern/model-versions - Related skills:
[[dbt-starrocks-models]],[[dbt-starrocks-testing]],[[github-actions-dataops]],[[starrocks-admin-security]]