The workflow itself is solid. A few things worth tightening at each stage, based on running this in production with Azure DevOps:
At the PR stage, run databricks bundle validate as a required check before merge is allowed. It catches wrong field names, broken resource references, and missing values before anything touches a workspace. Costs nothing to run and it's the cheapest gate in the whole pipeline.
For your dev target, make sure databricks.yml has mode: development with default: true. This prefixes resource names with the username automatically, so a few people can deploy to the same dev workspace without stepping on each other. Skip default: true and someone in a hurry will eventually run bundle deploy with no --target flag and end up somewhere they didn't mean to.
For UAT and prod, use mode: production and deploy under a service principal, not a personal account. Two reasons this matters: deployed resources don't get orphaned if someone leaves the team, and your prod audit trail actually means something when someone asks who deployed what.
Worth testing deliberately before you need it - what happens if a deploy fails mid-run and you have to retry. There's a thread on this board right now about --force-lock creating duplicate jobs after an Azure DevOps pipeline failure. Simulate that failure in dev before it happens for real in prod.
And keep validate as a gate at every promotion, not just at the PR. The bigger thing though is to promote the same validated artifact from UAT into prod rather than rebuilding from YAML at each stage - that's what actually guarantees prod matches what UAT tested.
Putting it together:
Feature branch → validate (PR gate) → review and merge → validate again → deploy to UAT under service principal → UAT sign-off → promote the same artifact to prod, don't rebuild from source → deploy to prod under service principal with manual approval
The part that matters most: validate early and often, but only ever promote one artifact forward instead of re-deploying from source at each stage. That's what keeps UAT and prod actually identical to what got tested.
Happy to go deeper on any of this if it's useful for what you're setting up.