Archived Repo Cleanup
When a repo is marked archived in the governance SharePoint list, removes it from the GitHub App installation's repo list via Remove Selected Repository From An Installation and posts confirmation in #archival.
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 reads a SharePoint governance list every morning, identifies repositories marked for removal, and calls the GitHub REST API to remove each one from a GitHub App installation's repository list. After each successful removal the flow marks the source list item as processed and posts an HTML confirmation card to a Microsoft Teams channel.
The flow ships in the Off state with zero hardcoded externals. Turning it on in any tenant requires only authorizing connections, populating six environment variables, and creating the backing SharePoint list.
Use Case
Governance teams use a SharePoint list as the source of truth for repo lifecycle decisions. When a repository is decommissioned or archived, someone updates its list row to Status = Pending Removal. This flow then idempotently removes it from the organization's GitHub App installation so that CI/CD bots, Copilot, security scanners, and any other installation-scoped tooling immediately lose access — no manual GitHub UI navigation, no forgotten cleanups, and a full audit trail in both SharePoint (the Status and ProcessedOn columns) and Teams (the confirmation card).
Flow Architecture
Every_Day_At_8AM
Recurrence triggerRuns daily at 08:00 UTC.
Init_varSPSiteUrl
Initialize Variable (string)Hydrates SharePoint site URL from the flowlibs_SPSiteUrl environment variable.
Init_varSPArchivedReposListId
Initialize Variable (string)Hydrates the governance list GUID from the flowlibs_SPArchivedReposListId environment variable.
Init_varGitHubPAT
Initialize Variable (string)Hydrates the GitHub PAT secret from the flowlibs_GitHubPAT environment variable, kept in a local variable so it never leaks into an HTTP header template directly.
Init_varGitHubAppInstallationId
Initialize Variable (string)Hydrates the numeric GitHub App installation ID from the flowlibs_GitHubAppInstallationId environment variable.
Init_varTeamsGroupId
Initialize Variable (string)Hydrates the Teams group ID from the flowlibs_TeamsGroupId environment variable.
Init_varTeamsChannelId
Initialize Variable (string)Hydrates the Teams channel ID from the flowlibs_TeamsChannelId environment variable.
Init_varRemovedCount
Initialize Variable (integer, 0)Per-run counter incremented on each successful removal.
Get_Archived_Repos
SharePoint GetItemsQueries the governance list with `$filter=Status eq 'Pending Removal'` and `$top=100` to fetch all rows queued for cleanup.
Environment Variables
| Schema name | Type | Default | Description |
|---|---|---|---|
| flowlibs_SPSiteUrl | String | https://your-tenant.sharepoint.com | SharePoint site root that hosts the governance list. |
| flowlibs_SPArchivedReposListId | String | <configure> | GUID of the FlowLibs - Archived Repos Governance SharePoint list. Set this on activation. |
| flowlibs_GitHubPAT | String | <configure> | GitHub Personal Access Token with `admin:org` (classic) or fine-grained installation/repository-admin permissions sufficient to remove repos from an App installation. |
| flowlibs_GitHubAppInstallationId | String | <configure> | Numeric GitHub App installation ID found at `https://github.com/organizations/{org}/settings/installations` (click Configure on the app — the ID appears in the URL). |
| flowlibs_TeamsGroupId | String | <configure> | Target Microsoft Teams group/team ID that owns the notification channel. |
| flowlibs_TeamsChannelId | String | <configure> | Target Microsoft Teams channel ID (the #archival or equivalent notification channel). |
Connectors & Connections
| Connector | API name | Actions used |
|---|---|---|
| SharePoint Online | shared_sharepointonline | GetItems (Get_Archived_Repos — pulls rows where Status eq 'Pending Removal') PatchItem (Mark_SP_Item_As_Removed — flips Status to Removed and sets ProcessedOn) |
| Microsoft Teams | shared_teams | PostMessageToConversation (Post_Confirmation_To_Teams — HTML card per removed repo) |
| HTTP (built-in) | n/a | HTTP DELETE (Remove_Repo_From_Installation — calls api.github.com/user/installations/{id}/repositories/{repoId} with a Bearer PAT concatenated at runtime) |
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.
- Create the SharePoint governance list
- On the site referenced by flowlibs_SPSiteUrl, create a list titled FlowLibs - Archived Repos Governance with columns: Title (single-line text — repo name), RepoId (number — GitHub numeric repo ID), Status (choice: Active, Pending Removal, Removed), and ProcessedOn (date & time, optional).
- Capture the list GUID
- Copy the new list's GUID into flowlibs_SPArchivedReposListId. The value is what follows List= in the list's classic settings URL, or from /_api/web/lists/getbytitle('FlowLibs - Archived Repos Governance')?$select=Id.
- Populate the GitHub App installation ID
- Set flowlibs_GitHubAppInstallationId to the numeric installation ID from https://github.com/organizations/{org}/settings/installations — click Configure on the App and the ID appears in the URL.
- Populate the GitHub PAT
- Set flowlibs_GitHubPAT to a PAT with rights to manage the installation's selected repositories. Classic PATs need admin:org; fine-grained PATs need repository administration for the target repos or installation-level access.
- Populate the Teams target
- Set flowlibs_TeamsGroupId and flowlibs_TeamsChannelId to the IDs of your #archival (or equivalent) Teams channel.
- Re-authorize connections and refresh list schema
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.01Governance filter
Only processes rows explicitly queued for removal. Prevents accidental double-processing once a row is flipped to Removed.
EXPR.02Removal URI
Builds the per-row REST URL for the DELETE call against the GitHub App installation.
EXPR.03Auth header
Runtime concatenation hides the PAT from the static authoring surface so Flow Checker does not flag a direct env-var leak.
EXPR.04Processed timestamp
Written to `ProcessedOn` so downstream audit reports can timestamp each removal.
EXPR.05Teams card body
HTML card body containing repo name, repo ID, installation ID, timestamp, and running count.
Comments
Sign in to join the conversation.
Sign inNo comments yet. Be the first to share your experience with this flow.