Run this action on a schedule to automatically remove inactive Copilot licenses. It also creates a report as a job summary and csv.
In addition to this it can also deploy users from a CSV file. This is useful as you are adopting Copilot as it can help facilitate the process of adding users to your organization.
Create a workflow (eg: .github/workflows/copilot-license-management.yml
). See Creating a Workflow file.
If you want to deploy users from a CSV file you will need to create a CSV file with the following columns:
organization
- The organization to add the user todeployment_group
- An arbitrary group name used to track the deploymentslogin
- The user's GitHub Login name to addactivation_date
- The date the user should be activated (YYYY-MM-DD)
Example:
organization,deployment_group,login,activation_date
exampleorg1,group1,octocat,2024-01-15
exampleorg1,group1,octodog,2024-01-15
This requires the users to already exist as members of the enterprise and target organization.
If you are using Enterprise Managed Users, it may be easier to use a group from your identity provider to manage the users. You can assign the group to a team in an organization and assign that team to Copilot. This will allow you to manage the users in your identity provider and have them automatically added/removed from Copilot as group membership changes.
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/copilot-license-cleanup@v1.4
with:
github-token: ${{ secrets.TOKEN }}
- uses: austenstone/copilot-license-cleanup@v1.4
with:
github-token: ${{ secrets.TOKEN }}
remove: true
remove-from-team: true
- uses: austenstone/copilot-license-cleanup@v1.4
with:
github-token: ${{ secrets.TOKEN }}
remove: true
remove-from-team: true
inactive-days: 10
- uses: austenstone/copilot-license-cleanup@v1.4
with:
github-token: ${{ secrets.TOKEN }}
organization: exampleorg1, demoorg2, myorg3
- uses: austenstone/copilot-license-cleanup@v1.4
with:
github-token: ${{ secrets.TOKEN }}
enterprise: myenterprise
- uses: austenstone/copilot-license-cleanup@v1.4
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
name: Copilot License Review
on:
workflow_dispatch:
schedule:
- cron: '0 0 * * *'
jobs:
copilot:
name: Copilot Seats
runs-on: ubuntu-latest
# Checkout your repo so we can access the CSV file
- name: Checkout code
uses: actions/checkout@v4
- uses: austenstone/copilot-license-cleanup@v1.4
id: copilot_job
with:
organization: exampleorg1, exampleorg2
github-token: ${{ secrets.TOKEN }}
remove: false
remove-from-team: false
inactive-days: 30
deploy-users: true
csv: true
# Optional inputs
deploy-users-dry-run: false # Default is true
deploy-users-csv: ./copilot-users.csv
deploy-validation-time: 3
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 |
deploy-users | Whether to deploy users from a CSV file | false |
deploy-users-dry-run | Whether to perform a dry run when deploying users | true |
deploy-users-csv | CSV file location if deploying users | ./copilot-users.csv |
deploy-validation-time | The number of days to attempt to deploy the user beyond activation date | 3 |
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 |
deployed-seats | JSON array of deployed seats |
deployed-seat-count | The number of deployed 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.