CODEOWNERS-Driven Reviewer Assignment
On PR open, reads a flexible CODEOWNERS map from Dataverse (more dynamic than a static file), calls Request Reviewers For A Pull Request by changed paths, and Teams-messages each reviewer.
Provided as-is, without warranty of any kind. Review and test each pattern in a non-production environment before deploying it to live automations. See our Terms.
Overview
This flow replaces GitHub's static CODEOWNERS file with a flexible, data-driven alternative that lives in Dataverse. When a pull request is opened (or marked ready for review, or reopened) in a watched repository, the flow reads a Dataverse-backed CODEOWNERS map, matches the PR's changed file paths against the patterns in that map, requests the corresponding GitHub users as reviewers on the PR, and posts a notification card to a Teams channel summarizing who was assigned.
Use Case
Static CODEOWNERS files ship in a repo and can only be updated via a PR. Teams that need dynamic ownership — rotating on-call reviewers, temporary subject-matter experts during a migration, or reviewer pools that differ by product line — outgrow the static file quickly. By sourcing the map from Dataverse, ownership can be managed from a Power App or a Dataverse table editor without touching source control, and the same map can be reused across multiple repositories or extended with extra metadata (SLA, backup reviewer, team alias).
Flow Architecture
When A Pull Request Event Occurs
GitHub triggerWatches the configured repository for pull request events.
Initialize variables (7)
Initialize variableOne variable per parameter — varGitHubOwner, varGitHubRepo, varCodeOwnersTable, varTeamsGroupId, varTeamsChannelId — plus an empty varReviewers array.
If PR Is Opened Or Ready For Review
If conditionSingle condition with an OR of three equality checks: action = opened, action = ready_for_review, action = reopened. Stops the flow early for irrelevant events (labeled, synchronized, closed, etc.).
- Get Pull Request Files (GitHub) — Returns every file changed in the PR with its filename path.
- Get CODEOWNERS Map (Dataverse — List rows) — Reads the Dataverse table identified by codeowners_table, returning every row with columns flowlibs_pathpattern and flowlibs_reviewerlogin.
- For Each CODEOWNERS Rule — Iterates the map rows. Inside the loop a Query action (Filter_PR_Files_By_Path_Pattern) uses startsWith(item().filename, items('For_Each_CODEOWNERS_Rule').flowlibs_pathpattern) to detect whether any changed file matches this rule's prefix. If one or more files match, Append_Reviewer_Login pushes the rule's flowlibs_reviewerlogin onto varReviewers.
- Deduplicate Reviewers — Compose action with union(variables('varReviewers'), variables('varReviewers')). union is self-deduplicating, so calling it against a single array is the idiomatic dedupe pattern in Power Automate Cloud.
- If Reviewers To Assign — Nested condition: if the deduplicated array is non-empty, Request Reviewers On Pull Request (GitHub) assigns the reviewer list to the PR, and Post Reviewer Notification To Teams (Teams — Flow bot) posts an HTML card to the configured channel with the PR number, repo, reviewer list, and a clickable link to the PR.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_GitHubOwner | String | <configure> | GitHub organization or user that owns the watched repository. |
| flowlibs_GitHubRepository | String | <configure> | GitHub repository name to watch for PR events. |
| flowlibs_CodeOwnersTableName | String | <configure> | Dataverse entity set name of the table holding the CODEOWNERS map. |
| flowlibs_TeamsGroupId | String | <configure> | Microsoft Teams group (team) ID for reviewer notifications. |
| flowlibs_TeamsChannelId | String | <configure> | Microsoft Teams channel ID for reviewer notifications. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| GitHub | shared_github | WebhookPullRequestTrigger (trigger) GetPullRequestFiles RequestReviewersPullRequest |
| Microsoft Dataverse | shared_commondataserviceforapps | ListRecords (entityName is variable-driven via @variables('varCodeOwnersTable') — one of the few Dataverse ops that tolerates a dynamic entity name.) |
| Microsoft Teams | shared_teams | PostMessageToConversation (Posted as Flow bot in the configured channel. Message body is HTML with a deep link to the PR.) |
Note — All connections are referenced as solution connection references; the flow is portable between environments as long as a connection is mapped at import time.
Customization Guide
Almost every realistic variant of this flow can be implemented by changing environment variable values. A few cases require small edits inside the flow definition — those are called out explicitly below.
- Pattern matching
- The default startsWith comparison behaves like a prefix matcher. To support full glob-style patterns (**/*.tsx, src/*.cs, etc.), replace the Filter array expression with a custom match function — either a Select+Compose chain using split/indexOf or a child flow that calls a small Office Script / Azure Function. startsWith covers the common 'own everything under this folder' case cleanly.
- Additional metadata
- Extend the Dataverse table with columns like flowlibs_backuplogin, flowlibs_teamalias, or flowlibs_sladays. Update the loop to conditionally append the backup login when the primary user is inactive, or use the team alias in the Teams message for better routing.
- Repo fan-out
- Wrap the flow in a child-flow pattern: a parent flow iterates a list of repositories from Dataverse and calls this flow once per repo, passing the owner/repo/table/channel parameters dynamically. The current build is single-repo by design to keep the trigger simple.
- Non-PR events
- The OR condition keeps this focused on opened, ready_for_review, and reopened. To also handle synchronize (new commits pushed), add a fourth equals row — but know that this will re-post to Teams on every push.
Key Expressions
The flow is intentionally light on Power Fx / WDL gymnastics — the heaviest expressions are the branch-name concatenation and the approval outcome check. They are listed below in the order they appear in the flow.
EXPR.01Path matching inside the loop
Prefix-matches each PR file against the rule's path pattern inside the For Each CODEOWNERS Rule loop.
EXPR.02Dedupe reviewers
union against itself is the idiomatic self-dedupe pattern in Power Automate Cloud.
EXPR.03Teams notification body
Builds the HTML body posted to Teams with PR number, repo, reviewer list, and a clickable link.
EXPR.04Action filter condition
Three equals operators under a single or, checking triggerOutputs()?['body/action'] against the three PR events handled.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.