PR & Code Review
Every change to the platform goes through a Pull Request. This page covers the PR lifecycle, CI validation, review permissions, merge policy, and what happens after merge.
PR Lifecycle
sequenceDiagram participant Dev as Developer participant Git as Azure Repos participant CI as CI Pipeline participant Rev as Reviewer Dev->>Git: Push feature branch Git->>CI: Trigger dbt-ci-smoke CI-->>Git: Pass/Fail status Dev->>Git: Create PR to main Git->>Rev: Request review Rev-->>Git: Approve Git->>Git: Squash merge Git->>CI: Trigger infra-deploy chain
Branch Naming
Feature branches follow the pattern feature/<descriptive-name>. Examples:
feature/trading-dashboardfeature/new-logistics-modelfeature/vesper-api-ingest
There are no branch policies on feature/* branches -- they allow bidirectional Fabric UI sync (developers can commit from the Fabric portal and push code from their local machine).
CI Validation
Two CI pipelines validate code quality before merge:
DuckDB Smoke CI (dbt-ci-smoke.yml)
- Triggers on: Every push to any branch
- Engine: DuckDB (in-memory)
- What it does: Compiles all models, runs all tests, scans for secrets (gitleaks)
- Speed: Fast (seconds)
- Purpose: Catch syntax errors, broken references, and secrets before they reach a PR
Fabric Slim CI (dbt-ci-slim.yml)
- Triggers on: PRs targeting
mainonly - Engine: Fabric CI Warehouse
- What it does: Builds only modified models (using manifest diffing against the nightly full build) on a dedicated CI warehouse
- Speed: Minutes (depends on number of modified models)
- Purpose: Catch Fabric-specific issues that DuckDB cannot detect: case sensitivity, datetime2 precision, T-SQL function availability
Both pipelines must pass before a PR can be merged. The Fabric Slim CI uses the nightly manifest (dbt-artifacts/ci/manifest.json) as its comparison baseline, ensuring it only builds what actually changed.
Review Permissions
The project uses a two-tier access model:
| Action | Leads (Platform Team) | Developers |
|---|---|---|
Create PR to main | Yes | Yes |
Approve PR to main | Yes | No |
Create PR to release/* | Yes | No |
Approve PR to release/* | Yes | No |
| Bypass policies (emergency) | Yes | No |
Who are Leads? Members of the FP GER Fabric Platform Team Entra group. Currently this is the platform architect; future senior developers will be added.
Who are Developers? Members of the FP GER Fabric Developers Entra group. They can create feature branches, push code, and create PRs to main, but cannot approve or merge without a Lead's review.
Branch Policies
| Branch | Min Reviewers | Build Validation | Merge Strategy |
|---|---|---|---|
main | 1 (Lead) | DuckDB Smoke CI + Fabric Slim CI | Squash merge |
release/uat | 1 (Lead) | DuckDB Smoke CI | Merge (no fast-forward) |
release/prod | 1 (Lead) | DuckDB Smoke CI | Merge (no fast-forward) |
feature/* | None | None | Any |
Why squash merge to main? Feature branches often contain many small commits (WIP saves, Fabric UI commits, iteration). Squash merge produces a single clean commit on main that represents the complete feature, making the main branch history readable and easy to cherry-pick for promotion.
Why no-fast-forward for release branches? Release branches use merge commits (not squash) to preserve the original commit hashes. This makes it easy to track which specific main commits have been promoted to UAT and PROD.
What Happens After Merge
When a PR is squash-merged to main, multiple pipelines trigger based on which files changed:
| Pipeline | Path Filter | What It Does |
|---|---|---|
dbt-dev-build.yml | dbt/** | Runs dbt build against the DEV Gold Warehouse |
fabric-deploy.yml (DEV stage) | workspaces/semantic/**, workspaces/reports/** | Deploys semantic models and reports to DEV workspaces |
infra-deploy.yml | terraform/** | Applies Terraform changes to DEV infrastructure |
functions-deploy.yml | functions/** | Deploys Azure Functions to DEV |
security-deploy.yml | security/** | Applies SQL security roles and grants to DEV warehouse |
All DEV deployments are automatic -- no approval gates. The deployment pipelines read configuration from deployment/dev.yml and use the fabric-ci-service-connection service connection for authentication.
Promotion to UAT and PROD
After changes are validated in DEV, they are promoted via cherry-pick PRs:
# Promote a specific commit to UAT
git checkout release/uat
git cherry-pick <commit-hash>
git push origin release/uat
# Create PR in Azure DevOps (requires 1 Lead reviewer)
# Promote to PROD (requires 1 Lead reviewer + approval gate)
git checkout release/prod
git cherry-pick <commit-hash>
git push origin release/prod
# Create PR in Azure DevOps
Changes are promoted individually (cherry-pick), not all-or-nothing. This allows hotfixing a single model to PROD without promoting everything on main, or incrementally validating changes in UAT.
PROD deployments require manual approval via the production Azure DevOps environment. An approver receives an email notification, reviews the changes, and clicks Approve or Reject. The deployment pauses until approval is granted (timeout: 72 hours).
PR Checklist
Before creating a PR, ensure:
-
dbt build --target local --profiles-dir .passes all tests - Column names match TMDL
sourceColumnvalues (if dbt models changed) - Source YAML target conditions exclude both
localandduckdb - No secrets in committed files (gitleaks will catch this, but check proactively)
- PR title is descriptive and concise
- All Fabric UI changes are committed via Source control panel
See the full Verification Checklist in Coding Conventions.
Related Pages
- Developer Workflow -- Full feature lifecycle from start to PR
- Coding Conventions -- What reviewers check
- Dual-Dialect Patterns -- Common CI failure causes
- Feature Branch Tiers -- Provisioning and teardown