GitHub Action
Copilot License Management
Run this action on a schedule to automatically remove inactive Copilot licenses. It also creates a report as a job summary and csv.
Create a workflow (eg: .github/workflows/copilot-license-cleanup.yml
). See Creating a Workflow file.
You will need to create a PAT(Personal Access Token) that has manage_billing:copilot
access. If you are specifying an 'enterprise' rather than individual organizations you must also include the read:org
and read:enterprise
scopes.
Add this PAT as a secret TOKEN
so we can use it for input github-token
, see Creating encrypted secrets for a repository.
If your organization has SAML enabled you must authorize the PAT, see Authorizing a personal access token for use with SAML single sign-on.
name: Cleanup Copilot Licenses
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
copilot:
name: Copilot Seats
runs-on: ubuntu-latest
steps:
- uses: austenstone/[email protected]
with:
github-token: ${{ secrets.TOKEN }}
- uses: austenstone/[email protected]
with:
github-token: ${{ secrets.TOKEN }}
remove: true
remove-from-team: true
- uses: austenstone/[email protected]
with:
github-token: ${{ secrets.TOKEN }}
remove: true
remove-from-team: true
inactive-days: 10
- uses: austenstone/[email protected]
with:
github-token: ${{ secrets.TOKEN }}
organization: exampleorg1, demoorg2, myorg3
- uses: austenstone/[email protected]
with:
github-token: ${{ secrets.TOKEN }}
enterprise: octodemo
- uses: austenstone/[email protected]
id: copilot
with:
github-token: ${{ secrets.TOKEN }}
- name: Save inactive seats JSON to a file
run: |
echo '${{ steps.copilot.outputs.inactive-seats }}' | jq . > inactive-seats.json
- name: Upload inactive seats JSON as artifact
uses: actions/upload-artifact@v4
with:
name: inactive-seats-json
path: inactive-seats.json
Various inputs are defined in action.yml
:
Name | Description | Default |
---|---|---|
github‑token | Token to use to authorize. | ${{ github.token }} |
organization | The organization(s) to use for the action (comma separated) | ${{ github.repository_owner }} |
enterprise | (optional) All organizations in this enterprise (overrides organization) | null |
remove | Whether to remove inactive users | false |
remove-from-team | Whether to remove inactive users from their assigning team | false |
inactive‑days | The number of days to consider a user inactive | 90 |
job-summary | Whether to output a summary of the job | true |
csv | Whether to output a CSV of inactive users | false |
Name | Description |
---|---|
inactive-seats | JSON array of inactive seats |
inactive-seat-count | The number of inactive seats |
removed-seats | The number of seats removed |
seat-count | The total number of seats |
We're simply leveraging the GitHub Copilot API. First we fetch all the Copilot seats and filter them to only inactive seats. Then if the seat is assigned directly we remove it but if it's assigned through a team we remove the user from the team. Those inactive users are reported as a CSV and a job summary table.
To get more help on the Actions see documentation.