Milestone Rollup to Executives
Every Friday aggregates milestones (due dates, completion %, open/closed issue counts) from all product repos into a single Word document and emails it to Executives and Project Managers.
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
A scheduled Power Automate cloud flow that aggregates open milestones across multiple GitHub repositories every Friday morning, calculates completion percentages, and emails a formatted HTML rollup to executives. The flow demonstrates multi-repo iteration, nested Apply-to-each, variable-accumulated HTML, conditional empty-state rendering, and recurrence-based scheduling — all driven by environment variables so the monitored repos, recipients, and report title can be re-targeted per environment without editing the flow.
Use Case
Leadership needs weekly visibility into product-milestone progress without logging into GitHub. This flow runs every Friday at 9:00 AM Eastern, walks the list of monitored repos (comma-separated env var), pulls every open milestone sorted by due date, and produces one HTML email with a single table containing due date, title, repo, open-issue count, closed-issue count, and % complete for every milestone across every repo. If no open milestones exist, the email still sends with a friendly empty-state row so executives know the flow ran successfully.
Flow Architecture
Weekly_Friday_9AM_ET
RecurrenceFrequency = Week, interval = 1, schedule = Friday at 09:00, time zone = Eastern Standard Time.
Init_varGitHubOwner
Initialize variableString variable, value @parameters('EnvVar_GitHubOwner (flowlibs_GitHubOwner)').
Init_varMonitoredRepos
Initialize variableString variable, value from EnvVar_GitHubMonitoredRepos (comma-separated repo list).
Init_varRecipientEmails
Initialize variableString variable, value from EnvVar_ExecutiveEmails (semicolon-separated recipients).
Init_varReportTitle
Initialize variableString variable, value from EnvVar_MilestoneReportTitle.
Init_varMilestoneRows
Initialize variableString variable, empty (accumulator for HTML <tr> rows).
Init_varTotalMilestones
Initialize variableInteger variable, value 0.
Compose_Repos_Array
Compose@split(variables('varMonitoredRepos'), ',') — splits the comma-separated repo list into an array.
Apply_to_each_repo
Apply to eachFor each repo in the repos array (concurrency capped at 1 so rows append deterministically): trims the repo name, calls GitHub GetMilestones with state=open, sort=due_on, direction=asc, per_page=100, then nested Apply_to_each_milestone increments varTotalMilestones, composes one <tr> row (due date with null-guard, title, repo, open count, closed count, computed completion %), and appends the row to varMilestoneRows.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_GitHubOwner | String | <configure> | GitHub user or org that owns the monitored repos. Set to the GitHub login that has access to the target repositories. |
| flowlibs_GitHubMonitoredRepos | String | FlowLibs-Site-Build,FlowLibs-Demos | Comma-separated list of repo names to poll. Example: Repo-A,Repo-B,Repo-C. |
| flowlibs_ExecutiveEmails | String | you@yourcompany.com | Semicolon-separated recipient list for the rollup (e.g. person1@x.com;person2@x.com). |
| flowlibs_MilestoneReportTitle | String | Weekly Milestone Rollup | Prefix used in the email subject. |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| GitHub | shared_github | GetMilestones (Pulls open milestones per repo (state=open, sort=due_on)) |
| Office 365 Outlook | shared_office365 | SendEmailV2 (Mails the HTML rollup to the configured recipients) |
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.
- Change who receives the email
- Edit the flowlibs_ExecutiveEmails current-value; use a semicolon between addresses (person1@x.com;person2@x.com). No flow edit required.
- Monitor different repos
- Update flowlibs_GitHubMonitoredRepos with a comma-separated list of repo names under the same owner (e.g. Repo-A,Repo-B,Repo-C). The Compose_Trimmed_Repo_Name action removes spaces around commas so formatting is forgiving.
- Monitor a different owner/org
- Update flowlibs_GitHubOwner. Remember to re-authorize the GitHub connection if the new owner requires different access.
- Change the schedule
- Open the Weekly_Friday_9AM_ET trigger and adjust weekDays, hours, minutes, or timeZone. The recurrence trigger is defined inline and does not depend on env vars, so this is a flow-level change.
- Switch from open-only to all milestones
- Change the state parameter in Get_Open_Milestones from open to all. You may also want to surface the state column in the HTML table.
- Replace HTML email with a Word document
- Swap Send_Rollup_Email for a Word Online (Business) PopulateWordTemplate action (requires a pre-uploaded template in SharePoint/OneDrive), then attach the resulting file to an Outlook SendEmailV2 Attachments array. The current HTML approach avoids the template dependency for the demo.
- Add a per-milestone assignee column
- GitHub milestones expose creator/login; add a seventh <td> to Compose_Milestone_Row pulling items('Apply_to_each_milestone')?['creator']?['login'].
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.01Completion percentage (zero-guarded)
Avoids divide-by-zero when a milestone has no issues yet; renders '0%' instead of erroring.
EXPR.02Due-date formatter with null-safe fallback
Renders 'No due date' when the milestone has no due_on set; formats otherwise.
EXPR.03Email subject with current date
Builds the subject line from the configurable title plus today's date.
EXPR.04Repo list to array
Used by Compose_Repos_Array to turn the comma-separated env var into an iterable array.
EXPR.05Conditional empty-state row
Inside Compose_Final_HTML_Body: emits a friendly empty-state row when no milestones were found.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.