|
| 1 | +name: dbt CI |
| 2 | + |
| 3 | +on: |
| 4 | + push: |
| 5 | + branches: [main] |
| 6 | + pull_request: |
| 7 | + |
| 8 | +jobs: |
| 9 | + build: |
| 10 | + name: dbt build (DuckDB) |
| 11 | + runs-on: ubuntu-latest |
| 12 | + env: |
| 13 | + DBT_PROFILES_DIR: ${{ github.workspace }} |
| 14 | + steps: |
| 15 | + - uses: actions/checkout@v4 |
| 16 | + |
| 17 | + - uses: actions/setup-python@v5 |
| 18 | + with: |
| 19 | + python-version: "3.12" |
| 20 | + |
| 21 | + - name: Install dbt + MetricFlow |
| 22 | + run: | |
| 23 | + python -m pip install --upgrade pip |
| 24 | + pip install -r requirements.txt |
| 25 | +
|
| 26 | + - name: Generate seed data |
| 27 | + run: python scripts/generate_seeds.py |
| 28 | + |
| 29 | + # Seeds stand in for raw sources here; load them first so the staging |
| 30 | + # models (which read via source()) find the tables. dbt has no dependency |
| 31 | + # edge from a source() to the seed that populates it, so we order it. |
| 32 | + - name: dbt seed |
| 33 | + run: dbt seed |
| 34 | + |
| 35 | + - name: dbt build (run + test + contracts) |
| 36 | + run: dbt build --exclude resource_type:seed |
| 37 | + |
| 38 | + - name: dbt parse (validate semantic layer) |
| 39 | + run: dbt parse |
| 40 | + |
| 41 | + - name: Resolve KPI through the semantic layer |
| 42 | + run: mf query --metrics cache_hit_rate,cpu_hours_saved --group-by metric_time__year |
| 43 | + |
| 44 | + agent-guardrail: |
| 45 | + name: agent-guardrail (execution-plane surfaces) |
| 46 | + runs-on: ubuntu-latest |
| 47 | + if: github.event_name == 'pull_request' |
| 48 | + steps: |
| 49 | + - uses: actions/checkout@v4 |
| 50 | + with: |
| 51 | + fetch-depth: 0 |
| 52 | + |
| 53 | + - name: Flag changes that warrant a sandboxed run (ADR 0001) |
| 54 | + run: | |
| 55 | + base="origin/${{ github.base_ref }}" |
| 56 | + git fetch origin "${{ github.base_ref }}" --depth=1 |
| 57 | + changed=$(git diff --name-only "$base"...HEAD) |
| 58 | + echo "Changed files:"; echo "$changed" |
| 59 | + risky=$(echo "$changed" | grep -E '(^|/)macros/|packages\.ya?ml|dependencies\.ya?ml|\.py$' || true) |
| 60 | + # Heuristic: hooks / run-operation introduced in the diff |
| 61 | + hooks=$(git diff "$base"...HEAD | grep -E '^\+.*(pre.?hook|post.?hook|on-run-(start|end)|run_operation|run-operation)' || true) |
| 62 | + if [ -n "$risky" ] || [ -n "$hooks" ]; then |
| 63 | + echo "::warning title=Execution-plane change::This PR touches macros/hooks/packages/Python models. Per docs/adr/0001-where-to-run-dbt.md, execute it only in a sandboxed runtime and review the code-execution surfaces, not just the SELECTs." |
| 64 | + echo "$risky"; echo "$hooks" |
| 65 | + else |
| 66 | + echo "No execution-plane surfaces touched — branch + DB role + CI confinement is sufficient." |
| 67 | + fi |
0 commit comments